diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..6f93fbc --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: schnapple +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9469a2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,89 @@ +base/doom.wad +.DS_Store +base/doom2.wad +base/plutonia.wad +base/tnt.wad +base/SIGIL.wad +base/SIGIL_SHREDS.wad + +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint +Thumbs.db + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ +code/iphone/Doom.xcodeproj/project.xcworkspace/xcuserdata/tomkidd.xcuserdatad/UserInterfaceState.xcuserstate +code/iphone/DOOM.xcodeproj/project.xcworkspace/xcuserdata/tomkidd.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/IB Images/AdvancedButton.png b/IB Images/AdvancedButton.png new file mode 100644 index 0000000..ef79c07 Binary files /dev/null and b/IB Images/AdvancedButton.png differ diff --git a/IB Images/AdvancedButton_Highlighted.png b/IB Images/AdvancedButton_Highlighted.png new file mode 100644 index 0000000..ea4029a Binary files /dev/null and b/IB Images/AdvancedButton_Highlighted.png differ diff --git a/IB Images/BackButton.png b/IB Images/BackButton.png new file mode 100644 index 0000000..acfa754 Binary files /dev/null and b/IB Images/BackButton.png differ diff --git a/IB Images/BackButton_Highlighted.png b/IB Images/BackButton_Highlighted.png new file mode 100644 index 0000000..3e92a7c Binary files /dev/null and b/IB Images/BackButton_Highlighted.png differ diff --git a/IB Images/Button.png b/IB Images/Button.png new file mode 100644 index 0000000..bd6b767 Binary files /dev/null and b/IB Images/Button.png differ diff --git a/IB Images/Button_Highlighted.png b/IB Images/Button_Highlighted.png new file mode 100644 index 0000000..13bfea8 Binary files /dev/null and b/IB Images/Button_Highlighted.png differ diff --git a/IB Images/DOOM_sigil_decal.png b/IB Images/DOOM_sigil_decal.png new file mode 100644 index 0000000..2fc60ed Binary files /dev/null and b/IB Images/DOOM_sigil_decal.png differ diff --git a/IB Images/DifficultyBackground.png b/IB Images/DifficultyBackground.png new file mode 100644 index 0000000..94498ce Binary files /dev/null and b/IB Images/DifficultyBackground.png differ diff --git a/IB Images/Divide.png b/IB Images/Divide.png new file mode 100644 index 0000000..3f086d4 Binary files /dev/null and b/IB Images/Divide.png differ diff --git a/IB Images/DoomLogo.png b/IB Images/DoomLogo.png new file mode 100644 index 0000000..8222eb8 Binary files /dev/null and b/IB Images/DoomLogo.png differ diff --git a/IB Images/DownArrow.png b/IB Images/DownArrow.png new file mode 100644 index 0000000..eb1529a Binary files /dev/null and b/IB Images/DownArrow.png differ diff --git a/IB Images/DownArrow_Highlighted.png b/IB Images/DownArrow_Highlighted.png new file mode 100644 index 0000000..3f23486 Binary files /dev/null and b/IB Images/DownArrow_Highlighted.png differ diff --git a/IB Images/Easy.png b/IB Images/Easy.png new file mode 100644 index 0000000..70a0a3a Binary files /dev/null and b/IB Images/Easy.png differ diff --git a/IB Images/Episode1Background.png b/IB Images/Episode1Background.png new file mode 100644 index 0000000..0c1c416 Binary files /dev/null and b/IB Images/Episode1Background.png differ diff --git a/IB Images/Episode1Background_Highlighted.png b/IB Images/Episode1Background_Highlighted.png new file mode 100644 index 0000000..7f59dc7 Binary files /dev/null and b/IB Images/Episode1Background_Highlighted.png differ diff --git a/IB Images/Episode2Background.png b/IB Images/Episode2Background.png new file mode 100644 index 0000000..bb97a32 Binary files /dev/null and b/IB Images/Episode2Background.png differ diff --git a/IB Images/Episode2Background_Highlighted.png b/IB Images/Episode2Background_Highlighted.png new file mode 100644 index 0000000..a29d2c6 Binary files /dev/null and b/IB Images/Episode2Background_Highlighted.png differ diff --git a/IB Images/Episode3Background.png b/IB Images/Episode3Background.png new file mode 100644 index 0000000..6fe250c Binary files /dev/null and b/IB Images/Episode3Background.png differ diff --git a/IB Images/Episode3Background_Highlighted.png b/IB Images/Episode3Background_Highlighted.png new file mode 100644 index 0000000..459c667 Binary files /dev/null and b/IB Images/Episode3Background_Highlighted.png differ diff --git a/IB Images/Episode4Background.png b/IB Images/Episode4Background.png new file mode 100644 index 0000000..79b1bd3 Binary files /dev/null and b/IB Images/Episode4Background.png differ diff --git a/IB Images/Episode4Background_Highlighted.png b/IB Images/Episode4Background_Highlighted.png new file mode 100644 index 0000000..3622ca3 Binary files /dev/null and b/IB Images/Episode4Background_Highlighted.png differ diff --git a/IB Images/Hard.png b/IB Images/Hard.png new file mode 100644 index 0000000..a3cb5f4 Binary files /dev/null and b/IB Images/Hard.png differ diff --git a/IB Images/LayoutDualButton.png b/IB Images/LayoutDualButton.png new file mode 100644 index 0000000..5a904ac Binary files /dev/null and b/IB Images/LayoutDualButton.png differ diff --git a/IB Images/LayoutDualButton_Highlighted.png b/IB Images/LayoutDualButton_Highlighted.png new file mode 100644 index 0000000..8e84b45 Binary files /dev/null and b/IB Images/LayoutDualButton_Highlighted.png differ diff --git a/IB Images/LayoutSingleButton.png b/IB Images/LayoutSingleButton.png new file mode 100644 index 0000000..6b61d72 Binary files /dev/null and b/IB Images/LayoutSingleButton.png differ diff --git a/IB Images/LayoutSingleButton_Highlighted.png b/IB Images/LayoutSingleButton_Highlighted.png new file mode 100644 index 0000000..1c106c1 Binary files /dev/null and b/IB Images/LayoutSingleButton_Highlighted.png differ diff --git a/IB Images/LayoutWheelButton.png b/IB Images/LayoutWheelButton.png new file mode 100644 index 0000000..f7989f1 Binary files /dev/null and b/IB Images/LayoutWheelButton.png differ diff --git a/IB Images/LayoutWheelButton_Highlighted.png b/IB Images/LayoutWheelButton_Highlighted.png new file mode 100644 index 0000000..381ea09 Binary files /dev/null and b/IB Images/LayoutWheelButton_Highlighted.png differ diff --git a/IB Images/MapOverlay.png b/IB Images/MapOverlay.png new file mode 100644 index 0000000..c14752c Binary files /dev/null and b/IB Images/MapOverlay.png differ diff --git a/IB Images/Medium.png b/IB Images/Medium.png new file mode 100644 index 0000000..8c1aa0f Binary files /dev/null and b/IB Images/Medium.png differ diff --git a/IB Images/MenuBackground.png b/IB Images/MenuBackground.png new file mode 100644 index 0000000..2ddc52c Binary files /dev/null and b/IB Images/MenuBackground.png differ diff --git a/IB Images/MissonBackground.png b/IB Images/MissonBackground.png new file mode 100644 index 0000000..492baf1 Binary files /dev/null and b/IB Images/MissonBackground.png differ diff --git a/IB Images/NextButton.png b/IB Images/NextButton.png new file mode 100644 index 0000000..1623d3e Binary files /dev/null and b/IB Images/NextButton.png differ diff --git a/IB Images/NextButton_Highlighted.png b/IB Images/NextButton_Highlighted.png new file mode 100644 index 0000000..55e9fc4 Binary files /dev/null and b/IB Images/NextButton_Highlighted.png differ diff --git a/IB Images/Nightmare.png b/IB Images/Nightmare.png new file mode 100644 index 0000000..3bb2ab0 Binary files /dev/null and b/IB Images/Nightmare.png differ diff --git a/IB Images/ResumeButton.png b/IB Images/ResumeButton.png new file mode 100644 index 0000000..75b4df4 Binary files /dev/null and b/IB Images/ResumeButton.png differ diff --git a/IB Images/SelectedBracket.png b/IB Images/SelectedBracket.png new file mode 100644 index 0000000..9f425a0 Binary files /dev/null and b/IB Images/SelectedBracket.png differ diff --git a/IB Images/SettingsButton.png b/IB Images/SettingsButton.png new file mode 100644 index 0000000..85a4b8c Binary files /dev/null and b/IB Images/SettingsButton.png differ diff --git a/IB Images/SettingsButton_Highlighted.png b/IB Images/SettingsButton_Highlighted.png new file mode 100644 index 0000000..4912fc7 Binary files /dev/null and b/IB Images/SettingsButton_Highlighted.png differ diff --git a/IB Images/SliderBackground.png b/IB Images/SliderBackground.png new file mode 100644 index 0000000..fd552dd Binary files /dev/null and b/IB Images/SliderBackground.png differ diff --git a/IB Images/SliderBar.png b/IB Images/SliderBar.png new file mode 100644 index 0000000..4dd6dc7 Binary files /dev/null and b/IB Images/SliderBar.png differ diff --git a/IB Images/SliderSkull.png b/IB Images/SliderSkull.png new file mode 100644 index 0000000..30f3349 Binary files /dev/null and b/IB Images/SliderSkull.png differ diff --git a/IB Images/SliderSkull@2x.png b/IB Images/SliderSkull@2x.png new file mode 100644 index 0000000..0c0a044 Binary files /dev/null and b/IB Images/SliderSkull@2x.png differ diff --git a/IB Images/SliderSkull~ipad.png b/IB Images/SliderSkull~ipad.png new file mode 100644 index 0000000..0c0a044 Binary files /dev/null and b/IB Images/SliderSkull~ipad.png differ diff --git a/IB Images/SubMenuBackground.png b/IB Images/SubMenuBackground.png new file mode 100644 index 0000000..a536ecb Binary files /dev/null and b/IB Images/SubMenuBackground.png differ diff --git a/IB Images/SubMenuButton.png b/IB Images/SubMenuButton.png new file mode 100644 index 0000000..355bd9d Binary files /dev/null and b/IB Images/SubMenuButton.png differ diff --git a/IB Images/SubMenuButton_Highlighted.png b/IB Images/SubMenuButton_Highlighted.png new file mode 100644 index 0000000..402feee Binary files /dev/null and b/IB Images/SubMenuButton_Highlighted.png differ diff --git a/IB Images/Thumbs.db b/IB Images/Thumbs.db new file mode 100644 index 0000000..ac98a41 Binary files /dev/null and b/IB Images/Thumbs.db differ diff --git a/IB Images/UpArrow.png b/IB Images/UpArrow.png new file mode 100644 index 0000000..9fab509 Binary files /dev/null and b/IB Images/UpArrow.png differ diff --git a/IB Images/UpArrow_Highlighted.png b/IB Images/UpArrow_Highlighted.png new file mode 100644 index 0000000..b5bed6e Binary files /dev/null and b/IB Images/UpArrow_Highlighted.png differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc795ea --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ + + +# DOOM, DOOM II, Final DOOM and SIGIL for iOS 11 and tvOS for Apple TV + +This is my update for DOOM for iOS to run on iOS 11, running in modern resolutions including the full width of the iPhone X. I have also made a target and version for tvOS to run on Apple TV. Additionally, I have included targets to create apps for DOOM II, Final DOOM and [SIGIL](https://www.romerogames.ie/si6il). + +![screenshot](https://raw.githubusercontent.com/tomkidd/DOOM-iOS/master/ss_doom.png) + +Improvements/Changes + +- Compiles and runs in iOS 11 SDK +- Orientation and coordinate system fixed to reflect iOS 8 changes +- C warnings fixed for Xcode 9.3 +- Basic MFi controller support +- Structure and View Controller usage grafted in from the DOOM-iOS2 repository and public user forks, unused code and embedded xcodeproj use eliminated +- Second project target for tvOS that takes advantage of focus model and removes on-screen controls. + +You will need to provide your own copy of `doom.wad` for DOOM, `doom2.wad` for DOOM II, `tnt.wad` and `plutonia.wad` for Final DOOM and `SIGIL.wad` (and optionally `SIGIL_SHREDS.wad`) for SIGIL + +You can find the file `doom.wad` in any installation of DOOM, available on [Steam](http://store.steampowered.com/app/2280/Ultimate_Doom/), [GOG](https://www.gog.com/game/the_ultimate_doom), and floppy disk from 1-800-IDGAMES (note: do not call 1-800-IDGAMES I don't know where it goes anymore). + +`doom2.wad` is in any installation of DOOM II, available on [Steam](https://store.steampowered.com/app/2300/DOOM_II/) or [GOG](https://www.gog.com/game/doom_ii_final_doom) + +`tnt.wad` and `plutonia.wad` are in any installation of Final DOOM, available on [Steam](https://store.steampowered.com/app/2290/Final_DOOM/) or [GOG](https://www.gog.com/game/doom_ii_final_doom) (note that GOG sells DOOM II and Final DOOM packaged together) + +`SIGIL.wad` is available free from the [SIGIL](https://www.romerogames.ie/si6il) website, and `SIGIL_SHREDS.wad` is available in the "registered" (purchased) versions. Note that SIGIL also requires `doom.wad` from the original game. + +This repo contains changes from id's [DOOM-iOS2](https://github.com/id-Software/DOOM-IOS2) repo (different than the parent of this repo), changes from the [FinalJudgement](https://github.com/JadingTsunami/FinalJudgment-iOS) repo by [JadingTsunami](https://github.com/JadingTsunami/), and [MFi controller code](https://github.com/johnnyw/DOOM-IOS2/commit/41646df7ccad6e39263a73767e91d5801759b780) from [John Watson](https://github.com/johnnyw) (by way of [TheRohans](https://github.com/TheRohans/DOOM-IOS2/), where I originally found it). I incorporated the efforts of [yarsrevenge](https://github.com/yarsrvenge/DOOM-IOS2) in getting the basics of the tvOS versions going. + +I wrote a [lengthy article](http://schnapple.com/wolfenstein-3d-and-doom-on-ios-11/) on the process of making these ports. For a rundown of the effort to get it running on tvOS, I wrote a [second lenghty article](http://schnapple.com/wolfenstein-3d-and-doom-on-tvos-for-apple-tv/) on the subject. + +And just for fun I did [another article](https://schnapple.com/sigil-for-ios-and-tvos-for-apple-tv/) on adding SIGIL support. Note that the previous issues with SIGIL's intermission screens and the Buckethead MP3 files have been addressed. + +[Video of DOOM running on an iPhone X](https://www.youtube.com/watch?v=IrY5L1kn-NA) + +[Video of DOOM running on an Apple TV](https://www.youtube.com/watch?v=P8QmMSabaqQ) + +I have also made apps for [*Wolfenstein 3-D*](https://github.com/tomkidd/Wolf3D-iOS), [*Quake*](https://github.com/tomkidd/Quake-iOS), [*Quake II*](https://github.com/tomkidd/Quake2-iOS), [*Quake III: Arena*](https://github.com/tomkidd/Quake3-iOS), [*Return to Castle Wolfenstein*](https://github.com/tomkidd/RTCW-iOS) and [*DOOM 3*](https://github.com/tomkidd/DOOM3-iOS). + +Have fun. For any questions I can be reached at tomkidd@gmail.com diff --git a/assets/iphone/arialimagelal.tga b/assets/iphone/arialimagelal.tga new file mode 100644 index 0000000..83e44f1 Binary files /dev/null and b/assets/iphone/arialimagelal.tga differ diff --git a/assets/iphone/baborted_01.wav b/assets/iphone/baborted_01.wav new file mode 100644 index 0000000..7af58d6 Binary files /dev/null and b/assets/iphone/baborted_01.wav differ diff --git a/assets/iphone/back_button.tga b/assets/iphone/back_button.tga new file mode 100644 index 0000000..09110bf Binary files /dev/null and b/assets/iphone/back_button.tga differ diff --git a/assets/iphone/baction_01.wav b/assets/iphone/baction_01.wav new file mode 100644 index 0000000..6a043c9 Binary files /dev/null and b/assets/iphone/baction_01.wav differ diff --git a/assets/iphone/bdown_01.wav b/assets/iphone/bdown_01.wav new file mode 100644 index 0000000..0d836ed Binary files /dev/null and b/assets/iphone/bdown_01.wav differ diff --git a/assets/iphone/controller_down_01.wav b/assets/iphone/controller_down_01.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/iphone/controller_down_01.wav differ diff --git a/assets/iphone/controller_down_01_silence.wav b/assets/iphone/controller_down_01_silence.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/iphone/controller_down_01_silence.wav differ diff --git a/assets/iphone/controller_up_01.wav b/assets/iphone/controller_up_01.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/iphone/controller_up_01.wav differ diff --git a/assets/iphone/controller_up_01_silence.wav b/assets/iphone/controller_up_01_silence.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/iphone/controller_up_01_silence.wav differ diff --git a/assets/iphone/deathmatch.tga b/assets/iphone/deathmatch.tga new file mode 100644 index 0000000..d324692 Binary files /dev/null and b/assets/iphone/deathmatch.tga differ diff --git a/assets/iphone/directional_2.tga b/assets/iphone/directional_2.tga new file mode 100644 index 0000000..4220fe1 Binary files /dev/null and b/assets/iphone/directional_2.tga differ diff --git a/assets/iphone/disc_1.tga b/assets/iphone/disc_1.tga new file mode 100644 index 0000000..d324692 Binary files /dev/null and b/assets/iphone/disc_1.tga differ diff --git a/assets/iphone/disc_2.tga b/assets/iphone/disc_2.tga new file mode 100644 index 0000000..d324692 Binary files /dev/null and b/assets/iphone/disc_2.tga differ diff --git a/assets/iphone/fire.tga b/assets/iphone/fire.tga new file mode 100644 index 0000000..0214ac6 Binary files /dev/null and b/assets/iphone/fire.tga differ diff --git a/assets/iphone/font1.tga b/assets/iphone/font1.tga new file mode 100644 index 0000000..c2d5412 Binary files /dev/null and b/assets/iphone/font1.tga differ diff --git a/assets/iphone/kills.tga b/assets/iphone/kills.tga new file mode 100644 index 0000000..afb22d6 Binary files /dev/null and b/assets/iphone/kills.tga differ diff --git a/assets/iphone/load_saved.tga b/assets/iphone/load_saved.tga new file mode 100644 index 0000000..ccd99e9 Binary files /dev/null and b/assets/iphone/load_saved.tga differ diff --git a/assets/iphone/loading.tga b/assets/iphone/loading.tga new file mode 100644 index 0000000..de99ac0 Binary files /dev/null and b/assets/iphone/loading.tga differ diff --git a/assets/iphone/long_string_box.tga b/assets/iphone/long_string_box.tga new file mode 100644 index 0000000..baf8301 Binary files /dev/null and b/assets/iphone/long_string_box.tga differ diff --git a/assets/iphone/map_button.tga b/assets/iphone/map_button.tga new file mode 100644 index 0000000..fc17feb Binary files /dev/null and b/assets/iphone/map_button.tga differ diff --git a/assets/iphone/menu_bar.tga b/assets/iphone/menu_bar.tga new file mode 100644 index 0000000..cf3176a Binary files /dev/null and b/assets/iphone/menu_bar.tga differ diff --git a/assets/iphone/menu_button.tga b/assets/iphone/menu_button.tga new file mode 100644 index 0000000..6f950f3 Binary files /dev/null and b/assets/iphone/menu_button.tga differ diff --git a/assets/iphone/multi_backdrop.tga b/assets/iphone/multi_backdrop.tga new file mode 100644 index 0000000..e6c9549 Binary files /dev/null and b/assets/iphone/multi_backdrop.tga differ diff --git a/assets/iphone/multi_face.tga b/assets/iphone/multi_face.tga new file mode 100644 index 0000000..ed2fbb1 Binary files /dev/null and b/assets/iphone/multi_face.tga differ diff --git a/assets/iphone/multi_frame.tga b/assets/iphone/multi_frame.tga new file mode 100644 index 0000000..ed2fbb1 Binary files /dev/null and b/assets/iphone/multi_frame.tga differ diff --git a/assets/iphone/multiplay.tga b/assets/iphone/multiplay.tga new file mode 100644 index 0000000..a973f69 Binary files /dev/null and b/assets/iphone/multiplay.tga differ diff --git a/assets/iphone/par.tga b/assets/iphone/par.tga new file mode 100644 index 0000000..ed2fbb1 Binary files /dev/null and b/assets/iphone/par.tga differ diff --git a/assets/iphone/partime.tga b/assets/iphone/partime.tga new file mode 100644 index 0000000..afb22d6 Binary files /dev/null and b/assets/iphone/partime.tga differ diff --git a/assets/iphone/respawn.tga b/assets/iphone/respawn.tga new file mode 100644 index 0000000..011fb88 Binary files /dev/null and b/assets/iphone/respawn.tga differ diff --git a/assets/iphone/respawn_gear.tga b/assets/iphone/respawn_gear.tga new file mode 100644 index 0000000..52575c8 Binary files /dev/null and b/assets/iphone/respawn_gear.tga differ diff --git a/assets/iphone/rotate.tga b/assets/iphone/rotate.tga new file mode 100644 index 0000000..3a0766f Binary files /dev/null and b/assets/iphone/rotate.tga differ diff --git a/assets/iphone/secrets.tga b/assets/iphone/secrets.tga new file mode 100644 index 0000000..ed2fbb1 Binary files /dev/null and b/assets/iphone/secrets.tga differ diff --git a/assets/iphone/short_string_box.tga b/assets/iphone/short_string_box.tga new file mode 100644 index 0000000..90d1ea5 Binary files /dev/null and b/assets/iphone/short_string_box.tga differ diff --git a/assets/iphone/side_2_side.tga b/assets/iphone/side_2_side.tga new file mode 100644 index 0000000..b3afa02 Binary files /dev/null and b/assets/iphone/side_2_side.tga differ diff --git a/assets/iphone/slide_01.wav b/assets/iphone/slide_01.wav new file mode 100644 index 0000000..6256eb3 Binary files /dev/null and b/assets/iphone/slide_01.wav differ diff --git a/assets/iphone/up_down.tga b/assets/iphone/up_down.tga new file mode 100644 index 0000000..6bb6670 Binary files /dev/null and b/assets/iphone/up_down.tga differ diff --git a/assets/newsfx/dsbarexp.wav b/assets/newsfx/dsbarexp.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbarexp.wav differ diff --git a/assets/newsfx/dsbdcls.wav b/assets/newsfx/dsbdcls.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbdcls.wav differ diff --git a/assets/newsfx/dsbdopn.wav b/assets/newsfx/dsbdopn.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbdopn.wav differ diff --git a/assets/newsfx/dsbfg.wav b/assets/newsfx/dsbfg.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbfg.wav differ diff --git a/assets/newsfx/dsbgact.wav b/assets/newsfx/dsbgact.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbgact.wav differ diff --git a/assets/newsfx/dsbgdth1.wav b/assets/newsfx/dsbgdth1.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbgdth1.wav differ diff --git a/assets/newsfx/dsbgdth2.wav b/assets/newsfx/dsbgdth2.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbgdth2.wav differ diff --git a/assets/newsfx/dsbgsit1.wav b/assets/newsfx/dsbgsit1.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbgsit1.wav differ diff --git a/assets/newsfx/dsbgsit2.wav b/assets/newsfx/dsbgsit2.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbgsit2.wav differ diff --git a/assets/newsfx/dsboscub.wav b/assets/newsfx/dsboscub.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsboscub.wav differ diff --git a/assets/newsfx/dsbosdth.wav b/assets/newsfx/dsbosdth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbosdth.wav differ diff --git a/assets/newsfx/dsbospit.wav b/assets/newsfx/dsbospit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbospit.wav differ diff --git a/assets/newsfx/dsbospn.wav b/assets/newsfx/dsbospn.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbospn.wav differ diff --git a/assets/newsfx/dsbossit.wav b/assets/newsfx/dsbossit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbossit.wav differ diff --git a/assets/newsfx/dsbrsdth.wav b/assets/newsfx/dsbrsdth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbrsdth.wav differ diff --git a/assets/newsfx/dsbrssit.wav b/assets/newsfx/dsbrssit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbrssit.wav differ diff --git a/assets/newsfx/dsbspact.wav b/assets/newsfx/dsbspact.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbspact.wav differ diff --git a/assets/newsfx/dsbspdth.wav b/assets/newsfx/dsbspdth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbspdth.wav differ diff --git a/assets/newsfx/dsbspsit.wav b/assets/newsfx/dsbspsit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbspsit.wav differ diff --git a/assets/newsfx/dsbspwlk.wav b/assets/newsfx/dsbspwlk.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsbspwlk.wav differ diff --git a/assets/newsfx/dscacdth.wav b/assets/newsfx/dscacdth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dscacdth.wav differ diff --git a/assets/newsfx/dscacsit.wav b/assets/newsfx/dscacsit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dscacsit.wav differ diff --git a/assets/newsfx/dsclaw.wav b/assets/newsfx/dsclaw.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsclaw.wav differ diff --git a/assets/newsfx/dscybdth.wav b/assets/newsfx/dscybdth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dscybdth.wav differ diff --git a/assets/newsfx/dscybsit.wav b/assets/newsfx/dscybsit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dscybsit.wav differ diff --git a/assets/newsfx/dsdbcls.wav b/assets/newsfx/dsdbcls.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsdbcls.wav differ diff --git a/assets/newsfx/dsdbload.wav b/assets/newsfx/dsdbload.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsdbload.wav differ diff --git a/assets/newsfx/dsdbopn.wav b/assets/newsfx/dsdbopn.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsdbopn.wav differ diff --git a/assets/newsfx/dsdmact.wav b/assets/newsfx/dsdmact.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsdmact.wav differ diff --git a/assets/newsfx/dsdmpain.wav b/assets/newsfx/dsdmpain.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsdmpain.wav differ diff --git a/assets/newsfx/dsdorcls.wav b/assets/newsfx/dsdorcls.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsdorcls.wav differ diff --git a/assets/newsfx/dsdoropn.wav b/assets/newsfx/dsdoropn.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsdoropn.wav differ diff --git a/assets/newsfx/dsdshtgn.wav b/assets/newsfx/dsdshtgn.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsdshtgn.wav differ diff --git a/assets/newsfx/dsfirsht.wav b/assets/newsfx/dsfirsht.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsfirsht.wav differ diff --git a/assets/newsfx/dsfirxpl.wav b/assets/newsfx/dsfirxpl.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsfirxpl.wav differ diff --git a/assets/newsfx/dsflame.wav b/assets/newsfx/dsflame.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsflame.wav differ diff --git a/assets/newsfx/dsflamst.wav b/assets/newsfx/dsflamst.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsflamst.wav differ diff --git a/assets/newsfx/dsgetpow.wav b/assets/newsfx/dsgetpow.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsgetpow.wav differ diff --git a/assets/newsfx/dshoof.wav b/assets/newsfx/dshoof.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dshoof.wav differ diff --git a/assets/newsfx/dsitemup.wav b/assets/newsfx/dsitemup.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsitemup.wav differ diff --git a/assets/newsfx/dsitmbk.wav b/assets/newsfx/dsitmbk.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsitmbk.wav differ diff --git a/assets/newsfx/dskeendt.wav b/assets/newsfx/dskeendt.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dskeendt.wav differ diff --git a/assets/newsfx/dskeenpn.wav b/assets/newsfx/dskeenpn.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dskeenpn.wav differ diff --git a/assets/newsfx/dskntdth.wav b/assets/newsfx/dskntdth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dskntdth.wav differ diff --git a/assets/newsfx/dskntsit.wav b/assets/newsfx/dskntsit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dskntsit.wav differ diff --git a/assets/newsfx/dsmanatk.wav b/assets/newsfx/dsmanatk.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsmanatk.wav differ diff --git a/assets/newsfx/dsmandth.wav b/assets/newsfx/dsmandth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsmandth.wav differ diff --git a/assets/newsfx/dsmansit.wav b/assets/newsfx/dsmansit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsmansit.wav differ diff --git a/assets/newsfx/dsmetal.wav b/assets/newsfx/dsmetal.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsmetal.wav differ diff --git a/assets/newsfx/dsmpain.wav b/assets/newsfx/dsmpain.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsmpain.wav differ diff --git a/assets/newsfx/dsnoway.wav b/assets/newsfx/dsnoway.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsnoway.wav differ diff --git a/assets/newsfx/dsoof.wav b/assets/newsfx/dsoof.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsoof.wav differ diff --git a/assets/newsfx/dspdiehi.wav b/assets/newsfx/dspdiehi.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspdiehi.wav differ diff --git a/assets/newsfx/dspedth.wav b/assets/newsfx/dspedth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspedth.wav differ diff --git a/assets/newsfx/dspepain.wav b/assets/newsfx/dspepain.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspepain.wav differ diff --git a/assets/newsfx/dspesit.wav b/assets/newsfx/dspesit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspesit.wav differ diff --git a/assets/newsfx/dspistol.wav b/assets/newsfx/dspistol.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspistol.wav differ diff --git a/assets/newsfx/dsplasma.wav b/assets/newsfx/dsplasma.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsplasma.wav differ diff --git a/assets/newsfx/dspldeth.wav b/assets/newsfx/dspldeth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspldeth.wav differ diff --git a/assets/newsfx/dsplpain.wav b/assets/newsfx/dsplpain.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsplpain.wav differ diff --git a/assets/newsfx/dspodth1.wav b/assets/newsfx/dspodth1.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspodth1.wav differ diff --git a/assets/newsfx/dspodth2.wav b/assets/newsfx/dspodth2.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspodth2.wav differ diff --git a/assets/newsfx/dspodth3.wav b/assets/newsfx/dspodth3.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspodth3.wav differ diff --git a/assets/newsfx/dspopain.wav b/assets/newsfx/dspopain.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspopain.wav differ diff --git a/assets/newsfx/dsposact.wav b/assets/newsfx/dsposact.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsposact.wav differ diff --git a/assets/newsfx/dsposit1.wav b/assets/newsfx/dsposit1.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsposit1.wav differ diff --git a/assets/newsfx/dsposit2.wav b/assets/newsfx/dsposit2.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsposit2.wav differ diff --git a/assets/newsfx/dsposit3.wav b/assets/newsfx/dsposit3.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsposit3.wav differ diff --git a/assets/newsfx/dspstart.wav b/assets/newsfx/dspstart.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspstart.wav differ diff --git a/assets/newsfx/dspstop.wav b/assets/newsfx/dspstop.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspstop.wav differ diff --git a/assets/newsfx/dspunch.wav b/assets/newsfx/dspunch.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dspunch.wav differ diff --git a/assets/newsfx/dsradio.wav b/assets/newsfx/dsradio.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsradio.wav differ diff --git a/assets/newsfx/dsrlaunc.wav b/assets/newsfx/dsrlaunc.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsrlaunc.wav differ diff --git a/assets/newsfx/dsrxplod.wav b/assets/newsfx/dsrxplod.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsrxplod.wav differ diff --git a/assets/newsfx/dssawful.wav b/assets/newsfx/dssawful.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssawful.wav differ diff --git a/assets/newsfx/dssawhit.wav b/assets/newsfx/dssawhit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssawhit.wav differ diff --git a/assets/newsfx/dssawidl.wav b/assets/newsfx/dssawidl.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssawidl.wav differ diff --git a/assets/newsfx/dssawup.wav b/assets/newsfx/dssawup.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssawup.wav differ diff --git a/assets/newsfx/dssgcock.wav b/assets/newsfx/dssgcock.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssgcock.wav differ diff --git a/assets/newsfx/dssgtatk.wav b/assets/newsfx/dssgtatk.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssgtatk.wav differ diff --git a/assets/newsfx/dssgtdth.wav b/assets/newsfx/dssgtdth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssgtdth.wav differ diff --git a/assets/newsfx/dssgtsit.wav b/assets/newsfx/dssgtsit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssgtsit.wav differ diff --git a/assets/newsfx/dsshotgn.wav b/assets/newsfx/dsshotgn.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsshotgn.wav differ diff --git a/assets/newsfx/dsskeact.wav b/assets/newsfx/dsskeact.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsskeact.wav differ diff --git a/assets/newsfx/dsskeatk.wav b/assets/newsfx/dsskeatk.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsskeatk.wav differ diff --git a/assets/newsfx/dsskedth.wav b/assets/newsfx/dsskedth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsskedth.wav differ diff --git a/assets/newsfx/dsskepch.wav b/assets/newsfx/dsskepch.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsskepch.wav differ diff --git a/assets/newsfx/dsskesit.wav b/assets/newsfx/dsskesit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsskesit.wav differ diff --git a/assets/newsfx/dsskeswg.wav b/assets/newsfx/dsskeswg.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsskeswg.wav differ diff --git a/assets/newsfx/dssklatk.wav b/assets/newsfx/dssklatk.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssklatk.wav differ diff --git a/assets/newsfx/dsskldth.wav b/assets/newsfx/dsskldth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsskldth.wav differ diff --git a/assets/newsfx/dsslop.wav b/assets/newsfx/dsslop.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsslop.wav differ diff --git a/assets/newsfx/dsspidth.wav b/assets/newsfx/dsspidth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsspidth.wav differ diff --git a/assets/newsfx/dsspisit.wav b/assets/newsfx/dsspisit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsspisit.wav differ diff --git a/assets/newsfx/dsssdth.wav b/assets/newsfx/dsssdth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsssdth.wav differ diff --git a/assets/newsfx/dssssit.wav b/assets/newsfx/dssssit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dssssit.wav differ diff --git a/assets/newsfx/dsstnmov.wav b/assets/newsfx/dsstnmov.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsstnmov.wav differ diff --git a/assets/newsfx/dsswtchn.wav b/assets/newsfx/dsswtchn.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsswtchn.wav differ diff --git a/assets/newsfx/dsswtchx.wav b/assets/newsfx/dsswtchx.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsswtchx.wav differ diff --git a/assets/newsfx/dstelept.wav b/assets/newsfx/dstelept.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dstelept.wav differ diff --git a/assets/newsfx/dstink.wav b/assets/newsfx/dstink.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dstink.wav differ diff --git a/assets/newsfx/dsvilact.wav b/assets/newsfx/dsvilact.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsvilact.wav differ diff --git a/assets/newsfx/dsvilatk.wav b/assets/newsfx/dsvilatk.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsvilatk.wav differ diff --git a/assets/newsfx/dsvildth.wav b/assets/newsfx/dsvildth.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsvildth.wav differ diff --git a/assets/newsfx/dsvilsit.wav b/assets/newsfx/dsvilsit.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsvilsit.wav differ diff --git a/assets/newsfx/dsvipain.wav b/assets/newsfx/dsvipain.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dsvipain.wav differ diff --git a/assets/newsfx/dswpnup.wav b/assets/newsfx/dswpnup.wav new file mode 100644 index 0000000..ad8841d Binary files /dev/null and b/assets/newsfx/dswpnup.wav differ diff --git a/base.parm b/base.parm new file mode 100755 index 0000000..806dda4 --- /dev/null +++ b/base.parm @@ -0,0 +1,2 @@ +iphone/livetile_1.tga PVR2 +iphone/arialImageLAL.tga LA diff --git a/base/.DS_Store b/base/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/base/.DS_Store and /dev/null differ diff --git a/base/base.iPack b/base/base.iPack new file mode 100644 index 0000000..4d91186 Binary files /dev/null and b/base/base.iPack differ diff --git a/base/music/d_bunny.mp3 b/base/music/d_bunny.mp3 new file mode 100644 index 0000000..b49109e Binary files /dev/null and b/base/music/d_bunny.mp3 differ diff --git a/base/music/d_e1m1.mp3 b/base/music/d_e1m1.mp3 new file mode 100644 index 0000000..bb16065 Binary files /dev/null and b/base/music/d_e1m1.mp3 differ diff --git a/base/music/d_e1m2.mp3 b/base/music/d_e1m2.mp3 new file mode 100644 index 0000000..ec24d5a Binary files /dev/null and b/base/music/d_e1m2.mp3 differ diff --git a/base/music/d_e1m3.mp3 b/base/music/d_e1m3.mp3 new file mode 100644 index 0000000..61ef8a0 Binary files /dev/null and b/base/music/d_e1m3.mp3 differ diff --git a/base/music/d_e1m4.mp3 b/base/music/d_e1m4.mp3 new file mode 100644 index 0000000..527d7db Binary files /dev/null and b/base/music/d_e1m4.mp3 differ diff --git a/base/music/d_e1m5.mp3 b/base/music/d_e1m5.mp3 new file mode 100644 index 0000000..100954b Binary files /dev/null and b/base/music/d_e1m5.mp3 differ diff --git a/base/music/d_e1m6.mp3 b/base/music/d_e1m6.mp3 new file mode 100644 index 0000000..d49e45a Binary files /dev/null and b/base/music/d_e1m6.mp3 differ diff --git a/base/music/d_e1m7.mp3 b/base/music/d_e1m7.mp3 new file mode 100644 index 0000000..365d222 Binary files /dev/null and b/base/music/d_e1m7.mp3 differ diff --git a/base/music/d_e1m8.mp3 b/base/music/d_e1m8.mp3 new file mode 100644 index 0000000..0a62e49 Binary files /dev/null and b/base/music/d_e1m8.mp3 differ diff --git a/base/music/d_e1m9.mp3 b/base/music/d_e1m9.mp3 new file mode 100644 index 0000000..07600ac Binary files /dev/null and b/base/music/d_e1m9.mp3 differ diff --git a/base/music/d_e2m1.mp3 b/base/music/d_e2m1.mp3 new file mode 100644 index 0000000..946c8c7 Binary files /dev/null and b/base/music/d_e2m1.mp3 differ diff --git a/base/music/d_e2m2.mp3 b/base/music/d_e2m2.mp3 new file mode 100644 index 0000000..8945320 Binary files /dev/null and b/base/music/d_e2m2.mp3 differ diff --git a/base/music/d_e2m3.mp3 b/base/music/d_e2m3.mp3 new file mode 100644 index 0000000..6688e56 Binary files /dev/null and b/base/music/d_e2m3.mp3 differ diff --git a/base/music/d_e2m4.mp3 b/base/music/d_e2m4.mp3 new file mode 100644 index 0000000..213685e Binary files /dev/null and b/base/music/d_e2m4.mp3 differ diff --git a/base/music/d_e2m5.mp3 b/base/music/d_e2m5.mp3 new file mode 100644 index 0000000..947a5e4 Binary files /dev/null and b/base/music/d_e2m5.mp3 differ diff --git a/base/music/d_e2m6.mp3 b/base/music/d_e2m6.mp3 new file mode 100644 index 0000000..84355f3 Binary files /dev/null and b/base/music/d_e2m6.mp3 differ diff --git a/base/music/d_e2m7.mp3 b/base/music/d_e2m7.mp3 new file mode 100644 index 0000000..548d5fb Binary files /dev/null and b/base/music/d_e2m7.mp3 differ diff --git a/base/music/d_e2m8.mp3 b/base/music/d_e2m8.mp3 new file mode 100644 index 0000000..1416ce5 Binary files /dev/null and b/base/music/d_e2m8.mp3 differ diff --git a/base/music/d_e2m9.mp3 b/base/music/d_e2m9.mp3 new file mode 100644 index 0000000..c273847 Binary files /dev/null and b/base/music/d_e2m9.mp3 differ diff --git a/base/music/d_e3m1.mp3 b/base/music/d_e3m1.mp3 new file mode 100644 index 0000000..c273847 Binary files /dev/null and b/base/music/d_e3m1.mp3 differ diff --git a/base/music/d_e3m2.mp3 b/base/music/d_e3m2.mp3 new file mode 100644 index 0000000..861b508 Binary files /dev/null and b/base/music/d_e3m2.mp3 differ diff --git a/base/music/d_e3m3.mp3 b/base/music/d_e3m3.mp3 new file mode 100644 index 0000000..25e1bf5 Binary files /dev/null and b/base/music/d_e3m3.mp3 differ diff --git a/base/music/d_e3m4.mp3 b/base/music/d_e3m4.mp3 new file mode 100644 index 0000000..1dd400e Binary files /dev/null and b/base/music/d_e3m4.mp3 differ diff --git a/base/music/d_e3m5.mp3 b/base/music/d_e3m5.mp3 new file mode 100644 index 0000000..8a24a80 Binary files /dev/null and b/base/music/d_e3m5.mp3 differ diff --git a/base/music/d_e3m6.mp3 b/base/music/d_e3m6.mp3 new file mode 100644 index 0000000..1506fd3 Binary files /dev/null and b/base/music/d_e3m6.mp3 differ diff --git a/base/music/d_e3m7.mp3 b/base/music/d_e3m7.mp3 new file mode 100644 index 0000000..548d5fb Binary files /dev/null and b/base/music/d_e3m7.mp3 differ diff --git a/base/music/d_e3m8.mp3 b/base/music/d_e3m8.mp3 new file mode 100644 index 0000000..0e676f6 Binary files /dev/null and b/base/music/d_e3m8.mp3 differ diff --git a/base/music/d_e3m9.mp3 b/base/music/d_e3m9.mp3 new file mode 100644 index 0000000..07600ac Binary files /dev/null and b/base/music/d_e3m9.mp3 differ diff --git a/base/music/d_inter.mp3 b/base/music/d_inter.mp3 new file mode 100644 index 0000000..6688e56 Binary files /dev/null and b/base/music/d_inter.mp3 differ diff --git a/base/music/d_intro.mp3 b/base/music/d_intro.mp3 new file mode 100644 index 0000000..4384137 Binary files /dev/null and b/base/music/d_intro.mp3 differ diff --git a/base/music/d_introa.mp3 b/base/music/d_introa.mp3 new file mode 100644 index 0000000..174dd1d Binary files /dev/null and b/base/music/d_introa.mp3 differ diff --git a/base/music/d_victor.mp3 b/base/music/d_victor.mp3 new file mode 100644 index 0000000..7f289b5 Binary files /dev/null and b/base/music/d_victor.mp3 differ diff --git a/code/.DS_Store b/code/.DS_Store deleted file mode 100644 index 7a56bc5..0000000 Binary files a/code/.DS_Store and /dev/null differ diff --git a/code/SDL_shim/SDL_Mixer.h b/code/SDL_shim/SDL_Mixer.h new file mode 100755 index 0000000..672148a --- /dev/null +++ b/code/SDL_shim/SDL_Mixer.h @@ -0,0 +1,102 @@ +/* + + Copyright (C) 2011 Id Software, Inc. + + 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. + + */ + +#ifndef doomengine_SDL_Mixer_h +#define doomengine_SDL_Mixer_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* +=============================== + +This is a minimal implemenation of SDL_Mixer for iOS, just to get MIDI files +playing so that we can play the music directly from the WADs. + +=============================== +*/ + +#include + +typedef struct Mix_Music_tag { + char unused; +} Mix_Music; + + +/* Open the mixer with a certain audio format */ +extern int Mix_OpenAudio(int frequency, uint16_t format, int channels, + int chunksize); + + +/* Close the mixer, halting all playing audio */ +extern void Mix_CloseAudio(void); + + +/* Set a function that is called after all mixing is performed. + This can be used to provide real-time visual display of the audio stream + or add a custom mixer filter for the stream data. +*/ +extern void Mix_SetPostMix(void (*mix_func) + (void *udata, uint8_t *stream, int len), void *arg); + + +/* Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions */ +extern int Mix_FadeInMusic(Mix_Music *music, int loops, int ms); + + +/* Pause/Resume the music stream */ +extern void Mix_PauseMusic(void); +extern void Mix_ResumeMusic(void); + + +/* Halt a channel, fading it out progressively till it's silent + The ms parameter indicates the number of milliseconds the fading + will take. + */ +extern int Mix_FadeOutMusic(int ms); + + +/* Free an audio chunk previously loaded */ +extern void Mix_FreeMusic(Mix_Music *music); + + +/* Load a wave file or a music (.mod .s3m .it .xm) file */ +extern Mix_Music * Mix_LoadMUS(const char *file); + + +extern const char * Mix_GetError(void); + + + + +/* Set the volume in the range of 0-128 of a specific channel or chunk. + If the specified channel is -1, set volume for all channels. + Returns the original volume. + If the specified volume is -1, just return the current volume. +*/ +extern int Mix_VolumeMusic(int volume); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/code/SDL_shim/ios/SDL_Mixer.m b/code/SDL_shim/ios/SDL_Mixer.m new file mode 100755 index 0000000..e08bea0 --- /dev/null +++ b/code/SDL_shim/ios/SDL_Mixer.m @@ -0,0 +1,518 @@ +/* + + Copyright (C) 2011 Id Software, Inc. + + 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. + + */ + + +/* +=============================== + +iOS implementation of our SDL_Mixer shim for playing MIDI files. + +=============================== +*/ + +#include + +#include "../SDL_Mixer.h" + + +// Use the Embedded Audio Synthesis library as the backend MIDI renderer. +#include "../../embeddedaudiosynthesis/EASGlue.h" + + +// Use Core Audio Units for sound output on the device. +#import +#import + + +/* +=============================== + +"Constants" + +=============================== +*/ +#define ID_GRAPH_SAMPLE_RATE 22050 + + +/* +=============================== + +Internal Structures + +=============================== +*/ + +// Data structure for mono or stereo sound, to pass to the application's render callback function, +// which gets invoked by a Mixer unit input bus when it needs more audio to play. +typedef struct { + + BOOL isStereo; // set to true if there is data in the audioDataRight member + UInt32 frameCount; // the total number of frames in the audio data + UInt32 sampleNumber; // the next audio sample to play +} soundStruct, *soundStructPtr; + + + +typedef struct MIDIPlayerGraph_tag { + + AUGraph processingGraph; + AudioUnit ioUnit; + BOOL playing; + + AudioStreamBasicDescription streamFormat; + + soundStruct soundStructInst; +} MIDIPlayerGraph; + +static MIDIPlayerGraph midiPlayer; + + + +/* +=============================== + +Internal prototypes + +=============================== +*/ +AudioStreamBasicDescription getStreamFormat( void ); +static void printASBD( AudioStreamBasicDescription asbd ); +static void printErrorMessage( NSString * errorString, OSStatus result ); +static void configureAndInitializeAudioProcessingGraph( MIDIPlayerGraph * player ); +static void startMIDIPlayer( MIDIPlayerGraph * player ); + +// AU graph callback. +static OSStatus inputRenderCallback ( + + void *inRefCon, // A pointer to a struct containing the complete audio data + // to play, as well as state information such as the + // first sample to play on this invocation of the callback. + AudioUnitRenderActionFlags *ioActionFlags, // Unused here. When generating audio, use ioActionFlags to indicate silence + // between sounds; for silence, also memset the ioData buffers to 0. + const AudioTimeStamp *inTimeStamp, // Unused here. + UInt32 inBusNumber, // The mixer unit input bus that is requesting some new + // frames of audio data to play. + UInt32 inNumberFrames, // The number of frames of audio to provide to the buffer(s) + // pointed to by the ioData parameter. + AudioBufferList *ioData // On output, the audio data to play. The callback's primary + // responsibility is to fill the buffer(s) in the + // AudioBufferList. +); + + + +/* Open the mixer with a certain audio format */ +int Mix_OpenAudio(int frequency, uint16_t format, int channels, + int chunksize) { + + EASGlueInit(); + + midiPlayer.streamFormat = getStreamFormat(); + midiPlayer.playing = FALSE; + + configureAndInitializeAudioProcessingGraph( &midiPlayer ); + + return 0; +} + + +/* Close the mixer, halting all playing audio */ +void Mix_CloseAudio(void) { + AUGraphStop( midiPlayer.processingGraph ); + EASGlueShutdown(); +} + + +/* Set a function that is called after all mixing is performed. + This can be used to provide real-time visual display of the audio stream + or add a custom mixer filter for the stream data. +*/ +void Mix_SetPostMix(void (*mix_func) + (void *udata, uint8_t *stream, int len), void *arg) { + +} + + +/* Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions */ +int Mix_FadeInMusic(Mix_Music *music, int loops, int ms) { + + + startMIDIPlayer( &midiPlayer ); + + + return 0; +} + + +/* Pause/Resume the music stream */ +void Mix_PauseMusic(void) { + EASGluePause(); +} + + +void Mix_ResumeMusic(void) { + EASGlueResume(); +} + + +/* Halt a channel, fading it out progressively till it's silent + The ms parameter indicates the number of milliseconds the fading + will take. + */ +int Mix_FadeOutMusic(int ms) { + + EASGlueCloseFile(); + + AUGraphStop( midiPlayer.processingGraph ); + + return 1; +} + + +/* Free an audio chunk previously loaded */ +void Mix_FreeMusic(Mix_Music *music) { + free(music); +} + + +/* Load a wave file or a music (.mod .s3m .it .xm) file */ +Mix_Music * Mix_LoadMUS(const char *file) { + + EASGlueOpenFile( file ); + + Mix_Music * musicStruct = malloc( sizeof(Mix_Music) ); + + return musicStruct; +} + + +const char * Mix_GetError(void) { + return ""; +} + + +/* Set the volume in the range of 0-128 of a specific channel or chunk. + If the specified channel is -1, set volume for all channels. + Returns the original volume. + If the specified volume is -1, just return the current volume. +*/ +int Mix_VolumeMusic(int volume) { + + return 0; + +} + + + + + + +/* +================================= + Audio Unit helper functions +================================= +*/ + + +AudioStreamBasicDescription getStreamFormat( void ) { + + AudioStreamBasicDescription streamFormat = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + + // The AudioUnitSampleType data type is the recommended type for sample data in audio + // units. This obtains the byte size of the type for use in filling in the ASBD. + size_t bytesPerSample = sizeof (SInt32); + + // Fill the application audio format struct's fields to define a linear PCM, + // stereo, noninterleaved stream at the hardware sample rate. + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift); + streamFormat.mBytesPerPacket = (UInt32) bytesPerSample; + streamFormat.mFramesPerPacket = 1; + streamFormat.mBytesPerFrame = (UInt32) bytesPerSample; + streamFormat.mChannelsPerFrame = 2; // 2 indicates stereo + streamFormat.mBitsPerChannel = (UInt32) (8 * bytesPerSample); + streamFormat.mSampleRate = ID_GRAPH_SAMPLE_RATE; + + + NSLog (@"The stereo stream format for the I/O unit:"); + printASBD( streamFormat ); + + return streamFormat; +} + +static void startMIDIPlayer( MIDIPlayerGraph * player ) { + + if ( player == 0 ) { + NSLog( @"NULL player object, can't start!" ); + return; + } + + NSLog (@"Starting audio processing graph"); + OSStatus result = AUGraphStart (player->processingGraph); + if (noErr != result) { printErrorMessage( @"AUGraphStart", result ); return;} + + player->playing = YES; + +} + +// You can use this method during development and debugging to look at the +// fields of an AudioStreamBasicDescription struct. +static void printASBD( AudioStreamBasicDescription asbd ) { + + char formatIDString[5]; + UInt32 formatID = CFSwapInt32HostToBig (asbd.mFormatID); + bcopy (&formatID, formatIDString, 4); + formatIDString[4] = '\0'; + + NSLog (@" Sample Rate: %10.0f", asbd.mSampleRate); + NSLog (@" Format ID: %10s", formatIDString); + NSLog (@" Format Flags: %10X", (unsigned int)asbd.mFormatFlags); + NSLog (@" Bytes per Packet: %10u", (unsigned int)asbd.mBytesPerPacket); + NSLog (@" Frames per Packet: %10u", (unsigned int)asbd.mFramesPerPacket); + NSLog (@" Bytes per Frame: %10u", (unsigned int)asbd.mBytesPerFrame); + NSLog (@" Channels per Frame: %10u", (unsigned int)asbd.mChannelsPerFrame); + NSLog (@" Bits per Channel: %10u", (unsigned int)asbd.mBitsPerChannel); +} + + +static void printErrorMessage( NSString * errorString, OSStatus result ) { + + char resultString[5]; + UInt32 swappedResult = CFSwapInt32HostToBig (result); + bcopy (&swappedResult, resultString, 4); + resultString[4] = '\0'; + + NSLog ( + @"*** %@ error: %s\n", + errorString, + (char*) &resultString + ); +} + + +// This method performs all the work needed to set up the audio processing graph: + + // 1. Instantiate and open an audio processing graph + // 2. Obtain the audio unit nodes for the graph + // 3. Configure the Multichannel Mixer unit + // * specify the number of input buses + // * specify the output sample rate + // * specify the maximum frames-per-slice + // 4. Initialize the audio processing graph + +static void configureAndInitializeAudioProcessingGraph( MIDIPlayerGraph * player ) { + + if ( player == 0 ) { + NSLog( @"NULL player graph object, can't initialize it!" ); + return; + } + + + NSLog (@"Configuring and then initializing audio processing graph"); + OSStatus result = noErr; + +//............................................................................ +// Create a new audio processing graph. + result = NewAUGraph (&player->processingGraph); + + if (noErr != result) { printErrorMessage( @"NewAUGraph", result ); return;} + + +//............................................................................ +// Specify the audio unit component descriptions for the audio units to be +// added to the graph. + + // I/O unit + AudioComponentDescription iOUnitDescription; + iOUnitDescription.componentType = kAudioUnitType_Output; + iOUnitDescription.componentSubType = kAudioUnitSubType_RemoteIO; + iOUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; + iOUnitDescription.componentFlags = 0; + iOUnitDescription.componentFlagsMask = 0; + + +//............................................................................ +// Add nodes to the audio processing graph. + NSLog (@"Adding nodes to audio processing graph"); + + AUNode iONode; // node for I/O unit + + // Add the nodes to the audio processing graph + result = AUGraphAddNode ( + player->processingGraph, + &iOUnitDescription, + &iONode); + + if (noErr != result) { printErrorMessage( @"AUGraphNewNode failed for I/O unit", result ); return;} + +//............................................................................ +// Open the audio processing graph + + // Following this call, the audio units are instantiated but not initialized + // (no resource allocation occurs and the audio units are not in a state to + // process audio). + result = AUGraphOpen (player->processingGraph); + + if (noErr != result) { printErrorMessage( @"AUGraphOpen", result ); return;} + + +//............................................................................ +// Obtain the mixer unit instance from its corresponding node. + + result = AUGraphNodeInfo ( + player->processingGraph, + iONode, + NULL, + &player->ioUnit + ); + + if (noErr != result) { printErrorMessage( @"AUGraphNodeInfo", result ); return;} + + +//............................................................................ +// Multichannel Mixer unit Setup + + + // Setup the struture that contains the input render callback + AURenderCallbackStruct inputCallbackStruct; + inputCallbackStruct.inputProc = &inputRenderCallback; + inputCallbackStruct.inputProcRefCon = &player->soundStructInst; + + NSLog (@"Registering the render callback with the I/O unit" ); + // Set a callback for the specified node's specified input + result = AUGraphSetNodeInputCallback ( + player->processingGraph, + iONode, + 0, + &inputCallbackStruct + ); + + if (noErr != result) { printErrorMessage( @"AUGraphSetNodeInputCallback", result ); return;} + + + NSLog (@"Setting stereo stream format for I/O unit input bus"); + result = AudioUnitSetProperty ( + player->ioUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &player->streamFormat, + sizeof (player->streamFormat) + ); + + if (noErr != result) { printErrorMessage( @"AudioUnitSetProperty (set input bus stream format)", result ); return;} + +//............................................................................ +// Initialize audio processing graph + + // Diagnostic code + // Call CAShow if you want to look at the state of the audio processing + // graph. + NSLog (@"Audio processing graph state immediately before initializing it:"); + CAShow (player->processingGraph); + + NSLog (@"Initializing the audio processing graph"); + // Initialize the audio processing graph, configure audio data stream formats for + // each input and output, and validate the connections between audio units. + result = AUGraphInitialize (player->processingGraph); + + if (noErr != result) { printErrorMessage( @"AUGraphInitialize", result ); return;} +} + +#define RAW_EAS_BUFFER_FRAMES 128 + +static OSStatus inputRenderCallback ( + + void *inRefCon, // A pointer to a struct containing the complete audio data + // to play, as well as state information such as the + // first sample to play on this invocation of the callback. + AudioUnitRenderActionFlags *ioActionFlags, // Unused here. When generating audio, use ioActionFlags to indicate silence + // between sounds; for silence, also memset the ioData buffers to 0. + const AudioTimeStamp *inTimeStamp, // Unused here. + UInt32 inBusNumber, // The mixer unit input bus that is requesting some new + // frames of audio data to play. + UInt32 inNumberFrames, // The number of frames of audio to provide to the buffer(s) + // pointed to by the ioData parameter. + AudioBufferList *ioData // On output, the audio data to play. The callback's primary + // responsibility is to fill the buffer(s) in the + // AudioBufferList. +) { + + //printf( "Need %lu samples in %lu buffers!\n", inNumberFrames, ioData->mNumberBuffers ); + + EAS_I32 generatedThisRender = 0; + EAS_I32 totalGenerated = 0; + + // It looks like EAS interleaves stereo samples, so we have to separate them into the two + // different buffers that the audio unit provides. + //const UInt32 totalInterleavedSamplesNeeded = inNumberFrames * 2; + + AudioBuffer * audioBufferLeft = &ioData->mBuffers[0]; + AudioBuffer * audioBufferRight = &ioData->mBuffers[1]; + + /* + printf( "Need %lu samples in %lu buffers!\n" + "audioBuffer byte size: %lu channels: %lu\n", + inNumberFrames, ioData->mNumberBuffers, + audioBuffer->mDataByteSize, audioBuffer->mNumberChannels ); + */ + SInt32 * hardwareBufferLeft = (SInt32 *) audioBufferLeft->mData; + SInt32 * hardwareBufferRight = (SInt32 *) audioBufferRight->mData; + + + // EAS_Render always produces BUFFER_SIZE_IN_MONO_SAMPLES frames per call. Currently, this + // is defined to 128. Let's fill up a 128 frame buffer, then do a conversion from EAS_PCM + // (which is signed 16-bit integer) to AudioUnitSampleType (which is 8.24 fixed-point with + // a range of -1 to +1). + // + // Note that EAS renders interleaved stereo, so we actually a buffer size of + // 2 * BUFFER_SIZE_IN_MONO_SAMPLES. + + EAS_PCM rawEASSamples[RAW_EAS_BUFFER_FRAMES * 2]; + + + // EAS generates interleaved stereo samples, but the AudioUnit wants noninterleaved. + while ( totalGenerated < inNumberFrames ) { + //EASGlueRender( hardwareBuffer + totalGenerated*2, &generatedThisRender ); + EASGlueRender( rawEASSamples, &generatedThisRender ); + + + // Convert from EAS's signed 16-bit format to the AudioUnit's 8.24 fixed-point format. + // Couldn't find this in the Apple docs, but the 8.24 format should be in the range of + // -1.0 to 1.0, wasting 6 bits of precision. + // All we have to do here is left-shift by 9 bits. This will not overflow, because the + // destination is a 32-bit value. + // Also take this opportunity to de-interleave the EAS-rendered samples. + for ( int i = 0; i < RAW_EAS_BUFFER_FRAMES; ++i ) { + hardwareBufferLeft[totalGenerated + i] = rawEASSamples[i * 2 + 0] << 9; + hardwareBufferRight[totalGenerated + i] = rawEASSamples[i * 2 + 1] << 9; + } + + totalGenerated += generatedThisRender; + } + + return noErr; +} + + + + + diff --git a/code/doomiphone.h b/code/doomiphone.h old mode 100644 new mode 100755 index 0eadedd..946d247 --- a/code/doomiphone.h +++ b/code/doomiphone.h @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * doomiphone.h + * doom + * + * Created by John Carmack on 3/13/09. + * Copyright 2009 idSoftware. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -21,6 +29,18 @@ #ifndef _DOOM_IPHONE_H_ #define _DOOM_IPHONE_H_ +#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width) +#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height) +#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT)) +#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT)) +#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) +#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) +#define IS_IPHONE_X (IS_IPHONE && SCREEN_MAX_LENGTH == 812.0) +#define IPHONE_X_BOTTOM_INSET 64 +#define IS_TV (TARGET_OS_TV) + +#define PWAD_LIST_SEPARATOR ':' + #include #include #include @@ -48,7 +68,7 @@ #include #include -#include "iphone/gles_glue.h" +#include "gles_glue.h" #include #include @@ -56,8 +76,9 @@ #undef ALCAPI #define ALCAPI -#undef false -#undef true +#ifdef __cplusplus +extern "C" { +#endif #include "prboom/SDL_opengl.h" @@ -111,14 +132,17 @@ #undef glScissor // our vestigial system environment -#include "iphone/misc.h" -#include "iphone/cvar.h" +#include "misc.h" +#include "cvar.h" // new iphone code -#include "iphone/IBGlue.h" -#include "iphone/ipak.h" -#include "iphone/iphone_doom.h" -#include "iphone/iphone_email.h" //gsh, adds support for emailing the console to id +#include "ipak.h" +#include "iphone_email.h" //gsh, adds support for emailing the console to id + +#ifdef __cplusplus +} +#endif +#include "iphone_doom.h" #endif diff --git a/code/embeddedaudiosynthesis/Android.mk b/code/embeddedaudiosynthesis/Android.mk new file mode 100755 index 0000000..6571161 --- /dev/null +++ b/code/embeddedaudiosynthesis/Android.mk @@ -0,0 +1 @@ +include $(all-subdir-makefiles) diff --git a/code/embeddedaudiosynthesis/EASGlue.c b/code/embeddedaudiosynthesis/EASGlue.c new file mode 100755 index 0000000..0e4c0d2 --- /dev/null +++ b/code/embeddedaudiosynthesis/EASGlue.c @@ -0,0 +1,211 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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 "EASGlue.h" + +#include +#include +#include +#include + +#include "eas.h" +#include "eas_wave.h" +#include "eas_report.h" + +#define NUM_BUFFERS 1 + +#ifndef NDEBUG +static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig); +#endif + +static EAS_DATA_HANDLE pEASData; +static const S_EAS_LIB_CONFIG *pLibConfig; +static long int polyphony; +static long int bufferSize; + +static EAS_FILE file; +static EAS_HANDLE handle; + +void EASGlueInit(void) { + EAS_RESULT result; + + /* get the library configuration */ + pLibConfig = EAS_Config(); + assert( EASLibraryCheck(pLibConfig) ); + + if (polyphony > pLibConfig->maxVoices) + polyphony = (int)pLibConfig->maxVoices; + + EAS_I32 mixSize = pLibConfig->mixBufferSize; + + bufferSize = (int)(mixSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS); + + /* calculate buffer size */ + //bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS; + + + if ( (result = EAS_Init(&pEASData)) != EAS_SUCCESS ) { + printf( "Error initializing EAS: %li\n", result ); + } +} + + +void EASGlueShutdown(void) { + EAS_RESULT result; + + EASGlueCloseFile(); + if ( (result = EAS_Shutdown(pEASData)) != EAS_SUCCESS ) { + printf( "Error shutting down EAS: %li\n", result ); + } +} + +void EASGlueOpenFile( const char * filename ) { + + EAS_RESULT result; + + + /* open the file */ + file.path = filename; + file.fd = 0; + if ((result = EAS_OpenFile(pEASData, &file, &handle)) != EAS_SUCCESS) { + printf( "Error opening EAS file: %li\n", result ); + return; + } + + EAS_SetRepeat( pEASData, handle, -1 ); + + /* prepare for playback */ + if ((result = EAS_Prepare(pEASData, handle)) != EAS_SUCCESS) { + printf( "Error preparing EAS file: %li\n", result ); + return; + } +} + +void EASGluePause(void) { + EAS_RESULT result; + + if ( handle == 0 ) { + return; + } + + result = EAS_Pause( pEASData, handle ); + + if ( result != EAS_SUCCESS ) { + printf( "Error pausing EAS file: %li\n", result ); + } +} + +void EASGlueResume(void) { + EAS_RESULT result; + + result = EAS_Resume( pEASData, handle ); + + if ( result != EAS_SUCCESS ) { + printf( "Error pausing EAS file: %li\n", result ); + } +} + +void EASGlueCloseFile(void) { + + if ( handle == 0 ) { + return; + } + + // File must be paused or stopped before closing it. + EASGluePause(); + + EAS_RESULT result; + + result = EAS_CloseFile( pEASData, handle ); + + if ( result != EAS_SUCCESS ) { + printf( "Error closing EAS file: %li\n", result ); + } + + handle = 0; +} + +void EASGlueRender( EAS_PCM * outputBuffer, EAS_I32 * generatedSamples ) { + EAS_RESULT result; + + if ( ( result = EAS_Render( pEASData, outputBuffer, pLibConfig->mixBufferSize, generatedSamples ) ) != EAS_SUCCESS ) { + printf( "Error rendering EAS: %li\n.", result ); + return; + } +} + + +#ifndef NDEBUG +/*---------------------------------------------------------------------------- + * EASLibraryCheck() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the library version and checks it against the header + * file used to build this code. + * + * Inputs: + * pLibConfig - library configuration retrieved from the library + * + * Outputs: + * returns EAS_TRUE if matched + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *libConfig) +{ + + /* display the library version */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "EAS Library Version %d.%d.%d.%d\n", + libConfig->libVersion >> 24, + (libConfig->libVersion >> 16) & 0x0f, + (libConfig->libVersion >> 8) & 0x0f, + libConfig->libVersion & 0x0f); */ } + + /* display some info about the library build */ + if (libConfig->checkedVersion) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tChecked library\n"); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMaximum polyphony: %d\n", libConfig->maxVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tNumber of channels: %d\n", libConfig->numChannels); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tSample rate: %d\n", libConfig->sampleRate); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMix buffer size: %d\n", libConfig->mixBufferSize); */ } + if (libConfig->filterEnabled) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tFilter enabled\n"); */ } +#ifndef _WIN32_WCE + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build Timestamp: %s", ctime((time_t*)&libConfig->buildTimeStamp)); */ } +#endif + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build ID: %s\n", libConfig->buildGUID); */ } + + /* check it against the header file used to build this code */ + /*lint -e{778} constant expression used for display purposes may evaluate to zero */ + if (LIB_VERSION != libConfig->libVersion) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Library version does not match header files. EAS Header Version %d.%d.%d.%d\n", + LIB_VERSION >> 24, + (LIB_VERSION >> 16) & 0x0f, + (LIB_VERSION >> 8) & 0x0f, + LIB_VERSION & 0x0f); */ } + return EAS_FALSE; + } + return EAS_TRUE; +} /* end EASLibraryCheck */ + +#endif diff --git a/code/embeddedaudiosynthesis/EASGlue.h b/code/embeddedaudiosynthesis/EASGlue.h new file mode 100755 index 0000000..efb9747 --- /dev/null +++ b/code/embeddedaudiosynthesis/EASGlue.h @@ -0,0 +1,36 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#ifndef EAS_GLUE_H +#define EAS_GLUE_H + +#include "arm-wt-22k/host_src/eas.h" + +void EASGlueInit( void ); +void EASGlueShutdown( void ); + +void EASGlueOpenFile( const char * filename ); +void EASGluePause(void); +void EASGlueResume(void); +void EASGlueCloseFile(void); + +void EASGlueRender( EAS_PCM * outputBuffer, EAS_I32 * generatedSamples ); + +#endif diff --git a/code/embeddedaudiosynthesis/MODULE_LICENSE_APACHE2 b/code/embeddedaudiosynthesis/MODULE_LICENSE_APACHE2 new file mode 100755 index 0000000..e69de29 diff --git a/code/embeddedaudiosynthesis/NOTICE b/code/embeddedaudiosynthesis/NOTICE new file mode 100755 index 0000000..1f00f30 --- /dev/null +++ b/code/embeddedaudiosynthesis/NOTICE @@ -0,0 +1,14 @@ +Copyright (c) 2004-2006 Sonic Network Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + diff --git a/code/embeddedaudiosynthesis/ThirdPartyProject.prop b/code/embeddedaudiosynthesis/ThirdPartyProject.prop new file mode 100755 index 0000000..56281bb --- /dev/null +++ b/code/embeddedaudiosynthesis/ThirdPartyProject.prop @@ -0,0 +1,9 @@ +# Copyright 2010 Google Inc. All Rights Reserved. +#Fri Jul 16 10:03:09 PDT 2010 +currentVersion=Unknown +version=3.6.10.14? +isNative=true +name=sonivox +keywords=sonivox +onDevice=true +homepage=http\://source.android.com/ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/Makefile b/code/embeddedaudiosynthesis/arm-fm-22k/Makefile new file mode 100755 index 0000000..8b76c55 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/Makefile @@ -0,0 +1,63 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES = \ + lib_src/eas_chorus.c \ + lib_src/eas_chorusdata.c \ + lib_src/eas_data.c \ + lib_src/eas_fmengine.c \ + lib_src/eas_fmsndlib.c \ + lib_src/eas_fmsynth.c \ + lib_src/eas_fmtables.c \ + lib_src/eas_ima_tables.c \ + lib_src/eas_imaadpcm.c \ + lib_src/eas_imelody.c \ + lib_src/eas_imelodydata.c \ + lib_src/eas_math.c \ + lib_src/eas_midi.c \ + lib_src/eas_mididata.c \ + lib_src/eas_mixbuf.c \ + lib_src/eas_mixer.c \ + lib_src/eas_ota.c \ + lib_src/eas_otadata.c \ + lib_src/eas_pan.c \ + lib_src/eas_pcm.c \ + lib_src/eas_pcmdata.c \ + lib_src/eas_public.c \ + lib_src/eas_reverb.c \ + lib_src/eas_reverbdata.c \ + lib_src/eas_rtttl.c \ + lib_src/eas_rtttldata.c \ + lib_src/eas_smf.c \ + lib_src/eas_smfdata.c \ + lib_src/eas_voicemgt.c \ + lib_src/eas_wavefile.c \ + lib_src/eas_wavefiledata.c \ + host_src/eas_config.c \ + host_src/eas_hostmm.c \ + host_src/eas_main.c \ + host_src/eas_report.c \ + host_src/eas_wave.c + +LOCAL_CFLAGS+= -O2 -D NUM_OUTPUT_CHANNELS=2 \ + -D _SAMPLE_RATE_22050 -D EAS_FM_SYNTH \ + -D MAX_SYNTH_VOICES=16 -D _IMELODY_PARSER \ + -D _RTTTL_PARSER -D _OTA_PARSER \ + -D _WAVE_PARSER -D _REVERB_ENABLED \ + -D _CHORUS_ENABLED -D _IMA_DECODER \ + -D UNIFIED_DEBUG_MESSAGES + +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH)/host_src/ \ + $(LOCAL_PATH)/lib_src/ + +LOCAL_ARM_MODE := arm + +LOCAL_MODULE := libsonivox + +LOCAL_COPY_HEADERS_TO := libsonivox +LOCAL_COPY_HEADERS := \ + host_src/eas.h \ + host_src/eas_types.h + +include $(BUILD_SHARED_LIBRARY) diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/bin/arm-fm-22k b/code/embeddedaudiosynthesis/arm-fm-22k/bin/arm-fm-22k new file mode 100755 index 0000000..50ba4ba Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-fm-22k/bin/arm-fm-22k differ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/arm-fm-22k.mak b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/arm-fm-22k.mak new file mode 100755 index 0000000..da12d71 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/arm-fm-22k.mak @@ -0,0 +1,25 @@ +# +# Auto-generated sample makefile +# +# This makefile is intended for use with GNU make. +# Set the paths to the tools (CC, AR, LD, etc.) +# + +vpath %.c host_src + +CC = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AS = C:\Program Files\GNUARM\bin\arm-elf-as.exe +LD = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AR = C:\Program Files\GNUARM\bin\arm-elf-ar.exe + +%.o: %.c + $(CC) -c -O2 -o $@ -I host_src -D UNIFIED_DEBUG_MESSAGES -D EAS_FM_SYNTH -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED $< + +%.o: %.s + $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa $< + +OBJS = eas_main.o eas_report.o eas_wave.o eas_hostmm.o eas_config.o + +arm-fm-22k: $(OBJS) + $(LD) -o $@ $(OBJS) libarm-fm-22k.a -lm + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas.h new file mode 100755 index 0000000..c64af49 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas.h @@ -0,0 +1,1062 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas.h + * + * Contents and purpose: + * The public interface header for the EAS synthesizer. + * + * This header only contains declarations that are specific + * to this implementation. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2005, 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 852 $ + * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_H +#define _EAS_H + +#include "eas_types.h" + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +/* library version macro */ +#define MAKE_LIB_VERSION(a,b,c,d) (((((((EAS_U32) a <<8) | (EAS_U32) b) << 8) | (EAS_U32) c) << 8) | (EAS_U32) d) +#define LIB_VERSION MAKE_LIB_VERSION(3, 6, 10, 14) + +typedef struct +{ + EAS_U32 libVersion; + EAS_BOOL checkedVersion; + EAS_I32 maxVoices; + EAS_I32 numChannels; + EAS_I32 sampleRate; + EAS_I32 mixBufferSize; + EAS_BOOL filterEnabled; + EAS_U32 buildTimeStamp; + EAS_CHAR *buildGUID; +} S_EAS_LIB_CONFIG; + +/* enumerated effects module numbers for configuration */ +typedef enum +{ + EAS_MODULE_ENHANCER = 0, + EAS_MODULE_COMPRESSOR, + EAS_MODULE_REVERB, + EAS_MODULE_CHORUS, + EAS_MODULE_WIDENER, + EAS_MODULE_GRAPHIC_EQ, + EAS_MODULE_WOW, + EAS_MODULE_MAXIMIZER, + EAS_MODULE_TONECONTROLEQ, + NUM_EFFECTS_MODULES +} E_FX_MODULES; + +/* enumerated optional module numbers for configuration */ +typedef enum +{ + EAS_MODULE_MMAPI_TONE_CONTROL = 0, + EAS_MODULE_METRICS +} E_OPT_MODULES; +#define NUM_OPTIONAL_MODULES 2 + +/* enumerated audio decoders for configuration */ +typedef enum +{ + EAS_DECODER_PCM = 0, + EAS_DECODER_SMAF_ADPCM, + EAS_DECODER_IMA_ADPCM, + EAS_DECODER_7BIT_SMAF_ADPCM, + EAS_DECODER_NOT_SUPPORTED +} E_DECODER_MODULES; +#define NUM_DECODER_MODULES 4 + +/* defines for EAS_PEOpenStream flags parameter */ +#define PCM_FLAGS_STEREO 0x00000100 /* stream is stereo */ +#define PCM_FLAGS_8_BIT 0x00000001 /* 8-bit format */ +#define PCM_FLAGS_UNSIGNED 0x00000010 /* unsigned format */ +#define PCM_FLAGS_STREAMING 0x80000000 /* streaming mode */ + +/* maximum volume setting */ +#define EAS_MAX_VOLUME 100 + +/*---------------------------------------------------------------------------- + * EAS_Init() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the synthesizer library + * + * Inputs: + * polyphony - number of voices to play (dynamic memory model only) + * ppLibData - pointer to data handle variable for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData); + +/*---------------------------------------------------------------------------- + * EAS_Config() + *---------------------------------------------------------------------------- + * Purpose: + * Returns a pointer to a structure containing the configuration options + * in this library build. + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void); + +/*---------------------------------------------------------------------------- + * EAS_Shutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the library. Deallocates any memory associated with the + * synthesizer (dynamic memory model only) + * + * Inputs: + * pEASData - handle to data for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_Render() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the Midi data and render PCM audio data. + * + * Inputs: + * pEASData - buffer for internal EAS data + * pOut - output buffer pointer + * nNumRequested - requested num samples to generate + * pnNumGenerated - actual number of samples generated + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated); + +/*---------------------------------------------------------------------------- + * EAS_SetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Set the selected stream to repeat. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * repeatCount - repeat count (0 = no repeat, -1 = repeat forever) + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 repeatCount); + +/*---------------------------------------------------------------------------- + * EAS_GetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the current repeat count for the selected stream. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * pRrepeatCount - pointer to variable to hold repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pRepeatCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPlaybackRate() + *---------------------------------------------------------------------------- + * Purpose: + * Set the playback rate. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U32 rate); +#define MAX_PLAYBACK_RATE (EAS_U32)(1L << 29) +#define MIN_PLAYBACK_RATE (EAS_U32)(1L << 27) + +/*---------------------------------------------------------------------------- + * EAS_SetTransposition) + *---------------------------------------------------------------------------- + * Purpose: + * Sets the key tranposition for the synthesizer. Transposes all + * melodic instruments by the specified amount. Range is limited + * to +/-12 semitones. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * transposition - +/-12 semitones + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 transposition); +#define MAX_TRANSPOSE 12 + +/*---------------------------------------------------------------------------- + * EAS_SetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the synthesizer. Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_GetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the stream. Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_GetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the priority of the stream. Determines which stream's voices + * are stolen when there are insufficient voices for all notes. + * Value must be in the range of 1-255, lower values are higher + * priority. The default priority is 50. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 priority); + +/*---------------------------------------------------------------------------- + * EAS_GetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current priority setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPriority - pointer to variable to receive priority + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPriority); + +/*---------------------------------------------------------------------------- + * EAS_SetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for the mixer. The default volume setting is + * 90 (-10 dB). The volume range is 0 to 100 in 1dB increments. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 volume); + +/*---------------------------------------------------------------------------- + * EAS_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the master volume for the mixer in 1dB increments. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_SetMaxLoad() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the maximum workload the parsers will do in a single call to + * EAS_Render. The units are currently arbitrary, but should correlate + * well to the actual CPU cycles consumed. The primary effect is to + * reduce the occasional peaks in CPU cycles consumed when parsing + * dense parts of a MIDI score. Setting maxWorkLoad to zero disables + * the workload limiting function. + * + * Inputs: + * pEASData - handle to data for this instance + * maxLoad - the desired maximum workload + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad); + +/*---------------------------------------------------------------------------- + * EAS_SetMaxPCMStreams() + *---------------------------------------------------------------------------- + * Sets the maximum number of PCM streams allowed in parsers that + * use PCM streaming. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * maxNumStreams - maximum number of PCM streams + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams); + +/*---------------------------------------------------------------------------- + * EAS_OpenFile() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * locator - pointer to filename or other locating information + * pStreamHandle - pointer to stream handle variable + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle); + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * EAS_MMAPIToneControl() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a ToneControl file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * locator - pointer to filename or other locating information + * pStreamHandle - pointer to stream handle variable + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle); + +/*---------------------------------------------------------------------------- + * EAS_GetWaveFmtChunk + *---------------------------------------------------------------------------- + * Helper function to retrieve WAVE file fmt chunk for MMAPI + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * streamHandle - stream handle + * pFmtChunk - pointer to pointer to FMT chunk data + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_VOID_PTR *ppFmtChunk); +#endif + +/*---------------------------------------------------------------------------- + * EAS_GetFileType + *---------------------------------------------------------------------------- + * Returns the file type (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * streamHandle - stream handle + * pFileType - pointer to variable to receive file type + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetFileType (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pFileType); + +/*---------------------------------------------------------------------------- + * EAS_ParseMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * playLength - pointer to variable to store the play length (in msecs) + * + * Outputs: + * + * + * Side Effects: + * - resets the parser to the start of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPlayLength); + +/*---------------------------------------------------------------------------- + * EAS_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the synthesizer to play the file or stream. Parses the first + * frame of data from the file and arms the synthesizer. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the state of an audio file or stream. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_RegisterMetaDataCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers a metadata callback function for parsed metadata. To + * de-register the callback, call this function again with parameter + * cbFunc set to NULL. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * cbFunc - pointer to host callback function + * metaDataBuffer - pointer to metadata buffer + * metaDataBufSize - maximum size of the metadata buffer + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( + EAS_DATA_HANDLE pEASData, + EAS_HANDLE streamHandle, + EAS_METADATA_CBFUNC cbFunc, + char *metaDataBuffer, + EAS_I32 metaDataBufSize, + EAS_VOID_PTR pUserData); + +/*---------------------------------------------------------------------------- + * EAS_GetNoteCount () + *---------------------------------------------------------------------------- + * Returns the total number of notes played in this stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * pNoteCount - pointer to variable to receive note count + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount); + +/*---------------------------------------------------------------------------- + * EAS_CloseFile() + *---------------------------------------------------------------------------- + * Purpose: + * Closes an audio file or stream. Playback should have either paused or + * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_OpenMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pStreamHandle - pointer to variable to hold file or stream handle + * streamHandle - open stream or NULL for new synthesizer instance + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *pStreamHandle, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_WriteMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Send data to the MIDI stream device + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - stream handle + * pBuffer - pointer to buffer + * count - number of bytes to write + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream(EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 *pBuffer, EAS_I32 count); + +/*---------------------------------------------------------------------------- + * EAS_CloseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Closes a raw MIDI stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_Locate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate into the file associated with the handle. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file handle + * milliseconds - playback offset from start of file in milliseconds + * + * Outputs: + * + * + * Side Effects: + * the actual offset will be quantized to the closest update period, typically + * a resolution of 5.9ms. Notes that are started prior to this time will not + * sound. Any notes currently playing will be shut off. + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 milliseconds, EAS_BOOL offset); + +/*---------------------------------------------------------------------------- + * EAS_GetRenderTime() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * Gets the render time clock in msecs. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime); + +/*---------------------------------------------------------------------------- + * EAS_GetLocation() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file handle + * + * Outputs: + * The offset in milliseconds from the start of the current sequence, quantized + * to the nearest update period. Actual resolution is typically 5.9 ms. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pTime); + +/*---------------------------------------------------------------------------- + * EAS_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the playback of the data associated with this handle. The audio + * is gracefully ramped down to prevent clicks and pops. It may take several + * buffers of audio before the audio is muted. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resumes the playback of the data associated with this handle. The audio + * is gracefully ramped up to prevent clicks and pops. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_GetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * module - enumerated module number + * param - enumerated parameter number + * pValue - pointer to variable to receive parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue); + +/*---------------------------------------------------------------------------- + * EAS_SetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * value - new parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value); + +#ifdef _METRICS_ENABLED +/*---------------------------------------------------------------------------- + * EAS_MetricsReport() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the EAS_Report interface. + * + * Inputs: + * pEASData - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_MetricsReset() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the EAS_Report interface. + * + * Inputs: + * pEASData - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetSoundLibrary() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * streamHandle - file or stream handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_SNDLIB_HANDLE pSndLib); + +/*---------------------------------------------------------------------------- + * EAS_SetHeaderSearchFlag() + *---------------------------------------------------------------------------- + * By default, when EAS_OpenFile is called, the parsers check the + * first few bytes of the file looking for a specific header. Some + * mobile devices may add a header to the start of a file, which + * will prevent the parser from recognizing the file. If the + * searchFlag is set to EAS_TRUE, the parser will search the entire + * file looking for the header. This may enable EAS to recognize + * some files that it would ordinarily reject. The negative is that + * it make take slightly longer to process the EAS_OpenFile request. + * + * Inputs: + * pEASData - instance data handle + * searchFlag - search flag (EAS_TRUE or EAS_FALSE) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag); + +/*---------------------------------------------------------------------------- + * EAS_SetPlayMode() + *---------------------------------------------------------------------------- + * Some file formats support special play modes, such as iMode partial + * play mode. This call can be used to change the play mode. The + * default play mode (usually straight playback) is always zero. + * + * Inputs: + * pEASData - instance data handle + * handle - file or stream handle + * playMode - play mode (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode); + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * EAS_LoadDLSCollection() + *---------------------------------------------------------------------------- + * Purpose: + * Downloads a DLS collection + * + * Inputs: + * pEASData - instance data handle + * streamHandle - file or stream handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_FILE_LOCATOR locator); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetFrameBuffer() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the frame buffer pointer passed to the IPC communications functions + * + * Inputs: + * pEASData - instance data handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers callback functions for audio events. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * cbProgChgFunc - pointer to host callback function for program change + * cbEventFunc - pointer to host callback functio for note events + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, + EAS_HANDLE streamHandle, + EAS_VOID_PTR pInstData, + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, + EAS_EXT_EVENT_FUNC cbEventFunc); + +/*---------------------------------------------------------------------------- + * EAS_GetMIDIControllers() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of MIDI controllers on the requested channel. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * pControl - pointer to structure to receive data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SearchFile + *---------------------------------------------------------------------------- + * Search file for specific sequence starting at current file + * position. Returns offset to start of sequence. + * + * Inputs: + * pEASData - pointer to EAS persistent data object + * fileHandle - file handle + * searchString - pointer to search sequence + * len - length of search sequence + * pOffset - pointer to variable to store offset to sequence + * + * Returns EAS_EOF if end-of-file is reached + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SearchFile (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* #ifndef _EAS_H */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_build.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_build.h new file mode 100755 index 0000000..5b058e7 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_build.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------- + * + * File: + * host_src\eas_build.h + * + * Contents and purpose: + * This file contains the build configuration for this + * build. The buildGUIDStr is a GUID created during + * the build process and is guaranteed to be unique + * for each build. + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file was autogenerated by buildid.exe + *---------------------------------------------------------------------------- +*/ + +#ifndef _GUID_53c2509edf8f42e3975a054126c0cc1b_ +#define _GUID_53c2509edf8f42e3975a054126c0cc1b_ + +#define _BUILD_VERSION_ "53c2509e-df8f-42e3-975a-054126c0cc1b" +#define _BUILD_TIME_ 0x4743b8c9 + +#endif /* _GUID_53c2509edf8f42e3975a054126c0cc1b_ */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_chorus.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_chorus.h new file mode 100755 index 0000000..998a828 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_chorus.h @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorus.h + * + * Contents and purpose: + * Contains parameter enumerations for the Chorus effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 309 $ + * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_CHORUS_H +#define EAS_CHORUS_H + +/* enumerated parameter settings for Chorus effect */ +typedef enum +{ + EAS_PARAM_CHORUS_BYPASS, + EAS_PARAM_CHORUS_PRESET, + EAS_PARAM_CHORUS_RATE, + EAS_PARAM_CHORUS_DEPTH, + EAS_PARAM_CHORUS_LEVEL +} E_CHORUS_PARAMS; + +typedef enum +{ + EAS_PARAM_CHORUS_PRESET1, + EAS_PARAM_CHORUS_PRESET2, + EAS_PARAM_CHORUS_PRESET3, + EAS_PARAM_CHORUS_PRESET4 +} E_CHORUS_PRESETS; + + +#endif \ No newline at end of file diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_config.c b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_config.c new file mode 100755 index 0000000..0b92357 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_config.c @@ -0,0 +1,619 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_config.c + * + * Contents and purpose: + * This file contains the Configuration Module interface (CM). The CM + * is a module compiled external to the library that sets the configuration + * for this build. It allows the library to find optional components and + * links to static memory allocations (when used in a static configuration). + * + * DO NOT MODIFY THIS FILE! + * + * NOTE: This module is not intended to be modified by the customer. It + * needs to be included in the build process with the correct configuration + * defines (see the library documentation for information on how to configure + * the library). + * + * Copyright Sonic Network Inc. 2004-2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 796 $ + * $Date: 2007-08-01 00:15:25 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas.h" +#include "eas_config.h" + + +#ifdef _MFI_PARSER +/*---------------------------------------------------------------------------- + * Vendor/Device ID for MFi Extensions + * + * Define the preprocessor symbols to establish the vendor ID and + * device ID for the MFi PCM/ADPCM extensions. + *---------------------------------------------------------------------------- +*/ +const EAS_U8 eas_MFIVendorIDMSB = (MFI_VENDOR_ID >> 8) & 0xff; +const EAS_U8 eas_MFIVendorIDLSB = MFI_VENDOR_ID & 0xff; +const EAS_U8 eas_MFIDeviceID = MFI_DEVICE_ID; +#endif + +/*---------------------------------------------------------------------------- + * + * parserModules + * + * This structure is used by the EAS library to locate file parsing + * modules. + *---------------------------------------------------------------------------- +*/ + +/* define the external file parsers */ +extern EAS_VOID_PTR EAS_SMF_Parser; + +#ifdef _XMF_PARSER +extern EAS_VOID_PTR EAS_XMF_Parser; +#endif + +#ifdef _SMAF_PARSER +extern EAS_VOID_PTR EAS_SMAF_Parser; +#endif + +#ifdef _WAVE_PARSER +extern EAS_VOID_PTR EAS_Wave_Parser; +#endif + +#ifdef _OTA_PARSER +extern EAS_VOID_PTR EAS_OTA_Parser; +#endif + +#ifdef _IMELODY_PARSER +extern EAS_VOID_PTR EAS_iMelody_Parser; +#endif + +#ifdef _RTTTL_PARSER +extern EAS_VOID_PTR EAS_RTTTL_Parser; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) +extern EAS_VOID_PTR EAS_CMF_Parser; +#endif + +/* initalize pointers to parser interfaces */ +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const parserModules[] = +{ + &EAS_SMF_Parser, + +#ifdef _XMF_PARSER + &EAS_XMF_Parser, +#endif + +#ifdef _WAVE_PARSER + &EAS_Wave_Parser, +#endif + +#ifdef _SMAF_PARSER + &EAS_SMAF_Parser, +#endif + +#ifdef _OTA_PARSER + &EAS_OTA_Parser, +#endif + +#ifdef _IMELODY_PARSER + &EAS_iMelody_Parser, +#endif + +#ifdef _RTTTL_PARSER + &EAS_RTTTL_Parser, +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) + &EAS_CMF_Parser +#endif +}; +#define NUM_PARSER_MODULES (sizeof(parserModules) / sizeof(EAS_VOID_PTR)) + +/*---------------------------------------------------------------------------- + * Data Modules + *---------------------------------------------------------------------------- +*/ + +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_SMFData; +extern EAS_VOID_PTR eas_Data; +extern EAS_VOID_PTR eas_MixBuffer; +extern EAS_VOID_PTR eas_Synth; +extern EAS_VOID_PTR eas_MIDI; +extern EAS_VOID_PTR eas_PCMData; +extern EAS_VOID_PTR eas_MIDIData; + +#ifdef _XMF_PARSER +extern EAS_VOID_PTR eas_XMFData; +#endif + +#ifdef _SMAF_PARSER +extern EAS_VOID_PTR eas_SMAFData; +#endif + +#ifdef _OTA_PARSER +extern EAS_VOID_PTR eas_OTAData; +#endif + +#ifdef _IMELODY_PARSER +extern EAS_VOID_PTR eas_iMelodyData; +#endif + +#ifdef _RTTTL_PARSER +extern EAS_VOID_PTR eas_RTTTLData; +#endif + +#ifdef _WAVE_PARSER +extern EAS_VOID_PTR eas_WaveData; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) +extern EAS_VOID_PTR eas_CMFData; +#endif +#endif + +/*---------------------------------------------------------------------------- + * + * Effects Modules + * + * These declarations are used by the EAS library to locate + * effects modules. + *---------------------------------------------------------------------------- +*/ + +#ifdef _ENHANCER_ENABLED +extern EAS_VOID_PTR EAS_Enhancer; +#define EAS_ENHANCER_INTERFACE &EAS_Enhancer +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_EnhancerData; +#define EAS_ENHANCER_DATA &eas_EnhancerData +#else +#define EAS_ENHANCER_DATA NULL +#endif +#else +#define EAS_ENHANCER_INTERFACE NULL +#define EAS_ENHANCER_DATA NULL +#endif + +#ifdef _COMPRESSOR_ENABLED +extern EAS_VOID_PTR EAS_Compressor; +#define EAS_COMPRESSOR_INTERFACE &EAS_Compressor +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_CompressorData; +#define EAS_COMPRESSOR_DATA &eas_CompressorData +#else +#define EAS_COMPRESSOR_DATA NULL +#endif +#else +#define EAS_COMPRESSOR_INTERFACE NULL +#define EAS_COMPRESSOR_DATA NULL +#endif + +#ifdef _MAXIMIZER_ENABLED +extern EAS_VOID_PTR EAS_Maximizer; +#define EAS_MAXIMIZER_INTERFACE &EAS_Maximizer +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_MaximizerData; +#define EAS_MAXIMIZER_DATA &eas_MaximizerData +#else +#define EAS_MAXIMIZER_DATA NULL +#endif +#else +#define EAS_MAXIMIZER_INTERFACE NULL +#define EAS_MAXIMIZER_DATA NULL +#endif + + +#ifdef _REVERB_ENABLED +extern EAS_VOID_PTR EAS_Reverb; +#define EAS_REVERB_INTERFACE &EAS_Reverb +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ReverbData; +#define EAS_REVERB_DATA &eas_ReverbData +#else +#define EAS_REVERB_DATA NULL +#endif +#else +#define EAS_REVERB_INTERFACE NULL +#define EAS_REVERB_DATA NULL +#endif + +#ifdef _CHORUS_ENABLED +extern EAS_VOID_PTR EAS_Chorus; +#define EAS_CHORUS_INTERFACE &EAS_Chorus +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ChorusData; +#define EAS_CHORUS_DATA &eas_ChorusData +#else +#define EAS_CHORUS_DATA NULL +#endif +#else +#define EAS_CHORUS_INTERFACE NULL +#define EAS_CHORUS_DATA NULL +#endif + +#ifdef _WIDENER_ENABLED +extern EAS_VOID_PTR EAS_Widener; +#define EAS_WIDENER_INTERFACE &EAS_Widener +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_WidenerData; +#define EAS_WIDENER_DATA &eas_WidenerData +#else +#define EAS_WIDENER_DATA NULL +#endif +#else +#define EAS_WIDENER_INTERFACE NULL +#define EAS_WIDENER_DATA NULL +#endif + +#ifdef _GRAPHIC_EQ_ENABLED +extern EAS_VOID_PTR EAS_GraphicEQ; +#define EAS_GRAPHIC_EQ_INTERFACE &EAS_GraphicEQ +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_GraphicEQData; +#define EAS_GRAPHIC_EQ_DATA &eas_GraphicEQData +#else +#define EAS_GRAPHIC_EQ_DATA NULL +#endif +#else +#define EAS_GRAPHIC_EQ_INTERFACE NULL +#define EAS_GRAPHIC_EQ_DATA NULL +#endif + +#ifdef _WOW_ENABLED +extern EAS_VOID_PTR EAS_Wow; +#define EAS_WOW_INTERFACE &EAS_Wow +#ifdef _STATIC_MEMORY +#error "WOW module requires dynamic memory model" +#else +#define EAS_WOW_DATA NULL +#endif +#else +#define EAS_WOW_INTERFACE NULL +#define EAS_WOW_DATA NULL +#endif + +#ifdef _TONECONTROLEQ_ENABLED +extern EAS_VOID_PTR EAS_ToneControlEQ; +#define EAS_TONECONTROLEQ_INTERFACE &EAS_ToneControlEQ +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ToneControlEQData; +#define EAS_TONECONTROLEQ_DATA &eas_ToneControlEQData +#else +#define EAS_TONECONTROLEQ_DATA NULL +#endif +#else +#define EAS_TONECONTROLEQ_INTERFACE NULL +#define EAS_TONECONTROLEQ_DATA NULL +#endif + +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const effectsModules[] = +{ + EAS_ENHANCER_INTERFACE, + EAS_COMPRESSOR_INTERFACE, + EAS_REVERB_INTERFACE, + EAS_CHORUS_INTERFACE, + EAS_WIDENER_INTERFACE, + EAS_GRAPHIC_EQ_INTERFACE, + EAS_WOW_INTERFACE, + EAS_MAXIMIZER_INTERFACE, + EAS_TONECONTROLEQ_INTERFACE +}; + +EAS_VOID_PTR const effectsData[] = +{ + EAS_ENHANCER_DATA, + EAS_COMPRESSOR_DATA, + EAS_REVERB_DATA, + EAS_CHORUS_DATA, + EAS_WIDENER_DATA, + EAS_GRAPHIC_EQ_DATA, + EAS_WOW_DATA, + EAS_MAXIMIZER_DATA, + EAS_TONECONTROLEQ_DATA +}; + +/*---------------------------------------------------------------------------- + * + * Optional Modules + * + * These declarations are used by the EAS library to locate + * effects modules. + *---------------------------------------------------------------------------- +*/ + +#ifdef _METRICS_ENABLED +extern EAS_VOID_PTR EAS_Metrics; +#define EAS_METRICS_INTERFACE &EAS_Metrics +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_MetricsData; +#define EAS_METRICS_DATA &eas_MetricsData +#else +#define EAS_METRICS_DATA NULL +#endif +#else +#define EAS_METRICS_INTERFACE NULL +#define EAS_METRICS_DATA NULL +#endif + +#ifdef MMAPI_SUPPORT +extern EAS_VOID_PTR EAS_TC_Parser; +#define EAS_TONE_CONTROL_PARSER &EAS_TC_Parser +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_TCData; +#define EAS_TONE_CONTROL_DATA &eas_TCData +#else +#define EAS_TONE_CONTROL_DATA NULL +#endif +#else +#define EAS_TONE_CONTROL_PARSER NULL +#define EAS_TONE_CONTROL_DATA NULL +#endif + +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const optionalModules[] = +{ + EAS_TONE_CONTROL_PARSER, + EAS_METRICS_INTERFACE +}; + +EAS_VOID_PTR const optionalData[] = +{ + EAS_TONE_CONTROL_DATA, + EAS_METRICS_DATA +}; + +/*---------------------------------------------------------------------------- + * EAS_CMStaticMemoryModel() + *---------------------------------------------------------------------------- + * Purpose: + * This function returns true if EAS has been configured for + * a static memory model. There are some limitations in the + * static memory model, see the documentation for more + * information. + * + * Outputs: + * returns EAS_TRUE if a module is found + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_CMStaticMemoryModel (void) +{ +#ifdef _STATIC_MEMORY + return EAS_TRUE; +#else + return EAS_FALSE; +#endif +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - module number + * + * Outputs: + * returns a pointer to the module function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module) +{ + + if (module >= (EAS_INT) NUM_PARSER_MODULES) + return NULL; + return parserModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, dataModule) used only when _STATIC_MEMORY is defined */ +EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule) +{ + +#ifdef _STATIC_MEMORY + switch (dataModule) + { + + /* main instance data for synthesizer */ + case EAS_CM_EAS_DATA: + return &eas_Data; + + /* mix buffer for mix engine */ + case EAS_CM_MIX_BUFFER: + /*lint -e{545} lint doesn't like this because it sees the underlying type */ + return &eas_MixBuffer; + + /* instance data for synth */ + case EAS_CM_SYNTH_DATA: + return &eas_Synth; + + /* instance data for MIDI parser */ + case EAS_CM_MIDI_DATA: + return &eas_MIDI; + + /* instance data for SMF parser */ + case EAS_CM_SMF_DATA: + return &eas_SMFData; + +#ifdef _XMF_PARSER + /* instance data for XMF parser */ + case EAS_CM_XMF_DATA: + return &eas_XMFData; +#endif + +#ifdef _SMAF_PARSER + /* instance data for SMAF parser */ + case EAS_CM_SMAF_DATA: + return &eas_SMAFData; +#endif + + /* instance data for the PCM engine */ + case EAS_CM_PCM_DATA: + /*lint -e{545} lint doesn't like this because it sees the underlying type */ + return &eas_PCMData; + + case EAS_CM_MIDI_STREAM_DATA: + return &eas_MIDIData; + +#ifdef _OTA_PARSER + /* instance data for OTA parser */ + case EAS_CM_OTA_DATA: + return &eas_OTAData; +#endif + +#ifdef _IMELODY_PARSER + /* instance data for iMelody parser */ + case EAS_CM_IMELODY_DATA: + return &eas_iMelodyData; +#endif + +#ifdef _RTTTL_PARSER + /* instance data for RTTTL parser */ + case EAS_CM_RTTTL_DATA: + return &eas_RTTTLData; +#endif + +#ifdef _WAVE_PARSER + /* instance data for WAVE parser */ + case EAS_CM_WAVE_DATA: + return &eas_WaveData; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) + /* instance data for CMF parser */ + case EAS_CM_CMF_DATA: + return &eas_CMFData; +#endif + + default: + return NULL; + } + +#else + return NULL; +#endif +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional effects modules. + * + * Inputs: + * module - enumerated module number + * pModule - pointer to module interface + * + * Outputs: + * Returns pointer to function table or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module) +{ + + if (module >= NUM_EFFECTS_MODULES) + return NULL; + return effectsModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * pData - pointer to handle variable + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule) +{ + + if (dataModule >= NUM_EFFECTS_MODULES) + return NULL; + return effectsData[dataModule]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - enumerated module number + * + * Outputs: + * returns pointer to function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module) +{ + + /* sanity check */ + if (module >= NUM_OPTIONAL_MODULES) + return EAS_FALSE; + return optionalModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule) +{ + + if (dataModule >= NUM_OPTIONAL_MODULES) + return NULL; + return optionalData[dataModule]; +} + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_config.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_config.h new file mode 100755 index 0000000..49c2ef2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_config.h @@ -0,0 +1,191 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_config.h + * + * Contents and purpose: + * This header declares the Configuration Module interface (CM). The CM + * is a module compiled external to the library that sets the configuration + * for this build. It allows the library to find optional components and + * links to static memory allocations (when used in a static configuration). + * + * NOTE: This module is not intended to be modified by the customer. It + * needs to be included in the build process with the correct configuration + * defines (see the library documentation for information on how to configure + * the library). + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// sentinel +#ifndef _EAS_CONFIG_H +#define _EAS_CONFIG_H + +#include "eas_types.h" + +/* list of enumerators for optional modules */ +typedef enum { + EAS_CM_FILE_PARSERS = 1 +} E_CM_ENUM_MODULES; + +/* list of enumerators for module and memory pointers */ +typedef enum { + EAS_CM_EAS_DATA = 1, + EAS_CM_MIX_BUFFER, + EAS_CM_SYNTH_DATA, + EAS_CM_MIDI_DATA, + EAS_CM_SMF_DATA, + EAS_CM_XMF_DATA, + EAS_CM_SMAF_DATA, + EAS_CM_PCM_DATA, + EAS_CM_MIDI_STREAM_DATA, + EAS_CM_METRICS_DATA, + EAS_CM_OTA_DATA, + EAS_CM_IMELODY_DATA, + EAS_CM_RTTTL_DATA, + EAS_CM_WAVE_DATA, + EAS_CM_CMF_DATA +} E_CM_DATA_MODULES; + +typedef struct +{ + int maxSMFStreams; + void *pSMFData; + void *pSMFStream; +} S_EAS_SMF_PTRS; + +typedef struct +{ + int maxSMAFStreams; + void *pSMAFData; + void *pSMAFStream; +} S_EAS_SMAF_PTRS; + +/*---------------------------------------------------------------------------- + * EAS_CMStaticMemoryModel() + *---------------------------------------------------------------------------- + * Purpose: + * This function returns true if EAS has been configured for + * a static memory model. There are some limitations in the + * static memory model, see the documentation for more + * information. + * + * Outputs: + * returns EAS_TRUE if a module is found + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_CMStaticMemoryModel (void); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - module number + * + * Outputs: + * returns a pointer to the module function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional effects modules. + * + * Inputs: + * module - enumerated module number + * pModule - pointer to module interface + * + * Outputs: + * Returns pointer to function table or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * pData - pointer to handle variable + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - enumerated module number + * + * Outputs: + * returns pointer to function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule); + +#endif /* end _EAS_CONFIG_H */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_debugmsgs.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_debugmsgs.h new file mode 100755 index 0000000..de60259 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_debugmsgs.h @@ -0,0 +1,43 @@ +/* Auto-generated from source file: eas_chorusdata.c */ +/* Auto-generated from source file: eas_imelodydata.c */ +/* Auto-generated from source file: eas_mididata.c */ +/* Auto-generated from source file: eas_pan.c */ +/* Auto-generated from source file: eas_wavefiledata.c */ +/* Auto-generated from source file: eas_voicemgt.c */ +/* Auto-generated from source file: eas_ota.c */ +/* Auto-generated from source file: eas_mixbuf.c */ +/* Auto-generated from source file: eas_fmsndlib.c */ +/* Auto-generated from source file: eas_rtttl.c */ +/* Auto-generated from source file: eas_reverb.c */ +/* Auto-generated from source file: eas_fmsynth.c */ +/* Auto-generated from source file: eas_pcmdata.c */ +/* Auto-generated from source file: eas_chorus.c */ +/* Auto-generated from source file: eas_math.c */ +/* Auto-generated from source file: eas_fmengine.c */ +/* Auto-generated from source file: eas_smfdata.c */ +/* Auto-generated from source file: eas_fmtables.c */ +/* Auto-generated from source file: eas_imelody.c */ +/* Auto-generated from source file: eas_public.c */ +/* Auto-generated from source file: eas_rtttldata.c */ +/* Auto-generated from source file: eas_reverbdata.c */ +/* Auto-generated from source file: eas_imaadpcm.c */ +{ 0x2380b977, 0x00000006, "eas_imaadpcm.c[305]: IMADecoderLocate: Time=%d, samples=%d\n" }, +{ 0x2380b977, 0x00000007, "eas_imaadpcm.c[328]: IMADecoderLocate: Looped sample, numBlocks=%d, samplesPerLoop=%d, samplesInLastBlock=%d, samples=%d\n" }, +{ 0x2380b977, 0x00000008, "eas_imaadpcm.c[335]: IMADecoderLocate: Byte location in audio = %d\n" }, +{ 0x2380b977, 0x00000009, "eas_imaadpcm.c[345]: IMADecoderLocate: bytesLeft = %d\n" }, +/* Auto-generated from source file: eas_midi.c */ +/* Auto-generated from source file: eas_otadata.c */ +/* Auto-generated from source file: eas_ima_tables.c */ +/* Auto-generated from source file: eas_data.c */ +/* Auto-generated from source file: eas_pcm.c */ +/* Auto-generated from source file: eas_mixer.c */ +/* Auto-generated from source file: eas_wavefile.c */ +/* Auto-generated from source file: eas_smf.c */ +/* Auto-generated from source file: eas_wave.c */ +/* Auto-generated from source file: eas_hostmm.c */ +{ 0x1a54b6e8, 0x00000001, "eas_hostmm.c[586]: Vibrate state: %d\n" }, +{ 0x1a54b6e8, 0x00000002, "eas_hostmm.c[601]: LED state: %d\n" }, +{ 0x1a54b6e8, 0x00000003, "eas_hostmm.c[616]: Backlight state: %d\n" }, +/* Auto-generated from source file: eas_config.c */ +/* Auto-generated from source file: eas_main.c */ +{ 0xe624f4d9, 0x00000005, "eas_main.c[106]: Play length: %d.%03d (secs)\n" }, diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_host.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_host.h new file mode 100755 index 0000000..b356982 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_host.h @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_host.h + * + * Contents and purpose: + * This header defines the host wrapper functions for stdio, stdlib, etc. + * The host application must provide an abstraction layer for these functions + * to support certain features, such as SMAF and SMF-1 conversion. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// sentinel +#ifndef _EAS_HOST_H +#define _EAS_HOST_H + +#include "eas_types.h" + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +/* initialization and shutdown routines */ +extern EAS_RESULT EAS_HWInit(EAS_HW_DATA_HANDLE *hwInstData); +extern EAS_RESULT EAS_HWShutdown(EAS_HW_DATA_HANDLE hwInstData); + +/* memory functions */ +extern void *EAS_HWMemSet(void *s, int c, EAS_I32 n); +extern void *EAS_HWMemCpy(void *s1, const void *s2, EAS_I32 n); +extern EAS_I32 EAS_HWMemCmp(const void *s1, const void *s2, EAS_I32 n); + +/* memory allocation */ +extern void *EAS_HWMalloc(EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size); +extern void EAS_HWFree(EAS_HW_DATA_HANDLE hwInstData, void *p); + +/* file I/O */ +extern EAS_RESULT EAS_HWOpenFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode); +extern EAS_RESULT EAS_HWReadFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead); +extern EAS_RESULT EAS_HWGetByte(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p); +extern EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst); +extern EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst); +extern EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition); +extern EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position); +extern EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position); +extern EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength); +extern EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pFile); +extern EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file); + +/* vibrate, LED, and backlight functions */ +extern EAS_RESULT EAS_HWVibrate(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); +extern EAS_RESULT EAS_HWLED(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); +extern EAS_RESULT EAS_HWBackLight(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + + +/* host yield function */ +extern EAS_BOOL EAS_HWYield(EAS_HW_DATA_HANDLE hwInstData); +#endif /* end _EAS_HOST_H */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_hostmm.c b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_hostmm.c new file mode 100755 index 0000000..df24cf2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_hostmm.c @@ -0,0 +1,660 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_hostmm.c + * + * Contents and purpose: + * This file contains the host wrapper functions for stdio, stdlib, etc. + * This is a sample version that maps the requested files to an + * allocated memory block and uses in-memory pointers to replace + * file system calls. The file locator (EAS_FILE_LOCATOR) handle passed + * HWOpenFile is the same one that is passed to EAS_OpenFile. If your + * system stores data in fixed locations (such as flash) instead of + * using a file system, you can use the locator handle to point to + * your memory. You will need a way of knowing the length of the + * data stored at that location in order to respond correctly in the + * HW_FileLength function. + * + * Modify this file to suit the needs of your particular system. + * + * EAS_MAX_FILE_HANDLES sets the maximum number of MIDI streams within + * a MIDI type 1 file that can be played. + * + * EAS_HW_FILE is a structure to support the file I/O functions. It + * comprises the base memory pointer, the file read pointer, and + * the dup flag, which when sets, indicates that the file handle has + * been duplicated. If your system uses in-memory resources, you + * can eliminate the duplicate handle logic, and simply copy the + * base memory pointer and file read pointer to the duplicate handle. + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#endif + +#include "eas_host.h" + +/* Only for debugging LED, vibrate, and backlight functions */ +#include "eas_report.h" + +/* this module requires dynamic memory support */ +#ifdef _STATIC_MEMORY +#error "eas_hostmm.c requires the dynamic memory model!\n" +#endif + +#ifndef EAS_MAX_FILE_HANDLES +#define EAS_MAX_FILE_HANDLES 32 +#endif + +/* + * this structure and the related function are here + * to support the ability to create duplicate handles + * and buffering it in memory. If your system uses + * in-memory resources, you can eliminate the calls + * to malloc and free, the dup flag, and simply track + * the file size and read position. + */ +typedef struct eas_hw_file_tag +{ + EAS_I32 fileSize; + EAS_I32 filePos; + EAS_BOOL dup; + EAS_U8 *buffer; +} EAS_HW_FILE; + +typedef struct eas_hw_inst_data_tag +{ + EAS_HW_FILE files[EAS_MAX_FILE_HANDLES]; +} EAS_HW_INST_DATA; + +/*---------------------------------------------------------------------------- + * EAS_HWInit + * + * Initialize host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData) +{ + + /* need to track file opens for duplicate handles */ + *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA)); + if (!(*pHWInstData)) + return EAS_ERROR_MALLOC_FAILED; + + EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA)); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_HWShutdown + * + * Shut down host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData) +{ + + free(hwInstData); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMalloc + * + * Allocates dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size) +{ + return malloc((size_t) size); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFree + * + * Frees dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p) +{ + free(p); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCpy + * + * Copy memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount) +{ + return memcpy(dest, src, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemSet + * + * Set memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount) +{ + return memset(dest, val, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCmp + * + * Compare memory wrapper + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount) +{ + return (EAS_I32) memcmp(s1, s2, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWOpenFile + * + * Open a file for read or write + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) +{ + EAS_HW_FILE *file; + FILE *ioFile; + int i, temp; + + /* set return value to NULL */ + *pFile = NULL; + + /* only support read mode at this time */ + if (mode != EAS_FILE_READ) + return EAS_ERROR_INVALID_FILE_MODE; + + /* find an empty entry in the file table */ + file = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (file->buffer == NULL) + { + /* open the file */ + if ((ioFile = fopen(locator,"rb")) == NULL) + return EAS_ERROR_FILE_OPEN_FAILED; + + /* determine the file size */ + if (fseek(ioFile, 0L, SEEK_END) != 0) + return EAS_ERROR_FILE_LENGTH; + if ((file->fileSize = ftell(ioFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(ioFile, 0L, SEEK_SET) != 0) + return EAS_ERROR_FILE_LENGTH; + + /* allocate a buffer */ + file->buffer = EAS_HWMalloc(hwInstData, file->fileSize); + if (file->buffer == NULL) + { + fclose(ioFile); + return EAS_ERROR_MALLOC_FAILED; + } + + /* read the file into memory */ + temp = (int) fread(file->buffer, (size_t) file->fileSize, 1, ioFile); + + /* close the file - don't need it any more */ + fclose(ioFile); + + /* check for error reading file */ + if (temp != 1) + return EAS_ERROR_FILE_READ_FAILED; + + /* initialize some values */ + file->filePos = 0; + file->dup = EAS_FALSE; + + *pFile = file; + return EAS_SUCCESS; + } + file++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWReadFile + * + * Read data from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) +{ + EAS_I32 count; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* calculate the bytes to read */ + count = file->fileSize - file->filePos; + if (n < count) + count = n; + + /* copy the data to the requested location, and advance the pointer */ + if (count) + EAS_HWMemCpy(pBuffer, &file->buffer[file->filePos], count); + file->filePos += count; + *pBytesRead = count; + + /* were n bytes read? */ + if (count!= n) + return EAS_EOF; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetByte + * + * Read a byte from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for end of file */ + if (file->filePos >= file->fileSize) + { + *((EAS_U8*) p) = 0; + return EAS_EOF; + } + + /* get a character from the buffer */ + *((EAS_U8*) p) = file->buffer[file->filePos++]; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2; + + /* read 2 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2; + else + *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetDWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2,c3,c4; + + /* read 4 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4; + else + *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFilePos + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pPosition = file->filePos; + return EAS_SUCCESS; +} /* end EAS_HWFilePos */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeek + * + * Seek to a specific location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* validate new position */ + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeekOfs + * + * Seek forward or back relative to the current position + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* determine the file position */ + position += file->filePos; + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileLength + * + * Return the file length + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pLength = file->fileSize; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWDupHandle + * + * Duplicate a file handle + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile) +{ + EAS_HW_FILE *dupFile; + int i; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* find an empty entry in the file table */ + dupFile = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (dupFile->buffer == NULL) + { + + /* copy info from the handle to be duplicated */ + dupFile->filePos = file->filePos; + dupFile->fileSize = file->fileSize; + dupFile->buffer = file->buffer; + + /* set the duplicate handle flag */ + dupFile->dup = file->dup = EAS_TRUE; + + *pDupFile = dupFile; + return EAS_SUCCESS; + } + dupFile++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWClose + * + * Wrapper for fclose function + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) +{ + EAS_HW_FILE *file2,*dupFile; + int i; + + + /* make sure we have a valid handle */ + if (file1->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for duplicate handle */ + if (file1->dup) + { + dupFile = NULL; + file2 = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* check for duplicate */ + if ((file1 != file2) && (file2->buffer == file1->buffer)) + { + /* is there more than one duplicate? */ + if (dupFile != NULL) + { + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; + } + + /* this is the first duplicate found */ + else + dupFile = file2; + } + file2++; + } + + /* there is only one duplicate, clear the dup flag */ + if (dupFile) + dupFile->dup = EAS_FALSE; + else + /* if we get here, there's a serious problem */ + return EAS_ERROR_HANDLE_INTEGRITY; + + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; + } + + /* no duplicates -free the buffer */ + EAS_HWFree(hwInstData, file1->buffer); + + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWVibrate + * + * Turn on/off vibrate function + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000001 , state); + return EAS_SUCCESS; +} /* end EAS_HWVibrate */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWLED + * + * Turn on/off LED + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000002 , state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWBackLight + * + * Turn on/off backlight + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000003 , state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWYield + * + * This function is called periodically by the EAS library to give the + * host an opportunity to allow other tasks to run. There are two ways to + * use this call: + * + * If you have a multi-tasking OS, you can call the yield function in the + * OS to allow other tasks to run. In this case, return EAS_FALSE to tell + * the EAS library to continue processing when control returns from this + * function. + * + * If tasks run in a single thread by sequential function calls (sometimes + * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to + * return to the caller. Be sure to check the number of bytes rendered + * before passing the audio buffer to the codec - it may not be filled. + * The next call to EAS_Render will continue processing until the buffer + * has been filled. + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData) +{ + /* put your code here */ + return EAS_FALSE; +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_main.c b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_main.c new file mode 100755 index 0000000..6ebb13e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_main.c @@ -0,0 +1,461 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_main.c + * + * Contents and purpose: + * The entry point and high-level functions for the EAS Synthesizer test + * harness. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 775 $ + * $Date: 2007-07-20 10:11:11 -0700 (Fri, 20 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#include +#endif + +#include "eas.h" +#include "eas_wave.h" +#include "eas_report.h" + +/* determines how many EAS buffers to fill a host buffer */ +#define NUM_BUFFERS 8 + +/* default file to play if no filename is specified on the command line */ +static const char defaultTestFile[] = "test.mid"; + +EAS_I32 polyphony; + +/* prototypes for helper functions */ +static void StrCopy(char *dest, const char *src, EAS_I32 size); +static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size); +static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize); +static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig); + +/* main is defined after playfile to avoid the need for two passes through lint */ + +/*---------------------------------------------------------------------------- + * PlayFile() + *---------------------------------------------------------------------------- + * Purpose: + * This function plays the file requested by filename + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize) +{ + EAS_HANDLE handle; + EAS_RESULT result, reportResult; + EAS_I32 count; + EAS_STATE state; + EAS_I32 playTime; + char waveFilename[256]; + WAVE_FILE *wFile; + EAS_INT i; + EAS_PCM *p; + + /* determine the name of the output file */ + wFile = NULL; + if (outputFile == NULL) + { + StrCopy(waveFilename, filename, sizeof(waveFilename)); + if (!ChangeFileExt(waveFilename, "wav", sizeof(waveFilename))) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error in output filename %s\n", waveFilename); */ } + return EAS_FAILURE; + } + outputFile = waveFilename; + } + + /* call EAS library to open file */ + if ((reportResult = EAS_OpenFile(easData, filename, &handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_OpenFile returned %ld\n", reportResult); */ } + return reportResult; + } + + /* prepare to play the file */ + if ((result = EAS_Prepare(easData, handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Prepare returned %ld\n", result); */ } + reportResult = result; + } + + /* get play length */ + if ((result = EAS_ParseMetaData(easData, handle, &playTime)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_ParseMetaData returned %ld\n", result); */ } + return result; + } + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0xe624f4d9, 0x00000005 , playTime / 1000, playTime % 1000); + + if (reportResult == EAS_SUCCESS) + { + /* create the output file */ + wFile = WaveFileCreate(outputFile, pLibConfig->numChannels, pLibConfig->sampleRate, sizeof(EAS_PCM) * 8); + if (!wFile) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to create output file %s\n", waveFilename); */ } + reportResult = EAS_FAILURE; + } + } + + /* rendering loop */ + while (reportResult == EAS_SUCCESS) + { + + /* we may render several buffers here to fill one host buffer */ + for (i = 0, p = buffer; i < NUM_BUFFERS; i++, p+= pLibConfig->mixBufferSize * pLibConfig->numChannels) + { + + /* get the current time */ + if ((result = EAS_GetLocation(easData, handle, &playTime)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_GetLocation returned %d\n",result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + break; + } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Parser time: %d.%03d\n", playTime / 1000, playTime % 1000); */ } + + /* render a buffer of audio */ + if ((result = EAS_Render(easData, p, pLibConfig->mixBufferSize, &count)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Render returned %d\n",result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + + if (result == EAS_SUCCESS) + { + /* write it to the wave file */ + if (WaveFileWrite(wFile, buffer, bufferSize) != bufferSize) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "WaveFileWrite failed\n"); */ } + reportResult = EAS_FAILURE; + } + } + + if (reportResult == EAS_SUCCESS) + { + /* check stream state */ + if ((result = EAS_State(easData, handle, &state)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_State returned %d\n", result); */ } + reportResult = result; + } + + /* is playback complete */ + if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) + break; + } + } + + /* close the output file */ + if (wFile) + { + if (!WaveFileClose(wFile)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error closing wave file %s\n", waveFilename); */ } + if (reportResult == EAS_SUCCESS) + result = EAS_FAILURE; + } + } + + /* close the input file */ + if ((result = EAS_CloseFile(easData,handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Close returned %ld\n", result); */ } + if (reportResult == EAS_SUCCESS) + result = EAS_FAILURE; + } + + return reportResult; +} /* end PlayFile */ + +/*---------------------------------------------------------------------------- + * main() + *---------------------------------------------------------------------------- + * Purpose: The entry point for the EAS sample application + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +int main( int argc, char **argv ) +{ + EAS_DATA_HANDLE easData; + const S_EAS_LIB_CONFIG *pLibConfig; + void *buffer; + EAS_RESULT result, playResult; + EAS_I32 bufferSize; + int i; + int temp; + FILE *debugFile; + char *outputFile = NULL; + + /* set the error reporting level */ + EAS_SetDebugLevel(_EAS_SEVERITY_INFO); + debugFile = NULL; + + /* process command-line arguments */ + for (i = 1; i < argc; i++) + { + /* check for switch */ + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'd': + temp = argv[i][2]; + if ((temp >= '0') || (temp <= '9')) + EAS_SetDebugLevel(temp); + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid debug level %d\n", temp); */ } + break; + case 'f': + if ((debugFile = fopen(&argv[i][2],"w")) == NULL) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unable to create debug file %s\n", &argv[i][2]); */ } + else + EAS_SetDebugFile(debugFile, EAS_TRUE); + break; + case 'o': + outputFile = &argv[i][2]; + break; + case 'p': + polyphony = atoi(&argv[i][2]); + if (polyphony < 1) + polyphony = 1; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Polyphony set to %d\n", polyphony); */ } + break; + default: + break; + } + continue; + } + } + + /* assume success */ + playResult = EAS_SUCCESS; + + /* get the library configuration */ + pLibConfig = EAS_Config(); + if (!EASLibraryCheck(pLibConfig)) + return -1; + if (polyphony > pLibConfig->maxVoices) + polyphony = pLibConfig->maxVoices; + + /* calculate buffer size */ + bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS; + + /* allocate output buffer memory */ + buffer = malloc((EAS_U32)bufferSize); + if (!buffer) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Error allocating memory for audio buffer\n"); */ } + return EAS_FAILURE; + } + + /* initialize the EAS library */ + polyphony = pLibConfig->maxVoices; + if ((result = EAS_Init(&easData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Init returned %ld - aborting!\n", result); */ } + free(buffer); + return result; + } + + /* + * Some debugging environments don't allow for passed parameters. + * In this case, just play the default MIDI file "test.mid" + */ + if (argc < 2) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", defaultTestFile); */ } + if ((playResult = PlayFile(easData, defaultTestFile, NULL, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, defaultTestFile); */ } + } + } + /* iterate through the list of files to be played */ + else + { + for (i = 1; i < argc; i++) + { + /* check for switch */ + if (argv[i][0] != '-') + { + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", argv[i]); */ } + if ((playResult = PlayFile(easData, argv[i], outputFile, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, argv[i]); */ } + break; + } + } + } + } + + /* shutdown the EAS library */ + if ((result = EAS_Shutdown(easData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Shutdown returned %ld\n", result); */ } + } + + /* free the output buffer */ + free(buffer); + + /* close the debug file */ + if (debugFile) + fclose(debugFile); + + /* play errors take precedence over shutdown errors */ + if (playResult != EAS_SUCCESS) + return playResult; + return result; +} /* end main */ + +/*---------------------------------------------------------------------------- + * StrCopy() + *---------------------------------------------------------------------------- + * Purpose: + * Safe string copy + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void StrCopy(char *dest, const char *src, EAS_I32 size) +{ + int len; + + strncpy(dest, src, (size_t) size-1); + len = (int) strlen(src); + if (len < size) + dest[len] = 0; +} /* end StrCopy */ + +/*---------------------------------------------------------------------------- + * ChangeFileExt() + *---------------------------------------------------------------------------- + * Purpose: + * Changes the file extension of a filename + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size) +{ + char *p; + + /* find the extension, if any */ + p = strrchr(str,'.'); + if (!p) + { + if ((EAS_I32)(strlen(str) + 5) > size) + return EAS_FALSE; + strcat(str,"."); + strcat(str,ext); + return EAS_TRUE; + } + + /* make sure there's room for the extension */ + p++; + *p = 0; + if ((EAS_I32)(strlen(str) + 4) > size) + return EAS_FALSE; + strcat(str,ext); + return EAS_TRUE; +} /* end ChangeFileExt */ + +/*---------------------------------------------------------------------------- + * EASLibraryCheck() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the library version and checks it against the header + * file used to build this code. + * + * Inputs: + * pLibConfig - library configuration retrieved from the library + * + * Outputs: + * returns EAS_TRUE if matched + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig) +{ + + /* display the library version */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "EAS Library Version %d.%d.%d.%d\n", + pLibConfig->libVersion >> 24, + (pLibConfig->libVersion >> 16) & 0x0f, + (pLibConfig->libVersion >> 8) & 0x0f, + pLibConfig->libVersion & 0x0f); */ } + + /* display some info about the library build */ + if (pLibConfig->checkedVersion) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tChecked library\n"); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMaximum polyphony: %d\n", pLibConfig->maxVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tNumber of channels: %d\n", pLibConfig->numChannels); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tSample rate: %d\n", pLibConfig->sampleRate); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMix buffer size: %d\n", pLibConfig->mixBufferSize); */ } + if (pLibConfig->filterEnabled) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tFilter enabled\n"); */ } +#ifndef _WIN32_WCE + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build Timestamp: %s", ctime((time_t*)&pLibConfig->buildTimeStamp)); */ } +#endif + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build ID: %s\n", pLibConfig->buildGUID); */ } + + /* check it against the header file used to build this code */ + /*lint -e{778} constant expression used for display purposes may evaluate to zero */ + if (LIB_VERSION != pLibConfig->libVersion) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Library version does not match header files. EAS Header Version %d.%d.%d.%d\n", + LIB_VERSION >> 24, + (LIB_VERSION >> 16) & 0x0f, + (LIB_VERSION >> 8) & 0x0f, + LIB_VERSION & 0x0f); */ } + return EAS_FALSE; + } + return EAS_TRUE; +} /* end EASLibraryCheck */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_report.c b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_report.c new file mode 100755 index 0000000..04a828c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_report.c @@ -0,0 +1,264 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_report.c + * + * Contents and purpose: + * This file contains the debug message handling routines for the EAS library. + * These routines should be modified as needed for your system. + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 659 $ + * $Date: 2007-04-24 13:36:35 -0700 (Tue, 24 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#endif + +#include "eas_report.h" + +static int severityLevel = 9999; + +/* debug file */ +static FILE *debugFile = NULL; +int flush = 0; + +#ifndef _NO_DEBUG_PREPROCESSOR + +/* structure should have an #include for each error message header file */ +S_DEBUG_MESSAGES debugMessages[] = +{ +#ifndef UNIFIED_DEBUG_MESSAGES +#include "eas_config_msgs.h" + + +#include "eas_host_msgs.h" +#include "eas_hostmm_msgs.h" +#include "eas_math_msgs.h" +#include "eas_midi_msgs.h" +#include "eas_mixer_msgs.h" +#include "eas_pcm_msgs.h" +#include "eas_public_msgs.h" +#include "eas_smf_msgs.h" +#include "eas_wave_msgs.h" +#include "eas_voicemgt_msgs.h" + +#ifdef _FM_SYNTH +#include "eas_fmsynth_msgs.h" +#include "eas_fmengine_msgs.h" +#endif + +#ifdef _WT_SYNTH +#include "eas_wtsynth_msgs.h" +#include "eas_wtengine_msgs.h" +#endif + +#ifdef _ARM_TEST_MAIN +#include "arm_main_msgs.h" +#endif + +#ifdef _EAS_MAIN +#include "eas_main_msgs.h" +#endif + +#ifdef _EAS_MAIN_IPC +#include "eas_main_ipc_msgs.h" +#endif + +#ifdef _METRICS_ENABLED +#include "eas_perf_msgs.h" +#endif + +#ifdef _COMPRESSOR_ENABLED +#include "eas_compressor_msgs.h" +#endif + +#ifdef _ENHANCER_ENABLED +#include "eas_enhancer_msgs.h" +#endif + +#ifdef _WOW_ENABLED +#include "eas_wow_msgs.h" +#endif + +#ifdef _SMAF_PARSER +#include "eas_smaf_msgs.h" +#endif + +#ifdef _OTA_PARSER +#include "eas_ota_msgs.h" +#endif + +#ifdef _IMELODY_PARSER +#include "eas_imelody_msgs.h" +#endif + +#ifdef _WAVE_PARSER +#include "eas_wavefile_msgs.h" +#endif + +#if defined(_CMX_PARSER) || defined(_MFI_PARSER) +#include "eas_cmf_msgs.h" +#endif + +#if defined(_CMX_PARSER) || defined(_MFI_PARSER) || defined(_WAVE_PARSER) +#include "eas_imaadpcm_msgs.h" +#endif + +#else +#include "eas_debugmsgs.h" +#endif + +/* denotes end of error messages */ +{ 0,0,0 } +}; + +/*---------------------------------------------------------------------------- + * EAS_ReportEx() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...) +{ + va_list vargs; + int i; + + /* check severity level */ + if (severity > severityLevel) + return; + + /* find the error message and output to stdout */ + /*lint -e{661} we check for NULL pointer - no fence post error here */ + for (i = 0; debugMessages[i].m_pDebugMsg; i++) + { + if ((debugMessages[i].m_nHashCode == hashCode) && + (debugMessages[i].m_nSerialNum == serialNum)) + { + /*lint -e{826} */ + va_start(vargs, serialNum); + if (debugFile) + { + vfprintf(debugFile, debugMessages[i].m_pDebugMsg, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(debugMessages[i].m_pDebugMsg, vargs); + } + va_end(vargs); + return; + } + } + printf("Unrecognized error: Severity=%d; HashCode=%lu; SerialNum=%d\n", severity, hashCode, serialNum); +} /* end EAS_ReportEx */ + +#else +/*---------------------------------------------------------------------------- + * EAS_Report() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_Report (int severity, const char *fmt, ...) +{ + va_list vargs; + + /* check severity level */ + if (severity > severityLevel) + return; + + /*lint -e{826} */ + va_start(vargs, fmt); + if (debugFile) + { + vfprintf(debugFile, fmt, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(fmt, vargs); + } + va_end(vargs); +} /* end EAS_Report */ + +/*---------------------------------------------------------------------------- + * EAS_ReportX() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_ReportX (int severity, const char *fmt, ...) +{ + va_list vargs; + + /* check severity level */ + if (severity > severityLevel) + return; + + /*lint -e{826} */ + va_start(vargs, fmt); + if (debugFile) + { + vfprintf(debugFile, fmt, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(fmt, vargs); + } + va_end(vargs); +} /* end EAS_ReportX */ +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetDebugLevel() + * + * Sets the level for debug message output + *---------------------------------------------------------------------------- +*/ + +void EAS_SetDebugLevel (int severity) +{ + severityLevel = severity; +} /* end EAS_SetDebugLevel */ + +/*---------------------------------------------------------------------------- + * EAS_SetDebugFile() + * + * Redirect debugger output to the specified file. + *---------------------------------------------------------------------------- +*/ +void EAS_SetDebugFile (void *file, int flushAfterWrite) +{ + debugFile = (FILE*) file; + flush = flushAfterWrite; +} /* end EAS_SetDebugFile */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_report.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_report.h new file mode 100755 index 0000000..b603b12 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_report.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_report.h + * + * Contents and purpose: + * This file contains the debug message handling routines for the EAS library. + * These routines should be modified as needed for your system. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +/* sentinel */ +#ifndef _EAS_REPORT_H +#define _EAS_REPORT_H + +#define _EAS_SEVERITY_NOFILTER 0 +#define _EAS_SEVERITY_FATAL 1 +#define _EAS_SEVERITY_ERROR 2 +#define _EAS_SEVERITY_WARNING 3 +#define _EAS_SEVERITY_INFO 4 +#define _EAS_SEVERITY_DETAIL 5 + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _NO_DEBUG_PREPROCESSOR + +/* structure for included debug message header files */ +typedef struct +{ + unsigned long m_nHashCode; + int m_nSerialNum; + char *m_pDebugMsg; +} S_DEBUG_MESSAGES; + +/* debug message handling prototypes */ +extern void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...); + +#else + +/* these prototypes are used if the debug preprocessor is not used */ +extern void EAS_Report (int severity, const char* fmt, ...); +extern void EAS_ReportX (int severity, const char* fmt, ...); + +#endif + +extern void EAS_SetDebugLevel (int severity); +extern void EAS_SetDebugFile (void *file, int flushAfterWrite); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_reverb.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_reverb.h new file mode 100755 index 0000000..559abed --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_reverb.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverb.h + * + * Contents and purpose: + * Contains parameter enumerations for the Reverb effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 300 $ + * $Date: 2006-09-11 17:37:20 -0700 (Mon, 11 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_REVERB_H +#define _EAS_REVERB_H + + +/* enumerated parameter settings for Reverb effect */ +typedef enum +{ + EAS_PARAM_REVERB_BYPASS, + EAS_PARAM_REVERB_PRESET, + EAS_PARAM_REVERB_WET, + EAS_PARAM_REVERB_DRY +} E_REVERB_PARAMS; + + +typedef enum +{ + EAS_PARAM_REVERB_LARGE_HALL, + EAS_PARAM_REVERB_HALL, + EAS_PARAM_REVERB_CHAMBER, + EAS_PARAM_REVERB_ROOM, +} E_REVERB_PRESETS; + + +#endif /* _REVERB_H */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_types.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_types.h new file mode 100755 index 0000000..45fa4b2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_types.h @@ -0,0 +1,268 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_types.h + * + * Contents and purpose: + * The public interface header for the EAS synthesizer. + * + * This header only contains declarations that are specific + * to this implementation. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 726 $ + * $Date: 2007-06-14 23:10:46 -0700 (Thu, 14 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_TYPES_H +#define _EAS_TYPES_H + +/* EAS_RESULT return codes */ +typedef long EAS_RESULT; +#define EAS_SUCCESS 0 +#define EAS_FAILURE -1 +#define EAS_ERROR_INVALID_MODULE -2 +#define EAS_ERROR_MALLOC_FAILED -3 +#define EAS_ERROR_FILE_POS -4 +#define EAS_ERROR_INVALID_FILE_MODE -5 +#define EAS_ERROR_FILE_SEEK -6 +#define EAS_ERROR_FILE_LENGTH -7 +#define EAS_ERROR_NOT_IMPLEMENTED -8 +#define EAS_ERROR_CLOSE_FAILED -9 +#define EAS_ERROR_FILE_OPEN_FAILED -10 +#define EAS_ERROR_INVALID_HANDLE -11 +#define EAS_ERROR_NO_MIX_BUFFER -12 +#define EAS_ERROR_PARAMETER_RANGE -13 +#define EAS_ERROR_MAX_FILES_OPEN -14 +#define EAS_ERROR_UNRECOGNIZED_FORMAT -15 +#define EAS_BUFFER_SIZE_MISMATCH -16 +#define EAS_ERROR_FILE_FORMAT -17 +#define EAS_ERROR_SMF_NOT_INITIALIZED -18 +#define EAS_ERROR_LOCATE_BEYOND_END -19 +#define EAS_ERROR_INVALID_PCM_TYPE -20 +#define EAS_ERROR_MAX_PCM_STREAMS -21 +#define EAS_ERROR_NO_VOICE_ALLOCATED -22 +#define EAS_ERROR_INVALID_CHANNEL -23 +#define EAS_ERROR_ALREADY_STOPPED -24 +#define EAS_ERROR_FILE_READ_FAILED -25 +#define EAS_ERROR_HANDLE_INTEGRITY -26 +#define EAS_ERROR_MAX_STREAMS_OPEN -27 +#define EAS_ERROR_INVALID_PARAMETER -28 +#define EAS_ERROR_FEATURE_NOT_AVAILABLE -29 +#define EAS_ERROR_SOUND_LIBRARY -30 +#define EAS_ERROR_NOT_VALID_IN_THIS_STATE -31 +#define EAS_ERROR_NO_VIRTUAL_SYNTHESIZER -32 +#define EAS_ERROR_FILE_ALREADY_OPEN -33 +#define EAS_ERROR_FILE_ALREADY_CLOSED -34 +#define EAS_ERROR_INCOMPATIBLE_VERSION -35 +#define EAS_ERROR_QUEUE_IS_FULL -36 +#define EAS_ERROR_QUEUE_IS_EMPTY -37 +#define EAS_ERROR_FEATURE_ALREADY_ACTIVE -38 + +/* special return codes */ +#define EAS_EOF 3 +#define EAS_STREAM_BUFFERING 4 +#define EAS_BUFFER_FULL 5 + +/* EAS_STATE return codes */ +typedef long EAS_STATE; +typedef enum +{ + EAS_STATE_READY = 0, + EAS_STATE_PLAY, + EAS_STATE_STOPPING, + EAS_STATE_PAUSING, + EAS_STATE_STOPPED, + EAS_STATE_PAUSED, + EAS_STATE_OPEN, + EAS_STATE_ERROR, + EAS_STATE_EMPTY +} E_EAS_STATE; + +/* constants */ +#ifndef EAS_CONST +#define EAS_CONST const +#endif + +/* definition for public interface functions */ +#ifndef EAS_PUBLIC +#define EAS_PUBLIC +#endif + +/* boolean values */ +typedef unsigned EAS_BOOL; +typedef unsigned char EAS_BOOL8; + +#define EAS_FALSE 0 +#define EAS_TRUE 1 + +/* scalar variable definitions */ +typedef unsigned char EAS_U8; +typedef signed char EAS_I8; +typedef char EAS_CHAR; + +typedef unsigned short EAS_U16; +typedef short EAS_I16; + +typedef unsigned long EAS_U32; +typedef long EAS_I32; + +typedef unsigned EAS_UINT; +typedef int EAS_INT; +typedef long EAS_LONG; + +/* audio output type */ +typedef short EAS_PCM; + +/* file open modes */ +typedef EAS_I32 EAS_FILE_MODE; +#define EAS_FILE_READ 1 +#define EAS_FILE_WRITE 2 + +/* file locator e.g. filename or memory pointer */ +typedef const void *EAS_FILE_LOCATOR; + +/* handle to stream */ +typedef struct s_eas_stream_tag *EAS_HANDLE; + +/* handle to file */ +typedef struct eas_hw_file_tag *EAS_FILE_HANDLE; + +/* handle for synthesizer data */ +typedef struct s_eas_data_tag *EAS_DATA_HANDLE; + +/* handle to persistent data for host wrapper interface */ +typedef struct eas_hw_inst_data_tag *EAS_HW_DATA_HANDLE; + +/* handle to sound library */ +typedef struct s_eas_sndlib_tag *EAS_SNDLIB_HANDLE; +typedef struct s_eas_dls_tag *EAS_DLSLIB_HANDLE; + +/* pointer to frame buffer - used in split architecture only */ +typedef struct s_eas_frame_buffer_tag *EAS_FRAME_BUFFER_HANDLE; + +/* untyped pointer for instance data */ +typedef void *EAS_VOID_PTR; + +/* inline functions */ +#ifndef EAS_INLINE +#if defined (__XCC__) +#define EAS_INLINE __inline__ +#elif defined (__GNUC__) +#define EAS_INLINE inline static +#else +#define EAS_INLINE __inline +#endif +#endif + +/* define NULL value */ +#ifndef NULL +#define NULL 0 +#endif + +/* metadata types for metadata return codes */ +typedef enum +{ + EAS_METADATA_UNKNOWN = 0, + EAS_METADATA_TITLE, + EAS_METADATA_AUTHOR, + EAS_METADATA_COPYRIGHT, + EAS_METADATA_LYRIC, + EAS_METADATA_TEXT +} E_EAS_METADATA_TYPE; + +/* metadata callback function */ +typedef void (*EAS_METADATA_CBFUNC) (E_EAS_METADATA_TYPE metaDataType, char *metaDataBuf, EAS_VOID_PTR pUserData); + +/* file types for metadata return codes */ +typedef enum +{ + EAS_FILE_UNKNOWN = 0, + EAS_FILE_SMF0, + EAS_FILE_SMF1, + EAS_FILE_SMAF_UNKNOWN, + EAS_FILE_SMAF_MA2, + EAS_FILE_SMAF_MA3, + EAS_FILE_SMAF_MA5, + EAS_FILE_CMX, + EAS_FILE_MFI, + EAS_FILE_OTA, + EAS_FILE_IMELODY, + EAS_FILE_RTTTL, + EAS_FILE_XMF0, + EAS_FILE_XMF1, + EAS_FILE_WAVE_PCM, + EAS_FILE_WAVE_IMA_ADPCM, + EAS_FILE_MMAPI_TONE_CONTROL +} E_EAS_FILE_TYPE; + +/* enumeration for synthesizers */ +typedef enum +{ + EAS_MCU_SYNTH = 0, + EAS_DSP_SYNTH +} E_SYNTHESIZER; + +/* external audio callback program change */ +typedef struct s_ext_audio_prg_chg_tag +{ + EAS_U16 bank; + EAS_U8 program; + EAS_U8 channel; +} S_EXT_AUDIO_PRG_CHG; + +/* external audio callback event */ +typedef struct s_ext_audio_event_tag +{ + EAS_U8 channel; + EAS_U8 note; + EAS_U8 velocity; + EAS_BOOL8 noteOn; +} S_EXT_AUDIO_EVENT; + +typedef struct s_midi_controllers_tag +{ + EAS_U8 modWheel; /* CC1 */ + EAS_U8 volume; /* CC7 */ + EAS_U8 pan; /* CC10 */ + EAS_U8 expression; /* CC11 */ + EAS_U8 channelPressure; /* MIDI channel pressure */ + +#ifdef _REVERB + EAS_U8 reverbSend; /* CC91 */ +#endif + +#ifdef _CHORUS + EAS_U8 chorusSend; /* CC93 */ +#endif +} S_MIDI_CONTROLLERS; + +/* iMode play modes enumeration for EAS_SetPlayMode */ +typedef enum +{ + IMODE_PLAY_ALL = 0, + IMODE_PLAY_PARTIAL +} E_I_MODE_PLAY_MODE; + +typedef EAS_BOOL (*EAS_EXT_PRG_CHG_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_PRG_CHG *pPrgChg); +typedef EAS_BOOL (*EAS_EXT_EVENT_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_EVENT *pEvent); + +#endif /* #ifndef _EAS_TYPES_H */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_wave.c b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_wave.c new file mode 100755 index 0000000..4f6ffbd --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_wave.c @@ -0,0 +1,423 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wave.c + * + * Contents and purpose: + * This module contains .WAV file functions for the EAS synthesizer + * test harness. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 658 $ + * $Date: 2007-04-24 13:35:49 -0700 (Tue, 24 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* lint complaints about most C library headers, so we use our own during lint step */ +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#endif + +#include "eas_wave.h" + +/* .WAV file format tags */ +const EAS_U32 riffTag = 0x46464952; +const EAS_U32 waveTag = 0x45564157; +const EAS_U32 fmtTag = 0x20746d66; +const EAS_U32 dataTag = 0x61746164; + +#ifdef _BIG_ENDIAN +/*---------------------------------------------------------------------------- + * FlipDWord() + *---------------------------------------------------------------------------- + * Purpose: Endian flip a DWORD for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipDWord (EAS_U32 *pValue) +{ + EAS_U8 *p; + EAS_U32 temp; + + p = (EAS_U8*) pValue; + temp = (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; + *pValue = temp; +} + +/*---------------------------------------------------------------------------- + * FlipWord() + *---------------------------------------------------------------------------- + * Purpose: Endian flip a WORD for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipWord (EAS_U16 *pValue) +{ + EAS_U8 *p; + EAS_U16 temp; + + p = (EAS_U8*) pValue; + temp = (p[1] << 8) | p[0]; + *pValue = temp; +} + +/*---------------------------------------------------------------------------- + * FlipWaveHeader() + *---------------------------------------------------------------------------- + * Purpose: Endian flip the wave header for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipWaveHeader (WAVE_HEADER *p) +{ + + FlipDWord(&p->nRiffTag); + FlipDWord(&p->nRiffSize); + FlipDWord(&p->nWaveTag); + FlipDWord(&p->nFmtTag); + FlipDWord(&p->nFmtSize); + FlipDWord(&p->nDataTag); + FlipDWord(&p->nDataSize); + FlipWord(&p->fc.wFormatTag); + FlipWord(&p->fc.nChannels); + FlipDWord(&p->fc.nSamplesPerSec); + FlipDWord(&p->fc.nAvgBytesPerSec); + FlipWord(&p->fc.nBlockAlign); + FlipWord(&p->fc.wBitsPerSample); + +} +#endif + +/*---------------------------------------------------------------------------- + * WaveFileCreate() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for writing and writes the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample) +{ + WAVE_FILE *wFile; + + /* allocate memory */ + wFile = malloc(sizeof(WAVE_FILE)); + if (!wFile) + return NULL; + wFile->write = EAS_TRUE; + + /* create the file */ + wFile->file = fopen(filename,"wb"); + if (!wFile->file) + { + free(wFile); + return NULL; + } + + /* initialize PCM format .WAV file header */ + wFile->wh.nRiffTag = riffTag; + wFile->wh.nRiffSize = sizeof(WAVE_HEADER) - 8; + wFile->wh.nWaveTag = waveTag; + wFile->wh.nFmtTag = fmtTag; + wFile->wh.nFmtSize = sizeof(FMT_CHUNK); + + /* initalize 'fmt' chunk */ + wFile->wh.fc.wFormatTag = 1; + wFile->wh.fc.nChannels = (EAS_U16) nChannels; + wFile->wh.fc.nSamplesPerSec = (EAS_U32) nSamplesPerSec; + wFile->wh.fc.wBitsPerSample = (EAS_U16) wBitsPerSample; + wFile->wh.fc.nBlockAlign = (EAS_U16) (nChannels * (EAS_U16) (wBitsPerSample / 8)); + wFile->wh.fc.nAvgBytesPerSec = wFile->wh.fc.nBlockAlign * (EAS_U32) nSamplesPerSec; + + /* initialize 'data' chunk */ + wFile->wh.nDataTag = dataTag; + wFile->wh.nDataSize = 0; + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + + /* write the header */ + if (fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file) != 1) + { + fclose(wFile->file); + free(wFile); + return NULL; + } + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + + /* return the file handle */ + return wFile; +} /* end WaveFileCreate */ + +/*---------------------------------------------------------------------------- + * WaveFileWrite() + *---------------------------------------------------------------------------- + * Purpose: Writes data to the wave file + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n) +{ + EAS_I32 count; + + /* make sure we have an open file */ + if (wFile == NULL) + { + return 0; + } + +#ifdef _BIG_ENDIAN + { + EAS_I32 i; + EAS_U16 *p; + p = buffer; + i = n >> 1; + while (i--) + FlipWord(p++); + } +#endif + + /* write the data */ + count = (EAS_I32) fwrite(buffer, 1, (size_t) n, wFile->file); + + /* add the number of bytes written */ + wFile->wh.nRiffSize += (EAS_U32) count; + wFile->wh.nDataSize += (EAS_U32) count; + + /* return the count of bytes written */ + return count; +} /* end WriteWaveHeader */ + +/*---------------------------------------------------------------------------- + * WaveFileClose() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for writing and writes the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +EAS_BOOL WaveFileClose (WAVE_FILE *wFile) +{ + EAS_I32 count = 1; + + /* return to beginning of file and write the header */ + if (wFile->write) + { + if (fseek(wFile->file, 0L, SEEK_SET) == 0) + { + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + count = (EAS_I32) fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file); +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + } + } + + /* close the file */ + if (fclose(wFile->file) != 0) + count = 0; + + /* free the memory */ + free(wFile); + + /* return the file handle */ + return (count == 1 ? EAS_TRUE : EAS_FALSE); +} /* end WaveFileClose */ + +#ifdef _WAVE_FILE_READ +#ifdef _BIG_ENDIAN +#error "WaveFileOpen not currently supported on big-endian processors" +#endif +/*---------------------------------------------------------------------------- + * WaveFileOpen() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for reading and reads the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +WAVE_FILE *WaveFileOpen (const char *filename) +{ + WAVE_FILE *wFile; + struct + { + EAS_U32 tag; + EAS_U32 size; + } chunk; + EAS_U32 tag; + EAS_I32 startChunkPos; + EAS_INT state; + EAS_BOOL done; + + /* allocate memory */ + wFile = malloc(sizeof(WAVE_FILE)); + if (!wFile) + return NULL; + + /* open the file */ + wFile->write = EAS_FALSE; + wFile->file = fopen(filename,"rb"); + if (!wFile->file) + { + free(wFile); + return NULL; + } + + /* make lint happy */ + chunk.tag = chunk.size = 0; + startChunkPos = 0; + + /* read the RIFF tag and file size */ + state = 0; + done = EAS_FALSE; + while (!done) + { + + switch(state) + { + /* read the RIFF tag */ + case 0: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + if (chunk.tag != riffTag) + done = EAS_TRUE; + else + state++; + } + break; + + /* read the WAVE tag */ + case 1: + if (fread(&tag, sizeof(tag), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + if (tag != waveTag) + done = EAS_TRUE; + else + state++; + } + break; + + /* looking for fmt chunk */ + case 2: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + startChunkPos = ftell(wFile->file); + + /* not fmt tag, skip it */ + if (chunk.tag != fmtTag) + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + else + state++; + } + break; + + /* read fmt chunk */ + case 3: + if (fread(&wFile->wh.fc, sizeof(FMT_CHUNK), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + state++; + } + break; + + /* looking for data chunk */ + case 4: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + startChunkPos = ftell(wFile->file); + + /* not data tag, skip it */ + if (chunk.tag != dataTag) + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + else + { + wFile->dataSize = chunk.size; + state++; + done = EAS_TRUE; + } + } + break; + + default: + done = EAS_TRUE; + break; + } + } + + /* if not final state, an error occurred */ + if (state != 5) + { + fclose(wFile->file); + free(wFile); + return NULL; + } + + /* return the file handle */ + return wFile; +} /* end WaveFileOpen */ +#endif + + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_wave.h b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_wave.h new file mode 100755 index 0000000..968782f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/host_src/eas_wave.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wave.h + * + * Contents and purpose: + * Writes output to a .WAV file + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" + +/* sentinel */ +#ifndef _EAS_WAVE_H +#define _EAS_WAVE_H + +/* .WAV file format chunk */ +typedef struct { + EAS_U16 wFormatTag; + EAS_U16 nChannels; + EAS_U32 nSamplesPerSec; + EAS_U32 nAvgBytesPerSec; + EAS_U16 nBlockAlign; + EAS_U16 wBitsPerSample; +} FMT_CHUNK; + +/* .WAV file header */ +typedef struct { + EAS_U32 nRiffTag; + EAS_U32 nRiffSize; + EAS_U32 nWaveTag; + EAS_U32 nFmtTag; + EAS_U32 nFmtSize; + FMT_CHUNK fc; + EAS_U32 nDataTag; + EAS_U32 nDataSize; +} WAVE_HEADER; + +typedef struct { + WAVE_HEADER wh; + FILE *file; + EAS_BOOL write; + EAS_U32 dataSize; +} WAVE_FILE; + +WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample); +EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n); +EAS_BOOL WaveFileClose (WAVE_FILE *wFile); +WAVE_FILE *WaveFileOpen (const char *filename); + +#endif /* end #ifndef _EAS_WAVE_H */ + + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib/libarm-fm-22k.a b/code/embeddedaudiosynthesis/arm-fm-22k/lib/libarm-fm-22k.a new file mode 100755 index 0000000..303b6b3 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-fm-22k/lib/libarm-fm-22k.a differ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/arm-fm-22k_lib.mak b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/arm-fm-22k_lib.mak new file mode 100755 index 0000000..e4bc63d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/arm-fm-22k_lib.mak @@ -0,0 +1,25 @@ +# +# Auto-generated sample makefile +# +# This makefile is intended for use with GNU make. +# Set the paths to the tools (CC, AR, LD, etc.) +# + +vpath %.c lib_src + +CC = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AS = C:\Program Files\GNUARM\bin\arm-elf-as.exe +LD = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AR = C:\Program Files\GNUARM\bin\arm-elf-ar.exe + +%.o: %.c + $(CC) -c -O2 -o $@ -I lib_src -I host_src -D NUM_OUTPUT_CHANNELS=2 -D _SAMPLE_RATE_22050 -D MAX_SYNTH_VOICES=16 -D EAS_FM_SYNTH -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED -D _IMA_DECODER $< + +%.o: %.s + $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa $< + +OBJS = eas_mididata.o eas_pan.o eas_wavefiledata.o eas_smfdata.o eas_imelody.o eas_math.o eas_fmengine.o eas_chorusdata.o eas_ima_tables.o eas_ota.o eas_rtttldata.o eas_imelodydata.o eas_fmtables.o eas_public.o eas_rtttl.o eas_reverb.o eas_fmsynth.o eas_midi.o eas_otadata.o eas_mixbuf.o eas_fmsndlib.o eas_imaadpcm.o eas_smf.o eas_chorus.o eas_pcm.o eas_mixer.o eas_wavefile.o eas_pcmdata.o eas_data.o eas_reverbdata.o eas_voicemgt.o + +arm-fm-22k.a: $(OBJS) + $(AR) rc lib$@ $(OBJS) + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_audioconst.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_audioconst.h new file mode 100755 index 0000000..066148e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_audioconst.h @@ -0,0 +1,97 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_audioconst.h + * + * Contents and purpose: + * Defines audio constants related to the sample rate, bit size, etc. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_AUDIOCONST_H +#define _EAS_AUDIOCONST_H + +/*---------------------------------------------------------------------------- + * These macros define the various characteristics of the defined sample rates + *---------------------------------------------------------------------------- + * BUFFER_SIZE_IN_MONO_SAMPLES size of buffer in samples + * _OUTPUT_SAMPLE_RATE compiled output sample rate + * AUDIO_FRAME_LENGTH length of an audio frame in 256ths of a millisecond + * SYNTH_UPDATE_PERIOD_IN_BITS length of an audio frame (2^x samples) + *---------------------------------------------------------------------------- +*/ + +#if defined (_SAMPLE_RATE_8000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 32 +#define _OUTPUT_SAMPLE_RATE 8000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 5 + +#elif defined (_SAMPLE_RATE_16000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 64 +#define _OUTPUT_SAMPLE_RATE 16000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 6 + +#elif defined (_SAMPLE_RATE_20000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 20000 +#define AUDIO_FRAME_LENGTH 1638 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_22050) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 22050 +#define AUDIO_FRAME_LENGTH 1486 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_24000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 24000 +#define AUDIO_FRAME_LENGTH 1365 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_32000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 32000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_44100) +#define BUFFER_SIZE_IN_MONO_SAMPLES 256 +#define _OUTPUT_SAMPLE_RATE 44100 +#define AUDIO_FRAME_LENGTH 1486 +#define SYNTH_UPDATE_PERIOD_IN_BITS 8 + +#elif defined (_SAMPLE_RATE_48000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 256 +#define _OUTPUT_SAMPLE_RATE 48000 +#define AUDIO_FRAME_LENGTH 1365 +#define SYNTH_UPDATE_PERIOD_IN_BITS 8 + +#else +#error "_SAMPLE_RATE_XXXXX must be defined to valid rate" +#endif + +#endif /* #ifndef _EAS_AUDIOCONST_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorus.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorus.c new file mode 100755 index 0000000..4a2c8d0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorus.c @@ -0,0 +1,604 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorus.c + * + * Contents and purpose: + * Contains the implementation of the Chorus effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 499 $ + * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_effects.h" +#include "eas_math.h" +#include "eas_chorusdata.h" +#include "eas_chorus.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" + +/* prototypes for effects interface */ +static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); +static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); +static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + +/* common effects interface for configuration module */ +const S_EFFECTS_INTERFACE EAS_Chorus = +{ + ChorusInit, + ChorusProcess, + ChorusShutdown, + ChorusGetParam, + ChorusSetParam +}; + + + +//LFO shape table used by the chorus, larger table would sound better +//this is a sine wave, where 32767 = 1.0 +static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = { + 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170, + 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728, + 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329, + 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212, + 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519, + -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785, + -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621, + -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010, + -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608 +}; + +/*---------------------------------------------------------------------------- + * InitializeChorus() + *---------------------------------------------------------------------------- + * Purpose: Initializes chorus parameters + * + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) +{ + S_CHORUS_OBJECT *pChorusData; + S_CHORUS_PRESET *pPreset; + EAS_I32 index; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS); + + /* allocate dynamic memory */ + else + pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT)); + + if (pChorusData == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* clear the structure */ + EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT)); + + ChorusReadInPresets(pChorusData); + + /* set some default values */ + pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT; + pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT; + pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT; + pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT; + pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT; + + //chorus rate and depth need some massaging from preset value (which is sample rate independent) + + //convert rate from steps of .05 Hz to value which can be used as phase increment, + //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits + //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate; + //computing it as below allows rate steps to be evenly spaced + //uses 32 bit divide, but only once when new value is selected + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction + //want to compute ((depth * sampleRate)/20000) + //use the following approximation since 105/32 is roughly 65536/20000 + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + pChorusData->m_nLevel = pChorusData->m_nLevel; + + //zero delay memory for chorus + for (index = CHORUS_L_SIZE - 1; index >= 0; index--) + { + pChorusData->chorusDelayL[index] = 0; + } + for (index = CHORUS_R_SIZE - 1; index >= 0; index--) + { + pChorusData->chorusDelayR[index] = 0; + } + + //init delay line index, these are used to implement circular delay buffer + pChorusData->chorusIndexL = 0; + pChorusData->chorusIndexR = 0; + + //init LFO phase + //16 bit whole part, 16 bit fraction + pChorusData->lfoLPhase = 0; + pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase; + + //init chorus delay position + //right now chorus delay is a compile-time value, as is sample rate + pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000); + + //now copy from the new preset into Chorus + pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; + + pChorusData->m_nLevel = pPreset->m_nLevel; + pChorusData->m_nRate = pPreset->m_nRate; + pChorusData->m_nDepth = pPreset->m_nDepth; + + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + *pInstData = pChorusData; + + return EAS_SUCCESS; +} /* end ChorusInit */ + +/*---------------------------------------------------------------------------- + * WeightedTap() + *---------------------------------------------------------------------------- + * Purpose: Does fractional array look-up using linear interpolation + * + * first convert indexDesired to actual desired index by taking into account indexReference + * then do linear interpolation between two actual samples using fractional part + * + * Inputs: + * array: pointer to array of signed 16 bit values, typically either PCM data or control data + * indexReference: the circular buffer relative offset + * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) + * indexLimit: the total size of the array, used to compute buffer wrap + * + * Outputs: + * Value from the input array, linearly interpolated between two actual data values + * + *---------------------------------------------------------------------------- +*/ +static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit) +{ + EAS_I16 index; + EAS_I16 fraction; + EAS_I16 val1; + EAS_I16 val2; + + //separate indexDesired into whole and fractional parts + /*lint -e{704} use shift for performance */ + index = (EAS_I16)(indexDesired >> 16); + /*lint -e{704} use shift for performance */ + fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part + + //adjust whole part by indexReference + index = indexReference - index; + //make sure we stay within array bounds, this implements circular buffer + while (index < 0) + { + index += indexLimit; + } + + //get two adjacent values from the array + val1 = array[index]; + + //handle special case when index == 0, else typical case + if (index == 0) + { + val2 = array[indexLimit-1]; //get last value from array + } + else + { + val2 = array[index-1]; //get previous value from array + } + + //compute linear interpolation as (val1 + ((val2-val1)*fraction)) + return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction)); +} + +/*---------------------------------------------------------------------------- + * ChorusProcess() + *---------------------------------------------------------------------------- + * Purpose: compute the chorus on the input buffer, and mix into output buffer + * + * + * Inputs: + * src: pointer to input buffer of PCM values to be processed + * dst: pointer to output buffer of PCM values we are to sume the result with + * bufSize: the number of sample frames (i.e. stereo samples) in the buffer + * + * Outputs: + * None + * + *---------------------------------------------------------------------------- +*/ +//compute the chorus, and mix into output buffer +static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) +{ + EAS_I32 ix; + EAS_I32 nChannelNumber; + EAS_I16 lfoValueLeft; + EAS_I16 lfoValueRight; + EAS_I32 positionOffsetL; + EAS_I32 positionOffsetR; + EAS_PCM tapL; + EAS_PCM tapR; + EAS_I32 tempValue; + EAS_PCM nInputSample; + EAS_I32 nOutputSample; + EAS_PCM *pIn; + EAS_PCM *pOut; + + S_CHORUS_OBJECT *pChorusData; + + pChorusData = (S_CHORUS_OBJECT*) pInstData; + + //if the chorus is disabled or turned all the way down + if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0) + { + if (pSrc != pDst) + EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); + return; + } + + if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus) + { + ChorusUpdate(pChorusData); + } + + for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++) + { + + pIn = pSrc + nChannelNumber; + pOut = pDst + nChannelNumber; + + if(nChannelNumber==0) + { + for (ix = 0; ix < numSamples; ix++) + { + nInputSample = *pIn; + pIn += NUM_OUTPUT_CHANNELS; + + //feed input into chorus delay line + pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample; + + //compute chorus lfo value using phase as fractional index into chorus shape table + //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number + lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE); + + //scale chorus depth by lfo value to get relative fractional sample index + //index is expressed as 32 bit number with 16 bit fractional part + /*lint -e{703} use shift for performance */ + positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1); + + //add fixed chorus delay to get actual fractional sample index + positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16; + + //get tap value from chorus delay using fractional sample index + tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE); + + //scale by chorus level, then sum with input buffer contents and saturate + tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel); + nOutputSample = SATURATE(tempValue + nInputSample); + + *pOut = (EAS_I16)SATURATE(nOutputSample); + pOut += NUM_OUTPUT_CHANNELS; + + + //increment chorus delay index and make it wrap as needed + //this implements circular buffer + if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE) + pChorusData->chorusIndexL = 0; + + //increment fractional lfo phase, and make it wrap as needed + pChorusData->lfoLPhase += pChorusData->m_nRate; + while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16)) + { + pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16); + } + } + } + else + { + for (ix = 0; ix < numSamples; ix++) + { + nInputSample = *pIn; + pIn += NUM_OUTPUT_CHANNELS; + + //feed input into chorus delay line + pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample; + + //compute chorus lfo value using phase as fractional index into chorus shape table + //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number + lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE); + + //scale chorus depth by lfo value to get relative fractional sample index + //index is expressed as 32 bit number with 16 bit fractional part + /*lint -e{703} use shift for performance */ + positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1); + + //add fixed chorus delay to get actual fractional sample index + positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16; + + //get tap value from chorus delay using fractional sample index + tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE); + + //scale by chorus level, then sum with output buffer contents and saturate + tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel); + nOutputSample = SATURATE(tempValue + nInputSample); + + *pOut = (EAS_I16)SATURATE(nOutputSample); + pOut += NUM_OUTPUT_CHANNELS; + + //increment chorus delay index and make it wrap as needed + //this implements circular buffer + if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE) + pChorusData->chorusIndexR = 0; + + //increment fractional lfo phase, and make it wrap as needed + pChorusData->lfoRPhase += pChorusData->m_nRate; + while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16)) + { + pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16); + } + } + } + + } +} /* end ChorusProcess */ + + + +/*---------------------------------------------------------------------------- + * ChorusShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the Chorus effect. + * + * Inputs: + * pInstData - handle to instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) +{ + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pInstData); + return EAS_SUCCESS; +} /* end ChorusShutdown */ + +/*---------------------------------------------------------------------------- + * ChorusGetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Get a Chorus parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - pointer to variable to hold retrieved value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_CHORUS_OBJECT *p; + + p = (S_CHORUS_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_CHORUS_BYPASS: + *pValue = (EAS_I32) p->bypass; + break; + case EAS_PARAM_CHORUS_PRESET: + *pValue = (EAS_I8) p->m_nCurrentChorus; + break; + case EAS_PARAM_CHORUS_RATE: + *pValue = (EAS_I32) p->m_nRate; + break; + case EAS_PARAM_CHORUS_DEPTH: + *pValue = (EAS_I32) p->m_nDepth; + break; + case EAS_PARAM_CHORUS_LEVEL: + *pValue = (EAS_I32) p->m_nLevel; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ChorusGetParam */ + + +/*---------------------------------------------------------------------------- + * ChorusSetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Set a Chorus parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - new paramter value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_CHORUS_OBJECT *p; + + p = (S_CHORUS_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_CHORUS_BYPASS: + p->bypass = (EAS_BOOL) value; + break; + case EAS_PARAM_CHORUS_PRESET: + if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 && + value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nNextChorus = (EAS_I8)value; + break; + case EAS_PARAM_CHORUS_RATE: + if(valueEAS_CHORUS_RATE_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nRate = (EAS_I16) value; + break; + case EAS_PARAM_CHORUS_DEPTH: + if(valueEAS_CHORUS_DEPTH_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nDepth = (EAS_I16) value; + break; + case EAS_PARAM_CHORUS_LEVEL: + if(valueEAS_CHORUS_LEVEL_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nLevel = (EAS_I16) value; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ChorusSetParam */ + + +/*---------------------------------------------------------------------------- + * ChorusReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global Chorus preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData) +{ + + int preset = 0; + int defaultPreset = 0; + + //now init any remaining presets to defaults + for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++) + { + S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset]; + if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1) + { + pPreset->m_nDepth = 39; + pPreset->m_nRate = 30; + pPreset->m_nLevel = 32767; + } + else if (defaultPreset == 1) + { + pPreset->m_nDepth = 21; + pPreset->m_nRate = 45; + pPreset->m_nLevel = 25000; + } + else if (defaultPreset == 2) + { + pPreset->m_nDepth = 53; + pPreset->m_nRate = 25; + pPreset->m_nLevel = 32000; + } + else if (defaultPreset == 3) + { + pPreset->m_nDepth = 32; + pPreset->m_nRate = 37; + pPreset->m_nLevel = 29000; + } + } + + return EAS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + * ChorusUpdate + *---------------------------------------------------------------------------- + * Purpose: + * Update the Chorus preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - chorus paramters will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData) +{ + S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; + + pChorusData->m_nLevel = pPreset->m_nLevel; + pChorusData->m_nRate = pPreset->m_nRate; + pChorusData->m_nDepth = pPreset->m_nDepth; + + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus; + + return EAS_SUCCESS; + +} /* end ChorusUpdate */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorusdata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorusdata.c new file mode 100755 index 0000000..ec71ff8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorusdata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorusdata.c + * + * Contents and purpose: + * Contains the static data allocation for the Chorus effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_chorusdata.h" + +S_CHORUS_OBJECT eas_ChorusData; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorusdata.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorusdata.h new file mode 100755 index 0000000..ec8daa4 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_chorusdata.h @@ -0,0 +1,160 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorusdata.h + * + * Contents and purpose: + * Contains the prototypes for the Chorus effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 309 $ + * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_CHORUS_H +#define _EAS_CHORUS_H + +#include "eas_types.h" +#include "eas_audioconst.h" + +//defines for chorus + +#define EAS_CHORUS_BYPASS_DEFAULT 1 +#define EAS_CHORUS_PRESET_DEFAULT 0 +#define EAS_CHORUS_RATE_DEFAULT 30 +#define EAS_CHORUS_DEPTH_DEFAULT 39 +#define EAS_CHORUS_LEVEL_DEFAULT 32767 + +#define EAS_CHORUS_LEVEL_MIN 0 +#define EAS_CHORUS_LEVEL_MAX 32767 + +#define EAS_CHORUS_RATE_MIN 10 +#define EAS_CHORUS_RATE_MAX 50 + +#define EAS_CHORUS_DEPTH_MIN 15 +#define EAS_CHORUS_DEPTH_MAX 60 + +#define CHORUS_SIZE_MS 20 +#define CHORUS_L_SIZE ((CHORUS_SIZE_MS*_OUTPUT_SAMPLE_RATE)/1000) +#define CHORUS_R_SIZE CHORUS_L_SIZE +#define CHORUS_SHAPE_SIZE 128 +#define CHORUS_DELAY_MS 10 + +#define CHORUS_MAX_TYPE 4 // any Chorus numbers larger than this are invalid + +typedef struct +{ + EAS_I16 m_nRate; + EAS_I16 m_nDepth; + EAS_I16 m_nLevel; + +} S_CHORUS_PRESET; + +typedef struct +{ + S_CHORUS_PRESET m_sPreset[CHORUS_MAX_TYPE]; //array of presets + +} S_CHORUS_PRESET_BANK; + +/* parameters for each Chorus */ +typedef struct +{ + EAS_I32 lfoLPhase; + EAS_I32 lfoRPhase; + EAS_I16 chorusIndexL; + EAS_I16 chorusIndexR; + EAS_U16 chorusTapPosition; + + EAS_I16 m_nRate; + EAS_I16 m_nDepth; + EAS_I16 m_nLevel; + + //delay lines used by the chorus, longer would sound better + EAS_PCM chorusDelayL[CHORUS_L_SIZE]; + EAS_PCM chorusDelayR[CHORUS_R_SIZE]; + + EAS_BOOL bypass; + EAS_I8 preset; + + EAS_I16 m_nCurrentChorus; // preset number for current Chorus + EAS_I16 m_nNextChorus; // preset number for next Chorus + + S_CHORUS_PRESET pPreset; + + S_CHORUS_PRESET_BANK m_sPreset; + +} S_CHORUS_OBJECT; + + +/*---------------------------------------------------------------------------- + * WeightedTap() + *---------------------------------------------------------------------------- + * Purpose: Does fractional array look-up using linear interpolation + * + * first convert indexDesired to actual desired index by taking into account indexReference + * then do linear interpolation between two actual samples using fractional part + * + * Inputs: + * array: pointer to array of signed 16 bit values, typically either PCM data or control data + * indexReference: the circular buffer relative offset + * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) + * indexLimit: the total size of the array, used to compute buffer wrap + * + * Outputs: + * Value from the input array, linearly interpolated between two actual data values + * + *---------------------------------------------------------------------------- +*/ +static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit); + +/*---------------------------------------------------------------------------- + * ChorusReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global Chorus preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData); + +/*---------------------------------------------------------------------------- + * ChorusUpdate + *---------------------------------------------------------------------------- + * Purpose: + * Update the Chorus preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - chorus paramters will be changed + * - m_nCurrentChorus := m_nNextChorus + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT* pChorusData); + +#endif /* #ifndef _EAS_CHORUSDATA_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ctype.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ctype.h new file mode 100755 index 0000000..14fa96f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ctype.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ctype.h + * + * Contents and purpose: + * This is a replacement for the CRT ctype.h functions. These + * functions are currently ASCII only, but eventually, we will want + * to support wide-characters for localization. + * + * Copyright (c) 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 429 $ + * $Date: 2006-10-19 23:50:15 -0700 (Thu, 19 Oct 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_CTYPE_H +#define _EAS_CTYPE_H + +EAS_INLINE EAS_I8 IsDigit (EAS_I8 c) { return ((c >= '0') && (c <= '9')); } +EAS_INLINE EAS_I8 IsSpace (EAS_I8 c) { return (((c >= 9) && (c <= 13)) || (c == ' ')); } +EAS_INLINE EAS_I8 ToUpper (EAS_I8 c) { if ((c >= 'a') && (c <= 'z')) return c & ~0x20; else return c; } +EAS_INLINE EAS_I8 ToLower (EAS_I8 c) { if ((c >= 'A') && (c <= 'Z')) return c |= 0x20; else return c; } + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_data.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_data.c new file mode 100755 index 0000000..31a4e6a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_data.c @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_data.c + * + * Contents and purpose: + * Contains a data allocation for synthesizer + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" + +// globals +S_EAS_DATA eas_Data; +S_VOICE_MGR eas_Synth; +S_SYNTH eas_MIDI; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_data.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_data.h new file mode 100755 index 0000000..e2fcb1a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_data.h @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_data.h + * + * Contents and purpose: + * This header defines all types, to support dynamic allocation of the + * memory resources needed for persistent EAS data. + * + * Copyright 2004 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 842 $ + * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_DATA_H +#define _EAS_DATA_H + +#include "eas_types.h" +#include "eas_synthcfg.h" +#include "eas.h" +#include "eas_audioconst.h" +#include "eas_sndlib.h" +#include "eas_pcm.h" +#include "eas_pcmdata.h" +#include "eas_synth.h" +#include "eas_miditypes.h" +#include "eas_effects.h" + +#ifdef AUX_MIXER +#include "eas_auxmixdata.h" +#endif + +#ifdef JET_INTERFACE +#include "jet.h" +#endif + +#ifdef _METRICS_ENABLED +#include "eas_perf.h" +#endif + +#ifndef MAX_NUMBER_STREAMS +#define MAX_NUMBER_STREAMS 4 +#endif + +/* flags for S_EAS_STREAM */ +#define STREAM_FLAGS_PARSED 1 +#define STREAM_FLAGS_PAUSE 2 +#define STREAM_FLAGS_LOCATE 4 +#define STREAM_FLAGS_RESUME 8 + +/* structure for parsing a stream */ +typedef struct s_eas_stream_tag +{ + void *pParserModule; + EAS_U32 time; + EAS_U32 frameLength; + EAS_I32 repeatCount; + EAS_VOID_PTR handle; + EAS_U8 volume; + EAS_BOOL8 streamFlags; +} S_EAS_STREAM; + +/* default master volume is -10dB */ +#define DEFAULT_VOLUME 90 +#define DEFAULT_STREAM_VOLUME 100 +#define DEFAULT_STREAM_GAIN 14622 + +/* 10 dB of boost available for individual parsers */ +#define STREAM_VOLUME_HEADROOM 10 + +/* amalgamated persistent data type */ +typedef struct s_eas_data_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; +#endif + EAS_HW_DATA_HANDLE hwInstData; + + S_EFFECTS_MODULE effectsModules[NUM_EFFECTS_MODULES]; + +#ifdef _METRICS_ENABLED + S_METRICS_INTERFACE *pMetricsModule; + EAS_VOID_PTR pMetricsData; +#endif + + EAS_I32 *pMixBuffer; + EAS_PCM *pOutputAudioBuffer; + +#ifdef AUX_MIXER + S_EAS_AUX_MIXER auxMixer; +#endif + +#ifdef _MAXIMIZER_ENABLED + EAS_VOID_PTR pMaximizerData; +#endif + + S_EAS_STREAM streams[MAX_NUMBER_STREAMS]; + + S_PCM_STATE *pPCMStreams; + + S_VOICE_MGR *pVoiceMgr; + +#ifdef JET_INTERFACE + JET_DATA_HANDLE jetHandle; +#endif + + EAS_U32 renderTime; + EAS_I16 masterGain; + EAS_U8 masterVolume; + EAS_BOOL8 staticMemoryModel; + EAS_BOOL8 searchHeaderFlag; +} S_EAS_DATA; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_effects.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_effects.h new file mode 100755 index 0000000..86dedac --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_effects.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_effects.h + * + * Contents and purpose: + * Defines a generic effects interface. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_EFFECTS_H +#define _EAS_EFFECTS_H + +#include "eas_types.h" + +typedef struct +{ + EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); + void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_PCM *in, EAS_PCM *out, EAS_I32 numSamples); + EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +} S_EFFECTS_INTERFACE; + +typedef struct +{ + EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); + void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_I32 *in, EAS_I32 *out, EAS_I32 numSamples); + EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +} S_EFFECTS32_INTERFACE; + +/* mixer instance data */ +typedef struct +{ + S_EFFECTS_INTERFACE *effect; + EAS_VOID_PTR effectData; +} S_EFFECTS_MODULE; + +#endif /* end _EAS_EFFECTS_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmengine.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmengine.c new file mode 100755 index 0000000..ea7f69c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmengine.c @@ -0,0 +1,785 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_fmengine.c + * + * Contents and purpose: + * Implements the low-level FM synthesizer functions. + * + * Copyright Sonic Network Inc. 2004, 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* includes */ +#include "eas_types.h" +#include "eas_math.h" +#include "eas_audioconst.h" +#include "eas_fmengine.h" + +#if defined(EAS_FM_SYNTH) || defined(EAS_HYBRID_SYNTH) || defined(EAS_SPLIT_HYBRID_SYNTH) || defined(EAS_SPLIT_FM_SYNTH) +#include "eas_data.h" +#endif + +/* externals */ +extern const EAS_I16 sineTable[]; +extern const EAS_U8 fmScaleTable[16]; + +// saturation constants for 32-bit to 16-bit conversion +#define _EAS_MAX_OUTPUT 32767 +#define _EAS_MIN_OUTPUT -32767 + +static S_FM_ENG_VOICE voices[NUM_FM_VOICES]; + +/* local prototypes */ +void FM_SynthMixVoice (S_FM_ENG_VOICE *p, EAS_U16 gainTarget, EAS_I32 numSamplesToAdd, EAS_PCM *pInputBuffer, EAS_I32 *pBuffer); + +/* used in development environment */ +#if defined(_SATURATION_MONITOR) +static EAS_BOOL bSaturated = EAS_FALSE; + +/*---------------------------------------------------------------------------- + * FM_CheckSaturation() + *---------------------------------------------------------------------------- + * Purpose: + * Allows the sound development tool to check for saturation at the voice + * level. Useful for tuning the level controls. + * + * Inputs: + * + * Outputs: + * Returns true if saturation has occurred since the last time the function + * was called. + * + * Side Effects: + * Resets the saturation flag + *---------------------------------------------------------------------------- +*/ +EAS_BOOL FM_CheckSaturation () +{ + EAS_BOOL bTemp; + bTemp = bSaturated; + bSaturated = EAS_FALSE; + return bTemp; +} +#endif + +/*---------------------------------------------------------------------------- + * FM_Saturate() + *---------------------------------------------------------------------------- + * Purpose: + * This inline function saturates a 32-bit number to 16-bits + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Returns a 16-bit integer + *---------------------------------------------------------------------------- +*/ +EAS_INLINE EAS_I16 FM_Saturate (EAS_I32 nValue) +{ + if (nValue > _EAS_MAX_OUTPUT) + { +#if defined(_SATURATION_MONITOR) + bSaturated = EAS_TRUE; +#endif + return _EAS_MAX_OUTPUT; + } + if (nValue < _EAS_MIN_OUTPUT) + { +#if defined(_SATURATION_MONITOR) + bSaturated = EAS_TRUE; +#endif + return _EAS_MIN_OUTPUT; + } + return (EAS_I16) nValue; +} + +/*---------------------------------------------------------------------------- + * FM_Noise() + *---------------------------------------------------------------------------- + * Purpose: + * A 31-bit low-cost linear congruential PRNG algorithm used to + * generate noise. + * + * Inputs: + * pnSeed - pointer to 32-bit PRNG seed + * + * Outputs: + * Returns a 16-bit integer + *---------------------------------------------------------------------------- +*/ +EAS_INLINE EAS_I16 FM_Noise (EAS_U32 *pnSeed) +{ + *pnSeed = *pnSeed * 214013L + 2531011L; + return (EAS_I16) ((*pnSeed >> 15) & 0xffff); +} + +/*---------------------------------------------------------------------------- + * FM_PhaseInc() + *---------------------------------------------------------------------------- + * Purpose: + * Transform pitch cents to linear phase increment + * + * Inputs: + * nCents - measured in cents + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_I32 FM_PhaseInc (EAS_I32 nCents) +{ + EAS_I32 nDents; + EAS_I32 nExponentInt, nExponentFrac; + EAS_I32 nTemp1, nTemp2; + EAS_I32 nResult; + + /* convert cents to dents */ + nDents = FMUL_15x15(nCents, CENTS_TO_DENTS); + nExponentInt = GET_DENTS_INT_PART(nDents) + (32 - SINE_TABLE_SIZE_IN_BITS - NUM_EG1_FRAC_BITS); + nExponentFrac = GET_DENTS_FRAC_PART(nDents); + + /* implement 2^(fracPart) as a power series */ + nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3); + nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1); + nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2); + + /* + implement 2^(intPart) as + a left shift for intPart >= 0 or + a left shift for intPart < 0 + */ + if (nExponentInt >= 0) + { + /* left shift for positive exponents */ + /*lint -e{703} */ + nResult = nTemp1 << nExponentInt; + } + else + { + /* right shift for negative exponents */ + nExponentInt = -nExponentInt; + nResult = nTemp1 >> nExponentInt; + } + + return nResult; +} + +#if (NUM_OUTPUT_CHANNELS == 2) +/*---------------------------------------------------------------------------- + * FM_CalculatePan() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the left and right gain values corresponding to the given pan value. + * + * Inputs: + * psVoice - ptr to the voice we have assigned for this channel + * psArticulation - ptr to this voice's articulation + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * the given voice's m_nGainLeft and m_nGainRight are assigned + *---------------------------------------------------------------------------- +*/ +static void FM_CalculatePan (EAS_I16 pan, EAS_U16 *pGainLeft, EAS_U16 *pGainRight) +{ + EAS_I32 nTemp; + EAS_INT nNetAngle; + + /* + Implement the following + sin(x) = (2-4*c)*x^2 + c + x + cos(x) = (2-4*c)*x^2 + c - x + + where c = 1/sqrt(2) + using the a0 + x*(a1 + x*a2) approach + */ + + /* + Get the Midi CC10 pan value for this voice's channel + convert the pan value to an "angle" representation suitable for + our sin, cos calculator. This representation is NOT necessarily the same + as the transform in the GM manuals because of our sin, cos calculator. + "angle" = (CC10 - 64)/128 + */ + /*lint -e{703} */ + nNetAngle = ((EAS_I32) pan) << (NUM_EG1_FRAC_BITS -7); + + /* calculate sin */ + nTemp = EG1_ONE + FMUL_15x15(COEFF_PAN_G2, nNetAngle); + nTemp = COEFF_PAN_G0 + FMUL_15x15(nTemp, nNetAngle); + + if (nTemp > SYNTH_FULL_SCALE_EG1_GAIN) + nTemp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (nTemp < 0) + nTemp = 0; + + *pGainRight = (EAS_U16) nTemp; + + /* calculate cos */ + nTemp = -EG1_ONE + FMUL_15x15(COEFF_PAN_G2, nNetAngle); + nTemp = COEFF_PAN_G0 + FMUL_15x15(nTemp, nNetAngle); + + if (nTemp > SYNTH_FULL_SCALE_EG1_GAIN) + nTemp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (nTemp < 0) + nTemp = 0; + + *pGainLeft = (EAS_U16) nTemp; +} +#endif /* #if (NUM_OUTPUT_CHANNELS == 2) */ + +/*---------------------------------------------------------------------------- + * FM_Operator() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesizes a buffer of samples based on passed parameters. + * + * Inputs: + * nNumSamplesToAdd - number of samples to synthesize + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void FM_Operator ( + S_FM_ENG_OPER *p, + EAS_I32 numSamplesToAdd, + EAS_PCM *pBuffer, + EAS_PCM *pModBuffer, + EAS_BOOL mix, + EAS_U16 gainTarget, + EAS_I16 pitch, + EAS_U8 feedback, + EAS_I16 *pLastOutput) +{ + EAS_I32 gain; + EAS_I32 gainInc; + EAS_U32 phase; + EAS_U32 phaseInc; + EAS_U32 phaseTemp; + EAS_I32 temp; + EAS_I32 temp2; + + /* establish local gain variable */ + gain = (EAS_I32) p->gain << 16; + + /* calculate gain increment */ + /*lint -e{703} use shift for performance */ + gainInc = ((EAS_I32) gainTarget - (EAS_I32) p->gain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + + /* establish local phase variables */ + phase = p->phase; + + /* calculate the new phase increment */ + phaseInc = (EAS_U32) FM_PhaseInc(pitch); + + /* restore final output from previous frame for feedback loop */ + if (pLastOutput) + temp = *pLastOutput; + else + temp = 0; + + /* generate a buffer of samples */ + while (numSamplesToAdd--) + { + + /* incorporate modulation */ + if (pModBuffer) + { + /*lint -e{701} use shift for performance */ + temp = *pModBuffer++ << FM_MODULATOR_INPUT_SHIFT; + } + + /* incorporate feedback */ + else + { + /*lint -e{703} use shift for performance */ + temp = (temp * (EAS_I32) feedback) << FM_FEEDBACK_SHIFT; + } + + /*lint -e{737} */ + phaseTemp = phase + temp; + + /* fetch sample from wavetable */ + temp = sineTable[phaseTemp >> (32 - SINE_TABLE_SIZE_IN_BITS)]; + + /* increment operator phase */ + phase += phaseInc; + + /* internal gain for modulation effects */ + temp = FMUL_15x15(temp, (gain >> 16)); + + /* output gain calculation */ + temp2 = FMUL_15x15(temp, p->outputGain); + + /* saturating add to buffer */ + if (mix) + { + temp2 += *pBuffer; + *pBuffer++ = FM_Saturate(temp2); + } + + /* output to buffer */ + else + *pBuffer++ = (EAS_I16) temp2; + + /* increment gain */ + gain += gainInc; + + } + + /* save phase and gain */ + p->phase = phase; + p->gain = gainTarget; + + /* save last output for feedback in next frame */ + if (pLastOutput) + *pLastOutput = (EAS_I16) temp; +} + +/*---------------------------------------------------------------------------- + * FM_NoiseOperator() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesizes a buffer of samples based on passed parameters. + * + * Inputs: + * nNumSamplesToAdd - number of samples to synthesize + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void FM_NoiseOperator ( + S_FM_ENG_OPER *p, + EAS_I32 numSamplesToAdd, + EAS_PCM *pBuffer, + EAS_BOOL mix, + EAS_U16 gainTarget, + EAS_U8 feedback, + EAS_I16 *pLastOutput) +{ + EAS_I32 gain; + EAS_I32 gainInc; + EAS_U32 phase; + EAS_I32 temp; + EAS_I32 temp2; + + /* establish local gain variable */ + gain = (EAS_I32) p->gain << 16; + + /* calculate gain increment */ + /*lint -e{703} use shift for performance */ + gainInc = ((EAS_I32) gainTarget - (EAS_I32) p->gain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + + /* establish local phase variables */ + phase = p->phase; + + /* establish local phase variables */ + phase = p->phase; + + /* recall last sample for filter Z-1 term */ + temp = 0; + if (pLastOutput) + temp = *pLastOutput; + + /* generate a buffer of samples */ + while (numSamplesToAdd--) + { + + /* if using filter */ + if (pLastOutput) + { + /* use PRNG for noise */ + temp2 = FM_Noise(&phase); + + /*lint -e{704} use shift for performance */ + temp += ((temp2 -temp) * feedback) >> 8; + } + else + { + temp = FM_Noise(&phase); + } + + /* internal gain for modulation effects */ + temp2 = FMUL_15x15(temp, (gain >> 16)); + + /* output gain calculation */ + temp2 = FMUL_15x15(temp2, p->outputGain); + + /* saturating add to buffer */ + if (mix) + { + temp2 += *pBuffer; + *pBuffer++ = FM_Saturate(temp2); + } + + /* output to buffer */ + else + *pBuffer++ = (EAS_I16) temp2; + + /* increment gain */ + gain += gainInc; + + } + + /* save phase and gain */ + p->phase = phase; + p->gain = gainTarget; + + /* save last output for feedback in next frame */ + if (pLastOutput) + *pLastOutput = (EAS_I16) temp; +} + +/*---------------------------------------------------------------------------- + * FM_ConfigVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Receives parameters to start a new voice. + * + * Inputs: + * voiceNum - voice number to start + * vCfg - configuration data + * pMixBuffer - pointer to host supplied buffer + * + * Outputs: + * + * Side Effects: + * + * Notes: + * pFrameBuffer is not used in the test version, but is passed as a + * courtesy to split architecture implementations. It can be used as + * as pointer to the interprocessor communications buffer when the + * synthesis parameters are passed off to a DSP for synthesis. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pFrameBuffer) pFrameBuffer not used in test version - see above */ +void FM_ConfigVoice (EAS_I32 voiceNum, S_FM_VOICE_CONFIG *vCfg, EAS_FRAME_BUFFER_HANDLE pFrameBuffer) +{ + S_FM_ENG_VOICE *pVoice; + EAS_INT i; + + /* establish pointer to voice data */ + pVoice = &voices[voiceNum]; + + /* save data */ + pVoice->feedback = vCfg->feedback; + pVoice->flags = vCfg->flags; + pVoice->voiceGain = vCfg->voiceGain; + + /* initialize Z-1 terms */ + pVoice->op1Out = 0; + pVoice->op3Out = 0; + + /* initialize operators */ + for (i = 0; i < 4; i++) + { + /* save operator data */ + pVoice->oper[i].gain = vCfg->gain[i]; + pVoice->oper[i].outputGain = vCfg->outputGain[i]; + pVoice->oper[i].outputGain = vCfg->outputGain[i]; + + /* initalize operator */ + pVoice->oper[i].phase = 0; + } + + /* calculate pan */ +#if NUM_OUTPUT_CHANNELS == 2 + FM_CalculatePan(vCfg->pan, &pVoice->gainLeft, &pVoice->gainRight); +#endif +} + +/*---------------------------------------------------------------------------- + * FM_ProcessVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesizes a buffer of samples based on calculated parameters. + * + * Inputs: + * nNumSamplesToAdd - number of samples to synthesize + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + * Notes: + * pOut is not used in the test version, but is passed as a + * courtesy to split architecture implementations. It can be used as + * as pointer to the interprocessor communications buffer when the + * synthesis parameters are passed off to a DSP for synthesis. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pOut) pOut not used in test version - see above */ +void FM_ProcessVoice ( + EAS_I32 voiceNum, + S_FM_VOICE_FRAME *pFrame, + EAS_I32 numSamplesToAdd, + EAS_PCM *pTempBuffer, + EAS_PCM *pBuffer, + EAS_I32 *pMixBuffer, + EAS_FRAME_BUFFER_HANDLE pFrameBuffer) +{ + S_FM_ENG_VOICE *p; + EAS_PCM *pOutBuf; + EAS_PCM *pMod; + EAS_BOOL mix; + EAS_U8 feedback1; + EAS_U8 feedback3; + EAS_U8 mode; + + /* establish pointer to voice data */ + p = &voices[voiceNum]; + mode = p->flags & 0x07; + + /* lookup feedback values */ + feedback1 = fmScaleTable[p->feedback >> 4]; + feedback3 = fmScaleTable[p->feedback & 0x0f]; + + /* operator 3 is on output bus in modes 0, 1, and 3 */ + if ((mode == 0) || (mode == 1) || (mode == 3)) + pOutBuf = pBuffer; + else + pOutBuf = pTempBuffer; + + if (p->flags & FLAG_FM_ENG_VOICE_OP3_NOISE) + { + FM_NoiseOperator( + p->oper + 2, + numSamplesToAdd, + pOutBuf, + EAS_FALSE, + pFrame->gain[2], + feedback3, + &p->op3Out); + } + else + { + FM_Operator( + p->oper + 2, + numSamplesToAdd, + pOutBuf, + 0, + EAS_FALSE, + pFrame->gain[2], + pFrame->pitch[2], + feedback3, + &p->op3Out); + } + + /* operator 4 is on output bus in modes 0, 1, and 2 */ + if (mode < 3) + pOutBuf = pBuffer; + else + pOutBuf = pTempBuffer; + + /* operator 4 is modulated in modes 2, 4, and 5 */ + if ((mode == 2) || (mode == 4) || (mode == 5)) + pMod = pTempBuffer; + else + pMod = 0; + + /* operator 4 is in mix mode in modes 0 and 1 */ + mix = (mode < 2); + + if (p->flags & FLAG_FM_ENG_VOICE_OP4_NOISE) + { + FM_NoiseOperator( + p->oper + 3, + numSamplesToAdd, + pOutBuf, + mix, + pFrame->gain[3], + 0, + 0); + } + else + { + FM_Operator( + p->oper + 3, + numSamplesToAdd, + pOutBuf, + pMod, + mix, + pFrame->gain[3], + pFrame->pitch[3], + 0, + 0); + } + + /* operator 1 is on output bus in mode 0 */ + if (mode == 0) + pOutBuf = pBuffer; + else + pOutBuf = pTempBuffer; + + /* operator 1 is modulated in modes 3 and 4 */ + if ((mode == 3) || (mode == 4)) + pMod = pTempBuffer; + else + pMod = 0; + + /* operator 1 is in mix mode in modes 0 and 5 */ + mix = ((mode == 0) || (mode == 5)); + + if (p->flags & FLAG_FM_ENG_VOICE_OP1_NOISE) + { + FM_NoiseOperator( + p->oper, + numSamplesToAdd, + pOutBuf, + mix, + pFrame->gain[0], + feedback1, + &p->op1Out); + } + else + { + FM_Operator( + p->oper, + numSamplesToAdd, + pOutBuf, + pMod, + mix, + pFrame->gain[0], + pFrame->pitch[0], + feedback1, + &p->op1Out); + } + + /* operator 2 is modulated in all modes except 0 */ + if (mode != 0) + pMod = pTempBuffer; + else + pMod = 0; + + /* operator 1 is in mix mode in modes 0 -3 */ + mix = (mode < 4); + + if (p->flags & FLAG_FM_ENG_VOICE_OP2_NOISE) + { + FM_NoiseOperator( + p->oper + 1, + numSamplesToAdd, + pBuffer, + mix, + pFrame->gain[1], + 0, + 0); + } + else + { + FM_Operator( + p->oper + 1, + numSamplesToAdd, + pBuffer, + pMod, + mix, + pFrame->gain[1], + pFrame->pitch[1], + 0, + 0); + } + + /* mix voice output to synthesizer output buffer */ + FM_SynthMixVoice(p, pFrame->voiceGain, numSamplesToAdd, pBuffer, pMixBuffer); +} + +/*---------------------------------------------------------------------------- + * FM_SynthMixVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Mixes the voice output buffer into the final mix using an anti-zipper + * filter. + * + * Inputs: + * nNumSamplesToAdd - number of samples to synthesize + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void FM_SynthMixVoice(S_FM_ENG_VOICE *p, EAS_U16 nGainTarget, EAS_I32 numSamplesToAdd, EAS_PCM *pInputBuffer, EAS_I32 *pBuffer) +{ + EAS_I32 nGain; + EAS_I32 nGainInc; + EAS_I32 nTemp; + + /* restore previous gain */ + /*lint -e{703} */ + nGain = (EAS_I32) p->voiceGain << 16; + + /* calculate gain increment */ + /*lint -e{703} */ + nGainInc = ((EAS_I32) nGainTarget - (EAS_I32) p->voiceGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + + /* mix the output buffer */ + while (numSamplesToAdd--) + { + /* output gain calculation */ + nTemp = *pInputBuffer++; + + /* sum to output buffer */ +#if (NUM_OUTPUT_CHANNELS == 2) + + /*lint -e{704} */ + nTemp = ((EAS_I32) nTemp * (nGain >> 16)) >> FM_GAIN_SHIFT; + + /*lint -e{704} */ + { + EAS_I32 nTemp2; + nTemp = nTemp >> FM_STEREO_PRE_GAIN_SHIFT; + nTemp2 = (nTemp * p->gainLeft) >> FM_STEREO_POST_GAIN_SHIFT; + *pBuffer++ += nTemp2; + nTemp2 = (nTemp * p->gainRight) >> FM_STEREO_POST_GAIN_SHIFT; + *pBuffer++ += nTemp2; + } +#else + /*lint -e{704} */ + nTemp = ((EAS_I32) nTemp * (nGain >> 16)) >> FM_MONO_GAIN_SHIFT; + *pBuffer++ += nTemp; +#endif + + /* increment gain for anti-zipper filter */ + nGain += nGainInc; + } + + /* save gain */ + p->voiceGain = nGainTarget; +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmengine.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmengine.h new file mode 100755 index 0000000..dd248f8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmengine.h @@ -0,0 +1,121 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_fmengine.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for FM synthesize low-level. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 664 $ + * $Date: 2007-04-25 13:11:22 -0700 (Wed, 25 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* sentinel */ +#ifndef _FMENGINE_H +#define _FMENGINE_H + +/* check for split architecture */ +#if defined (EAS_SPLIT_HYBRID_SYNTH) || defined(EAS_SPLIT_FM_SYNTH) +#define FM_OFFBOARD +#endif + +/* output level to mix buffer (3 = -24dB) */ +#define FM_GAIN_SHIFT 3 +#define FM_MONO_GAIN_SHIFT 9 + +/* voice output level for stereo 15 = +6dB */ +#define FM_STEREO_PRE_GAIN_SHIFT 11 +#define FM_STEREO_POST_GAIN_SHIFT 10 + +/* modulator input level shift (21 = -30dB) */ +#define FM_MODULATOR_INPUT_SHIFT 21 + +/* feedback control level shift (7 = 0dB) */ +#define FM_FEEDBACK_SHIFT 7 + +/* synth final output level */ +#define SYNTH_POST_GAIN_SHIFT 14 + +/* LFO modulation to gain control */ +#define FM_LFO_GAIN_SHIFT 12 + +/* sine table is always a power of 2 - saves cycles in inner loop */ +#define SINE_TABLE_SIZE_IN_BITS 11 +#define SINE_TABLE_SIZE 2048 + +/* operator structure for FM engine */ +typedef struct +{ + EAS_U32 phase; /* current waveform phase */ + EAS_U16 gain; /* current internal gain */ + EAS_U16 outputGain; /* current output gain */ +} S_FM_ENG_OPER; + +typedef struct +{ + S_FM_ENG_OPER oper[4]; /* operator data */ + EAS_I16 op1Out; /* op1 output for feedback loop */ + EAS_I16 op3Out; /* op3 output for feedback loop */ + EAS_U16 voiceGain; /* LFO + channel parameters */ +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_U16 gainLeft; /* left gain multiplier */ + EAS_U16 gainRight; /* right gain multiplier */ +#endif + EAS_U8 flags; /* mode bits and noise waveform flags */ + EAS_U8 feedback; /* feedback for Op1 and Op3 */ +} S_FM_ENG_VOICE; + +typedef struct +{ + EAS_U16 gain[4]; /* initial operator gain value */ + EAS_U16 outputGain[4]; /* initial operator output gain value */ + EAS_U16 voiceGain; /* initial voice gain */ + EAS_U8 flags; /* mode bits and noise waveform flags */ + EAS_U8 feedback; /* feedback for Op1 and Op3 */ +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I8 pan; /* pan value +/-64 */ +#endif +} S_FM_VOICE_CONFIG; + +typedef struct +{ + EAS_U16 gain[4]; /* new operator gain value */ + EAS_I16 pitch[4]; /* new pitch value */ + EAS_U16 voiceGain; /* new voice gain */ +} S_FM_VOICE_FRAME; + +/* bit definitions for S_FM_ENG_VOICE.flags */ +#define FLAG_FM_ENG_VOICE_OP1_NOISE 0x10 /* operator 1 source is PRNG */ +#define FLAG_FM_ENG_VOICE_OP2_NOISE 0x20 /* operator 2 source is PRNG */ +#define FLAG_FM_ENG_VOICE_OP3_NOISE 0x40 /* operator 3 source is PRNG */ +#define FLAG_FM_ENG_VOICE_OP4_NOISE 0x80 /* operator 4 source is PRNG */ + +#ifdef FM_OFFBOARD +extern EAS_BOOL FM_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +extern EAS_BOOL FM_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffe, EAS_I32 *pMixBuffer, EAS_I16 masterGain); +#endif + +/* FM engine prototypes */ +extern void FM_ConfigVoice (EAS_I32 voiceNum, S_FM_VOICE_CONFIG *vCfg, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +extern void FM_ProcessVoice (EAS_I32 voiceNum, S_FM_VOICE_FRAME *pFrame, EAS_I32 numSamplesToAdd, EAS_PCM *pTempBuffer, EAS_PCM *pBuffer, EAS_I32 *pMixBuffer, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); + +#endif +/* #ifndef _FMENGINE_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsndlib.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsndlib.c new file mode 100755 index 0000000..dcde967 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsndlib.c @@ -0,0 +1,1674 @@ +/******************************************************************** + * + * fmsndlib.c + * + * (c) Copyright 2005 Sonic Network, Inc. All Rights Reserved + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Source: C:\Sonic\Source\Gen3.3\FMSynth\GMdblib-3.fml + ********************************************************************/ + + +#include "eas_data.h" + +/* begin region data */ +/*lint -e{651} lint complains about unnecessary brackets */ +const S_FM_REGION regions[] = +{ + + /* Region 0 */ + { + 0x8005, 0, 127, 0, 255, 8, 0, + 514, 239, 47, 97, 0, 184, 3, + 1, 244, 89, 114, 0, 248, 2, + 3370, 244, 49, 76, 40, 192, 2, + -1, 227, 97, 51, 160, 212, 2 + }, + + /* Region 1 */ + { + 0x8005, 0, 127, 160, 255, 8, 0, + 2514, 223, 95, 72, 0, 176, 3, + 1, 244, 73, 145, 0, 244, 2, + 3600, 245, 81, 198, 40, 192, 2, + 3, 246, 81, 163, 108, 212, 2 + }, + + /* Region 2 */ + { + 0x8005, 0, 127, 160, 255, 119, 0, + 0, 216, 79, 72, 0, 216, 2, + 2, 244, 73, 145, 0, 244, 2, + 3370, 247, 33, 182, 60, 204, 2, + 1200, 246, 65, 163, 108, 204, 2 + }, + + /* Region 3 */ + { + 0x8005, 0, 127, 160, 255, 1, 0, + 3369, 248, 65, 71, 40, 208, 2, + -3, 245, 88, 113, 0, 244, 2, + 2784, 225, 65, 133, 80, 192, 2, + 3, 241, 81, 113, 80, 216, 2 + }, + + /* Region 4 */ + { + 0x8002, 0, 127, 0, 255, 128, 0, + 0, 229, 155, 183, 0, 228, 2, + -3, 243, 90, 81, 0, 244, 2, + 4800, 248, 109, 180, 36, 192, 2, + 3, 245, 90, 85, 16, 244, 2 + }, + + /* Region 5 */ + { + 0x8002, 0, 127, 9, 96, 192, 0, + 1200, 229, 157, 180, 0, 216, 2, + -3, 244, 90, 81, 0, 244, 2, + 1902, 255, 111, 182, 80, 208, 2, + 3, 246, 92, 83, 0, 244, 2 + }, + + /* Region 6 */ + { + 0x8002, 0, 127, 0, 255, 154, 0, + 3102, 244, 63, 102, 228, 228, 2, + 1200, 247, 93, 97, 0, 236, 2, + 1902, 255, 63, 98, 156, 220, 2, + 1200, 244, 92, 98, 0, 236, 2 + }, + + /* Region 7 */ + { + 0x8005, 0, 127, 0, 255, 202, 0, + 0, 251, 131, 19, 216, 220, 2, + 1201, 247, 62, 113, 0, 240, 2, + 0, 243, 154, 36, 240, 224, 2, + 2784, 250, 61, 36, 240, 208, 2 + }, + + /* Region 8 */ + { + 0x8001, 0, 127, 0, 255, 80, 0, + -1, 213, 191, 183, 0, 204, 2, + 1, 245, 154, 129, 0, 244, 2, + 3831, 252, 159, 100, 0, 200, 2, + 1197, 246, 91, 182, 0, 244, 2 + }, + + /* Region 9 */ + { + 0x8002, 0, 127, 48, 80, 21, 0, + 2982, 255, 43, 96, 0, 196, 3, + 3, 247, 71, 130, 0, 244, 2, + 3358, 253, 40, 98, 144, 208, 2, + -2, 246, 70, 130, 0, 236, 2 + }, + + /* Region 10 */ + { + 0x8002, 0, 127, 48, 80, 26, 0, + 3096, 249, 72, 100, 0, 208, 2, + 2185, 249, 102, 130, 0, 240, 2, + 3386, 247, 66, 100, 144, 212, 2, + -2, 247, 102, 130, 0, 240, 2 + }, + + /* Region 11 */ + { + 0x8002, 0, 127, 92, 67, 21, 0, + 2982, 255, 27, 146, 0, 200, 3, + 3, 246, 68, 146, 0, 240, 2, + 3358, 250, 149, 116, 144, 208, 2, + -3, 245, 68, 146, 0, 240, 0 + }, + + /* Region 12 */ + { + 0x8002, 0, 127, 0, 67, 0, 0, + 1500, 239, 60, 151, 0, 220, 2, + 0, 247, 76, 146, 0, 240, 2, + 2398, 234, 156, 151, 0, 212, 2, + 0, 246, 105, 146, 0, 244, 2 + }, + + /* Region 13 */ + { + 0x8002, 0, 127, 0, 67, 0, 0, + 2500, 255, 60, 151, 0, 220, 2, + 0, 249, 92, 146, 0, 244, 2, + 3369, 250, 156, 151, 0, 196, 2, + 0, 248, 89, 146, 0, 244, 2 + }, + + /* Region 14 */ + { + 0x8005, 0, 127, 160, 255, 0, 0, + 2300, 229, 112, 49, 0, 208, 2, + -3, 247, 67, 50, 0, 248, 2, + 1074, 255, 41, 49, 0, 196, 2, + 686, 240, 97, 18, 0, 196, 2 + }, + + /* Region 15 */ + { + 0x8005, 0, 127, 160, 255, 219, 0, + 3369, 255, 65, 70, 40, 216, 2, + 1, 246, 72, 113, 0, 240, 2, + 1902, 225, 33, 129, 80, 204, 2, + 2400, 225, 97, 113, 80, 200, 2 + }, + + /* Region 16 */ + { + 0x8003, 0, 127, 32, 48, 151, 0, + 1201, 215, 35, 66, 252, 208, 0, + -9581, 254, 63, 177, 240, 240, 3, + 1902, 248, 47, 64, 112, 244, 2, + 0, 247, 35, 66, 208, 212, 2 + }, + + /* Region 17 */ + { + 0x8001, 0, 127, 0, 255, 153, 0, + 1, 252, 31, 3, 244, 196, 2, + -1, 208, 31, 4, 248, 244, 2, + 1205, 209, 31, 4, 248, 236, 2, + 1899, 250, 31, 32, 0, 240, 2 + }, + + /* Region 18 */ + { + 0x8002, 0, 127, 32, 49, 201, 0, + 1, 220, 47, 3, 244, 220, 0, + -10000, 208, 63, 1, 248, 240, 3, + 1586, 255, 47, 3, 188, 216, 2, + -1, 202, 63, 32, 80, 232, 2 + }, + + /* Region 19 */ + { + 0x8001, 0, 127, 0, 143, 29, 0, + -1200, 223, 64, 0, 252, 216, 2, + 1200, 96, 41, 35, 248, 240, 2, + 1200, 143, 41, 64, 252, 224, 2, + 3102, 161, 41, 96, 248, 216, 2 + }, + + /* Region 20 */ + { + 0x8002, 0, 127, 0, 143, 34, 0, + -1200, 133, 79, 1, 252, 212, 2, + 1201, 112, 46, 34, 248, 232, 2, + 0, 116, 79, 65, 252, 200, 2, + 1900, 161, 46, 98, 248, 232, 2 + }, + + /* Region 21 */ + { + 0x8002, 0, 127, 0, 143, 187, 0, + 1202, 80, 74, 1, 252, 216, 2, + 2402, 112, 46, 34, 248, 232, 2, + 0, 99, 78, 97, 184, 216, 2, + 1899, 81, 46, 98, 236, 232, 2 + }, + + /* Region 22 */ + { + 0x8005, 0, 127, 22, 141, 34, 0, + 2787, 176, 79, 4, 252, 208, 2, + 2785, 144, 45, 34, 248, 236, 2, + 3369, 83, 77, 100, 184, 172, 2, + 1902, 102, 45, 100, 172, 212, 0 + }, + + /* Region 23 */ + { + 0x8002, 0, 127, 0, 143, 135, 0, + 1900, 112, 79, 3, 252, 220, 2, + 2400, 128, 45, 34, 248, 232, 2, + 1200, 115, 77, 98, 184, 220, 2, + 1904, 97, 45, 98, 236, 232, 2 + }, + + /* Region 24 */ + { + 0x8005, 0, 127, 0, 255, 157, 0, + 1200, 244, 54, 4, 20, 200, 2, + 0, 245, 92, 130, 0, 244, 2, + 3802, 247, 68, 21, 0, 196, 2, + 1, 245, 43, 114, 0, 204, 2 + }, + + /* Region 25 */ + { + 0x8005, 0, 127, 0, 128, 83, 0, + 0, 244, 51, 4, 200, 204, 0, + 0, 247, 108, 129, 0, 248, 0, + 2786, 243, 31, 70, 200, 220, 0, + 1902, 246, 44, 113, 12, 188, 0 + }, + + /* Region 26 */ + { + 0x8005, 0, 127, 0, 128, 61, 0, + 0, 246, 51, 97, 76, 204, 0, + 0, 244, 60, 97, 0, 240, 0, + 1786, 255, 31, 64, 0, 180, 0, + 1200, 247, 60, 97, 12, 204, 0 + }, + + /* Region 27 */ + { + 0x8005, 0, 127, 0, 128, 153, 0, + -2, 243, 53, 99, 96, 200, 0, + 0, 243, 60, 97, 0, 240, 0, + 3983, 247, 63, 100, 24, 204, 0, + 2, 242, 53, 99, 52, 212, 0 + }, + + /* Region 28 */ + { + 0x8005, 0, 127, 0, 128, 205, 0, + -2, 244, 47, 97, 20, 208, 0, + 0, 252, 75, 193, 0, 248, 0, + 0, 254, 63, 98, 132, 224, 0, + 2786, 251, 63, 98, 52, 192, 0 + }, + + /* Region 29 */ + { + 0x8005, 0, 127, 0, 128, 221, 0, + -1, 208, 191, 99, 220, 224, 0, + 1200, 243, 92, 97, 0, 244, 0, + 3984, 212, 11, 96, 168, 196, 0, + 1, 242, 127, 98, 108, 204, 0 + }, + + /* Region 30 */ + { + 0x8005, 0, 127, 0, 128, 174, 0, + -3, 212, 207, 99, 0, 228, 0, + 1902, 241, 108, 97, 0, 248, 0, + 3805, 212, 59, 98, 0, 220, 0, + 1902, 146, 107, 98, 144, 196, 0 + }, + + /* Region 31 */ + { + 0x8009, 0, 127, 0, 255, 128, 0, + 1206, 239, 43, 69, 0, 216, 2, + 4, 254, 42, 66, 0, 244, 2, + 702, 88, 55, 66, 0, 204, 2, + -4, 71, 55, 66, 0, 240, 2 + }, + + /* Region 32 */ + { + 0x8005, 0, 127, 0, 255, 85, 0, + 500, 239, 95, 82, 0, 184, 3, + 0, 248, 73, 132, 0, 252, 2, + 2786, 203, 59, 130, 0, 176, 2, + 0, 216, 42, 100, 0, 208, 2 + }, + + /* Region 33 */ + { + 0x8005, 0, 127, 0, 128, 73, 0, + 1, 229, 54, 131, 160, 208, 0, + -1, 244, 62, 97, 0, 248, 0, + 3986, 227, 127, 69, 140, 184, 0, + 1201, 249, 92, 114, 0, 204, 0 + }, + + /* Region 34 */ + { + 0x8005, 0, 127, 0, 128, 73, 0, + 1, 225, 54, 100, 200, 212, 0, + -1, 244, 94, 97, 0, 248, 0, + 3986, 249, 127, 88, 112, 188, 0, + 1201, 249, 92, 85, 52, 208, 0 + }, + + /* Region 35 */ + { + 0x8005, 0, 127, 0, 128, 188, 0, + -3, 198, 92, 179, 28, 212, 0, + 0, 243, 90, 145, 0, 248, 0, + 1901, 215, 95, 69, 28, 196, 0, + 3, 84, 108, 196, 32, 208, 0 + }, + + /* Region 36 */ + { + 0x8005, 0, 127, 0, 136, 6, 0, + 0, 226, 99, 36, 224, 216, 0, + 1902, 248, 78, 33, 0, 252, 0, + 3369, 239, 250, 33, 0, 204, 0, + 0, 230, 253, 33, 0, 208, 0 + }, + + /* Region 37 */ + { + 0x8005, 0, 127, 0, 136, 195, 0, + 0, 245, 99, 36, 152, 208, 0, + 1200, 248, 78, 33, 0, 252, 0, + 3369, 246, 250, 33, 0, 216, 0, + 0, 246, 61, 33, 0, 180, 0 + }, + + /* Region 38 */ + { + 0x8002, 0, 127, 0, 133, 221, 0, + 1, 244, 67, 35, 80, 220, 0, + 3, 246, 94, 33, 0, 244, 0, + -1, 245, 70, 35, 80, 236, 2, + -3, 246, 63, 33, 0, 236, 2 + }, + + /* Region 39 */ + { + 0x8002, 0, 127, 0, 133, 220, 0, + 0, 114, 51, 34, 132, 208, 0, + 3, 214, 62, 33, 0, 248, 0, + 0, 85, 54, 34, 44, 224, 2, + -3, 214, 63, 33, 0, 236, 2 + }, + + /* Region 40 */ + { + 0x8005, 0, 127, 48, 142, 187, 0, + -1, 33, 22, 33, 200, 208, 0, + 0, 81, 105, 33, 220, 240, 0, + 2786, 245, 19, 50, 208, 192, 0, + 1, 245, 21, 82, 200, 220, 0 + }, + + /* Region 41 */ + { + 0x8005, 0, 127, 48, 126, 103, 0, + -1, 193, 22, 33, 228, 212, 0, + 0, 81, 105, 33, 220, 244, 0, + 0, 245, 19, 50, 216, 228, 0, + 1200, 245, 19, 82, 200, 188, 0 + }, + + /* Region 42 */ + { + 0x8005, 0, 127, 16, 126, 202, 0, + -1, 49, 24, 41, 200, 212, 0, + 0, 81, 71, 49, 220, 244, 0, + 3371, 243, 19, 36, 232, 192, 0, + 1, 242, 24, 36, 220, 212, 0 + }, + + /* Region 43 */ + { + 0x8005, 0, 127, 16, 124, 205, 0, + 0, 129, 24, 49, 208, 200, 0, + 0, 67, 102, 81, 224, 244, 0, + 3804, 246, 23, 36, 160, 196, 0, + 1200, 244, 24, 35, 208, 200, 0 + }, + + /* Region 44 */ + { + 0x8005, 0, 127, 48, 144, 208, 0, + -3, 209, 22, 33, 200, 204, 2, + 0, 81, 89, 33, 220, 240, 2, + -5000, 208, 6, 33, 244, 188, 3, + 3, 97, 89, 33, 224, 200, 0 + }, + + /* Region 45 */ + { + 0x8005, 0, 127, 0, 255, 186, 0, + 500, 223, 95, 0, 0, 192, 3, + 0, 247, 89, 100, 0, 248, 2, + 3369, 255, 59, 168, 0, 212, 2, + 0, 216, 42, 97, 0, 212, 2 + }, + + /* Region 46 */ + { + 0x8002, 0, 127, 0, 255, 221, 0, + 1206, 235, 70, 69, 0, 216, 2, + 4, 248, 84, 66, 0, 244, 2, + 1902, 247, 52, 137, 80, 216, 2, + -4, 245, 84, 131, 0, 240, 2 + }, + + /* Region 47 */ + { + 0x8005, 0, 127, 0, 255, 105, 0, + 387, 231, 115, 34, 4, 216, 2, + 0, 248, 37, 65, 0, 252, 2, + 3308, 248, 117, 34, 8, 200, 2, + 1900, 213, 82, 50, 0, 192, 2 + }, + + /* Region 48 */ + { + 0x8002, 0, 127, 32, 160, 221, 0, + -7, 209, 22, 33, 200, 204, 2, + -7, 81, 73, 33, 220, 244, 0, + 7, 209, 22, 33, 200, 208, 0, + 7, 97, 73, 33, 224, 244, 2 + }, + + /* Region 49 */ + { + 0x8002, 0, 127, 64, 128, 189, 0, + -2, 209, 54, 32, 224, 216, 2, + -7726, 97, 105, 33, 220, 240, 3, + 1902, 209, 54, 34, 216, 208, 0, + 2, 81, 105, 33, 224, 236, 0 + }, + + /* Region 50 */ + { + 0x8002, 0, 127, 80, 144, 206, 0, + -3, 179, 38, 33, 160, 220, 2, + -7726, 81, 69, 34, 220, 244, 3, + 3, 193, 38, 33, 240, 212, 0, + -8000, 65, 69, 34, 224, 236, 3 + }, + + /* Region 51 */ + { + 0x8005, 0, 127, 96, 128, 204, 0, + -3, 97, 38, 33, 180, 216, 0, + 0, 81, 69, 34, 220, 240, 2, + 3369, 145, 38, 33, 240, 196, 2, + -13190, 65, 69, 34, 240, 200, 3 + }, + + /* Region 52 */ + { + 0x8002, 0, 127, 64, 128, 108, 0, + -3, 193, 37, 35, 236, 208, 0, + 2394, 97, 90, 36, 224, 232, 2, + 3, 65, 40, 35, 236, 204, 2, + 1203, 97, 89, 33, 224, 240, 0 + }, + + /* Region 53 */ + { + 0x8005, 0, 127, 128, 128, 122, 0, + 0, 193, 21, 34, 236, 188, 0, + 3, 97, 74, 36, 224, 248, 2, + 1906, 251, 24, 32, 96, 192, 3, + 1200, 97, 73, 32, 224, 184, 0 + }, + + /* Region 54 */ + { + 0x8002, 0, 127, 64, 133, 135, 0, + 0, 194, 25, 35, 120, 200, 2, + 0, 97, 75, 36, 224, 240, 0, + 2906, 254, 28, 48, 0, 184, 3, + 0, 216, 75, 80, 204, 240, 2 + }, + + /* Region 55 */ + { + 0x8009, 0, 127, 208, 64, 255, 0, + 475, 249, 16, 32, 252, 240, 2, + 702, 248, 71, 32, 0, 244, 2, + 1136, 232, 27, 32, 216, 248, 0, + 0, 249, 23, 48, 0, 248, 2 + }, + + /* Region 56 */ + { + 0x8005, 0, 127, 0, 132, 233, 0, + 0, 195, 95, 64, 240, 208, 0, + 0, 225, 94, 64, 248, 240, 0, + 0, 254, 127, 0, 4, 196, 4, + 1902, 228, 95, 1, 248, 200, 0 + }, + + /* Region 57 */ + { + 0x8005, 0, 127, 16, 140, 238, 0, + 0, 163, 90, 67, 228, 208, 0, + 0, 209, 77, 65, 248, 240, 0, + 1969, 173, 58, 65, 0, 176, 0, + 0, 210, 61, 52, 204, 220, 0 + }, + + /* Region 58 */ + { + 0x8005, 0, 127, 16, 140, 222, 0, + 0, 119, 74, 67, 160, 212, 0, + 0, 146, 61, 65, 248, 244, 0, + 1900, 137, 58, 65, 100, 196, 0, + 0, 119, 61, 52, 120, 200, 0 + }, + + /* Region 59 */ + { + 0x8005, 0, 127, 16, 135, 219, 0, + 0, 176, 79, 69, 240, 216, 0, + 0, 193, 79, 64, 248, 236, 0, + 0, 178, 123, 54, 92, 228, 0, + 3369, 212, 95, 38, 144, 212, 0 + }, + + /* Region 60 */ + { + 0x8002, 0, 127, 0, 119, 203, 0, + 2, 65, 77, 66, 228, 204, 0, + 2, 161, 74, 64, 240, 240, 0, + -2, 85, 60, 66, 180, 216, 2, + -2, 162, 74, 64, 220, 240, 2 + }, + + /* Region 61 */ + { + 0x8002, 0, 127, 16, 154, 237, 0, + 0, 179, 42, 64, 216, 208, 0, + 0, 209, 61, 64, 248, 244, 0, + -1200, 226, 55, 65, 244, 220, 2, + 1902, 162, 62, 52, 204, 236, 2 + }, + + /* Region 62 */ + { + 0x8002, 0, 127, 48, 119, 221, 0, + 2, 119, 79, 64, 208, 212, 0, + 2, 209, 110, 64, 248, 236, 0, + -2, 84, 79, 64, 136, 212, 2, + -2, 209, 110, 64, 240, 240, 2 + }, + + /* Region 63 */ + { + 0x8002, 0, 127, 32, 135, 221, 0, + 2, 165, 79, 64, 152, 216, 0, + 2, 225, 110, 64, 248, 236, 0, + -2, 132, 79, 64, 72, 224, 2, + -2, 241, 110, 64, 252, 236, 2 + }, + + /* Region 64 */ + { + 0x8005, 0, 127, 17, 127, 190, 0, + 0, 209, 60, 67, 244, 208, 0, + 1200, 145, 94, 65, 248, 244, 2, + 3369, 197, 47, 4, 128, 192, 0, + 1902, 167, 94, 6, 200, 200, 0 + }, + + /* Region 65 */ + { + 0x8005, 0, 127, 17, 143, 190, 0, + 0, 209, 60, 67, 244, 216, 0, + 1902, 145, 62, 65, 248, 240, 2, + 3369, 197, 47, 4, 128, 196, 0, + 2400, 167, 94, 6, 200, 212, 2 + }, + + /* Region 66 */ + { + 0x8005, 0, 127, 17, 143, 190, 0, + 0, 209, 60, 67, 244, 208, 0, + 1902, 145, 62, 65, 248, 240, 2, + 3369, 197, 47, 4, 128, 192, 0, + 1902, 167, 94, 6, 200, 216, 2 + }, + + /* Region 67 */ + { + 0x8005, 0, 127, 17, 125, 190, 0, + 0, 114, 109, 67, 244, 224, 0, + 1902, 166, 93, 97, 200, 240, 0, + 2786, 165, 95, 52, 160, 200, 0, + 2400, 173, 78, 54, 240, 212, 2 + }, + + /* Region 68 */ + { + 0x8002, 0, 127, 16, 140, 205, 0, + 0, 211, 55, 66, 244, 208, 0, + 1902, 193, 93, 65, 248, 240, 0, + 0, 204, 47, 4, 244, 216, 0, + 3600, 183, 95, 6, 160, 232, 0 + }, + + /* Region 69 */ + { + 0x8002, 0, 127, 16, 126, 222, 0, + 0, 243, 36, 66, 172, 200, 0, + 1200, 193, 110, 67, 248, 244, 0, + 0, 215, 33, 2, 232, 212, 0, + 3369, 178, 63, 6, 184, 240, 0 + }, + + /* Region 70 */ + { + 0x8002, 0, 127, 16, 140, 221, 0, + 1200, 213, 61, 66, 136, 200, 0, + 1902, 193, 93, 68, 248, 240, 0, + 0, 197, 47, 2, 228, 216, 0, + 3369, 183, 95, 2, 160, 236, 0 + }, + + /* Region 71 */ + { + 0x8002, 0, 127, 16, 124, 201, 0, + 1200, 195, 55, 68, 240, 208, 0, + 0, 209, 76, 65, 248, 236, 0, + 1902, 147, 47, 19, 208, 212, 0, + 0, 183, 79, 22, 156, 228, 0 + }, + + /* Region 72 */ + { + 0x8005, 0, 127, 32, 110, 234, 0, + 500, 237, 60, 68, 0, 192, 1, + 1, 161, 93, 65, 248, 240, 2, + 3365, 154, 47, 16, 48, 180, 6, + 1200, 165, 92, 52, 160, 212, 2 + }, + + /* Region 73 */ + { + 0x8005, 0, 127, 32, 142, 200, 0, + 0, 193, 60, 68, 248, 200, 0, + 1, 129, 61, 65, 248, 240, 2, + 3365, 154, 47, 16, 68, 184, 6, + 1200, 169, 92, 52, 160, 204, 2 + }, + + /* Region 74 */ + { + 0x8003, 0, 127, 32, 135, 36, 0, + 1199, 165, 79, 66, 152, 192, 2, + -3, 145, 110, 64, 248, 240, 2, + 0, 199, 79, 66, 44, 236, 2, + 2986, 136, 110, 67, 100, 196, 2 + }, + + /* Region 75 */ + { + 0x8005, 0, 127, 32, 190, 71, 0, + 868, 202, 140, 16, 24, 188, 2, + 0, 176, 77, 65, 248, 240, 2, + 3750, 169, 127, 16, 36, 228, 6, + 2400, 195, 60, 17, 232, 172, 2 + }, + + /* Region 76 */ + { + 0x8005, 0, 127, 224, 16, 123, 0, + 275, 202, 14, 2, 44, 196, 2, + 0, 165, 89, 65, 56, 244, 2, + 0, 255, 12, 2, 64, 216, 6, + 963, 169, 14, 4, 40, 196, 2 + }, + + /* Region 77 */ + { + 0x8012, 0, 127, 192, 128, 100, 0, + 1500, 202, 79, 68, 76, 204, 2, + -2, 97, 26, 64, 248, 232, 2, + 1588, 202, 223, 69, 4, 220, 0, + 3, 188, 121, 67, 48, 252, 2 + }, + + /* Region 78 */ + { + 0x8002, 0, 127, 112, 140, 205, 0, + 0, 68, 47, 66, 60, 176, 2, + -2, 113, 94, 64, 248, 236, 0, + 5000, 121, 47, 64, 32, 168, 7, + 3, 136, 94, 64, 0, 236, 0 + }, + + /* Region 79 */ + { + 0x8003, 0, 127, 32, 135, 33, 0, + 1199, 197, 79, 66, 152, 184, 2, + 0, 161, 110, 64, 248, 240, 2, + 0, 199, 79, 66, 44, 236, 2, + 2400, 255, 110, 65, 36, 208, 6 + }, + + /* Region 80 */ + { + 0x8002, 0, 127, 0, 192, 170, 0, + 1199, 192, 77, 33, 200, 212, 0, + 0, 209, 107, 33, 232, 240, 0, + 1201, 80, 77, 33, 200, 212, 0, + 0, 241, 107, 33, 232, 240, 0 + }, + + /* Region 81 */ + { + 0x8002, 0, 127, 0, 192, 221, 0, + -1, 192, 45, 33, 200, 212, 0, + -1, 209, 107, 33, 232, 244, 0, + 1, 80, 45, 33, 200, 212, 0, + 1, 241, 107, 33, 232, 244, 0 + }, + + /* Region 82 */ + { + 0x8005, 0, 127, 0, 112, 255, 0, + 4750, 221, 45, 34, 48, 172, 4, + -10000, 161, 107, 33, 200, 244, 3, + 2204, 137, 45, 37, 64, 184, 0, + -2, 211, 107, 33, 160, 208, 0 + }, + + /* Region 83 */ + { + 0x8005, 0, 127, 16, 127, 238, 0, + 2, 248, 45, 32, 204, 208, 0, + -9500, 241, 107, 33, 200, 240, 3, + 3369, 186, 45, 38, 24, 208, 0, + -2, 211, 107, 32, 220, 212, 0 + }, + + /* Region 84 */ + { + 0x8005, 0, 127, 0, 128, 221, 0, + -1, 192, 191, 99, 220, 216, 0, + 1200, 243, 92, 97, 0, 244, 0, + 3984, 200, 11, 96, 168, 192, 0, + 1, 194, 127, 98, 108, 200, 0 + }, + + /* Region 85 */ + { + 0x8002, 0, 127, 128, 128, 111, 0, + 1, 194, 25, 35, 120, 204, 2, + -9750, 193, 107, 36, 224, 244, 3, + 3906, 255, 28, 50, 12, 188, 3, + -1, 216, 107, 80, 204, 240, 2 + }, + + /* Region 86 */ + { + 0x8002, 0, 127, 32, 134, 222, 0, + 0, 195, 52, 33, 200, 208, 0, + 0, 177, 90, 33, 232, 240, 2, + 702, 195, 52, 33, 200, 208, 2, + 702, 177, 90, 34, 232, 240, 2 + }, + + /* Region 87 */ + { + 0x8002, 0, 127, 32, 134, 205, 0, + 0, 198, 75, 36, 120, 220, 2, + 0, 225, 78, 52, 40, 244, 2, + 0, 246, 47, 32, 220, 208, 2, + 1902, 241, 124, 32, 240, 236, 2 + }, + + /* Region 88 */ + { + 0x8003, 0, 127, 32, 120, 14, 0, + 3600, 244, 67, 34, 88, 208, 0, + 3, 194, 84, 33, 84, 240, 2, + -3, 194, 84, 33, 172, 236, 2, + 902, 254, 114, 34, 0, 224, 3 + }, + + /* Region 89 */ + { + 0x8002, 0, 127, 64, 169, 170, 0, + -3, 83, 69, 34, 184, 212, 0, + -7500, 50, 69, 33, 176, 244, 3, + 3, 81, 69, 34, 212, 212, 2, + -8500, 66, 69, 33, 176, 244, 3 + }, + + /* Region 90 */ + { + 0x8002, 0, 127, 64, 120, 221, 0, + -2, 82, 69, 34, 244, 216, 0, + 0, 145, 102, 33, 228, 240, 0, + 2, 81, 69, 34, 244, 208, 2, + 0, 145, 102, 33, 224, 240, 2 + }, + + /* Region 91 */ + { + 0x8003, 0, 127, 32, 138, 14, 0, + 2400, 148, 67, 34, 176, 200, 0, + 3, 194, 85, 33, 220, 236, 2, + -3, 194, 69, 33, 220, 236, 2, + 1905, 254, 114, 34, 48, 224, 2 + }, + + /* Region 92 */ + { + 0x8002, 0, 127, 82, 67, 71, 0, + 2982, 228, 22, 146, 88, 192, 3, + 3, 102, 84, 146, 196, 240, 2, + 3358, 50, 149, 116, 144, 208, 2, + -3, 85, 84, 146, 120, 240, 0 + }, + + /* Region 93 */ + { + 0x8005, 0, 127, 48, 126, 219, 0, + -3, 49, 19, 33, 120, 200, 0, + 0, 81, 70, 33, 220, 240, 0, + 3804, 242, 18, 50, 200, 200, 0, + 1203, 82, 19, 82, 200, 176, 0 + }, + + /* Region 94 */ + { + 0x8003, 0, 127, 32, 138, 13, 0, + 2786, 116, 67, 34, 204, 184, 0, + 1902, 114, 69, 33, 192, 232, 2, + -3, 178, 69, 33, 188, 232, 2, + 3804, 254, 82, 34, 164, 228, 2 + }, + + /* Region 95 */ + { + 0x8002, 0, 127, 48, 135, 238, 0, + -2, 34, 85, 34, 184, 224, 0, + 1, 113, 70, 33, 228, 236, 0, + 2, 19, 85, 34, 156, 224, 2, + -1, 129, 70, 33, 224, 236, 2 + }, + + /* Region 96 */ + { + 0x8012, 0, 127, 240, 112, 221, 0, + 3369, 213, 69, 32, 0, 204, 0, + 0, 193, 70, 33, 112, 232, 2, + 0, 145, 69, 34, 244, 208, 2, + -9000, 145, 70, 33, 224, 236, 3 + }, + + /* Region 97 */ + { + 0x8002, 0, 127, 96, 122, 168, 0, + -1, 99, 51, 33, 200, 208, 0, + -8500, 81, 83, 33, 232, 240, 3, + 702, 99, 52, 33, 200, 208, 2, + -9500, 65, 83, 34, 224, 240, 3 + }, + + /* Region 98 */ + { + 0x8002, 0, 127, 0, 67, 0, 0, + 1500, 217, 55, 151, 20, 224, 2, + 3, 231, 70, 146, 88, 220, 2, + 2369, 115, 148, 151, 32, 196, 2, + -3, 118, 36, 146, 64, 244, 2 + }, + + /* Region 99 */ + { + 0x8002, 0, 127, 64, 169, 204, 0, + -3, 228, 69, 34, 148, 220, 0, + -7448, 243, 69, 33, 200, 240, 3, + 3, 81, 68, 34, 212, 212, 2, + -8526, 65, 68, 33, 196, 240, 3 + }, + + /* Region 100 */ + { + 0x8002, 0, 127, 64, 119, 187, 0, + 2786, 228, 22, 146, 176, 192, 0, + 3, 102, 68, 146, 196, 236, 2, + 3369, 178, 149, 116, 176, 208, 2, + -3, 231, 68, 146, 120, 240, 0 + }, + + /* Region 101 */ + { + 0x8002, 0, 127, 240, 144, 239, 0, + -2, 49, 69, 34, 236, 208, 2, + -9000, 113, 102, 33, 228, 236, 3, + 2400, 149, 69, 34, 12, 216, 1, + 0, 145, 102, 33, 224, 236, 2 + }, + + /* Region 102 */ + { + 0x8012, 0, 127, 241, 176, 6, 0, + 1200, 247, 49, 64, 252, 204, 0, + 3804, 246, 101, 32, 0, 232, 2, + 1902, 247, 32, 32, 112, 188, 2, + 0, 228, 84, 32, 0, 240, 2 + }, + + /* Region 103 */ + { + 0x8005, 0, 127, 64, 101, 221, 0, + 1, 194, 68, 97, 196, 200, 2, + -10001, 247, 100, 114, 176, 240, 3, + 3370, 213, 33, 70, 52, 200, 2, + -1, 178, 68, 49, 208, 212, 0 + }, + + /* Region 104 */ + { + 0x8002, 0, 127, 0, 255, 203, 0, + -3, 245, 82, 99, 200, 232, 2, + 2787, 244, 84, 96, 0, 236, 2, + 1198, 133, 81, 100, 196, 220, 2, + 1902, 147, 67, 80, 0, 232, 2 + }, + + /* Region 105 */ + { + 0x8005, 0, 127, 0, 255, 140, 0, + 500, 255, 137, 179, 0, 200, 3, + 1902, 248, 90, 160, 0, 244, 2, + 3804, 245, 57, 35, 164, 204, 2, + 0, 245, 38, 51, 196, 208, 2 + }, + + /* Region 106 */ + { + 0x8005, 0, 127, 0, 255, 72, 0, + 1000, 238, 57, 65, 0, 188, 3, + 1902, 247, 103, 112, 0, 244, 2, + 2786, 250, 36, 81, 68, 212, 2, + 0, 249, 50, 49, 172, 204, 2 + }, + + /* Region 107 */ + { + 0x8005, 0, 127, 16, 119, 72, 0, + 1500, 255, 89, 65, 0, 196, 3, + 2790, 246, 39, 112, 0, 240, 0, + 1905, 246, 36, 81, 168, 208, 0, + 0, 249, 114, 49, 172, 212, 0 + }, + + /* Region 108 */ + { + 0x8005, 0, 127, 0, 255, 237, 0, + 1902, 254, 89, 65, 0, 212, 2, + 0, 248, 87, 112, 0, 240, 2, + 3369, 231, 62, 81, 0, 208, 2, + 3, 245, 118, 49, 96, 196, 2 + }, + + /* Region 109 */ + { + 0x8002, 0, 127, 16, 188, 205, 0, + -2, 179, 47, 50, 244, 224, 2, + 1900, 145, 94, 49, 248, 232, 2, + 3, 210, 46, 2, 244, 208, 2, + 2789, 133, 93, 4, 180, 244, 2 + }, + + /* Region 110 */ + { + 0x8005, 0, 127, 48, 135, 220, 0, + 1901, 162, 25, 35, 144, 208, 0, + 0, 113, 105, 65, 220, 240, 0, + 3369, 233, 88, 51, 120, 212, 0, + 0, 229, 24, 84, 200, 208, 0 + }, + + /* Region 111 */ + { + 0x8002, 0, 127, 112, 32, 190, 0, + 0, 53, 79, 66, 152, 212, 2, + 1200, 53, 75, 64, 136, 244, 2, + 500, 149, 60, 66, 16, 208, 2, + 1902, 200, 78, 64, 0, 248, 0 + }, + + /* Region 112 */ + { + 0x8005, 0, 127, 0, 144, 130, 0, + 2514, 255, 68, 53, 0, 204, 2, + 2400, 247, 133, 48, 0, 240, 2, + 4151, 243, 67, 50, 0, 212, 2, + 3369, 243, 66, 56, 0, 204, 2 + }, + + /* Region 113 */ + { + 0x8005, 0, 127, 0, 255, 0, 0, + 514, 253, 79, 51, 0, 196, 3, + 1905, 252, 89, 51, 0, 244, 2, + 4349, 245, 35, 51, 0, 208, 2, + 1205, 247, 34, 51, 0, 208, 2 + }, + + /* Region 114 */ + { + 0x8005, 0, 127, 0, 255, 0, 0, + 514, 221, 69, 35, 0, 204, 3, + 0, 250, 86, 115, 0, 252, 2, + 1884, 244, 116, 51, 0, 200, 2, + 1208, 210, 35, 51, 0, 208, 2 + }, + + /* Region 115 */ + { + 0x8005, 0, 127, 0, 255, 16, 0, + 514, 222, 85, 163, 0, 192, 3, + 0, 254, 108, 163, 0, 252, 2, + 3800, 255, 143, 160, 0, 176, 2, + 1200, 250, 105, 163, 0, 212, 2 + }, + + /* Region 116 */ + { + 0x8005, 0, 127, 0, 255, 16, 0, + 1514, 249, 101, 163, 0, 204, 3, + -1200, 249, 87, 160, 0, 252, 2, + 0, 235, 143, 160, 0, 204, 2, + 1200, 234, 73, 163, 0, 204, 2 + }, + + /* Region 117 */ + { + 0x8005, 0, 127, 0, 255, 16, 0, + 500, 239, 101, 160, 0, 204, 3, + -1195, 248, 104, 160, 0, 252, 2, + 1898, 252, 72, 163, 0, 216, 2, + 1239, 248, 87, 163, 0, 196, 2 + }, + + /* Region 118 */ + { + 0x8005, 0, 127, 0, 255, 255, 0, + 500, 255, 98, 160, 0, 196, 3, + -1, 249, 105, 160, 0, 252, 2, + 1907, 250, 71, 160, 0, 252, 2, + 1182, 249, 87, 161, 0, 192, 2 + }, + + /* Region 119 */ + { + 0x8005, 0, 127, 0, 0, 100, 0, + 600, 32, 15, 0, 252, 224, 6, + 0, 47, 111, 65, 0, 244, 2, + 1826, 16, 47, 0, 252, 216, 2, + 3551, 240, 47, 0, 252, 212, 2 + }, + + /* Region 120 */ + { + 0x8014, 0, 127, 240, 128, 235, 0, + 1228, 161, 47, 17, 196, 200, 3, + 3000, 123, 75, 17, 0, 240, 2, + 7022, 72, 43, 17, 0, 216, 0, + 4000, 150, 79, 17, 48, 196, 3 + }, + + /* Region 121 */ + { + 0x8005, 0, 127, 224, 16, 86, 0, + 275, 251, 6, 0, 36, 200, 2, + 0, 101, 104, 65, 56, 240, 2, + 0, 240, 6, 0, 252, 208, 6, + 1000, 195, 8, 0, 248, 200, 2 + }, + + /* Region 122 */ + { + 0x8002, 0, 127, 0, 0, 185, 0, + 600, 35, 66, 17, 72, 224, 4, + -13000, 81, 67, 17, 228, 244, 2, + 702, 97, 38, 17, 212, 196, 6, + -14000, 81, 65, 17, 224, 244, 3 + }, + + /* Region 123 */ + { + 0x8012, 0, 127, 240, 112, 237, 0, + -6528, 153, 127, 16, 0, 252, 3, + 1200, 105, 109, 16, 0, 216, 2, + -6022, 179, 139, 17, 0, 248, 3, + 2000, 104, 79, 17, 0, 240, 0 + }, + + /* Region 124 */ + { + 0x8012, 0, 127, 240, 240, 16, 0, + 1914, 240, 64, 160, 240, 208, 2, + 1200, 240, 73, 163, 240, 244, 0, + 1900, 240, 64, 160, 240, 148, 2, + 4151, 240, 73, 163, 240, 244, 0 + }, + + /* Region 125 */ + { + 0x8002, 0, 127, 240, 56, 235, 0, + -5522, 97, 32, 17, 196, 240, 3, + 0, 84, 75, 17, 180, 248, 3, + 702, 65, 38, 17, 224, 212, 6, + -4000, 161, 73, 17, 224, 252, 1 + }, + + /* Region 126 */ + { + 0x8015, 0, 127, 240, 248, 37, 0, + 1050, 243, 0, 0, 252, 224, 7, + 2000, 49, 68, 0, 224, 236, 3, + 350, 240, 0, 0, 252, 216, 1, + 700, 240, 0, 0, 252, 212, 3 + }, + + /* Region 127 */ + { + 0x8015, 0, 127, 240, 248, 37, 0, + 1050, 245, 85, 0, 0, 244, 7, + -5000, 247, 71, 0, 0, 252, 3, + 350, 240, 0, 0, 0, 164, 0, + 700, 32, 0, 0, 0, 252, 2 + }, + + /* Region 128 */ + { + 0x0005, 35, 35, 0, 255, 103, 0, + 3, 215, 68, 65, 0, 204, 2, + -1700, 249, 95, 177, 0, 252, 2, + 5374, 236, 144, 204, 0, 176, 3, + 114, 253, 144, 179, 0, 200, 3 + }, + + /* Region 129 */ + { + 0x0005, 36, 36, 0, 255, 103, 0, + 3, 219, 68, 65, 0, 204, 2, + -1700, 251, 95, 177, 0, 252, 2, + 5374, 255, 144, 204, 0, 176, 3, + 114, 255, 144, 179, 0, 208, 3 + }, + + /* Region 130 */ + { + 0x001a, 37, 37, 240, 128, 216, 0, + 2780, 255, 16, 0, 112, 200, 3, + 3800, 255, 32, 0, 0, 240, 3, + 2501, 251, 48, 0, 48, 240, 3, + 2751, 254, 48, 0, 0, 244, 3 + }, + + /* Region 131 */ + { + 0x000d, 38, 38, 0, 255, 190, 0, + -2000, 239, 48, 128, 0, 236, 3, + -2400, 254, 92, 128, 0, 252, 2, + 3374, 255, 33, 192, 240, 244, 2, + 1000, 255, 49, 176, 240, 204, 2 + }, + + /* Region 132 */ + { + 0x001a, 39, 39, 240, 128, 254, -10, + 5780, 186, 16, 0, 112, 240, 3, + 3800, 254, 32, 0, 0, 248, 3, + 5780, 234, 16, 0, 112, 240, 3, + 4829, 254, 32, 0, 0, 252, 3 + }, + + /* Region 133 */ + { + 0x000d, 40, 40, 0, 255, 203, 0, + 0, 254, 74, 128, 0, 176, 3, + -600, 252, 73, 128, 0, 252, 3, + 3368, 251, 80, 192, 0, 244, 3, + 1200, 254, 64, 176, 0, 208, 3 + }, + + /* Region 134 */ + { + 0x000d, 41, 41, 208, 16, 187, -30, + -600, 247, 128, 0, 0, 204, 1, + -890, 248, 88, 0, 0, 252, 3, + 1068, 250, 182, 0, 0, 200, 3, + -100, 249, 116, 0, 0, 208, 3 + }, + + /* Region 135 */ + { + 0x0005, 42, 42, 160, 255, 126, 20, + 3514, 247, 23, 72, 0, 212, 3, + 400, 255, 94, 177, 0, 232, 2, + 2347, 250, 47, 0, 196, 184, 6, + 4388, 248, 26, 0, 136, 224, 2 + }, + + /* Region 136 */ + { + 0x000d, 43, 43, 208, 16, 187, -20, + -500, 247, 128, 0, 0, 204, 1, + -690, 249, 88, 0, 0, 252, 3, + 1068, 254, 182, 0, 0, 200, 3, + 0, 249, 116, 0, 0, 208, 3 + }, + + /* Region 137 */ + { + 0x0005, 44, 44, 160, 255, 126, 20, + 3514, 151, 20, 72, 0, 244, 3, + 400, 223, 92, 177, 0, 240, 2, + 2347, 134, 34, 0, 176, 208, 6, + 4388, 200, 21, 0, 100, 220, 2 + }, + + /* Region 138 */ + { + 0x000d, 45, 45, 208, 16, 187, -10, + -350, 246, 128, 0, 0, 204, 1, + -590, 249, 88, 0, 0, 252, 3, + 2368, 254, 182, 0, 0, 196, 3, + 500, 249, 116, 0, 0, 208, 3 + }, + + /* Region 139 */ + { + 0x0005, 46, 46, 160, 255, 126, 20, + 3510, 147, 51, 72, 0, 236, 3, + 400, 219, 90, 177, 0, 240, 2, + 2347, 134, 66, 0, 176, 224, 6, + 4388, 200, 84, 0, 100, 212, 2 + }, + + /* Region 140 */ + { + 0x000d, 47, 47, 176, 32, 187, 10, + 0, 247, 128, 0, 0, 204, 1, + -280, 249, 88, 0, 0, 252, 3, + 2968, 255, 182, 0, 0, 200, 3, + 700, 250, 116, 0, 0, 204, 3 + }, + + /* Region 141 */ + { + 0x000d, 48, 48, 0, 255, 187, 20, + 10, 247, 128, 0, 0, 204, 3, + -130, 249, 88, 0, 0, 252, 3, + 3068, 255, 182, 0, 0, 188, 3, + 800, 250, 116, 0, 0, 204, 3 + }, + + /* Region 142 */ + { + 0x000d, 49, 49, 160, 255, 215, 20, + 3986, 18, 6, 8, 0, 252, 2, + 0, 247, 70, 1, 0, 240, 2, + 5354, 242, 48, 0, 252, 216, 2, + 3868, 193, 48, 0, 212, 208, 2 + }, + + /* Region 143 */ + { + 0x000d, 50, 50, 0, 255, 201, 30, + 200, 247, 128, 0, 0, 208, 3, + 20, 249, 88, 0, 0, 252, 3, + 3368, 255, 182, 0, 0, 200, 3, + 1100, 250, 116, 0, 0, 204, 3 + }, + + /* Region 144 */ + { + 0x000d, 51, 51, 160, 255, 97, -20, + 3831, 240, 39, 0, 232, 224, 3, + 1258, 246, 102, 0, 0, 232, 3, + 4323, 242, 32, 0, 0, 216, 3, + 868, 243, 64, 0, 0, 204, 3 + }, + + /* Region 145 */ + { + 0x000d, 52, 52, 112, 128, 234, -20, + 725, 228, 32, 0, 0, 208, 1, + 400, 248, 86, 0, 0, 248, 3, + 2003, 53, 32, 0, 0, 236, 3, + 100, 209, 32, 0, 0, 212, 1 + }, + + /* Region 146 */ + { + 0x000d, 53, 53, 160, 255, 97, -20, + 3831, 240, 39, 0, 232, 224, 3, + 1258, 246, 102, 0, 0, 232, 3, + 4323, 242, 32, 0, 0, 224, 3, + 868, 243, 64, 0, 0, 196, 3 + }, + + /* Region 147 */ + { + 0x001d, 54, 54, 240, 240, 242, 10, + -1, 245, 71, 1, 24, 236, 0, + 1200, 218, 102, 1, 0, 236, 2, + 1354, 255, 48, 0, 0, 208, 2, + 5868, 209, 48, 0, 160, 212, 0 + }, + + /* Region 148 */ + { + 0x000d, 55, 55, 48, 32, 234, -10, + 725, 228, 32, 0, 0, 208, 3, + 900, 249, 86, 0, 0, 240, 3, + 2303, 69, 32, 0, 0, 236, 1, + 400, 177, 32, 0, 0, 212, 3 + }, + + /* Region 149 */ + { + 0x000d, 56, 56, 0, 255, 149, 20, + 414, 254, 123, 48, 0, 204, 3, + 1986, 252, 118, 48, 0, 244, 3, + 4383, 242, 67, 48, 0, 200, 3, + 4205, 243, 81, 48, 0, 204, 3 + }, + + /* Region 150 */ + { + 0x000d, 57, 57, 48, 32, 234, -20, + 526, 210, 32, 0, 0, 200, 3, + 719, 246, 86, 0, 0, 240, 3, + 1303, 48, 32, 0, 0, 236, 1, + 202, 98, 32, 0, 0, 212, 3 + }, + + /* Region 151 */ + { + 0x001d, 58, 58, 240, 240, 204, -40, + 5650, 247, 16, 0, 84, 220, 1, + 3800, 248, 32, 0, 0, 248, 3, + 1780, 252, 16, 0, 0, 152, 3, + 6825, 245, 32, 0, 0, 208, 1 + }, + + /* Region 152 */ + { + 0x000d, 59, 59, 144, 0, 108, -20, + 3531, 240, 103, 0, 232, 220, 3, + 1058, 246, 102, 0, 0, 232, 3, + 5331, 242, 64, 0, 0, 220, 3, + 1968, 243, 64, 0, 0, 204, 1 + }, + + /* Region 153 */ + { + 0x000d, 60, 60, 192, 64, 155, 40, + 700, 214, 84, 0, 0, 208, 1, + 950, 253, 76, 0, 0, 248, 3, + 2803, 255, 127, 0, 0, 200, 3, + 750, 255, 89, 0, 0, 204, 3 + }, + + /* Region 154 */ + { + 0x000d, 61, 61, 224, 48, 91, 40, + 400, 229, 68, 0, 0, 204, 1, + 700, 251, 76, 0, 0, 248, 3, + 1803, 255, 95, 0, 0, 196, 3, + 450, 255, 89, 0, 0, 208, 3 + }, + + /* Region 155 */ + { + 0x000d, 62, 62, 240, 32, 191, 25, + 214, 237, 69, 0, 0, 204, 1, + 400, 252, 78, 0, 0, 248, 3, + 2830, 255, 95, 0, 0, 208, 3, + 2500, 255, 25, 0, 0, 192, 3 + }, + + /* Region 156 */ + { + 0x000d, 63, 63, 240, 32, 91, 25, + 400, 229, 68, 0, 0, 188, 1, + -100, 250, 76, 0, 0, 248, 3, + 1803, 254, 95, 0, 0, 200, 3, + 450, 238, 89, 0, 0, 200, 3 + }, + + /* Region 157 */ + { + 0x000d, 64, 64, 240, 16, 91, 20, + 300, 210, 68, 0, 0, 196, 1, + -400, 250, 76, 0, 0, 248, 3, + 1803, 254, 95, 0, 0, 200, 3, + 550, 238, 89, 0, 0, 200, 3 + }, + + /* Region 158 */ + { + 0x001c, 65, 65, 240, 128, 223, 20, + 1780, 234, 16, 0, 112, 208, 3, + 800, 251, 32, 0, 0, 248, 3, + 5501, 231, 48, 0, 48, 200, 3, + 2751, 232, 48, 0, 0, 220, 3 + }, + + /* Region 159 */ + { + 0x001c, 66, 66, 240, 128, 223, 20, + 1580, 234, 16, 0, 112, 208, 3, + 600, 250, 32, 0, 0, 248, 3, + 5201, 231, 48, 0, 48, 200, 3, + 2510, 232, 48, 0, 0, 220, 3 + }, + + /* Region 160 */ + { + 0x000d, 67, 67, 0, 255, 0, -35, + 1514, 255, 63, 51, 0, 184, 3, + 4830, 251, 73, 51, 0, 252, 3, + 4349, 245, 67, 51, 0, 212, 3, + 5267, 246, 65, 51, 0, 200, 3 + }, + + /* Region 161 */ + { + 0x000d, 68, 68, 0, 255, 0, -35, + 1514, 255, 63, 51, 0, 196, 3, + 4905, 251, 73, 51, 0, 252, 3, + 4349, 245, 67, 51, 0, 196, 3, + 5214, 246, 65, 51, 0, 208, 3 + }, + + /* Region 162 */ + { + 0x000a, 69, 69, 240, 240, 243, -35, + 10000, 160, 68, 0, 0, 200, 3, + 7000, 156, 140, 0, 0, 228, 3, + 1586, 176, 16, 0, 0, 228, 7, + 8000, 140, 80, 0, 0, 236, 3 + }, + + /* Region 163 */ + { + 0x001a, 70, 70, 240, 240, 227, -38, + 500, 240, 52, 0, 0, 220, 1, + 8000, 188, 124, 0, 0, 228, 3, + 1586, 240, 16, 0, 0, 224, 7, + 8000, 203, 80, 0, 0, 228, 3 + }, + + /* Region 164 */ + { + 0x0004, 71, 71, 226, 240, 181, 35, + 7253, 224, 32, 48, 0, 184, 3, + 3594, 224, 79, 48, 0, 248, 1, + 220, 97, 19, 48, 156, 152, 3, + 5243, 172, 16, 48, 92, 204, 1 + }, + + /* Region 165 */ + { + 0x0004, 72, 72, 240, 241, 181, 35, + 6253, 134, 32, 48, 0, 184, 3, + 3994, 176, 76, 48, 160, 248, 1, + 22, 183, 19, 48, 156, 172, 3, + 1243, 160, 16, 48, 240, 188, 3 + }, + + /* Region 166 */ + { + 0x001a, 73, 73, 240, 224, 155, 30, + -2145, 240, 70, 0, 0, 252, 3, + 600, 109, 111, 0, 0, 240, 3, + -1800, 240, 71, 0, 0, 248, 3, + 200, 173, 111, 0, 0, 240, 3 + }, + + /* Region 167 */ + { + 0x0012, 74, 74, 240, 224, 119, 30, + -2545, 240, 70, 0, 252, 252, 3, + 0, 153, 111, 0, 0, 240, 3, + -2400, 240, 71, 0, 252, 252, 3, + 100, 137, 111, 0, 0, 240, 3 + }, + + /* Region 168 */ + { + 0x001a, 75, 75, 240, 128, 240, 20, + 3780, 255, 16, 0, 252, 188, 2, + 800, 255, 64, 0, 0, 248, 2, + 2501, 255, 48, 0, 252, 208, 0, + 751, 255, 48, 0, 0, 236, 2 + }, + + /* Region 169 */ + { + 0x000d, 76, 76, 0, 255, 68, 35, + 1100, 239, 69, 0, 0, 184, 3, + 2600, 255, 76, 0, 0, 252, 3, + 5000, 255, 111, 0, 0, 204, 3, + 3400, 254, 73, 0, 0, 184, 3 + }, + + /* Region 170 */ + { + 0x000d, 77, 77, 0, 255, 68, 35, + 914, 239, 69, 0, 0, 180, 3, + 1801, 254, 76, 0, 0, 252, 3, + 4800, 255, 111, 0, 0, 192, 3, + 3200, 254, 73, 0, 0, 192, 3 + }, + + /* Region 171 */ + { + 0x000d, 78, 78, 240, 32, 197, -20, + 1200, 216, 86, 0, 0, 180, 1, + 1800, 189, 127, 0, 0, 244, 3, + 2700, 156, 102, 0, 0, 196, 1, + 700, 109, 104, 0, 0, 196, 1 + }, + + /* Region 172 */ + { + 0x000d, 79, 79, 240, 32, 197, -20, + 1200, 216, 86, 0, 0, 196, 1, + 2200, 171, 127, 0, 0, 244, 3, + 2700, 145, 102, 0, 0, 192, 1, + 700, 106, 104, 0, 0, 192, 1 + }, + + /* Region 173 */ + { + 0x000d, 80, 80, 0, 255, 0, -40, + 3514, 254, 79, 51, 0, 196, 3, + 5905, 252, 73, 51, 0, 248, 3, + 6348, 245, 35, 51, 0, 176, 3, + 2203, 244, 33, 51, 0, 216, 3 + }, + + /* Region 174 */ + { + 0x800d, 81, 81, 0, 255, 0, -40, + 3514, 255, 79, 51, 0, 192, 3, + 5905, 246, 73, 51, 0, 252, 3, + 6348, 241, 35, 51, 0, 180, 3, + 2203, 242, 33, 51, 0, 212, 3 + } +}; + + +/*---------------------------------------------------------------------------- + * Programs + *---------------------------------------------------------------------------- +*/ +const S_PROGRAM programs[] = +{ + { 7864320, 128 } /* program 0 */ +}; /* end Programs */ + +/*---------------------------------------------------------------------------- + * Banks + *---------------------------------------------------------------------------- +*/ +const S_BANK banks[] = +{ + { /* bank 0 */ + 30976, + { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 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, 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, 127 + } + } +}; /* end Banks */ + +/*---------------------------------------------------------------------------- + * S_EAS + *---------------------------------------------------------------------------- +*/ +const S_EAS easSoundLib = +{ + 0x01534145, + 0x00105622, + + banks, + programs, + + NULL, + NULL, + NULL, + NULL, + NULL, + + regions, + + 1, + 1, + + 0, + 0, + 0, + + 175 +}; /* end S_EAS */ +/* end sound library */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsynth.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsynth.c new file mode 100755 index 0000000..629506a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsynth.c @@ -0,0 +1,910 @@ +/*---------------------------------------------------------------------------- + * + * File: + * fmsynth.c + * + * Contents and purpose: + * Implements the high-level FM synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_host.h" +#include "eas_report.h" + +#include "eas_data.h" +#include "eas_synth_protos.h" +#include "eas_audioconst.h" +#include "eas_fmengine.h" +#include "eas_math.h" + +/* option sanity check */ +#ifdef _REVERB +#error "No reverb for FM synthesizer" +#endif +#ifdef _CHORUS +#error "No chorus for FM synthesizer" +#endif + +/* + * WARNING: These macros can cause unwanted side effects. Use them + * with care. For example, min(x++,y++) will cause either x or y to be + * incremented twice. + */ +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define max(a,b) ((a) > (b) ? (a) : (b)) + +/* pivot point for keyboard scalars */ +#define EG_SCALE_PIVOT_POINT 64 +#define KEY_SCALE_PIVOT_POINT 36 + +/* This number is the negative of the frequency of the note (in cents) of + * the sine wave played at unity. The number can be calculated as follows: + * + * MAGIC_NUMBER = 1200 * log(base2) (SINE_TABLE_SIZE * 8.175798916 / SAMPLE_RATE) + * + * 8.17578 is a reference to the frequency of MIDI note 0 + */ +#if defined (_SAMPLE_RATE_8000) +#define MAGIC_NUMBER 1279 +#elif defined (_SAMPLE_RATE_16000) +#define MAGIC_NUMBER 79 +#elif defined (_SAMPLE_RATE_20000) +#define MAGIC_NUMBER -308 +#elif defined (_SAMPLE_RATE_22050) +#define MAGIC_NUMBER -477 +#elif defined (_SAMPLE_RATE_24000) +#define MAGIC_NUMBER -623 +#elif defined (_SAMPLE_RATE_32000) +#define MAGIC_NUMBER -1121 +#elif defined (_SAMPLE_RATE_44100) +#define MAGIC_NUMBER -1677 +#elif defined (_SAMPLE_RATE_48000) +#define MAGIC_NUMBER -1823 +#endif + +/* externs */ +extern const EAS_I16 fmControlTable[128]; +extern const EAS_U16 fmRateTable[256]; +extern const EAS_U16 fmAttackTable[16]; +extern const EAS_U8 fmDecayTable[16]; +extern const EAS_U8 fmReleaseTable[16]; +extern const EAS_U8 fmScaleTable[16]; + +/* local prototypes */ +/*lint -esym(715, pVoiceMgr) standard synthesizer interface - pVoiceMgr not used */ +static EAS_RESULT FM_Initialize (S_VOICE_MGR *pVoiceMgr) { return EAS_SUCCESS; } +static EAS_RESULT FM_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); +static EAS_BOOL FM_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); +static void FM_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +static void FM_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +static void FM_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); +static void FM_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + + +/*---------------------------------------------------------------------------- + * Synthesizer interface + *---------------------------------------------------------------------------- +*/ +const S_SYNTH_INTERFACE fmSynth = +{ + FM_Initialize, + FM_StartVoice, + FM_UpdateVoice, + FM_ReleaseVoice, + FM_MuteVoice, + FM_SustainPedal, + FM_UpdateChannel +}; + +#ifdef FM_OFFBOARD +const S_FRAME_INTERFACE fmFrameInterface = +{ + FM_StartFrame, + FM_EndFrame +}; +#endif + +/*---------------------------------------------------------------------------- + * inline functions + *---------------------------------------------------------------------------- + */ +EAS_INLINE S_FM_VOICE *GetFMVoicePtr (S_VOICE_MGR *pVoiceMgr, EAS_INT voiceNum) +{ + return &pVoiceMgr->fmVoices[voiceNum]; +} +EAS_INLINE S_SYNTH_CHANNEL *GetChannelPtr (S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice) +{ + return &pSynth->channels[pVoice->channel & 15]; +} +EAS_INLINE const S_FM_REGION *GetFMRegionPtr (S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice) +{ +#ifdef _SECONDARY_SYNTH + return &pSynth->pEAS->pFMRegions[pVoice->regionIndex & REGION_INDEX_MASK]; +#else + return &pSynth->pEAS->pFMRegions[pVoice->regionIndex]; +#endif +} + +/*---------------------------------------------------------------------------- + * FM_SynthIsOutputOperator + *---------------------------------------------------------------------------- + * Purpose: + * Returns true if the operator is a direct output and not muted + * + * Inputs: + * + * Outputs: + * Returns boolean + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL FM_SynthIsOutputOperator (const S_FM_REGION *pRegion, EAS_INT operIndex) +{ + + /* see if voice is muted */ + if ((pRegion->oper[operIndex].gain & 0xfc) == 0) + return 0; + + /* check based on mode */ + switch (pRegion->region.keyGroupAndFlags & 7) + { + + /* mode 0 - all operators are external */ + case 0: + return EAS_TRUE; + + /* mode 1 - operators 1-3 are external */ + case 1: + if (operIndex != 0) + return EAS_TRUE; + break; + + /* mode 2 - operators 1 & 3 are external */ + case 2: + if ((operIndex == 1) || (operIndex == 3)) + return EAS_TRUE; + break; + + /* mode 2 - operators 1 & 2 are external */ + case 3: + if ((operIndex == 1) || (operIndex == 2)) + return EAS_TRUE; + break; + + /* modes 4 & 5 - operator 1 is external */ + case 4: + case 5: + if (operIndex == 1) + return EAS_TRUE; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL,"Invalid voice mode: %d", + pRegion->region.keyGroupAndFlags & 7); */ } + } + + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * FM_CalcEGRate() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * nKeyNumber - MIDI note + * nLogRate - logarithmic scale rate from patch data + * nKeyScale - key scaling factor for this EG + * + * Outputs: + * 16-bit linear multiplier + *---------------------------------------------------------------------------- +*/ + +static EAS_U16 FM_CalcEGRate (EAS_U8 nKeyNumber, EAS_U8 nLogRate, EAS_U8 nEGScale) +{ + EAS_I32 temp; + + /* incorporate key scaling on release rate */ + temp = (EAS_I32) nLogRate << 7; + temp += ((EAS_I32) nKeyNumber - EG_SCALE_PIVOT_POINT) * (EAS_I32) nEGScale; + + /* saturate */ + temp = max(temp, 0); + temp = min(temp, 32767); + + /* look up in rate table */ + /*lint -e{704} use shift for performance */ + return fmRateTable[temp >> 8]; +} + +/*---------------------------------------------------------------------------- + * FM_ReleaseVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being released. + * + * Inputs: + * psEASData - pointer to S_EAS_DATA + * pVoice - pointer to voice to release + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static void FM_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + EAS_INT operIndex; + const S_FM_REGION *pRegion; + S_FM_VOICE *pFMVoice; + + /* check to see if voice responds to NOTE-OFF's */ + pRegion = GetFMRegionPtr(pSynth, pVoice); + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_ONE_SHOT) + return; + + /* set all envelopes to release state */ + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + for (operIndex = 0; operIndex < 4; operIndex++) + { + pFMVoice->oper[operIndex].envState = eFMEnvelopeStateRelease; + + /* incorporate key scaling on release rate */ + pFMVoice->oper[operIndex].envRate = FM_CalcEGRate( + pVoice->note, + fmReleaseTable[pRegion->oper[operIndex].velocityRelease & 0x0f], + fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]); + } /* end for (operIndex = 0; operIndex < 4; operIndex++) */ +} + +/*---------------------------------------------------------------------------- + * FM_MuteVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being muted. + * + * Inputs: + * pVoice - pointer to voice to release + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pSynth) standard interface, pVoiceMgr not used */ +static void FM_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + S_FM_VOICE *pFMVoice; + + /* clear deferred action flags */ + pVoice->voiceFlags &= + ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | + VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF | + VOICE_FLAG_DEFER_MUTE); + + /* set all envelopes to muted state */ + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + pFMVoice->oper[0].envState = eFMEnvelopeStateMuted; + pFMVoice->oper[1].envState = eFMEnvelopeStateMuted; + pFMVoice->oper[2].envState = eFMEnvelopeStateMuted; + pFMVoice->oper[3].envState = eFMEnvelopeStateMuted; +} + +/*---------------------------------------------------------------------------- + * FM_SustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is held due to sustain pedal + * + * Inputs: + * pVoice - pointer to voice to sustain + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pChannel) standard interface, pVoiceMgr not used */ +static void FM_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) +{ + const S_FM_REGION *pRegion; + S_FM_VOICE *pFMVoice; + EAS_INT operIndex; + + pRegion = GetFMRegionPtr(pSynth, pVoice); + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + + /* check to see if any envelopes are above the sustain level */ + for (operIndex = 0; operIndex < 4; operIndex++) + { + + /* if level control or envelope gain is zero, skip this envelope */ + if (((pRegion->oper[operIndex].gain & 0xfc) == 0) || + (pFMVoice->oper[operIndex].envGain == 0)) + { + continue; + } + + /* if the envelope gain is above the sustain level, we need to catch this voice */ + if (pFMVoice->oper[operIndex].envGain >= ((EAS_U16) (pRegion->oper[operIndex].sustain & 0xfc) << 7)) + { + + /* reset envelope to decay state */ + pFMVoice->oper[operIndex].envState = eFMEnvelopeStateDecay; + + pFMVoice->oper[operIndex].envRate = FM_CalcEGRate( + pVoice->note, + fmDecayTable[pRegion->oper[operIndex].attackDecay & 0x0f], + fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]); + + /* set voice to decay state */ + pVoice->voiceState = eVoiceStatePlay; + + /* set sustain flag */ + pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + } + } /* end for (operIndex = 0; operIndex < 4; operIndex++) */ +} + +/*---------------------------------------------------------------------------- + * FM_StartVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the region for the given instrument using the midi key number + * and the RPN2 (coarse tuning) value. By using RPN2 as part of the + * region selection process, we reduce the amount a given sample has + * to be transposed by selecting the closest recorded root instead. + * + * This routine is the second half of SynthAssignRegion(). + * If the region was successfully found by SynthFindRegionIndex(), + * then assign the region's parameters to the voice. + * + * Setup and initialize the following voice parameters: + * m_nRegionIndex + * + * Inputs: + * pVoice - ptr to the voice we have assigned for this channel + * nRegionIndex - index of the region + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * success - could find and assign the region for this voice's note otherwise + * failure - could not find nor assign the region for this voice's note + * + * Side Effects: + * psSynthObject->m_sVoice[].m_nRegionIndex is assigned + * psSynthObject->m_sVoice[] parameters are assigned + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT FM_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) +{ + S_FM_VOICE *pFMVoice; + S_SYNTH_CHANNEL *pChannel; + const S_FM_REGION *pRegion; + EAS_I32 temp; + EAS_INT operIndex; + + /* establish pointers to data */ + pVoice->regionIndex = regionIndex; + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + pChannel = GetChannelPtr(pSynth, pVoice); + pRegion = GetFMRegionPtr(pSynth, pVoice); + + /* update static channel parameters */ + if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS) + FM_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15); + + /* init the LFO */ + pFMVoice->lfoValue = 0; + pFMVoice->lfoPhase = 0; + pFMVoice->lfoDelay = (EAS_U16) (fmScaleTable[pRegion->lfoFreqDelay & 0x0f] >> 1); + +#if (NUM_OUTPUT_CHANNELS == 2) + /* calculate pan gain values only if stereo output */ + /* set up panning only at note start */ + temp = (EAS_I32) pChannel->pan - 64; + temp += (EAS_I32) pRegion->pan; + if (temp < -64) + temp = -64; + if (temp > 64) + temp = 64; + pFMVoice->pan = (EAS_I8) temp; +#endif /* #if (NUM_OUTPUT_CHANNELS == 2) */ + + /* no samples have been synthesized for this note yet */ + pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + + /* initialize gain value for anti-zipper filter */ + pFMVoice->voiceGain = (EAS_I16) EAS_LogToLinear16(pChannel->staticGain); + pFMVoice->voiceGain = (EAS_I16) FMUL_15x15(pFMVoice->voiceGain, pSynth->masterVolume); + + /* initialize the operators */ + for (operIndex = 0; operIndex < 4; operIndex++) + { + + /* establish operator output gain level */ + /*lint -e{701} */ + pFMVoice->oper[operIndex].outputGain = EAS_LogToLinear16(((EAS_I16) (pRegion->oper[operIndex].gain & 0xfc) - 0xfc) << 7); + + /* check for linear velocity flag */ + /*lint -e{703} */ + if (pRegion->oper[operIndex].flags & FM_OPER_FLAG_LINEAR_VELOCITY) + temp = (EAS_I32) (pVoice->velocity - 127) << 5; + else + temp = (EAS_I32) fmControlTable[pVoice->velocity]; + + /* scale velocity */ + /*lint -e{704} use shift for performance */ + temp = (temp * (EAS_I32)(pRegion->oper[operIndex].velocityRelease & 0xf0)) >> 7; + + /* include key scalar */ + temp -= ((EAS_I32) pVoice->note - KEY_SCALE_PIVOT_POINT) * (EAS_I32) fmScaleTable[pRegion->oper[operIndex].egKeyScale & 0x0f]; + + /* saturate */ + temp = min(temp, 0); + temp = max(temp, -32768); + + /* save static gain parameters */ + pFMVoice->oper[operIndex].baseGain = (EAS_I16) EAS_LogToLinear16(temp); + + /* incorporate key scaling on decay rate */ + pFMVoice->oper[operIndex].envRate = FM_CalcEGRate( + pVoice->note, + fmDecayTable[pRegion->oper[operIndex].attackDecay & 0x0f], + fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]); + + /* if zero attack time, max out envelope and jump to decay state */ + if ((pRegion->oper[operIndex].attackDecay & 0xf0) == 0xf0) + { + + /* start out envelope at max */ + pFMVoice->oper[operIndex].envGain = 0x7fff; + + /* set envelope to decay state */ + pFMVoice->oper[operIndex].envState = eFMEnvelopeStateDecay; + } + + /* start envelope at zero and start in attack state */ + else + { + pFMVoice->oper[operIndex].envGain = 0; + pFMVoice->oper[operIndex].envState = eFMEnvelopeStateAttack; + } + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateChannel() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate and assign static channel parameters + * These values only need to be updated if one of the controller values + * for this channel changes. + * Called when CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS flag is set. + * + * Inputs: + * nChannel - channel to update + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - the given channel's static gain and static pitch are updated + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) standard interface, pVoiceMgr not used */ +static void FM_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_I32 temp; + + pChannel = &pSynth->channels[channel]; + + /* convert CC7 volume controller to log scale */ + temp = fmControlTable[pChannel->volume]; + + /* incorporate CC11 expression controller */ + temp += fmControlTable[pChannel->expression]; + + /* saturate */ + pChannel->staticGain = (EAS_I16) max(temp,-32768); + + /* calculate pitch bend */ + /*lint -e{703} */ + temp = (((EAS_I32)(pChannel->pitchBend) << 2) - 32768); + + temp = FMUL_15x15(temp, pChannel->pitchBendSensitivity); + + /* include "magic number" compensation for sample rate and lookup table size */ + temp += MAGIC_NUMBER; + + /* if this is not a drum channel, then add in the per-channel tuning */ + if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL)) + temp += (pChannel->finePitch + (pChannel->coarsePitch * 100)); + + /* save static pitch */ + pChannel->staticPitch = temp; + + /* Calculate LFO modulation depth */ + /* mod wheel to LFO depth */ + temp = FMUL_15x15(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS, + pChannel->modWheel << (NUM_EG1_FRAC_BITS -7)); + + /* channel pressure to LFO depth */ + pChannel->lfoAmt = (EAS_I16) (temp + + FMUL_15x15(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS, + pChannel->channelPressure << (NUM_EG1_FRAC_BITS -7))); + + /* clear update flag */ + pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + return; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateLFO() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the LFO for the given voice + * + * Inputs: + * pVoice - ptr to the voice whose LFO we want to update + * psEASData - pointer to overall EAS data structure - used for debug only + * + * Outputs: + * + * Side Effects: + * - updates LFO values for the given voice + *---------------------------------------------------------------------------- +*/ +static void FM_UpdateLFO (S_FM_VOICE *pFMVoice, const S_FM_REGION *pRegion) +{ + + /* increment the LFO phase if the delay time has elapsed */ + if (!pFMVoice->lfoDelay) + { + /*lint -e{701} */ + pFMVoice->lfoPhase = pFMVoice->lfoPhase + (EAS_U16) (-fmControlTable[((15 - (pRegion->lfoFreqDelay >> 4)) << 3) + 4]); + + /* square wave LFO? */ + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_SQUARE_WAVE) + pFMVoice->lfoValue = (EAS_I16)(pFMVoice->lfoPhase & 0x8000 ? -32767 : 32767); + + /* trick to get a triangle wave out of a sawtooth */ + else + { + pFMVoice->lfoValue = (EAS_I16) (pFMVoice->lfoPhase << 1); + /*lint -e{502} */ + if ((pFMVoice->lfoPhase > 0x3fff) && (pFMVoice->lfoPhase < 0xC000)) + pFMVoice->lfoValue = ~pFMVoice->lfoValue; + } + } + + /* still in delay */ + else + pFMVoice->lfoDelay--; + + return; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateEG() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the synthesis parameters for an operator to be used during + * the next buffer + * + * Inputs: + * pVoice - pointer to the voice being updated + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL FM_UpdateEG (S_SYNTH_VOICE *pVoice, S_OPERATOR *pOper, const S_FM_OPER *pOperData, EAS_BOOL oneShot) +{ + EAS_U32 temp; + EAS_BOOL done; + + /* set flag assuming the envelope is not done */ + done = EAS_FALSE; + + /* take appropriate action based on state */ + switch (pOper->envState) + { + + case eFMEnvelopeStateAttack: + + /* the envelope is linear during the attack, so add the value */ + temp = pOper->envGain + fmAttackTable[pOperData->attackDecay >> 4]; + + /* check for end of attack */ + if (temp >= 0x7fff) + { + pOper->envGain = 0x7fff; + pOper->envState = eFMEnvelopeStateDecay; + } + else + pOper->envGain = (EAS_U16) temp; + break; + + case eFMEnvelopeStateDecay: + + /* decay is exponential, multiply by decay rate */ + pOper->envGain = (EAS_U16) FMUL_15x15(pOper->envGain, pOper->envRate); + + /* check for sustain level reached */ + temp = (EAS_U32) (pOperData->sustain & 0xfc) << 7; + if (pOper->envGain <= (EAS_U16) temp) + { + /* if this is a one-shot patch, go directly to release phase */ + if (oneShot) + { + pOper->envRate = FM_CalcEGRate( + pVoice->note, + fmReleaseTable[pOperData->velocityRelease & 0x0f], + fmScaleTable[pOperData->egKeyScale >> 4]); + pOper->envState = eFMEnvelopeStateRelease; + } + + /* normal sustaining type */ + else + { + pOper->envGain = (EAS_U16) temp; + pOper->envState = eFMEnvelopeStateSustain; + } + } + break; + + case eFMEnvelopeStateSustain: + pOper->envGain = (EAS_U16)((EAS_U16)(pOperData->sustain & 0xfc) << 7); + break; + + case eFMEnvelopeStateRelease: + + /* release is exponential, multiply by release rate */ + pOper->envGain = (EAS_U16) FMUL_15x15(pOper->envGain, pOper->envRate); + + /* fully released */ + if (pOper->envGain == 0) + { + pOper->envGain = 0; + pOper->envState = eFMEnvelopeStateMuted; + done = EAS_TRUE; + } + break; + + case eFMEnvelopeStateMuted: + pOper->envGain = 0; + done = EAS_TRUE; + break; + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL,"Invalid operator state: %d", pOper->envState); */ } + } /* end switch (pOper->m_eState) */ + + return done; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateDynamic() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the synthesis parameters for this voice that will be used to + * synthesize the next buffer + * + * Inputs: + * pVoice - pointer to the voice being updated + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Returns EAS_TRUE if voice will be fully ramped to zero at the end of + * the next synthesized buffer. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL FM_UpdateDynamic (S_SYNTH_VOICE *pVoice, S_FM_VOICE *pFMVoice, const S_FM_REGION *pRegion, S_SYNTH_CHANNEL *pChannel) +{ + EAS_I32 temp; + EAS_I32 pitch; + EAS_I32 lfoPitch; + EAS_INT operIndex; + EAS_BOOL done; + + /* increment LFO phase */ + FM_UpdateLFO(pFMVoice, pRegion); + + /* base pitch in cents */ + pitch = pVoice->note * 100; + + /* LFO amount includes LFO depth from programming + channel dynamics */ + temp = (fmScaleTable[pRegion->vibTrem >> 4] >> 1) + pChannel->lfoAmt; + + /* multiply by LFO output to get final pitch modulation */ + lfoPitch = FMUL_15x15(pFMVoice->lfoValue, temp); + + /* flag to indicate this voice is done */ + done = EAS_TRUE; + + /* iterate through operators to establish parameters */ + for (operIndex = 0; operIndex < 4; operIndex++) + { + EAS_BOOL bTemp; + + /* set base phase increment for each operator */ + temp = pRegion->oper[operIndex].tuning + + pChannel->staticPitch; + + /* add vibrato effect unless it is disabled for this operator */ + if ((pRegion->oper[operIndex].flags & FM_OPER_FLAG_NO_VIBRATO) == 0) + temp += lfoPitch; + + /* if note is monotonic, bias to MIDI note 60 */ + if (pRegion->oper[operIndex].flags & FM_OPER_FLAG_MONOTONE) + temp += 6000; + else + temp += pitch; + pFMVoice->oper[operIndex].pitch = (EAS_I16) temp; + + /* calculate envelope, returns true if done */ + bTemp = FM_UpdateEG(pVoice, &pFMVoice->oper[operIndex], &pRegion->oper[operIndex], pRegion->region.keyGroupAndFlags & REGION_FLAG_ONE_SHOT); + + /* check if all output envelopes have completed */ + if (FM_SynthIsOutputOperator(pRegion, operIndex)) + done = done && bTemp; + } + + return done; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize a block of samples for the given voice. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL FM_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples) +{ + S_SYNTH_CHANNEL *pChannel; + const S_FM_REGION *pRegion; + S_FM_VOICE *pFMVoice; + S_FM_VOICE_CONFIG vCfg; + S_FM_VOICE_FRAME vFrame; + EAS_I32 temp; + EAS_INT oper; + EAS_U16 voiceGainTarget; + EAS_BOOL done; + + /* setup some pointers */ + pChannel = GetChannelPtr(pSynth, pVoice); + pRegion = GetFMRegionPtr(pSynth, pVoice); + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + + /* if the voice is just starting, get the voice configuration data */ + if (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + { + + /* split architecture may limit the number of voice starts */ +#ifdef MAX_VOICE_STARTS + if (pVoiceMgr->numVoiceStarts == MAX_VOICE_STARTS) + return EAS_FALSE; + pVoiceMgr->numVoiceStarts++; +#endif + + /* get initial parameters */ + vCfg.feedback = pRegion->feedback; + vCfg.voiceGain = (EAS_U16) pFMVoice->voiceGain; + +#if (NUM_OUTPUT_CHANNELS == 2) + vCfg.pan = pFMVoice->pan; +#endif + + /* get voice mode */ + vCfg.flags = pRegion->region.keyGroupAndFlags & 7; + + /* get operator parameters */ + for (oper = 0; oper < 4; oper++) + { + /* calculate initial gain */ + vCfg.gain[oper] = (EAS_U16) FMUL_15x15(pFMVoice->oper[oper].baseGain, pFMVoice->oper[oper].envGain); + vCfg.outputGain[oper] = pFMVoice->oper[oper].outputGain; + + /* copy noise waveform flag */ + if (pRegion->oper[oper].flags & FM_OPER_FLAG_NOISE) + vCfg.flags |= (EAS_U8) (FLAG_FM_ENG_VOICE_OP1_NOISE << oper); + } + +#ifdef FM_OFFBOARD + FM_ConfigVoice(voiceNum, &vCfg, pVoiceMgr->pFrameBuffer); +#else + FM_ConfigVoice(voiceNum, &vCfg, NULL); +#endif + + /* clear startup flag */ + pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + } + + /* calculate new synthesis parameters */ + done = FM_UpdateDynamic(pVoice, pFMVoice, pRegion, pChannel); + + /* calculate LFO gain modulation */ + /*lint -e{702} */ + temp = ((fmScaleTable[pRegion->vibTrem & 0x0f] >> 1) * pFMVoice->lfoValue) >> FM_LFO_GAIN_SHIFT; + + /* include channel gain */ + temp += pChannel->staticGain; + + /* -32768 or lower is infinite attenuation */ + if (temp < -32767) + voiceGainTarget = 0; + + /* translate to linear gain multiplier */ + else + voiceGainTarget = EAS_LogToLinear16(temp); + + /* include synth master volume */ + voiceGainTarget = (EAS_U16) FMUL_15x15(voiceGainTarget, pSynth->masterVolume); + + /* save target values for this frame */ + vFrame.voiceGain = voiceGainTarget; + + /* assume voice output is zero */ + pVoice->gain = 0; + + /* save operator targets for this frame */ + for (oper = 0; oper < 4; oper++) + { + vFrame.gain[oper] = (EAS_U16) FMUL_15x15(pFMVoice->oper[oper].baseGain, pFMVoice->oper[oper].envGain); + vFrame.pitch[oper] = pFMVoice->oper[oper].pitch; + + /* use the highest output envelope level as the gain for the voice stealing algorithm */ + if (FM_SynthIsOutputOperator(pRegion, oper)) + pVoice->gain = max(pVoice->gain, (EAS_I16) vFrame.gain[oper]); + } + + /* consider voice gain multiplier in calculating gain for stealing algorithm */ + pVoice->gain = (EAS_I16) FMUL_15x15(voiceGainTarget, pVoice->gain); + + /* synthesize samples */ +#ifdef FM_OFFBOARD + FM_ProcessVoice(voiceNum, &vFrame, numSamples, pVoiceMgr->operMixBuffer, pVoiceMgr->voiceBuffer, pMixBuffer, pVoiceMgr->pFrameBuffer); +#else + FM_ProcessVoice(voiceNum, &vFrame, numSamples, pVoiceMgr->operMixBuffer, pVoiceMgr->voiceBuffer, pMixBuffer, NULL); +#endif + + return done; +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsynth.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsynth.h new file mode 100755 index 0000000..8ceda46 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmsynth.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_fmsynth.h + * + * Contents and purpose: + * Implements the FM synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 90 $ + * $Date: 2006-07-11 20:18:13 -0700 (Tue, 11 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef fmsynthH +#define fmsynthH + +#include "eas_data.h" + +#if defined (_FM_SYNTH) + +/* FM envelope state */ +typedef enum { + eFMEnvelopeStateAttack = 0, + eFMEnvelopeStateDecay, + eFMEnvelopeStateSustain, + eFMEnvelopeStateRelease, + eFMEnvelopeStateMuted, + eFMEnvelopeStateInvalid /* should never be in this state! */ +} E_FM_ENVELOPE_STATE; + +/*------------------------------------ + * S_OPERATOR data structure + *------------------------------------ +*/ +typedef struct s_operator_tag +{ + EAS_I16 pitch; /* operator pitch in cents */ + EAS_U16 envGain; /* envelope target */ + EAS_I16 baseGain; /* patch gain (inc. vel & key scale) */ + EAS_U16 outputGain; /* current output gain */ + EAS_U16 envRate; /* calculated envelope rate */ + EAS_U8 envState; /* envelope state */ + EAS_U8 pad; /* pad to 16-bits */ +} S_OPERATOR; +#endif + +typedef struct s_fm_voice_tag +{ + S_OPERATOR oper[4]; /* operator data */ + EAS_I16 voiceGain; /* LFO + channel parameters */ + EAS_U16 lfoPhase; /* LFO current phase */ + EAS_I16 lfoValue; /* LFO current value */ + EAS_U16 lfoDelay; /* keeps track of elapsed delay time */ + EAS_I8 pan; /* stereo pan value (-64 to +64) */ + EAS_I8 pad; /* reserved to maintain alignment */ +} S_FM_VOICE; + +#ifdef _FM_EDITOR +extern S_FM_REGION newPatch; +extern S_FM_REGION OriginalPatch; +#endif + +extern EAS_U32 freqTable[]; + +#endif diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmtables.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmtables.c new file mode 100755 index 0000000..a8ff0a2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_fmtables.c @@ -0,0 +1,368 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_fmtables.c + * + * Contents and purpose: + * Contains lookup tables for the FM synthesizer + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + * + *---------------------------------------------------------------------------- +*/ + + +#include "eas_types.h" + +/* this table is needed by the DSP and the main processor */ +const EAS_U8 fmScaleTable[16] = +{ + 0,8,16,24,32,40,48,56,64,72,80,96,128,160,192,255 +}; + +/* these tables are needed on the main processor */ +#ifndef _DSP_CODE +const EAS_I16 fmControlTable[128] = +{ + -32768,-14313,-12265,-11067,-10217,-9558,-9019,-8563, + -8169,-7821,-7510,-7228,-6971,-6734,-6515,-6312, + -6121,-5942,-5773,-5613,-5462,-5317,-5180,-5049, + -4923,-4802,-4686,-4575,-4467,-4364,-4264,-4167, + -4073,-3982,-3894,-3808,-3725,-3644,-3565,-3488, + -3414,-3341,-3269,-3200,-3132,-3066,-3001,-2937, + -2875,-2814,-2754,-2696,-2638,-2582,-2527,-2473, + -2419,-2367,-2316,-2265,-2216,-2167,-2119,-2071, + -2025,-1979,-1934,-1889,-1846,-1803,-1760,-1718, + -1677,-1636,-1596,-1556,-1517,-1478,-1440,-1403, + -1366,-1329,-1293,-1257,-1221,-1186,-1152,-1118, + -1084,-1051,-1018,-985,-953,-921,-889,-858, + -827,-796,-766,-736,-706,-677,-648,-619, + -590,-562,-534,-506,-479,-452,-425,-398, + -371,-345,-319,-293,-268,-242,-217,-192, + -168,-143,-119,-95,-71,-47,-23,0 +}; + +const EAS_U16 fmRateTable[128] = +{ + 32767,32764,32758,32747,32731,32712,32688,32659, + 32627,32590,32548,32503,32453,32398,32340,32277, + 32211,32140,32065,31985,31902,31815,31724,31628, + 31529,31426,31319,31208,31094,30976,30854,30728, + 30599,30466,30330,30191,30048,29902,29752,29599, + 29443,29285,29123,28958,28790,28619,28445,28269, + 28090,27909,27725,27538,27349,27158,26964,26769, + 26571,26371,26169,25965,25760,25552,25343,25132, + 24920,24706,24490,24274,24056,23836,23616,23394, + 23172,22948,22724,22499,22273,22046,21819,21591, + 21363,21135,20906,20676,20447,20217,19987,19758, + 19528,19298,19069,18840,18610,18382,18153,17926, + 17698,17471,17245,17020,16795,16571,16347,16125, + 15903,15683,15463,15245,15027,14811,14596,14382, + 14169,13957,13747,13538,13331,13125,12920,12717, + 12516,12316,12117,11921,11725,11532,11340,0 +}; + +const EAS_U16 fmAttackTable[15] = +{ + 27,54,109,327,655,1310,2730,4095, + 4681,5461,6553,8191,10922,16383,32767 +}; + +const EAS_U8 fmDecayTable[16] = +{ + 4,7,10,15,20,25,30,35,40,50,60,70,80,90,100,127 +}; + +const EAS_U8 fmReleaseTable[16] = +{ + 10,15,20,25,30,35,40,45,50,60,70,80,90,100,113,127 +}; +#endif + +/* this table is needed only on the DSP */ +#if defined(_DSP_CODE) || !defined(_SPLIT_ARCHITECTURE) +//--------------------------------------------------------------------- +// sineTable +// +// Contains sine lookup table +//--------------------------------------------------------------------- + +const EAS_I16 sineTable[2048] = +{ + 0,101,201,302,402,503,603,704, + 804,905,1005,1106,1206,1307,1407,1507, + 1608,1708,1809,1909,2009,2110,2210,2310, + 2410,2511,2611,2711,2811,2911,3012,3112, + 3212,3312,3412,3512,3612,3712,3811,3911, + 4011,4111,4210,4310,4410,4509,4609,4708, + 4808,4907,5007,5106,5205,5305,5404,5503, + 5602,5701,5800,5899,5998,6096,6195,6294, + 6393,6491,6590,6688,6786,6885,6983,7081, + 7179,7277,7375,7473,7571,7669,7767,7864, + 7962,8059,8157,8254,8351,8448,8545,8642, + 8739,8836,8933,9030,9126,9223,9319,9416, + 9512,9608,9704,9800,9896,9992,10087,10183, + 10278,10374,10469,10564,10659,10754,10849,10944, + 11039,11133,11228,11322,11417,11511,11605,11699, + 11793,11886,11980,12074,12167,12260,12353,12446, + 12539,12632,12725,12817,12910,13002,13094,13187, + 13279,13370,13462,13554,13645,13736,13828,13919, + 14010,14101,14191,14282,14372,14462,14553,14643, + 14732,14822,14912,15001,15090,15180,15269,15358, + 15446,15535,15623,15712,15800,15888,15976,16063, + 16151,16238,16325,16413,16499,16586,16673,16759, + 16846,16932,17018,17104,17189,17275,17360,17445, + 17530,17615,17700,17784,17869,17953,18037,18121, + 18204,18288,18371,18454,18537,18620,18703,18785, + 18868,18950,19032,19113,19195,19276,19357,19438, + 19519,19600,19680,19761,19841,19921,20000,20080, + 20159,20238,20317,20396,20475,20553,20631,20709, + 20787,20865,20942,21019,21096,21173,21250,21326, + 21403,21479,21554,21630,21705,21781,21856,21930, + 22005,22079,22154,22227,22301,22375,22448,22521, + 22594,22667,22739,22812,22884,22956,23027,23099, + 23170,23241,23311,23382,23452,23522,23592,23662, + 23731,23801,23870,23938,24007,24075,24143,24211, + 24279,24346,24413,24480,24547,24613,24680,24746, + 24811,24877,24942,25007,25072,25137,25201,25265, + 25329,25393,25456,25519,25582,25645,25708,25770, + 25832,25893,25955,26016,26077,26138,26198,26259, + 26319,26378,26438,26497,26556,26615,26674,26732, + 26790,26848,26905,26962,27019,27076,27133,27189, + 27245,27300,27356,27411,27466,27521,27575,27629, + 27683,27737,27790,27843,27896,27949,28001,28053, + 28105,28157,28208,28259,28310,28360,28411,28460, + 28510,28560,28609,28658,28706,28755,28803,28850, + 28898,28945,28992,29039,29085,29131,29177,29223, + 29268,29313,29358,29403,29447,29491,29534,29578, + 29621,29664,29706,29749,29791,29832,29874,29915, + 29956,29997,30037,30077,30117,30156,30195,30234, + 30273,30311,30349,30387,30424,30462,30498,30535, + 30571,30607,30643,30679,30714,30749,30783,30818, + 30852,30885,30919,30952,30985,31017,31050,31082, + 31113,31145,31176,31206,31237,31267,31297,31327, + 31356,31385,31414,31442,31470,31498,31526,31553, + 31580,31607,31633,31659,31685,31710,31736,31760, + 31785,31809,31833,31857,31880,31903,31926,31949, + 31971,31993,32014,32036,32057,32077,32098,32118, + 32137,32157,32176,32195,32213,32232,32250,32267, + 32285,32302,32318,32335,32351,32367,32382,32397, + 32412,32427,32441,32455,32469,32482,32495,32508, + 32521,32533,32545,32556,32567,32578,32589,32599, + 32609,32619,32628,32637,32646,32655,32663,32671, + 32678,32685,32692,32699,32705,32711,32717,32722, + 32728,32732,32737,32741,32745,32748,32752,32755, + 32757,32759,32761,32763,32765,32766,32766,32767, + 32767,32767,32766,32766,32765,32763,32761,32759, + 32757,32755,32752,32748,32745,32741,32737,32732, + 32728,32722,32717,32711,32705,32699,32692,32685, + 32678,32671,32663,32655,32646,32637,32628,32619, + 32609,32599,32589,32578,32567,32556,32545,32533, + 32521,32508,32495,32482,32469,32455,32441,32427, + 32412,32397,32382,32367,32351,32335,32318,32302, + 32285,32267,32250,32232,32213,32195,32176,32157, + 32137,32118,32098,32077,32057,32036,32014,31993, + 31971,31949,31926,31903,31880,31857,31833,31809, + 31785,31760,31736,31710,31685,31659,31633,31607, + 31580,31553,31526,31498,31470,31442,31414,31385, + 31356,31327,31297,31267,31237,31206,31176,31145, + 31113,31082,31050,31017,30985,30952,30919,30885, + 30852,30818,30783,30749,30714,30679,30643,30607, + 30571,30535,30498,30462,30424,30387,30349,30311, + 30273,30234,30195,30156,30117,30077,30037,29997, + 29956,29915,29874,29832,29791,29749,29706,29664, + 29621,29578,29534,29491,29447,29403,29358,29313, + 29268,29223,29177,29131,29085,29039,28992,28945, + 28898,28850,28803,28755,28706,28658,28609,28560, + 28510,28460,28411,28360,28310,28259,28208,28157, + 28105,28053,28001,27949,27896,27843,27790,27737, + 27683,27629,27575,27521,27466,27411,27356,27300, + 27245,27189,27133,27076,27019,26962,26905,26848, + 26790,26732,26674,26615,26556,26497,26438,26378, + 26319,26259,26198,26138,26077,26016,25955,25893, + 25832,25770,25708,25645,25582,25519,25456,25393, + 25329,25265,25201,25137,25072,25007,24942,24877, + 24811,24746,24680,24613,24547,24480,24413,24346, + 24279,24211,24143,24075,24007,23938,23870,23801, + 23731,23662,23592,23522,23452,23382,23311,23241, + 23170,23099,23027,22956,22884,22812,22739,22667, + 22594,22521,22448,22375,22301,22227,22154,22079, + 22005,21930,21856,21781,21705,21630,21554,21479, + 21403,21326,21250,21173,21096,21019,20942,20865, + 20787,20709,20631,20553,20475,20396,20317,20238, + 20159,20080,20000,19921,19841,19761,19680,19600, + 19519,19438,19357,19276,19195,19113,19032,18950, + 18868,18785,18703,18620,18537,18454,18371,18288, + 18204,18121,18037,17953,17869,17784,17700,17615, + 17530,17445,17360,17275,17189,17104,17018,16932, + 16846,16759,16673,16586,16499,16413,16325,16238, + 16151,16063,15976,15888,15800,15712,15623,15535, + 15446,15358,15269,15180,15090,15001,14912,14822, + 14732,14643,14553,14462,14372,14282,14191,14101, + 14010,13919,13828,13736,13645,13554,13462,13370, + 13279,13187,13094,13002,12910,12817,12725,12632, + 12539,12446,12353,12260,12167,12074,11980,11886, + 11793,11699,11605,11511,11417,11322,11228,11133, + 11039,10944,10849,10754,10659,10564,10469,10374, + 10278,10183,10087,9992,9896,9800,9704,9608, + 9512,9416,9319,9223,9126,9030,8933,8836, + 8739,8642,8545,8448,8351,8254,8157,8059, + 7962,7864,7767,7669,7571,7473,7375,7277, + 7179,7081,6983,6885,6786,6688,6590,6491, + 6393,6294,6195,6096,5998,5899,5800,5701, + 5602,5503,5404,5305,5205,5106,5007,4907, + 4808,4708,4609,4509,4410,4310,4210,4111, + 4011,3911,3811,3712,3612,3512,3412,3312, + 3212,3112,3012,2911,2811,2711,2611,2511, + 2410,2310,2210,2110,2009,1909,1809,1708, + 1608,1507,1407,1307,1206,1106,1005,905, + 804,704,603,503,402,302,201,101, + 0,-101,-201,-302,-402,-503,-603,-704, + -804,-905,-1005,-1106,-1206,-1307,-1407,-1507, + -1608,-1708,-1809,-1909,-2009,-2110,-2210,-2310, + -2410,-2511,-2611,-2711,-2811,-2911,-3012,-3112, + -3212,-3312,-3412,-3512,-3612,-3712,-3811,-3911, + -4011,-4111,-4210,-4310,-4410,-4509,-4609,-4708, + -4808,-4907,-5007,-5106,-5205,-5305,-5404,-5503, + -5602,-5701,-5800,-5899,-5998,-6096,-6195,-6294, + -6393,-6491,-6590,-6688,-6786,-6885,-6983,-7081, + -7179,-7277,-7375,-7473,-7571,-7669,-7767,-7864, + -7962,-8059,-8157,-8254,-8351,-8448,-8545,-8642, + -8739,-8836,-8933,-9030,-9126,-9223,-9319,-9416, + -9512,-9608,-9704,-9800,-9896,-9992,-10087,-10183, + -10278,-10374,-10469,-10564,-10659,-10754,-10849,-10944, + -11039,-11133,-11228,-11322,-11417,-11511,-11605,-11699, + -11793,-11886,-11980,-12074,-12167,-12260,-12353,-12446, + -12539,-12632,-12725,-12817,-12910,-13002,-13094,-13187, + -13279,-13370,-13462,-13554,-13645,-13736,-13828,-13919, + -14010,-14101,-14191,-14282,-14372,-14462,-14553,-14643, + -14732,-14822,-14912,-15001,-15090,-15180,-15269,-15358, + -15446,-15535,-15623,-15712,-15800,-15888,-15976,-16063, + -16151,-16238,-16325,-16413,-16499,-16586,-16673,-16759, + -16846,-16932,-17018,-17104,-17189,-17275,-17360,-17445, + -17530,-17615,-17700,-17784,-17869,-17953,-18037,-18121, + -18204,-18288,-18371,-18454,-18537,-18620,-18703,-18785, + -18868,-18950,-19032,-19113,-19195,-19276,-19357,-19438, + -19519,-19600,-19680,-19761,-19841,-19921,-20000,-20080, + -20159,-20238,-20317,-20396,-20475,-20553,-20631,-20709, + -20787,-20865,-20942,-21019,-21096,-21173,-21250,-21326, + -21403,-21479,-21554,-21630,-21705,-21781,-21856,-21930, + -22005,-22079,-22154,-22227,-22301,-22375,-22448,-22521, + -22594,-22667,-22739,-22812,-22884,-22956,-23027,-23099, + -23170,-23241,-23311,-23382,-23452,-23522,-23592,-23662, + -23731,-23801,-23870,-23938,-24007,-24075,-24143,-24211, + -24279,-24346,-24413,-24480,-24547,-24613,-24680,-24746, + -24811,-24877,-24942,-25007,-25072,-25137,-25201,-25265, + -25329,-25393,-25456,-25519,-25582,-25645,-25708,-25770, + -25832,-25893,-25955,-26016,-26077,-26138,-26198,-26259, + -26319,-26378,-26438,-26497,-26556,-26615,-26674,-26732, + -26790,-26848,-26905,-26962,-27019,-27076,-27133,-27189, + -27245,-27300,-27356,-27411,-27466,-27521,-27575,-27629, + -27683,-27737,-27790,-27843,-27896,-27949,-28001,-28053, + -28105,-28157,-28208,-28259,-28310,-28360,-28411,-28460, + -28510,-28560,-28609,-28658,-28706,-28755,-28803,-28850, + -28898,-28945,-28992,-29039,-29085,-29131,-29177,-29223, + -29268,-29313,-29358,-29403,-29447,-29491,-29534,-29578, + -29621,-29664,-29706,-29749,-29791,-29832,-29874,-29915, + -29956,-29997,-30037,-30077,-30117,-30156,-30195,-30234, + -30273,-30311,-30349,-30387,-30424,-30462,-30498,-30535, + -30571,-30607,-30643,-30679,-30714,-30749,-30783,-30818, + -30852,-30885,-30919,-30952,-30985,-31017,-31050,-31082, + -31113,-31145,-31176,-31206,-31237,-31267,-31297,-31327, + -31356,-31385,-31414,-31442,-31470,-31498,-31526,-31553, + -31580,-31607,-31633,-31659,-31685,-31710,-31736,-31760, + -31785,-31809,-31833,-31857,-31880,-31903,-31926,-31949, + -31971,-31993,-32014,-32036,-32057,-32077,-32098,-32118, + -32137,-32157,-32176,-32195,-32213,-32232,-32250,-32267, + -32285,-32302,-32318,-32335,-32351,-32367,-32382,-32397, + -32412,-32427,-32441,-32455,-32469,-32482,-32495,-32508, + -32521,-32533,-32545,-32556,-32567,-32578,-32589,-32599, + -32609,-32619,-32628,-32637,-32646,-32655,-32663,-32671, + -32678,-32685,-32692,-32699,-32705,-32711,-32717,-32722, + -32728,-32732,-32737,-32741,-32745,-32748,-32752,-32755, + -32757,-32759,-32761,-32763,-32765,-32766,-32766,-32767, + -32767,-32767,-32766,-32766,-32765,-32763,-32761,-32759, + -32757,-32755,-32752,-32748,-32745,-32741,-32737,-32732, + -32728,-32722,-32717,-32711,-32705,-32699,-32692,-32685, + -32678,-32671,-32663,-32655,-32646,-32637,-32628,-32619, + -32609,-32599,-32589,-32578,-32567,-32556,-32545,-32533, + -32521,-32508,-32495,-32482,-32469,-32455,-32441,-32427, + -32412,-32397,-32382,-32367,-32351,-32335,-32318,-32302, + -32285,-32267,-32250,-32232,-32213,-32195,-32176,-32157, + -32137,-32118,-32098,-32077,-32057,-32036,-32014,-31993, + -31971,-31949,-31926,-31903,-31880,-31857,-31833,-31809, + -31785,-31760,-31736,-31710,-31685,-31659,-31633,-31607, + -31580,-31553,-31526,-31498,-31470,-31442,-31414,-31385, + -31356,-31327,-31297,-31267,-31237,-31206,-31176,-31145, + -31113,-31082,-31050,-31017,-30985,-30952,-30919,-30885, + -30852,-30818,-30783,-30749,-30714,-30679,-30643,-30607, + -30571,-30535,-30498,-30462,-30424,-30387,-30349,-30311, + -30273,-30234,-30195,-30156,-30117,-30077,-30037,-29997, + -29956,-29915,-29874,-29832,-29791,-29749,-29706,-29664, + -29621,-29578,-29534,-29491,-29447,-29403,-29358,-29313, + -29268,-29223,-29177,-29131,-29085,-29039,-28992,-28945, + -28898,-28850,-28803,-28755,-28706,-28658,-28609,-28560, + -28510,-28460,-28411,-28360,-28310,-28259,-28208,-28157, + -28105,-28053,-28001,-27949,-27896,-27843,-27790,-27737, + -27683,-27629,-27575,-27521,-27466,-27411,-27356,-27300, + -27245,-27189,-27133,-27076,-27019,-26962,-26905,-26848, + -26790,-26732,-26674,-26615,-26556,-26497,-26438,-26378, + -26319,-26259,-26198,-26138,-26077,-26016,-25955,-25893, + -25832,-25770,-25708,-25645,-25582,-25519,-25456,-25393, + -25329,-25265,-25201,-25137,-25072,-25007,-24942,-24877, + -24811,-24746,-24680,-24613,-24547,-24480,-24413,-24346, + -24279,-24211,-24143,-24075,-24007,-23938,-23870,-23801, + -23731,-23662,-23592,-23522,-23452,-23382,-23311,-23241, + -23170,-23099,-23027,-22956,-22884,-22812,-22739,-22667, + -22594,-22521,-22448,-22375,-22301,-22227,-22154,-22079, + -22005,-21930,-21856,-21781,-21705,-21630,-21554,-21479, + -21403,-21326,-21250,-21173,-21096,-21019,-20942,-20865, + -20787,-20709,-20631,-20553,-20475,-20396,-20317,-20238, + -20159,-20080,-20000,-19921,-19841,-19761,-19680,-19600, + -19519,-19438,-19357,-19276,-19195,-19113,-19032,-18950, + -18868,-18785,-18703,-18620,-18537,-18454,-18371,-18288, + -18204,-18121,-18037,-17953,-17869,-17784,-17700,-17615, + -17530,-17445,-17360,-17275,-17189,-17104,-17018,-16932, + -16846,-16759,-16673,-16586,-16499,-16413,-16325,-16238, + -16151,-16063,-15976,-15888,-15800,-15712,-15623,-15535, + -15446,-15358,-15269,-15180,-15090,-15001,-14912,-14822, + -14732,-14643,-14553,-14462,-14372,-14282,-14191,-14101, + -14010,-13919,-13828,-13736,-13645,-13554,-13462,-13370, + -13279,-13187,-13094,-13002,-12910,-12817,-12725,-12632, + -12539,-12446,-12353,-12260,-12167,-12074,-11980,-11886, + -11793,-11699,-11605,-11511,-11417,-11322,-11228,-11133, + -11039,-10944,-10849,-10754,-10659,-10564,-10469,-10374, + -10278,-10183,-10087,-9992,-9896,-9800,-9704,-9608, + -9512,-9416,-9319,-9223,-9126,-9030,-8933,-8836, + -8739,-8642,-8545,-8448,-8351,-8254,-8157,-8059, + -7962,-7864,-7767,-7669,-7571,-7473,-7375,-7277, + -7179,-7081,-6983,-6885,-6786,-6688,-6590,-6491, + -6393,-6294,-6195,-6096,-5998,-5899,-5800,-5701, + -5602,-5503,-5404,-5305,-5205,-5106,-5007,-4907, + -4808,-4708,-4609,-4509,-4410,-4310,-4210,-4111, + -4011,-3911,-3811,-3712,-3612,-3512,-3412,-3312, + -3212,-3112,-3012,-2911,-2811,-2711,-2611,-2511, + -2410,-2310,-2210,-2110,-2009,-1909,-1809,-1708, + -1608,-1507,-1407,-1307,-1206,-1106,-1005,-905, + -804,-704,-603,-503,-402,-302,-201,-101 +}; +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ima_tables.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ima_tables.c new file mode 100755 index 0000000..b03b4d4 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ima_tables.c @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ima_tables.c + * + * Contents and purpose: + * Contains the constant tables for IMA encode/decode + * + * Copyright (c) 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 760 $ + * $Date: 2007-07-17 23:09:36 -0700 (Tue, 17 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" + +/*---------------------------------------------------------------------------- + * ADPCM decode tables + *---------------------------------------------------------------------------- +*/ +const EAS_I16 imaIndexTable[16] = +{ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +const EAS_I16 imaStepSizeTable[89] = +{ + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 +}; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imaadpcm.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imaadpcm.c new file mode 100755 index 0000000..41280b5 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imaadpcm.c @@ -0,0 +1,368 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imaadpcm.c + * + * Contents and purpose: + * Implements the IMA ADPCM decoder + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_host.h" +#include "eas_pcm.h" +#include "eas_math.h" +#include "eas_report.h" + +// #define _DEBUG_IMA_ADPCM_LOCATE + +/*---------------------------------------------------------------------------- + * externs + *---------------------------------------------------------------------------- +*/ +extern const EAS_I16 imaIndexTable[]; +extern const EAS_I16 imaStepSizeTable[]; + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble); +static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); + +/*---------------------------------------------------------------------------- + * IMA ADPCM Decoder interface + *---------------------------------------------------------------------------- +*/ +const S_DECODER_INTERFACE IMADecoder = +{ + IMADecoderInit, + IMADecoderSample, + IMADecoderLocate +}; + +/*---------------------------------------------------------------------------- + * IMADecoderInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the IMA ADPCM decoder + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + pState->decoderL.step = 0; + pState->decoderR.step = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMADecoderSample() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes an IMA ADPCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + EAS_RESULT result; + EAS_I16 sTemp; + + /* if high nibble, decode */ + if (pState->hiNibble) + { + IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte >> 4)); + pState->hiNibble = EAS_FALSE; + } + + /* low nibble, need to fetch another byte */ + else + { + /* check for loop */ + if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) + { + /* seek to start of loop */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) + return result; + pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; + pState->blockCount = 0; + pState->flags &= ~PCM_FLAGS_EMPTY; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMADecoderSample: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } + } + + /* if start of block, fetch new predictor and step index */ + if ((pState->blockSize != 0) && (pState->blockCount == 0) && (pState->bytesLeft != 0)) + { + + /* get predicted sample for left channel */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Predictor: Was %d, now %d\n", pState->decoderL.acc, sTemp); */ } +#endif + pState->decoderL.acc = pState->decoderL.x1 = sTemp; + + /* get step index for left channel - upper 8 bits are reserved */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderL.step, sTemp); */ } +#endif + pState->decoderL.step = sTemp & 0xff; + + if (pState->flags & PCM_FLAGS_STEREO) + { + /* get predicted sample for right channel */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->decoderR.acc = pState->decoderR.x1 = sTemp; + + /* get step index for right channel - upper 8 bits are reserved */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderR.step, sTemp); */ } +#endif + pState->decoderR.step = sTemp & 0xff; + + pState->blockCount = pState->blockSize - 8; + pState->bytesLeft -= 8; + } + else + { + pState->blockCount = pState->blockSize - 4; + pState->bytesLeft -= 4; + } + } + else + { + + /* get another ADPCM data pair */ + if (pState->bytesLeft) + { + + if ((result = EAS_HWGetByte(pEASData->hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* decode the low nibble */ + pState->bytesLeft--; + pState->blockCount--; + IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte & 0x0f)); + + if (pState->flags & PCM_FLAGS_STEREO) + IMADecoderADPCM(&pState->decoderR, (EAS_U8)(pState->srcByte >> 4)); + else + pState->hiNibble = EAS_TRUE; + } + + /* out of ADPCM data, generate enough samples to fill buffer */ + else + { + pState->decoderL.x1 = pState->decoderL.x0; + pState->decoderR.x1 = pState->decoderR.x0; + } + } + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMADecoderADPCM() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes an IMA ADPCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble) +{ + EAS_INT delta; + EAS_INT stepSize; + + /* get stepsize from table */ + stepSize = imaStepSizeTable[pState->step]; + + /* delta = (abs(delta) + 0.5) * step / 4 */ + delta = 0; + if (nibble & 4) + delta += stepSize; + + if (nibble & 2) + /*lint -e{702} use shift for performance */ + delta += stepSize >> 1; + + if (nibble & 1) + /*lint -e{702} use shift for performance */ + delta += stepSize >> 2; + + /*lint -e{702} use shift for performance */ + delta += stepSize >> 3; + + /* integrate the delta */ + if (nibble & 8) + pState->acc -= delta; + else + pState->acc += delta; + + /* saturate */ + if (pState->acc > 32767) + pState->acc = 32767; + if (pState->acc < -32768) + pState->acc = -32768; + pState->x1 = (EAS_PCM) pState->acc; + + /* compute new step size */ + pState->step += imaIndexTable[nibble]; + if (pState->step < 0) + pState->step = 0; + if (pState->step > 88) + pState->step = 88; + +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "In=%u, Pred=%d, Step=%d\n", nibble, pState->acc, imaStepSizeTable[pState->step]); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * IMADecoderLocate() + *---------------------------------------------------------------------------- + * Locate in an IMA ADPCM stream + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_I32 samplesPerBlock; + EAS_I32 secs, msecs; + + /* no need to calculate if time is zero */ + if (time == 0) + temp = 0; + + /* not zero */ + else + { + + /* can't seek if not a blocked file */ + if (pState->blockSize == 0) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* calculate number of samples per block */ + if (pState->flags & PCM_FLAGS_STEREO) + samplesPerBlock = pState->blockSize - 7; + else + samplesPerBlock = (pState->blockSize << 1) - 7; + + /* break down into secs and msecs */ + secs = time / 1000; + msecs = time - (secs * 1000); + + /* calculate sample number fraction from msecs */ + temp = (msecs * pState->sampleRate); + temp = (temp >> 10) + ((temp * 49) >> 21); + + /* add integer sample count */ + temp += secs * pState->sampleRate; + +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000006 , time, temp); +#endif + + /* for looped samples, calculate position in the loop */ + if ((temp > pState->byteCount) && (pState->loopSamples != 0)) + { + EAS_I32 numBlocks; + EAS_I32 samplesPerLoop; + EAS_I32 samplesInLastBlock; + + numBlocks = (EAS_I32) (pState->loopStart / pState->blockSize); + samplesInLastBlock = (EAS_I32) pState->loopStart - (numBlocks * pState->blockSize); + if (samplesInLastBlock) + { + if (pState->flags & PCM_FLAGS_STEREO) + samplesInLastBlock = samplesInLastBlock - 7; + else + /*lint -e{703} use shift for performance */ + samplesInLastBlock = (samplesInLastBlock << 1) - 7; + } + samplesPerLoop = numBlocks * samplesPerBlock + samplesInLastBlock; + temp = temp % samplesPerLoop; +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000007 , numBlocks, samplesPerLoop, samplesInLastBlock, temp); +#endif + } + + /* find start of block for requested sample */ + temp = (temp / samplesPerBlock) * pState->blockSize; +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000008 , temp); +#endif + + } + + /* seek to new location */ + if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000009 , pState->bytesLeft); +#endif + + /* reset state */ + pState->blockCount = 0; + pState->hiNibble = EAS_FALSE; + if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) + pState->state = EAS_STATE_READY; + + return EAS_SUCCESS; +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelody.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelody.c new file mode 100755 index 0000000..698c7df --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelody.c @@ -0,0 +1,1738 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelody.c + * + * Contents and purpose: + * iMelody parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 797 $ + * $Date: 2007-08-01 00:15:56 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* lint doesn't like the way some string.h files look */ +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#endif + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_imelodydata.h" +#include "eas_ctype.h" + +// #define _DEBUG_IMELODY + +/* increase gain for mono ringtones */ +#define IMELODY_GAIN_OFFSET 8 + +/* length of 32nd note in 1/256ths of a msec for 120 BPM tempo */ +#define DEFAULT_TICK_CONV 16000 +#define TICK_CONVERT 1920000 + +/* default channel and program for iMelody playback */ +#define IMELODY_CHANNEL 0 +#define IMELODY_PROGRAM 80 +#define IMELODY_VEL_MUL 4 +#define IMELODY_VEL_OFS 67 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +static const char* const tokens[] = +{ + "BEGIN:IMELODY", + "VERSION:", + "FORMAT:CLASS", + "NAME:", + "COMPOSER:", + "BEAT:", + "STYLE:", + "VOLUME:", + "MELODY:", + "END:IMELODY" +}; + +/* ledon or ledoff */ +static const char ledStr[] = "edo"; + +/* vibeon or vibeoff */ +static const char vibeStr[] = "ibeo"; + +/* backon or backoff */ +static const char backStr[] = "cko"; + +typedef enum +{ + TOKEN_BEGIN, + TOKEN_VERSION, + TOKEN_FORMAT, + TOKEN_NAME, + TOKEN_COMPOSER, + TOKEN_BEAT, + TOKEN_STYLE, + TOKEN_VOLUME, + TOKEN_MELODY, + TOKEN_END, + TOKEN_INVALID +} ENUM_IMELODY_TOKENS; + +/* lookup table for note values */ +static const EAS_I8 noteTable[] = { 9, 11, 0, 2, 4, 5, 7 }; + +/* inline functions */ +#ifdef _DEBUG_IMELODY +static void PutBackChar (S_IMELODY_DATA *pData) +{ + if (pData->index) + pData->index--; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "PutBackChar '%c'\n", pData->buffer[pData->index]); */ } +} +#else +EAS_INLINE void PutBackChar (S_IMELODY_DATA *pData) { if (pData->index) pData->index--; } +#endif + + +/* local prototypes */ +static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode); +static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration); +static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader); +static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader); +static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData); +static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader); +static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine); +static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex); + + +/*---------------------------------------------------------------------------- + * + * EAS_iMelody_Parser + * + * This structure contains the functional interface for the iMelody parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_iMelody_Parser = +{ + IMY_CheckFileType, + IMY_Prepare, + IMY_Time, + IMY_Event, + IMY_State, + IMY_Close, + IMY_Reset, + IMY_Pause, + IMY_Resume, + NULL, + IMY_SetData, + IMY_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * IMY_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_IMELODY_DATA* pData; + EAS_I8 buffer[MAX_LINE_SIZE+1]; + EAS_U8 index; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_CheckFileType\n"); */ } +#endif + + /* read the first line of the file */ + *ppHandle = NULL; + if (IMY_ReadLine(pEASData->hwInstData, fileHandle, buffer, NULL) != EAS_SUCCESS) + return EAS_SUCCESS; + + /* check for header string */ + if (IMY_ParseLine(buffer, &index) == TOKEN_BEGIN) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_IMELODY_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_IMELODY_DATA)); + if (!pData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pData, 0, sizeof(S_IMELODY_DATA)); + + /* initialize */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_ERROR; + pData->state = EAS_STATE_OPEN; + + /* return a pointer to the instance data */ + *ppHandle = pData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_Prepare\n"); */ } +#endif + + /* check for valid state */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + /* parse the header */ + if ((result = IMY_ParseHeader(pEASData, pData)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Prepare: state set to EAS_STATE_READY\n"); */ } +#endif + + pData ->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + EAS_I8 c; + EAS_BOOL eof; + EAS_INT temp; + + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: Reset\n"); */ } +#endif + /* set program to square lead */ + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, IMELODY_PROGRAM); + + /* set channel volume to max */ + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Stopping note %d\n", pData->note); */ } +#endif + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* parse the next event */ + eof = EAS_FALSE; + while (!eof) + { + + /* get next character */ + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + + switch (c) + { + /* start repeat */ + case '(': + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter repeat section\n", c); */ } +#endif + + if (pData->repeatOffset < 0) + { + pData->repeatOffset = pData->startLine + (EAS_I32) pData->index; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat offset = %d\n", pData->repeatOffset); */ } +#endif + } + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring nested repeat section\n"); */ } + break; + + /* end repeat */ + case ')': + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "End repeat section, repeat offset = %d\n", pData->repeatOffset); */ } +#endif + /* ignore invalid repeats */ + if (pData->repeatCount >= 0) + { + + /* decrement repeat count (repeatCount == 0 means infinite loop) */ + if (pData->repeatCount > 0) + { + if (--pData->repeatCount == 0) + { + pData->repeatCount = -1; +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat loop complete\n"); */ } +#endif + } + } + +//2 TEMPORARY FIX: If locating, don't do infinite loops. +//3 We need a different mode for metadata parsing where we don't loop at all + if ((parserMode == eParserModePlay) || (pData->repeatCount != 0)) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Rewinding file for repeat\n"); */ } +#endif + /* rewind to start of loop */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS) + return result; + IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine); + pData->index = 0; + + /* if last loop, prevent future loops */ + if (pData->repeatCount == -1) + pData->repeatOffset = -1; + } + } + break; + + /* repeat count */ + case '@': + if (!IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_FALSE)) + eof = EAS_TRUE; + else if (pData->repeatOffset > 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat count = %dt", pData->repeatCount); */ } +#endif + if (pData->repeatCount < 0) + pData->repeatCount = (EAS_I16) temp; + } + break; + + /* volume */ + case 'V': + if (!IMY_GetVolume(pEASData->hwInstData, pData, EAS_FALSE)) + eof = EAS_TRUE; + break; + + /* flat */ + case '&': + pData->noteModifier = -1; + break; + + /* sharp */ + case '#': + pData->noteModifier = +1; + break; + + /* octave */ + case '*': + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (IsDigit(c)) + pData->octave = (EAS_U8) ((c - '0' + 1) * 12); + else if (!c) + eof = EAS_TRUE; + break; + + /* ledon or ledoff */ + case 'l': + if (!IMY_GetLEDState(pEASData, pData)) + eof = EAS_TRUE; + break; + + /* vibeon or vibeoff */ + case 'v': + if (!IMY_GetVibeState(pEASData, pData)) + eof = EAS_TRUE; + break; + + /* either a B note or backon or backoff */ + case 'b': + if (IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE) == 'a') + { + if (!IMY_GetBackState(pEASData, pData)) + eof = EAS_TRUE; + } + else + { + PutBackChar(pData); + if (IMY_PlayNote(pEASData, pData, c, parserMode)) + return EAS_SUCCESS; + eof = EAS_TRUE; + } + break; + + /* rest */ + case 'r': + case 'R': + if (IMY_PlayRest(pEASData, pData)) + return EAS_SUCCESS; + eof = EAS_TRUE; + break; + + /* EOF */ + case 0: +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: end of iMelody file detected\n"); */ } +#endif + eof = EAS_TRUE; + break; + + /* must be a note */ + default: + c = ToLower(c); + if ((c >= 'a') && (c <= 'g')) + { + if (IMY_PlayNote(pEASData, pData, c, parserMode)) + return EAS_SUCCESS; + eof = EAS_TRUE; + } + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unexpected character '%c' [0x%02x]\n", c, c); */ } + break; + } + } + + /* handle EOF */ +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: state set to EAS_STATE_STOPPING\n"); */ } +#endif + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_IMELODY_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_IMELODY_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + { + pData->state = EAS_STATE_STOPPED; +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_STOPPED\n"); */ } +#endif + } + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_PAUSED\n"); */ } +#endif + pData->state = EAS_STATE_PAUSED; + } + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Close: close file\n"); */ } +#endif + + pData = (S_IMELODY_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: reset file\n"); */ } +#endif + pData = (S_IMELODY_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + + /* reset time to zero */ + pData->time = 0; + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + if ((result = IMY_ParseHeader (pEASData, pData)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: state set to EAS_STATE_ERROR\n"); */ } +#endif + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA *pData; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Pause: pause file\n"); */ } +#endif + + /* can't pause a stopped stream */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA *pData; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Resume: resume file\n"); */ } +#endif + + /* can't resume a stopped stream */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Adjust tempo relative to song tempo + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pInstData - pointer to iMelody instance data + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return the file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pInstData - pointer to iMelody instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + + switch (param) + { + /* return file type as iMelody */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_IMELODY; + break; + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = IMELODY_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_PlayNote() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode) +{ + EAS_I32 duration; + EAS_U8 velocity; + + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: start note %d\n", note); */ } +#endif + + /* get the duration */ + if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration)) + return EAS_FALSE; + + /* save note value */ + pData->note = (EAS_U8) (pData->octave + noteTable[note - 'a'] + pData->noteModifier); + velocity = (EAS_U8) (pData->volume ? pData->volume * IMELODY_VEL_MUL + IMELODY_VEL_OFS : 0); + + /* start note only if in play mode */ + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, velocity); + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: Start note %d, duration %d\n", pData->note, duration); */ } +#endif + + /* determine note length */ + switch (pData->style) + { + case 0: + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 4; + break; + case 1: + pData->restTicks = 0; + break; + case 2: + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 1; + break; + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "IMY_PlayNote: Note style out of range: %d\n", pData->style); */ } + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 4; + break; + } + + /* next event is at end of this note */ + pData->time += duration - pData->restTicks; + + /* reset the flat/sharp modifier */ + pData->noteModifier = 0; + + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_PlayRest() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I32 duration; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_PlayRest]n"); */ } +#endif + + /* get the duration */ + if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration)) + return EAS_FALSE; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayRest: note duration %d\n", duration); */ } +#endif + + /* next event is at end of this note */ + pData->time += duration; + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetDuration() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ + +static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration) +{ + EAS_I32 duration; + EAS_I8 c; + + /* get the duration */ + *pDuration = 0; + c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + if ((c < '0') || (c > '5')) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetDuration: error in duration '%c'\n", c); */ } +#endif + return EAS_FALSE; + } + + /* calculate total length of note */ + duration = pData->tick * (1 << ('5' - c)); + + /* check for duration modifier */ + c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE); + if (c) + { + if (c == '.') + /*lint -e{704} shift for performance */ + duration += duration >> 1; + else if (c == ':') + /*lint -e{704} shift for performance */ + duration += (duration >> 1) + (duration >> 2); + else if (c == ';') + /*lint -e{704} shift for performance */ + duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT; + else + PutBackChar(pData); + } + + *pDuration = duration; + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetLEDState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetLEDState\n"); */ } +#endif + + for (i = 0; i < 5; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 3: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED on\n"); */ } +#endif + EAS_HWLED(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 4: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED off\n"); */ } +#endif + EAS_HWLED(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != ledStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetVibeState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVibeState\n"); */ } +#endif + + for (i = 0; i < 6; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 4: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate on\n"); */ } +#endif + EAS_HWVibrate(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 5: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate off\n"); */ } +#endif + EAS_HWVibrate(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != vibeStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetBackState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetBackState\n"); */ } +#endif + + for (i = 0; i < 5; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 3: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight on\n"); */ } +#endif + EAS_HWBackLight(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 4: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight off\n"); */ } +#endif + EAS_HWBackLight(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != backStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader) +{ + EAS_INT temp; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVolume\n"); */ } +#endif + + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (c == '+') + { + if (pData->volume < 15) + pData->volume++; + return EAS_TRUE; + } + else if (c == '-') + { + if (pData->volume > 0) + pData->volume--; + return EAS_TRUE; + } + else if (IsDigit(c)) + temp = c - '0'; + else + return EAS_FALSE; + + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (IsDigit(c)) + temp = temp * 10 + c - '0'; + else if (c) + PutBackChar(pData); + if ((temp >= 0) && (temp <= 15)) + { + if (inHeader && (temp == 0)) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring V0 encountered in header\n"); */ } + else + pData->volume = (EAS_U8) temp; + } + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetNumber() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader) +{ + EAS_BOOL ok; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetNumber\n"); */ } +#endif + + *temp = 0; + ok = EAS_FALSE; + for (;;) + { + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (IsDigit(c)) + { + *temp = *temp * 10 + c - '0'; + ok = EAS_TRUE; + } + else + { + if (c) + PutBackChar(pData); + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNumber: value %d\n", *temp); */ } +#endif + + return ok; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_GetVersion() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVersion (S_IMELODY_DATA *pData, EAS_INT *pVersion) +{ + EAS_I8 c; + EAS_INT temp; + EAS_INT version; + + version = temp = 0; + for (;;) + { + c = pData->buffer[pData->index++]; + if ((c == 0) || (c == '.')) + { + /*lint -e{701} use shift for performance */ + version = (version << 8) + temp; + if (c == 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVersion: version 0x%04x\n", version); */ } +#endif + + *pVersion = version; + return EAS_TRUE; + } + temp = 0; + } + else if (IsDigit(c)) + temp = (temp * 10) + c - '0'; + } +} + +/*---------------------------------------------------------------------------- + * IMY_MetaData() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void IMY_MetaData (S_IMELODY_DATA *pData, E_EAS_METADATA_TYPE metaType, EAS_I8 *buffer) +{ + EAS_I32 len; + + /* check for callback */ + if (!pData->metadata.callback) + return; + + /* copy data to host buffer */ + len = (EAS_I32) strlen((char*) buffer); + if (len >pData->metadata.bufferSize) + len = pData->metadata.bufferSize; + strncpy((char*) pData->metadata.buffer, (char*) buffer, (size_t) len); + pData->metadata.buffer[len] = 0; + + /* callback to host */ + pData->metadata.callback(metaType, pData->metadata.buffer, pData->metadata.pUserData); +} + +/*---------------------------------------------------------------------------- + * IMY_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData) +{ + EAS_RESULT result; + EAS_INT token; + EAS_INT temp; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_ParseHeader\n"); */ } +#endif + + /* initialize some defaults */ + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->note = 0; + pData->noteModifier = 0; + pData ->restTicks = 0; + pData->volume = 7; + pData->octave = 60; + pData->repeatOffset = -1; + pData->repeatCount = -1; + pData->style = 0; + + /* force the read of the first line */ + pData->index = 1; + + /* read data until we get to melody */ + for (;;) + { + /* read a line from the file and parse the token */ + if (pData->index != 0) + { + if ((result = IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine)) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: IMY_ReadLine returned %d\n", result); */ } +#endif + return result; + } + } + token = IMY_ParseLine(pData->buffer, &pData->index); + + switch (token) + { + /* ignore these valid tokens */ + case TOKEN_BEGIN: + break; + + case TOKEN_FORMAT: + if (!IMY_GetVersion(pData, &temp)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid FORMAT field '%s'\n", pData->buffer); */ } + return EAS_ERROR_FILE_FORMAT; + } + if ((temp != 0x0100) && (temp != 0x0200)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported FORMAT %02x\n", temp); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + break; + + case TOKEN_VERSION: + if (!IMY_GetVersion(pData, &temp)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid VERSION field '%s'\n", pData->buffer); */ } + return EAS_ERROR_FILE_FORMAT; + } + if ((temp != 0x0100) && (temp != 0x0102)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported VERSION %02x\n", temp); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + break; + + case TOKEN_NAME: + IMY_MetaData(pData, EAS_METADATA_TITLE, pData->buffer + pData->index); + break; + + case TOKEN_COMPOSER: + IMY_MetaData(pData, EAS_METADATA_AUTHOR, pData->buffer + pData->index); + break; + + /* handle beat */ + case TOKEN_BEAT: + IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_TRUE); + if ((temp >= 25) && (temp <= 900)) + pData->tick = TICK_CONVERT / temp; + break; + + /* handle style */ + case TOKEN_STYLE: + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if (c == 'S') + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if ((c >= '0') && (c <= '2')) + pData->style = (EAS_U8) (c - '0'); + else + { + PutBackChar(pData); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in style command: %s\n", pData->buffer); */ } + } + break; + + /* handle volume */ + case TOKEN_VOLUME: + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if (c != 'V') + { + PutBackChar(pData); + if (!IsDigit(c)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in volume command: %s\n", pData->buffer); */ } + break; + } + } + IMY_GetVolume(pEASData->hwInstData, pData, EAS_TRUE); + break; + + case TOKEN_MELODY: +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Header successfully parsed\n"); */ } +#endif + return EAS_SUCCESS; + + case TOKEN_END: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unexpected END:IMELODY encountered\n"); */ } + return EAS_ERROR_FILE_FORMAT; + + default: + /* force a read of the next line */ + pData->index = 1; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized token in iMelody file: %s\n", pData->buffer); */ } + break; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_GetNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader) +{ + EAS_I8 c; + EAS_U8 index; + + for (;;) + { + /* get next character */ + c = pData->buffer[pData->index++]; + + /* buffer empty, read more */ + if (!c) + { + /* don't read the next line in the header */ + if (inHeader) + return 0; + + pData->index = 0; + pData->buffer[0] = 0; + if (IMY_ReadLine(hwInstData, pData->fileHandle, pData->buffer, &pData->startLine) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: EOF\n"); */ } +#endif + return 0; + } + + /* check for END:IMELODY token */ + if (IMY_ParseLine(pData->buffer, &index) == TOKEN_END) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: found END:IMELODY\n"); */ } +#endif + pData->buffer[0] = 0; + return 0; + } + continue; + } + + /* ignore white space */ + if (!IsSpace(c)) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar returned '%c'\n", c); */ } +#endif + return c; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_ReadLine() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a line of input from the file, discarding the CR/LF + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine) +{ + EAS_RESULT result; + EAS_INT i; + EAS_I8 c; + + /* fetch current file position and save it */ + if (pStartLine != NULL) + { + if ((result = EAS_HWFilePos(hwInstData, fileHandle, pStartLine)) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: EAS_HWFilePos returned %d\n", result); */ } +#endif + return result; + } + } + + buffer[0] = 0; + for (i = 0; i < MAX_LINE_SIZE; ) + { + if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) + { + if ((result == EAS_EOF) && (i > 0)) + break; + return result; + } + + /* return on LF or end of data */ + if (c == '\n') + break; + + /* store characters in buffer */ + if (c != '\r') + buffer[i++] = c; + } + buffer[i] = 0; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ReadLine read %s\n", buffer); */ } +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_ParseLine() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex) +{ + EAS_INT i; + EAS_INT j; + + /* there's no strnicmp() in stdlib, so we have to roll our own */ + for (i = 0; i < TOKEN_INVALID; i++) + { + for (j = 0; ; j++) + { + /* end of token, must be a match */ + if (tokens[i][j] == 0) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine found token %d\n", i); */ } +#endif + *pIndex = (EAS_U8) j; + return i; + } + if (tokens[i][j] != ToUpper(buffer[j])) + break; + } + } +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine: no token found\n"); */ } +#endif + return TOKEN_INVALID; +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelodydata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelodydata.c new file mode 100755 index 0000000..9437e08 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelodydata.c @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelodydata.c + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_imelodydata.h" + +/*---------------------------------------------------------------------------- + * + * eas_iMelodyData + * + * Static memory allocation for iMelody parser + *---------------------------------------------------------------------------- +*/ +S_IMELODY_DATA eas_iMelodyData; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelodydata.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelodydata.h new file mode 100755 index 0000000..57c1ed0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_imelodydata.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelodydata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data declarations for the iMelody parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_IMELODYDATA_H +#define EAS_IMELODYDATA_H + +#include "eas_data.h" + +/* maximum line size as specified in iMelody V1.2 spec */ +#define MAX_LINE_SIZE 75 + +/*---------------------------------------------------------------------------- + * + * S_IMELODY_DATA + * + * This structure contains the state data for the iMelody parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* pointer to synth */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_I32 tickBase; /* basline length of 32nd note in 256th of a msec */ + EAS_I32 tick; /* actual length of 32nd note in 256th of a msec */ + EAS_I32 restTicks; /* ticks to rest after current note */ + EAS_I32 startLine; /* file offset at start of line (for repeats) */ + EAS_I32 repeatOffset; /* file offset to start of repeat section */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I16 repeatCount; /* repeat counter */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 style; /* from STYLE */ + EAS_U8 index; /* index into buffer */ + EAS_U8 octave; /* octave prefix */ + EAS_U8 volume; /* current volume */ + EAS_U8 note; /* MIDI note number */ + EAS_I8 noteModifier; /* sharp or flat */ + EAS_I8 buffer[MAX_LINE_SIZE+1]; /* buffer for ASCII data */ +} S_IMELODY_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_math.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_math.c new file mode 100755 index 0000000..dc85051 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_math.c @@ -0,0 +1,168 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_math.c + * + * Contents and purpose: + * Contains common math routines for the various audio engines. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 586 $ + * $Date: 2007-03-08 20:33:04 -0800 (Thu, 08 Mar 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas.h" +#include "eas_math.h" + +/* anything less than this converts to a fraction too small to represent in 32-bits */ +#define MIN_CENTS -18000 + +/*---------------------------------------------------------------------------- + * EAS_Calculate2toX() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate 2^x + * + * Inputs: + * nCents - measured in cents + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_Calculate2toX (EAS_I32 nCents) +{ + EAS_I32 nDents; + EAS_I32 nExponentInt, nExponentFrac; + EAS_I32 nTemp1, nTemp2; + EAS_I32 nResult; + + /* check for minimum value */ + if (nCents < MIN_CENTS) + return 0; + + /* for the time being, convert cents to dents */ + nDents = FMUL_15x15(nCents, CENTS_TO_DENTS); + + nExponentInt = GET_DENTS_INT_PART(nDents); + nExponentFrac = GET_DENTS_FRAC_PART(nDents); + + /* + implement 2^(fracPart) as a power series + */ + nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3); + nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1); + nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2); + + /* + implement 2^(intPart) as + a left shift for intPart >= 0 or + a left shift for intPart < 0 + */ + if (nExponentInt >= 0) + { + /* left shift for positive exponents */ + /*lint -e{703} */ + nResult = nTemp1 << nExponentInt; + } + else + { + /* right shift for negative exponents */ + nExponentInt = -nExponentInt; + nResult = nTemp1 >> nExponentInt; + } + + return nResult; +} + +/*---------------------------------------------------------------------------- + * EAS_LogToLinear16() + *---------------------------------------------------------------------------- + * Purpose: + * Transform log value to linear gain multiplier using piece-wise linear + * approximation + * + * Inputs: + * nGain - log scale value in 20.10 format. Even though gain is normally + * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate + * the need for saturation checking when combining gain values. + * + * Outputs: + * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain) +{ + EAS_INT nExp; + EAS_U16 nTemp; + + /* bias to positive */ + nGain += 32767; + + /* check for infinite attenuation */ + if (nGain < 0) + return 0; + + /* extract the exponent */ + nExp = 31 - (nGain >> 10); + + /* check for maximum output */ + if (nExp < 0) + return 0x7fff; + + /* extract mantissa and restore implied 1 bit */ + nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp); + + /* use shift to approximate power-of-2 operation */ + return nTemp; +} + +/*---------------------------------------------------------------------------- + * EAS_VolumeToGain() + *---------------------------------------------------------------------------- + * Purpose: + * Transform volume control in 1dB increments to gain multiplier + * + * Inputs: + * volume - 100 = 0dB, 99 = -1dB, 0 = -inf + * + * Outputs: + * Returns a 16-bit linear value + *---------------------------------------------------------------------------- +*/ +EAS_I16 EAS_VolumeToGain (EAS_INT volume) +{ + /* check for limits */ + if (volume <= 0) + return 0; + if (volume >= 100) + return 0x7fff; + + /*lint -e{702} use shift instead of division */ + return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1); +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_math.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_math.h new file mode 100755 index 0000000..f240b51 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_math.h @@ -0,0 +1,412 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_math.h + * + * Contents and purpose: + * Contains common math routines for the various audio engines. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 584 $ + * $Date: 2007-03-08 09:49:24 -0800 (Thu, 08 Mar 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MATH_H +#define _EAS_MATH_H + + +/** coefs for pan, generates sin, cos */ +#define COEFF_PAN_G2 -27146 /* -0.82842712474619 = 2 - 4/sqrt(2) */ +#define COEFF_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ + +/* +coefficients for approximating +2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3 +where x is a int.frac number representing number of octaves. +Actually, we approximate only the 2^(frac) using the power series +and implement the 2^(int) as a shift, so that +2^x == 2^(int.frac) == 2^(int) * 2^(fract) + == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int) + +The gn2toX.. were generated using a best fit for a 3rd +order polynomial, instead of taking the coefficients from +a truncated Taylor (or Maclaurin?) series. +*/ + +#define GN2_TO_X0 32768 /* 1 */ +#define GN2_TO_X1 22833 /* 0.696807861328125 */ +#define GN2_TO_X2 7344 /* 0.22412109375 */ +#define GN2_TO_X3 2588 /* 0.0789794921875 */ + +/*---------------------------------------------------------------------------- + * Fixed Point Math + *---------------------------------------------------------------------------- + * These macros are used for fixed point multiplies. If the processor + * supports fixed point multiplies, replace these macros with inline + * assembly code to improve performance. + *---------------------------------------------------------------------------- +*/ + +/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */ +#define FMUL_15x15(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b)) >> 15) + +/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */ +#define FMUL_7x7(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b) ) << 1) + +/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */ +#define FMUL_8x8(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b) ) >> 1) + +/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */ +#define FMUL_8x15(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)((a) << 7) * (EAS_I32)(b)) >> 15) + +/* macros for fractional phase accumulator */ +/* +Note: changed the _U32 to _I32 on 03/14/02. This should not +affect the phase calculations, and should allow us to reuse these +macros for other audio sample related math. +*/ +#define HARDWARE_BIT_WIDTH 32 + +#define NUM_PHASE_INT_BITS 1 +#define NUM_PHASE_FRAC_BITS 15 + +#define PHASE_FRAC_MASK (EAS_U32) ((0x1L << NUM_PHASE_FRAC_BITS) -1) + +#define GET_PHASE_INT_PART(x) (EAS_U32)((EAS_U32)(x) >> NUM_PHASE_FRAC_BITS) +#define GET_PHASE_FRAC_PART(x) (EAS_U32)((EAS_U32)(x) & PHASE_FRAC_MASK) + +#define DEFAULT_PHASE_FRAC 0 +#define DEFAULT_PHASE_INT 0 + +/* +Linear interpolation calculates: +output = (1-frac) * sample[n] + (frac) * sample[n+1] + +where conceptually 0 <= frac < 1 + +For a fixed point implementation, frac is actually an integer value +with an implied binary point one position to the left. The value of +one (unity) is given by PHASE_ONE +one half and one quarter are useful for 4-point linear interp. +*/ +#define PHASE_ONE (EAS_I32) (0x1L << NUM_PHASE_FRAC_BITS) + +/* + Multiply the signed audio sample by the unsigned fraction. +- a is the signed audio sample +- b is the unsigned fraction (cast to signed int as long as coef + uses (n-1) or less bits, where n == hardware bit width) +*/ +#define MULT_AUDIO_COEF(audio,coef) /*lint -e704 */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_PHASE_FRAC_BITS \ + ) \ + /* lint +704 */ + +/* wet / dry calculation macros */ +#define NUM_WET_DRY_FRAC_BITS 7 // 15 +#define NUM_WET_DRY_INT_BITS 9 // 1 + +/* define a 1.0 */ +#define WET_DRY_ONE (EAS_I32) ((0x1L << NUM_WET_DRY_FRAC_BITS)) +#define WET_DRY_MINUS_ONE (EAS_I32) (~WET_DRY_ONE) +#define WET_DRY_FULL_SCALE (EAS_I32) (WET_DRY_ONE - 1) + +#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_WET_DRY_FRAC_BITS \ + ) + +/* Envelope 1 (EG1) calculation macros */ +#define NUM_EG1_INT_BITS 1 +#define NUM_EG1_FRAC_BITS 15 + +/* the max positive gain used in the synth for EG1 */ +/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas +converter, otherwise, the values we read from the .eas file are bogus. */ +#define SYNTH_FULL_SCALE_EG1_GAIN (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS) -1) + +/* define a 1.0 */ +#define EG1_ONE (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS)) +#define EG1_MINUS_ONE (EAS_I32) (~SYNTH_FULL_SCALE_EG1_GAIN) + +#define EG1_HALF (EAS_I32) (EG1_ONE/2) +#define EG1_MINUS_HALF (EAS_I32) (EG1_MINUS_ONE/2) + +/* +We implement the EG1 using a linear gain value, which means that the +attack segment is handled by incrementing (adding) the linear gain. +However, EG1 treats the Decay, Sustain, and Release differently than +the Attack portion. For Decay, Sustain, and Release, the gain is +linear on dB scale, which is equivalent to exponential damping on +a linear scale. Because we use a linear gain for EG1, we implement +the Decay and Release as multiplication (instead of incrementing +as we did for the attack segment). +Therefore, we need the following macro to implement the multiplication +(i.e., exponential damping) during the Decay and Release segments of +the EG1 +*/ +#define MULT_EG1_EG1(gain,damping) /*lint -e(704) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \ + ) \ + >> NUM_EG1_FRAC_BITS \ + ) + +// Use the following macro specifically for the filter, when multiplying +// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow +// in certain conditions because we store b1 as a 1.15 value. +// Instead, we could store b1 as b1p (b1' == b1 "prime") where +// b1p == b1/2, thus ensuring no potential overflow for b1p because +// 0 <= |b1p| < 1 +// However, during the filter calculation, we must account for the fact +// that we are using b1p instead of b1, and thereby multiply by +// an extra factor of 2. Rather than multiply by an extra factor of 2, +// we can instead shift the result right by one less, hence the +// modified shift right value of (NUM_EG1_FRAC_BITS -1) +#define MULT_EG1_EG1_X2(gain,damping) /*lint -e(702) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \ + ) \ + >> (NUM_EG1_FRAC_BITS -1) \ + ) + +#define SATURATE_EG1(x) /*lint -e{734} saturation operation */ \ + ((EAS_I32)(x) > SYNTH_FULL_SCALE_EG1_GAIN) ? (SYNTH_FULL_SCALE_EG1_GAIN) : \ + ((EAS_I32)(x) < EG1_MINUS_ONE) ? (EG1_MINUS_ONE) : (x); + + +/* use "digital cents" == "dents" instead of cents */ +/* we coudl re-use the phase frac macros, but if we do, +we must change the phase macros to cast to _I32 instead of _U32, +because using a _U32 cast causes problems when shifting the exponent +for the 2^x calculation, because right shift a negative values MUST +be sign extended, or else the 2^x calculation is wrong */ + +/* use "digital cents" == "dents" instead of cents */ +#define NUM_DENTS_FRAC_BITS 12 +#define NUM_DENTS_INT_BITS (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS) + +#define DENTS_FRAC_MASK (EAS_I32) ((0x1L << NUM_DENTS_FRAC_BITS) -1) + +#define GET_DENTS_INT_PART(x) /*lint -e(704) */ \ + (EAS_I32)((EAS_I32)(x) >> NUM_DENTS_FRAC_BITS) + +#define GET_DENTS_FRAC_PART(x) (EAS_I32)((EAS_I32)(x) & DENTS_FRAC_MASK) + +#define DENTS_ONE (EAS_I32) (0x1L << NUM_DENTS_FRAC_BITS) + +/* use CENTS_TO_DENTS to convert a value in cents to dents */ +#define CENTS_TO_DENTS (EAS_I32) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L) \ + + +/* +For gain, the LFO generates a value that modulates in terms +of dB. However, we use a linear gain value, so we must convert +the LFO value in dB to a linear gain. Normally, we would use +linear gain = 10^x, where x = LFO value in dB / 20. +Instead, we implement 10^x using our 2^x approximation. +because + + 10^x = 2^(log2(10^x)) = 2^(x * log2(10)) + +so we need to multiply by log2(10) which is just a constant. +Ah, but just wait -- our 2^x actually doesn't exactly implement +2^x, but it actually assumes that the input is in cents, and within +the 2^x approximation converts its input from cents to octaves +by dividing its input by 1200. + +So, in order to convert the LFO gain value in dB to something +that our existing 2^x approximation can use, multiply the LFO gain +by log2(10) * 1200 / 20 + +The divide by 20 helps convert dB to linear gain, and we might +as well incorporate that operation into this conversion. +Of course, we need to keep some fractional bits, so multiply +the constant by NUM_EG1_FRAC_BITS +*/ + +/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */ +#if 0 +#define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */ + +#define DOUBLE_LFO_GAIN_TO_CENTS (double) \ + ( \ + (DOUBLE_LOG2_10) * \ + 1200.0 / \ + 20.0 \ + ) + +#define LFO_GAIN_TO_CENTS (EAS_I32) \ + ( \ + DOUBLE_LFO_GAIN_TO_CENTS * \ + (0x1L << NUM_EG1_FRAC_BITS) \ + ) +#endif + +#define LFO_GAIN_TO_CENTS (EAS_I32) (1671981156L >> (23 - NUM_EG1_FRAC_BITS)) + + +#define MULT_DENTS_COEF(dents,coef) /*lint -e704 */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(dents)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_DENTS_FRAC_BITS \ + ) \ + /* lint +e704 */ + +/* we use 16-bits in the PC per audio sample */ +#define BITS_PER_AUDIO_SAMPLE 16 + +/* we define 1 as 1.0 - 1 LSbit */ +#define DISTORTION_ONE (EAS_I32)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1) +#define DISTORTION_MINUS_ONE (EAS_I32)(~DISTORTION_ONE) + +/* drive coef is given as int.frac */ +#define NUM_DRIVE_COEF_INT_BITS 1 +#define NUM_DRIVE_COEF_FRAC_BITS 4 + +#define MULT_AUDIO_DRIVE(audio,drive) /*lint -e(702) */ \ + (EAS_I32) ( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(drive)) \ + ) \ + >> NUM_DRIVE_COEF_FRAC_BITS \ + ) + +#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) */ \ + (EAS_I32) ( \ + ( \ + ((EAS_I32)(audio1)) * ((EAS_I32)(audio2)) \ + ) \ + >> (BITS_PER_AUDIO_SAMPLE-1) \ + ) + +#define SATURATE(x) \ + ((((EAS_I32)(x)) > DISTORTION_ONE) ? (DISTORTION_ONE) : \ + (((EAS_I32)(x)) < DISTORTION_MINUS_ONE) ? (DISTORTION_MINUS_ONE) : ((EAS_I32)(x))); + + + +/*---------------------------------------------------------------------------- + * EAS_Calculate2toX() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate 2^x + * + * Inputs: + * nCents - measured in cents + * + * Outputs: + * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_Calculate2toX (EAS_I32 nCents); + +/*---------------------------------------------------------------------------- + * EAS_LogToLinear16() + *---------------------------------------------------------------------------- + * Purpose: + * Transform log value to linear gain multiplier using piece-wise linear + * approximation + * + * Inputs: + * nGain - log scale value in 20.10 format. Even though gain is normally + * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate + * the need for saturation checking when combining gain values. + * + * Outputs: + * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain); + +/*---------------------------------------------------------------------------- + * EAS_VolumeToGain() + *---------------------------------------------------------------------------- + * Purpose: + * Transform volume control in 1dB increments to gain multiplier + * + * Inputs: + * volume - 100 = 0dB, 99 = -1dB, 0 = -inf + * + * Outputs: + * Returns a 16-bit linear value + *---------------------------------------------------------------------------- +*/ +EAS_I16 EAS_VolumeToGain (EAS_INT volume); + +/*---------------------------------------------------------------------------- + * EAS_fsqrt() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the square root of a 32-bit fixed point value + * + * Inputs: + * n = value of interest + * + * Outputs: + * returns the square root of n + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_fsqrt (EAS_U32 n); + +/*---------------------------------------------------------------------------- + * EAS_flog2() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the log2 of a 32-bit fixed point value + * + * Inputs: + * n = value of interest + * + * Outputs: + * returns the log2 of n + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_flog2 (EAS_U32 n); + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midi.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midi.c new file mode 100755 index 0000000..2c0c793 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midi.c @@ -0,0 +1,569 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midi.c + * + * Contents and purpose: + * This file implements the MIDI stream parser. It is called by eas_smf.c to parse MIDI messages + * that are streamed out of the file. It can also parse live MIDI streams. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 794 $ + * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_miditypes.h" +#include "eas_midi.h" +#include "eas_vm_protos.h" +#include "eas_parser.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + + +/* state enumerations for ProcessSysExMessage */ +typedef enum +{ + eSysEx, + eSysExUnivNonRealTime, + eSysExUnivNrtTargetID, + eSysExGMControl, + eSysExUnivRealTime, + eSysExUnivRtTargetID, + eSysExDeviceControl, + eSysExMasterVolume, + eSysExMasterVolLSB, + eSysExSPMIDI, + eSysExSPMIDIchan, + eSysExSPMIDIMIP, + eSysExMfgID1, + eSysExMfgID2, + eSysExMfgID3, + eSysExEnhancer, + eSysExEnhancerSubID, + eSysExEnhancerFeedback1, + eSysExEnhancerFeedback2, + eSysExEnhancerDrive, + eSysExEnhancerWet, + eSysExEOX, + eSysExIgnore +} E_SYSEX_STATES; + +/* local prototypes */ +static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode); +static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode); + +/*---------------------------------------------------------------------------- + * EAS_InitMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the MIDI stream state for parsing. + * + * Inputs: + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream) +{ + pMIDIStream->byte3 = EAS_FALSE; + pMIDIStream->pending = EAS_FALSE; + pMIDIStream->runningStatus = 0; + pMIDIStream->status = 0; +} + +/*---------------------------------------------------------------------------- + * EAS_ParseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled) + * so the interface works equally well for both file and stream I/O. + * + * Inputs: + * c - character from MIDI stream + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) +{ + + /* check for new status byte */ + if (c & 0x80) + { + /* save new running status */ + if (c < 0xf8) + { + pMIDIStream->runningStatus = c; + pMIDIStream->byte3 = EAS_FALSE; + + /* deal with SysEx */ + if ((c == 0xf7) || (c == 0xf0)) + { + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode); + } + + /* inform the file parser that we're in the middle of a message */ + if ((c < 0xf4) || (c > 0xf6)) + pMIDIStream->pending = EAS_TRUE; + } + + /* real-time message - ignore it */ + return EAS_SUCCESS; + } + + /* 3rd byte of a 3-byte message? */ + if (pMIDIStream->byte3) + { + pMIDIStream->d2 = c; + pMIDIStream->byte3 = EAS_FALSE; + pMIDIStream->pending = EAS_FALSE; + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode); + } + + /* check for status received */ + if (pMIDIStream->runningStatus) + { + + /* save new status and data byte */ + pMIDIStream->status = pMIDIStream->runningStatus; + + /* check for 3-byte messages */ + if (pMIDIStream->status < 0xc0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_TRUE; + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + + /* check for 2-byte messages */ + if (pMIDIStream->status < 0xe0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_FALSE; + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode); + } + + /* check for more 3-bytes message */ + if (pMIDIStream->status < 0xf0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_TRUE; + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + + /* SysEx message? */ + if (pMIDIStream->status == 0xF0) + { + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode); + } + + /* remaining messages all clear running status */ + pMIDIStream->runningStatus = 0; + + /* F2 is 3-byte message */ + if (pMIDIStream->status == 0xf2) + { + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + } + + /* no status byte received, provide a warning, but we should be able to recover */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Received MIDI data without a valid status byte: %d\n",c); */ } + pMIDIStream->pending = EAS_FALSE; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * ProcessMIDIMessage() + *---------------------------------------------------------------------------- + * Purpose: + * This function processes a typical MIDI message. All of the data has been received, just need + * to take appropriate action. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode) +{ + EAS_U8 channel; + + channel = pMIDIStream->status & 0x0f; + switch (pMIDIStream->status & 0xf0) + { + case 0x80: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode < eParserModeMute) + VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + break; + + case 0x90: + if (pMIDIStream->d2) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOn: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + pMIDIStream->flags |= MIDI_FLAG_FIRST_NOTE; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + } + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode < eParserModeMute) + VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + } + break; + + case 0xa0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PolyPres: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + break; + + case 0xb0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Control: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode < eParserModeMute) + VMControlChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); +#ifdef JET_INTERFACE + if (pMIDIStream->jetData & MIDI_FLAGS_JET_CB) + { + JET_Event(pEASData, pMIDIStream->jetData & (JET_EVENT_SEG_MASK | JET_EVENT_TRACK_MASK), + channel, pMIDIStream->d1, pMIDIStream->d2); + } +#endif + break; + + case 0xc0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Program: %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1); */ } + if (parserMode < eParserModeMute) + VMProgramChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1); + break; + + case 0xd0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"ChanPres: %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1); */ } + if (parserMode < eParserModeMute) + VMChannelPressure(pSynth, channel, pMIDIStream->d1); + break; + + case 0xe0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PBend: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode < eParserModeMute) + VMPitchBend(pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Unknown: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * ProcessSysExMessage() + *---------------------------------------------------------------------------- + * Purpose: + * Process a SysEx character byte from the MIDI stream. Since we cannot + * simply wait for the next character to arrive, we are forced to save + * state after each character. It would be easier to parse at the file + * level, but then we lose the nice feature of being able to support + * these messages in a real-time MIDI stream. + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * c - character to be processed + * locating - if true, the sequencer is relocating to a new position + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * These are the SysEx messages we can receive: + * + * SysEx messages + * { f0 7e 7f 09 01 f7 } GM 1 On + * { f0 7e 7f 09 02 f7 } GM 1/2 Off + * { f0 7e 7f 09 03 f7 } GM 2 On + * { f0 7f 7f 04 01 lsb msb } Master Volume + * { f0 7f 7f 0b 01 ch mip [ch mip ...] f7 } SP-MIDI + * { f0 00 01 3a 04 01 fdbk1 fdbk2 drive wet dry f7 } Enhancer + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) +{ + + /* check for start byte */ + if (c == 0xf0) + { + pMIDIStream->sysExState = eSysEx; + } + /* check for end byte */ + else if (c == 0xf7) + { + /* if this was a MIP message, update the MIP table */ + if ((pMIDIStream->sysExState == eSysExSPMIDIchan) && (parserMode != eParserModeMetaData)) + VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); + pMIDIStream->sysExState = eSysExIgnore; + } + + /* process SysEx message */ + else + { + switch (pMIDIStream->sysExState) + { + case eSysEx: + + /* first byte, determine message class */ + switch (c) + { + case 0x7e: + pMIDIStream->sysExState = eSysExUnivNonRealTime; + break; + case 0x7f: + pMIDIStream->sysExState = eSysExUnivRealTime; + break; + case 0x00: + pMIDIStream->sysExState = eSysExMfgID1; + break; + default: + pMIDIStream->sysExState = eSysExIgnore; + break; + } + break; + + /* process GM message */ + case eSysExUnivNonRealTime: + if (c == 0x7f) + pMIDIStream->sysExState = eSysExUnivNrtTargetID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExUnivNrtTargetID: + if (c == 0x09) + pMIDIStream->sysExState = eSysExGMControl; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExGMControl: + if ((c == 1) || (c == 3)) + { + /* GM 1 or GM2 On, reset synth */ + if (parserMode != eParserModeMetaData) + { + pMIDIStream->flags |= MIDI_FLAG_GM_ON; + VMReset(pEASData->pVoiceMgr, pSynth, EAS_FALSE); + VMInitMIPTable(pSynth); + } + pMIDIStream->sysExState = eSysExEOX; + } + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + /* Process Master Volume and SP-MIDI */ + case eSysExUnivRealTime: + if (c == 0x7f) + pMIDIStream->sysExState = eSysExUnivRtTargetID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExUnivRtTargetID: + if (c == 0x04) + pMIDIStream->sysExState = eSysExDeviceControl; + else if (c == 0x0b) + pMIDIStream->sysExState = eSysExSPMIDI; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + /* process master volume */ + case eSysExDeviceControl: + if (c == 0x01) + pMIDIStream->sysExState = eSysExMasterVolume; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMasterVolume: + /* save LSB */ + pMIDIStream->d1 = c; + pMIDIStream->sysExState = eSysExMasterVolLSB; + break; + + case eSysExMasterVolLSB: + if (parserMode != eParserModeMetaData) + { + EAS_I32 gain = ((EAS_I32) c << 8) | ((EAS_I32) pMIDIStream->d1 << 1); + gain = (gain * gain) >> 15; + VMSetVolume(pSynth, (EAS_U16) gain); + } + pMIDIStream->sysExState = eSysExEOX; + break; + + /* process SP-MIDI MIP message */ + case eSysExSPMIDI: + if (c == 0x01) + { + /* assume all channels are muted */ + if (parserMode != eParserModeMetaData) + VMInitMIPTable(pSynth); + pMIDIStream->d1 = 0; + pMIDIStream->sysExState = eSysExSPMIDIchan; + } + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExSPMIDIchan: + if (c < NUM_SYNTH_CHANNELS) + { + pMIDIStream->d2 = c; + pMIDIStream->sysExState = eSysExSPMIDIMIP; + } + else + { + /* bad MIP message - unmute channels */ + if (parserMode != eParserModeMetaData) + VMInitMIPTable(pSynth); + pMIDIStream->sysExState = eSysExIgnore; + } + break; + + case eSysExSPMIDIMIP: + /* process MIP entry here */ + if (parserMode != eParserModeMetaData) + VMSetMIPEntry(pEASData->pVoiceMgr, pSynth, pMIDIStream->d2, pMIDIStream->d1, c); + pMIDIStream->sysExState = eSysExSPMIDIchan; + + /* if 16 channels received, update MIP table */ + if (++pMIDIStream->d1 == NUM_SYNTH_CHANNELS) + { + if (parserMode != eParserModeMetaData) + VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); + pMIDIStream->sysExState = eSysExEOX; + } + break; + + /* process Enhancer */ + case eSysExMfgID1: + if (c == 0x01) + pMIDIStream->sysExState = eSysExMfgID1; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMfgID2: + if (c == 0x3a) + pMIDIStream->sysExState = eSysExMfgID1; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMfgID3: + if (c == 0x04) + pMIDIStream->sysExState = eSysExEnhancer; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExEnhancer: + if (c == 0x01) + pMIDIStream->sysExState = eSysExEnhancerSubID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExEnhancerSubID: + pMIDIStream->sysExState = eSysExEnhancerFeedback1; + break; + + case eSysExEnhancerFeedback1: + pMIDIStream->sysExState = eSysExEnhancerFeedback2; + break; + + case eSysExEnhancerFeedback2: + pMIDIStream->sysExState = eSysExEnhancerDrive; + break; + + case eSysExEnhancerDrive: + pMIDIStream->sysExState = eSysExEnhancerWet; + break; + + case eSysExEnhancerWet: + pMIDIStream->sysExState = eSysExEOX; + break; + + case eSysExEOX: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Expected F7, received %02x\n", c); */ } + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExIgnore: + break; + + default: + pMIDIStream->sysExState = eSysExIgnore; + break; + } + } + + if (pMIDIStream->sysExState == eSysExIgnore) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Ignoring SysEx byte %02x\n", c); */ } + return EAS_SUCCESS; +} /* end ProcessSysExMessage */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midi.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midi.h new file mode 100755 index 0000000..10649a0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midi.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midi.h + * + * Contents and purpose: + * Prototypes for MIDI stream parsing functions + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDI_H +#define _EAS_MIDI_H + +/*---------------------------------------------------------------------------- + * EAS_InitMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the MIDI stream state for parsing. + * + * Inputs: + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream); + +/*---------------------------------------------------------------------------- + * EAS_ParseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled) + * so the interface works equally well for both file and stream I/O. + * + * Inputs: + * c - character from MIDI stream + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode); + +#endif /* #define _EAS_MIDI_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midictrl.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midictrl.h new file mode 100755 index 0000000..46fdc4f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_midictrl.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midictrl.h + * + * Contents and purpose: + * MIDI controller definitions + * + * This header only contains declarations that are specific + * to this implementation. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDICTRL_H +#define _EAS_MIDICTRL_H + +/* define controller types */ +/* + Note that these controller types are specified in base 10 (decimal) + and not in hexadecimal. The above midi messages are specified + in hexadecimal. +*/ +#define MIDI_CONTROLLER_BANK_SELECT 0 +#define MIDI_CONTROLLER_BANK_SELECT_MSB 0 +#define MIDI_CONTROLLER_MOD_WHEEL 1 +#define MIDI_CONTROLLER_ENTER_DATA_MSB 6 +#define MIDI_CONTROLLER_VOLUME 7 +#define MIDI_CONTROLLER_PAN 10 +#define MIDI_CONTROLLER_EXPRESSION 11 +#define MIDI_CONTROLLER_BANK_SELECT_LSB 32 +#define MIDI_CONTROLLER_ENTER_DATA_LSB 38 /* 0x26 */ +#define MIDI_CONTROLLER_SUSTAIN_PEDAL 64 +#define MIDI_CONTROLLER_SELECT_NRPN_LSB 98 +#define MIDI_CONTROLLER_SELECT_NRPN_MSB 99 +#define MIDI_CONTROLLER_SELECT_RPN_LSB 100 /* 0x64 */ +#define MIDI_CONTROLLER_SELECT_RPN_MSB 101 /* 0x65 */ +#define MIDI_CONTROLLER_ALL_SOUND_OFF 120 +#define MIDI_CONTROLLER_RESET_CONTROLLERS 121 +#define MIDI_CONTROLLER_ALL_NOTES_OFF 123 +#define MIDI_CONTROLLER_OMNI_OFF 124 +#define MIDI_CONTROLLER_OMNI_ON 125 +#define MIDI_CONTROLLER_MONO_ON_POLY_OFF 126 +#define MIDI_CONTROLLER_POLY_ON_MONO_OFF 127 + +#endif /* #ifndef _EAS_MIDICTRL_H */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mididata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mididata.c new file mode 100755 index 0000000..4463b7e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mididata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mididata.c + * + * Contents and purpose: + * Data module for MIDI stream interface + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_miditypes.h" + +S_INTERACTIVE_MIDI eas_MIDIData; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_miditypes.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_miditypes.h new file mode 100755 index 0000000..015f08b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_miditypes.h @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_miditypes.h + * + * Contents and purpose: + * Contains declarations for the MIDI stream parser. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDITYPES_H +#define _EAS_MIDITYPES_H + +#include "eas_data.h" +#include "eas_parser.h" + +/*---------------------------------------------------------------------------- + * S_MIDI_STREAM + * + * Maintains parser state for the MIDI stream parser + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_midi_stream_tag +{ + EAS_BOOL8 byte3; /* flag indicates 3rd byte expected */ + EAS_BOOL8 pending; /* flag indicates more data expected */ + EAS_U8 sysExState; /* maintains the SysEx state */ + EAS_U8 runningStatus; /* last running status received */ + EAS_U8 status; /* status byte */ + EAS_U8 d1; /* first data byte */ + EAS_U8 d2; /* second data byte */ + EAS_U8 flags; /* flags - see below for definition */ +#ifdef JET_INTERFACE + EAS_U32 jetData; /* JET data */ +#endif +} S_MIDI_STREAM; + +/* flags for S_MIDI_STREAM.flags */ +#define MIDI_FLAG_GM_ON 0x01 /* GM System On message received */ +#define MIDI_FLAG_FIRST_NOTE 0x02 /* first note received */ + +/* flags for S_MIDI_STREAM.jetFlags */ +#define MIDI_FLAGS_JET_MUTE 0x00000001 /* track is muted */ +#define MIDI_FLAGS_JET_CB 0x00000002 /* JET callback enabled */ + +/*---------------------------------------------------------------------------- + * + * S_SMF_STREAM + * + * This structure contains data required to parse an SMF stream. For SMF0 files, there + * will be a single instance of this per file. For SMF1 files, there will be multiple instance, + * one for each separate stream in the file. + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_smf_stream_tag +{ + EAS_FILE_HANDLE fileHandle; /* host wrapper file handle */ + EAS_U32 ticks; /* time of next event in stream */ + EAS_I32 startFilePos; /* start location of track within file */ + S_MIDI_STREAM midiStream; /* MIDI stream state */ +} S_SMF_STREAM; + +/*---------------------------------------------------------------------------- + * + * S_SMF_DATA + * + * This structure contains the instance data required to parse an SMF stream. + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_smf_data_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + S_SMF_STREAM *streams; /* pointer to individual streams in file */ + S_SMF_STREAM *nextStream; /* pointer to next stream with event */ + S_SYNTH *pSynth; /* pointer to synth */ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I32 fileOffset; /* for embedded files */ + EAS_I32 time; /* current time in milliseconds/256 */ + EAS_U16 numStreams; /* actual number of streams */ + EAS_U16 tickConv; /* current MIDI tick to msec conversion */ + EAS_U16 ppqn; /* ticks per quarter note */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 flags; /* flags - see definitions below */ +} S_SMF_DATA; + +#define SMF_FLAGS_CHASE_MODE 0x01 /* chase mode - skip to first note */ +#define SMF_FLAGS_HAS_TIME_SIG 0x02 /* time signature encountered at time 0 */ +#define SMF_FLAGS_HAS_TEMPO 0x04 /* tempo encountered at time 0 */ +#define SMF_FLAGS_HAS_GM_ON 0x08 /* GM System On encountered at time 0 */ +#define SMF_FLAGS_JET_STREAM 0x80 /* JET in use - keep strict timing */ + +/* combo flags indicate setup bar */ +#define SMF_FLAGS_SETUP_BAR (SMF_FLAGS_HAS_TIME_SIG | SMF_FLAGS_HAS_TEMPO | SMF_FLAGS_HAS_GM_ON) + +/*---------------------------------------------------------------------------- + * Interactive MIDI structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_interactive_midi_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + S_SYNTH *pSynth; /* pointer to synth */ + S_MIDI_STREAM stream; /* stream data */ +} S_INTERACTIVE_MIDI; + +#endif /* #ifndef _EAS_MIDITYPES_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixbuf.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixbuf.c new file mode 100755 index 0000000..db5bd02 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixbuf.c @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixbuf.c + * + * Contents and purpose: + * Contains a data allocation for synthesizer + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" +#include "eas_mixer.h" + +// globals +EAS_I32 eas_MixBuffer[BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS]; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixer.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixer.c new file mode 100755 index 0000000..0a839a8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixer.c @@ -0,0 +1,464 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixer.c + * + * Contents and purpose: + * This file contains the critical components of the mix engine that + * must be optimized for best performance. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 706 $ + * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +//3 dls: This module is in the midst of being converted from a synth +//3 specific module to a general purpose mix engine + +/*------------------------------------ + * includes + *------------------------------------ +*/ +#include "eas_data.h" +#include "eas_host.h" +#include "eas_math.h" +#include "eas_mixer.h" +#include "eas_config.h" +#include "eas_report.h" + +#ifdef _MAXIMIZER_ENABLED +EAS_I32 MaximizerProcess (EAS_VOID_PTR pInstData, EAS_I32 *pSrc, EAS_I32 *pDst, EAS_I32 numSamples); +#endif + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +/* need to boost stereo by ~3dB to compensate for the panner */ +#define STEREO_3DB_GAIN_BOOST 512 + +/*---------------------------------------------------------------------------- + * EAS_MixEngineInit() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the mix engine for work, allocates buffers, locates effects modules, etc. + * + * Inputs: + * pEASData - instance data + * pInstData - pointer to variable to receive instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineInit (S_EAS_DATA *pEASData) +{ + + /* check Configuration Module for mix buffer allocation */ + if (pEASData->staticMemoryModel) + pEASData->pMixBuffer = EAS_CMEnumData(EAS_CM_MIX_BUFFER); + else + pEASData->pMixBuffer = EAS_HWMalloc(pEASData->hwInstData, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32)); + if (pEASData->pMixBuffer == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate mix buffer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet((void *)(pEASData->pMixBuffer), 0, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32)); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePrep() + *---------------------------------------------------------------------------- + * Purpose: + * Performs prep before synthesize a buffer of audio, such as clearing + * audio buffers, etc. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePrep (S_EAS_DATA *pEASData, EAS_I32 numSamples) +{ + + /* clear the mix buffer */ +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_HWMemSet(pEASData->pMixBuffer, 0, numSamples * (EAS_I32) sizeof(long) * 2); +#else + EAS_HWMemSet(pEASData->pMixBuffer, 0, (EAS_I32) numSamples * (EAS_I32) sizeof(long)); +#endif + + /* need to clear other side-chain effect buffers (chorus & reverb) */ +} + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePost + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the post-processing after all voices have been + * synthesized. It calls any sweeteners and does the final mixdown to + * the output buffer. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePost (S_EAS_DATA *pEASData, EAS_I32 numSamples) +{ + EAS_U16 gain; + +//3 dls: Need to restore the mix engine metrics + + /* calculate the gain multiplier */ +#ifdef _MAXIMIZER_ENABLED + if (pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effect) + { + EAS_I32 temp; + temp = MaximizerProcess(pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effectData, pEASData->pMixBuffer, pEASData->pMixBuffer, numSamples); + temp = (temp * pEASData->masterGain) >> 15; + if (temp > 32767) + gain = 32767; + else + gain = (EAS_U16) temp; + } + else + gain = (EAS_U16) pEASData->masterGain; +#else + gain = (EAS_U16) pEASData->masterGain; +#endif + + /* Not using all the gain bits for now + * Reduce the input to the compressor by 6dB to prevent saturation + */ +#ifdef _COMPRESSOR_ENABLED + if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData) + gain = gain >> 5; + else + gain = gain >> 4; +#else + gain = gain >> 4; +#endif + + /* convert 32-bit mix buffer to 16-bit output format */ +#if (NUM_OUTPUT_CHANNELS == 2) + SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) ((EAS_U16) numSamples * 2)); +#else + SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) numSamples); +#endif + +#ifdef _ENHANCER_ENABLED + /* enhancer effect */ + if (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData) + (*pEASData->effectsModules[EAS_MODULE_ENHANCER].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _GRAPHIC_EQ_ENABLED + /* graphic EQ effect */ + if (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData) + (*pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _COMPRESSOR_ENABLED + /* compressor effect */ + if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData) + (*pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _WOW_ENABLED + /* WOW requires a 32-bit buffer, borrow the mix buffer and + * pass it as the destination buffer + */ + /*lint -e{740} temporarily passing a parameter through an existing I/F */ + if (pEASData->effectsModules[EAS_MODULE_WOW].effectData) + (*pEASData->effectsModules[EAS_MODULE_WOW].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_WOW].effectData, + pEASData->pOutputAudioBuffer, + (EAS_PCM*) pEASData->pMixBuffer, + numSamples); +#endif + +#ifdef _TONECONTROLEQ_ENABLED + /* ToneControlEQ effect */ + if (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData) + (*pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _REVERB_ENABLED + /* Reverb effect */ + if (pEASData->effectsModules[EAS_MODULE_REVERB].effectData) + (*pEASData->effectsModules[EAS_MODULE_REVERB].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_REVERB].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _CHORUS_ENABLED + /* Chorus effect */ + if (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData) + (*pEASData->effectsModules[EAS_MODULE_CHORUS].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +} + +#ifndef NATIVE_EAS_KERNEL +/*---------------------------------------------------------------------------- + * SynthMasterGain + *---------------------------------------------------------------------------- + * Purpose: + * Mixes down audio from 32-bit to 16-bit target buffer + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void SynthMasterGain (long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 numSamples) { + + /* loop through the buffer */ + while (numSamples--) { + long s; + + /* read a sample from the input buffer and add some guard bits */ + s = *pInputBuffer++; + + /* add some guard bits */ + /*lint -e{704} */ + s = s >> 7; + + /* apply master gain */ + s *= (long) nGain; + + /* shift to lower 16-bits */ + /*lint -e{704} */ + s = s >> 9; + + /* saturate */ + s = SATURATE(s); + + *pOutputBuffer++ = (EAS_PCM)s; + } +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_MixEngineShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down effects modules and deallocates memory + * + * Inputs: + * pEASData - instance data + * pInstData - instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineShutdown (S_EAS_DATA *pEASData) +{ + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel && (pEASData->pMixBuffer != NULL)) + EAS_HWFree(pEASData->hwInstData, pEASData->pMixBuffer); + + return EAS_SUCCESS; +} + +#ifdef UNIFIED_MIXER +#ifndef NATIVE_MIX_STREAM +/*---------------------------------------------------------------------------- + * EAS_MixStream + *---------------------------------------------------------------------------- + * Mix a 16-bit stream into a 32-bit buffer + * + * pInputBuffer 16-bit input buffer + * pMixBuffer 32-bit mix buffer + * numSamples number of samples to mix + * gainLeft initial gain left or mono + * gainRight initial gain right + * gainLeft left gain increment per sample + * gainRight right gain increment per sample + * flags bit 0 = stereo source + * bit 1 = stereo output + *---------------------------------------------------------------------------- +*/ +void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags) +{ + EAS_I32 temp; + EAS_INT src, dest; + + /* NOTE: There are a lot of optimizations that can be done + * in the native implementations based on register + * availability, etc. For example, it may make sense to + * break this down into 8 separate routines: + * + * 1. Mono source to mono output + * 2. Mono source to stereo output + * 3. Stereo source to mono output + * 4. Stereo source to stereo output + * 5. Mono source to mono output - no gain change + * 6. Mono source to stereo output - no gain change + * 7. Stereo source to mono output - no gain change + * 8. Stereo source to stereo output - no gain change + * + * Other possibilities include loop unrolling, skipping + * a gain calculation every 2 or 4 samples, etc. + */ + + /* no gain change, use fast loops */ + if ((gainIncLeft == 0) && (gainIncRight == 0)) + { + switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT)) + { + /* mono to mono */ + case 0: + gainLeft >>= 15; + for (src = dest = 0; src < numSamples; src++, dest++) + { + + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* mono to stereo */ + case MIX_FLAGS_STEREO_OUTPUT: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src++, dest+=2) + { + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src] * gainRight) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* stereo to mono */ + case MIX_FLAGS_STEREO_SOURCE: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src+=2, dest++) + { + temp = (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + temp += ((pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS); + pMixBuffer[dest] += temp; + } + break; + + /* stereo to stereo */ + case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src+=2, dest+=2) + { + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS; + } + break; + } + } + + /* gain change - do gain increment */ + else + { + switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT)) + { + /* mono to mono */ + case 0: + for (src = dest = 0; src < numSamples; src++, dest++) + { + gainLeft += gainIncLeft; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* mono to stereo */ + case MIX_FLAGS_STEREO_OUTPUT: + for (src = dest = 0; src < numSamples; src++, dest+=2) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* stereo to mono */ + case MIX_FLAGS_STEREO_SOURCE: + for (src = dest = 0; src < numSamples; src+=2, dest++) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + temp = (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + temp += ((pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS); + pMixBuffer[dest] += temp; + } + break; + + /* stereo to stereo */ + case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT: + for (src = dest = 0; src < numSamples; src+=2, dest+=2) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + } + } +} +#endif +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixer.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixer.h new file mode 100755 index 0000000..b2eb33b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_mixer.h @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixer.h + * + * Contents and purpose: + * This file contains the critical components of the mix engine that + * must be optimized for best performance. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 706 $ + * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIXER_H +#define _EAS_MIXER_H + +//3 dls: This module is in the midst of being converted from a synth +//3 specific module to a general purpose mix engine + +#define MIX_FLAGS_STEREO_SOURCE 1 +#define MIX_FLAGS_STEREO_OUTPUT 2 +#define NUM_MIXER_GUARD_BITS 4 + +#include "eas_effects.h" + +extern void SynthMasterGain( long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 nNumLoopSamples); + +/*---------------------------------------------------------------------------- + * EAS_MixEngineInit() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the mix engine for work, allocates buffers, locates effects modules, etc. + * + * Inputs: + * pEASData - instance data + * pInstData - pointer to variable to receive instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineInit (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePrep() + *---------------------------------------------------------------------------- + * Purpose: + * Performs prep before synthesize a buffer of audio, such as clearing + * audio buffers, etc. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePrep (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePost + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the post-processing after all voices have been + * synthesized. It calls any sweeteners and does the final mixdown to + * the output buffer. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePost (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * EAS_MixEngineShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down effects modules and deallocates memory + * + * Inputs: + * pEASData - instance data + * pInstData - instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineShutdown (EAS_DATA_HANDLE pEASData); + +#ifdef UNIFIED_MIXER +/*---------------------------------------------------------------------------- + * EAS_MixStream + *---------------------------------------------------------------------------- + * Mix a 16-bit stream into a 32-bit buffer + * + * pInputBuffer 16-bit input buffer + * pMixBuffer 32-bit mix buffer + * numSamples number of samples to mix + * gainLeft initial gain left or mono + * gainRight initial gain right + * gainLeft left gain increment per sample + * gainRight right gain increment per sample + * flags bit 0 = stereo source + * bit 1 = stereo output + *---------------------------------------------------------------------------- +*/ +void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags); +#endif + +#endif /* #ifndef _EAS_MIXER_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ota.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ota.c new file mode 100755 index 0000000..5bc9062 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_ota.c @@ -0,0 +1,1077 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ota.c + * + * Contents and purpose: + * OTA parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_otadata.h" + +/* increase gain for mono ringtones */ +#define OTA_GAIN_OFFSET 8 + +/* file definitions */ +#define OTA_RINGTONE 0x25 +#define OTA_SOUND 0x1d +#define OTA_UNICODE 0x22 + +/* song type definitions */ +#define OTA_BASIC_SONG_TYPE 0x01 +#define OTA_TEMPORARY_SONG_TYPE 0x02 + +/* instruction ID coding */ +#define OTA_PATTERN_HEADER_ID 0x00 +#define OTA_NOTE_INST_ID 0x01 +#define OTA_SCALE_INST_ID 0x02 +#define OTA_STYLE_INST_ID 0x03 +#define OTA_TEMPO_INST_ID 0x04 +#define OTA_VOLUME_INST_ID 0x05 + +/* note durations */ +#define OTA_NORMAL_DURATION 0x00 +#define OTA_DOTTED_NOTE 0x01 +#define OTA_DOUBLE_DOTTED_NOTE 0x02 +#define OTA_TRIPLET_NOTE 0x03 + +/* loop count value for infinite loop */ +#define OTA_INFINITE_LOOP 0x0f + +/* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */ +#define DEFAULT_TICK_CONV 30476 + +/* default channel and program for OTA playback */ +#define OTA_CHANNEL 0 +#define OTA_PROGRAM 80 +#define OTA_VEL_MUL 4 +#define OTA_VEL_OFS 67 +#define OTA_VEL_DEFAULT 95 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +/* local prototypes */ +static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData); +static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue); +static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc); +static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc); + + +/*---------------------------------------------------------------------------- + * + * EAS_OTA_Parser + * + * This structure contains the functional interface for the OTA parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_OTA_Parser = +{ + OTA_CheckFileType, + OTA_Prepare, + OTA_Time, + OTA_Event, + OTA_State, + OTA_Close, + OTA_Reset, + OTA_Pause, + OTA_Resume, + NULL, + OTA_SetData, + OTA_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * + * bpmTable + * + * BPM conversion table. Converts bpm values to 256ths of a millisecond for a 32nd note + *---------------------------------------------------------------------------- +*/ +static const EAS_U32 bpmTable[32] = +{ + 76800, 68571, 61935, 54857, + 48000, 42667, 38400, 34286, + 30476, 27429, 24000, 21333, + 19200, 17143, 15360, 13714, + 12000, 10667, 9600, 8533, + 7680, 6737, 6000, 5408, + 4800, 4267, 3840, 3398, + 3024, 2685, 2400, 2133 +}; + +/*---------------------------------------------------------------------------- + * OTA_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + EAS_INT cmdLen; + EAS_INT state; + EAS_U8 temp; + + /* read the first byte, should be command length */ + *ppHandle = NULL; + if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS) + return result; + + /* read all the commands */ + cmdLen = temp; + state = 0; + while (cmdLen--) + { + + /* read the command, upper 7 bits */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS) + return result; + temp = temp >> 1; + + if (state == 0) + { + if (temp != OTA_RINGTONE) + break; + state++; + } + else + { + + if (temp == OTA_SOUND) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_OTA_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_OTA_DATA)); + if (!pData) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Malloc failed in OTA_Prepare\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pData, 0, sizeof(S_OTA_DATA)); + + /* return a pointer to the instance data */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_OPEN; + *ppHandle = pData; + break; + } + + if (temp != OTA_UNICODE) + break; + } + } + + /* not recognized */ + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + /* check for valid state */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + pData->state = EAS_STATE_ERROR; + if ((result = OTA_ParseHeader(pEASData, pData)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + EAS_U32 duration; + EAS_U8 temp; + + pData = (S_OTA_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + /* set program to square lead */ + if (parserMode != eParserModeMetaData) + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, OTA_PROGRAM); + + /* set channel volume to max */ + if (parserMode != eParserModeMetaData) + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += (EAS_I32) pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* if not in a pattern, read the pattern header */ + while (pData->current.patternLen == 0) + { + + /* check for loop - don't do infinite loops when locating */ + if (pData->loopCount && ((parserMode == eParserModePlay) || (pData->loopCount != OTA_INFINITE_LOOP))) + { + /* if not infinite loop, decrement loop count */ + if (pData->loopCount != OTA_INFINITE_LOOP) + pData->loopCount--; + + /* back to start of pattern*/ + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* if no previous position to restore, continue forward */ + else if (pData->restore.fileOffset < 0) + { + + /* check for end of song */ + if (pData->numPatterns == 0) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* read the next pattern header */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + if (temp != OTA_PATTERN_HEADER_ID) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA pattern header\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* get the pattern ID */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->currentPattern)) != EAS_SUCCESS) + return result; + + /* get the loop count */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->loopCount)) != EAS_SUCCESS) + return result; + + /* get the pattern length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->current.patternLen)) != EAS_SUCCESS) + return result; + + /* if pattern definition, save the current position */ + if (pData->current.patternLen) + { + if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* if pattern length is zero, repeat a previous pattern */ + else + { + /* make sure it's a valid pattern */ + if (pData->patterns[pData->currentPattern].fileOffset < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA pattern error, invalid pattern specified\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* save current position and data */ + if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS) + return result; + + /* seek to the pattern in the file */ + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* decrement pattern count */ + pData->numPatterns--; + } + + /* restore previous position */ + else + { + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS) + return result; + } + } + + /* get the next event */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + + switch (temp) + { + case OTA_NOTE_INST_ID: + /* fetch note value */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->note)) != EAS_SUCCESS) + return result; + + /* fetch note duration */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + duration = pData->tick * (0x20 >> temp); + + /* fetch note duration modifier */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS) + return result; + switch (temp) + { + case OTA_NORMAL_DURATION: + break; + + case OTA_DOTTED_NOTE: + duration += duration >> 1; + break; + + case OTA_DOUBLE_DOTTED_NOTE: + duration += (duration >> 1) + (duration >> 2); + break; + + case OTA_TRIPLET_NOTE: + duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note duration ignored\n"); */ } + break; + } + + /* check for note */ + if (pData->note) + { + + /* determine note length based on style */ + switch (pData->style) + { + case 0: + pData->restTicks = duration >> 4; + break; + case 1: + pData->restTicks = 0; + break; + case 2: + pData->restTicks = duration >> 1; + break; + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note style ignored\n"); */ } + } + + /* add octave */ + pData->note += pData->octave; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, pData->velocity); + pData->time += (EAS_I32) duration - (EAS_I32) pData->restTicks; + } + + /* this is a rest */ + else + pData->time += (EAS_I32) duration; + break; + + case OTA_SCALE_INST_ID: + /* fetch octave */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS) + return result; + pData->octave = (EAS_U8) (temp * 12 + 59); + break; + + case OTA_STYLE_INST_ID: + /* fetch note style */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->style)) != EAS_SUCCESS) + return result; + break; + + case OTA_TEMPO_INST_ID: + /* fetch tempo */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 5, &temp)) != EAS_SUCCESS) + return result; + pData->tick = bpmTable[temp]; + break; + + case OTA_VOLUME_INST_ID: + /* fetch volume */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &temp)) != EAS_SUCCESS) + return result; + pData->velocity = temp ? (EAS_U8) (temp * OTA_VEL_MUL + OTA_VEL_OFS) : 0; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected instruction ID in OTA stream\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* decrement pattern length */ + pData->current.patternLen--; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_OTA_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_OTA_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_STOPPED; + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + pData = (S_OTA_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + pData = (S_OTA_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = OTA_ParseHeader (pEASData, pData)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA *pData; + + /* can't pause a stopped stream */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA *pData; + + /* can't resume a stopped stream */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA *) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA*) pInstData; + switch (param) + { + /* return file type as OTA */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_OTA; + break; + +#if 0 + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = OTA_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData) +{ + EAS_RESULT result; + EAS_INT i; + EAS_INT state; + EAS_U8 temp; + EAS_U8 titleLen; + + /* initialize some data */ + pData->flags = 0; + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->patterns[0].fileOffset = pData->patterns[1].fileOffset = + pData->patterns[2].fileOffset = pData->patterns[3].fileOffset = -1; + pData->current.bitCount = 0; + pData->current.patternLen = 0; + pData->loopCount = 0; + pData->restore.fileOffset = -1; + pData->note = 0; + pData->restTicks = 0; + pData->velocity = OTA_VEL_DEFAULT; + pData->style = 0; + pData->octave = 59; + + /* seek to start of data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + + /* read the first byte, should be command length */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + + /* read all the commands */ + i = temp; + state = 0; + while (i--) + { + + /* fetch command, always starts on byte boundary */ + pData->current.bitCount = 0; + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 7, &temp)) != EAS_SUCCESS) + return result; + + if (state == 0) + { + if (temp != OTA_RINGTONE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Ring Tone Programming type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + state++; + } + else + { + + if (temp == OTA_SOUND) + break; + + if (temp == OTA_UNICODE) + pData->flags |= OTA_FLAGS_UNICODE; + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Sound or Unicode type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + } + } + + /* get song type */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + + /* check for basic song type */ + if (temp == OTA_BASIC_SONG_TYPE) + { + /* fetch title length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &titleLen)) != EAS_SUCCESS) + return result; + + /* if unicode, double the length */ + if (pData->flags & OTA_FLAGS_UNICODE) + titleLen = (EAS_U8) (titleLen << 1); + + /* zero the metadata buffer */ + if (pData->metadata.buffer) + EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize); + + /* read the song title */ + for (i = 0; i < titleLen; i++) + { + /* fetch character */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &temp)) != EAS_SUCCESS) + return result; + + /* check for metadata callback */ + if (pData->metadata.callback) + { + if (i < (pData->metadata.bufferSize - 1)) + pData->metadata.buffer[i] = (char) temp; + } + } + + /* if host has registered callback, call it now */ + if (pData->metadata.callback) + (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData); + } + + /* must be temporary song */ + else if (temp != OTA_TEMPORARY_SONG_TYPE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA basic or temporary song type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* get the song length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->numPatterns)) != EAS_SUCCESS) + return result; + + /* sanity check */ + if (pData->numPatterns == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA number of patterns is zero\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* at start of first pattern */ + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_FetchBitField() + *---------------------------------------------------------------------------- + * Purpose: + * Fetch a specified number of bits from the input stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue) +{ + EAS_RESULT result; + EAS_I32 bitsLeft; + EAS_U8 value; + + value = 0; + + /* do we have enough bits? */ + bitsLeft = pData->current.bitCount - numBits; + + /* not enough bits, assemble them from 2 characters */ + if (bitsLeft < 0) + { + /* grab the remaining bits from the previous byte */ + if (pData->current.bitCount) + /*lint -e{504,734} this is a legitimate shift operation */ + value = pData->current.dataByte << -bitsLeft; + + /* read the next byte */ + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->current.dataByte)) != EAS_SUCCESS) + return result; + bitsLeft += 8; + } + + /* more bits than needed? */ + if (bitsLeft > 0) + { + value |= pData->current.dataByte >> bitsLeft; + pData->current.bitCount = (EAS_U8) bitsLeft; + pData->current.dataByte = pData->current.dataByte & (0xff >> (8 - bitsLeft)); + } + + /* exactly the right number of bits */ + else + { + value |= pData->current.dataByte; + pData->current.bitCount = 0; + } + + *pValue = value; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_SavePosition() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc) +{ + EAS_HWMemCpy(pLoc, &pData->current, sizeof(S_OTA_LOC)); + return EAS_HWFilePos(hwInstData, pData->fileHandle, &pLoc->fileOffset); +} + +/*---------------------------------------------------------------------------- + * OTA_RestorePosition() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc) +{ + EAS_HWMemCpy(&pData->current, pLoc, sizeof(S_OTA_LOC)); + pData->restore.fileOffset = -1; + return EAS_HWFileSeek(hwInstData, pData->fileHandle, pLoc->fileOffset); +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_otadata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_otadata.c new file mode 100755 index 0000000..7463a0c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_otadata.c @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_otadata..c + * + * Contents and purpose: + * OTA Stream Parser data module for static memory model + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_otadata.h" + +/*---------------------------------------------------------------------------- + * + * eas_OTAData + * + * Static memory allocation for OTA parser + *---------------------------------------------------------------------------- +*/ +S_OTA_DATA eas_OTAData; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_otadata.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_otadata.h new file mode 100755 index 0000000..c06e3d3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_otadata.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_otadata.h + * + * Contents and purpose: + * OTA File Parser + * + * This file contains data declarations for the OTA parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_OTADATA_H +#define EAS_OTADATA_H + +#include "eas_data.h" + +/* definition for state flags */ +#define OTA_FLAGS_UNICODE 0x01 /* unicode text */ + +/*---------------------------------------------------------------------------- + * + * S_OTA_DATA + * + * This structure contains the state data for the OTA parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_I32 fileOffset; /* offset to location in file */ + EAS_U8 patternLen; /* length of current pattern */ + EAS_U8 dataByte; /* previous char from file */ + EAS_U8 bitCount; /* bit count in char */ +} S_OTA_LOC; + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* synth handle */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_U32 tick; /* length of 32nd note in 256th of a msec */ + EAS_U32 restTicks; /* ticks to rest after current note */ + S_OTA_LOC patterns[4]; /* pattern locations */ + S_OTA_LOC current; /* current location */ + S_OTA_LOC restore; /* previous location */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_U8 flags; /* bit flags */ + EAS_U8 numPatterns; /* number of patterns left in song */ + EAS_U8 currentPattern; /* current pattern for loop */ + EAS_U8 note; /* MIDI note number */ + EAS_U8 octave; /* octave modifier */ + EAS_U8 style; /* from STYLE */ + EAS_U8 velocity; /* current volume */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 loopCount; /* loop count for pattern */ +} S_OTA_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pan.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pan.c new file mode 100755 index 0000000..ae4c69d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pan.c @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pan.c + * + * Contents and purpose: + * Calculates left and right gain multipliers based on a pan value from -63 to +63 + * + * NOTES: + * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine + * whether the parser works for those particular file formats. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_pan.h" +#include "eas_math.h" + +/*---------------------------------------------------------------------------- + * EAS_CalcPanControl() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the left and right gain values corresponding to the given pan value. + * + * This routine uses sin/cos approximations for an equal power curve: + * + * sin(x) = (2-4*c)*x^2 + c + x + * cos(x) = (2-4*c)*x^2 + c - x + * + * where c = 1/sqrt(2) + * using the a0 + x*(a1 + x*a2) approach + * + * Inputs: + * pan - pan value (-63 to + 63) + * + * Outputs: + * pGainLeft linear gain multiplier for left channel (15-bit fraction) + * pGainRight linear gain multiplier for left channel (15-bit fraction) + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight) +{ + EAS_INT temp; + EAS_INT netAngle; + + /* impose hard limit */ + if (pan < -63) + netAngle = -63; + else if (pan > 63) + netAngle = 63; + else + netAngle = pan; + + /*lint -e{701} */ + netAngle = netAngle << 8; + + /* calculate sin */ + temp = EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle); + temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle); + + if (temp > SYNTH_FULL_SCALE_EG1_GAIN) + temp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (temp < 0) + temp = 0; + + *pGainRight = (EAS_I16) temp; + + /* calculate cos */ + temp = -EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle); + temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle); + if (temp > SYNTH_FULL_SCALE_EG1_GAIN) + temp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (temp < 0) + temp = 0; + + *pGainLeft = (EAS_I16) temp; +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pan.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pan.h new file mode 100755 index 0000000..cb0a90d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pan.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pan.h + * + * Contents and purpose: + * Calculates left and right gain multipliers based on a pan value from -63 to +63 + * + * NOTES: + * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine + * whether the parser works for those particular file formats. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_PAN_H +#define _EAS_PAN_H + +#include "eas_types.h" + +/*---------------------------------------------------------------------------- + * EAS_CalcPanControl() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the left and right gain values corresponding to the given pan value. + * + * This routine uses sin/cos approximations for an equal power curve: + * + * sin(x) = (2-4*c)*x^2 + c + x + * cos(x) = (2-4*c)*x^2 + c - x + * + * where c = 1/sqrt(2) + * using the a0 + x*(a1 + x*a2) approach + * + * Inputs: + * pan - pan value (-63 to + 63) + * + * Outputs: + * pGainLeft linear gain multiplier for left channel (15-bit fraction) + * pGainRight linear gain multiplier for left channel (15-bit fraction) + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight); + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_parser.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_parser.h new file mode 100755 index 0000000..96ec35b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_parser.h @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_parser.h + * + * Contents and purpose: + * Interface declarations for the generic parser interface + * + * This header only contains declarations that are specific + * to this implementation. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 767 $ + * $Date: 2007-07-19 13:47:31 -0700 (Thu, 19 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PARSER_H +#define _EAS_PARSER_H + +#include "eas_types.h" + + +/* metadata callback */ +typedef struct s_metadata_cb_tag +{ + EAS_METADATA_CBFUNC callback; + char *buffer; + EAS_VOID_PTR pUserData; + EAS_I32 bufferSize; +} S_METADATA_CB; + +/* generic parser interface */ +typedef struct +{ + EAS_RESULT (* EAS_CONST pfCheckFileType)(struct s_eas_data_tag *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); + EAS_RESULT (* EAS_CONST pfPrepare)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfTime)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); + EAS_RESULT (* EAS_CONST pfEvent)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_INT parseMode); + EAS_RESULT (* EAS_CONST pfState)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); + EAS_RESULT (* EAS_CONST pfClose)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfReset)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfPause)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfResume)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfLocate)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate); + EAS_RESULT (* EAS_CONST pfSetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + EAS_RESULT (* EAS_CONST pfGetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (* EAS_CONST pfGetMetaData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength); +} S_FILE_PARSER_INTERFACE; + +typedef enum +{ + eParserModePlay, + eParserModeLocate, + eParserModeMute, + eParserModeMetaData +} E_PARSE_MODE; + +typedef enum +{ + PARSER_DATA_FILE_TYPE, + PARSER_DATA_PLAYBACK_RATE, + PARSER_DATA_TRANSPOSITION, + PARSER_DATA_VOLUME, + PARSER_DATA_SYNTH_HANDLE, + PARSER_DATA_METADATA_CB, + PARSER_DATA_DLS_COLLECTION, + PARSER_DATA_EAS_LIBRARY, + PARSER_DATA_POLYPHONY, + PARSER_DATA_PRIORITY, + PARSER_DATA_FORMAT, + PARSER_DATA_MEDIA_LENGTH, + PARSER_DATA_JET_CB, + PARSER_DATA_MUTE_FLAGS, + PARSER_DATA_SET_MUTE, + PARSER_DATA_CLEAR_MUTE, + PARSER_DATA_NOTE_COUNT, + PARSER_DATA_MAX_PCM_STREAMS, + PARSER_DATA_GAIN_OFFSET, + PARSER_DATA_PLAY_MODE +} E_PARSER_DATA; + +#endif /* #ifndef _EAS_PARSER_H */ diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcm.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcm.c new file mode 100755 index 0000000..ff3f6f9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcm.c @@ -0,0 +1,1482 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcm.c + * + * Contents and purpose: + * Implements the PCM engine including ADPCM decode for SMAF and CMX audio playback. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 849 $ + * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_config.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_math.h" +#include "eas_mixer.h" + +#define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1) + +/*---------------------------------------------------------------------------- + * Decoder interfaces + *---------------------------------------------------------------------------- +*/ + +static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); + +static const S_DECODER_INTERFACE PCMDecoder = +{ + NULL, + LinearPCMDecode, + LinearPCMLocate, +}; + +/* SMAF ADPCM decoder */ +#ifdef _SMAF_PARSER +extern S_DECODER_INTERFACE SmafDecoder; +#define SMAF_DECODER &SmafDecoder +extern S_DECODER_INTERFACE Smaf7BitDecoder; +#define SMAF_7BIT_DECODER &Smaf7BitDecoder +#else +#define SMAF_DECODER NULL +#define SMAF_7BIT_DECODER NULL +#endif + +/* IMA ADPCM decoder */ +#ifdef _IMA_DECODER +extern S_DECODER_INTERFACE IMADecoder; +#define IMA_DECODER &IMADecoder +#else +#define IMA_DECODER NULL +#endif + +static const S_DECODER_INTERFACE * const decoders[] = +{ + &PCMDecoder, + SMAF_DECODER, + IMA_DECODER, + SMAF_7BIT_DECODER +}; + +/*---------------------------------------------------------------------------- + * Sample rate conversion + *---------------------------------------------------------------------------- +*/ + +#define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE) + +#ifdef _LOOKUP_SAMPLE_RATE +static const EAS_U32 srcConvRate[][2] = +{ + 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE, + 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE, + 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE, + 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE, + 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE, + 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE, + 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE, + 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE +}; +static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate); +#define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2) +#endif + + +/* interface prototypes */ +static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples); + + +/* local prototypes */ +static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData); +static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_PEInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData) +{ + S_PCM_STATE *pState; + EAS_INT i; + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA); + /* allocate dynamic memory */ + else + pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); + + if (!pEASData->pPCMStreams) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + //zero the memory to insure complete initialization + EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); + + /* initialize the state data */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + pState->fileHandle = NULL; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData) +{ + + /* free any dynamic memory */ + if (!pEASData->staticMemoryModel) + { + if (pEASData->pPCMStreams) + { + EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams); + pEASData->pPCMStreams = NULL; + } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PERender() + *---------------------------------------------------------------------------- + * Purpose: + * Render a buffer of PCM audio + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples) +{ + S_PCM_STATE *pState; + EAS_RESULT result; + EAS_INT i; + + /* render all the active streams */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + { + if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED)) + if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS) + return result; + } + return EAS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + * EAS_PEState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState) +{ + /* return current state */ + *pState = pInstData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_RESULT result; + + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS) + return result; + + pState->fileHandle = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * PCM_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_RESULT result; + + /* reset file position to first byte of data in the stream */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ } + return result; + } + + /* re-initialize stream */ + return InitPCMStream(pEASData, pState); +} + +/*---------------------------------------------------------------------------- + * EAS_PEOpenStream() + *---------------------------------------------------------------------------- + * Purpose: + * Starts up a PCM playback + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle) +{ + EAS_RESULT result; + S_PCM_STATE *pState; + EAS_I32 filePos; + + /* make sure we support this decoder */ + if (pParams->decoder >= NUM_DECODER_MODULES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ } + return EAS_ERROR_PARAMETER_RANGE; + } + if (decoders[pParams->decoder] == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ } + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + } + + /* find a slot for the new stream */ + if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ } + return EAS_ERROR_MAX_PCM_STREAMS; + } + + /* get the current file position */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ } + pState->fileHandle = NULL; + return result; + } + + pState->pDecoder = decoders[pParams->decoder]; + pState->startPos = filePos; + pState->bytesLeftLoop = pState->byteCount = pParams->size; + pState->loopStart = pParams->loopStart; + pState->samplesTilLoop = (EAS_I32) pState->loopStart; + pState->loopSamples = pParams->loopSamples; + pState->samplesInLoop = 0; + pState->blockSize = (EAS_U16) pParams->blockSize; + pState->flags = pParams->flags; + pState->envData = pParams->envData; + pState->volume = pParams->volume; + pState->sampleRate = (EAS_U16) pParams->sampleRate; + + /* set the base frequency */ + pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15; + + /* calculate shift for frequencies > 1.0 */ + pState->rateShift = 0; + while (pState->basefreq > 32767) + { + pState->basefreq = pState->basefreq >> 1; + pState->rateShift++; + } + + /* initialize */ + if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS) + return result; + + *pHandle = pState; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n", + pState->startPos, pState->byteCount, pState->loopSamples); */ } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEContinueStream() + *---------------------------------------------------------------------------- + * Purpose: + * Continues a PCM stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{715} reserved for future use */ +EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size) +{ + + /* add new samples to count */ + pState->bytesLeft += size; + if (pState->bytesLeft > 0) + pState->flags &= ~PCM_FLAGS_EMPTY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEGetFileHandle() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the file handle of a stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle) +{ + *pFileHandle = pState->fileHandle; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateParams() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch and volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * pitch - pitch shift in cents + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +/*lint -esym(715, gainRight) used only in 2-channel version */ +EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight) +{ + + pState->gainLeft = gainLeft; + +#if (NUM_OUTPUT_CHANNELS == 2) + pState->gainRight = gainRight; +#endif + + pState->pitch = pitch; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PELocate() + *---------------------------------------------------------------------------- + * Purpose: + * This function seeks to the requested place in the file. Accuracy + * is dependent on the sample rate and block size. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pState - stream handle + * time - media time in milliseconds + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time) +{ + if (pState->pDecoder->pfLocate == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + return pState->pDecoder->pfLocate(pEASData, pState, time); +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Update the volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume) +{ + pState->volume = volume; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdatePitch() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch parameter for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * pState - pointer to S_PCM_STATE for this stream + * pitch - new pitch value in pitch cents + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch) +{ + pState->pitch = pitch; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEPause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + /* set state to stopping */ + pState->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + /* set state to stopping */ + pState->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +EAS_U32 getDecayScale(EAS_U32 index) +{ + EAS_U32 utemp; + + //envelope decay segment + switch (index) + { + case 0: //no decay + utemp = 512;//32768; + break; + case 1: //.0156 dB per update + utemp = 511;//32709; + break; + case 2: //.03125 + utemp = 510;//32649; + break; + case 3: //.0625 + utemp = 508;//32532; + break; + case 4: //.125 + utemp = 505;//32298; + break; + case 5: //.25 + utemp = 497;//31835; + break; + case 6: //.5 + utemp = 483;//30929; + break; + case 7: //1.0 + utemp = 456;//29193; + break; + case 8: //2.0 + utemp = 406;//26008; + break; + case 9: //4.0 + utemp = 323;//20642; + break; + case 10: //8.0 + utemp = 203;//13004; + break; + case 11: //16.0 + utemp = 81;//5160; + break; + case 12: //32.0 + utemp = 13;//813; + break; + case 13: //64.0 + utemp = 0;//20; + break; + case 14: //128.0 + utemp = 0; + break; + case 15: //256.0 + default: + utemp = 0; + break; + } + //printf("getdecayscale returned %d\n",utemp); + return utemp; +} + +EAS_U32 getAttackIncrement(EAS_U32 index) +{ + EAS_U32 utemp; + + //envelope decay segment + switch (index) + { + case 0: + utemp = 32; + break; + case 1: + utemp = 64; + break; + case 2: + utemp = 128; + break; + case 3: + utemp = 256; + break; + case 4: + utemp = 512; + break; + case 5: + utemp = 1024; + break; + case 6: + utemp = 2048; + break; + case 7: + utemp = 4096; + break; + case 8: + utemp = 8192; + break; + case 9: + utemp = 16384; + break; + case 10: + utemp = 32768; + break; + case 11: + utemp = 65536; + break; + case 12: + utemp = 65536; + break; + case 13: + utemp = 65536; + break; + case 14: + utemp = 65535; + break; + case 15: + default: + utemp = 0; + break; + } + //printf("getattackincrement returned %d\n",utemp); + return utemp; +} + +/*---------------------------------------------------------------------------- + * EAS_PERelease() + *---------------------------------------------------------------------------- + * Purpose: + * Put the PCM stream envelope into release. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_U32 utemp; + + //printf("handling note-off part of envelope\n"); + /*if the note is not ignore release or sustained*/ + if (((pState->envData >> 24) & 0x0F)==0) + { + /* set envelope state to release */ + pState->envState = PCM_ENV_RELEASE; + utemp = ((pState->envData >> 20) & 0x0F); + pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp); + } + else + { + /*else change envelope state to sustain */ + pState->envState = PCM_ENV_SUSTAIN; + utemp = ((pState->envData >> 28) & 0x0F); + pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); + } + //since we are in release, don't let anything hang around too long + //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale); + if (pState->envScale > 505) + pState->envScale = 505; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * FindSlot() + *---------------------------------------------------------------------------- + * Purpose: + * Locates an empty stream slot and assigns the file handle + * + * Inputs: + * pEASData - pointer to EAS library instance data + * fileHandle - file handle + * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED + * + * Outputs: + * returns handle to slot or NULL if all slots are used + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData) +{ + EAS_INT i; + S_PCM_STATE *pState; + +#ifndef NO_PCM_STEAL + S_PCM_STATE *foundState = NULL; + EAS_INT count = 0; + EAS_U32 startOrder = 0xFFFFFFFF; + S_PCM_STATE *stealState = NULL; + EAS_U32 youngest = 0; + + /* find an empty slot, count total in use, and find oldest in use (lowest start order) */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + { + /* if this one is available */ + if (pState->fileHandle == NULL) + { + foundState = pState; + } + /* else this one is in use, so see if it is the oldest, and count total in use */ + /* also find youngest */ + else + { + /*one more voice in use*/ + count++; + /* is this the oldest? (lowest start order) */ + if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder)) + { + /* remember this one */ + stealState = pState; + /* remember the oldest so far */ + startOrder = pState->startOrder; + } + /* is this the youngest? (highest start order) */ + if (pState->startOrder >= youngest) + { + youngest = pState->startOrder; + } + } + } + + /* if there are too many voices active, stop the oldest one */ + if (count > PCM_STREAM_THRESHOLD) + { + //printf("stealing!!!\n"); + /* make sure we got one, although we should always have one at this point */ + if (stealState != NULL) + { + //flag this as stopping, so it will get shut off + stealState->state = EAS_STATE_STOPPING; + } + } + + /* if there are no available open streams (we won't likely see this, due to stealing) */ + if (foundState == NULL) + return NULL; + + /* save info */ + foundState->startOrder = youngest + 1; + foundState->fileHandle = fileHandle; + foundState->pCallback = pCallbackFunc; + foundState->cbInstData = cbInstData; + return foundState; +#else + /* find an empty slot*/ + for (i = 0; i < MAX_PCM_STREAMS; i++) + { + pState = &pEASData->pPCMStreams[i]; + if (pState->fileHandle != NULL) + continue; + + pState->fileHandle = fileHandle; + pState->pCallback = pCallbackFunc; + pState->cbInstData = cbInstData; + return pState; + } + return NULL; +#endif +} + +#ifdef _LOOKUP_SAMPLE_RATE +/*---------------------------------------------------------------------------- + * CalcBaseFreq() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the fractional phase increment for the sample rate converter + * + * Inputs: + * sampleRate - sample rate in samples/sec + * + * Outputs: + * Returns fractional sample rate with a 15-bit fraction + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate) +{ + EAS_INT i; + + /* look up the conversion rate */ + for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++) + { + if (srcConvRate[i][0] == sampleRate) + return srcConvRate[i][1]; + } + + /* if not found in table, do it the long way */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ } + + return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15; +} +#endif + +/*---------------------------------------------------------------------------- + * InitPCMStream() + *---------------------------------------------------------------------------- + * Purpose: + * Start an ADPCM stream playback. Decodes the header, preps the engine. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState) +{ + + /* initialize the data structure */ + pState->bytesLeft = pState->byteCount; + pState->phase = 0; + pState->srcByte = 0; + pState->decoderL.acc = 0; + pState->decoderL.output = 0; + pState->decoderL.x0 = pState->decoderL.x1 = 0; + pState->decoderL.step = 0; + pState->decoderR.acc = 0; + pState->decoderR.output = 0; + pState->decoderR.x0 = pState->decoderR.x1 = 0; + pState->decoderR.step = 0; + pState->hiNibble = EAS_FALSE; + pState->pitch = 0; + pState->blockCount = 0; + pState->gainLeft = PCM_DEFAULT_GAIN_SETTING; +// pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING; + pState->envValue = 0; + pState->envState = PCM_ENV_START; + +#if (NUM_OUTPUT_CHANNELS == 2) + pState->gainRight = PCM_DEFAULT_GAIN_SETTING; +// pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING; +#endif + pState->state = EAS_STATE_READY; + + /* initialize the decoder */ + if (pState->pDecoder->pfInit) + return (*pState->pDecoder->pfInit)(pEASData, pState); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RenderPCMStream() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes a buffer of ADPCM data. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples) +{ + EAS_RESULT result; + EAS_U32 phaseInc; + EAS_I32 gainLeft, gainIncLeft; + EAS_I32 *pOut; + EAS_I32 temp; + EAS_U32 utemp; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I32 gainRight, gainIncRight; +#endif + +#if 0 + printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n", + ((pState->envData >> 12) & 0x0F), + ((pState->envData >> 16) & 0x0F), + ((pState->envData >> 8) & 0x0F), + ((pState->envData >> 28) & 0x0F), + ((pState->envData >> 20) & 0x0F)); +#endif + + if (pState->envState == PCM_ENV_START) + { + //printf("env start\n"); + utemp = ((pState->envData >> 12) & 0x0F); + //if fastest rate, attack is already completed + //do the same for slowest rate, since that allows zero to be passed for default envelope + if (utemp == 0x0F || utemp == 0x00) + { + //start envelope at full + pState->envValue = (32768<<7); + //jump right into decay + utemp = ((pState->envData >> 16) & 0x0F); + pState->envScale = getDecayScale(utemp); + pState->envState = PCM_ENV_DECAY; + pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume); + pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume); + } + //else attack has a ramp + else + { + //start the envelope very low + pState->envValue = (2<<7); + pState->currentGainLeft = 0; + pState->currentGainRight = 0; + //get envelope attack scaling value + pState->envScale = getAttackIncrement(utemp); + //go to attack state + pState->envState = PCM_ENV_ATTACK; + } + } + if (pState->envState == PCM_ENV_ATTACK) + { + //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = pState->envValue + (pState->envScale << 7); + //check envelope level and update state if needed + if (pState->envValue >= (32768<<7)) + { + pState->envValue = (32768<<7); + utemp = ((pState->envData >> 16) & 0x0F); + pState->envScale = getDecayScale(utemp); + pState->envState = PCM_ENV_DECAY; + } + } + else if (pState->envState == PCM_ENV_DECAY) + { + //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against sustain level and update state if needed + utemp = ((pState->envData >> 8) & 0x0F); + if (utemp == (EAS_U32)0x0F) + utemp = (2<<7); + else + { + utemp = ((32769<<7) >> (utemp>>1)); + } + if (pState->envValue <= utemp) + { + utemp = ((pState->envData >> 28) & 0x0F); + pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); + pState->envState = PCM_ENV_SUSTAIN; + } + } + else if (pState->envState == PCM_ENV_SUSTAIN) + { + //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against bottom level and update state if needed + if (pState->envValue <= (2<<7)) + { + //no more decay + pState->envScale = 512; + pState->envState = PCM_ENV_END; + } + } + else if (pState->envState == PCM_ENV_RELEASE) + { + //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against bottom level and update state if needed + if (pState->envValue <= (2<<7)) + { + //no more decay + pState->envScale = 512; + pState->envState = PCM_ENV_END; + } + } + else if (pState->envState == PCM_ENV_END) + { + //printf("env end\n"); + /* set state to stopping, already ramped down */ + pState->state = EAS_STATE_STOPPING; + } + + //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15); + //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15); + + /* gain to 32-bits to increase resolution on anti-zipper filter */ + /*lint -e{703} use shift for performance */ + gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS; +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{703} use shift for performance */ + gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS; +#endif + + /* calculate a new gain increment, gain target is zero if pausing */ + if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED)) + { + gainIncLeft = -pState->currentGainLeft; +#if (NUM_OUTPUT_CHANNELS == 2) + gainIncRight= -pState->currentGainRight; +#endif + } + else + { + EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume); + gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft; +#if (NUM_OUTPUT_CHANNELS == 2) + gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight; +#endif + } + + /* calculate phase increment */ + phaseInc = pState->basefreq; + + /* convert pitch cents to linear multiplier */ + if (pState->pitch) + { + temp = EAS_Calculate2toX(pState->pitch); + phaseInc = FMUL_15x15(phaseInc, temp); + } + phaseInc = phaseInc << pState->rateShift; + + /* pointer to mix buffer */ + pOut = pEASData->pMixBuffer; + + /* render a buffer of samples */ + while (numSamples--) + { + + /* interpolate an output sample */ + pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK); + + /* stereo output */ +#if (NUM_OUTPUT_CHANNELS == 2) + + /* stereo stream? */ + if (pState->flags & PCM_FLAGS_STEREO) + pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); + + /* gain scale and mix */ + /*lint -e{704} use shift instead of division */ + *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + gainLeft += gainIncLeft; + + /*lint -e{704} use shift instead of division */ + if (pState->flags & PCM_FLAGS_STEREO) + *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + else + *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + + gainRight += gainIncRight; + + /* mono output */ +#else + /* if stereo stream, decode right channel and mix to mono */ + if (pState->flags & PCM_FLAGS_STEREO) + { + pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); + + /* for mono, sum stereo ADPCM to mono */ + /*lint -e{704} use shift instead of division */ + *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + } + else + /*lint -e{704} use shift instead of division */ + *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + + gainLeft += gainIncLeft; +#endif + + /* advance phase accumulator */ + pState->phase += phaseInc; + + /* if integer part of phase accumulator is non-zero, advance to next sample */ + while (pState->phase & ~PHASE_FRAC_MASK) + { + pState->decoderL.x0 = pState->decoderL.x1; + pState->decoderR.x0 = pState->decoderR.x1; + + /* give the source a chance to continue the stream */ + if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0)) + { + pState->flags |= PCM_FLAGS_EMPTY; + (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ } + } + + /* decode the next sample */ + if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS) + return result; + + /* adjust phase by one sample */ + pState->phase -= (1L << NUM_PHASE_FRAC_BITS); + } + + } + + /* save new gain */ + /*lint -e{704} use shift instead of division */ + pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS); + +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{704} use shift instead of division */ + pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS); +#endif + + /* if pausing, set new state and notify */ + if (pState->state == EAS_STATE_PAUSING) + { + pState->state = EAS_STATE_PAUSED; + if (pState->pCallback) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); + } + + /* if out of data, set stopped state and notify */ + if (pState->bytesLeft == 0 || pState->state == EAS_STATE_STOPPING) + { + pState->state = EAS_STATE_STOPPED; + + /* do callback unless the file has already been closed */ + if (pState->pCallback && pState->fileHandle) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); + } + + if (pState->state == EAS_STATE_READY) + pState->state = EAS_STATE_PLAY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * LinearPCMDecode() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes a PCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + EAS_RESULT result; + EAS_HW_DATA_HANDLE hwInstData; + + hwInstData = ((S_EAS_DATA*) pEASData)->hwInstData; + + /* if out of data, check for loop */ + if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) + { + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) + return result; + pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; + pState->flags &= ~PCM_FLAGS_EMPTY; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "LinearPCMDecode: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } + } + + if (pState->bytesLeft) + { + + /* check format byte for 8-bit samples */ + if (pState->flags & PCM_FLAGS_8_BIT) + { + /* fetch left or mono sample */ + if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* if unsigned */ + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ + pState->decoderL.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); + } + else + { + /*lint -e{734} converting signed 8-bit to signed 16-bit */ + pState->decoderL.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); + } + pState->bytesLeft--; + + /* fetch right sample */ + if(pState->flags & PCM_FLAGS_STEREO) + { + if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* if unsigned */ + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ + pState->decoderR.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); + } + else + { + /*lint -e{734} converting signed 8-bit to signed 16-bit */ + pState->decoderR.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); + } + pState->bytesLeft--; + } + } + + /* must be 16-bit samples */ + else + { + //unsigned 16 bit currently not supported + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + return EAS_ERROR_INVALID_PCM_TYPE; + } + + /* fetch left or mono sample */ + if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderL.x1, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->bytesLeft -= 2; + + /* fetch right sample */ + if(pState->flags & PCM_FLAGS_STEREO) + { + if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderR.x1, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->bytesLeft -= 2; + } + } + } + + /* no more data, force zero samples */ + else + pState->decoderL.x1 = pState->decoderR.x1 = 0; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * LinearPCMLocate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate in a linear PCM stream + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_I32 secs, msecs; + EAS_INT shift; + + /* calculate size of sample frame */ + if (pState->flags & PCM_FLAGS_8_BIT) + shift = 0; + else + shift = 1; + if (pState->flags & PCM_FLAGS_STEREO) + shift++; + + /* break down into secs and msecs */ + secs = time / 1000; + msecs = time - (secs * 1000); + + /* calculate sample number fraction from msecs */ + temp = (msecs * pState->sampleRate); + temp = (temp >> 10) + ((temp * 49) >> 21); + + /* add integer sample count */ + temp += secs * pState->sampleRate; + + /* calculate the position based on sample frame size */ + /*lint -e{703} use shift for performance */ + temp <<= shift; + + /* past end of sample? */ + if (temp > (EAS_I32) pState->loopStart) + { + /* if not looped, flag error */ + if (pState->loopSamples == 0) + { + pState->bytesLeft = 0; + pState->flags |= PCM_FLAGS_EMPTY; + return EAS_ERROR_LOCATE_BEYOND_END; + } + + /* looped sample - calculate position in loop */ + while (temp > (EAS_I32) pState->loopStart) + temp -= (EAS_I32) pState->loopStart; + } + + /* seek to new position */ + if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) + return result; + + /* reset state */ + if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) + pState->state = EAS_STATE_READY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PESeek + *---------------------------------------------------------------------------- + * Purpose: + * Locate to a particular byte in a PCM stream + *---------------------------------------------------------------------------- + * This bit is tricky because the chunks may not be contiguous, + * so we have to rely on the parser to position in the file. We + * do this by seeking to the end of each chunk and simulating an + * empty buffer condition until we get to where we want to go. + * + * A better solution would be a parser API for re-positioning, + * but there isn't time at the moment to re-factor all the + * parsers to support a new API. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PESeek (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation) +{ + EAS_RESULT result; + + /* seek to start of audio */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + pState->bytesLeft = pState->bytesLeftLoop; + + /* skip through chunks until we find the right chunk */ + while (*pLocation > (EAS_I32) pState->bytesLeft) + { + /* seek to end of audio chunk */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", pState->bytesLeft); */ } + if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, pState->bytesLeft)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + *pLocation -= pState->bytesLeft; + pState->bytesLeft = 0; + pState->flags |= PCM_FLAGS_EMPTY; + + /* retrieve more data */ + if (pState->pCallback) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: bytesLeft=%d, byte location = %d\n", pState->bytesLeft, *pLocation); */ } + + /* no more samples */ + if (pState->bytesLeft == 0) + return EAS_ERROR_LOCATE_BEYOND_END; + } + + /* seek to new offset in current chunk */ + if (*pLocation > 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", *pLocation); */ } + if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, *pLocation)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + + /* if not streamed, calculate number of bytes left */ + if (pState->flags & PCM_FLAGS_STREAMING) + pState->bytesLeft = 0x7fffffff; + else + pState->bytesLeft -= *pLocation; + } + return EAS_SUCCESS; +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcm.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcm.h new file mode 100755 index 0000000..4fc77e9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcm.h @@ -0,0 +1,359 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcm.h + * + * Contents and purpose: + * External function prototypes for eas_pcm.c module + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PCM_H +#define _EAS_PCM_H + +/* default gain setting - roughly unity gain */ +#define PCM_DEFAULT_GAIN_SETTING 0x6000 + +typedef struct s_pcm_state_tag *EAS_PCM_HANDLE; +typedef void (*EAS_PCM_CALLBACK) (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR cbInstData, EAS_PCM_HANDLE pcmHandle, EAS_STATE state); + +/* parameters for EAS_PEOpenStream */ +typedef struct s_pcm_open_params_tag +{ + EAS_FILE_HANDLE fileHandle; + EAS_I32 decoder; + EAS_U32 sampleRate; + EAS_I32 size; + EAS_U32 loopStart; + EAS_U32 loopSamples; + EAS_I32 blockSize; + EAS_U32 flags; + EAS_U32 envData; + EAS_I16 volume; + EAS_PCM_CALLBACK pCallbackFunc; + EAS_VOID_PTR cbInstData; + } S_PCM_OPEN_PARAMS; + +/*---------------------------------------------------------------------------- + * EAS_PEInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEInit (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_PEShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEShutdown (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_PEOpenStream() + *---------------------------------------------------------------------------- + * Purpose: + * Starts up a PCM playback + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEOpenStream (EAS_DATA_HANDLE pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle); + +/*---------------------------------------------------------------------------- + * EAS_PEContinueStream() + *---------------------------------------------------------------------------- + * Purpose: + * Continues a PCM stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEContinueStream (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_I32 size); + +/*---------------------------------------------------------------------------- + * EAS_PEGetFileHandle() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the file handle of a stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEGetFileHandle (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_FILE_HANDLE *pFileHandle); + +/*---------------------------------------------------------------------------- + * EAS_PERender() + *---------------------------------------------------------------------------- + * Purpose: + * Render a buffer of PCM audio + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERender (EAS_DATA_HANDLE pEASData, EAS_I32 numSamples); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateParams() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch and volume parameters using MIDI controls + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEUpdateParams (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight); + +/*---------------------------------------------------------------------------- + * EAS_PELocate() + *---------------------------------------------------------------------------- + * Purpose: + * This function seeks to the requested place in the file. Accuracy + * is dependent on the sample rate and block size. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pState - stream handle + * time - media time in milliseconds + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PELocate (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I32 time); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Update the volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdateVolume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdatePitch() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch parameter for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * pState - pointer to S_PCM_STATE for this stream + * pitch - new pitch value in pitch cents + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdatePitch (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch); + +/*---------------------------------------------------------------------------- + * EAS_PEState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEState (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_PEClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEClose (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEReset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEReset (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEPause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and pause rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEPause (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEResume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PERelease() + *---------------------------------------------------------------------------- + * Purpose: + * Put the PCM stream envelope into release. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERelease (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +#endif /* end _EAS_PCM_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcmdata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcmdata.c new file mode 100755 index 0000000..2d85ac2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcmdata.c @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcmdata.c + * + * Contents and purpose: + * Contains the static data for the PCM engine. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" + +/* static data allocation */ +S_PCM_STATE eas_PCMData[MAX_PCM_STREAMS]; + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcmdata.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcmdata.h new file mode 100755 index 0000000..ae18d6d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_pcmdata.h @@ -0,0 +1,157 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcmdata.h + * + * Contents and purpose: + * Data declarations for the PCM engine + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PCMDATA_H +#define _EAS_PCMDATA_H + +/* sets the maximum number of simultaneous PCM streams */ +#ifndef MAX_PCM_STREAMS +#define MAX_PCM_STREAMS 16 +#define PCM_STREAM_THRESHOLD (MAX_PCM_STREAMS - 4) +#endif + +/* coefficents for high-pass filter in ADPCM */ +#define INTEGRATOR_COEFFICIENT 100 /* coefficient for leaky integrator */ + +/* additional flags in S_PCM_STATE.flags used internal to module */ +#define PCM_FLAGS_EMPTY 0x01000000 /* unsigned format */ + +/*---------------------------------------------------------------------------- + * S_PCM_STATE + * + * Retains state information for PCM streams. + *---------------------------------------------------------------------------- +*/ +typedef struct s_decoder_state_tag +{ + EAS_I32 output; /* last output for DC offset filter */ + EAS_I32 acc; /* accumulator for DC offset filter */ + EAS_I32 step; /* current ADPCM step size */ + EAS_PCM x1; /* current generated sample */ + EAS_PCM x0; /* previous generated sample */ +} S_DECODER_STATE; + +typedef enum +{ + PCM_ENV_START = 0, + PCM_ENV_ATTACK, + PCM_ENV_DECAY, + PCM_ENV_SUSTAIN, + PCM_ENV_RELEASE, + PCM_ENV_END +} E_PCM_ENV_STATE; + +typedef struct s_pcm_state_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + EAS_FILE_HANDLE fileHandle; /* pointer to input file */ + EAS_PCM_CALLBACK pCallback; /* pointer to callback function */ + EAS_VOID_PTR cbInstData; /* instance data for callback function */ + struct s_decoder_interface_tag EAS_CONST * pDecoder; /* pointer to decoder interface */ + EAS_STATE state; /* stream state */ + EAS_I32 time; /* media time */ + EAS_I32 startPos; /* start of PCM stream */ + EAS_I32 loopLocation; /* file location where loop starts */ + EAS_I32 byteCount; /* size of file */ + EAS_U32 loopStart; /* loop start, offset in samples from startPos */ + /* NOTE: For CMF, we use this to store total sample size */ + EAS_U32 loopSamples; /* total loop length, in samples, 0 means no loop */ + /* NOTE: For CMF, non-zero means looped */ + EAS_U32 samplesInLoop; /* samples left in the loop to play back */ + EAS_I32 samplesTilLoop; /* samples left to play until top of loop */ + EAS_I32 bytesLeft; /* count of bytes left in stream */ + EAS_I32 bytesLeftLoop; /* count of bytes left in stream, value at start of loop */ + EAS_U32 phase; /* current phase for interpolator */ + EAS_U32 basefreq; /* frequency multiplier */ + EAS_U32 flags; /* stream flags */ + EAS_U32 envData; /* envelope data (and LFO data) */ + EAS_U32 envValue; /* current envelope value */ + EAS_U32 envScale; /* current envelope scale */ + EAS_U32 startOrder; /* start order index, first is 0, next is 1, etc. */ + S_DECODER_STATE decoderL; /* left (mono) ADPCM state */ + S_DECODER_STATE decoderR; /* right ADPCM state */ + S_DECODER_STATE decoderLLoop; /* left (mono) ADPCM state, value at start of loop */ + S_DECODER_STATE decoderRLoop; /* right ADPCM state, value at start of loop */ + E_PCM_ENV_STATE envState; /* current envelope state */ + EAS_I16 volume; /* volume for stream */ + EAS_I16 pitch; /* relative pitch in cents - zero is unity playback */ + EAS_I16 gainLeft; /* requested gain */ + EAS_I16 gainRight; /* requested gain */ + EAS_I16 currentGainLeft; /* current gain for anti-zipper filter */ + EAS_I16 currentGainRight; /* current gain for anti-zipper filter */ + EAS_U16 blockSize; /* block size for ADPCM decoder */ + EAS_U16 blockCount; /* block counter for ADPCM decoder */ + EAS_U16 sampleRate; /* input sample rate */ + EAS_U8 srcByte; /* source byte */ + EAS_U8 msBitCount; /* count keeps track of MS bits */ + EAS_U8 msBitMask; /* mask keeps track of MS bits */ + EAS_U8 msBitValue; /* value keeps track of MS bits */ + EAS_U8 msBitCountLoop; /* count keeps track of MS bits, value at loop start */ + EAS_U8 msBitMaskLoop; /* mask keeps track of MS bits, value at loop start */ + EAS_U8 msBitValueLoop; /* value keeps track of MS bits, value at loop start */ + EAS_BOOL8 hiNibble; /* indicates high/low nibble is next */ + EAS_BOOL8 hiNibbleLoop; /* indicates high/low nibble is next, value loop start */ + EAS_U8 rateShift; /* for playback rate greater than 1.0 */ +} S_PCM_STATE; + +/*---------------------------------------------------------------------------- + * S_DECODER_INTERFACE + * + * Generic interface for audio decoders + *---------------------------------------------------------------------------- +*/ +typedef struct s_decoder_interface_tag +{ + EAS_RESULT (* EAS_CONST pfInit)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); + EAS_RESULT (* EAS_CONST pfDecodeSample)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); + EAS_RESULT (* EAS_CONST pfLocate)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); +} S_DECODER_INTERFACE; + + +/* header chunk for SMAF ADPCM */ +#define TAG_YAMAHA_ADPCM 0x4d776100 +#define TAG_MASK 0xffffff00 +#define TAG_RIFF_FILE 0x52494646 +#define TAG_WAVE_CHUNK 0x57415645 +#define TAG_FMT_CHUNK 0x666d7420 + +/*---------------------------------------------------------------------------- + * EAS_PESeek + *---------------------------------------------------------------------------- + * Purpose: + * Locate to a particular byte in a PCM stream + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PESeek (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation); + +#endif /* _EAS_PCMDATA_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_public.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_public.c new file mode 100755 index 0000000..394a9a1 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_public.c @@ -0,0 +1,2597 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_public.c + * + * Contents and purpose: + * Contains EAS library public interface + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 842 $ + * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_synthcfg.h" +#include "eas.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" +#include "eas_data.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_midi.h" +#include "eas_mixer.h" +#include "eas_build.h" +#include "eas_vm_protos.h" +#include "eas_math.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + +#ifdef DLS_SYNTHESIZER +#include "eas_mdls.h" +#endif + +/* number of events to parse before calling EAS_HWYield function */ +#define YIELD_EVENT_COUNT 10 + +/*---------------------------------------------------------------------------- + * easLibConfig + * + * This structure is available through the EAS public interface to allow + * the user to check the configuration of the library. + *---------------------------------------------------------------------------- +*/ +static const S_EAS_LIB_CONFIG easLibConfig = +{ + LIB_VERSION, +#ifdef _CHECKED_BUILD + EAS_TRUE, +#else + EAS_FALSE, +#endif + MAX_SYNTH_VOICES, + NUM_OUTPUT_CHANNELS, + _OUTPUT_SAMPLE_RATE, + BUFFER_SIZE_IN_MONO_SAMPLES, +#ifdef _FILTER_ENABLED + EAS_TRUE, +#else + EAS_FALSE, +#endif + _BUILD_TIME_, + _BUILD_VERSION_ +}; + +/* local prototypes */ +static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, S_EAS_STREAM *pStream, EAS_U32 endTime, EAS_INT parseMode); + +/*---------------------------------------------------------------------------- + * EAS_SetStreamParameter + *---------------------------------------------------------------------------- + * Sets the specified parameter in the stream. Allows access to + * customizable settings within the individual file parsers. + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * param - enumerated parameter (see eas_parser.h) + * value - new value + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 value) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfSetData) + return (*pParserModule->pfSetData)(pEASData, pStream->handle, param, value); + return EAS_ERROR_FEATURE_NOT_AVAILABLE; +} + +/*---------------------------------------------------------------------------- + * EAS_GetStreamParameter + *---------------------------------------------------------------------------- + * Sets the specified parameter in the stream. Allows access to + * customizable settings within the individual file parsers. + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * param - enumerated parameter (see eas_parser.h) + * pValue - pointer to variable to receive current setting + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_GetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 *pValue) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfGetData) + return (*pParserModule->pfGetData)(pEASData, pStream->handle, param, pValue); + return EAS_ERROR_FEATURE_NOT_AVAILABLE; +} + +/*---------------------------------------------------------------------------- + * EAS_StreamReady() + *---------------------------------------------------------------------------- + * This routine sets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_SetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * set the parameter directly on the synth. This eliminates duplicate + * code in the parser. + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_StreamReady (S_EAS_DATA *pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfState(pEASData, pStream->handle, &state) != EAS_SUCCESS) + return EAS_FALSE; + return (state < EAS_STATE_OPEN); +} + +/*---------------------------------------------------------------------------- + * EAS_IntSetStrmParam() + *---------------------------------------------------------------------------- + * This routine sets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_SetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * set the parameter directly on the synth. This eliminates duplicate + * code in the parser. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value) +{ + S_SYNTH *pSynth; + + /* try to set the parameter using stream interface */ + if (EAS_SetStreamParameter(pEASData, pStream, param, value) == EAS_SUCCESS) + return EAS_SUCCESS; + + /* get a pointer to the synth object and set it directly */ + /*lint -e{740} we are cheating by passing a pointer through this interface */ + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + switch (param) + { + +#ifdef DLS_SYNTHESIZER + case PARSER_DATA_DLS_COLLECTION: + { + EAS_RESULT result = VMSetDLSLib(pSynth, (EAS_DLSLIB_HANDLE) value); + if (result == EAS_SUCCESS) + { + DLSAddRef((S_DLS*) value); + VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); + } + return result; + } +#endif + + case PARSER_DATA_EAS_LIBRARY: + return VMSetEASLib(pSynth, (EAS_SNDLIB_HANDLE) value); + + case PARSER_DATA_POLYPHONY: + return VMSetPolyphony(pEASData->pVoiceMgr, pSynth, value); + + case PARSER_DATA_PRIORITY: + return VMSetPriority(pEASData->pVoiceMgr, pSynth, value); + + case PARSER_DATA_TRANSPOSITION: + VMSetTranposition(pSynth, value); + break; + + case PARSER_DATA_VOLUME: + VMSetVolume(pSynth, (EAS_U16) value); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_IntGetStrmParam() + *---------------------------------------------------------------------------- + * This routine gets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_GetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * get the parameter directly on the synth. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_IntGetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 *pValue) +{ + S_SYNTH *pSynth; + + /* try to set the parameter */ + if (EAS_GetStreamParameter(pEASData, pStream, param, pValue) == EAS_SUCCESS) + return EAS_SUCCESS; + + /* get a pointer to the synth object and retrieve data directly */ + /*lint -e{740} we are cheating by passing a pointer through this interface */ + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + switch (param) + { + case PARSER_DATA_POLYPHONY: + return VMGetPolyphony(pEASData->pVoiceMgr, pSynth, pValue); + + case PARSER_DATA_PRIORITY: + return VMGetPriority(pEASData->pVoiceMgr, pSynth, pValue); + + case PARSER_DATA_TRANSPOSITION: + VMGetTranposition(pSynth, pValue); + break; + + case PARSER_DATA_NOTE_COUNT: + *pValue = VMGetNoteCount(pSynth); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_AllocateStream() + *---------------------------------------------------------------------------- + * Purpose: + * Allocates a stream handle + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_INT EAS_AllocateStream (EAS_DATA_HANDLE pEASData) +{ + EAS_INT streamNum; + + /* check for static allocation, only one stream allowed */ + if (pEASData->staticMemoryModel) + { + if (pEASData->streams[0].handle != NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Attempt to open multiple streams in static model\n"); */ } + return -1; + } + return 0; + } + + /* dynamic model */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + if (pEASData->streams[streamNum].handle == NULL) + break; + if (streamNum == MAX_NUMBER_STREAMS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Exceeded maximum number of open streams\n"); */ } + return -1; + } + return streamNum; +} + +/*---------------------------------------------------------------------------- + * EAS_InitStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize a stream + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void EAS_InitStream (S_EAS_STREAM *pStream, EAS_VOID_PTR pParserModule, EAS_VOID_PTR streamHandle) +{ + pStream->pParserModule = pParserModule; + pStream->handle = streamHandle; + pStream->time = 0; + pStream->frameLength = AUDIO_FRAME_LENGTH; + pStream->repeatCount = 0; + pStream->volume = DEFAULT_STREAM_VOLUME; +} + +/*---------------------------------------------------------------------------- + * EAS_Config() + *---------------------------------------------------------------------------- + * Purpose: + * Returns a pointer to a structure containing the configuration options + * in this library build. + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void) +{ + return &easLibConfig; +} + +/*---------------------------------------------------------------------------- + * EAS_Init() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the synthesizer library + * + * Inputs: + * ppEASData - pointer to data handle variable for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData) +{ + EAS_HW_DATA_HANDLE pHWInstData; + EAS_RESULT result; + S_EAS_DATA *pEASData; + EAS_INT module; + EAS_BOOL staticMemoryModel; + + /* get the memory model */ + staticMemoryModel = EAS_CMStaticMemoryModel(); + + /* initialize the host wrapper interface */ + *ppEASData = NULL; + if ((result = EAS_HWInit(&pHWInstData)) != EAS_SUCCESS) + return result; + + /* check Configuration Module for S_EAS_DATA allocation */ + if (staticMemoryModel) + pEASData = EAS_CMEnumData(EAS_CM_EAS_DATA); + else + pEASData = EAS_HWMalloc(pHWInstData, sizeof(S_EAS_DATA)); + if (!pEASData) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate EAS library memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* initialize some data */ + EAS_HWMemSet(pEASData, 0, sizeof(S_EAS_DATA)); + pEASData->staticMemoryModel = (EAS_BOOL8) staticMemoryModel; + pEASData->hwInstData = pHWInstData; + pEASData->renderTime = 0; + + /* set header search flag */ +#ifdef FILE_HEADER_SEARCH + pEASData->searchHeaderFlag = EAS_TRUE; +#endif + + /* initalize parameters */ + EAS_SetVolume(pEASData, NULL, DEFAULT_VOLUME); + +#ifdef _METRICS_ENABLED + /* initalize the metrics module */ + pEASData->pMetricsModule = EAS_CMEnumOptModules(EAS_MODULE_METRICS); + if (pEASData->pMetricsModule != NULL) + { + if ((result = (*pEASData->pMetricsModule->pfInit)(pEASData, &pEASData->pMetricsData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld initializing metrics module\n", result); */ } + return result; + } + } +#endif + + /* initailize the voice manager & synthesizer */ + if ((result = VMInitialize(pEASData)) != EAS_SUCCESS) + return result; + + /* initialize mix engine */ + if ((result = EAS_MixEngineInit(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld starting up mix engine\n", result); */ } + return result; + } + + /* initialize effects modules */ + for (module = 0; module < NUM_EFFECTS_MODULES; module++) + { + pEASData->effectsModules[module].effect = EAS_CMEnumFXModules(module); + if (pEASData->effectsModules[module].effect != NULL) + { + if ((result = (*pEASData->effectsModules[module].effect->pfInit)(pEASData, &pEASData->effectsModules[module].effectData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Initialization of effects module %d returned %d\n", module, result); */ } + return result; + } + } + } + + /* initialize PCM engine */ + if ((result = EAS_PEInit(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_PEInit failed with error code %ld\n", result); */ } + return result; + } + + /* return instance data pointer to host */ + *ppEASData = pEASData; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_Shutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the library. Deallocates any memory associated with the + * synthesizer (dynamic memory model only) + * + * Inputs: + * pEASData - handle to data for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData) +{ + EAS_HW_DATA_HANDLE hwInstData; + EAS_RESULT result, reportResult; + EAS_INT i; + + /* establish pointers */ + hwInstData = pEASData->hwInstData; + + /* check for NULL handle */ + if (!pEASData) + return EAS_ERROR_HANDLE_INTEGRITY; + + /* if there are streams open, close them */ + reportResult = EAS_SUCCESS; + for (i = 0; i < MAX_NUMBER_STREAMS; i++) + { + if (pEASData->streams[i].pParserModule && pEASData->streams[i].handle) + { + if ((result = (*((S_FILE_PARSER_INTERFACE*)(pEASData->streams[i].pParserModule))->pfClose)(pEASData, pEASData->streams[i].handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down parser module\n", result); */ } + reportResult = result; + } + } + } + + /* shutdown PCM engine */ + if ((result = EAS_PEShutdown(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down PCM engine\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + + /* shutdown mix engine */ + if ((result = EAS_MixEngineShutdown(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down mix engine\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + + /* shutdown effects modules */ + for (i = 0; i < NUM_EFFECTS_MODULES; i++) + { + if (pEASData->effectsModules[i].effect) + { + if ((result = (*pEASData->effectsModules[i].effect->pfShutdown)(pEASData, pEASData->effectsModules[i].effectData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Shutdown of effects module %d returned %d\n", i, result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + } + + /* shutdown the voice manager & synthesizer */ + VMShutdown(pEASData); + +#ifdef _METRICS_ENABLED + /* shutdown the metrics module */ + if (pEASData->pMetricsModule != NULL) + { + if ((result = (*pEASData->pMetricsModule->pfShutdown)(pEASData, pEASData->pMetricsData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down metrics module\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } +#endif + + /* release allocated memory */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(hwInstData, pEASData); + + /* shutdown host wrappers */ + if (hwInstData) + { + if ((result = EAS_HWShutdown(hwInstData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down host wrappers\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + + return reportResult; +} + +#ifdef JET_INTERFACE +/*---------------------------------------------------------------------------- + * EAS_OpenJETStream() + *---------------------------------------------------------------------------- + * Private interface for JET to open an SMF stream with an offset + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for SMF parser */ + *ppStream = NULL; + streamHandle = NULL; + pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(0); + if (pParserModule == NULL) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* see if SMF parser recognizes the file */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, offset)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser recognized the file, return the handle */ + if (streamHandle) + { + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_OpenFile() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_FILE_HANDLE fileHandle; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + EAS_INT moduleNum; + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for file parsers */ + pParserModule = NULL; + *ppStream = NULL; + streamHandle = NULL; + for (moduleNum = 0; ; moduleNum++) + { + pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(moduleNum); + if (pParserModule == NULL) + break; + + /* see if this parser recognizes it */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser recognized the file, return the handle */ + if (streamHandle) + { + + /* save the parser pointer and file handle */ + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + /* rewind the file for the next parser */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, 0L)) != EAS_SUCCESS) + return result; + } + + /* no parser was able to recognize the file, close it and return an error */ + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * EAS_MMAPIToneControl() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a ToneControl file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_FILE_HANDLE fileHandle; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + + /* check if the tone control parser is available */ + *ppStream = NULL; + streamHandle = NULL; + pParserModule = EAS_CMEnumOptModules(EAS_MODULE_MMAPI_TONE_CONTROL); + if (pParserModule == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_MMAPIToneControl: ToneControl parser not available\n"); */ } + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + } + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* see if ToneControl parser recognizes it */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser accepted the file, return the handle */ + if (streamHandle) + { + + /* save the parser pointer and file handle */ + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + /* parser did not recognize the file, close it and return an error */ + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} + +/*---------------------------------------------------------------------------- + * EAS_GetWaveFmtChunk + *---------------------------------------------------------------------------- + * Helper function to retrieve WAVE file fmt chunk for MMAPI + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * pFmtChunk - pointer to variable to receive current setting + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_VOID_PTR *ppFmtChunk) +{ + EAS_RESULT result; + EAS_I32 value; + + if ((result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FORMAT, &value)) != EAS_SUCCESS) + return result; + *ppFmtChunk = (EAS_VOID_PTR) value; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_GetFileType + *---------------------------------------------------------------------------- + * Returns the file type (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * pFileType - pointer to variable to receive file type + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetFileType (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 *pFileType) +{ + if (!EAS_StreamReady (pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FILE_TYPE, pFileType); +} + +/*---------------------------------------------------------------------------- + * EAS_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the synthesizer to play the file or stream. Parses the first + * frame of data from the file and arms the synthesizer. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + /* prepare the stream */ + if (state == EAS_STATE_OPEN) + { + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + result = (*pParserModule->pfPrepare)(pEASData, pStream->handle); + + /* set volume */ + if (result == EAS_SUCCESS) + result = EAS_SetVolume(pEASData, pStream, pStream->volume); + } + else + result = EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_Render() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the Midi data and render PCM audio data. + * + * Inputs: + * pEASData - buffer for internal EAS data + * pOut - output buffer pointer + * nNumRequested - requested num samples to generate + * pnNumGenerated - actual number of samples generated + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_I32 voicesRendered; + EAS_STATE parserState; + EAS_INT streamNum; + + /* assume no samples generated and reset workload */ + *pNumGenerated = 0; + VMInitWorkload(pEASData->pVoiceMgr); + + /* no support for other buffer sizes yet */ + if (numRequested != BUFFER_SIZE_IN_MONO_SAMPLES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "This library supports only %ld samples in buffer, host requested %ld samples\n", + (EAS_I32) BUFFER_SIZE_IN_MONO_SAMPLES, numRequested); */ } + return EAS_BUFFER_SIZE_MISMATCH; + } + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); +#endif + + /* prep the frame buffer, do mix engine prep only if TRUE */ +#ifdef _SPLIT_ARCHITECTURE + if (VMStartFrame(pEASData)) + EAS_MixEnginePrep(pEASData, numRequested); +#else + /* prep the mix engine */ + EAS_MixEnginePrep(pEASData, numRequested); +#endif + + /* save the output buffer pointer */ + pEASData->pOutputAudioBuffer = pOut; + + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); +#endif + + /* if we haven't finished parsing from last time, do it now */ + /* need to parse another frame of events before we render again */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + { + /* clear the locate flag */ + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_LOCATE; + + if (pEASData->streams[streamNum].pParserModule) + { + + /* establish pointer to parser module */ + pParserModule = pEASData->streams[streamNum].pParserModule; + + /* handle pause */ + if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PAUSE) + { + if (pParserModule->pfPause) + result = pParserModule->pfPause(pEASData, pEASData->streams[streamNum].handle); + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PAUSE; + } + + /* get current state */ + if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) + return result; + + /* handle resume */ + if (parserState == EAS_STATE_PAUSED) + { + if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_RESUME) + { + if (pParserModule->pfResume) + result = pParserModule->pfResume(pEASData, pEASData->streams[streamNum].handle); + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_RESUME; + } + } + + /* if necessary, parse stream */ + if ((pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PARSED) == 0) + if ((result = EAS_ParseEvents(pEASData, &pEASData->streams[streamNum], pEASData->streams[streamNum].time + pEASData->streams[streamNum].frameLength, eParserModePlay)) != EAS_SUCCESS) + return result; + + /* check for an early abort */ + if ((pEASData->streams[streamNum].streamFlags) == 0) + { + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); +#endif + + return EAS_SUCCESS; + } + + /* check for repeat */ + if (pEASData->streams[streamNum].repeatCount) + { + + /* check for stopped state */ + if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) + return result; + if (parserState == EAS_STATE_STOPPED) + { + + /* decrement repeat count, unless it is negative */ + if (pEASData->streams[streamNum].repeatCount > 0) + pEASData->streams[streamNum].repeatCount--; + + /* reset the parser */ + if ((result = (*pParserModule->pfReset)(pEASData, pEASData->streams[streamNum].handle)) != EAS_SUCCESS) + return result; + pEASData->streams[streamNum].time = 0; + } + } + } + } + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); +#endif + +#ifdef _METRICS_ENABLED + /* start the render timer */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); +#endif + + /* render audio */ + if ((result = VMRender(pEASData->pVoiceMgr, BUFFER_SIZE_IN_MONO_SAMPLES, pEASData->pMixBuffer, &voicesRendered)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "pfRender function returned error %ld\n", result); */ } + return result; + } + +#ifdef _METRICS_ENABLED + /* stop the render timer */ + if (pEASData->pMetricsData) { + (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_FRAME_COUNT, 1); + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); + (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_TOTAL_VOICE_COUNT, (EAS_U32) voicesRendered); + (void)(*pEASData->pMetricsModule->pfRecordMaxValue)(pEASData->pMetricsData, EAS_PM_MAX_VOICES, (EAS_U32) voicesRendered); + } +#endif + + //2 Do we really need frameParsed? + /* need to parse another frame of events before we render again */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + if (pEASData->streams[streamNum].pParserModule != NULL) + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PARSED; + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); +#endif + + /* render PCM audio */ + if ((result = EAS_PERender(pEASData, numRequested)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_PERender returned error %ld\n", result); */ } + return result; + } + +#ifdef _METRICS_ENABLED + /* stop the stream timer */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); +#endif + +#ifdef _METRICS_ENABLED + /* start the post timer */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); +#endif + + /* for split architecture, send DSP vectors. Do post only if return is TRUE */ +#ifdef _SPLIT_ARCHITECTURE + if (VMEndFrame(pEASData)) + { + /* now do post-processing */ + EAS_MixEnginePost(pEASData, numRequested); + *pNumGenerated = numRequested; + } +#else + /* now do post-processing */ + EAS_MixEnginePost(pEASData, numRequested); + *pNumGenerated = numRequested; +#endif + +#ifdef _METRICS_ENABLED + /* stop the post timer */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); +#endif + + /* advance render time */ + pEASData->renderTime += AUDIO_FRAME_LENGTH; + +#if 0 + /* dump workload for debug */ + if (pEASData->pVoiceMgr->workload) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Workload = %d\n", pEASData->pVoiceMgr->workload); */ } +#endif + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + { + PERF_TIMER temp; + temp = (*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); + + /* if max render time, record the number of voices and time */ + if ((*pEASData->pMetricsModule->pfRecordMaxValue) + (pEASData->pMetricsData, EAS_PM_MAX_CYCLES, (EAS_U32) temp)) + { + (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_VOICES, (EAS_U32) voicesRendered); + (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_TIME, (EAS_I32) (pEASData->renderTime >> 8)); + } + } +#endif + +#ifdef JET_INTERFACE + /* let JET to do its thing */ + if (pEASData->jetHandle != NULL) + { + result = JET_Process(pEASData); + if (result != EAS_SUCCESS) + return result; + } +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Set the selected stream to repeat. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * repeatCount - repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 repeatCount) +{ + pStream->repeatCount = repeatCount; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the current repeat count for the selected stream. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * pRrepeatCount - pointer to variable to hold repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pRepeatCount) +{ + *pRepeatCount = pStream->repeatCount; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPlaybackRate() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the playback rate. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U32 rate) +{ + + /* check range */ + if ((rate < (1 << 27)) || (rate > (1 << 29))) + return EAS_ERROR_INVALID_PARAMETER; + + /* calculate new frame length + * + * NOTE: The maximum frame length we can accomodate based on a + * maximum rate of 2.0 (2^28) is 2047 (2^13-1). To accomodate a + * longer frame length or a higher maximum rate, the fixed point + * divide below will need to be adjusted + */ + pStream->frameLength = (AUDIO_FRAME_LENGTH * (rate >> 8)) >> 20; + + /* notify stream of new playback rate */ + EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_PLAYBACK_RATE, (EAS_I32) rate); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetTransposition) + *---------------------------------------------------------------------------- + * Purpose: + * Sets the key tranposition for the synthesizer. Transposes all + * melodic instruments by the specified amount. Range is limited + * to +/-12 semitones. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * transposition - +/-12 semitones + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 transposition) +{ + + /* check range */ + if ((transposition < -12) || (transposition > 12)) + return EAS_ERROR_INVALID_PARAMETER; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_TRANSPOSITION, transposition); +} + +/*---------------------------------------------------------------------------- + * EAS_ParseEvents() + *---------------------------------------------------------------------------- + * Purpose: + * Parse events in the current streams until the desired time is reached. + * + * Inputs: + * pEASData - buffer for internal EAS data + * endTime - stop parsing if this time is reached + * parseMode - play, locate, or metadata + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_U32 endTime, EAS_INT parseMode) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_I32 parserState; + EAS_BOOL done; + EAS_INT yieldCount = YIELD_EVENT_COUNT; + EAS_U32 time = 0; + + /* does this parser have a time function? */ + pParserModule = pStream->pParserModule; + if (pParserModule->pfTime == NULL) + { + /* check state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) + return result; + /* if play state, advance time */ + if ((parserState >= EAS_STATE_READY) && (parserState <= EAS_STATE_PAUSING)) + pStream->time += pStream->frameLength; + done = EAS_TRUE; + } + + /* assume we're not done, in case we abort out */ + else + { + pStream->streamFlags &= ~STREAM_FLAGS_PARSED; + done = EAS_FALSE; + } + + while (!done) + { + + /* check for stopped state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) + return result; + if (parserState > EAS_STATE_PLAY) + { + /* save current time if we're not in play mode */ + if (parseMode != eParserModePlay) + pStream->time = time << 8; + done = EAS_TRUE; + break; + } + + /* get the next event time */ + if (pParserModule->pfTime) + { + if ((result = (*pParserModule->pfTime)(pEASData, pStream->handle, &time)) != EAS_SUCCESS) + return result; + + /* if next event is within this frame, parse it */ + if (time < (endTime >> 8)) + { + + /* parse the next event */ + if (pParserModule->pfEvent) + if ((result = (*pParserModule->pfEvent)(pEASData, pStream->handle, parseMode)) != EAS_SUCCESS) + return result; + } + + /* no more events in this frame, advance time */ + else + { + pStream->time = endTime; + done = EAS_TRUE; + } + } + + /* check for max workload exceeded */ + if (VMCheckWorkload(pEASData->pVoiceMgr)) + { + /* stop even though we may not have parsed + * all the events in this frame. The parser will try to + * catch up on the next frame. + */ + break; + } + + /* give host a chance for an early abort */ + if (--yieldCount == 0) + { + if (EAS_HWYield(pEASData->hwInstData)) + break; + yieldCount = YIELD_EVENT_COUNT; + } + } + + /* if no early abort, parsing is complete for this frame */ + if (done) + pStream->streamFlags |= STREAM_FLAGS_PARSED; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_ParseMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * playLength - pointer to variable to store the play length (in msecs) + * + * Outputs: + * + * + * Side Effects: + * - resets the parser to the start of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *playLength) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_STATE state; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check parser state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) + return result; + if (state >= EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* if parser has metadata function, use that */ + if (pParserModule->pfGetMetaData != NULL) + return pParserModule->pfGetMetaData(pEASData, pStream->handle, playLength); + + /* reset the parser to the beginning */ + if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) + return result; + + /* parse the file to end */ + pStream->time = 0; + VMInitWorkload(pEASData->pVoiceMgr); + if ((result = EAS_ParseEvents(pEASData, pStream, 0x7fffffff, eParserModeMetaData)) != EAS_SUCCESS) + return result; + + /* get the parser time */ + if ((result = EAS_GetLocation(pEASData, pStream, playLength)) != EAS_SUCCESS) + return result; + + /* reset the parser to the beginning */ + pStream->time = 0; + return (*pParserModule->pfReset)(pEASData, pStream->handle); +} + +/*---------------------------------------------------------------------------- + * EAS_RegisterMetaDataCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers a metadata callback function for parsed metadata. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * cbFunc - pointer to host callback function + * metaDataBuffer - pointer to metadata buffer + * metaDataBufSize - maximum size of the metadata buffer + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( + EAS_DATA_HANDLE pEASData, + EAS_HANDLE pStream, + EAS_METADATA_CBFUNC cbFunc, + char *metaDataBuffer, + EAS_I32 metaDataBufSize, + EAS_VOID_PTR pUserData) +{ + S_METADATA_CB metadata; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* register callback function */ + metadata.callback = cbFunc; + metadata.buffer = metaDataBuffer; + metadata.bufferSize = metaDataBufSize; + metadata.pUserData = pUserData; + return EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_METADATA_CB, (EAS_I32) &metadata); +} + +/*---------------------------------------------------------------------------- + * EAS_GetNoteCount () + *---------------------------------------------------------------------------- + * Returns the total number of notes played in this stream + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_NOTE_COUNT, pNoteCount); +} + +/*---------------------------------------------------------------------------- + * EAS_CloseFile() + *---------------------------------------------------------------------------- + * Purpose: + * Closes an audio file or stream. Playback should have either paused or + * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + + /* call the close function */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + result = (*pParserModule->pfClose)(pEASData, pStream->handle); + + /* clear the handle and parser interface pointer */ + pStream->handle = NULL; + pStream->pParserModule = NULL; + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_OpenMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to variable to hold file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *ppStream, EAS_HANDLE streamHandle) +{ + EAS_RESULT result; + S_INTERACTIVE_MIDI *pMIDIStream; + EAS_INT streamNum; + + /* initialize some pointers */ + *ppStream = NULL; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for S_EAS_DATA allocation */ + if (pEASData->staticMemoryModel) + pMIDIStream = EAS_CMEnumData(EAS_CM_MIDI_STREAM_DATA); + else + pMIDIStream = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_INTERACTIVE_MIDI)); + + /* allocate dynamic memory */ + if (!pMIDIStream) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate MIDI stream data\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* zero the memory to insure complete initialization */ + EAS_HWMemSet(pMIDIStream, 0, sizeof(S_INTERACTIVE_MIDI)); + EAS_InitStream(&pEASData->streams[streamNum], NULL, pMIDIStream); + + /* instantiate a new synthesizer */ + if (streamHandle == NULL) + { + result = VMInitMIDI(pEASData, &pMIDIStream->pSynth); + } + + /* use an existing synthesizer */ + else + { + EAS_I32 value; + result = EAS_GetStreamParameter(pEASData, streamHandle, PARSER_DATA_SYNTH_HANDLE, &value); + pMIDIStream->pSynth = (S_SYNTH*) value; + VMIncRefCount(pMIDIStream->pSynth); + } + if (result != EAS_SUCCESS) + { + EAS_CloseMIDIStream(pEASData, &pEASData->streams[streamNum]); + return result; + } + + /* initialize the MIDI stream data */ + EAS_InitMIDIStream(&pMIDIStream->stream); + + *ppStream = (EAS_HANDLE) &pEASData->streams[streamNum]; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_WriteMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Send data to the MIDI stream device + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - stream handle + * pBuffer - pointer to buffer + * count - number of bytes to write + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 *pBuffer, EAS_I32 count) +{ + S_INTERACTIVE_MIDI *pMIDIStream; + EAS_RESULT result; + + pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; + + /* send the entire buffer */ + while (count--) + { + if ((result = EAS_ParseMIDIStream(pEASData, pMIDIStream->pSynth, &pMIDIStream->stream, *pBuffer++, eParserModePlay)) != EAS_SUCCESS) + return result; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_CloseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Closes a raw MIDI stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_INTERACTIVE_MIDI *pMIDIStream; + + pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; + + /* close synth */ + if (pMIDIStream->pSynth != NULL) + { + VMMIDIShutdown(pEASData, pMIDIStream->pSynth); + pMIDIStream->pSynth = NULL; + } + + /* release allocated memory */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(((S_EAS_DATA*) pEASData)->hwInstData, pMIDIStream); + + pStream->handle = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the state of an audio file or stream. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_STATE *pState) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + + /* call the parser to return state */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, pState)) != EAS_SUCCESS) + return result; + + /* if repeat count is set for this parser, mask the stopped state from the application */ + if (pStream->repeatCount && (*pState == EAS_STATE_STOPPED)) + *pState = EAS_STATE_PLAY; + + /* if we're not ready or playing, we don't need to hide state from host */ + if (*pState > EAS_STATE_PLAY) + return EAS_SUCCESS; + + /* if stream is about to be paused, report it as paused */ + if (pStream->streamFlags & STREAM_FLAGS_PAUSE) + { + if (pStream->streamFlags & STREAM_FLAGS_LOCATE) + *pState = EAS_STATE_PAUSED; + else + *pState = EAS_STATE_PAUSING; + } + + /* if stream is about to resume, report it as playing */ + if (pStream->streamFlags & STREAM_FLAGS_RESUME) + *pState = EAS_STATE_PLAY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the stream. A value of 0 allows the stream + * to use all voices (set by EAS_SetSynthPolyphony). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 polyphonyCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, polyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_GetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPolyphonyCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, pPolyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_SetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the synth . Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount) +{ + return VMSetSynthPolyphony(pEASData->pVoiceMgr, synthNum, polyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_GetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the synth + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount) +{ + return VMGetSynthPolyphony(pEASData->pVoiceMgr, synthNum, pPolyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_SetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the priority of the stream. Determines which stream's voices + * are stolen when there are insufficient voices for all notes. + * Value must be in the range of 1-15, lower values are higher + * priority. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 priority) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, priority); +} + +/*---------------------------------------------------------------------------- + * EAS_GetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current priority setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPriority - pointer to variable to receive priority + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPriority) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, pPriority); +} + +/*---------------------------------------------------------------------------- + * EAS_SetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master gain for the mix engine in 1dB increments + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master gain (100 is max) + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 volume) +{ + EAS_I16 gain; + + /* check range */ + if ((volume < 0) || (volume > EAS_MAX_VOLUME)) + return EAS_ERROR_PARAMETER_RANGE; + + /* stream volume */ + if (pStream != NULL) + { + EAS_I32 gainOffset; + EAS_RESULT result; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* get gain offset */ + pStream->volume = (EAS_U8) volume; + result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_GAIN_OFFSET, &gainOffset); + if (result == EAS_SUCCESS) + volume += gainOffset; + + /* set stream volume */ + gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM); + + /* convert to linear scalar */ + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_VOLUME, gain); + } + + /* master volume */ + pEASData->masterVolume = (EAS_U8) volume; +#if (NUM_OUTPUT_CHANNELS == 1) + /* leave 3dB headroom for mono output */ + volume -= 3; +#endif + + gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM); + pEASData->masterGain = gain; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the master volume for the synthesizer. The default volume setting is + * 50. The volume range is 0 to 100; + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + if (pStream == NULL) + return pEASData->masterVolume; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return pStream->volume; +} + +/*---------------------------------------------------------------------------- + * EAS_SetMaxLoad() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the maximum workload the parsers will do in a single call to + * EAS_Render. The units are currently arbitrary, but should correlate + * well to the actual CPU cycles consumed. The primary effect is to + * reduce the occasional peaks in CPU cycles consumed when parsing + * dense parts of a MIDI score. + * + * Inputs: + * pEASData - handle to data for this instance + * maxLoad - the desired maximum workload + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad) +{ + VMSetWorkload(pEASData->pVoiceMgr, maxLoad); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetMaxPCMStreams() + *---------------------------------------------------------------------------- + * Sets the maximum number of PCM streams allowed in parsers that + * use PCM streaming. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * maxNumStreams - maximum number of PCM streams + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_MAX_PCM_STREAMS, maxNumStreams); +} + +/*---------------------------------------------------------------------------- + * EAS_Locate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate into the file associated with the handle. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file handle + * milliseconds - playback offset from start of file in milliseconds + * + * Outputs: + * + * + * Side Effects: + * the actual offset will be quantized to the closest update period, typically + * a resolution of 5.9ms. Notes that are started prior to this time will not + * sound. Any notes currently playing will be shut off. + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 milliseconds, EAS_BOOL offset) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_U32 requestedTime; + EAS_STATE state; + + /* get pointer to parser function table */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) + return result; + if (state >= EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* handle offset and limit to start of file */ + /*lint -e{704} use shift for performance*/ + if (offset) + milliseconds += (EAS_I32) pStream->time >> 8; + if (milliseconds < 0) + milliseconds = 0; + + /* check to see if the request is different from the current time */ + requestedTime = (EAS_U32) milliseconds; + if (requestedTime == (pStream->time >> 8)) + return EAS_SUCCESS; + + /* set the locate flag */ + pStream->streamFlags |= STREAM_FLAGS_LOCATE; + + /* use the parser locate function, if available */ + if (pParserModule->pfLocate != NULL) + { + EAS_BOOL parserLocate = EAS_FALSE; + result = pParserModule->pfLocate(pEASData, pStream->handle, (EAS_I32) requestedTime, &parserLocate); + if (!parserLocate) + { + if (result == EAS_SUCCESS) + pStream->time = requestedTime << 8; + return result; + } + } + + /* if we were paused and not going to resume, set pause request flag */ + if (((state == EAS_STATE_PAUSING) || (state == EAS_STATE_PAUSED)) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) + pStream->streamFlags |= STREAM_FLAGS_PAUSE; + + /* reset the synth and parser */ + if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) + return result; + pStream->time = 0; + + /* locating forward, clear parsed flag and parse data until we get to the requested location */ + if ((result = EAS_ParseEvents(pEASData, pStream, requestedTime << 8, eParserModeLocate)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetLocation() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file handle + * + * Outputs: + * The offset in milliseconds from the start of the current sequence, quantized + * to the nearest update period. Actual resolution is typically 5.9 ms. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pTime) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + *pTime = pStream->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetRenderTime() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * Gets the render time clock in msecs. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime) +{ + *pTime = pEASData->renderTime >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the playback of the data associated with this handle. The audio + * is gracefully ramped down to prevent clicks and pops. It may take several + * buffers of audio before the audio is muted. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + if ((state != EAS_STATE_PLAY) && (state != EAS_STATE_READY) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* make sure parser implements pause */ + if (pParserModule->pfPause == NULL) + result = EAS_ERROR_NOT_IMPLEMENTED; + + /* clear resume flag */ + pStream->streamFlags &= ~STREAM_FLAGS_RESUME; + + /* set pause flag */ + pStream->streamFlags |= STREAM_FLAGS_PAUSE; + +#if 0 + /* pause the stream */ + if (pParserModule->pfPause) + result = pParserModule->pfPause(pEASData, pStream->handle); + else + result = EAS_ERROR_NOT_IMPLEMENTED; +#endif + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resumes the playback of the data associated with this handle. The audio + * is gracefully ramped up to prevent clicks and pops. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + if ((state != EAS_STATE_PAUSED) && (state != EAS_STATE_PAUSING) && ((pStream->streamFlags & STREAM_FLAGS_PAUSE) == 0)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* make sure parser implements this function */ + if (pParserModule->pfResume == NULL) + result = EAS_ERROR_NOT_IMPLEMENTED; + + /* clear pause flag */ + pStream->streamFlags &= ~STREAM_FLAGS_PAUSE; + + /* set resume flag */ + pStream->streamFlags |= STREAM_FLAGS_RESUME; + +#if 0 + /* resume the stream */ + if (pParserModule->pfResume) + result = pParserModule->pfResume(pEASData, pStream->handle); + else + result = EAS_ERROR_NOT_IMPLEMENTED; +#endif + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_GetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * pValue - pointer to variable to receive parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue) +{ + + if (module >= NUM_EFFECTS_MODULES) + return EAS_ERROR_INVALID_MODULE; + + if (pEASData->effectsModules[module].effectData == NULL) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->effectsModules[module].effect->pFGetParam) + (pEASData->effectsModules[module].effectData, param, pValue); +} + +/*---------------------------------------------------------------------------- + * EAS_SetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * value - new parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value) +{ + + if (module >= NUM_EFFECTS_MODULES) + return EAS_ERROR_INVALID_MODULE; + + if (pEASData->effectsModules[module].effectData == NULL) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->effectsModules[module].effect->pFSetParam) + (pEASData->effectsModules[module].effectData, param, value); +} + +#ifdef _METRICS_ENABLED +/*---------------------------------------------------------------------------- + * EAS_MetricsReport() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the metrics interface. + * + * Inputs: + * p - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData) +{ + if (!pEASData->pMetricsModule) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->pMetricsModule->pfReport)(pEASData->pMetricsData); +} + +/*---------------------------------------------------------------------------- + * EAS_MetricsReset() + *---------------------------------------------------------------------------- + * Purpose: + * Resets the metrics. + * + * Inputs: + * p - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData) +{ + + if (!pEASData->pMetricsModule) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->pMetricsModule->pfReset)(pEASData->pMetricsData); +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetSoundLibrary() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_SNDLIB_HANDLE pSndLib) +{ + if (pStream) + { + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_EAS_LIBRARY, (EAS_I32) pSndLib); + } + + return VMSetGlobalEASLib(pEASData->pVoiceMgr, pSndLib); +} + +/*---------------------------------------------------------------------------- + * EAS_SetHeaderSearchFlag() + *---------------------------------------------------------------------------- + * By default, when EAS_OpenFile is called, the parsers check the + * first few bytes of the file looking for a specific header. Some + * mobile devices may add a header to the start of a file, which + * will prevent the parser from recognizing the file. If the + * searchFlag is set to EAS_TRUE, the parser will search the entire + * file looking for the header. This may enable EAS to recognize + * some files that it would ordinarily reject. The negative is that + * it make take slightly longer to process the EAS_OpenFile request. + * + * Inputs: + * pEASData - instance data handle + * searchFlag - search flag (EAS_TRUE or EAS_FALSE) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag) +{ + pEASData->searchHeaderFlag = (EAS_BOOL8) searchFlag; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPlayMode() + *---------------------------------------------------------------------------- + * Some file formats support special play modes, such as iMode partial + * play mode. This call can be used to change the play mode. The + * default play mode (usually straight playback) is always zero. + * + * Inputs: + * pEASData - instance data handle + * handle - file or stream handle + * playMode - play mode (see file parser for specifics) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode) +{ + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PLAY_MODE, playMode); +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * EAS_LoadDLSCollection() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_FILE_LOCATOR locator) +{ + EAS_FILE_HANDLE fileHandle; + EAS_RESULT result; + EAS_DLSLIB_HANDLE pDLS; + + if (pStream != NULL) + { + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + } + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* parse the file */ + result = DLSParser(pEASData->hwInstData, fileHandle, 0, &pDLS); + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + + if (result == EAS_SUCCESS) + { + + /* if a stream pStream is specified, point it to the DLS collection */ + if (pStream) + result = EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_DLS_COLLECTION, (EAS_I32) pDLS); + + /* global DLS load */ + else + result = VMSetGlobalDLSLib(pEASData, pDLS); + } + + return result; +} +#endif + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers callback functions for audio events. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * cbProgChgFunc - pointer to host callback function for program change + * cbEventFunc - pointer to host callback functio for note events + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, + EAS_HANDLE pStream, + EAS_VOID_PTR pInstData, + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, + EAS_EXT_EVENT_FUNC cbEventFunc) +{ + S_SYNTH *pSynth; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + VMRegExtAudioCallback(pSynth, pInstData, cbProgChgFunc, cbEventFunc); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetMIDIControllers() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of MIDI controllers on the requested channel. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * pControl - pointer to structure to receive data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) +{ + S_SYNTH *pSynth; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + VMGetMIDIControllers(pSynth, channel, pControl); + return EAS_SUCCESS; +} +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * EAS_SetFrameBuffer() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the frame buffer pointer passed to the IPC communications functions + * + * Inputs: + * pEASData - instance data handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer) +{ + if (pEASData->pVoiceMgr) + pEASData->pVoiceMgr->pFrameBuffer = pFrameBuffer; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_SearchFile + *---------------------------------------------------------------------------- + * Search file for specific sequence starting at current file + * position. Returns offset to start of sequence. + * + * Inputs: + * pEASData - pointer to EAS persistent data object + * fileHandle - file handle + * searchString - pointer to search sequence + * len - length of search sequence + * pOffset - pointer to variable to store offset to sequence + * + * Returns EAS_EOF if end-of-file is reached + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SearchFile (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset) +{ + EAS_RESULT result; + EAS_INT index; + EAS_U8 c; + + *pOffset = -1; + index = 0; + for (;;) + { + result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &c); + if (result != EAS_SUCCESS) + return result; + if (c == searchString[index]) + { + index++; + if (index == 4) + { + result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, pOffset); + if (result != EAS_SUCCESS) + return result; + *pOffset -= len; + break; + } + } + else + index = 0; + } + return EAS_SUCCESS; +} + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverb.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverb.c new file mode 100755 index 0000000..cd5befe --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverb.c @@ -0,0 +1,1154 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverb.c + * + * Contents and purpose: + * Contains the implementation of the Reverb effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 510 $ + * $Date: 2006-12-19 01:47:33 -0800 (Tue, 19 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +/*------------------------------------ + * includes + *------------------------------------ +*/ + +#include "eas_data.h" +#include "eas_effects.h" +#include "eas_math.h" +#include "eas_reverbdata.h" +#include "eas_reverb.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" + +/* prototypes for effects interface */ +static EAS_RESULT ReverbInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); +static void ReverbProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); +static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + +/* common effects interface for configuration module */ +const S_EFFECTS_INTERFACE EAS_Reverb = +{ + ReverbInit, + ReverbProcess, + ReverbShutdown, + ReverbGetParam, + ReverbSetParam +}; + + + +/*---------------------------------------------------------------------------- + * InitializeReverb() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbInit(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) +{ + EAS_I32 i; + EAS_U16 nOffset; + EAS_INT temp; + + S_REVERB_OBJECT *pReverbData; + S_REVERB_PRESET *pPreset; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pReverbData = EAS_CMEnumFXData(EAS_MODULE_REVERB); + + /* allocate dynamic memory */ + else + pReverbData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_REVERB_OBJECT)); + + if (pReverbData == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Reverb memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* clear the structure */ + EAS_HWMemSet(pReverbData, 0, sizeof(S_REVERB_OBJECT)); + + ReverbReadInPresets(pReverbData); + + pReverbData->m_nMinSamplesToAdd = REVERB_UPDATE_PERIOD_IN_SAMPLES; + + pReverbData->m_nRevOutFbkR = 0; + pReverbData->m_nRevOutFbkL = 0; + + pReverbData->m_sAp0.m_zApIn = AP0_IN; + pReverbData->m_sAp0.m_zApOut = AP0_IN + DEFAULT_AP0_LENGTH; + pReverbData->m_sAp0.m_nApGain = DEFAULT_AP0_GAIN; + + pReverbData->m_zD0In = DELAY0_IN; + + pReverbData->m_sAp1.m_zApIn = AP1_IN; + pReverbData->m_sAp1.m_zApOut = AP1_IN + DEFAULT_AP1_LENGTH; + pReverbData->m_sAp1.m_nApGain = DEFAULT_AP1_GAIN; + + pReverbData->m_zD1In = DELAY1_IN; + + pReverbData->m_zLpf0 = 0; + pReverbData->m_zLpf1 = 0; + pReverbData->m_nLpfFwd = 8837; + pReverbData->m_nLpfFbk = 6494; + + pReverbData->m_nSin = 0; + pReverbData->m_nCos = 0; + pReverbData->m_nSinIncrement = 0; + pReverbData->m_nCosIncrement = 0; + + // set xfade parameters + pReverbData->m_nXfadeInterval = (EAS_U16)REVERB_XFADE_PERIOD_IN_SAMPLES; + pReverbData->m_nXfadeCounter = pReverbData->m_nXfadeInterval + 1; // force update on first iteration + pReverbData->m_nPhase = -32768; + pReverbData->m_nPhaseIncrement = REVERB_XFADE_PHASE_INCREMENT; + + pReverbData->m_nNoise = (EAS_I16)0xABCD; + + pReverbData->m_nMaxExcursion = 0x007F; + + // set delay tap lengths + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD1Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD0Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD0Self = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD1Self = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + // for debugging purposes, allow noise generator + pReverbData->m_bUseNoise = EAS_FALSE; + + // for debugging purposes, allow bypass + pReverbData->m_bBypass = EAS_TRUE; //EAS_FALSE; + + pReverbData->m_nNextRoom = 1; + + pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom + 1; // force update on first iteration + + pReverbData->m_nWet = REVERB_DEFAULT_WET; + + pReverbData->m_nDry = REVERB_DEFAULT_DRY; + + // set base index into circular buffer + pReverbData->m_nBaseIndex = 0; + + // set the early reflections, L + pReverbData->m_sEarlyL.m_nLpfFbk = 4915; + pReverbData->m_sEarlyL.m_nLpfFwd = 27852; + pReverbData->m_sEarlyL.m_zLpf = 0; + + for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) + { + pReverbData->m_sEarlyL.m_nGain[i] = 0; + pReverbData->m_sEarlyL.m_zDelay[i] = 0; + } + + // set the early reflections, R + pReverbData->m_sEarlyR.m_nLpfFbk = 4915; + pReverbData->m_sEarlyR.m_nLpfFwd = 27852; + pReverbData->m_sEarlyR.m_zLpf = 0; + + for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) + { + pReverbData->m_sEarlyR.m_nGain[i] = 0; + pReverbData->m_sEarlyR.m_zDelay[i] = 0; + } + + // clear the reverb delay line + for (i=0; i < REVERB_BUFFER_SIZE_IN_SAMPLES; i++) + { + pReverbData->m_nDelayLine[i] = 0; + } + + //////////////////////////////// + ///code from the EAS DEMO Reverb + //now copy from the new preset into the reverb + pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; + + pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; + pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; + + pReverbData->m_nEarly = pPreset->m_nEarly; + pReverbData->m_nWet = pPreset->m_nWet; + pReverbData->m_nDry = pPreset->m_nDry; + + pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_nXfadeInterval = (EAS_U16) temp; + //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval; + + pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); + //gsReverbObject.m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; + + pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); + //gsReverbObject.m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + ///code from the EAS DEMO Reverb + //////////////////////////////// + + *pInstData = pReverbData; + + return EAS_SUCCESS; + +} /* end InitializeReverb */ + + + +/*---------------------------------------------------------------------------- + * ReverbProcess() + *---------------------------------------------------------------------------- + * Purpose: + * Reverberate the requested number of samples (block based processing) + * + * Inputs: + * pInputBuffer - src buffer + * pOutputBuffer - dst buffer + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +static void ReverbProcess(EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) +{ + S_REVERB_OBJECT *pReverbData; + + pReverbData = (S_REVERB_OBJECT*) pInstData; + + //if bypassed or the preset forces the signal to be completely dry + if (pReverbData->m_bBypass || + (pReverbData->m_nWet == 0 && pReverbData->m_nDry == 32767)) + { + if (pSrc != pDst) + EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); + return; + } + + if (pReverbData->m_nNextRoom != pReverbData->m_nCurrentRoom) + { + ReverbUpdateRoom(pReverbData); + } + + ReverbUpdateXfade(pReverbData, numSamples); + + Reverb(pReverbData, numSamples, pDst, pSrc); + + /* check if update counter needs to be reset */ + if (pReverbData->m_nUpdateCounter >= REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES) + { + /* update interval has elapsed, so reset counter */ + pReverbData->m_nUpdateCounter = 0; + } /* end if m_nUpdateCounter >= update interval */ + + /* increment update counter */ + pReverbData->m_nUpdateCounter += (EAS_I16)numSamples; + +} /* end ComputeReverb */ + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd) +{ + EAS_U16 nOffset; + EAS_I16 tempCos; + EAS_I16 tempSin; + + if (pReverbData->m_nXfadeCounter >= pReverbData->m_nXfadeInterval) + { + /* update interval has elapsed, so reset counter */ + pReverbData->m_nXfadeCounter = 0; + + // Pin the sin,cos values to min / max values to ensure that the + // modulated taps' coefs are zero (thus no clicks) + if (pReverbData->m_nPhaseIncrement > 0) + { + // if phase increment > 0, then sin -> 1, cos -> 0 + pReverbData->m_nSin = 32767; + pReverbData->m_nCos = 0; + + // reset the phase to match the sin, cos values + pReverbData->m_nPhase = 32767; + + // modulate the cross taps because their tap coefs are zero + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD1Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD0Cross = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + } + else + { + // if phase increment < 0, then sin -> 0, cos -> 1 + pReverbData->m_nSin = 0; + pReverbData->m_nCos = 32767; + + // reset the phase to match the sin, cos values + pReverbData->m_nPhase = -32768; + + // modulate the self taps because their tap coefs are zero + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD0Self = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD1Self = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + } // end if-else (pReverbData->m_nPhaseIncrement > 0) + + // Reverse the direction of the sin,cos so that the + // tap whose coef was previously increasing now decreases + // and vice versa + pReverbData->m_nPhaseIncrement = -pReverbData->m_nPhaseIncrement; + + } // end if counter >= update interval + + //compute what phase will be next time + pReverbData->m_nPhase += pReverbData->m_nPhaseIncrement; + + //calculate what the new sin and cos need to reach by the next update + ReverbCalculateSinCos(pReverbData->m_nPhase, &tempSin, &tempCos); + + //calculate the per-sample increment required to get there by the next update + /*lint -e{702} shift for performance */ + pReverbData->m_nSinIncrement = + (tempSin - pReverbData->m_nSin) >> REVERB_UPDATE_PERIOD_IN_BITS; + + /*lint -e{702} shift for performance */ + pReverbData->m_nCosIncrement = + (tempCos - pReverbData->m_nCos) >> REVERB_UPDATE_PERIOD_IN_BITS; + + + /* increment update counter */ + pReverbData->m_nXfadeCounter += (EAS_U16) nNumSamplesToAdd; + + return EAS_SUCCESS; + +} /* end ReverbUpdateXfade */ + + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * nMaxExcursion - noise value is limited to this value + * pnNoise - return new noise sample in this (not limited) + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - *pnNoise noise value is updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise) +{ + // calculate new noise value + *pnNoise = (EAS_I16) (*pnNoise * 5 + 1); + +#if 0 // 1xxx, test + *pnNoise = 0; +#endif // 1xxx, test + + // return the limited noise value + return (nMaxExcursion & (*pnNoise)); + +} /* end ReverbCalculateNoise */ + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos) +{ + EAS_I32 nTemp; + EAS_I32 nNetAngle; + + // -1 <= nPhase < 1 + // However, for the calculation, we need a value + // that ranges from -1/2 to +1/2, so divide the phase by 2 + /*lint -e{702} shift for performance */ + nNetAngle = nPhase >> 1; + + /* + Implement the following + sin(x) = (2-4*c)*x^2 + c + x + cos(x) = (2-4*c)*x^2 + c - x + + where c = 1/sqrt(2) + using the a0 + x*(a1 + x*a2) approach + */ + + /* limit the input "angle" to be between -0.5 and +0.5 */ + if (nNetAngle > EG1_HALF) + { + nNetAngle = EG1_HALF; + } + else if (nNetAngle < EG1_MINUS_HALF) + { + nNetAngle = EG1_MINUS_HALF; + } + + /* calculate sin */ + nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnSin = (EAS_I16) SATURATE_EG1(nTemp); + + /* calculate cos */ + nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnCos = (EAS_I16) SATURATE_EG1(nTemp); + + return EAS_SUCCESS; +} /* end ReverbCalculateSinCos */ + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Reverb(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer) +{ + EAS_I32 i; + EAS_I32 nDelayOut; + EAS_U16 nBase; + + EAS_U32 nAddr; + EAS_I32 nTemp1; + EAS_I32 nTemp2; + EAS_I32 nApIn; + EAS_I32 nApOut; + + EAS_I32 j; + EAS_I32 nEarlyOut; + + EAS_I32 tempValue; + + + // get the base address + nBase = pReverbData->m_nBaseIndex; + + for (i=0; i < nNumSamplesToAdd; i++) + { + // ********** Left Allpass - start + // left input = (left dry/4) + right feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkR; +// nApIn = *pInputBuffer++; // 1xxx test and debug ap + + // fetch allpass delay line out + //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, REVERB_BUFFER_MASK); + nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApOut, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp0.m_nApGain); + nApOut = SATURATE(nDelayOut - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp0.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApIn, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverbData->m_zD0In, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; + + // ********** Left Allpass - end + + // ********** Right Allpass - start + // right input = (right dry/4) + left feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkL; +// nApIn = *pInputBuffer++; // 1xxx test and debug ap + + // fetch allpass delay line out + nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApOut, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp1.m_nApGain); + nApOut = SATURATE(nDelayOut - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp1.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApIn, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverbData->m_zD1In, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; + + // ********** Right Allpass - end + + // ********** D0 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverbData->m_zD0Self, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverbData->m_zD1Cross, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); + + // calculate unfiltered delay out + nDelayOut = SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf0, pReverbData->m_nLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_zLpf0 + pReverbData->m_zLpf0 = (EAS_PCM) SATURATE(nTemp1 + nTemp2); + + // ********** D0 output - end + + // ********** D1 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverbData->m_zD1Self, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverbData->m_zD0Cross, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); + + // calculate unfiltered delay out + nDelayOut = SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf1, pReverbData->m_nLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_zLpf1 + pReverbData->m_zLpf1 = (EAS_PCM)SATURATE(nTemp1 + nTemp2); + + // ********** D1 output - end + + // ********** mixer and feedback - start + // sum is fedback to right input (R + L) + pReverbData->m_nRevOutFbkL = + (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 + (EAS_I32)pReverbData->m_zLpf0); + + // difference is feedback to left input (R - L) + /*lint -e{685} lint complains that it can't saturate negative */ + pReverbData->m_nRevOutFbkR = + (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 - (EAS_I32)pReverbData->m_zLpf0); + + // ********** mixer and feedback - end + + // ********** start early reflection generator, left + //psEarly = &(pReverbData->m_sEarlyL); + + nEarlyOut = 0; + + for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + { + // fetch delay line out + //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], REVERB_BUFFER_MASK); + nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyL.m_zDelay[j], REVERB_BUFFER_MASK); + + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate reflection + //nTemp1 = MULT_EG1_EG1(nDelayOut, psEarly->m_nGain[j]); + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyL.m_nGain[j]); + + nEarlyOut = SATURATE(nEarlyOut + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nLpfFwd); + nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyL.m_nLpfFwd); + + //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk); + nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyL.m_zLpf, pReverbData->m_sEarlyL.m_nLpfFbk); + + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zLpf1 + //psEarly->m_zLpf = SATURATE(nTemp1 + nTemp2); + pReverbData->m_sEarlyL.m_zLpf = (EAS_PCM) SATURATE(nTemp1 + nTemp2); + + // combine filtered early and late reflections for output + //*pOutputBuffer++ = inL; + //tempValue = SATURATE(psEarly->m_zLpf + pReverbData->m_nRevOutFbkL); + tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyL.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkL); + //scale reverb output by wet level + /*lint -e{701} use shift for performance */ + tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet<<1)); + //sum with output buffer + tempValue += *pOutputBuffer; + *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); + + // ********** end early reflection generator, left + + // ********** start early reflection generator, right + //psEarly = &(pReverbData->m_sEarlyR); + + nEarlyOut = 0; + + for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + { + // fetch delay line out + nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyR.m_zDelay[j], REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate reflection + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyR.m_nGain[j]); + + nEarlyOut = SATURATE(nEarlyOut + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyR.m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyR.m_zLpf, pReverbData->m_sEarlyR.m_nLpfFbk); + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zLpf1 + pReverbData->m_sEarlyR.m_zLpf = (EAS_PCM)SATURATE(nTemp1 + nTemp2); + + // combine filtered early and late reflections for output + //*pOutputBuffer++ = inR; + tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyR.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkR); + //scale reverb output by wet level + /*lint -e{701} use shift for performance */ + tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet << 1)); + //sum with output buffer + tempValue = tempValue + *pOutputBuffer; + *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); + + // ********** end early reflection generator, right + + // decrement base addr for next sample period + nBase--; + + pReverbData->m_nSin += pReverbData->m_nSinIncrement; + pReverbData->m_nCos += pReverbData->m_nCosIncrement; + + } // end for (i=0; i < nNumSamplesToAdd; i++) + + // store the most up to date version + pReverbData->m_nBaseIndex = nBase; + + return EAS_SUCCESS; +} /* end Reverb */ + + + +/*---------------------------------------------------------------------------- + * ReverbShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the Reverb effect. + * + * Inputs: + * pInstData - handle to instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) +{ + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pInstData); + return EAS_SUCCESS; +} /* end ReverbShutdown */ + +/*---------------------------------------------------------------------------- + * ReverbGetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Get a Reverb parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - pointer to variable to hold retrieved value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_REVERB_OBJECT *p; + + p = (S_REVERB_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_REVERB_BYPASS: + *pValue = (EAS_I32) p->m_bBypass; + break; + case EAS_PARAM_REVERB_PRESET: + *pValue = (EAS_I8) p->m_nCurrentRoom; + break; + case EAS_PARAM_REVERB_WET: + *pValue = p->m_nWet; + break; + case EAS_PARAM_REVERB_DRY: + *pValue = p->m_nDry; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ReverbGetParam */ + + +/*---------------------------------------------------------------------------- + * ReverbSetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Set a Reverb parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - new paramter value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_REVERB_OBJECT *p; + + p = (S_REVERB_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_REVERB_BYPASS: + p->m_bBypass = (EAS_BOOL) value; + break; + case EAS_PARAM_REVERB_PRESET: + if(value!=EAS_PARAM_REVERB_LARGE_HALL && value!=EAS_PARAM_REVERB_HALL && + value!=EAS_PARAM_REVERB_CHAMBER && value!=EAS_PARAM_REVERB_ROOM) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nNextRoom = (EAS_I16)value; + break; + case EAS_PARAM_REVERB_WET: + if(value>EAS_REVERB_WET_MAX || valuem_nWet = (EAS_I16)value; + break; + case EAS_PARAM_REVERB_DRY: + if(value>EAS_REVERB_DRY_MAX || valuem_nDry = (EAS_I16)value; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ReverbSetParam */ + + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT *pReverbData) +{ + EAS_INT temp; + + S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; + + pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; + pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; + + pReverbData->m_nEarly = pPreset->m_nEarly; + pReverbData->m_nWet = pPreset->m_nWet; + pReverbData->m_nDry = pPreset->m_nDry; + + + pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_nXfadeInterval = (EAS_U16) temp; + //gpsReverbObject->m_nXfadeInterval = pPreset->m_nXfadeInterval; + pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); + //gpsReverbObject->m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; + pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); + //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + + pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom; + + return EAS_SUCCESS; + +} /* end ReverbUpdateRoom */ + + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT *pReverbData) +{ + + int preset = 0; + int defaultPreset = 0; + + //now init any remaining presets to defaults + for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++) + { + S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[defaultPreset]; + if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE-1) + { + pPreset->m_nLpfFbk = 8307; + pPreset->m_nLpfFwd = 14768; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 27690; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6388; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 711; + pPreset->m_nAp1_ApGain = 17999; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 1) + { + pPreset->m_nLpfFbk = 6461; + pPreset->m_nLpfFwd = 14307; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 27690; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6391; + pPreset->m_nAp0_ApGain = 15230; + pPreset->m_nAp0_ApOut = 708; + pPreset->m_nAp1_ApGain = 9692; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 2) + { + pPreset->m_nLpfFbk = 5077; + pPreset->m_nLpfFwd = 12922; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 24460; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6449; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 774; + pPreset->m_nAp1_ApGain = 15691; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 3) + { + pPreset->m_nLpfFbk = 5077; + pPreset->m_nLpfFwd = 11076; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 23075; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6470; //6483; + pPreset->m_nAp0_ApGain = 14768; + pPreset->m_nAp0_ApOut = 792; + pPreset->m_nAp1_ApGain = 15783; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + + } + } + + return EAS_SUCCESS; +} diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverbdata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverbdata.c new file mode 100755 index 0000000..db34b48 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverbdata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverbdata.c + * + * Contents and purpose: + * Contains the static data allocation for the Reverb effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_reverbdata.h" + +S_REVERB_OBJECT eas_ReverbData; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverbdata.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverbdata.h new file mode 100755 index 0000000..926ea2e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_reverbdata.h @@ -0,0 +1,486 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverbdata.h + * + * Contents and purpose: + * Contains the prototypes for the Reverb effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 499 $ + * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_REVERBDATA_H +#define _EAS_REVERBDATA_H + +#include "eas_types.h" +#include "eas_audioconst.h" + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +/* +CIRCULAR() calculates the array index using modulo arithmetic. +The "trick" is that modulo arithmetic is simplified by masking +the effective address where the mask is (2^n)-1. This only works +if the buffer size is a power of two. +*/ +#define CIRCULAR(base,offset,size) (EAS_U32)( \ + ( \ + ((EAS_I32)(base)) + ((EAS_I32)(offset)) \ + ) \ + & size \ + ) + +/* reverb parameters are updated every 2^(REVERB_UPDATE_PERIOD_IN_BITS) samples */ +#if defined (_SAMPLE_RATE_8000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 5 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 2048 + +#elif defined (_SAMPLE_RATE_16000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 6 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 + +#elif defined (_SAMPLE_RATE_22050) + +#define REVERB_UPDATE_PERIOD_IN_BITS 7 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 + +#elif defined (_SAMPLE_RATE_32000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 7 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#elif defined (_SAMPLE_RATE_44100) + +#define REVERB_UPDATE_PERIOD_IN_BITS 8 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#elif defined (_SAMPLE_RATE_48000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 8 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#endif + +// Define a mask for circular addressing, so that array index +// can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1) +// The buffer size MUST be a power of two +#define REVERB_BUFFER_MASK (REVERB_BUFFER_SIZE_IN_SAMPLES -1) + +#define REVERB_MAX_ROOM_TYPE 4 // any room numbers larger than this are invalid +#define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ +#define REVERB_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << REVERB_UPDATE_PERIOD_IN_BITS) + +/* +calculate the update counter by bitwise ANDING with this value to +generate a 2^n modulo value +*/ +#define REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(REVERB_UPDATE_PERIOD_IN_SAMPLES -1) + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SECONDS seconds */ +#define REVERB_UPDATE_PERIOD_IN_SECONDS (REVERB_UPDATE_PERIOD_IN_SAMPLES / _OUTPUT_SAMPLE_RATE) + +// xfade parameters +#define REVERB_XFADE_PERIOD_IN_SECONDS (100.0 / 1000.0) // xfade once every this many seconds + +#define REVERB_XFADE_PERIOD_IN_SAMPLES (REVERB_XFADE_PERIOD_IN_SECONDS * _OUTPUT_SAMPLE_RATE) + +#define REVERB_XFADE_PHASE_INCREMENT (EAS_I16)(65536 / ((EAS_I16)REVERB_XFADE_PERIOD_IN_SAMPLES/(EAS_I16)REVERB_UPDATE_PERIOD_IN_SAMPLES)) + +/**********/ +/* the entire synth uses various flags in a bit field */ + +/* if flag is set, synth reset has been requested */ +#define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */ +#define MASK_REVERB_RESET_IS_REQUESTED 0x01 +#define MASK_REVERB_RESET_IS_NOT_REQUESTED (EAS_U32)(~MASK_REVERB_RESET_IS_REQUESTED) + +/* +by default, we always want to update ALL channel parameters +when we reset the synth (e.g., during GM ON) +*/ +#define DEFAULT_REVERB_FLAGS 0x0 + +/* coefficients for generating sin, cos */ +#define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */ +/* +EAS_I32 nPanG1 = +1.0 for sin +EAS_I32 nPanG1 = -1.0 for cos +*/ +#define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ + +/*************************************************************/ +// define the input injection points +#define GUARD 5 // safety guard of this many samples + +#define MAX_AP_TIME (double) (20.0/1000.0) // delay time in milliseconds +#define MAX_DELAY_TIME (double) (65.0/1000.0) // delay time in milliseconds + +#define MAX_AP_SAMPLES (int)(((double) MAX_AP_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) +#define MAX_DELAY_SAMPLES (int)(((double) MAX_DELAY_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) + +#define AP0_IN 0 +#define AP1_IN (AP0_IN + MAX_AP_SAMPLES + GUARD) +#define DELAY0_IN (AP1_IN + MAX_AP_SAMPLES + GUARD) +#define DELAY1_IN (DELAY0_IN + MAX_DELAY_SAMPLES + GUARD) + +// Define the max offsets for the end points of each section +// i.e., we don't expect a given section's taps to go beyond +// the following limits +#define AP0_OUT (AP0_IN + MAX_AP_SAMPLES -1) +#define AP1_OUT (AP1_IN + MAX_AP_SAMPLES -1) +#define DELAY0_OUT (DELAY0_IN + MAX_DELAY_SAMPLES -1) +#define DELAY1_OUT (DELAY1_IN + MAX_DELAY_SAMPLES -1) + +#define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number +#define DEFAULT_AP0_LENGTH (int)(((double) (17.0/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) +#define DEFAULT_AP0_GAIN 19400 +#define DEFAULT_AP1_LENGTH (int)(((double) (16.5/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) +#define DEFAULT_AP1_GAIN -19400 + +#define REVERB_DEFAULT_WET 32767 +#define REVERB_DEFAULT_DRY 0 + +#define EAS_REVERB_WET_MAX 32767 +#define EAS_REVERB_WET_MIN 0 +#define EAS_REVERB_DRY_MAX 32767 +#define EAS_REVERB_DRY_MIN 0 + +/* parameters for each allpass */ +typedef struct +{ + EAS_U16 m_zApOut; // delay offset for ap out + + EAS_I16 m_nApGain; // gain for ap + + EAS_U16 m_zApIn; // delay offset for ap in + +} S_ALLPASS_OBJECT; + + +/* parameters for each allpass */ +typedef struct +{ + EAS_PCM m_zLpf; // actual state variable, not a length + + EAS_I16 m_nLpfFwd; // lpf forward gain + + EAS_I16 m_nLpfFbk; // lpf feedback gain + + EAS_U16 m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out + + EAS_I16 m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap + +} S_EARLY_REFLECTION_OBJECT; + +//demo +typedef struct +{ + EAS_I16 m_nLpfFbk; + EAS_I16 m_nLpfFwd; + + EAS_I16 m_nEarly; + EAS_I16 m_nWet; + EAS_I16 m_nDry; + + EAS_I16 m_nEarlyL_LpfFbk; + EAS_I16 m_nEarlyL_LpfFwd; + + EAS_I16 m_nEarlyL_Delay0; //8 + EAS_I16 m_nEarlyL_Gain0; + EAS_I16 m_nEarlyL_Delay1; + EAS_I16 m_nEarlyL_Gain1; + EAS_I16 m_nEarlyL_Delay2; + EAS_I16 m_nEarlyL_Gain2; + EAS_I16 m_nEarlyL_Delay3; + EAS_I16 m_nEarlyL_Gain3; + EAS_I16 m_nEarlyL_Delay4; + EAS_I16 m_nEarlyL_Gain4; + + EAS_I16 m_nEarlyR_Delay0; //18 + EAS_I16 m_nEarlyR_Gain0; + EAS_I16 m_nEarlyR_Delay1; + EAS_I16 m_nEarlyR_Gain1; + EAS_I16 m_nEarlyR_Delay2; + EAS_I16 m_nEarlyR_Gain2; + EAS_I16 m_nEarlyR_Delay3; + EAS_I16 m_nEarlyR_Gain3; + EAS_I16 m_nEarlyR_Delay4; + EAS_I16 m_nEarlyR_Gain4; + + EAS_U16 m_nMaxExcursion; //28 + EAS_I16 m_nXfadeInterval; + + EAS_I16 m_nAp0_ApGain; //30 + EAS_I16 m_nAp0_ApOut; + EAS_I16 m_nAp1_ApGain; + EAS_I16 m_nAp1_ApOut; + + EAS_I16 m_rfu4; + EAS_I16 m_rfu5; + EAS_I16 m_rfu6; + EAS_I16 m_rfu7; + EAS_I16 m_rfu8; + EAS_I16 m_rfu9; + EAS_I16 m_rfu10; //43 + +} S_REVERB_PRESET; + +typedef struct +{ + S_REVERB_PRESET m_sPreset[REVERB_MAX_ROOM_TYPE]; //array of presets + +} S_REVERB_PRESET_BANK; + +/* parameters for each reverb */ +typedef struct +{ + /* controls entire reverb playback volume */ + /* to conserve memory, use the MSB and ignore the LSB */ + EAS_U8 m_nMasterVolume; + + /* update counter keeps track of when synth params need updating */ + /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */ + EAS_I16 m_nUpdateCounter; + + EAS_U16 m_nMinSamplesToAdd; /* ComputeReverb() generates this many samples */ + + EAS_U8 m_nFlags; /* misc flags/bit fields */ + + EAS_PCM *m_pOutputBuffer; + EAS_PCM *m_pInputBuffer; + + EAS_U16 m_nNumSamplesInOutputBuffer; + EAS_U16 m_nNumSamplesInInputBuffer; + + EAS_U16 m_nNumInputSamplesRead; // if m_nNumInputSamplesRead >= NumSamplesInInputBuffer + // then get a new input buffer + EAS_PCM *m_pNextInputSample; + + EAS_U16 m_nBaseIndex; // base index for circular buffer + + // reverb delay line offsets, allpass parameters, etc: + + EAS_PCM m_nRevOutFbkR; // combine feedback reverb right out with dry left in + + S_ALLPASS_OBJECT m_sAp0; // allpass 0 (left channel) + + EAS_U16 m_zD0In; // delay offset for delay line D0 in + + EAS_PCM m_nRevOutFbkL; // combine feedback reverb left out with dry right in + + S_ALLPASS_OBJECT m_sAp1; // allpass 1 (right channel) + + EAS_U16 m_zD1In; // delay offset for delay line D1 in + + // delay output taps, notice criss cross order + EAS_U16 m_zD0Self; // self feeds forward d0 --> d0 + + EAS_U16 m_zD1Cross; // cross feeds across d1 --> d0 + + EAS_PCM m_zLpf0; // actual state variable, not a length + + EAS_U16 m_zD1Self; // self feeds forward d1 --> d1 + + EAS_U16 m_zD0Cross; // cross feeds across d0 --> d1 + + EAS_PCM m_zLpf1; // actual state variable, not a length + + EAS_I16 m_nSin; // gain for self taps + + EAS_I16 m_nCos; // gain for cross taps + + EAS_I16 m_nSinIncrement; // increment for gain + + EAS_I16 m_nCosIncrement; // increment for gain + + EAS_I16 m_nLpfFwd; // lpf forward gain (includes scaling for mixer) + + EAS_I16 m_nLpfFbk; // lpf feedback gain + + EAS_U16 m_nXfadeInterval; // update/xfade after this many samples + + EAS_U16 m_nXfadeCounter; // keep track of when to xfade + + EAS_I16 m_nPhase; // -1 <= m_nPhase < 1 + // but during sin,cos calculations + // use m_nPhase/2 + + EAS_I16 m_nPhaseIncrement; // add this to m_nPhase each frame + + EAS_I16 m_nNoise; // random noise sample + + EAS_U16 m_nMaxExcursion; // the taps can excurse +/- this amount + + EAS_BOOL m_bUseNoise; // if EAS_TRUE, use noise as input signal + + EAS_BOOL m_bBypass; // if EAS_TRUE, then bypass reverb and copy input to output + + EAS_I16 m_nCurrentRoom; // preset number for current room + + EAS_I16 m_nNextRoom; // preset number for next room + + EAS_I16 m_nWet; // gain for wet (processed) signal + + EAS_I16 m_nDry; // gain for dry (unprocessed) signal + + EAS_I16 m_nEarly; // gain for early (widen) signal + + S_EARLY_REFLECTION_OBJECT m_sEarlyL; // left channel early reflections + S_EARLY_REFLECTION_OBJECT m_sEarlyR; // right channel early reflections + + EAS_PCM m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES]; // one large delay line for all reverb elements + + S_REVERB_PRESET pPreset; + + S_REVERB_PRESET_BANK m_sPreset; + + //EAS_I8 preset; + +} S_REVERB_OBJECT; + + +/*------------------------------------ + * prototypes + *------------------------------------ +*/ + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * nMaxExcursion - noise value is limited to this value + * pnNoise - return new noise sample in this (not limited) + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - *pnNoise noise value is updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise); + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos); + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Reverb(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer); + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT* pReverbData); + + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT* pReverbData); + +#endif /* #ifndef _EAS_REVERBDATA_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttl.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttl.c new file mode 100755 index 0000000..d8253fb --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttl.c @@ -0,0 +1,1197 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttl.c + * + * Contents and purpose: + * RTTTL parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_rtttldata.h" +#include "eas_ctype.h" + +/* increase gain for mono ringtones */ +#define RTTTL_GAIN_OFFSET 8 + +/* maximum title length including colon separator */ +#define RTTTL_MAX_TITLE_LEN 32 +#define RTTTL_INFINITE_LOOP 15 + +/* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */ +#define DEFAULT_TICK_CONV 30476 +#define TICK_CONVERT 1920000 + +/* default channel and program for RTTTL playback */ +#define RTTTL_CHANNEL 0 +#define RTTTL_PROGRAM 80 +#define RTTTL_VELOCITY 127 + +/* note used for rest */ +#define RTTTL_REST 1 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +/* local prototypes */ +static EAS_RESULT RTTTL_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT RTTTL_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT RTTTL_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT RTTTL_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT RTTTL_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT RTTTL_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT RTTTL_GetStyle (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData); +static EAS_RESULT RTTTL_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pDuration); +static EAS_RESULT RTTTL_GetOctave (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_U8 *pOctave); +static EAS_RESULT RTTTL_GetTempo (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData); +static EAS_RESULT RTTTL_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I32 *pValue); +static EAS_RESULT RTTTL_ParseHeader (S_EAS_DATA *pEASData, S_RTTTL_DATA* pData, EAS_BOOL metaData); +static EAS_RESULT RTTTL_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue); +static EAS_RESULT RTTTL_PeekNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue); + +/* inline functions */ +EAS_INLINE void RTTTL_PutBackChar (S_RTTTL_DATA *pData, EAS_I8 value) { pData->dataByte = value; } + + +/* lookup table for note values */ +static const EAS_U8 noteTable[] = { 21, 23, 12, 14, 16, 17, 19, 23 }; + +/*---------------------------------------------------------------------------- + * + * EAS_RTTTL_Parser + * + * This structure contains the functional interface for the iMelody parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_RTTTL_Parser = +{ + RTTTL_CheckFileType, + RTTTL_Prepare, + RTTTL_Time, + RTTTL_Event, + RTTTL_State, + RTTTL_Close, + RTTTL_Reset, + RTTTL_Pause, + RTTTL_Resume, + NULL, + RTTTL_SetData, + RTTTL_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * RTTTL_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_RTTTL_DATA data; + S_RTTTL_DATA *pData; + + /* see if we can parse the header */ + data.fileHandle = fileHandle; + data.fileOffset = offset; + *ppHandle= NULL; + if (RTTTL_ParseHeader (pEASData, &data, EAS_FALSE) == EAS_SUCCESS) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_RTTTL_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_RTTTL_DATA)); + if (!pData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pData, 0, sizeof(S_RTTTL_DATA)); + + /* return a pointer to the instance data */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_OPEN; + *ppHandle = pData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + /* check for valid state */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + pData->state = EAS_STATE_ERROR; + if ((result = RTTTL_ParseHeader (pEASData, pData, (EAS_BOOL) (pData->metadata.callback != NULL))) != EAS_SUCCESS) + { + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + return result; + } + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + EAS_I32 ticks; + EAS_I32 temp; + EAS_I8 c; + EAS_U8 note; + EAS_U8 octave; + + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + /* set program to square lead */ + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, RTTTL_PROGRAM); + + /* set channel volume to max */ + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* parse the next event */ + octave = pData->octave; + note = 0; + ticks = pData->duration * pData->tick; + for (;;) + { + + /* get next character */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + { + if (result != EAS_EOF) + return result; + + /* end of file, if no notes to process, check for looping */ + if (!note) + { + /* if no loop set state to stopping */ + if (pData->repeatCount == 0) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* decrement loop count */ + if (pData->repeatCount != RTTTL_INFINITE_LOOP) + pData->repeatCount--; + + /* if locating, ignore infinite loops */ + else if (parserMode != eParserModePlay) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* loop back to start of notes */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS) + return result; + continue; + } + + /* still have a note to process */ + else + c = ','; + } + + /* bpm */ + if (c == 'b') + { + /* peek at next character */ + if ((result = RTTTL_PeekNextChar(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + return result; + + /* if a number, must be octave or tempo */ + if (IsDigit(c)) + { + if ((result = RTTTL_GetNumber(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + + /* check for octave first */ + if ((temp >= 4) && (temp <= 7)) + { + octave = (EAS_U8) temp; + } + + /* check for tempo */ + else if ((temp >= 25) && (temp <= 900)) + { + pData->tick = TICK_CONVERT / (EAS_U32) temp; + } + + /* don't know what it was */ + else + return EAS_ERROR_FILE_FORMAT; + } + + /* must be a note */ + else + { + note = noteTable[1]; + } + } + + /* octave */ + else if (c == 'o') + { + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &pData->octave)) != EAS_SUCCESS) + return result; + } + + /* style */ + else if (c == 's') + { + if ((result = RTTTL_GetStyle(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + } + + /* duration or octave */ + else if (IsDigit(c)) + { + RTTTL_PutBackChar(pData, c); + + /* duration comes before note */ + if (!note) + { + if ((result = RTTTL_GetDuration(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + return result; + ticks = c * pData->tick; + } + + /* octave comes after note */ + else + { + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &octave)) != EAS_SUCCESS) + return result; + } + } + + /* note or rest */ + else if ((c >= 'a') && (c <= 'h')) + { + note = noteTable[c - 'a']; + } + + else if (c == 'p') + { + note = RTTTL_REST; + } + + /* dotted note */ + else if (c == '.') + { + /*lint -e{704} shift for performance */ + ticks += ticks >> 1; + } + + /* accidental */ + else if (c == '#') + { + if (note) + note++; + } + + /* end of event */ + else if ((c == ',') && note) + { + + /* handle note events */ + if (note != RTTTL_REST) + { + + /* save note and start it */ + pData->note = note + octave; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, pData->note, RTTTL_VELOCITY); + + /* determine note length */ + switch (pData->style) + { + /* natural */ + case 'n': + /*lint -e{704} shift for performance */ + pData->restTicks = ticks >> 4; + break; + /* continuous */ + + case 'c': + pData->restTicks = 0; + break; + + /* staccato */ + case 's': + /*lint -e{704} shift for performance */ + pData->restTicks = ticks >> 1; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "RTTTL_Event: Unexpected style type %c\n", pData->style); */ } + break; + } + + /* next event is at end of this note */ + pData->time += ticks - pData->restTicks; + } + + /* rest */ + else + pData->time += ticks; + + /* event found, return to caller */ + break; + } + } + + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_RTTTL_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_RTTTL_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_STOPPED; + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + pData = (S_RTTTL_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + pData = (S_RTTTL_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + + /* reset time to zero */ + pData->time = 0; + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + if ((result = RTTTL_ParseHeader (pEASData, pData, EAS_TRUE)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA *pData; + + /* can't pause a stopped stream */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA *pData; + + /* can't resume a stopped stream */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA *) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA *) pInstData; + switch (param) + { + /* return file type as RTTTL */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_RTTTL; + break; + +#if 0 + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = RTTTL_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetStyle() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetStyle (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData) +{ + EAS_RESULT result; + EAS_I8 style; + + /* get style */ + if ((result = RTTTL_GetNextChar(hwInstData, pData, &style)) != EAS_SUCCESS) + return result; + + if ((style != 's') && (style != 'n') && (style != 'c')) + return EAS_ERROR_FILE_FORMAT; + + pData->style = style; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetDuration() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pDuration) +{ + EAS_RESULT result; + EAS_I32 duration; + EAS_I8 temp; + + /* get the duration */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &duration)) != EAS_SUCCESS) + return result; + + if ((duration != 1) && (duration != 2) && (duration != 4) && (duration != 8) && (duration != 16) && (duration != 32)) + return EAS_ERROR_FILE_FORMAT; + + temp = 64; + while (duration) + { + /*lint -e{704} shift for performance */ + duration = duration >> 1; + /*lint -e{702} use shift for performance */ + temp = temp >> 1; + } + + *pDuration = temp; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetOctave() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetOctave (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_U8 *pOctave) +{ + EAS_RESULT result; + EAS_I32 octave; + + /* get the tempo */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &octave)) != EAS_SUCCESS) + return result; + + if ((octave < 4) || (octave > 7)) + return EAS_ERROR_FILE_FORMAT; + + *pOctave = (EAS_U8) (octave * 12); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetTempo() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetTempo (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData) +{ + EAS_RESULT result; + EAS_I32 tempo; + + /* get the tempo */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &tempo)) != EAS_SUCCESS) + return result; + + if ((tempo < 25) || (tempo > 900)) + return EAS_ERROR_FILE_FORMAT; + + pData->tick = TICK_CONVERT / (EAS_U32) tempo; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetNumber() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I32 *pValue) +{ + EAS_RESULT result; + EAS_INT temp; + EAS_I8 c; + + *pValue = -1; + temp = 0; + for (;;) + { + if ((result = RTTTL_PeekNextChar(hwInstData, pData, &c)) != EAS_SUCCESS) + { + if ((result == EAS_EOF) && (*pValue != -1)) + return EAS_SUCCESS; + return result; + } + + if (IsDigit(c)) + { + pData->dataByte = 0; + temp = temp * 10 + c - '0'; + *pValue = temp; + } + else + return EAS_SUCCESS; + } +} + +/*---------------------------------------------------------------------------- + * RTTTL_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_ParseHeader (S_EAS_DATA *pEASData, S_RTTTL_DATA* pData, EAS_BOOL metaData) +{ + EAS_RESULT result; + EAS_I32 i; + EAS_I8 temp; + EAS_I8 control; + + /* initialize some defaults */ + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->note = 0; + pData->duration = 4; + pData ->restTicks = 0; + pData->octave = 60; + pData->repeatOffset = -1; + pData->repeatCount = 0; + pData->style = 'n'; + pData->dataByte = 0; + + metaData = metaData && (pData->metadata.buffer != NULL) && (pData->metadata.callback != NULL); + + /* seek to start of data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + + /* zero the metadata buffer */ + if (metaData) + EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize); + + /* read the title */ + for (i = 0; i < RTTTL_MAX_TITLE_LEN; i++) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + + if (temp == ':') + break; + + /* pass along metadata */ + if (metaData) + { + if (i < (pData->metadata.bufferSize- 1)) + pData->metadata.buffer[i] = (char) temp; + } + } + + /* check for error in title */ + if (i == RTTTL_MAX_TITLE_LEN) + return EAS_ERROR_FILE_FORMAT; + + /* pass along metadata */ + if (metaData) + (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData); + + /* control fields */ + for (;;) + { + + /* get control type */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &control)) != EAS_SUCCESS) + return result; + + /* next char should be equal sign */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + if (temp != '=') + return EAS_ERROR_FILE_FORMAT; + + /* get the control value */ + switch (control) + { + + /* bpm */ + case 'b': + if ((result = RTTTL_GetTempo(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + break; + + /* duration */ + case 'd': + if ((result = RTTTL_GetDuration(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + pData->duration = temp; + break; + + /* loop */ + case 'l': + if ((result = RTTTL_GetNumber(pEASData->hwInstData, pData, &i)) != EAS_SUCCESS) + return result; + if ((i < 0) || (i > 15)) + return EAS_ERROR_FILE_FORMAT; + pData->repeatCount = (EAS_U8) i; + break; + + /* octave */ + case 'o': + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &pData->octave)) != EAS_SUCCESS) + return result; + break; + + /* get style */ + case 's': + if ((result = RTTTL_GetStyle(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + break; + + /* unrecognized control */ + default: + return EAS_ERROR_FILE_FORMAT; + } + + /* next character should be comma or colon */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + + /* check for end of control field */ + if (temp == ':') + break; + + /* must be a comma */ + if (temp != ',') + return EAS_ERROR_FILE_FORMAT; + } + + /* should be at the start of the music block */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pData->fileHandle, &pData->repeatOffset)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue) +{ + EAS_RESULT result; + EAS_I8 temp; + + *pValue = 0; + for(;;) + { + + /* check for character that has been put back */ + if (pData->dataByte) + { + temp = pData->dataByte; + pData->dataByte = 0; + } + else + { + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + } + + /* ignore white space */ + if (!IsSpace(temp)) + { + *pValue = ToLower(temp); + return EAS_SUCCESS; + } + } +} + +/*---------------------------------------------------------------------------- + * RTTTL_PeekNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_PeekNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue) +{ + EAS_RESULT result; + EAS_I8 temp; + + *pValue = 0; + for(;;) + { + + /* read a character from the file, if necessary */ + if (!pData->dataByte) + { + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->dataByte)) != EAS_SUCCESS) + return result; + + } + temp = pData->dataByte; + + /* ignore white space */ + if (!IsSpace(temp)) + { + *pValue = ToLower(temp); + return EAS_SUCCESS; + } + pData->dataByte = 0; + } +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttldata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttldata.c new file mode 100755 index 0000000..708a1d9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttldata.c @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttldata.c + * + * Contents and purpose: + * RTTTL File Parser data module for static memory models + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_rtttldata.h" + +/*---------------------------------------------------------------------------- + * + * eas_RTTTLData + * + * Static memory allocation for RTTTL parser + *---------------------------------------------------------------------------- +*/ +S_RTTTL_DATA eas_RTTTLData; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttldata.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttldata.h new file mode 100755 index 0000000..31dd522 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_rtttldata.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttldata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data declarations for the RTTTL parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_RTTTLDATA_H +#define EAS_RTTTLDATA_H + +#include "eas_data.h" + + +/* maximum line size as specified in iMelody V1.2 spec */ +#define MAX_LINE_SIZE 75 + +/*---------------------------------------------------------------------------- + * + * S_RTTTL_DATA + * + * This structure contains the state data for the iMelody parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* synthesizer handle */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_I32 tick; /* length of 32nd note in 256th of a msec */ + EAS_I32 restTicks; /* ticks to rest after current note */ + EAS_I32 repeatOffset; /* file offset to start of repeat section */ + EAS_U8 repeatCount; /* repeat counter */ + EAS_I8 dataByte; /* storage for characters that are "put back" */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_I8 style; /* from STYLE */ + EAS_U8 note; /* MIDI note number */ + EAS_U8 octave; /* decault octave prefix */ + EAS_I8 duration; /* default note duration */ +} S_RTTTL_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smf.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smf.c new file mode 100755 index 0000000..e609583 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smf.c @@ -0,0 +1,1203 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smf.c + * + * Contents and purpose: + * SMF Type 0 and 1 File Parser + * + * For SMF timebase analysis, see "MIDI Sequencer Analysis.xls". + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 803 $ + * $Date: 2007-08-01 09:57:00 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_smfdata.h" +#include "eas_smf.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + +//3 dls: The timebase for this module is adequate to keep MIDI and +//3 digital audio synchronized for only a few minutes. It should be +//3 sufficient for most mobile applications. If better accuracy is +//3 required, more fractional bits should be added to the timebase. + +static const EAS_U8 smfHeader[] = { 'M', 'T', 'h', 'd' }; + +/* local prototypes */ +static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData); +static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream); +static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode); +static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode); +static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream); +static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks); + + +/*---------------------------------------------------------------------------- + * + * SMF_Parser + * + * This structure contains the functional interface for the SMF parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_SMF_Parser = +{ + SMF_CheckFileType, + SMF_Prepare, + SMF_Time, + SMF_Event, + SMF_State, + SMF_Close, + SMF_Reset, + SMF_Pause, + SMF_Resume, + NULL, + SMF_SetData, + SMF_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * SMF_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + + /* seek to starting offset - usually 0 */ + *ppHandle = NULL; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS) + return result; + + /* search through file for header - slow method */ + if (pEASData->searchHeaderFlag) + { + result = EAS_SearchFile(pEASData, fileHandle, smfHeader, sizeof(smfHeader), &offset); + if (result != EAS_SUCCESS) + return (result == EAS_EOF) ? EAS_SUCCESS : result; + } + + /* read the first 4 bytes of the file - quick method */ + else { + EAS_U8 header[4]; + EAS_I32 count; + if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, header, sizeof(header), &count)) != EAS_SUCCESS) + return result; + + /* check for 'MTrk' - return if no match */ + if ((header[0] != 'M') || (header[1] != 'T') || (header[2] != 'h') || (header[3] != 'd')) + return EAS_SUCCESS; + } + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pSMFData = EAS_CMEnumData(EAS_CM_SMF_DATA); + else + { + pSMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SMF_DATA)); + EAS_HWMemSet((void *)pSMFData,0, sizeof(S_SMF_DATA)); + } + if (!pSMFData) + return EAS_ERROR_MALLOC_FAILED; + + /* initialize some critical data */ + pSMFData->fileHandle = fileHandle; + pSMFData->fileOffset = offset; + pSMFData->pSynth = NULL; + pSMFData->time = 0; + pSMFData->state = EAS_STATE_OPEN; + *ppHandle = pSMFData; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + + /* check for valid state */ + pSMFData = (S_SMF_DATA *) pInstData; + if (pSMFData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pSMFData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + /* parse the file header and setup the individual stream parsers */ + if ((result = SMF_ParseHeader(pEASData->hwInstData, pSMFData)) != EAS_SUCCESS) + return result; + + /* ready to play */ + pSMFData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* sanity check */ +#ifdef _CHECKED_BUILD + if (pSMFData->state == EAS_STATE_STOPPED) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Can't ask for time on a stopped stream\n"); */ } + } + + if (pSMFData->nextStream == NULL) + { + { /* dpp: EAS_ReportEx( _EAS_SEVERITY_ERROR, "no is NULL\n"); */ } + } +#endif + +#if 0 + /* return time in milliseconds */ + /* if chase mode, lie about time */ + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + *pTime = 0; + + else +#endif + + /*lint -e{704} use shift instead of division */ + *pTime = pSMFData->time >> 8; + + *pTime = pSMFData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + EAS_I32 i; + EAS_U32 ticks; + EAS_U32 temp; + + /* establish pointer to instance data */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* get current ticks */ + ticks = pSMFData->nextStream->ticks; + + /* assume that an error occurred */ + pSMFData->state = EAS_STATE_ERROR; + +#ifdef JET_INTERFACE + /* if JET has track muted, set parser mode to mute */ + if (pSMFData->nextStream->midiStream.jetData & MIDI_FLAGS_JET_MUTE) + parserMode = eParserModeMute; +#endif + + /* parse the next event from all the streams */ + if ((result = SMF_ParseEvent(pEASData, pSMFData, pSMFData->nextStream, parserMode)) != EAS_SUCCESS) + { + /* check for unexpected end-of-file */ + if (result != EAS_EOF) + return result; + + /* indicate end of track for this stream */ + pSMFData->nextStream->ticks = SMF_END_OF_TRACK; + } + + /* get next delta time, unless already at end of track */ + else if (pSMFData->nextStream->ticks != SMF_END_OF_TRACK) + { + if ((result = SMF_GetDeltaTime(pEASData->hwInstData, pSMFData->nextStream)) != EAS_SUCCESS) + { + /* check for unexpected end-of-file */ + if (result != EAS_EOF) + return result; + + /* indicate end of track for this stream */ + pSMFData->nextStream->ticks = SMF_END_OF_TRACK; + } + + /* if zero delta to next event, stay with this stream */ + else if (pSMFData->nextStream->ticks == ticks) + { + pSMFData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; + } + } + + /* find next event in all streams */ + temp = 0x7ffffff; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + if (pSMFData->streams[i].ticks < temp) + { + temp = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + } + + /* are there any more events to parse? */ + if (pSMFData->nextStream) + { + pSMFData->state = EAS_STATE_PLAY; + + /* update the time of the next event */ + SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks - ticks); + } + else + { + pSMFData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth); + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_SMF_DATA* pSMFData; + + /* establish pointer to instance data */ + pSMFData = (S_SMF_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pSMFData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pSMFData->pSynth) == 0) + pSMFData->state = EAS_STATE_STOPPED; + } + + if (pSMFData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pSMFData->pSynth) == 0) + pSMFData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pSMFData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_I32 i; + EAS_RESULT result; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* close all the streams */ + for (i = 0; i < pSMFData->numStreams; i++) + { + if (pSMFData->streams[i].fileHandle != NULL) + { + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->streams[i].fileHandle)) != EAS_SUCCESS) + return result; + } + } + if (pSMFData->fileHandle != NULL) + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pSMFData->pSynth != NULL) + VMMIDIShutdown(pEASData, pSMFData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + { + if (pSMFData->streams) + EAS_HWFree(pEASData->hwInstData, pSMFData->streams); + + /* free the instance data */ + EAS_HWFree(pEASData->hwInstData, pSMFData); + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_I32 i; + EAS_RESULT result; + EAS_U32 ticks; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* reset time to zero */ + pSMFData->time = 0; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pSMFData->pSynth, EAS_TRUE); + + /* find the start of each track */ + ticks = 0x7fffffffL; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + + /* reset file position to first byte of data in track */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFData->streams[i].fileHandle, pSMFData->streams[i].startFilePos)) != EAS_SUCCESS) + return result; + + /* initalize some data */ + pSMFData->streams[i].ticks = 0; + + /* initalize the MIDI parser data */ + EAS_InitMIDIStream(&pSMFData->streams[i].midiStream); + + /* parse the first delta time in each stream */ + if ((result = SMF_GetDeltaTime(pEASData->hwInstData,&pSMFData->streams[i])) != EAS_SUCCESS) + return result; + if (pSMFData->streams[i].ticks < ticks) + { + ticks = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + } + + + pSMFData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA *pSMFData; + + /* can't pause a stopped stream */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth); + pSMFData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA *pSMFData; + + /* can't resume a stopped stream */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pSMFData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Sets parser parameters + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pSMFData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + +#ifdef JET_INTERFACE + /* set jet segment and track ID of all tracks for callback function */ + case PARSER_DATA_JET_CB: + { + EAS_U32 i; + EAS_U32 bit = (EAS_U32) value; + bit = (bit << JET_EVENT_SEG_SHIFT) & JET_EVENT_SEG_MASK; + for (i = 0; i < pSMFData->numStreams; i++) + pSMFData->streams[i].midiStream.jetData = + (pSMFData->streams[i].midiStream.jetData & + ~(JET_EVENT_TRACK_MASK | JET_EVENT_SEG_MASK)) | + i << JET_EVENT_TRACK_SHIFT | bit | MIDI_FLAGS_JET_CB; + pSMFData->flags |= SMF_FLAGS_JET_STREAM; + } + break; + + /* set state of all mute flags at once */ + case PARSER_DATA_MUTE_FLAGS: + { + EAS_INT i; + EAS_U32 bit = (EAS_U32) value; + for (i = 0; i < pSMFData->numStreams; i++) + { + if (bit & 1) + pSMFData->streams[i].midiStream.jetData |= MIDI_FLAGS_JET_MUTE; + else + pSMFData->streams[i].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE; + bit >>= 1; + } + } + break; + + /* set track mute */ + case PARSER_DATA_SET_MUTE: + if (value < pSMFData->numStreams) + pSMFData->streams[value].midiStream.jetData |= MIDI_FLAGS_JET_MUTE; + else + return EAS_ERROR_PARAMETER_RANGE; + break; + + /* clear track mute */ + case PARSER_DATA_CLEAR_MUTE: + if (value < pSMFData->numStreams) + pSMFData->streams[value].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE; + else + return EAS_ERROR_PARAMETER_RANGE; + break; +#endif + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Retrieves parser parameters + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + switch (param) + { + /* return file type */ + case PARSER_DATA_FILE_TYPE: + if (pSMFData->numStreams == 1) + *pValue = EAS_FILE_SMF0; + else + *pValue = EAS_FILE_SMF1; + break; + +/* now handled in eas_public.c */ +#if 0 + case PARSER_DATA_POLYPHONY: + if (pSMFData->pSynth) + VMGetPolyphony(pEASData->pVoiceMgr, pSMFData->pSynth, pValue); + else + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + break; + + case PARSER_DATA_PRIORITY: + if (pSMFData->pSynth) + VMGetPriority(pEASData->pVoiceMgr, pSMFData->pSynth, pValue); + break; + + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pSMFData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pSMFData->pSynth; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetVarLenData() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData) +{ + EAS_RESULT result; + EAS_U32 data; + EAS_U8 c; + + /* read until bit 7 is zero */ + data = 0; + do + { + if ((result = EAS_HWGetByte(hwInstData, fileHandle,&c)) != EAS_SUCCESS) + return result; + data = (data << 7) | (c & 0x7f); + } while (c & 0x80); + *pData = data; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetDeltaTime() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream) +{ + EAS_RESULT result; + EAS_U32 ticks; + + if ((result = SMF_GetVarLenData(hwInstData, pSMFStream->fileHandle, &ticks)) != EAS_SUCCESS) + return result; + + pSMFStream->ticks += ticks; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseMetaEvent() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream) +{ + EAS_RESULT result; + EAS_U32 len; + EAS_I32 pos; + EAS_U32 temp; + EAS_U8 c; + + /* get the meta-event type */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + + /* get the length */ + if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS) + return result; + + /* get the current file position so we can skip the event */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pSMFStream->fileHandle, &pos)) != EAS_SUCCESS) + return result; + pos += (EAS_I32) len; + + /* end of track? */ + if (c == SMF_META_END_OF_TRACK) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: end of track\n", c, len); */ } + pSMFStream->ticks = SMF_END_OF_TRACK; + } + + /* tempo event? */ + else if (c == SMF_META_TEMPO) + { + /* read the 3-byte timebase value */ + temp = 0; + while (len--) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + temp = (temp << 8) | c; + } + + pSMFData->tickConv = (EAS_U16) (((temp * 1024) / pSMFData->ppqn + 500) / 1000); + pSMFData->flags |= SMF_FLAGS_HAS_TEMPO; + } + + /* check for time signature - see iMelody spec V1.4 section 4.1.2.2.3.6 */ + else if (c == SMF_META_TIME_SIGNATURE) + { + pSMFData->flags |= SMF_FLAGS_HAS_TIME_SIG; + } + + /* if the host has registered a metadata callback return the metadata */ + else if (pSMFData->metadata.callback) + { + EAS_I32 readLen; + E_EAS_METADATA_TYPE metaType; + + metaType = EAS_METADATA_UNKNOWN; + + /* only process title on the first track */ + if (c == SMF_META_SEQTRK_NAME) + metaType = EAS_METADATA_TITLE; + else if (c == SMF_META_TEXT) + metaType = EAS_METADATA_TEXT; + else if (c == SMF_META_COPYRIGHT) + metaType = EAS_METADATA_COPYRIGHT; + else if (c == SMF_META_LYRIC) + metaType = EAS_METADATA_LYRIC; + + if (metaType != EAS_METADATA_UNKNOWN) + { + readLen = pSMFData->metadata.bufferSize - 1; + if ((EAS_I32) len < readLen) + readLen = (EAS_I32) len; + if ((result = EAS_HWReadFile(pEASData->hwInstData, pSMFStream->fileHandle, pSMFData->metadata.buffer, readLen, &readLen)) != EAS_SUCCESS) + return result; + pSMFData->metadata.buffer[readLen] = 0; + pSMFData->metadata.callback(metaType, pSMFData->metadata.buffer, pSMFData->metadata.pUserData); + } + } + + /* position file to next event - in case we ignored all or part of the meta-event */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFStream->fileHandle, pos)) != EAS_SUCCESS) + return result; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: type=%02x, len=%d\n", c, len); */ } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseSysEx() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode) +{ + EAS_RESULT result; + EAS_U32 len; + EAS_U8 c; + + /* get the length */ + if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS) + return result; + + /* start of SysEx message? */ + if (f0 == 0xf0) + { + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, f0, parserMode)) != EAS_SUCCESS) + return result; + } + + /* feed the SysEx to the stream parser */ + while (len--) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + + /* check for GM system ON */ + if (pSMFStream->midiStream.flags & MIDI_FLAG_GM_ON) + pSMFData->flags |= SMF_FLAGS_HAS_GM_ON; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseEvent() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode) +{ + EAS_RESULT result; + EAS_U8 c; + + /* get the event type */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + + /* parse meta-event */ + if (c == 0xff) + { + if ((result = SMF_ParseMetaEvent(pEASData, pSMFData, pSMFStream)) != EAS_SUCCESS) + return result; + } + + /* parse SysEx */ + else if ((c == 0xf0) || (c == 0xf7)) + { + if ((result = SMF_ParseSysEx(pEASData, pSMFData, pSMFStream, c, parserMode)) != EAS_SUCCESS) + return result; + } + + /* parse MIDI message */ + else + { + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + + /* keep streaming data to the MIDI parser until the message is complete */ + while (pSMFStream->midiStream.pending) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + } + + } + + /* chase mode logic */ + if (pSMFData->time == 0) + { + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + { + if (pSMFStream->midiStream.flags & MIDI_FLAG_FIRST_NOTE) + pSMFData->flags &= ~SMF_FLAGS_CHASE_MODE; + } + else if ((pSMFData->flags & SMF_FLAGS_SETUP_BAR) == SMF_FLAGS_SETUP_BAR) + pSMFData->flags = (pSMFData->flags & ~SMF_FLAGS_SETUP_BAR) | SMF_FLAGS_CHASE_MODE; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Parses the header of an SMF file, allocates memory the stream parsers and initializes the + * stream parsers. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pSMFData - pointer to parser instance data + * fileHandle - file handle + * fileOffset - offset in the file where the header data starts, usually 0 + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{801} we know that 'goto' is deprecated - but it's cleaner in this case */ +EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData) +{ + EAS_RESULT result; + EAS_I32 i; + EAS_U16 division; + EAS_U32 chunkSize; + EAS_U32 chunkStart; + EAS_U32 temp; + EAS_U32 ticks; + + /* rewind the file and find the end of the header chunk */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_HEADER_SIZE)) != EAS_SUCCESS) + goto ReadError; + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* determine the number of tracks */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_NUM_TRACKS)) != EAS_SUCCESS) + goto ReadError; + if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &pSMFData->numStreams, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* limit the number of tracks */ + if (pSMFData->numStreams > MAX_SMF_STREAMS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "SMF file contains %u tracks, playing %d tracks\n", pSMFData->numStreams, MAX_SMF_STREAMS); */ } + pSMFData->numStreams = MAX_SMF_STREAMS; + } + + /* get the time division */ + if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &division, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* setup default timebase for 120 bpm */ + pSMFData->ppqn = 192; + if (division & 0x8000) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"No support for SMPTE code timebase\n"); */ } + else + pSMFData->ppqn = (division & 0x7fff); + pSMFData->tickConv = (EAS_U16) (((SMF_DEFAULT_TIMEBASE * 1024) / pSMFData->ppqn + 500) / 1000); + + /* dynamic memory allocation, allocate memory for streams */ + if (pSMFData->streams == NULL) + { + pSMFData->streams = EAS_HWMalloc(hwInstData,sizeof(S_SMF_STREAM) * pSMFData->numStreams); + if (pSMFData->streams == NULL) + return EAS_ERROR_MALLOC_FAILED; + + /* zero the memory to insure complete initialization */ + EAS_HWMemSet((void *)(pSMFData->streams), 0, sizeof(S_SMF_STREAM) * pSMFData->numStreams); + } + + /* find the start of each track */ + chunkStart = (EAS_U32) pSMFData->fileOffset; + ticks = 0x7fffffffL; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + + for (;;) + { + + /* calculate start of next chunk - checking for errors */ + temp = chunkStart + SMF_CHUNK_INFO_SIZE + chunkSize; + if (temp <= chunkStart) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Error in chunk size at offset %d\n", chunkStart); */ } + return EAS_ERROR_FILE_FORMAT; + } + chunkStart = temp; + + /* seek to the start of the next chunk */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, (EAS_I32) chunkStart)) != EAS_SUCCESS) + goto ReadError; + + /* read the chunk identifier */ + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* read the chunk size */ + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* make sure this is an 'MTrk' chunk */ + if (temp == SMF_CHUNK_TYPE_TRACK) + break; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Unexpected chunk type: 0x%08x\n", temp); */ } + } + + /* initalize some data */ + pSMFData->streams[i].ticks = 0; + pSMFData->streams[i].fileHandle = pSMFData->fileHandle; + + /* NULL the file handle so we don't try to close it twice */ + pSMFData->fileHandle = NULL; + + /* save this file position as the start of the track */ + pSMFData->streams[i].startFilePos = (EAS_I32) chunkStart + SMF_CHUNK_INFO_SIZE; + + /* initalize the MIDI parser data */ + EAS_InitMIDIStream(&pSMFData->streams[i].midiStream); + + /* parse the first delta time in each stream */ + if ((result = SMF_GetDeltaTime(hwInstData, &pSMFData->streams[i])) != EAS_SUCCESS) + goto ReadError; + + if (pSMFData->streams[i].ticks < ticks) + { + ticks = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + + /* more tracks to do, create a duplicate file handle */ + if (i < (pSMFData->numStreams - 1)) + { + if ((result = EAS_HWDupHandle(hwInstData, pSMFData->streams[i].fileHandle, &pSMFData->fileHandle)) != EAS_SUCCESS) + goto ReadError; + } + } + + /* update the time of the next event */ + if (pSMFData->nextStream) + SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks); + + return EAS_SUCCESS; + + /* ugly goto: but simpler than structured */ + ReadError: + if (result == EAS_EOF) + return EAS_ERROR_FILE_FORMAT; + return result; +} + +/*---------------------------------------------------------------------------- + * SMF_UpdateTime() + *---------------------------------------------------------------------------- + * Purpose: + * Update the millisecond time base by converting the ticks into millieconds + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks) +{ + EAS_U32 temp1, temp2; + + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + return; + + temp1 = (ticks >> 10) * pSMFData->tickConv; + temp2 = (ticks & 0x3ff) * pSMFData->tickConv; + pSMFData->time += (EAS_I32)((temp1 << 8) + (temp2 >> 2)); +} + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smf.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smf.h new file mode 100755 index 0000000..37c0790 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smf.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smf.h + * + * Contents and purpose: + * SMF Type 0 and 1 File Parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SMF_H +#define _EAS_SMF_H + +/* prototypes for private interface to SMF parser */ +EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData); + +#endif /* end _EAS_SMF_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smfdata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smfdata.c new file mode 100755 index 0000000..383d7f3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smfdata.c @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smfdata.c + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_miditypes.h" +#include "eas_smfdata.h" + +/*---------------------------------------------------------------------------- + * + * S_SMF_STREAM + * + * Static memory allocation for SMF parser + *---------------------------------------------------------------------------- +*/ +static S_SMF_STREAM eas_SMFStreams[MAX_SMF_STREAMS]; + +/*---------------------------------------------------------------------------- + * + * eas_SMFData + * + * Static memory allocation for SMF parser + *---------------------------------------------------------------------------- +*/ +S_SMF_DATA eas_SMFData = +{ + eas_SMFStreams, /* pointer to individual streams in file */ + 0, /* pointer to next stream with event */ + 0, /* pointer to synth */ + 0, /* file handle */ + { 0, 0, 0, 0}, /* metadata callback */ + 0, /* file offset */ + 0, /* current time in milliseconds/256 */ + 0, /* actual number of streams */ + 0, /* current MIDI tick to msec conversion */ + 0, /* ticks per quarter note */ + 0, /* current state EAS_STATE_XXXX */ + 0 /* flags */ +}; + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smfdata.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smfdata.h new file mode 100755 index 0000000..8861d90 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_smfdata.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smfdata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 686 $ + * $Date: 2007-05-03 14:10:54 -0700 (Thu, 03 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SMF_DATA_H +#define _EAS_SMF_DATA_H + +#ifndef MAX_SMF_STREAMS +#define MAX_SMF_STREAMS 17 +#endif + +/* offsets in to the SMF file */ +#define SMF_OFS_HEADER_SIZE 4 +#define SMF_OFS_FILE_TYPE 8 +#define SMF_OFS_NUM_TRACKS 10 + +/* size of chunk info (chunk ID + chunk size) */ +#define SMF_CHUNK_INFO_SIZE 8 + +/* 'MTrk' track chunk ID */ +#define SMF_CHUNK_TYPE_TRACK 0x4d54726bL + +/* some useful meta-events */ +#define SMF_META_TEXT 0x01 +#define SMF_META_COPYRIGHT 0x02 +#define SMF_META_SEQTRK_NAME 0x03 +#define SMF_META_LYRIC 0x05 +#define SMF_META_END_OF_TRACK 0x2f +#define SMF_META_TEMPO 0x51 +#define SMF_META_TIME_SIGNATURE 0x58 + +/* default timebase (120BPM) */ +#define SMF_DEFAULT_TIMEBASE 500000L + +/* value for pSMFStream->ticks to signify end of track */ +#define SMF_END_OF_TRACK 0xffffffff + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_sndlib.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_sndlib.h new file mode 100755 index 0000000..416be6e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_sndlib.h @@ -0,0 +1,406 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_sndlib.h + * + * Contents and purpose: + * Declarations for the sound library + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SNDLIB_H +#define _EAS_SNDLIB_H + +#include "eas_types.h" +#include "eas_synthcfg.h" + +#ifdef _WT_SYNTH +#include "eas_wtengine.h" +#endif + +/*---------------------------------------------------------------------------- + * This is bit of a hack to allow us to keep the same structure + * declarations for the DLS parser. Normally, the data is located + * in read-only memory, but for DLS, we store the data in RW + * memory. + *---------------------------------------------------------------------------- +*/ +#ifndef SCNST +#define SCNST const +#endif + +/*---------------------------------------------------------------------------- + * sample size + *---------------------------------------------------------------------------- +*/ +#ifdef _16_BIT_SAMPLES +typedef EAS_I16 EAS_SAMPLE; +#else +typedef EAS_I8 EAS_SAMPLE; +#endif + +/*---------------------------------------------------------------------------- + * EAS Library ID - quick check for valid library and version + *---------------------------------------------------------------------------- +*/ +#define _EAS_LIBRARY_VERSION 0x01534145 + +#define NUM_PROGRAMS_IN_BANK 128 +#define INVALID_REGION_INDEX 0xffff + +/* this bit in region index indicates that region is for secondary synth */ +#define FLAG_RGN_IDX_FM_SYNTH 0x8000 +#define FLAG_RGN_IDX_DLS_SYNTH 0x4000 +#define REGION_INDEX_MASK 0x3fff + +/*---------------------------------------------------------------------------- + * Generic region data structure + * + * This must be the first element in each region structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_region_tag +{ + EAS_U16 keyGroupAndFlags; + EAS_U8 rangeLow; + EAS_U8 rangeHigh; +} S_REGION; + +/* + * Bit fields for m_nKeyGroupAndFlags + * Bits 0-2 are mode bits in FM synth + * Bits 8-11 are the key group + */ +#define REGION_FLAG_IS_LOOPED 0x01 +#define REGION_FLAG_USE_WAVE_GENERATOR 0x02 +#define REGION_FLAG_USE_ADPCM 0x04 +#define REGION_FLAG_ONE_SHOT 0x08 +#define REGION_FLAG_SQUARE_WAVE 0x10 +#define REGION_FLAG_OFF_CHIP 0x20 +#define REGION_FLAG_NON_SELF_EXCLUSIVE 0x40 +#define REGION_FLAG_LAST_REGION 0x8000 + +/*---------------------------------------------------------------------------- + * Envelope data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_envelope_tag +{ + EAS_I16 attackTime; + EAS_I16 decayTime; + EAS_I16 sustainLevel; + EAS_I16 releaseTime; +} S_ENVELOPE; + +/*---------------------------------------------------------------------------- + * DLS envelope data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_dls_envelope_tag +{ + EAS_I16 delayTime; + EAS_I16 attackTime; + EAS_I16 holdTime; + EAS_I16 decayTime; + EAS_I16 sustainLevel; + EAS_I16 releaseTime; + EAS_I16 velToAttack; + EAS_I16 keyNumToDecay; + EAS_I16 keyNumToHold; +} S_DLS_ENVELOPE; + +/*---------------------------------------------------------------------------- + * LFO data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_lfo_params_tag +{ + EAS_I16 lfoFreq; + EAS_I16 lfoDelay; +} S_LFO_PARAMS; + +/*---------------------------------------------------------------------------- + * Articulation data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_articulation_tag +{ + S_ENVELOPE eg1; + S_ENVELOPE eg2; + EAS_I16 lfoToPitch; + EAS_I16 lfoDelay; + EAS_I16 lfoFreq; + EAS_I16 eg2ToPitch; + EAS_I16 eg2ToFc; + EAS_I16 filterCutoff; + EAS_I8 lfoToGain; + EAS_U8 filterQ; + EAS_I8 pan; +} S_ARTICULATION; + +/*---------------------------------------------------------------------------- + * DLS articulation data structure + *---------------------------------------------------------------------------- +*/ + +typedef struct s_dls_articulation_tag +{ + S_LFO_PARAMS modLFO; + S_LFO_PARAMS vibLFO; + + S_DLS_ENVELOPE eg1; + S_DLS_ENVELOPE eg2; + + EAS_I16 eg1ShutdownTime; + + EAS_I16 filterCutoff; + EAS_I16 modLFOToFc; + EAS_I16 modLFOCC1ToFc; + EAS_I16 modLFOChanPressToFc; + EAS_I16 eg2ToFc; + EAS_I16 velToFc; + EAS_I16 keyNumToFc; + + EAS_I16 modLFOToGain; + EAS_I16 modLFOCC1ToGain; + EAS_I16 modLFOChanPressToGain; + + EAS_I16 tuning; + EAS_I16 keyNumToPitch; + EAS_I16 vibLFOToPitch; + EAS_I16 vibLFOCC1ToPitch; + EAS_I16 vibLFOChanPressToPitch; + EAS_I16 modLFOToPitch; + EAS_I16 modLFOCC1ToPitch; + EAS_I16 modLFOChanPressToPitch; + EAS_I16 eg2ToPitch; + + /* pad to 4-byte boundary */ + EAS_U16 pad; + + EAS_I8 pan; + EAS_U8 filterQandFlags; + +#ifdef _REVERB + EAS_I16 reverbSend; + EAS_I16 cc91ToReverbSend; +#endif + +#ifdef _CHORUS + EAS_I16 chorusSend; + EAS_I16 cc93ToChorusSend; +#endif +} S_DLS_ARTICULATION; + +/* flags in filterQandFlags + * NOTE: Q is stored in bottom 5 bits + */ +#define FLAG_DLS_VELOCITY_SENSITIVE 0x80 +#define FILTER_Q_MASK 0x1f + +/*---------------------------------------------------------------------------- + * Wavetable region data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_region_tag +{ + S_REGION region; + EAS_I16 tuning; + EAS_I16 gain; + EAS_U32 loopStart; + EAS_U32 loopEnd; + EAS_U16 waveIndex; + EAS_U16 artIndex; +} S_WT_REGION; + +/*---------------------------------------------------------------------------- + * DLS region data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_dls_region_tag +{ + S_WT_REGION wtRegion; + EAS_U8 velLow; + EAS_U8 velHigh; +} S_DLS_REGION; + +/*---------------------------------------------------------------------------- + * FM synthesizer data structures + *---------------------------------------------------------------------------- +*/ +typedef struct s_fm_oper_tag +{ + EAS_I16 tuning; + EAS_U8 attackDecay; + EAS_U8 velocityRelease; + EAS_U8 egKeyScale; + EAS_U8 sustain; + EAS_U8 gain; + EAS_U8 flags; +} S_FM_OPER; + +/* defines for S_FM_OPER.m_nFlags */ +#define FM_OPER_FLAG_MONOTONE 0x01 +#define FM_OPER_FLAG_NO_VIBRATO 0x02 +#define FM_OPER_FLAG_NOISE 0x04 +#define FM_OPER_FLAG_LINEAR_VELOCITY 0x08 + +/* NOTE: The first two structure elements are common with S_WT_REGION + * and we will rely on that in the voice management code and must + * remain there unless the voice management code is revisited. + */ +typedef struct s_fm_region_tag +{ + S_REGION region; + EAS_U8 vibTrem; + EAS_U8 lfoFreqDelay; + EAS_U8 feedback; + EAS_I8 pan; + S_FM_OPER oper[4]; +} S_FM_REGION; + +/*---------------------------------------------------------------------------- + * Common data structures + *---------------------------------------------------------------------------- +*/ + +/*---------------------------------------------------------------------------- + * Program data structure + * Used for individual programs not stored as a complete bank. + *---------------------------------------------------------------------------- +*/ +typedef struct s_program_tag +{ + EAS_U32 locale; + EAS_U16 regionIndex; +} S_PROGRAM; + +/*---------------------------------------------------------------------------- + * Bank data structure + * + * A bank always consists of 128 programs. If a bank is less than 128 + * programs, it should be stored as a spare matrix in the pPrograms + * array. + * + * bankNum: MSB/LSB of MIDI bank select controller + * regionIndex: Index of first region in program + *---------------------------------------------------------------------------- +*/ +typedef struct s_bank_tag +{ + EAS_U16 locale; + EAS_U16 regionIndex[NUM_PROGRAMS_IN_BANK]; +} S_BANK; + + +/* defines for libFormat field + * bits 0-17 are the sample rate + * bit 18 is true if wavetable is present + * bit 19 is true if FM is present + * bit 20 is true if filter is enabled + * bit 21 is sample depth (0 = 8-bits, 1 = 16-bits) + * bits 22-31 are reserved + */ +#define LIBFORMAT_SAMPLE_RATE_MASK 0x0003ffff +#define LIB_FORMAT_TYPE_MASK 0x000c0000 +#define LIB_FORMAT_WAVETABLE 0x00000000 +#define LIB_FORMAT_FM 0x00040000 +#define LIB_FORMAT_HYBRID 0x00080000 +#define LIB_FORMAT_FILTER_ENABLED 0x00100000 +#define LIB_FORMAT_16_BIT_SAMPLES 0x00200000 + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * DLS data structure + * + * pDLSPrograms pointer to array of DLS programs + * pDLSRegions pointer to array of DLS regions + * pDLSArticulations pointer to array of DLS articulations + * pSampleLen pointer to array of sample lengths + * ppSamples pointer to array of sample pointers + * numDLSPrograms number of DLS programs + * numDLSRegions number of DLS regions + * numDLSArticulations number of DLS articulations + * numDLSSamples number of DLS samples + *---------------------------------------------------------------------------- +*/ +typedef struct s_eas_dls_tag +{ + S_PROGRAM *pDLSPrograms; + S_DLS_REGION *pDLSRegions; + S_DLS_ARTICULATION *pDLSArticulations; + EAS_U32 *pDLSSampleLen; + EAS_U32 *pDLSSampleOffsets; + EAS_SAMPLE *pDLSSamples; + EAS_U16 numDLSPrograms; + EAS_U16 numDLSRegions; + EAS_U16 numDLSArticulations; + EAS_U16 numDLSSamples; + EAS_U8 refCount; +} S_DLS; +#endif + +/*---------------------------------------------------------------------------- + * Sound library data structure + * + * pBanks pointer to array of banks + * pPrograms pointer to array of programs + * pWTRegions pointer to array of wavetable regions + * pFMRegions pointer to array of FM regions + * pArticulations pointer to array of articulations + * pSampleLen pointer to array of sample lengths + * ppSamples pointer to array of sample pointers + * numBanks number of banks + * numPrograms number of individual program + * numRegions number of regions + * numArticulations number of articulations + * numSamples number of samples + *---------------------------------------------------------------------------- +*/ +typedef struct s_eas_sndlib_tag +{ + SCNST EAS_U32 identifier; + SCNST EAS_U32 libAttr; + + SCNST S_BANK *pBanks; + SCNST S_PROGRAM *pPrograms; + + SCNST S_WT_REGION *pWTRegions; + SCNST S_ARTICULATION *pArticulations; + SCNST EAS_U32 *pSampleLen; + SCNST EAS_U32 *pSampleOffsets; + SCNST EAS_SAMPLE *pSamples; + + SCNST S_FM_REGION *pFMRegions; + + SCNST EAS_U16 numBanks; + SCNST EAS_U16 numPrograms; + + SCNST EAS_U16 numWTRegions; + SCNST EAS_U16 numArticulations; + SCNST EAS_U16 numSamples; + + SCNST EAS_U16 numFMRegions; +} S_EAS; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synth.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synth.h new file mode 100755 index 0000000..6274b7d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synth.h @@ -0,0 +1,395 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synth.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for synth. + * + * Copyright Sonic Network Inc. 2004, 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 718 $ + * $Date: 2007-06-08 16:43:16 -0700 (Fri, 08 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTH_H +#define _EAS_SYNTH_H + +#include "eas_types.h" +#include "eas_sndlib.h" + +#ifdef _WT_SYNTH +#include "eas_wtsynth.h" +#endif + +#ifdef _FM_SYNTH +#include "eas_fmsynth.h" +#endif + +#ifndef NUM_OUTPUT_CHANNELS +#define NUM_OUTPUT_CHANNELS 2 +#endif + +#ifndef MAX_SYNTH_VOICES +#define MAX_SYNTH_VOICES 64 +#endif + +#ifndef MAX_VIRTUAL_SYNTHESIZERS +#define MAX_VIRTUAL_SYNTHESIZERS 4 +#endif + +/* defines */ +#ifndef NUM_PRIMARY_VOICES +#define NUM_PRIMARY_VOICES MAX_SYNTH_VOICES +#elif !defined(NUM_SECONDARY_VOICES) +#define NUM_SECONDARY_VOICES (MAX_SYNTH_VOICES - NUM_PRIMARY_VOICES) +#endif + +#if defined(EAS_WT_SYNTH) +#define NUM_WT_VOICES MAX_SYNTH_VOICES + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +#define NUM_FM_VOICES MAX_SYNTH_VOICES + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +#define NUM_WT_VOICES MAX_SYNTH_VOICES + +/* wavetable drums and FM melodic on MCU */ +#elif defined(EAS_HYBRID_SYNTH) +#define NUM_WT_VOICES NUM_PRIMARY_VOICES +#define NUM_FM_VOICES NUM_SECONDARY_VOICES + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +#define NUM_WT_VOICES NUM_PRIMARY_VOICES +#define NUM_FM_VOICES NUM_SECONDARY_VOICES + +/* FM synth on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +#define NUM_FM_VOICES MAX_SYNTH_VOICES + +#else +#error "Unrecognized architecture option" +#endif + +#define NUM_SYNTH_CHANNELS 16 + +#define DEFAULT_SYNTH_VOICES MAX_SYNTH_VOICES + +/* use the following values to specify unassigned channels or voices */ +#define UNASSIGNED_SYNTH_CHANNEL NUM_SYNTH_CHANNELS +#define UNASSIGNED_SYNTH_VOICE MAX_SYNTH_VOICES + + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ +#define SYNTH_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << SYNTH_UPDATE_PERIOD_IN_BITS) + +/* stealing weighting factors */ +#define NOTE_AGE_STEAL_WEIGHT 1 +#define NOTE_GAIN_STEAL_WEIGHT 4 +#define CHANNEL_POLY_STEAL_WEIGHT 12 +#define CHANNEL_PRIORITY_STEAL_WEIGHT 2 +#define NOTE_MATCH_PENALTY 128 +#define SYNTH_PRIORITY_WEIGHT 8 + +/* default synth master volume */ +#define DEFAULT_SYNTH_MASTER_VOLUME 0x7fff + +#define DEFAULT_SYNTH_PRIORITY 5 + +/* default tuning values */ +#define DEFAULT_PITCH_BEND_SENSITIVITY 200 /* 2 semitones */ +#define DEFAULT_FINE_PITCH 0 /* 0 cents */ +#define DEFAULT_COARSE_PITCH 0 /* 0 semitones */ + +/* default drum channel is 10, but is internally 9 due to unit offset */ +#define DEFAULT_DRUM_CHANNEL 9 + +/* drum channel can simultaneously play this many voices at most */ +#define DEFAULT_CHANNEL_POLYPHONY_LIMIT 2 + +/* default instrument is acoustic piano */ +#define DEFAULT_MELODY_BANK_MSB 0x79 +#define DEFAULT_RHYTHM_BANK_MSB 0x78 +#define DEFAULT_MELODY_BANK_NUMBER (DEFAULT_MELODY_BANK_MSB << 8) +#define DEFAULT_RHYTHM_BANK_NUMBER (DEFAULT_RHYTHM_BANK_MSB << 8) +#define DEFAULT_SYNTH_PROGRAM_NUMBER 0 + +#define DEFAULT_PITCH_BEND 0x2000 /* 0x2000 == (0x40 << 7) | 0x00 */ +#define DEFAULT_MOD_WHEEL 0 +#define DEFAULT_CHANNEL_VOLUME 0x64 +#define DEFAULT_PAN 0x40 /* decimal 64, center */ + +#ifdef _REVERB +#define DEFAULT_REVERB_SEND 40 /* some reverb */ +#endif + +#ifdef _CHORUS +#define DEFAULT_CHORUS_SEND 0 /* no chorus */ +#endif + +#define DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY 0 /* EAS synth uses a different default */ +#define DEFAULT_FILTER_RESONANCE 0 +#define DEFAULT_EXPRESSION 0x7F + +#define DEFAULT_CHANNEL_PRESSURE 0 + +#define DEFAULT_REGISTERED_PARAM 0x3FFF + +#define DEFAULT_CHANNEL_STATIC_GAIN 0 +#define DEFAULT_CHANNEL_STATIC_PITCH 0 + +#define DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS 50 +#define DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS 50 + +#define DEFAULT_KEY_NUMBER 0x69 +#define DEFAULT_VELOCITY 0x64 +#define DEFAULT_REGION_INDEX 0 +#define DEFAULT_ARTICULATION_INDEX 0 +#define DEFAULT_VOICE_GAIN 0 +#define DEFAULT_AGE 0 +#define DEFAULT_SP_MIDI_PRIORITY 16 + + +/* filter defines */ +#define DEFAULT_FILTER_ZERO 0 +#define FILTER_CUTOFF_MAX_PITCH_CENTS 1919 +#define FILTER_CUTOFF_MIN_PITCH_CENTS -4467 +#define A5_PITCH_OFFSET_IN_CENTS 6900 + +/*------------------------------------ + * S_SYNTH_CHANNEL data structure + *------------------------------------ +*/ + +/* S_SYNTH_CHANNEL.m_nFlags */ +#define CHANNEL_FLAG_SUSTAIN_PEDAL 0x01 +#define CHANNEL_FLAG_MUTE 0x02 +#define CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS 0x04 +#define CHANNEL_FLAG_RHYTHM_CHANNEL 0x08 +#define CHANNEL_FLAG_EXTERNAL_AUDIO 0x10 +#define DEFAULT_CHANNEL_FLAGS 0 + +/* macros for extracting virtual synth and channel numbers */ +#define GET_VSYNTH(a) ((a) >> 4) +#define GET_CHANNEL(a) ((a) & 15) + +typedef struct s_synth_channel_tag +{ + /* use static channel parameters to reduce MIPs */ + /* parameters shared by multiple voices assigned to same channel */ + EAS_I32 staticPitch; /* (pitch bend * pitch sens) + fine pitch */ + EAS_I16 staticGain; /* (CC7 * CC11 * master vol)^2 */ + + EAS_U16 regionIndex; /* index of first region in program */ + + EAS_U16 bankNum; /* play programs from this bank */ + EAS_I16 pitchBend; /* pitch wheel value */ + EAS_I16 pitchBendSensitivity; + EAS_I16 registeredParam; /* currently selected registered param */ + + +#if defined(_FM_SYNTH) + EAS_I16 lfoAmt; /* amount of LFO to apply to voice */ +#endif + + EAS_U8 programNum; /* play this instrument number */ + EAS_U8 modWheel; /* CC1 */ + EAS_U8 volume; /* CC7 */ + EAS_U8 pan; /* CC10 */ + + EAS_U8 expression; /* CC11 */ + + /* the following parameters are controlled by RPNs */ + EAS_I8 finePitch; + EAS_I8 coarsePitch; + + EAS_U8 channelPressure; /* applied to all voices on a given channel */ + + EAS_U8 channelFlags; /* bit field channelFlags for */ + /* CC64, SP-MIDI channel masking */ + + EAS_U8 pool; /* SPMIDI channel voice pool */ + EAS_U8 mip; /* SPMIDI MIP setting */ + +#ifdef _REVERB + EAS_U8 reverbSend; /* CC91 */ +#endif + +#ifdef _CHORUS + EAS_U8 chorusSend; /* CC93 */ +#endif +} S_SYNTH_CHANNEL; + +/*------------------------------------ + * S_SYNTH_VOICE data structure + *------------------------------------ +*/ + +/* S_SYNTH_VOICE.m_nFlags */ +#define VOICE_FLAG_UPDATE_VOICE_PARAMETERS 0x01 +#define VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF 0x02 +#define VOICE_FLAG_DEFER_MIDI_NOTE_OFF 0x04 +#define VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET 0x08 +#define VOICE_FLAG_DEFER_MUTE 0x40 +#define DEFAULT_VOICE_FLAGS 0 + +/* S_SYNTH_VOICE.m_eState */ +typedef enum { + + eVoiceStateFree = 0, + eVoiceStateStart, + eVoiceStatePlay, + eVoiceStateRelease, + eVoiceStateMuting, + eVoiceStateStolen, + eVoiceStateInvalid /* should never be in this state! */ + +} E_VOICE_STATE; +#define DEFAULT_VOICE_STATE eVoiceStateFree + +typedef struct s_synth_voice_tag +{ + +/* These parameters are common to both wavetable and FM + * synthesizers. The voice manager should only access this data. + * Any other data should be manipulated by the code that is + * specific to that synthesizer and reflected back through the + * common state data available here. + */ + EAS_U16 regionIndex; /* index to wave and playback params */ + EAS_I16 gain; /* current gain */ + EAS_U16 age; /* large value means old note */ + EAS_U16 nextRegionIndex; /* index to wave and playback params */ + EAS_U8 voiceState; /* current voice state */ + EAS_U8 voiceFlags; /* misc flags/bit fields */ + EAS_U8 channel; /* this voice plays on this synth channel */ + EAS_U8 note; /* 12 <= key number <= 108 */ + EAS_U8 velocity; /* 0 <= velocity <= 127 */ + EAS_U8 nextChannel; /* play stolen voice on this channel */ + EAS_U8 nextNote; /* 12 <= key number <= 108 */ + EAS_U8 nextVelocity; /* 0 <= velocity <= 127 */ +} S_SYNTH_VOICE; + +/*------------------------------------ + * S_SYNTH data structure + * + * One instance for each MIDI stream + *------------------------------------ +*/ + +/* S_SYNTH.m_nFlags */ +#define SYNTH_FLAG_RESET_IS_REQUESTED 0x01 +#define SYNTH_FLAG_SP_MIDI_ON 0x02 +#define SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS 0x04 +#define SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING 0x08 +#define DEFAULT_SYNTH_FLAGS SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS + +typedef struct s_synth_tag +{ + struct s_eas_data_tag *pEASData; + const S_EAS *pEAS; + +#ifdef DLS_SYNTHESIZER + S_DLS *pDLS; +#endif + +#ifdef EXTERNAL_AUDIO + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc; + EAS_EXT_EVENT_FUNC cbEventFunc; + EAS_VOID_PTR *pExtAudioInstData; +#endif + + S_SYNTH_CHANNEL channels[NUM_SYNTH_CHANNELS]; + EAS_I32 totalNoteCount; + EAS_U16 maxPolyphony; + EAS_U16 numActiveVoices; + EAS_U16 masterVolume; + EAS_U8 channelsByPriority[NUM_SYNTH_CHANNELS]; + EAS_U8 poolCount[NUM_SYNTH_CHANNELS]; + EAS_U8 poolAlloc[NUM_SYNTH_CHANNELS]; + EAS_U8 synthFlags; + EAS_I8 globalTranspose; + EAS_U8 vSynthNum; + EAS_U8 refCount; + EAS_U8 priority; +} S_SYNTH; + +/*------------------------------------ + * S_VOICE_MGR data structure + * + * One instance for each EAS library instance + *------------------------------------ +*/ +typedef struct s_voice_mgr_tag +{ + S_SYNTH *pSynth[MAX_VIRTUAL_SYNTHESIZERS]; + EAS_PCM voiceBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES]; + +#ifdef _FM_SYNTH + EAS_PCM operMixBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES]; + S_FM_VOICE fmVoices[NUM_FM_VOICES]; +#endif + +#ifdef _WT_SYNTH + S_WT_VOICE wtVoices[NUM_WT_VOICES]; +#endif + +#ifdef _REVERB + EAS_PCM reverbSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES]; +#endif + +#ifdef _CHORUS + EAS_PCM chorusSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES]; +#endif + S_SYNTH_VOICE voices[MAX_SYNTH_VOICES]; + + EAS_SNDLIB_HANDLE pGlobalEAS; + +#ifdef DLS_SYNTHESIZER + S_DLS *pGlobalDLS; +#endif + +#ifdef _SPLIT_ARCHITECTURE + EAS_FRAME_BUFFER_HANDLE pFrameBuffer; +#endif + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + EAS_U16 maxPolyphonyPrimary; + EAS_U16 maxPolyphonySecondary; +#endif + + EAS_I32 workload; + EAS_I32 maxWorkLoad; + + EAS_U16 activeVoices; + EAS_U16 maxPolyphony; + + EAS_U16 age; + +/* limits the number of voice starts in a frame for split architecture */ +#ifdef MAX_VOICE_STARTS + EAS_U16 numVoiceStarts; +#endif +} S_VOICE_MGR; + +#endif /* #ifdef _EAS_SYNTH_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synth_protos.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synth_protos.h new file mode 100755 index 0000000..b03af0f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synth_protos.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synth_protos.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for synth. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTH_PROTOS_H +#define _EAS_SYNTH_PROTOS_H + +/* includes */ +#include "eas_data.h" +#include "eas_sndlib.h" + +#ifdef _SPLIT_ARCHITECTURE +typedef struct s_frame_interface_tag +{ + EAS_BOOL (* EAS_CONST pfStartFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer); + EAS_BOOL (* EAS_CONST pfEndFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain); +} S_FRAME_INTERFACE; +#endif + +/* generic synthesizer interface */ +typedef struct +{ + EAS_RESULT (* EAS_CONST pfInitialize)(S_VOICE_MGR *pVoiceMgr); + EAS_RESULT (* EAS_CONST pfStartVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); + EAS_BOOL (* EAS_CONST pfUpdateVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); + void (* EAS_CONST pfReleaseVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); + void (* EAS_CONST pfMuteVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); + void (* EAS_CONST pfSustainPedal)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); + void (* EAS_CONST pfUpdateChannel)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); +} S_SYNTH_INTERFACE; + +#endif + + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synthcfg.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synthcfg.h new file mode 100755 index 0000000..78a4178 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_synthcfg.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synthcfg.h + * + * Contents and purpose: + * Defines for various synth configurations + * + * Copyright Sonic Network Inc. 2004, 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 664 $ + * $Date: 2007-04-25 13:11:22 -0700 (Wed, 25 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTHCFG_H +#define _EAS_SYNTHCFG_H + +#if defined(EAS_WT_SYNTH) +#define _WT_SYNTH + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +#define _FM_SYNTH + +/* wavetable drums and FM melodic on MCU */ +#elif defined(EAS_HYBRID_SYNTH) +#define _WT_SYNTH +#define _FM_SYNTH +#define _SECONDARY_SYNTH +#define _HYBRID_SYNTH + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +#define _WT_SYNTH +#define _SPLIT_ARCHITECTURE + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +#define _WT_SYNTH +#define _FM_SYNTH +#define _SECONDARY_SYNTH +#define _SPLIT_ARCHITECTURE +#define _HYBRID_SYNTH + +/* FM synth on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +#define _FM_SYNTH +#define _SPLIT_ARCHITECTURE + +#else +#error "Unrecognized architecture option" +#endif + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_vm_protos.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_vm_protos.h new file mode 100755 index 0000000..20f7c09 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_vm_protos.h @@ -0,0 +1,1086 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_vm_protos.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for voice manager. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 736 $ + * $Date: 2007-06-22 13:51:24 -0700 (Fri, 22 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_VM_PROTOS_H +#define _EAS_VM_PROTOS_H + +// includes +#include "eas_data.h" +#include "eas_sndlib.h" + +/*---------------------------------------------------------------------------- + * VMInitialize() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitialize (S_EAS_DATA *pEASData); + +/*---------------------------------------------------------------------------- + * VMInitMIDI() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitMIDI (S_EAS_DATA *pEASData, S_SYNTH **ppSynth); + +/*---------------------------------------------------------------------------- + * VMInitializeAllChannels() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllChannels (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMResetControllers() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMResetControllers (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMInitMIPTable() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the SP-MIDI MIP table + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * mute - EAS_FALSE to unmute channels, EAS_TRUE to mute + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitMIPTable (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMSetMIPEntry() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the priority and MIP level for a MIDI channel + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * channel - MIDI channel number + * priority - priority (0-15 with 0 = highest priority) + * mip - maximum instantaneous polyphony + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetMIPEntry (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 priority, EAS_U8 mip); + +/*---------------------------------------------------------------------------- + * VMUpdateMIPTable() + *---------------------------------------------------------------------------- + * Purpose: + * This routine is called when the polyphony count in the synthesizer changes + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMUpdateMIPTable (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMInitializeAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllVoices (S_VOICE_MGR *pVoiceMgr, EAS_INT vSynthNum); + +/*---------------------------------------------------------------------------- + * VMStartNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to play the requested note on the requested + * channel if possible. + * + * Inputs: + * nChannel - the MIDI channel + * nKeyNumber - the MIDI key number for this note + * nNoteVelocity - the key velocity for this note + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMStartNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity); + +/*---------------------------------------------------------------------------- + * VMCheckKeyGroup() + *---------------------------------------------------------------------------- + * Purpose: + * If the note that we've been asked to start is in the same key group as + * any currently playing notes, then we must shut down the currently playing + * note in the same key group and then start the newly requested note. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nRegionIndex - calling routine finds this index and gives to us + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * + * Side Effects: + * gsSynthObject.m_sVoice[free voice num].m_nKeyNumber may be assigned + * gsSynthObject.m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +void VMCheckKeyGroup (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U16 keyGroup, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMCheckPolyphonyLimiting() + *---------------------------------------------------------------------------- + * Purpose: + * We only play at most 2 of the same note on a MIDI channel. + * E.g., if we are asked to start note 36, and there are already two voices + * that are playing note 36, then we must steal the voice playing + * the oldest note 36 and use that stolen voice to play the new note 36. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * * + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber may be assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckPolyphonyLimiting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to end the requested note on the requested + * channel. + * + * Inputs: + * nChannel - the MIDI channel + * nKeyNumber - the key number of the note to stop + * nNoteVelocity - the note-off velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sVoice[free voice num].m_nSynthChannel may be assigned + * gsSynthObject.m_sVoice[free voice num].m_nKeyNumber is assigned + * gsSynthObject.m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +void VMStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 key, EAS_U8 velocity); + +/*---------------------------------------------------------------------------- + * VMFindAvailableVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Find an available voice and return the voice number if available. + * + * Inputs: + * pnVoiceNumber - really an output, see below + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - returns the voice number of available voice if found + * success - if there is an available voice + * failure - otherwise + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindAvailableVoice (S_VOICE_MGR *pVoiceMgr, EAS_INT *pVoiceNumber, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMStealVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Steal a voice and return the voice number + * + * Stealing algorithm: steal the best choice with minimal work, taking into + * account SP-Midi channel priorities and polyphony allocation. + * + * In one pass through all the voices, figure out which voice to steal + * taking into account a number of different factors: + * Priority of the voice's MIDI channel + * Number of voices over the polyphony allocation for voice's MIDI channel + * Amplitude of the voice + * Note age + * Key velocity (for voices that haven't been started yet) + * If any matching notes are found + * + * Inputs: + * nChannel - the channel that this voice wants to be started on + * nKeyNumber - the key number for this new voice + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - voice stolen + * EAS_RESULT EAS_SUCCESS - always successful + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMStealVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_INT *pVoiceNumber, EAS_U8 channel, EAS_U8 note, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMAddSamples() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize the requested number of samples. + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMAddSamples (S_VOICE_MGR *pVoiceMgr, EAS_I32 *pMixBuffer, EAS_I32 numSamplesToAdd); + +/*---------------------------------------------------------------------------- + * VMProgramChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the instrument (program) for the given channel. + * + * Depending on the program number, and the bank selected for this channel, the + * program may be in ROM, RAM (from SMAF or CMX related RAM wavetable), or + * Alternate wavetable (from mobile DLS or other DLS file) + * + * This function figures out what wavetable should be used, and sets it up as the + * wavetable to use for this channel. Also the channel may switch from a melodic + * channel to a rhythm channel, or vice versa. + * + * Inputs: + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nProgramNumber is likely changed + * gsSynthObject.m_sChannel[nChannel].m_psEAS may be changed + * gsSynthObject.m_sChannel[nChannel].m_bRhythmChannel may be changed + * + *---------------------------------------------------------------------------- +*/ +void VMProgramChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 program); + +/*---------------------------------------------------------------------------- + * VMChannelPressure() + *---------------------------------------------------------------------------- + * Purpose: + * Change the channel pressure for the given channel + * + * Inputs: + * nChannel - the MIDI channel + * nVelocity - the channel pressure value + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nChannelPressure is updated + *---------------------------------------------------------------------------- +*/ +void VMChannelPressure (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMPitchBend() + *---------------------------------------------------------------------------- + * Purpose: + * Change the pitch wheel value for the given channel. + * This routine constructs the proper 14-bit argument when the calling routine + * passes the pitch LSB and MSB. + * + * Note: some midi disassemblers display a bipolar pitch bend value. + * We can display the bipolar value using + * if m_nPitchBend >= 0x2000 + * bipolar pitch bend = postive (m_nPitchBend - 0x2000) + * else + * bipolar pitch bend = negative (0x2000 - m_nPitchBend) + * + * Inputs: + * nChannel - the MIDI channel + * nPitchLSB - the LSB byte from the pitch bend message + * nPitchMSB - the MSB byte from the message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nPitchBend is changed + * + *---------------------------------------------------------------------------- +*/ +void VMPitchBend (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 pitchLSB, EAS_U8 pitchMSB); + +/*---------------------------------------------------------------------------- + * VMControlChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the controller (or mode) for the given channel. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the controller number + * nControlValue - the controller number for this control change + * nControlValue - the value for this control change + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel] controller is changed + * + *---------------------------------------------------------------------------- +*/ +void VMControlChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMUpdateRPNStateMachine() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when we want to parse a stream of RPN messages. + * NOTE: The synth has only one set of global RPN data instead of RPN data + * per channel. + * So actually, we don't really need to look at the nChannel parameter, + * but we pass it to facilitate future upgrades. Furthermore, we only + * support RPN0 (pitch bend sensitivity), RPN1 (fine tuning) and + * RPN2 (coarse tuning). Any other RPNs are rejected. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the RPN controller number + * nControlValue - the value for this control change + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * gsSynthObject.m_RPN0 (or m_RPN1 or m_RPN2) may be updated if the + * proper RPN message sequence is parsed. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMUpdateRPNStateMachine (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMUpdateStaticChannelParameters() + *---------------------------------------------------------------------------- + * Purpose: + * Update all of the static channel parameters for channels that have had + * a controller change values + * Or if the synth has signalled that all channels must forcibly + * be updated + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * none + * + * Side Effects: + * - psSynthObject->m_sChannel[].m_nStaticGain and m_nStaticPitch + * are updated for channels whose controller values have changed + * or if the synth has signalled that all channels must forcibly + * be updated + *---------------------------------------------------------------------------- +*/ +void VMUpdateStaticChannelParameters (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReleaseAllDeferredNoteOffs() + *---------------------------------------------------------------------------- + * Purpose: + * Call this functin when the sustain flag is presently set but + * we are now transitioning from damper pedal on to + * damper pedal off. This means all notes in this channel + * that received a note off while the damper pedal was on, and + * had their note-off requests deferred, should now proceed to + * the release state. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllDeferredNoteOffs (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMCatchNotesForSustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when the sustain flag is presently clear and + * the damper pedal is off and we are transitioning from damper pedal OFF to + * damper pedal ON. Currently sounding notes should be left + * unchanged. However, we should try to "catch" notes if possible. + * If any notes have levels >= sustain level, catch them, + * otherwise, let them continue to release. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * psVoice->m_sEG1.m_eState = eEnvelopeStateSustainPedal + *---------------------------------------------------------------------------- +*/ +void VMCatchNotesForSustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMUpdateAllNotesAge() + *---------------------------------------------------------------------------- + * Purpose: + * Increment the note age for all voices older than the age of the voice + * that is stopping, effectively making the voices "younger". + * + * Inputs: + * nAge - age of voice that is going away + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * m_nAge for some voices is incremented + *---------------------------------------------------------------------------- +*/ +void VMUpdateAllNotesAge (S_VOICE_MGR *pVoiceMgr, EAS_U16 nAge); + +/*---------------------------------------------------------------------------- + * VMFindRegionIndex() + *---------------------------------------------------------------------------- + * Purpose: + * Find the region index for the given instrument using the midi key number + * and the RPN2 (coarse tuning) value. By using RPN2 as part of the + * region selection process, we reduce the amount a given sample has + * to be transposed by selecting the closest recorded root instead. + * + * Inputs: + * nChannel - current channel for this note + * nKeyNumber - current midi note number + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnRegionIndex - valid only if we returned success + * success if we found the region index number, otherwise + * failure + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindRegionIndex (S_VOICE_MGR *pVoiceMgr, EAS_U8 channel, EAS_U8 note, EAS_U16 *pRegionIndex); + +/*---------------------------------------------------------------------------- + * VMIncRefCount() + *---------------------------------------------------------------------------- + * Increment reference count for virtual synth + *---------------------------------------------------------------------------- +*/ +void VMIncRefCount (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReset() + *---------------------------------------------------------------------------- + * Purpose: + * We call this routine to start the process of reseting the synth. + * This routine sets a flag for the entire synth indicating that we want + * to reset. + * We also force all voices to mute quickly. + * However, we do not actually perform any synthesis in this routine. That + * is, we do not ramp the voices down from this routine, but instead, we + * let the "regular" synth processing steps take care of adding the ramp + * down samples to the output buffer. After we are sure that all voices + * have completed ramping down, we continue the process of resetting the + * synth (from another routine). + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - set a flag (in gsSynthObject.m_nFlags) indicating synth reset requested. + * - force all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMReset (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_BOOL force); + +/*---------------------------------------------------------------------------- + * VMMuteAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this in an emergency reset situation. + * This forces all voices to mute quickly. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMMuteVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum); +void VMMuteAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReleaseAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this after we've encountered the end of the Midi file. + * This ensures all voice are either in release (because we received their + * note off already) or forces them to mute quickly. + * We use this as a safety to prevent bad midi files from playing forever. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to release or mute + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMAllNotesOff() + *---------------------------------------------------------------------------- + * Purpose: + * Quickly mute all notes on the given channel. + * + * Inputs: + * nChannel - quickly turn off all notes on this channel + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices on this channel to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMAllNotesOff (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMDeferredStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Stop the notes that had deferred note-off requests. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None. + * + * Side Effects: + * voices that have had deferred note-off requests are now put into release + * gsSynthObject.m_sVoice[i].m_nFlags has the VOICE_FLAG_DEFER_MIDI_NOTE_OFF + * cleared + *---------------------------------------------------------------------------- +*/ +void VMDeferredStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMSetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * VMGetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * VMSetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth polyphony. 0 = no limit (i.e. can use + * all available voices). + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * VMGetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pSynth pointer to virtual synth + * pPolyphonyCount pointer to variable to receive data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * VMSetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * priority new priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 priority); + +/*---------------------------------------------------------------------------- + * VMGetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPriority pointer to variable to hold priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPriority); + +/*---------------------------------------------------------------------------- + * VMSetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for this sequence + * + * Inputs: + * nSynthVolume - the desired master volume + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +void VMSetVolume (S_SYNTH *pSynth, EAS_U16 masterVolume); + +/*---------------------------------------------------------------------------- + * VMSetPitchBendRange() + *---------------------------------------------------------------------------- + * Set the pitch bend range for the given channel. + *---------------------------------------------------------------------------- +*/ +void VMSetPitchBendRange (S_SYNTH *pSynth, EAS_INT channel, EAS_I16 pitchBendRange); + +/*---------------------------------------------------------------------------- + * VMSetEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the pointer to the sound library + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalEASLib (S_VOICE_MGR *pVoiceMgr, EAS_SNDLIB_HANDLE pEAS); +EAS_RESULT VMSetEASLib (S_SYNTH *pSynth, EAS_SNDLIB_HANDLE pEAS); + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMSetDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the pointer to the sound library + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalDLSLib (EAS_DATA_HANDLE pEASData, EAS_DLSLIB_HANDLE pDLS); +EAS_RESULT VMSetDLSLib (S_SYNTH *pSynth, EAS_DLSLIB_HANDLE pDLS); +#endif + +/*---------------------------------------------------------------------------- + * VMSetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * transposition - transpose amount (+/-12) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetTranposition (S_SYNTH *pSynth, EAS_I32 transposition); + +/*---------------------------------------------------------------------------- + * VMGetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMGetTranposition (S_SYNTH *pSynth, EAS_I32 *pTransposition); + +/*---------------------------------------------------------------------------- + * VMGetNoteCount() + *---------------------------------------------------------------------------- +* Returns the total note count +*---------------------------------------------------------------------------- +*/ +EAS_I32 VMGetNoteCount (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMRender() + *---------------------------------------------------------------------------- + * Purpose: + * This routine renders a frame of audio + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pVoicesRendered - number of voices rendered this frame + * + * Side Effects: + * sets psMidiObject->m_nMaxWorkloadPerFrame + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMRender (S_VOICE_MGR *pVoiceMgr, EAS_I32 numSamples, EAS_I32 *pMixBuffer, EAS_I32 *pVoicesRendered); + +/*---------------------------------------------------------------------------- + * VMInitWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Clears the workload counter + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitWorkload (S_VOICE_MGR *pVoiceMgr); + +/*---------------------------------------------------------------------------- + * VMSetWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the max workload for a single frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetWorkload (S_VOICE_MGR *pVoiceMgr, EAS_I32 maxWorkLoad); + +/*---------------------------------------------------------------------------- + * VMCheckWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Checks to see if work load has been exceeded on this frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckWorkload (S_VOICE_MGR *pVoiceMgr); + +/*---------------------------------------------------------------------------- + * VMActiveVoices() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the number of active voices in the synthesizer. + * + * Inputs: + * pEASData - pointer to instance data + * + * Outputs: + * Returns the number of active voices + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMActiveVoices (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMMIDIShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMMIDIShutdown (S_EAS_DATA *pEASData, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMShutdown (S_EAS_DATA *pEASData); + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Register a callback for external audio processing + *---------------------------------------------------------------------------- +*/ +void VMRegExtAudioCallback (S_SYNTH *pSynth, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc); + +/*---------------------------------------------------------------------------- + * VMGetMIDIControllers() + *---------------------------------------------------------------------------- + * Returns the MIDI controller values on the specified channel + *---------------------------------------------------------------------------- +*/ +void VMGetMIDIControllers (S_SYNTH *pSynth, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl); +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * VMStartFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Starts an audio frame + * + * Inputs: + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMStartFrame (S_EAS_DATA *pEASData); + +/*---------------------------------------------------------------------------- + * VMEndFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Stops an audio frame + * + * Inputs: + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMEndFrame (S_EAS_DATA *pEASData); +#endif + +#endif /* #ifdef _EAS_VM_PROTOS_H */ + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_voicemgt.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_voicemgt.c new file mode 100755 index 0000000..ab0b776 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_voicemgt.c @@ -0,0 +1,3971 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_voicemgt.c + * + * Contents and purpose: + * Implements the synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 794 $ + * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* includes */ +#include "eas.h" +#include "eas_data.h" +#include "eas_config.h" +#include "eas_report.h" +#include "eas_midictrl.h" +#include "eas_host.h" +#include "eas_synth_protos.h" +#include "eas_vm_protos.h" + +#ifdef DLS_SYNTHESIZER +#include "eas_mdls.h" +#endif + +// #define _DEBUG_VM + +/* some defines for workload */ +#define WORKLOAD_AMOUNT_SMALL_INCREMENT 5 +#define WORKLOAD_AMOUNT_START_NOTE 10 +#define WORKLOAD_AMOUNT_STOP_NOTE 10 +#define WORKLOAD_AMOUNT_KEY_GROUP 10 +#define WORKLOAD_AMOUNT_POLY_LIMIT 10 + +/* pointer to base sound library */ +extern S_EAS easSoundLib; + +#ifdef TEST_HARNESS +extern S_EAS easTestLib; +EAS_SNDLIB_HANDLE VMGetLibHandle(EAS_INT libNum) +{ + switch (libNum) + { + case 0: + return &easSoundLib; +#ifdef _WT_SYNTH + case 1: + return &easTestLib; +#endif + default: + return NULL; + } +} +#endif + +/* pointer to synthesizer interface(s) */ +#ifdef _WT_SYNTH +extern const S_SYNTH_INTERFACE wtSynth; +#endif + +#ifdef _FM_SYNTH +extern const S_SYNTH_INTERFACE fmSynth; +#endif + +typedef S_SYNTH_INTERFACE *S_SYNTH_INTERFACE_HANDLE; + +/* wavetable on MCU */ +#if defined(EAS_WT_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &fmSynth; + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_HYBRID_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +const S_SYNTH_INTERFACE *const pSecondarySynth = &fmSynth; + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +extern const S_FRAME_INTERFACE wtFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &wtFrameInterface; + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +const S_SYNTH_INTERFACE *const pSecondarySynth = &fmSynth; +extern const S_FRAME_INTERFACE fmFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &fmFrameInterface; + +/* FM on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &fmSynth; +extern const S_FRAME_INTERFACE fmFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &fmFrameInterface; + +#else +#error "Undefined architecture option" +#endif + +/*---------------------------------------------------------------------------- + * inline functions + *---------------------------------------------------------------------------- +*/ +EAS_INLINE const S_REGION* GetRegionPtr (S_SYNTH *pSynth, EAS_U16 regionIndex) +{ +#if defined(DLS_SYNTHESIZER) + if (regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + return &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK].wtRegion.region; +#endif +#if defined(_HYBRID_SYNTH) + if (regionIndex & FLAG_RGN_IDX_FM_SYNTH) + return &pSynth->pEAS->pFMRegions[regionIndex & REGION_INDEX_MASK].region; + else + return &pSynth->pEAS->pWTRegions[regionIndex].region; +#elif defined(_WT_SYNTH) + return &pSynth->pEAS->pWTRegions[regionIndex].region; +#elif defined(_FM_SYNTH) + return &pSynth->pEAS->pFMRegions[regionIndex].region; +#endif +} + +/*lint -esym(715, voiceNum) used in some implementation */ +EAS_INLINE const S_SYNTH_INTERFACE* GetSynthPtr (EAS_INT voiceNum) +{ +#if defined(_HYBRID_SYNTH) + if (voiceNum < NUM_PRIMARY_VOICES) + return pPrimarySynth; + else + return pSecondarySynth; +#else + return pPrimarySynth; +#endif +} + +EAS_INLINE EAS_INT GetAdjustedVoiceNum (EAS_INT voiceNum) +{ +#if defined(_HYBRID_SYNTH) + if (voiceNum >= NUM_PRIMARY_VOICES) + return voiceNum - NUM_PRIMARY_VOICES; +#endif + return voiceNum; +} + +EAS_INLINE EAS_U8 VSynthToChannel (S_SYNTH *pSynth, EAS_U8 channel) +{ + /*lint -e{734} synthNum is always 0-15 */ + return channel | (pSynth->vSynthNum << 4); +} + +/*---------------------------------------------------------------------------- + * InitVoice() + *---------------------------------------------------------------------------- + * Initialize a synthesizer voice + *---------------------------------------------------------------------------- +*/ +void InitVoice (S_SYNTH_VOICE *pVoice) +{ + pVoice->channel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->nextChannel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->note = pVoice->nextNote = DEFAULT_KEY_NUMBER; + pVoice->velocity = pVoice->nextVelocity = DEFAULT_VELOCITY; + pVoice->regionIndex = DEFAULT_REGION_INDEX; + pVoice->age = DEFAULT_AGE; + pVoice->voiceFlags = DEFAULT_VOICE_FLAGS; + pVoice->voiceState = DEFAULT_VOICE_STATE; +} + +/*---------------------------------------------------------------------------- + * IncVoicePoolCount() + *---------------------------------------------------------------------------- + * Updates the voice pool count when a voice changes state + *---------------------------------------------------------------------------- +*/ +static void IncVoicePoolCount (S_VOICE_MGR *pVoiceMgr, S_SYNTH_VOICE *pVoice) +{ + S_SYNTH *pSynth; + EAS_INT pool; + + /* ignore muting voices */ + if (pVoice->voiceState == eVoiceStateMuting) + return; + + if (pVoice->voiceState == eVoiceStateStolen) + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool; + } + else + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->channel)].pool; + } + + pSynth->poolCount[pool]++; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IncVoicePoolCount: Synth=%d pool=%d\n", pSynth->vSynthNum, pool); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * DecVoicePoolCount() + *---------------------------------------------------------------------------- + * Updates the voice pool count when a voice changes state + *---------------------------------------------------------------------------- +*/ +static void DecVoicePoolCount (S_VOICE_MGR *pVoiceMgr, S_SYNTH_VOICE *pVoice) +{ + S_SYNTH *pSynth; + EAS_INT pool; + + /* ignore muting voices */ + if (pVoice->voiceState == eVoiceStateMuting) + return; + + if (pVoice->voiceState == eVoiceStateStolen) + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool; + } + else + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->channel)].pool; + } + + pSynth->poolCount[pool]--; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "DecVoicePoolCount: Synth=%d pool=%d\n", pSynth->vSynthNum, pool); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * VMInitialize() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitialize (S_EAS_DATA *pEASData) +{ + S_VOICE_MGR *pVoiceMgr; + EAS_INT i; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pVoiceMgr = EAS_CMEnumData(EAS_CM_SYNTH_DATA); + else + pVoiceMgr = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_VOICE_MGR)); + if (!pVoiceMgr) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitialize: Failed to allocate synthesizer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pVoiceMgr, 0, sizeof(S_VOICE_MGR)); + + /* initialize non-zero variables */ + pVoiceMgr->pGlobalEAS = (S_EAS*) &easSoundLib; + pVoiceMgr->maxPolyphony = (EAS_U16) MAX_SYNTH_VOICES; + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + pVoiceMgr->maxPolyphonyPrimary = NUM_PRIMARY_VOICES; + pVoiceMgr->maxPolyphonySecondary = NUM_SECONDARY_VOICES; +#endif + + /* set max workload to zero */ + pVoiceMgr->maxWorkLoad = 0; + + /* initialize the voice manager parameters */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + InitVoice(&pVoiceMgr->voices[i]); + + /* initialize the synth */ + /*lint -e{522} return unused at this time */ + pPrimarySynth->pfInitialize(pVoiceMgr); + + /* initialize the off-chip synth */ +#ifdef _HYBRID_SYNTH + /*lint -e{522} return unused at this time */ + pSecondarySynth->pfInitialize(pVoiceMgr); +#endif + + pEASData->pVoiceMgr = pVoiceMgr; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMInitMIDI() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitMIDI (S_EAS_DATA *pEASData, S_SYNTH **ppSynth) +{ + EAS_RESULT result; + S_SYNTH *pSynth; + EAS_INT virtualSynthNum; + + *ppSynth = NULL; + + /* static memory model only allows one synth */ + if (pEASData->staticMemoryModel) + { + if (pEASData->pVoiceMgr->pSynth[0] != NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: No virtual synthesizer support for static memory model\n"); */ } + return EAS_ERROR_NO_VIRTUAL_SYNTHESIZER; + } + + /* check Configuration Module for data allocation */ + pSynth = EAS_CMEnumData(EAS_CM_MIDI_DATA); + virtualSynthNum = 0; + } + + /* dynamic memory model */ + else + { + for (virtualSynthNum = 0; virtualSynthNum < MAX_VIRTUAL_SYNTHESIZERS; virtualSynthNum++) + if (pEASData->pVoiceMgr->pSynth[virtualSynthNum] == NULL) + break; + if (virtualSynthNum == MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: Exceeded number of active virtual synthesizers"); */ } + return EAS_ERROR_NO_VIRTUAL_SYNTHESIZER; + } + pSynth = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SYNTH)); + } + + /* make sure we have a valid memory pointer */ + if (pSynth == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: Failed to allocate synthesizer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pSynth, 0, sizeof(S_SYNTH)); + + /* set the sound library pointer */ + if ((result = VMSetEASLib(pSynth, pEASData->pVoiceMgr->pGlobalEAS)) != EAS_SUCCESS) + { + VMMIDIShutdown(pEASData, pSynth); + return result; + } + + /* link in DLS bank if downloaded */ +#ifdef DLS_SYNTHESIZER + if (pEASData->pVoiceMgr->pGlobalDLS) + { + pSynth->pDLS = pEASData->pVoiceMgr->pGlobalDLS; + DLSAddRef(pSynth->pDLS); + } +#endif + + /* initialize MIDI state variables */ + pSynth->synthFlags = DEFAULT_SYNTH_FLAGS; + pSynth->masterVolume = DEFAULT_SYNTH_MASTER_VOLUME; + pSynth->refCount = 1; + pSynth->priority = DEFAULT_SYNTH_PRIORITY; + pSynth->poolAlloc[0] = (EAS_U8) pEASData->pVoiceMgr->maxPolyphony; + + VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); + + pSynth->vSynthNum = (EAS_U8) virtualSynthNum; + pEASData->pVoiceMgr->pSynth[virtualSynthNum] = pSynth; + + *ppSynth = pSynth; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMIncRefCount() + *---------------------------------------------------------------------------- + * Increment reference count for virtual synth + *---------------------------------------------------------------------------- +*/ +void VMIncRefCount (S_SYNTH *pSynth) +{ + pSynth->refCount++; +} + +/*---------------------------------------------------------------------------- + * VMReset() + *---------------------------------------------------------------------------- + * Purpose: + * We call this routine to start the process of reseting the synth. + * This routine sets a flag for the entire synth indicating that we want + * to reset. + * We also force all voices to mute quickly. + * However, we do not actually perform any synthesis in this routine. That + * is, we do not ramp the voices down from this routine, but instead, we + * let the "regular" synth processing steps take care of adding the ramp + * down samples to the output buffer. After we are sure that all voices + * have completed ramping down, we continue the process of resetting the + * synth (from another routine). + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * force - force reset even if voices are active + * + * Outputs: + * + * Side Effects: + * - set a flag (in psSynthObject->m_nFlags) indicating synth reset requested. + * - force all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMReset (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_BOOL force) +{ + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReset: request to reset synth. Force = %d\n", force); */ } +#endif + + /* force voices to off state - may cause audio artifacts */ + if (force) + { + pVoiceMgr->activeVoices -= pSynth->numActiveVoices; + pSynth->numActiveVoices = 0; + VMInitializeAllVoices(pVoiceMgr, pSynth->vSynthNum); + } + else + VMMuteAllVoices(pVoiceMgr, pSynth); + + /* don't reset if voices are still playing */ + if (pSynth->numActiveVoices == 0) + { + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReset: complete the reset process\n"); */ } +#endif + + VMInitializeAllChannels(pVoiceMgr, pSynth); + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + pSynth->poolCount[i] = 0; + + /* set polyphony */ + if (pSynth->maxPolyphony < pVoiceMgr->maxPolyphony) + pSynth->poolAlloc[0] = (EAS_U8) pVoiceMgr->maxPolyphony; + else + pSynth->poolAlloc[0] = (EAS_U8) pSynth->maxPolyphony; + + /* clear reset flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_RESET_IS_REQUESTED; + } + + /* handle reset after voices are muted */ + else + pSynth->synthFlags |= SYNTH_FLAG_RESET_IS_REQUESTED; +} + +/*---------------------------------------------------------------------------- + * VMInitializeAllChannels() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllChannels (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + + VMResetControllers(pSynth); + + /* init each channel */ + pChannel = pSynth->channels; + + for (i = 0; i < NUM_SYNTH_CHANNELS; i++, pChannel++) + { + pChannel->channelFlags = DEFAULT_CHANNEL_FLAGS; + pChannel->staticGain = DEFAULT_CHANNEL_STATIC_GAIN; + pChannel->staticPitch = DEFAULT_CHANNEL_STATIC_PITCH; + pChannel->pool = 0; + + /* the drum channel needs a different init */ + if (i == DEFAULT_DRUM_CHANNEL) + { + pChannel->bankNum = DEFAULT_RHYTHM_BANK_NUMBER; + pChannel->channelFlags |= CHANNEL_FLAG_RHYTHM_CHANNEL; + } + else + pChannel->bankNum = DEFAULT_MELODY_BANK_NUMBER; + + VMProgramChange(pVoiceMgr, pSynth, (EAS_U8) i, DEFAULT_SYNTH_PROGRAM_NUMBER); + } + +} + +/*---------------------------------------------------------------------------- + * VMResetControllers() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMResetControllers (S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + + pChannel = pSynth->channels; + + for (i = 0; i < NUM_SYNTH_CHANNELS; i++, pChannel++) + { + pChannel->pitchBend = DEFAULT_PITCH_BEND; + pChannel->modWheel = DEFAULT_MOD_WHEEL; + pChannel->volume = DEFAULT_CHANNEL_VOLUME; + pChannel->pan = DEFAULT_PAN; + pChannel->expression = DEFAULT_EXPRESSION; + +#ifdef _REVERB + pSynth->channels[i].reverbSend = DEFAULT_REVERB_SEND; +#endif + +#ifdef _CHORUS + pSynth->channels[i].chorusSend = DEFAULT_CHORUS_SEND; +#endif + + pChannel->channelPressure = DEFAULT_CHANNEL_PRESSURE; + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + pChannel->pitchBendSensitivity = DEFAULT_PITCH_BEND_SENSITIVITY; + pChannel->finePitch = DEFAULT_FINE_PITCH; + pChannel->coarsePitch = DEFAULT_COARSE_PITCH; + + /* update all voices on this channel */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + } +} + +/*---------------------------------------------------------------------------- + * VMInitializeAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllVoices (S_VOICE_MGR *pVoiceMgr, EAS_INT vSynthNum) +{ + EAS_INT i; + + /* initialize the voice manager parameters */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + if (pVoiceMgr->voices[i].voiceState != eVoiceStateStolen) + { + if (GET_VSYNTH(pVoiceMgr->voices[i].channel) == vSynthNum) + InitVoice(&pVoiceMgr->voices[i]); + } + else + { + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == vSynthNum) + InitVoice(&pVoiceMgr->voices[i]); + } + } +} + +/*---------------------------------------------------------------------------- + * VMMuteVoice() + *---------------------------------------------------------------------------- + * Mute the selected voice + *---------------------------------------------------------------------------- +*/ +void VMMuteVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum) +{ + S_SYNTH *pSynth; + S_SYNTH_VOICE *pVoice; + + /* take no action if voice is already muted */ + pVoice = &pVoiceMgr->voices[voiceNum]; + if ((pVoice->voiceState == eVoiceStateMuting) || (pVoice->voiceState == eVoiceStateFree)) + return; + + /* one less voice in pool */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pSynth, pVoice, GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateMuting; + +} + +/*---------------------------------------------------------------------------- + * VMReleaseVoice() + *---------------------------------------------------------------------------- + * Release the selected voice + *---------------------------------------------------------------------------- +*/ +void VMReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 voiceNum) +{ + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + + /* take no action if voice is already free, muting, or releasing */ + if (( pVoice->voiceState == eVoiceStateMuting) || + (pVoice->voiceState == eVoiceStateFree) || + (pVoice->voiceState == eVoiceStateRelease)) + return; + + /* stolen voices should just be muted */ + if (pVoice->voiceState == eVoiceStateStolen) + VMMuteVoice(pVoiceMgr, voiceNum); + + /* release this voice */ + GetSynthPtr(voiceNum)->pfReleaseVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateRelease; +} + +/*---------------------------------------------------------------------------- + * VMInitMIPTable() + *---------------------------------------------------------------------------- + * Initialize the SP-MIDI MIP table in preparation for receiving MIP message + *---------------------------------------------------------------------------- +*/ +void VMInitMIPTable (S_SYNTH *pSynth) +{ + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMInitMIPTable\n"); */ } +#endif + + /* clear SP-MIDI flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_SP_MIDI_ON; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + pSynth->channels[i].pool = 0; + pSynth->channels[i].mip = 0; + } +} + +/*---------------------------------------------------------------------------- + * VMSetMIPEntry() + *---------------------------------------------------------------------------- + * Sets the priority and MIP level for a MIDI channel + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMSetMIPEntry (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 priority, EAS_U8 mip) +{ + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMSetMIPEntry: channel=%d, priority=%d, MIP=%d\n", channel, priority, mip); */ } +#endif + + /* save data for use by MIP message processing */ + if (priority < NUM_SYNTH_CHANNELS) + { + pSynth->channels[channel].pool = priority; + pSynth->channels[channel].mip = mip; + } +} + +/*---------------------------------------------------------------------------- + * VMMIPUpdateChannelMuting() + *---------------------------------------------------------------------------- + * This routine is called after an SP-MIDI message is received and + * any time the allocated polyphony changes. It mutes or unmutes + * channels based on polyphony. + *---------------------------------------------------------------------------- +*/ +void VMMIPUpdateChannelMuting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + EAS_INT maxPolyphony; + EAS_INT channel; + EAS_INT vSynthNum; + EAS_INT pool; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateMIPTable\n"); */ } +#endif + + /* determine max polyphony */ + if (pSynth->maxPolyphony) + maxPolyphony = pSynth->maxPolyphony; + else + maxPolyphony = pVoiceMgr->maxPolyphony; + + /* process channels */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + + /* channel must be in MIP message and must meet allocation target */ + if ((pSynth->channels[i].mip != 0) && (pSynth->channels[i].mip <= maxPolyphony)) + pSynth->channels[i].channelFlags &= ~CHANNEL_FLAG_MUTE; + else + pSynth->channels[i].channelFlags |= CHANNEL_FLAG_MUTE; + + /* reset voice pool count */ + pSynth->poolCount[i] = 0; + } + + /* mute any voices on muted channels, and count unmuted voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + /* ignore free voices */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateFree) + continue; + + /* get channel and virtual synth */ + if (pVoiceMgr->voices[i].voiceState != eVoiceStateStolen) + { + vSynthNum = GET_VSYNTH(pVoiceMgr->voices[i].channel); + channel = GET_CHANNEL(pVoiceMgr->voices[i].channel); + } + else + { + vSynthNum = GET_VSYNTH(pVoiceMgr->voices[i].nextChannel); + channel = GET_CHANNEL(pVoiceMgr->voices[i].nextChannel); + } + + /* ignore voices on other synths */ + if (vSynthNum != pSynth->vSynthNum) + continue; + + /* count voices */ + pool = pSynth->channels[channel].pool; + + /* deal with muted channels */ + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_MUTE) + { + /* mute stolen voices scheduled to play on this channel */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateStolen) + pVoiceMgr->voices[i].voiceState = eVoiceStateMuting; + + /* release voices that aren't already muting */ + else if (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting) + { + VMReleaseVoice(pVoiceMgr, pSynth, i); + pSynth->poolCount[pool]++; + } + } + + /* not muted, count this voice */ + else + pSynth->poolCount[pool]++; + } +} + +/*---------------------------------------------------------------------------- + * VMUpdateMIPTable() + *---------------------------------------------------------------------------- + * This routine is called at the end of the SysEx message to allow + * the Voice Manager to complete the initialization of the MIP + * table. It assigns channels to the appropriate voice pool based + * on the MIP setting and calculates the voices allocated for each + * pool. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMUpdateMIPTable (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + EAS_INT currentMIP; + EAS_INT currentPool; + EAS_INT priority[NUM_SYNTH_CHANNELS]; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateMIPTable\n"); */ } +#endif + + /* set SP-MIDI flag */ + pSynth->synthFlags |= SYNTH_FLAG_SP_MIDI_ON; + + /* sort channels into priority order */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + priority[i] = -1; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + if (pSynth->channels[i].pool != DEFAULT_SP_MIDI_PRIORITY) + priority[pSynth->channels[i].pool] = i; + } + + /* process channels in priority order */ + currentMIP = 0; + currentPool = -1; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + /* stop when we run out of channels */ + if (priority[i] == -1) + break; + + pChannel = &pSynth->channels[priority[i]]; + + /* when 2 or more channels have the same MIP setting, they + * share a common voice pool + */ + if (pChannel->mip == currentMIP) + pChannel->pool = (EAS_U8) currentPool; + + /* new voice pool */ + else + { + currentPool++; + pSynth->poolAlloc[currentPool] = (EAS_U8) (pChannel->mip - currentMIP); + currentMIP = pChannel->mip; + } + } + + /* set SP-MIDI flag */ + pSynth->synthFlags |= SYNTH_FLAG_SP_MIDI_ON; + + /* update channel muting */ + VMMIPUpdateChannelMuting (pVoiceMgr, pSynth); +} + +/*---------------------------------------------------------------------------- + * VMMuteAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this in an emergency reset situation. + * This forces all voices to mute quickly. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMMuteAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMMuteAllVoices: about to mute all voices!!\n"); */ } +#endif + + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + /* for stolen voices, check new channel */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateStolen) + { + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == pSynth->vSynthNum) + VMMuteVoice(pVoiceMgr, i); + } + + else if (pSynth->vSynthNum == GET_VSYNTH(pVoiceMgr->voices[i].channel)) + VMMuteVoice(pVoiceMgr, i); + } +} + +/*---------------------------------------------------------------------------- + * VMReleaseAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this after we've encountered the end of the Midi file. + * This ensures all voices are either in release (because we received their + * note off already) or forces them to mute quickly. + * We use this as a safety to prevent bad midi files from playing forever. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to release or mute + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + + /* release sustain pedal on all channels */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + if (pSynth->channels[ i ].channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + VMReleaseAllDeferredNoteOffs(pVoiceMgr, pSynth, (EAS_U8) i); + pSynth->channels[i].channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + } + } + + /* release all voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + switch (pVoiceMgr->voices[i].voiceState) + { + case eVoiceStateStart: + case eVoiceStatePlay: + /* only release voices on this synth */ + if (GET_VSYNTH(pVoiceMgr->voices[i].channel) == pSynth->vSynthNum) + VMReleaseVoice(pVoiceMgr, pSynth, i); + break; + + case eVoiceStateStolen: + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == pSynth->vSynthNum) + VMMuteVoice(pVoiceMgr, i); + break; + + case eVoiceStateFree: + case eVoiceStateRelease: + case eVoiceStateMuting: + break; + + case eVoiceStateInvalid: + default: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReleaseAllVoices: error, %d is an unrecognized state\n", + pVoiceMgr->voices[i].voiceState); */ } +#endif + break; + } + } +} + +/*---------------------------------------------------------------------------- + * VMAllNotesOff() + *---------------------------------------------------------------------------- + * Purpose: + * Quickly mute all notes on the given channel. + * + * Inputs: + * nChannel - quickly turn off all notes on this channel + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices on this channel to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMAllNotesOff (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + EAS_INT voiceNum; + S_SYNTH_VOICE *pVoice; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMAllNotesOff: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif + + /* increment workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + + /* check each voice */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + pVoice = &pVoiceMgr->voices[voiceNum]; + if (pVoice->voiceState != eVoiceStateFree) + { + if (((pVoice->voiceState != eVoiceStateStolen) && (channel == pVoice->channel)) || + ((pVoice->voiceState == eVoiceStateStolen) && (channel == pVoice->nextChannel))) + { + /* this voice is assigned to the requested channel */ + GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pSynth, pVoice, GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateMuting; + } + } + } +} + +/*---------------------------------------------------------------------------- + * VMDeferredStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Stop the notes that had deferred note-off requests. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None. + * + * Side Effects: + * voices that have had deferred note-off requests are now put into release + * psSynthObject->m_sVoice[i].m_nFlags has the VOICE_FLAG_DEFER_MIDI_NOTE_OFF + * cleared + *---------------------------------------------------------------------------- +*/ +void VMDeferredStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT voiceNum; + EAS_INT channel; + EAS_BOOL deferredNoteOff; + + deferredNoteOff = EAS_FALSE; + + /* check each voice to see if it requires a deferred note off */ + for (voiceNum=0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_DEFER_MIDI_NOTE_OFF) + { + /* check if this voice was stolen */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) + { + /* + This voice was stolen, AND it also has a deferred note-off. + The stolen note must be completely ramped down at this point. + The note that caused the stealing to occur, however, must + have received a note-off request before the note that caused + stealing ever had a chance to even start. We want to give + the note that caused the stealing a chance to play, so we + start it on the next update interval, and we defer sending + the note-off request until the subsequent update interval. + So do not send the note-off request for this voice because + this voice was stolen and should have completed ramping down, + Also, do not clear the global flag nor this voice's flag + because we must indicate that the subsequent update interval, + after the note that caused stealing has started, should + then send the deferred note-off request. + */ + deferredNoteOff = EAS_TRUE; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: defer request to stop voice %d (channel=%d note=%d) - voice not started\n", + voiceNum, + pVoiceMgr->voices[voiceNum].nextChannel, + pVoiceMgr->voices[voiceNum].note); */ } + + /* sanity check: this stolen voice better be ramped to zero */ + if (0 != pVoiceMgr->voices[voiceNum].gain) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: warning, this voice did not complete its ramp to zero\n"); */ } + } +#endif // #ifdef _DEBUG_VM + + } + else + { + /* clear the flag using exor */ + pVoiceMgr->voices[voiceNum].voiceFlags ^= + VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: Stop voice %d (channel=%d note=%d)\n", + voiceNum, + pVoiceMgr->voices[voiceNum].nextChannel, + pVoiceMgr->voices[voiceNum].note); */ } +#endif + + channel = pVoiceMgr->voices[voiceNum].channel & 15; + + /* check if sustain pedal is on */ + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + GetSynthPtr(voiceNum)->pfSustainPedal(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], &pSynth->channels[channel], GetAdjustedVoiceNum(voiceNum)); + } + + /* release this voice */ + else + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + } + + } + + } + + /* clear the deferred note-off flag, unless there's another one pending */ + if (deferredNoteOff == EAS_FALSE) + pSynth->synthFlags ^= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; +} + +/*---------------------------------------------------------------------------- + * VMReleaseAllDeferredNoteOffs() + *---------------------------------------------------------------------------- + * Purpose: + * Call this functin when the sustain flag is presently set but + * we are now transitioning from damper pedal on to + * damper pedal off. This means all notes in this channel + * that received a note off while the damper pedal was on, and + * had their note-off requests deferred, should now proceed to + * the release state. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * pVoice->m_sEG1.m_eState = eEnvelopeStateRelease + * pVoice->m_sEG1.m_nIncrement = release increment + * pVoice->m_nFlags = clear the deferred note off flag + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllDeferredNoteOffs (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + S_SYNTH_VOICE *pVoice; + EAS_INT voiceNum; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReleaseAllDeferredNoteOffs: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif /* #ifdef _DEBUG_VM */ + + /* increment workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + + /* find all the voices assigned to this channel */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + pVoice = &pVoiceMgr->voices[voiceNum]; + if (channel == pVoice->channel) + { + + /* does this voice have a deferred note off? */ + if (pVoice->voiceFlags & VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF) + { + /* release voice */ + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + /* use exor to flip bit, clear the flag */ + pVoice->voiceFlags &= ~VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + + } + + } + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMCatchNotesForSustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when the sustain flag is presently clear and + * the damper pedal is off and we are transitioning from damper pedal OFF to + * damper pedal ON. Currently sounding notes should be left + * unchanged. However, we should try to "catch" notes if possible. + * If any notes are in release and have levels >= sustain level, catch them, + * otherwise, let them continue to release. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +void VMCatchNotesForSustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + EAS_INT voiceNum; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCatchNotesForSustainPedal: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif + + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + channel = VSynthToChannel(pSynth, channel); + + /* find all the voices assigned to this channel */ + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (channel == pVoiceMgr->voices[voiceNum].channel) + { + if (eVoiceStateRelease == pVoiceMgr->voices[voiceNum].voiceState) + GetSynthPtr(voiceNum)->pfSustainPedal(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], &pSynth->channels[channel], GetAdjustedVoiceNum(voiceNum)); + } + } +} + +/*---------------------------------------------------------------------------- + * VMUpdateAllNotesAge() + *---------------------------------------------------------------------------- + * Purpose: + * Increment the note age for all of the active voices. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * m_nAge for all voices is incremented + *---------------------------------------------------------------------------- +*/ +void VMUpdateAllNotesAge (S_VOICE_MGR *pVoiceMgr, EAS_U16 age) +{ + EAS_INT i; + + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + if (age - pVoiceMgr->voices[i].age > 0) + pVoiceMgr->voices[i].age++; + } +} + +/*---------------------------------------------------------------------------- + * VMStolenVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being stolen. Sets the parameters so that the + * voice will begin playing the new sound on the next buffer. + * + * Inputs: + * pVoice - pointer to voice to steal + * nChannel - the channel to start a note on + * nKeyNumber - the key number to start a note for + * nNoteVelocity - the key velocity from this note + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static void VMStolenVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 voiceNum, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex) +{ + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + + /* one less voice in old pool */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + /* mute the sound that is currently playing */ + GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)], &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateStolen; + + /* set new note data */ + pVoice->nextChannel = VSynthToChannel(pSynth, channel); + pVoice->nextNote = note; + pVoice->nextVelocity = velocity; + pVoice->nextRegionIndex = regionIndex; + + /* one more voice in new pool */ + IncVoicePoolCount(pVoiceMgr, pVoice); + + /* clear the deferred flags */ + pVoice->voiceFlags &= + ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | + VOICE_FLAG_DEFER_MUTE | + VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF); + + /* all notes older than this one get "younger" */ + VMUpdateAllNotesAge(pVoiceMgr, pVoice->age); + + /* assign current age to this note and increment for the next note */ + pVoice->age = pVoiceMgr->age++; +} + +/*---------------------------------------------------------------------------- + * VMFreeVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is done playing and being returned to the + * pool of free voices + * + * Inputs: + * pVoice - pointer to voice to free + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static void VMFreeVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice) +{ + + /* do nothing if voice is already free */ + if (pVoice->voiceState == eVoiceStateFree) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMFreeVoice: Attempt to free voice that is already free\n"); */ } + return; + } + + /* if we jump directly to free without passing muting stage, + * we need to adjust the voice count */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMFreeVoice: Synth=%d\n", pSynth->vSynthNum); */ } +#endif + + /* return to free voice pool */ + pVoiceMgr->activeVoices--; + pSynth->numActiveVoices--; + InitVoice(pVoice); + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMFreeVoice: free voice %d\n", pVoice - pVoiceMgr->voices); */ } +#endif + + /* all notes older than this one get "younger" */ + VMUpdateAllNotesAge(pVoiceMgr, pVoice->age); + } + +/*---------------------------------------------------------------------------- + * VMRetargetStolenVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice has been stolen and needs to be initalized with + * the paramters of its new note. + * + * Inputs: + * pVoice - pointer to voice to retarget + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL VMRetargetStolenVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum) +{ + EAS_U8 flags; + S_SYNTH_CHANNEL *pMIDIChannel; + S_SYNTH_VOICE *pVoice; + S_SYNTH *pSynth; + S_SYNTH *pNextSynth; + + /* establish some pointers */ + pVoice = &pVoiceMgr->voices[voiceNum]; + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pMIDIChannel = &pSynth->channels[pVoice->channel & 15]; + pNextSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + +#ifdef _DEBUG_VM +{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetStolenVoice: retargeting stolen voice %d on channel %d\n", + voiceNum, pVoice->channel); */ } + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\to channel %d note: %d velocity: %d\n", + pVoice->nextChannel, pVoice->nextNote, pVoice->nextVelocity); */ } +#endif + + /* make sure new channel hasn't been muted by SP-MIDI since the voice was stolen */ + if ((pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) && + (pMIDIChannel->channelFlags & CHANNEL_FLAG_MUTE)) + { + VMFreeVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum]); + return EAS_FALSE; + } + + /* if assigned to a new synth, correct the active voice count */ + if (pVoice->channel != pVoice->nextChannel) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetStolenVoice: Note assigned to different virtual synth, adjusting numActiveVoices\n"); */ } +#endif + pSynth->numActiveVoices--; + pNextSynth->numActiveVoices++; + } + + /* assign new channel number, and increase channel voice count */ + pVoice->channel = pVoice->nextChannel; + pMIDIChannel = &pNextSynth->channels[pVoice->channel & 15]; + + /* assign other data */ + pVoice->note = pVoice->nextNote; + pVoice->velocity = pVoice->nextVelocity; + pVoice->nextChannel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->regionIndex = pVoice->nextRegionIndex; + + /* save the flags, pfStartVoice() will clear them */ + flags = pVoice->voiceFlags; + + /* keep track of the note-start related workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_START_NOTE; + + /* setup the voice parameters */ + pVoice->voiceState = eVoiceStateStart; + + /*lint -e{522} return not used at this time */ + GetSynthPtr(voiceNum)->pfStartVoice(pVoiceMgr, pNextSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), pVoice->regionIndex); + + /* did the new note already receive a MIDI note-off request? */ + if (flags & VOICE_FLAG_DEFER_MIDI_NOTE_OFF) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetVoice: stolen note note-off request deferred\n"); */ } +#endif + pVoice->voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + pNextSynth->synthFlags |= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; + } + + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * VMCheckKeyGroup() + *---------------------------------------------------------------------------- + * If the note that we've been asked to start is in the same key group as + * any currently playing notes, then we must shut down the currently playing + * note in the same key group + *---------------------------------------------------------------------------- +*/ +void VMCheckKeyGroup (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U16 keyGroup, EAS_U8 channel) +{ + const S_REGION *pRegion; + EAS_INT voiceNum; + + /* increment frame workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_KEY_GROUP; + + /* need to check all voices in case this is a layered sound */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateStolen) + { + /* voice must be on the same channel */ + if (channel == pVoiceMgr->voices[voiceNum].channel) + { + /* check key group */ + pRegion = GetRegionPtr(pSynth, pVoiceMgr->voices[voiceNum].regionIndex); + if (keyGroup == (pRegion->keyGroupAndFlags & 0x0f00)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckKeyGroup: voice %d matches key group %d\n", voiceNum, keyGroup >> 8); */ } +#endif + + /* if this voice was just started, set it to mute on the next buffer */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MUTE; + + /* mute immediately */ + else + VMMuteVoice(pVoiceMgr, voiceNum); + } + } + } + + /* for stolen voice, check new values */ + else + { + /* voice must be on the same channel */ + if (channel == pVoiceMgr->voices[voiceNum].nextChannel) + { + /* check key group */ + pRegion = GetRegionPtr(pSynth, pVoiceMgr->voices[voiceNum].nextRegionIndex); + if (keyGroup == (pRegion->keyGroupAndFlags & 0x0f00)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckKeyGroup: voice %d matches key group %d\n", voiceNum, keyGroup >> 8); */ } +#endif + + /* if this voice was just started, set it to mute on the next buffer */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MUTE; + + /* mute immediately */ + else + VMMuteVoice(pVoiceMgr, voiceNum); + } + } + + } + } +} + +/*---------------------------------------------------------------------------- + * VMCheckPolyphonyLimiting() + *---------------------------------------------------------------------------- + * Purpose: + * We only play at most 2 of the same note on a MIDI channel. + * E.g., if we are asked to start note 36, and there are already two voices + * that are playing note 36, then we must steal the voice playing + * the oldest note 36 and use that stolen voice to play the new note 36. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * * + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber may be assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckPolyphonyLimiting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + EAS_INT voiceNum; + EAS_INT oldestVoiceNum; + EAS_INT numVoicesPlayingNote; + EAS_U16 age; + EAS_U16 oldestNoteAge; + + pVoiceMgr->workload += WORKLOAD_AMOUNT_POLY_LIMIT; + + numVoicesPlayingNote = 0; + oldestVoiceNum = MAX_SYNTH_VOICES; + oldestNoteAge = 0; + channel = VSynthToChannel(pSynth, channel); + + /* examine each voice on this channel playing this note */ + for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) + { + /* check stolen notes separately */ + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateStolen) + { + + /* same channel and note ? */ + if ((channel == pVoiceMgr->voices[voiceNum].channel) && (note == pVoiceMgr->voices[voiceNum].note)) + { + numVoicesPlayingNote++; + age = pVoiceMgr->age - pVoiceMgr->voices[voiceNum].age; + + /* is this the oldest voice for this note? */ + if (age >= oldestNoteAge) + { + oldestNoteAge = age; + oldestVoiceNum = voiceNum; + } + } + } + + /* handle stolen voices */ + else + { + /* same channel and note ? */ + if ((channel == pVoiceMgr->voices[voiceNum].nextChannel) && (note == pVoiceMgr->voices[voiceNum].nextNote)) + { + numVoicesPlayingNote++; + } + } + } + + /* check to see if we exceeded poly limit */ + if (numVoicesPlayingNote < DEFAULT_CHANNEL_POLYPHONY_LIMIT) + return EAS_FALSE; + + /* make sure we have a voice to steal */ + if (oldestVoiceNum != MAX_SYNTH_VOICES) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckPolyphonyLimiting: voice %d has the oldest note\n", oldestVoiceNum); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMCheckPolyphonyLimiting: polyphony limiting requires shutting down note %d \n", pVoiceMgr->voices[oldestVoiceNum].note); */ } +#endif + VMStolenVoice(pVoiceMgr, pSynth, oldestVoiceNum, channel, note, velocity, regionIndex); + return EAS_TRUE; + } + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMCheckPolyphonyLimiting: No oldest voice to steal\n"); */ } +#endif + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * VMStartVoice() + *---------------------------------------------------------------------------- + * Starts a voice given a region index + *---------------------------------------------------------------------------- +*/ +void VMStartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex) +{ + const S_REGION *pRegion; + S_SYNTH_CHANNEL *pChannel; + EAS_INT voiceNum; + EAS_INT maxSynthPoly; + EAS_I32 lowVoice, highVoice; + EAS_U16 keyGroup; + + pChannel = &pSynth->channels[channel]; + pRegion = GetRegionPtr(pSynth, regionIndex); + + /* select correct synth */ +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + { +#ifdef EAS_SPLIT_WT_SYNTH + if ((pRegion->keyGroupAndFlags & REGION_FLAG_OFF_CHIP) == 0) +#else + if ((regionIndex & FLAG_RGN_IDX_FM_SYNTH) == 0) +#endif + { + lowVoice = 0; + highVoice = NUM_PRIMARY_VOICES - 1; + } + else + { + lowVoice = NUM_PRIMARY_VOICES; + highVoice = MAX_SYNTH_VOICES - 1; + } + } +#else + lowVoice = 0; + highVoice = MAX_SYNTH_VOICES - 1; +#endif + + /* keep track of the note-start related workload */ + pVoiceMgr->workload+= WORKLOAD_AMOUNT_START_NOTE; + + /* other voices in pool, check for key group and poly limiting */ + if (pSynth->poolCount[pChannel->pool] != 0) + { + + /* check for key group exclusivity */ + keyGroup = pRegion->keyGroupAndFlags & 0x0f00; + if (keyGroup!= 0) + VMCheckKeyGroup(pVoiceMgr, pSynth, keyGroup, channel); + + /* check polyphony limit and steal a voice if necessary */ + if ((pRegion->keyGroupAndFlags & REGION_FLAG_NON_SELF_EXCLUSIVE) == 0) + { + if (VMCheckPolyphonyLimiting(pVoiceMgr, pSynth, channel, note, velocity, regionIndex, lowVoice, highVoice) == EAS_TRUE) + return; + } + } + + /* check max poly allocation */ + if ((pSynth->maxPolyphony == 0) || (pVoiceMgr->maxPolyphony < pSynth->maxPolyphony)) + maxSynthPoly = pVoiceMgr->maxPolyphony; + else + maxSynthPoly = pSynth->maxPolyphony; + + /* any free voices? */ + if ((pVoiceMgr->activeVoices < pVoiceMgr->maxPolyphony) && + (pSynth->numActiveVoices < maxSynthPoly) && + (EAS_SUCCESS == VMFindAvailableVoice(pVoiceMgr, &voiceNum, lowVoice, highVoice))) + { + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMStartVoice: Synth=%d\n", pSynth->vSynthNum); */ } +#endif + + /* bump voice counts */ + pVoiceMgr->activeVoices++; + pSynth->numActiveVoices++; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStartVoice: voice %d assigned to channel %d note %d velocity %d\n", + voiceNum, channel, note, velocity); */ } +#endif + + /* save parameters */ + pVoiceMgr->voices[voiceNum].channel = VSynthToChannel(pSynth, channel); + pVoiceMgr->voices[voiceNum].note = note; + pVoiceMgr->voices[voiceNum].velocity = velocity; + + /* establish note age for voice stealing */ + pVoiceMgr->voices[voiceNum].age = pVoiceMgr->age++; + + /* setup the synthesis parameters */ + pVoiceMgr->voices[voiceNum].voiceState = eVoiceStateStart; + + /* increment voice pool count */ + IncVoicePoolCount(pVoiceMgr, pVoice); + + /* start voice on correct synth */ + /*lint -e{522} return not used at this time */ + GetSynthPtr(voiceNum)->pfStartVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), regionIndex); + return; + } + + /* no free voices, we have to steal one using appropriate algorithm */ + if (VMStealVoice(pVoiceMgr, pSynth, &voiceNum, channel, note, lowVoice, highVoice) == EAS_SUCCESS) + VMStolenVoice(pVoiceMgr, pSynth, voiceNum, channel, note, velocity, regionIndex); + +#ifdef _DEBUG_VM + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStartVoice: Could not steal a voice for channel %d note %d velocity %d\n", + channel, note, velocity); */ } + } +#endif + + return; +} + +/*---------------------------------------------------------------------------- + * VMStartNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to play the requested note on the requested + * channel if possible. + * + * Inputs: + * nChannel - the channel to start a note on + * nKeyNumber - the key number to start a note for + * nNoteVelocity - the key velocity from this note + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_nNumActiveVoices may be incremented + * psSynthObject->m_sVoice[free voice num].m_nSynthChannel may be assigned + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber is assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +void VMStartNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_U16 regionIndex; + EAS_I16 adjustedNote; + + /* bump note count */ + pSynth->totalNoteCount++; + + pChannel = &pSynth->channels[channel]; + + /* check channel mute */ + if (pChannel->channelFlags & CHANNEL_FLAG_MUTE) + return; + +#ifdef EXTERNAL_AUDIO + /* pass event to external audio when requested */ + if ((pChannel->channelFlags & CHANNEL_FLAG_EXTERNAL_AUDIO) && (pSynth->cbEventFunc != NULL)) + { + S_EXT_AUDIO_EVENT event; + event.channel = channel; + event.note = note; + event.velocity = velocity; + event.noteOn = EAS_TRUE; + if (pSynth->cbEventFunc(pSynth->pExtAudioInstData, &event)) + return; + } +#endif + + /* start search at first region */ + regionIndex = pChannel->regionIndex; + + /* handle transposition */ + adjustedNote = note; + if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) + adjustedNote += pChannel->coarsePitch; + else + adjustedNote += pChannel->coarsePitch + pSynth->globalTranspose; + + /* limit adjusted key number so it does not wraparound, over/underflow */ + if (adjustedNote < 0) + { + adjustedNote = 0; + } + else if (adjustedNote > 127) + { + adjustedNote = 127; + } + +#if defined(DLS_SYNTHESIZER) + if (regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + /* DLS voice */ + for (;;) + { + /*lint -e{740,826} cast OK, we know this is actually a DLS region */ + const S_DLS_REGION *pDLSRegion = (S_DLS_REGION*) GetRegionPtr(pSynth, regionIndex); + + /* check key against this region's key and velocity range */ + if (((adjustedNote >= pDLSRegion->wtRegion.region.rangeLow) && (adjustedNote <= pDLSRegion->wtRegion.region.rangeHigh)) && + ((velocity >= pDLSRegion->velLow) && (velocity <= pDLSRegion->velHigh))) + { + VMStartVoice(pVoiceMgr, pSynth, channel, note, velocity, regionIndex); + } + + /* last region in program? */ + if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_LAST_REGION) + break; + + /* advance to next region */ + regionIndex++; + } + } + else +#endif + + /* braces here for #if clause */ + { + /* EAS voice */ + for (;;) + { + const S_REGION *pRegion = GetRegionPtr(pSynth, regionIndex); + + /* check key against this region's keyrange */ + if ((adjustedNote >= pRegion->rangeLow) && (adjustedNote <= pRegion->rangeHigh)) + { + VMStartVoice(pVoiceMgr, pSynth, channel, note, velocity, regionIndex); + break; + } + + /* last region in program? */ + if (pRegion->keyGroupAndFlags & REGION_FLAG_LAST_REGION) + break; + + /* advance to next region */ + regionIndex++; + } + } +} + +/*---------------------------------------------------------------------------- + * VMStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to end the requested note on the requested + * channel. + * + * Inputs: + * nChannel - the channel to stop a note on + * nKeyNumber - the key number for this note off + * nNoteVelocity - the note-off velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nSynthChannel may be assigned + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber is assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, velocity) reserved for future use */ +void VMStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT voiceNum; + + pChannel = &(pSynth->channels[channel]); + +#ifdef EXTERNAL_AUDIO + if ((pChannel->channelFlags & CHANNEL_FLAG_EXTERNAL_AUDIO) && (pSynth->cbEventFunc != NULL)) + { + S_EXT_AUDIO_EVENT event; + event.channel = channel; + event.note = note; + event.velocity = velocity; + event.noteOn = EAS_FALSE; + if (pSynth->cbEventFunc(pSynth->pExtAudioInstData, &event)) + return; + } +#endif + + /* keep track of the note-start workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_STOP_NOTE; + + channel = VSynthToChannel(pSynth, channel); + + for (voiceNum=0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + /* stolen notes are handled separately */ + if (eVoiceStateStolen != pVoiceMgr->voices[voiceNum].voiceState) + { + + /* channel and key number must match */ + if ((channel == pVoiceMgr->voices[voiceNum].channel) && (note == pVoiceMgr->voices[voiceNum].note)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStopNote: voice %d channel %d note %d\n", + voiceNum, channel, note); */ } +#endif + + /* if sustain pedal is down, set deferred note-off flag */ + if (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + continue; + } + + /* if this note just started, wait before we stop it */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tDeferred: Not started yet\n"); */ } +#endif + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + pSynth->synthFlags |= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; + } + + /* release voice */ + else + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + } + } + + /* process stolen notes, new channel and key number must match */ + else if ((channel == pVoiceMgr->voices[voiceNum].nextChannel) && (note == pVoiceMgr->voices[voiceNum].nextNote)) + { + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStopNote: voice %d channel %d note %d\n\tDeferred: Stolen voice\n", + voiceNum, channel, note); */ } +#endif + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + } + } +} + +/*---------------------------------------------------------------------------- + * VMFindAvailableVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Find an available voice and return the voice number if available. + * + * Inputs: + * pnVoiceNumber - really an output, returns the voice number found + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * success - if there is an available voice + * failure - otherwise + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindAvailableVoice (S_VOICE_MGR *pVoiceMgr, EAS_INT *pVoiceNumber, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + EAS_INT voiceNum; + + /* Check each voice to see if it has been assigned to a synth channel */ + for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) + { + /* check if this voice has been assigned to a synth channel */ + if ( pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateFree) + { + *pVoiceNumber = voiceNum; /* this voice is available */ + return EAS_SUCCESS; + } + } + + /* if we reach here, we have not found a free voice */ + *pVoiceNumber = UNASSIGNED_SYNTH_VOICE; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMFindAvailableVoice: error, could not find an available voice\n"); */ } +#endif + return EAS_FAILURE; +} + +/*---------------------------------------------------------------------------- + * VMStealVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Steal a voice and return the voice number + * + * Stealing algorithm: steal the best choice with minimal work, taking into + * account SP-Midi channel priorities and polyphony allocation. + * + * In one pass through all the voices, figure out which voice to steal + * taking into account a number of different factors: + * Priority of the voice's MIDI channel + * Number of voices over the polyphony allocation for voice's MIDI channel + * Amplitude of the voice + * Note age + * Key velocity (for voices that haven't been started yet) + * If any matching notes are found + * + * Inputs: + * pnVoiceNumber - really an output, see below + * nChannel - the channel that this voice wants to be started on + * nKeyNumber - the key number for this new voice + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - voice number of the voice that was stolen + * EAS_RESULT EAS_SUCCESS - always successful + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMStealVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_INT *pVoiceNumber, EAS_U8 channel, EAS_U8 note, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + S_SYNTH_VOICE *pCurrVoice; + S_SYNTH *pCurrSynth; + EAS_INT voiceNum; + EAS_INT bestCandidate; + EAS_U8 currChannel; + EAS_U8 currNote; + EAS_I32 bestPriority; + EAS_I32 currentPriority; + + /* determine which voice to steal */ + bestPriority = 0; + bestCandidate = MAX_SYNTH_VOICES; + + for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) + { + pCurrVoice = &pVoiceMgr->voices[voiceNum]; + + /* ignore free voices */ + if (pCurrVoice->voiceState == eVoiceStateFree) + continue; + + /* for stolen voices, use the new parameters, not the old */ + if (pCurrVoice->voiceState == eVoiceStateStolen) + { + pCurrSynth = pVoiceMgr->pSynth[GET_VSYNTH(pCurrVoice->nextChannel)]; + currChannel = pCurrVoice->nextChannel; + currNote = pCurrVoice->nextNote; + } + else + { + pCurrSynth = pVoiceMgr->pSynth[GET_VSYNTH(pCurrVoice->channel)]; + currChannel = pCurrVoice->channel; + currNote = pCurrVoice->note; + } + + /* ignore voices that are higher priority */ + if (pSynth->priority > pCurrSynth->priority) + continue; +#ifdef _DEBUG_VM +// { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: New priority = %d exceeds old priority = %d\n", pSynth->priority, pCurrSynth->priority); */ } +#endif + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pCurrVoice->voiceState == eVoiceStateStolen) || (pCurrVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + currentPriority = 128 - pCurrVoice->nextVelocity; + } + else + { + /* compute the priority of this voice, higher means better for stealing */ + /* use not age */ + currentPriority = (EAS_I32) pCurrVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pCurrVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + } + + /* in SP-MIDI mode, include over poly allocation and channel priority */ + if (pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + { + S_SYNTH_CHANNEL *pChannel = &pCurrSynth->channels[GET_CHANNEL(currChannel)]; + /*lint -e{701} use shift for performance */ + if (pSynth->poolCount[pChannel->pool] >= pSynth->poolAlloc[pChannel->pool]) + currentPriority += (pSynth->poolCount[pChannel->pool] -pSynth->poolAlloc[pChannel->pool] + 1) << CHANNEL_POLY_STEAL_WEIGHT; + + /* include channel priority */ + currentPriority += (EAS_I32)(pChannel->pool << CHANNEL_PRIORITY_STEAL_WEIGHT); + } + + /* if a note is already playing that matches this note, consider stealing it more readily */ + if ((note == currNote) && (channel == currChannel)) + currentPriority += NOTE_MATCH_PENALTY; + + /* is this the best choice so far? */ + if (currentPriority >= bestPriority) + { + bestPriority = currentPriority; + bestCandidate = voiceNum; + } + } + + /* may happen if all voices are allocated to a higher priority virtual synth */ + if (bestCandidate == MAX_SYNTH_VOICES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: Unable to allocate a voice\n"); */ } + return EAS_ERROR_NO_VOICE_ALLOCATED; + } + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: Voice %d stolen\n", bestCandidate); */ } + + /* are we stealing a stolen voice? */ + if (pVoiceMgr->voices[bestCandidate].voiceState == eVoiceStateStolen) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMStealVoice: Voice %d is already marked as stolen and was scheduled to play ch: %d note: %d vel: %d\n", + bestCandidate, + pVoiceMgr->voices[bestCandidate].nextChannel, + pVoiceMgr->voices[bestCandidate].nextNote, + pVoiceMgr->voices[bestCandidate].nextVelocity); */ } + } +#endif + + *pVoiceNumber = (EAS_U16) bestCandidate; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMChannelPressure() + *---------------------------------------------------------------------------- + * Purpose: + * Change the channel pressure for the given channel + * + * Inputs: + * nChannel - the MIDI channel + * nVelocity - the channel pressure value + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sChannel[nChannel].m_nChannelPressure is updated + *---------------------------------------------------------------------------- +*/ +void VMChannelPressure (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + pChannel->channelPressure = value; + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMPitchBend() + *---------------------------------------------------------------------------- + * Purpose: + * Change the pitch wheel value for the given channel. + * This routine constructs the proper 14-bit argument when the calling routine + * passes the pitch LSB and MSB. + * + * Note: some midi disassemblers display a bipolar pitch bend value. + * We can display the bipolar value using + * if m_nPitchBend >= 0x2000 + * bipolar pitch bend = postive (m_nPitchBend - 0x2000) + * else + * bipolar pitch bend = negative (0x2000 - m_nPitchBend) + * + * Inputs: + * nChannel - the MIDI channel + * nPitchLSB - the LSB byte of the pitch bend message + * nPitchMSB - the MSB byte of the pitch bend message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * psSynthObject->m_sChannel[nChannel].m_nPitchBend is changed + * + *---------------------------------------------------------------------------- +*/ +void VMPitchBend (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 nPitchLSB, EAS_U8 nPitchMSB) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + pChannel->pitchBend = (EAS_I16) ((nPitchMSB << 7) | nPitchLSB); + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMControlChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the controller (or mode) for the given channel. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the MIDI controller number + * nControlValue - the value for this controller message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sChannel[nChannel] controller is changed + * + *---------------------------------------------------------------------------- +*/ +void VMControlChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + switch ( controller ) + { + case MIDI_CONTROLLER_BANK_SELECT_MSB: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: Bank Select MSB: msb 0x%X\n", value); */ } +#endif + /* use this MSB with a zero LSB, until we get an LSB message */ + pChannel->bankNum = value << 8; + break; + + case MIDI_CONTROLLER_MOD_WHEEL: + /* we treat mod wheel as a 7-bit controller and only use the MSB */ + pChannel->modWheel = value; + break; + + case MIDI_CONTROLLER_VOLUME: + /* we treat volume as a 7-bit controller and only use the MSB */ + pChannel->volume = value; + break; + + case MIDI_CONTROLLER_PAN: + /* we treat pan as a 7-bit controller and only use the MSB */ + pChannel->pan = value; + break; + + case MIDI_CONTROLLER_EXPRESSION: + /* we treat expression as a 7-bit controller and only use the MSB */ + pChannel->expression = value; + break; + + case MIDI_CONTROLLER_BANK_SELECT_LSB: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: Bank Select LSB: lsb 0x%X\n", value); */ } +#endif + /* + construct bank number as 7-bits (stored as 8) of existing MSB + and 7-bits of new LSB (also stored as 8( + */ + pChannel->bankNum = + (pChannel->bankNum & 0xFF00) | value; + + break; + + case MIDI_CONTROLLER_SUSTAIN_PEDAL: + /* we treat sustain pedal as a boolean on/off bit flag */ + if (value < 64) + { + /* + we are requested to turn the pedal off, but first check + if the pedal is already on + */ + if (0 != + (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + ) + { + /* + The sustain flag is presently set and the damper pedal is on. + We are therefore transitioning from damper pedal ON to + damper pedal OFF. This means all notes in this channel + that received a note off while the damper pedal was on, and + had their note-off requests deferred, should now proceed to + the release state. + */ + VMReleaseAllDeferredNoteOffs(pVoiceMgr, pSynth, channel); + } /* end if sustain pedal is already on */ + + /* turn the sustain pedal off */ + pChannel->channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + } + else + { + /* + we are requested to turn the pedal on, but first check + if the pedal is already off + */ + if (0 == + (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + ) + { + /* + The sustain flag is presently clear and the damper pedal is off. + We are therefore transitioning from damper pedal OFF to + damper pedal ON. Currently sounding notes should be left + unchanged. However, we should try to "catch" notes if possible. + If any notes have levels >= sustain level, catch them, + otherwise, let them continue to release. + */ + VMCatchNotesForSustainPedal(pVoiceMgr, pSynth, channel); + } + + /* turn the sustain pedal on */ + pChannel->channelFlags |= CHANNEL_FLAG_SUSTAIN_PEDAL; + } + + break; +#ifdef _REVERB + case MIDI_CONTROLLER_REVERB_SEND: + /* we treat send as a 7-bit controller and only use the MSB */ + pSynth->channels[channel].reverbSend = value; + break; +#endif +#ifdef _CHORUS + case MIDI_CONTROLLER_CHORUS_SEND: + /* we treat send as a 7-bit controller and only use the MSB */ + pSynth->channels[channel].chorusSend = value; + break; +#endif + case MIDI_CONTROLLER_RESET_CONTROLLERS: + /* despite the Midi message name, not ALL controllers are reset */ + pChannel->modWheel = DEFAULT_MOD_WHEEL; + pChannel->expression = DEFAULT_EXPRESSION; + + /* turn the sustain pedal off as default/reset */ + pChannel->channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + pChannel->pitchBend = DEFAULT_PITCH_BEND; + + /* reset channel pressure */ + pChannel->channelPressure = DEFAULT_CHANNEL_PRESSURE; + + /* reset RPN values */ + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + pChannel->pitchBendSensitivity = DEFAULT_PITCH_BEND_SENSITIVITY; + pChannel->finePitch = DEFAULT_FINE_PITCH; + pChannel->coarsePitch = DEFAULT_COARSE_PITCH; + + /* + program change, bank select, channel volume CC7, pan CC10 + are NOT reset + */ + break; + + /* + For logical reasons, the RPN data entry are grouped together. + However, keep in mind that these cases are not necessarily in + ascending order. + e.g., MIDI_CONTROLLER_DATA_ENTRY_MSB == 6, + whereas MIDI_CONTROLLER_SUSTAIN_PEDAL == 64. + So arrange these case statements in whatever manner is more efficient for + the processor / compiler. + */ + case MIDI_CONTROLLER_ENTER_DATA_MSB: + case MIDI_CONTROLLER_ENTER_DATA_LSB: + case MIDI_CONTROLLER_SELECT_RPN_LSB: + case MIDI_CONTROLLER_SELECT_RPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_LSB: + VMUpdateRPNStateMachine(pSynth, channel, controller, value); + break; + + case MIDI_CONTROLLER_ALL_SOUND_OFF: + case MIDI_CONTROLLER_ALL_NOTES_OFF: + case MIDI_CONTROLLER_OMNI_OFF: + case MIDI_CONTROLLER_OMNI_ON: + case MIDI_CONTROLLER_MONO_ON_POLY_OFF: + case MIDI_CONTROLLER_POLY_ON_MONO_OFF: + /* NOTE: we treat all sounds off the same as all notes off */ + VMAllNotesOff(pVoiceMgr, pSynth, channel); + break; + + default: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: controller %d not yet implemented\n", controller); */ } +#endif + break; + + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMUpdateRPNStateMachine() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when we want to parse RPN related controller messages. + * We only support RPN0 (pitch bend sensitivity), RPN1 (fine tuning) and + * RPN2 (coarse tuning). Any other RPNs or NRPNs are ignored for now. + *. + * Supports any order, so not a state machine anymore. This function was + * rewritten to work correctly regardless of order. + * + * Inputs: + * nChannel - the channel this controller message is coming from + * nControllerNumber - which RPN related controller + * nControlValue - the value of the RPN related controller + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * returns EAS_RESULT, which is typically EAS_SUCCESS, since there are + * few possible errors + * + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nPitchBendSensitivity + * (or m_nFinePitch or m_nCoarsePitch) + * will be updated if the proper RPN message is received. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMUpdateRPNStateMachine (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateRPNStateMachines: error, %d invalid channel number\n", + channel); */ } + return EAS_FAILURE; + } +#endif + + pChannel = &(pSynth->channels[channel]); + + switch (controller) + { + case MIDI_CONTROLLER_SELECT_NRPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_LSB: + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + break; + case MIDI_CONTROLLER_SELECT_RPN_MSB: + pChannel->registeredParam = + (pChannel->registeredParam & 0x7F) | (value<<7); + break; + case MIDI_CONTROLLER_SELECT_RPN_LSB: + pChannel->registeredParam = + (pChannel->registeredParam & 0x7F00) | value; + break; + case MIDI_CONTROLLER_ENTER_DATA_MSB: + switch (pChannel->registeredParam) + { + case 0: + pChannel->pitchBendSensitivity = value * 100; + break; + case 1: + /*lint -e{702} */ + pChannel->finePitch = (EAS_I8)((((value << 7) - 8192) * 100) >> 13); + break; + case 2: + pChannel->coarsePitch = (EAS_I8)(value - 64); + break; + default: + break; + } + break; + case MIDI_CONTROLLER_ENTER_DATA_LSB: + switch (pChannel->registeredParam) + { + case 0: + //ignore lsb + break; + case 1: + //ignore lsb + break; + case 2: + //ignore lsb + break; + default: + break; + } + break; + default: + return EAS_FAILURE; //not a RPN related controller + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMUpdateStaticChannelParameters() + *---------------------------------------------------------------------------- + * Purpose: + * Update all of the static channel parameters for channels that have had + * a controller change values + * Or if the synth has signalled that all channels must forcibly + * be updated + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * none + * + * Side Effects: + * - psSynthObject->m_sChannel[].m_nStaticGain and m_nStaticPitch + * are updated for channels whose controller values have changed + * or if the synth has signalled that all channels must forcibly + * be updated + *---------------------------------------------------------------------------- +*/ +void VMUpdateStaticChannelParameters (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT channel; + + if (pSynth->synthFlags & SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS) + { + /* + the synth wants us to forcibly update all channel + parameters. This event occurs when we are about to + finish resetting the synth + */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + { +#ifdef _HYBRID_SYNTH + if (pSynth->channels[channel].regionIndex & FLAG_RGN_IDX_FM_SYNTH) + pSecondarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); + else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#endif + } + + /* + clear the flag to indicates we have now forcibly + updated all channel parameters + */ + pSynth->synthFlags &= ~SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS; + } + else + { + + /* only update channel params if signalled by a channel flag */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + { + if ( 0 != (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS)) + { +#ifdef _HYBRID_SYNTH + if (pSynth->channels[channel].regionIndex & FLAG_RGN_IDX_FM_SYNTH) + pSecondarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); + else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#endif + } + } + + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMFindProgram() + *---------------------------------------------------------------------------- + * Purpose: + * Look up an individual program in sound library. This function + * searches the bank list for a program, then the individual program + * list. + * + * Inputs: + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT VMFindProgram (const S_EAS *pEAS, EAS_U32 bank, EAS_U8 programNum, EAS_U16 *pRegionIndex) +{ + EAS_U32 locale; + const S_PROGRAM *p; + EAS_U16 i; + EAS_U16 regionIndex; + + /* make sure we have a valid sound library */ + if (pEAS == NULL) + return EAS_FAILURE; + + /* search the banks */ + for (i = 0; i < pEAS->numBanks; i++) + { + if (bank == (EAS_U32) pEAS->pBanks[i].locale) + { + regionIndex = pEAS->pBanks[i].regionIndex[programNum]; + if (regionIndex != INVALID_REGION_INDEX) + { + *pRegionIndex = regionIndex; + return EAS_SUCCESS; + } + break; + } + } + + /* establish locale */ + locale = ( bank << 8) | programNum; + + /* search for program */ + for (i = 0, p = pEAS->pPrograms; i < pEAS->numPrograms; i++, p++) + { + if (p->locale == locale) + { + *pRegionIndex = p->regionIndex; + return EAS_SUCCESS; + } + } + + return EAS_FAILURE; +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMFindDLSProgram() + *---------------------------------------------------------------------------- + * Purpose: + * Look up an individual program in sound library. This function + * searches the bank list for a program, then the individual program + * list. + * + * Inputs: + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT VMFindDLSProgram (const S_DLS *pDLS, EAS_U32 bank, EAS_U8 programNum, EAS_U16 *pRegionIndex) +{ + EAS_U32 locale; + const S_PROGRAM *p; + EAS_U16 i; + + /* make sure we have a valid sound library */ + if (pDLS == NULL) + return EAS_FAILURE; + + /* establish locale */ + locale = (bank << 8) | programNum; + + /* search for program */ + for (i = 0, p = pDLS->pDLSPrograms; i < pDLS->numDLSPrograms; i++, p++) + { + if (p->locale == locale) + { + *pRegionIndex = p->regionIndex; + return EAS_SUCCESS; + } + } + + return EAS_FAILURE; +} +#endif + +/*---------------------------------------------------------------------------- + * VMProgramChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the instrument (program) for the given channel. + * + * Depending on the program number, and the bank selected for this channel, the + * program may be in ROM, RAM (from SMAF or CMX related RAM wavetable), or + * Alternate wavetable (from mobile DLS or other DLS file) + * + * This function figures out what wavetable should be used, and sets it up as the + * wavetable to use for this channel. Also the channel may switch from a melodic + * channel to a rhythm channel, or vice versa. + * + * Inputs: + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nProgramNumber is likely changed + * gsSynthObject.m_sChannel[nChannel].m_psEAS may be changed + * gsSynthObject.m_sChannel[nChannel].m_bRhythmChannel may be changed + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMProgramChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 program) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_U32 bank; + EAS_U16 regionIndex; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMProgramChange: vSynthNum=%d, channel=%d, program=%d\n", pSynth->vSynthNum, channel, program); */ } +#endif + + /* setup pointer to MIDI channel data */ + pChannel = &pSynth->channels[channel]; + bank = pChannel->bankNum; + + /* allow channels to switch between being melodic or rhythm channels, using GM2 CC values */ + if ((bank & 0xFF00) == DEFAULT_RHYTHM_BANK_NUMBER) + { + /* make it a rhythm channel */ + pChannel->channelFlags |= CHANNEL_FLAG_RHYTHM_CHANNEL; + } + else if ((bank & 0xFF00) == DEFAULT_MELODY_BANK_NUMBER) + { + /* make it a melody channel */ + pChannel->channelFlags &= ~CHANNEL_FLAG_RHYTHM_CHANNEL; + } + + regionIndex = DEFAULT_REGION_INDEX; + +#ifdef EXTERNAL_AUDIO + /* give the external audio interface a chance to handle it */ + if (pSynth->cbProgChgFunc != NULL) + { + S_EXT_AUDIO_PRG_CHG prgChg; + prgChg.channel = channel; + prgChg.bank = (EAS_U16) bank; + prgChg.program = program; + if (pSynth->cbProgChgFunc(pSynth->pExtAudioInstData, &prgChg)) + pChannel->channelFlags |= CHANNEL_FLAG_EXTERNAL_AUDIO; + } + +#endif + + +#ifdef DLS_SYNTHESIZER + /* first check for DLS program that may overlay the internal instrument */ + if (VMFindDLSProgram(pSynth->pDLS, bank, program, ®ionIndex) != EAS_SUCCESS) +#endif + + /* braces to support 'if' clause above */ + { + + /* look in the internal banks */ + if (VMFindProgram(pSynth->pEAS, bank, program, ®ionIndex) != EAS_SUCCESS) + + /* fall back to default bank */ + { + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) + bank = DEFAULT_RHYTHM_BANK_NUMBER; + else + bank = DEFAULT_MELODY_BANK_NUMBER; + + if (VMFindProgram(pSynth->pEAS, bank, program, ®ionIndex) != EAS_SUCCESS) + + /* switch to program 0 in the default bank */ + { + if (VMFindProgram(pSynth->pEAS, bank, 0, ®ionIndex) != EAS_SUCCESS) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMProgramChange: No program @ %03d:%03d:%03d\n", + (bank >> 8) & 0x7f, bank & 0x7f, program); */ } + } + } + } + + /* we have our new program change for this channel */ + pChannel->programNum = program; + pChannel->regionIndex = regionIndex; + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + return; +} + +/*---------------------------------------------------------------------------- + * VMAddSamples() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize the requested number of samples (block based processing) + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * number of voices rendered + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMAddSamples (S_VOICE_MGR *pVoiceMgr, EAS_I32 *pMixBuffer, EAS_I32 numSamples) +{ + S_SYNTH *pSynth; + EAS_INT voicesRendered; + EAS_INT voiceNum; + EAS_BOOL done; + +#ifdef _REVERB + EAS_PCM *pReverbSendBuffer; +#endif // ifdef _REVERB + +#ifdef _CHORUS + EAS_PCM *pChorusSendBuffer; +#endif // ifdef _CHORUS + + voicesRendered = 0; + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + /* retarget stolen voices */ + if ((pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) && (pVoiceMgr->voices[voiceNum].gain <= 0)) + VMRetargetStolenVoice(pVoiceMgr, voiceNum); + + /* get pointer to virtual synth */ + pSynth = pVoiceMgr->pSynth[pVoiceMgr->voices[voiceNum].channel >> 4]; + + /* synthesize active voices */ + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateFree) + { + done = GetSynthPtr(voiceNum)->pfUpdateVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), pMixBuffer, numSamples); + voicesRendered++; + + /* voice is finished */ + if (done == EAS_TRUE) + { + /* set gain of stolen voice to zero so it will be restarted */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) + pVoiceMgr->voices[voiceNum].gain = 0; + + /* or return it to the free voice pool */ + else + VMFreeVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum]); + } + + /* if this voice is scheduled to be muted, set the mute flag */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_DEFER_MUTE) + { + pVoiceMgr->voices[voiceNum].voiceFlags &= ~(VOICE_FLAG_DEFER_MUTE | VOICE_FLAG_DEFER_MIDI_NOTE_OFF); + VMMuteVoice(pVoiceMgr, voiceNum); + } + + /* if voice just started, advance state to play */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStart) + pVoiceMgr->voices[voiceNum].voiceState = eVoiceStatePlay; + } + } + + return voicesRendered; +} + +/*---------------------------------------------------------------------------- + * VMRender() + *---------------------------------------------------------------------------- + * Purpose: + * This routine renders a frame of audio + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pVoicesRendered - number of voices rendered this frame + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMRender (S_VOICE_MGR *pVoiceMgr, EAS_I32 numSamples, EAS_I32 *pMixBuffer, EAS_I32 *pVoicesRendered) +{ + S_SYNTH *pSynth; + EAS_INT i; + EAS_INT channel; + +#ifdef _CHECKED_BUILD + SanityCheck(pVoiceMgr); +#endif + + /* update MIDI channel parameters */ + *pVoicesRendered = 0; + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pVoiceMgr->pSynth[i] != NULL) + VMUpdateStaticChannelParameters(pVoiceMgr, pVoiceMgr->pSynth[i]); + } + + /* synthesize a buffer of audio */ + *pVoicesRendered = VMAddSamples(pVoiceMgr, pMixBuffer, numSamples); + + /* + * check for deferred note-off messages + * If flag is set, that means one or more voices are expecting deferred + * midi note-off messages because the midi note-on and corresponding midi + * note-off requests occurred during the same update interval. The goal + * is the defer the note-off request so that the note can at least start. + */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + pSynth = pVoiceMgr->pSynth[i]; + + if (pSynth== NULL) + continue; + + if (pSynth->synthFlags & SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING) + VMDeferredStopNote(pVoiceMgr, pSynth); + + /* check if we need to reset the synth */ + if ((pSynth->synthFlags & SYNTH_FLAG_RESET_IS_REQUESTED) && + (pSynth->numActiveVoices == 0)) + { + /* + complete the process of resetting the synth now that + all voices have muted + */ +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMAddSamples: complete the reset process\n"); */ } +#endif + + VMInitializeAllChannels(pVoiceMgr, pSynth); + VMInitializeAllVoices(pVoiceMgr, pSynth->vSynthNum); + + /* clear the reset flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_RESET_IS_REQUESTED; + } + + /* clear channel update flags */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + pSynth->channels[channel].channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + } + +#ifdef _CHECKED_BUILD + SanityCheck(pVoiceMgr); +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMInitWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Clears the workload counter + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitWorkload (S_VOICE_MGR *pVoiceMgr) +{ + pVoiceMgr->workload = 0; +} + +/*---------------------------------------------------------------------------- + * VMSetWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the max workload for a single frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetWorkload (S_VOICE_MGR *pVoiceMgr, EAS_I32 maxWorkLoad) +{ + pVoiceMgr->maxWorkLoad = maxWorkLoad; +} + +/*---------------------------------------------------------------------------- + * VMCheckWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Checks to see if work load has been exceeded on this frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckWorkload (S_VOICE_MGR *pVoiceMgr) +{ + if (pVoiceMgr->maxWorkLoad > 0) + return (EAS_BOOL) (pVoiceMgr->workload >= pVoiceMgr->maxWorkLoad); + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * VMActiveVoices() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the number of active voices in the synthesizer. + * + * Inputs: + * pEASData - pointer to instance data + * + * Outputs: + * Returns the number of active voices + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMActiveVoices (S_SYNTH *pSynth) +{ + return pSynth->numActiveVoices; +} + +/*---------------------------------------------------------------------------- + * VMSetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * synth synthesizer number (0 = onboard, 1 = DSP) + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 polyphonyCount) +{ + EAS_INT i; + EAS_INT activeVoices; + + /* lower limit */ + if (polyphonyCount < 1) + polyphonyCount = 1; + + /* split architecture */ +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + if (synth == EAS_MCU_SYNTH) + { + if (polyphonyCount > NUM_PRIMARY_VOICES) + polyphonyCount = NUM_PRIMARY_VOICES; + if (pVoiceMgr->maxPolyphonyPrimary == polyphonyCount) + return EAS_SUCCESS; + pVoiceMgr->maxPolyphonyPrimary = (EAS_U16) polyphonyCount; + } + else if (synth == EAS_DSP_SYNTH) + { + if (polyphonyCount > NUM_SECONDARY_VOICES) + polyphonyCount = NUM_SECONDARY_VOICES; + if (pVoiceMgr->maxPolyphonySecondary == polyphonyCount) + return EAS_SUCCESS; + pVoiceMgr->maxPolyphonySecondary = (EAS_U16) polyphonyCount; + } + else + return EAS_ERROR_PARAMETER_RANGE; + + /* setting for SP-MIDI */ + pVoiceMgr->maxPolyphony = pVoiceMgr->maxPolyphonyPrimary + pVoiceMgr->maxPolyphonySecondary; + + /* standard architecture */ +#else + if (synth != EAS_MCU_SYNTH) + return EAS_ERROR_PARAMETER_RANGE; + + /* pin desired value to possible limits */ + if (polyphonyCount > MAX_SYNTH_VOICES) + polyphonyCount = MAX_SYNTH_VOICES; + + /* set polyphony, if value is different than current value */ + if (pVoiceMgr->maxPolyphony == polyphonyCount) + return EAS_SUCCESS; + + pVoiceMgr->maxPolyphony = (EAS_U16) polyphonyCount; +#endif + + /* if SPMIDI enabled, update channel masking based on new polyphony */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pVoiceMgr->pSynth[i]) + { + if (pVoiceMgr->pSynth[i]->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + VMMIPUpdateChannelMuting(pVoiceMgr, pVoiceMgr->pSynth[i]); + else + pVoiceMgr->pSynth[i]->poolAlloc[0] = (EAS_U8) polyphonyCount; + } + } + + /* are we under polyphony limit? */ + if (pVoiceMgr->activeVoices <= polyphonyCount) + return EAS_SUCCESS; + + /* count the number of active voices */ + activeVoices = 0; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + /* is voice active? */ + if ((pVoiceMgr->voices[i].voiceState != eVoiceStateFree) && (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting)) + activeVoices++; + } + + /* we may have to mute voices to reach new target */ + while (activeVoices > polyphonyCount) + { + S_SYNTH *pSynth; + S_SYNTH_VOICE *pVoice; + EAS_I32 currentPriority, bestPriority; + EAS_INT bestCandidate; + + /* find the lowest priority voice */ + bestPriority = bestCandidate = -1; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + pVoice = &pVoiceMgr->voices[i]; + + /* ignore free and muting voices */ + if ((pVoice->voiceState == eVoiceStateFree) || (pVoice->voiceState == eVoiceStateMuting)) + continue; + + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pVoice->voiceState == eVoiceStateStolen) || (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + /* include velocity */ + currentPriority = 128 - pVoice->nextVelocity; + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + else + { + /* include age */ + currentPriority = (EAS_I32) pVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->channel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + + /* include synth priority */ + currentPriority += pSynth->priority << SYNTH_PRIORITY_WEIGHT; + + /* is this the best choice so far? */ + if (currentPriority > bestPriority) + { + bestPriority = currentPriority; + bestCandidate = i; + } + } + + /* shutdown best candidate */ + if (bestCandidate < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMSetPolyphony: Unable to reduce polyphony\n"); */ } + break; + } + + /* shut down this voice */ + /*lint -e{771} pSynth is initialized if bestCandidate >= 0 */ + VMMuteVoice(pVoiceMgr, bestCandidate); + activeVoices--; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * + * Outputs: + * Returns actual polyphony value set, as pinned by limits + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 *pPolyphonyCount) +{ + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + if (synth == EAS_MCU_SYNTH) + *pPolyphonyCount = pVoiceMgr->maxPolyphonyPrimary; + else if (synth == EAS_DSP_SYNTH) + *pPolyphonyCount = pVoiceMgr->maxPolyphonySecondary; + else + return EAS_ERROR_PARAMETER_RANGE; +#else + if (synth != EAS_MCU_SYNTH) + return EAS_ERROR_PARAMETER_RANGE; + *pPolyphonyCount = pVoiceMgr->maxPolyphony; +#endif + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth polyphony. 0 = no limit (i.e. can use + * all available voices). + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 polyphonyCount) +{ + EAS_INT i; + EAS_INT activeVoices; + + /* check limits */ + if (polyphonyCount < 0) + return EAS_ERROR_PARAMETER_RANGE; + + /* zero is max polyphony */ + if ((polyphonyCount == 0) || (polyphonyCount > MAX_SYNTH_VOICES)) + { + pSynth->maxPolyphony = 0; + return EAS_SUCCESS; + } + + /* set new polyphony */ + pSynth->maxPolyphony = (EAS_U16) polyphonyCount; + + /* max polyphony is minimum of virtual synth and actual synth */ + if (polyphonyCount > pVoiceMgr->maxPolyphony) + polyphonyCount = pVoiceMgr->maxPolyphony; + + /* if SP-MIDI mode, update the channel muting */ + if (pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + VMMIPUpdateChannelMuting(pVoiceMgr, pSynth); + else + pSynth->poolAlloc[0] = (EAS_U8) polyphonyCount; + + /* are we under polyphony limit? */ + if (pSynth->numActiveVoices <= polyphonyCount) + return EAS_SUCCESS; + + /* count the number of active voices */ + activeVoices = 0; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + /* this synth? */ + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) != pSynth->vSynthNum) + continue; + + /* is voice active? */ + if ((pVoiceMgr->voices[i].voiceState != eVoiceStateFree) && (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting)) + activeVoices++; + } + + /* we may have to mute voices to reach new target */ + while (activeVoices > polyphonyCount) + { + S_SYNTH_VOICE *pVoice; + EAS_I32 currentPriority, bestPriority; + EAS_INT bestCandidate; + + /* find the lowest priority voice */ + bestPriority = bestCandidate = -1; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + pVoice = &pVoiceMgr->voices[i]; + + /* this synth? */ + if (GET_VSYNTH(pVoice->nextChannel) != pSynth->vSynthNum) + continue; + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pVoice->voiceState == eVoiceStateStolen) || (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + /* include velocity */ + currentPriority = 128 - pVoice->nextVelocity; + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + else + { + /* include age */ + currentPriority = (EAS_I32) pVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + + /* is this the best choice so far? */ + if (currentPriority > bestPriority) + { + bestPriority = currentPriority; + bestCandidate = i; + } + } + + /* shutdown best candidate */ + if (bestCandidate < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMSetPolyphony: Unable to reduce polyphony\n"); */ } + break; + } + + /* shut down this voice */ + VMMuteVoice(pVoiceMgr, bestCandidate); + activeVoices--; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth polyphony + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPolyphonyCount pointer to variable to hold polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMGetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPolyphonyCount) +{ + *pPolyphonyCount = (EAS_U16) pSynth->maxPolyphony; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * priority new priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMSetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 priority) +{ + pSynth->priority = (EAS_U8) priority ; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPriority pointer to variable to hold priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMGetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPriority) +{ + *pPriority = pSynth->priority; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for this synthesizer for this sequence. + * + * Inputs: + * nSynthVolume - the desired master volume + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +void VMSetVolume (S_SYNTH *pSynth, EAS_U16 masterVolume) +{ + pSynth->masterVolume = masterVolume; + pSynth->synthFlags |= SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMSetPitchBendRange() + *---------------------------------------------------------------------------- + * Set the pitch bend range for the given channel. + *---------------------------------------------------------------------------- +*/ +void VMSetPitchBendRange (S_SYNTH *pSynth, EAS_INT channel, EAS_I16 pitchBendRange) +{ + pSynth->channels[channel].pitchBendSensitivity = pitchBendRange; +} + +/*---------------------------------------------------------------------------- + * VMValidateEASLib() + *---------------------------------------------------------------------------- + * Validates an EAS library + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMValidateEASLib (EAS_SNDLIB_HANDLE pEAS) +{ + /* validate the sound library */ + if (pEAS) + { + if (pEAS->identifier != _EAS_LIBRARY_VERSION) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Sound library mismatch in sound library: Read 0x%08x, expected 0x%08x\n", + pEAS->identifier, _EAS_LIBRARY_VERSION); */ } + return EAS_ERROR_SOUND_LIBRARY; + } + + /* check sample rate */ + if ((pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK) != _OUTPUT_SAMPLE_RATE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Sample rate mismatch in sound library: Read %lu, expected %lu\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } + +#ifdef _WT_SYNTH + /* check sample bit depth */ +#ifdef _8_BIT_SAMPLES + if (pEAS->libAttr & LIB_FORMAT_16_BIT_SAMPLES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Expected 8-bit samples and found 16-bit\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } +#endif +#ifdef _16_BIT_SAMPLES + if ((pEAS->libAttr & LIB_FORMAT_16_BIT_SAMPLES) == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Expected 16-bit samples and found 8-bit\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } +#endif +#endif + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetGlobalEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the EAS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalEASLib (S_VOICE_MGR *pVoiceMgr, EAS_SNDLIB_HANDLE pEAS) +{ + EAS_RESULT result; + + result = VMValidateEASLib(pEAS); + if (result != EAS_SUCCESS) + return result; + + pVoiceMgr->pGlobalEAS = pEAS; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the EAS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetEASLib (S_SYNTH *pSynth, EAS_SNDLIB_HANDLE pEAS) +{ + EAS_RESULT result; + + result = VMValidateEASLib(pEAS); + if (result != EAS_SUCCESS) + return result; + + pSynth->pEAS = pEAS; + return EAS_SUCCESS; +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMSetGlobalDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the DLS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalDLSLib (EAS_DATA_HANDLE pEASData, EAS_DLSLIB_HANDLE pDLS) +{ + + if (pEASData->pVoiceMgr->pGlobalDLS) + DLSCleanup(pEASData->hwInstData, pEASData->pVoiceMgr->pGlobalDLS); + + pEASData->pVoiceMgr->pGlobalDLS = pDLS; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the DLS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetDLSLib (S_SYNTH *pSynth, EAS_DLSLIB_HANDLE pDLS) +{ + pSynth->pDLS = pDLS; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * VMSetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetTranposition (S_SYNTH *pSynth, EAS_I32 transposition) +{ + pSynth->globalTranspose = (EAS_I8) transposition; +} + +/*---------------------------------------------------------------------------- + * VMGetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMGetTranposition (S_SYNTH *pSynth, EAS_I32 *pTransposition) +{ + *pTransposition = pSynth->globalTranspose; +} + +/*---------------------------------------------------------------------------- + * VMGetNoteCount() + *---------------------------------------------------------------------------- +* Returns the total note count +*---------------------------------------------------------------------------- +*/ +EAS_I32 VMGetNoteCount (S_SYNTH *pSynth) +{ + return pSynth->totalNoteCount; +} + +/*---------------------------------------------------------------------------- + * VMMIDIShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMMIDIShutdown (S_EAS_DATA *pEASData, S_SYNTH *pSynth) +{ + EAS_INT vSynthNum; + + /* decrement reference count, free if all references are gone */ + if (--pSynth->refCount > 0) + return; + + vSynthNum = pSynth->vSynthNum; + + /* cleanup DLS load */ +#ifdef DLS_SYNTHESIZER + /*lint -e{550} result used only in debugging code */ + if (pSynth->pDLS != NULL) + { + EAS_RESULT result; + if ((result = DLSCleanup(pEASData->hwInstData, pSynth->pDLS)) != EAS_SUCCESS) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMMIDIShutdown: Error %ld cleaning up DLS collection\n", result); */ } + pSynth->pDLS = NULL; + } +#endif + + VMReset(pEASData->pVoiceMgr, pSynth, EAS_TRUE); + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pSynth); + + /* clear pointer to MIDI state */ + pEASData->pVoiceMgr->pSynth[vSynthNum] = NULL; +} + +/*---------------------------------------------------------------------------- + * VMShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMShutdown (S_EAS_DATA *pEASData) +{ + + /* don't free a NULL pointer */ + if (pEASData->pVoiceMgr == NULL) + return; + +#ifdef DLS_SYNTHESIZER + /* if we have a global DLS collection, clean it up */ + if (pEASData->pVoiceMgr->pGlobalDLS) + { + DLSCleanup(pEASData->hwInstData, pEASData->pVoiceMgr->pGlobalDLS); + pEASData->pVoiceMgr->pGlobalDLS = NULL; + } +#endif + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pEASData->pVoiceMgr); + pEASData->pVoiceMgr = NULL; +} + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Register a callback for external audio processing + *---------------------------------------------------------------------------- +*/ +void VMRegExtAudioCallback (S_SYNTH *pSynth, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc) +{ + pSynth->pExtAudioInstData = pInstData; + pSynth->cbProgChgFunc = cbProgChgFunc; + pSynth->cbEventFunc = cbEventFunc; +} + +/*---------------------------------------------------------------------------- + * VMGetMIDIControllers() + *---------------------------------------------------------------------------- + * Returns the MIDI controller values on the specified channel + *---------------------------------------------------------------------------- +*/ +void VMGetMIDIControllers (S_SYNTH *pSynth, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) +{ + pControl->modWheel = pSynth->channels[channel].modWheel; + pControl->volume = pSynth->channels[channel].volume; + pControl->pan = pSynth->channels[channel].pan; + pControl->expression = pSynth->channels[channel].expression; + pControl->channelPressure = pSynth->channels[channel].channelPressure; + +#ifdef _REVERB + pControl->reverbSend = pSynth->channels[channel].reverbSend; +#endif + +#ifdef _CHORUSE + pControl->chorusSend = pSynth->channels[channel].chorusSend; +#endif +} +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * VMStartFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Starts an audio frame + * + * Inputs: + * + * Outputs: + * Returns true if EAS_MixEnginePrep should be called (onboard mixing) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMStartFrame (S_EAS_DATA *pEASData) +{ + + /* init counter for voices starts in split architecture */ +#ifdef MAX_VOICE_STARTS + pVoiceMgr->numVoiceStarts = 0; +#endif + + return pFrameInterface->pfStartFrame(pEASData->pVoiceMgr->pFrameBuffer); +} + +/*---------------------------------------------------------------------------- + * VMEndFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Stops an audio frame + * + * Inputs: + * + * Outputs: + * Returns true if EAS_MixEnginePost should be called (onboard mixing) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMEndFrame (S_EAS_DATA *pEASData) +{ + + return pFrameInterface->pfEndFrame(pEASData->pVoiceMgr->pFrameBuffer, pEASData->pMixBuffer, pEASData->masterGain); +} +#endif + +#ifdef TEST_HARNESS +/*---------------------------------------------------------------------------- + * SanityCheck() + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSanityCheck (EAS_DATA_HANDLE pEASData) +{ + S_SYNTH_VOICE *pVoice; + S_SYNTH *pSynth; + EAS_INT i; + EAS_INT j; + EAS_INT freeVoices; + EAS_INT activeVoices; + EAS_INT playingVoices; + EAS_INT stolenVoices; + EAS_INT releasingVoices; + EAS_INT mutingVoices; + EAS_INT poolCount[MAX_VIRTUAL_SYNTHESIZERS][NUM_SYNTH_CHANNELS]; + EAS_INT vSynthNum; + EAS_RESULT result = EAS_SUCCESS; + + /* initialize counts */ + EAS_HWMemSet(poolCount, 0, sizeof(poolCount)); + freeVoices = activeVoices = playingVoices = stolenVoices = releasingVoices = mutingVoices = 0; + + /* iterate through all voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + pVoice = &pEASData->pVoiceMgr->voices[i]; + if (pVoice->voiceState != eVoiceStateFree) + { + vSynthNum = GET_VSYNTH(pVoice->channel); + if (vSynthNum >= MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Voice %d has invalid virtual synth number %d\n", i, vSynthNum); */ } + result = EAS_FAILURE; + continue; + } + pSynth = pEASData->pVoiceMgr->pSynth[vSynthNum]; + + switch (pVoice->voiceState) + { + case eVoiceStateMuting: + activeVoices++; + mutingVoices++; + break; + + case eVoiceStateStolen: + vSynthNum = GET_VSYNTH(pVoice->nextChannel); + if (vSynthNum >= MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Voice %d has invalid virtual synth number %d\n", i, vSynthNum); */ } + result = EAS_FAILURE; + continue; + } + pSynth = pEASData->pVoiceMgr->pSynth[vSynthNum]; + activeVoices++; + stolenVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool]++; + break; + + case eVoiceStateStart: + case eVoiceStatePlay: + activeVoices++; + playingVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->channel)].pool]++; + break; + + case eVoiceStateRelease: + activeVoices++; + releasingVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->channel)].pool]++; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck : voice %d in invalid state\n", i); */ } + result = EAS_FAILURE; + break; + } + } + + /* count free voices */ + else + freeVoices++; + } + + /* dump state info */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d free\n", freeVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d active\n", activeVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d playing\n", playingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d releasing\n", releasingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d muting\n", mutingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d stolen\n", stolenVoices); */ } + + if (pEASData->pVoiceMgr->activeVoices != activeVoices) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Active voice mismatch was %d should be %d\n", + pEASData->pVoiceMgr->activeVoices, activeVoices); */ } + result = EAS_FAILURE; + } + + /* check virtual synth status */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pEASData->pVoiceMgr->pSynth[i] == NULL) + continue; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Synth %d numActiveVoices: %d\n", i, pEASData->pVoiceMgr->pSynth[i]->numActiveVoices); */ } + if (pEASData->pVoiceMgr->pSynth[i]->numActiveVoices > MAX_SYNTH_VOICES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Synth %d illegal count for numActiveVoices: %d\n", i, pEASData->pVoiceMgr->pSynth[i]->numActiveVoices); */ } + result = EAS_FAILURE; + } + for (j = 0; j < NUM_SYNTH_CHANNELS; j++) + { + if (poolCount[i][j] != pEASData->pVoiceMgr->pSynth[i]->poolCount[j]) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Pool count mismatch synth %d pool %d, was %d, should be %d\n", + i, j, pEASData->pVoiceMgr->pSynth[i]->poolCount[j], poolCount[i][j]); */ } + result = EAS_FAILURE; + } + } + } + + return result; +} +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefile.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefile.c new file mode 100755 index 0000000..f24bde2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefile.c @@ -0,0 +1,867 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefile.c + * + * Contents and purpose: + * This file implements the wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 852 $ + * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_config.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_wavefile.h" + +/* lint is choking on the ARM math.h file, so we declare the log10 function here */ +extern double log10(double x); + +/* increase gain to compensate for loss in mixer */ +#define WAVE_GAIN_OFFSET 6 + +/* constant for 1200 / log10(2.0) */ +#define PITCH_CENTS_CONVERSION 3986.313714 + +/*---------------------------------------------------------------------------- + * WAVE file defines + *---------------------------------------------------------------------------- +*/ +/* RIFF chunks */ +#define CHUNK_TYPE(a,b,c,d) ( \ + ( ((EAS_U32)(a) & 0xFF) << 24 ) \ + + ( ((EAS_U32)(b) & 0xFF) << 16 ) \ + + ( ((EAS_U32)(c) & 0xFF) << 8 ) \ + + ( ((EAS_U32)(d) & 0xFF) ) ) + +#define CHUNK_RIFF CHUNK_TYPE('R','I','F','F') +#define CHUNK_WAVE CHUNK_TYPE('W','A','V','E') +#define CHUNK_FMT CHUNK_TYPE('f','m','t',' ') +#define CHUNK_DATA CHUNK_TYPE('d','a','t','a') +#define CHUNK_LIST CHUNK_TYPE('L','I','S','T') +#define CHUNK_INFO CHUNK_TYPE('I','N','F','O') +#define CHUNK_INAM CHUNK_TYPE('I','N','A','M') +#define CHUNK_ICOP CHUNK_TYPE('I','C','O','P') +#define CHUNK_IART CHUNK_TYPE('I','A','R','T') + +/* wave file format identifiers */ +#define WAVE_FORMAT_PCM 0x0001 +#define WAVE_FORMAT_IMA_ADPCM 0x0011 + +/* file size for streamed file */ +#define FILE_SIZE_STREAMING 0x80000000 + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset); +static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate); +static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData); +static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength); + +#ifdef MMAPI_SUPPORT +static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 size); +#endif + +/*---------------------------------------------------------------------------- + * + * EAS_Wave_Parser + * + * This structure contains the functional interface for the Wave file parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_Wave_Parser = +{ + WaveCheckFileType, + WavePrepare, + NULL, + NULL, + WaveState, + WaveClose, + WaveReset, + WavePause, + WaveResume, + WaveLocate, + WaveSetData, + WaveGetData, + WaveGetMetaData +}; + +/*---------------------------------------------------------------------------- + * WaveCheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset) +{ + S_WAVE_STATE *pWaveData; + + /* zero the memory to insure complete initialization */ + *pHandle = NULL; + + /* read the file header */ + if (WaveParseHeader(pEASData, fileHandle, NULL) == EAS_SUCCESS) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pWaveData = EAS_CMEnumData(EAS_CM_WAVE_DATA); + else + pWaveData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_WAVE_STATE)); + if (!pWaveData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pWaveData, 0, sizeof(S_WAVE_STATE)); + + /* return a pointer to the instance data */ + pWaveData->fileHandle = fileHandle; + pWaveData->fileOffset = offset; + *pHandle = pWaveData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WavePrepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + + /* validate parser state */ + pWaveData = (S_WAVE_STATE*) pInstData; + if (pWaveData->streamHandle != NULL) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* back to start of file */ + pWaveData->time = 0; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->fileOffset)) != EAS_SUCCESS) + return result; + + /* parse the file header */ + if ((result = WaveParseHeader(pEASData, pWaveData->fileHandle, pWaveData)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState) +{ + S_WAVE_STATE *pWaveData; + + /* return current state */ + pWaveData = (S_WAVE_STATE*) pInstData; + if (pWaveData->streamHandle) + return EAS_PEState(pEASData, pWaveData->streamHandle, pState); + + /* if no stream handle, and time is not zero, we are done */ + if (pWaveData->time > 0) + *pState = EAS_STATE_STOPPED; + else + *pState = EAS_STATE_OPEN; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + + pWaveData = (S_WAVE_STATE*) pInstData; + + /* close the stream */ + if (pWaveData->streamHandle) + { + if ((result = EAS_PEClose(pEASData, pWaveData->streamHandle)) != EAS_SUCCESS) + return result; + pWaveData->streamHandle = NULL; + } + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + { + +#ifdef MMAPI_SUPPORT + /* need to free the fmt chunk */ + if (pWaveData->fmtChunk != NULL) + EAS_HWFree(pEASData->hwInstData, pWaveData->fmtChunk); +#endif + + /* free the instance data */ + EAS_HWFree(pEASData->hwInstData, pWaveData); + + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveReset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* reset to first byte of data in the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEReset(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveLocate() + *---------------------------------------------------------------------------- + * Purpose: + * Rewind/fast-forward in file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * time - time (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pParserLocate) reserved for future use */ +static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate) +{ + EAS_PCM_HANDLE streamHandle; + + /* reset to first byte of data in the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PELocate(pEASData, streamHandle, time); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WavePause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* pause the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEPause(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* resume the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEResume(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveSetData() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_WAVE_STATE *pWaveData = (S_WAVE_STATE*) pInstData; + + switch (param) + { + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pWaveData->metadata, (void*) value, sizeof(S_METADATA_CB)); + return EAS_SUCCESS; + + case PARSER_DATA_PLAYBACK_RATE: + value = (EAS_I32) (PITCH_CENTS_CONVERSION * log10((double) value / (double) (1 << 28))); + return EAS_PEUpdatePitch(pEASData, pWaveData->streamHandle, (EAS_I16) value); + + case PARSER_DATA_VOLUME: + return EAS_PEUpdateVolume(pEASData, pWaveData->streamHandle, (EAS_I16) value); + + default: + return EAS_ERROR_INVALID_PARAMETER; + } +} + +/*---------------------------------------------------------------------------- + * WaveGetData() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_WAVE_STATE *pWaveData; + + pWaveData = (S_WAVE_STATE*) pInstData; + switch (param) + { + /* return file type as WAVE */ + case PARSER_DATA_FILE_TYPE: + *pValue = pWaveData->fileType; + break; + +#ifdef MMAPI_SUPPORT + /* return pointer to 'fmt' chunk */ + case PARSER_DATA_FORMAT: + *pValue = (EAS_I32) pWaveData->fmtChunk; + break; +#endif + + case PARSER_DATA_GAIN_OFFSET: + *pValue = WAVE_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the WAVE file header. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData) +{ + S_PCM_OPEN_PARAMS params; + EAS_RESULT result; + EAS_U32 tag; + EAS_U32 fileSize; + EAS_U32 size; + EAS_I32 pos; + EAS_I32 audioOffset; + EAS_U16 usTemp; + EAS_BOOL parseDone; + EAS_U32 avgBytesPerSec; + + /* init some data (and keep lint happy) */ + params.sampleRate = 0; + params.size = 0; + audioOffset = 0; + params.decoder = 0; + params.blockSize = 0; + params.pCallbackFunc = NULL; + params.cbInstData = NULL; + params.loopSamples = 0; + params.fileHandle = fileHandle; + params.volume = 0x7fff; + params.envData = 0; + avgBytesPerSec = 8000; + + /* check for 'RIFF' tag */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag != CHUNK_RIFF) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get size */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &fileSize, EAS_FALSE)) != EAS_FALSE) + return result; + + /* check for 'WAVE' tag */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag != CHUNK_WAVE) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* this is enough to say we recognize the file */ + if (pWaveData == NULL) + return EAS_SUCCESS; + + /* check for streaming mode */ + pWaveData->flags = 0; + pWaveData->mediaLength = -1; + pWaveData->infoChunkPos = -1; + pWaveData->infoChunkSize = -1; + if (fileSize== FILE_SIZE_STREAMING) + { + pWaveData->flags |= PCM_FLAGS_STREAMING; + fileSize = 0x7fffffff; + } + + /* find out where we're at */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS) + return result; + fileSize -= 4; + + parseDone = EAS_FALSE; + for (;;) + { + /* get tag and size for next chunk */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &size, EAS_FALSE)) != EAS_FALSE) + return result; + + /* process chunk */ + pos += 8; + switch (tag) + { + case CHUNK_FMT: + +#ifdef MMAPI_SUPPORT + if ((result = SaveFmtChunk(pEASData, fileHandle, pWaveData, (EAS_I32) size)) != EAS_SUCCESS) + return result; +#endif + + /* get audio format */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + if (usTemp == WAVE_FORMAT_PCM) + { + params.decoder = EAS_DECODER_PCM; + pWaveData->fileType = EAS_FILE_WAVE_PCM; + } + else if (usTemp == WAVE_FORMAT_IMA_ADPCM) + { + params.decoder = EAS_DECODER_IMA_ADPCM; + pWaveData->fileType = EAS_FILE_WAVE_IMA_ADPCM; + } + else + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get number of channels */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + if (usTemp == 2) + pWaveData->flags |= PCM_FLAGS_STEREO; + else if (usTemp != 1) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get sample rate */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, ¶ms.sampleRate, EAS_FALSE)) != EAS_FALSE) + return result; + + /* get stream rate */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &avgBytesPerSec, EAS_FALSE)) != EAS_FALSE) + return result; + + /* get block alignment */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + params.blockSize = usTemp; + + /* get bits per sample */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + + /* PCM, must be 8 or 16 bit samples */ + if (params.decoder == EAS_DECODER_PCM) + { + if (usTemp == 8) + pWaveData->flags |= PCM_FLAGS_8_BIT | PCM_FLAGS_UNSIGNED; + else if (usTemp != 16) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* for IMA ADPCM, we only support mono 4-bit ADPCM */ + else + { + if ((usTemp != 4) || (pWaveData->flags & PCM_FLAGS_STEREO)) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + break; + + case CHUNK_DATA: + audioOffset = pos; + if (pWaveData->flags & PCM_FLAGS_STREAMING) + { + params.size = 0x7fffffff; + parseDone = EAS_TRUE; + } + else + { + params.size = (EAS_I32) size; + params.loopStart = size; + /* use more accurate method if possible */ + if (size <= (0x7fffffff / 1000)) + pWaveData->mediaLength = (EAS_I32) ((size * 1000) / avgBytesPerSec); + else + pWaveData->mediaLength = (EAS_I32) (size / (avgBytesPerSec / 1000)); + } + break; + + case CHUNK_LIST: + /* get the list type */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag == CHUNK_INFO) + { + pWaveData->infoChunkPos = pos + 4; + pWaveData->infoChunkSize = (EAS_I32) size - 4; + } + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + if (parseDone) + break; + + /* subtract header size */ + fileSize -= 8; + + /* account for zero-padding on odd length chunks */ + if (size & 1) + size++; + + /* this check works for files with odd length last chunk and no zero-pad */ + if (size >= fileSize) + { + if (size > fileSize) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: '%c%c%c%c' chunk size exceeds length of file or is not zero-padded\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + /* subtract size of data chunk (including any zero-pad) */ + fileSize -= size; + + /* seek to next chunk */ + pos += (EAS_I32) size; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos)) != EAS_SUCCESS) + return result; + } + + /* check for valid header */ + if ((params.sampleRate == 0) || (params.size == 0)) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* save the pertinent information */ + pWaveData->audioOffset = audioOffset; + params.flags = pWaveData->flags; + + /* seek to data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, audioOffset)) != EAS_SUCCESS) + return result; + + /* open a stream in the PCM engine */ + return EAS_PEOpenStream(pEASData, ¶ms, &pWaveData->streamHandle); +} + +/*---------------------------------------------------------------------------- + * WaveGetMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * Process the INFO chunk and return metadata to host + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + EAS_I32 pos; + EAS_U32 size; + EAS_I32 infoSize; + EAS_U32 tag; + EAS_I32 restorePos; + E_EAS_METADATA_TYPE metaType; + EAS_I32 metaLen; + + /* get current position so we can restore it */ + pWaveData = (S_WAVE_STATE*) pInstData; + + /* return media length */ + *pMediaLength = pWaveData->mediaLength; + + /* did we encounter an INFO chunk? */ + if (pWaveData->infoChunkPos < 0) + return EAS_SUCCESS; + + if ((result = EAS_HWFilePos(pEASData->hwInstData, pWaveData->fileHandle, &restorePos)) != EAS_SUCCESS) + return result; + + /* offset to start of first chunk in INFO chunk */ + pos = pWaveData->infoChunkPos; + infoSize = pWaveData->infoChunkSize; + + /* read all the chunks in the INFO chunk */ + for (;;) + { + + /* seek to next chunk */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get tag and size for next chunk */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &size, EAS_FALSE)) != EAS_FALSE) + return result; + + /* process chunk */ + pos += 8; + metaType = EAS_METADATA_UNKNOWN; + switch (tag) + { + case CHUNK_INAM: + metaType = EAS_METADATA_TITLE; + break; + + case CHUNK_IART: + metaType = EAS_METADATA_AUTHOR; + break; + + case CHUNK_ICOP: + metaType = EAS_METADATA_COPYRIGHT; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + /* process known metadata */ + if (metaType != EAS_METADATA_UNKNOWN) + { + metaLen = pWaveData->metadata.bufferSize - 1; + if (metaLen > (EAS_I32) size) + metaLen = (EAS_I32) size; + if ((result = EAS_HWReadFile(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->metadata.buffer, metaLen, &metaLen)) != EAS_SUCCESS) + return result; + pWaveData->metadata.buffer[metaLen] = 0; + pWaveData->metadata.callback(metaType, pWaveData->metadata.buffer, pWaveData->metadata.pUserData); + } + + /* subtract this block */ + if (size & 1) + size++; + infoSize -= (EAS_I32) size + 8; + if (infoSize == 0) + break; + pos += (EAS_I32) size; + } + + + /* restore original position */ + return EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, restorePos); +} + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * SaveFmtChunk() + *---------------------------------------------------------------------------- + * Purpose: + * Save the fmt chunk for the MMAPI library + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 fmtSize) +{ + EAS_RESULT result; + EAS_I32 pos; + EAS_I32 count; + + /* save current file position */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS) + return result; + + /* allocate a chunk of memory */ + pWaveData->fmtChunk = EAS_HWMalloc(pEASData->hwInstData, fmtSize); + if (!pWaveData->fmtChunk) + return EAS_ERROR_MALLOC_FAILED; + + /* read the fmt chunk into memory */ + if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, pWaveData->fmtChunk, fmtSize, &count)) != EAS_SUCCESS) + return result; + if (count != fmtSize) + return EAS_ERROR_FILE_READ_FAILED; + + /* restore file position */ + return EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos); +} +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefile.h b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefile.h new file mode 100755 index 0000000..f8814a8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefile.h @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefile.h + * + * Contents and purpose: + * Static data block for wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 439 $ + * $Date: 2006-10-26 11:53:18 -0700 (Thu, 26 Oct 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WAVEFILE_H +#define _EAS_WAVEFILE_H + +#include "eas_data.h" +#include "eas_pcm.h" + +/*---------------------------------------------------------------------------- + * + * S_WAVE_STATE + * + * This structure contains the WAVE file parser state information + *---------------------------------------------------------------------------- +*/ +typedef struct s_wave_state_tag +{ + EAS_FILE_HANDLE fileHandle; + EAS_PCM_HANDLE streamHandle; + S_METADATA_CB metadata; + EAS_U32 time; + EAS_I32 fileOffset; + EAS_I32 audioOffset; + EAS_I32 mediaLength; + EAS_U32 audioSize; + EAS_U32 flags; + EAS_I16 fileType; +#ifdef MMAPI_SUPPORT + EAS_VOID_PTR fmtChunk; +#endif + EAS_I32 infoChunkPos; + EAS_I32 infoChunkSize; +} S_WAVE_STATE; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefiledata.c b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefiledata.c new file mode 100755 index 0000000..c224a6c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-fm-22k/lib_src/eas_wavefiledata.c @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefiledata.c + * + * Contents and purpose: + * Static data block for wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_wavefile.h" + +S_WAVE_STATE eas_WaveData; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/Makefile b/code/embeddedaudiosynthesis/arm-hybrid-22k/Makefile new file mode 100755 index 0000000..5648139 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/Makefile @@ -0,0 +1,66 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES = \ + lib_src/eas_chorus.c \ + lib_src/eas_chorusdata.c \ + lib_src/eas_data.c \ + lib_src/eas_fmengine.c \ + lib_src/eas_fmsynth.c \ + lib_src/eas_fmtables.c \ + lib_src/eas_ima_tables.c \ + lib_src/eas_imaadpcm.c \ + lib_src/eas_imelody.c \ + lib_src/eas_imelodydata.c \ + lib_src/eas_math.c \ + lib_src/eas_midi.c \ + lib_src/eas_mididata.c \ + lib_src/eas_mixbuf.c \ + lib_src/eas_mixer.c \ + lib_src/eas_ota.c \ + lib_src/eas_otadata.c \ + lib_src/eas_pan.c \ + lib_src/eas_pcm.c \ + lib_src/eas_pcmdata.c \ + lib_src/eas_public.c \ + lib_src/eas_reverb.c \ + lib_src/eas_reverbdata.c \ + lib_src/eas_rtttl.c \ + lib_src/eas_rtttldata.c \ + lib_src/eas_smf.c \ + lib_src/eas_smfdata.c \ + lib_src/eas_voicemgt.c \ + lib_src/eas_wavefile.c \ + lib_src/eas_wavefiledata.c \ + lib_src/eas_wtengine.c \ + lib_src/eas_wtsynth.c \ + lib_src/hybrid_22khz_mcu.c \ + host_src/eas_config.c \ + host_src/eas_hostmm.c \ + host_src/eas_main.c \ + host_src/eas_report.c \ + host_src/eas_wave.c + +LOCAL_CFLAGS+= -O2 -D UNIFIED_DEBUG_MESSAGES -D EAS_HYBRID_SYNTH \ + -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER \ + -D _WAVE_PARSER -D _REVERB_ENABLED \ + -D _CHORUS_ENABLED -D NUM_OUTPUT_CHANNELS=2 \ + -D _SAMPLE_RATE_22050 -D MAX_SYNTH_VOICES=32 \ + -D NUM_PRIMARY_VOICES=8 \ + -D _8_BIT_SAMPLES -D _FILTER_ENABLED -D _IMELODY_PARSER \ + -D _IMA_DECODER + +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH)/host_src/ \ + $(LOCAL_PATH)/lib_src/ + +LOCAL_ARM_MODE := arm + +LOCAL_MODULE := libsonivox + +LOCAL_COPY_HEADERS_TO := libsonivox +LOCAL_COPY_HEADERS := \ + host_src/eas.h \ + host_src/eas_types.h + +include $(BUILD_SHARED_LIBRARY) diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/bin/arm-hybrid-22k b/code/embeddedaudiosynthesis/arm-hybrid-22k/bin/arm-hybrid-22k new file mode 100755 index 0000000..ea80a08 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-hybrid-22k/bin/arm-hybrid-22k differ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/arm-hybrid-22k.mak b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/arm-hybrid-22k.mak new file mode 100755 index 0000000..8874f31 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/arm-hybrid-22k.mak @@ -0,0 +1,25 @@ +# +# Auto-generated sample makefile +# +# This makefile is intended for use with GNU make. +# Set the paths to the tools (CC, AR, LD, etc.) +# + +vpath %.c host_src + +CC = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AS = C:\Program Files\GNUARM\bin\arm-elf-as.exe +LD = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AR = C:\Program Files\GNUARM\bin\arm-elf-ar.exe + +%.o: %.c + $(CC) -c -O2 -o $@ -I host_src -D UNIFIED_DEBUG_MESSAGES -D EAS_HYBRID_SYNTH -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED $< + +%.o: %.s + $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa -I lib_src --defsym CHECK_STACK=0 --defsym REVERB=0 --defsym CHORUS=0 --defsym STEREO_OUTPUT=1 --defsym SAMPLE_RATE_22050=1 --defsym SAMPLES_8_BIT=1 --defsym FILTER_ENABLED=1 $< + +OBJS = eas_main.o eas_report.o eas_wave.o eas_hostmm.o eas_config.o + +arm-hybrid-22k: $(OBJS) + $(LD) -o $@ $(OBJS) libarm-hybrid-22k.a -lm + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas.h new file mode 100755 index 0000000..c64af49 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas.h @@ -0,0 +1,1062 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas.h + * + * Contents and purpose: + * The public interface header for the EAS synthesizer. + * + * This header only contains declarations that are specific + * to this implementation. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2005, 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 852 $ + * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_H +#define _EAS_H + +#include "eas_types.h" + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +/* library version macro */ +#define MAKE_LIB_VERSION(a,b,c,d) (((((((EAS_U32) a <<8) | (EAS_U32) b) << 8) | (EAS_U32) c) << 8) | (EAS_U32) d) +#define LIB_VERSION MAKE_LIB_VERSION(3, 6, 10, 14) + +typedef struct +{ + EAS_U32 libVersion; + EAS_BOOL checkedVersion; + EAS_I32 maxVoices; + EAS_I32 numChannels; + EAS_I32 sampleRate; + EAS_I32 mixBufferSize; + EAS_BOOL filterEnabled; + EAS_U32 buildTimeStamp; + EAS_CHAR *buildGUID; +} S_EAS_LIB_CONFIG; + +/* enumerated effects module numbers for configuration */ +typedef enum +{ + EAS_MODULE_ENHANCER = 0, + EAS_MODULE_COMPRESSOR, + EAS_MODULE_REVERB, + EAS_MODULE_CHORUS, + EAS_MODULE_WIDENER, + EAS_MODULE_GRAPHIC_EQ, + EAS_MODULE_WOW, + EAS_MODULE_MAXIMIZER, + EAS_MODULE_TONECONTROLEQ, + NUM_EFFECTS_MODULES +} E_FX_MODULES; + +/* enumerated optional module numbers for configuration */ +typedef enum +{ + EAS_MODULE_MMAPI_TONE_CONTROL = 0, + EAS_MODULE_METRICS +} E_OPT_MODULES; +#define NUM_OPTIONAL_MODULES 2 + +/* enumerated audio decoders for configuration */ +typedef enum +{ + EAS_DECODER_PCM = 0, + EAS_DECODER_SMAF_ADPCM, + EAS_DECODER_IMA_ADPCM, + EAS_DECODER_7BIT_SMAF_ADPCM, + EAS_DECODER_NOT_SUPPORTED +} E_DECODER_MODULES; +#define NUM_DECODER_MODULES 4 + +/* defines for EAS_PEOpenStream flags parameter */ +#define PCM_FLAGS_STEREO 0x00000100 /* stream is stereo */ +#define PCM_FLAGS_8_BIT 0x00000001 /* 8-bit format */ +#define PCM_FLAGS_UNSIGNED 0x00000010 /* unsigned format */ +#define PCM_FLAGS_STREAMING 0x80000000 /* streaming mode */ + +/* maximum volume setting */ +#define EAS_MAX_VOLUME 100 + +/*---------------------------------------------------------------------------- + * EAS_Init() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the synthesizer library + * + * Inputs: + * polyphony - number of voices to play (dynamic memory model only) + * ppLibData - pointer to data handle variable for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData); + +/*---------------------------------------------------------------------------- + * EAS_Config() + *---------------------------------------------------------------------------- + * Purpose: + * Returns a pointer to a structure containing the configuration options + * in this library build. + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void); + +/*---------------------------------------------------------------------------- + * EAS_Shutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the library. Deallocates any memory associated with the + * synthesizer (dynamic memory model only) + * + * Inputs: + * pEASData - handle to data for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_Render() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the Midi data and render PCM audio data. + * + * Inputs: + * pEASData - buffer for internal EAS data + * pOut - output buffer pointer + * nNumRequested - requested num samples to generate + * pnNumGenerated - actual number of samples generated + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated); + +/*---------------------------------------------------------------------------- + * EAS_SetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Set the selected stream to repeat. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * repeatCount - repeat count (0 = no repeat, -1 = repeat forever) + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 repeatCount); + +/*---------------------------------------------------------------------------- + * EAS_GetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the current repeat count for the selected stream. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * pRrepeatCount - pointer to variable to hold repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pRepeatCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPlaybackRate() + *---------------------------------------------------------------------------- + * Purpose: + * Set the playback rate. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U32 rate); +#define MAX_PLAYBACK_RATE (EAS_U32)(1L << 29) +#define MIN_PLAYBACK_RATE (EAS_U32)(1L << 27) + +/*---------------------------------------------------------------------------- + * EAS_SetTransposition) + *---------------------------------------------------------------------------- + * Purpose: + * Sets the key tranposition for the synthesizer. Transposes all + * melodic instruments by the specified amount. Range is limited + * to +/-12 semitones. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * transposition - +/-12 semitones + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 transposition); +#define MAX_TRANSPOSE 12 + +/*---------------------------------------------------------------------------- + * EAS_SetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the synthesizer. Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_GetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the stream. Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_GetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the priority of the stream. Determines which stream's voices + * are stolen when there are insufficient voices for all notes. + * Value must be in the range of 1-255, lower values are higher + * priority. The default priority is 50. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 priority); + +/*---------------------------------------------------------------------------- + * EAS_GetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current priority setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPriority - pointer to variable to receive priority + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPriority); + +/*---------------------------------------------------------------------------- + * EAS_SetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for the mixer. The default volume setting is + * 90 (-10 dB). The volume range is 0 to 100 in 1dB increments. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 volume); + +/*---------------------------------------------------------------------------- + * EAS_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the master volume for the mixer in 1dB increments. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_SetMaxLoad() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the maximum workload the parsers will do in a single call to + * EAS_Render. The units are currently arbitrary, but should correlate + * well to the actual CPU cycles consumed. The primary effect is to + * reduce the occasional peaks in CPU cycles consumed when parsing + * dense parts of a MIDI score. Setting maxWorkLoad to zero disables + * the workload limiting function. + * + * Inputs: + * pEASData - handle to data for this instance + * maxLoad - the desired maximum workload + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad); + +/*---------------------------------------------------------------------------- + * EAS_SetMaxPCMStreams() + *---------------------------------------------------------------------------- + * Sets the maximum number of PCM streams allowed in parsers that + * use PCM streaming. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * maxNumStreams - maximum number of PCM streams + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams); + +/*---------------------------------------------------------------------------- + * EAS_OpenFile() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * locator - pointer to filename or other locating information + * pStreamHandle - pointer to stream handle variable + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle); + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * EAS_MMAPIToneControl() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a ToneControl file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * locator - pointer to filename or other locating information + * pStreamHandle - pointer to stream handle variable + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle); + +/*---------------------------------------------------------------------------- + * EAS_GetWaveFmtChunk + *---------------------------------------------------------------------------- + * Helper function to retrieve WAVE file fmt chunk for MMAPI + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * streamHandle - stream handle + * pFmtChunk - pointer to pointer to FMT chunk data + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_VOID_PTR *ppFmtChunk); +#endif + +/*---------------------------------------------------------------------------- + * EAS_GetFileType + *---------------------------------------------------------------------------- + * Returns the file type (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * streamHandle - stream handle + * pFileType - pointer to variable to receive file type + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetFileType (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pFileType); + +/*---------------------------------------------------------------------------- + * EAS_ParseMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * playLength - pointer to variable to store the play length (in msecs) + * + * Outputs: + * + * + * Side Effects: + * - resets the parser to the start of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPlayLength); + +/*---------------------------------------------------------------------------- + * EAS_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the synthesizer to play the file or stream. Parses the first + * frame of data from the file and arms the synthesizer. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the state of an audio file or stream. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_RegisterMetaDataCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers a metadata callback function for parsed metadata. To + * de-register the callback, call this function again with parameter + * cbFunc set to NULL. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * cbFunc - pointer to host callback function + * metaDataBuffer - pointer to metadata buffer + * metaDataBufSize - maximum size of the metadata buffer + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( + EAS_DATA_HANDLE pEASData, + EAS_HANDLE streamHandle, + EAS_METADATA_CBFUNC cbFunc, + char *metaDataBuffer, + EAS_I32 metaDataBufSize, + EAS_VOID_PTR pUserData); + +/*---------------------------------------------------------------------------- + * EAS_GetNoteCount () + *---------------------------------------------------------------------------- + * Returns the total number of notes played in this stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * pNoteCount - pointer to variable to receive note count + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount); + +/*---------------------------------------------------------------------------- + * EAS_CloseFile() + *---------------------------------------------------------------------------- + * Purpose: + * Closes an audio file or stream. Playback should have either paused or + * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_OpenMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pStreamHandle - pointer to variable to hold file or stream handle + * streamHandle - open stream or NULL for new synthesizer instance + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *pStreamHandle, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_WriteMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Send data to the MIDI stream device + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - stream handle + * pBuffer - pointer to buffer + * count - number of bytes to write + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream(EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 *pBuffer, EAS_I32 count); + +/*---------------------------------------------------------------------------- + * EAS_CloseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Closes a raw MIDI stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_Locate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate into the file associated with the handle. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file handle + * milliseconds - playback offset from start of file in milliseconds + * + * Outputs: + * + * + * Side Effects: + * the actual offset will be quantized to the closest update period, typically + * a resolution of 5.9ms. Notes that are started prior to this time will not + * sound. Any notes currently playing will be shut off. + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 milliseconds, EAS_BOOL offset); + +/*---------------------------------------------------------------------------- + * EAS_GetRenderTime() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * Gets the render time clock in msecs. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime); + +/*---------------------------------------------------------------------------- + * EAS_GetLocation() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file handle + * + * Outputs: + * The offset in milliseconds from the start of the current sequence, quantized + * to the nearest update period. Actual resolution is typically 5.9 ms. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pTime); + +/*---------------------------------------------------------------------------- + * EAS_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the playback of the data associated with this handle. The audio + * is gracefully ramped down to prevent clicks and pops. It may take several + * buffers of audio before the audio is muted. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resumes the playback of the data associated with this handle. The audio + * is gracefully ramped up to prevent clicks and pops. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_GetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * module - enumerated module number + * param - enumerated parameter number + * pValue - pointer to variable to receive parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue); + +/*---------------------------------------------------------------------------- + * EAS_SetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * value - new parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value); + +#ifdef _METRICS_ENABLED +/*---------------------------------------------------------------------------- + * EAS_MetricsReport() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the EAS_Report interface. + * + * Inputs: + * pEASData - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_MetricsReset() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the EAS_Report interface. + * + * Inputs: + * pEASData - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetSoundLibrary() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * streamHandle - file or stream handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_SNDLIB_HANDLE pSndLib); + +/*---------------------------------------------------------------------------- + * EAS_SetHeaderSearchFlag() + *---------------------------------------------------------------------------- + * By default, when EAS_OpenFile is called, the parsers check the + * first few bytes of the file looking for a specific header. Some + * mobile devices may add a header to the start of a file, which + * will prevent the parser from recognizing the file. If the + * searchFlag is set to EAS_TRUE, the parser will search the entire + * file looking for the header. This may enable EAS to recognize + * some files that it would ordinarily reject. The negative is that + * it make take slightly longer to process the EAS_OpenFile request. + * + * Inputs: + * pEASData - instance data handle + * searchFlag - search flag (EAS_TRUE or EAS_FALSE) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag); + +/*---------------------------------------------------------------------------- + * EAS_SetPlayMode() + *---------------------------------------------------------------------------- + * Some file formats support special play modes, such as iMode partial + * play mode. This call can be used to change the play mode. The + * default play mode (usually straight playback) is always zero. + * + * Inputs: + * pEASData - instance data handle + * handle - file or stream handle + * playMode - play mode (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode); + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * EAS_LoadDLSCollection() + *---------------------------------------------------------------------------- + * Purpose: + * Downloads a DLS collection + * + * Inputs: + * pEASData - instance data handle + * streamHandle - file or stream handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_FILE_LOCATOR locator); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetFrameBuffer() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the frame buffer pointer passed to the IPC communications functions + * + * Inputs: + * pEASData - instance data handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers callback functions for audio events. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * cbProgChgFunc - pointer to host callback function for program change + * cbEventFunc - pointer to host callback functio for note events + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, + EAS_HANDLE streamHandle, + EAS_VOID_PTR pInstData, + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, + EAS_EXT_EVENT_FUNC cbEventFunc); + +/*---------------------------------------------------------------------------- + * EAS_GetMIDIControllers() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of MIDI controllers on the requested channel. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * pControl - pointer to structure to receive data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SearchFile + *---------------------------------------------------------------------------- + * Search file for specific sequence starting at current file + * position. Returns offset to start of sequence. + * + * Inputs: + * pEASData - pointer to EAS persistent data object + * fileHandle - file handle + * searchString - pointer to search sequence + * len - length of search sequence + * pOffset - pointer to variable to store offset to sequence + * + * Returns EAS_EOF if end-of-file is reached + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SearchFile (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* #ifndef _EAS_H */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_build.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_build.h new file mode 100755 index 0000000..0e26211 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_build.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------- + * + * File: + * host_src\eas_build.h + * + * Contents and purpose: + * This file contains the build configuration for this + * build. The buildGUIDStr is a GUID created during + * the build process and is guaranteed to be unique + * for each build. + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file was autogenerated by buildid.exe + *---------------------------------------------------------------------------- +*/ + +#ifndef _GUID_0cbd200ab054487f9ece7d3c8852e426_ +#define _GUID_0cbd200ab054487f9ece7d3c8852e426_ + +#define _BUILD_VERSION_ "0cbd200a-b054-487f-9ece-7d3c8852e426" +#define _BUILD_TIME_ 0x4743b9dc + +#endif /* _GUID_0cbd200ab054487f9ece7d3c8852e426_ */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_chorus.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_chorus.h new file mode 100755 index 0000000..998a828 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_chorus.h @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorus.h + * + * Contents and purpose: + * Contains parameter enumerations for the Chorus effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 309 $ + * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_CHORUS_H +#define EAS_CHORUS_H + +/* enumerated parameter settings for Chorus effect */ +typedef enum +{ + EAS_PARAM_CHORUS_BYPASS, + EAS_PARAM_CHORUS_PRESET, + EAS_PARAM_CHORUS_RATE, + EAS_PARAM_CHORUS_DEPTH, + EAS_PARAM_CHORUS_LEVEL +} E_CHORUS_PARAMS; + +typedef enum +{ + EAS_PARAM_CHORUS_PRESET1, + EAS_PARAM_CHORUS_PRESET2, + EAS_PARAM_CHORUS_PRESET3, + EAS_PARAM_CHORUS_PRESET4 +} E_CHORUS_PRESETS; + + +#endif \ No newline at end of file diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_config.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_config.c new file mode 100755 index 0000000..0b92357 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_config.c @@ -0,0 +1,619 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_config.c + * + * Contents and purpose: + * This file contains the Configuration Module interface (CM). The CM + * is a module compiled external to the library that sets the configuration + * for this build. It allows the library to find optional components and + * links to static memory allocations (when used in a static configuration). + * + * DO NOT MODIFY THIS FILE! + * + * NOTE: This module is not intended to be modified by the customer. It + * needs to be included in the build process with the correct configuration + * defines (see the library documentation for information on how to configure + * the library). + * + * Copyright Sonic Network Inc. 2004-2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 796 $ + * $Date: 2007-08-01 00:15:25 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas.h" +#include "eas_config.h" + + +#ifdef _MFI_PARSER +/*---------------------------------------------------------------------------- + * Vendor/Device ID for MFi Extensions + * + * Define the preprocessor symbols to establish the vendor ID and + * device ID for the MFi PCM/ADPCM extensions. + *---------------------------------------------------------------------------- +*/ +const EAS_U8 eas_MFIVendorIDMSB = (MFI_VENDOR_ID >> 8) & 0xff; +const EAS_U8 eas_MFIVendorIDLSB = MFI_VENDOR_ID & 0xff; +const EAS_U8 eas_MFIDeviceID = MFI_DEVICE_ID; +#endif + +/*---------------------------------------------------------------------------- + * + * parserModules + * + * This structure is used by the EAS library to locate file parsing + * modules. + *---------------------------------------------------------------------------- +*/ + +/* define the external file parsers */ +extern EAS_VOID_PTR EAS_SMF_Parser; + +#ifdef _XMF_PARSER +extern EAS_VOID_PTR EAS_XMF_Parser; +#endif + +#ifdef _SMAF_PARSER +extern EAS_VOID_PTR EAS_SMAF_Parser; +#endif + +#ifdef _WAVE_PARSER +extern EAS_VOID_PTR EAS_Wave_Parser; +#endif + +#ifdef _OTA_PARSER +extern EAS_VOID_PTR EAS_OTA_Parser; +#endif + +#ifdef _IMELODY_PARSER +extern EAS_VOID_PTR EAS_iMelody_Parser; +#endif + +#ifdef _RTTTL_PARSER +extern EAS_VOID_PTR EAS_RTTTL_Parser; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) +extern EAS_VOID_PTR EAS_CMF_Parser; +#endif + +/* initalize pointers to parser interfaces */ +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const parserModules[] = +{ + &EAS_SMF_Parser, + +#ifdef _XMF_PARSER + &EAS_XMF_Parser, +#endif + +#ifdef _WAVE_PARSER + &EAS_Wave_Parser, +#endif + +#ifdef _SMAF_PARSER + &EAS_SMAF_Parser, +#endif + +#ifdef _OTA_PARSER + &EAS_OTA_Parser, +#endif + +#ifdef _IMELODY_PARSER + &EAS_iMelody_Parser, +#endif + +#ifdef _RTTTL_PARSER + &EAS_RTTTL_Parser, +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) + &EAS_CMF_Parser +#endif +}; +#define NUM_PARSER_MODULES (sizeof(parserModules) / sizeof(EAS_VOID_PTR)) + +/*---------------------------------------------------------------------------- + * Data Modules + *---------------------------------------------------------------------------- +*/ + +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_SMFData; +extern EAS_VOID_PTR eas_Data; +extern EAS_VOID_PTR eas_MixBuffer; +extern EAS_VOID_PTR eas_Synth; +extern EAS_VOID_PTR eas_MIDI; +extern EAS_VOID_PTR eas_PCMData; +extern EAS_VOID_PTR eas_MIDIData; + +#ifdef _XMF_PARSER +extern EAS_VOID_PTR eas_XMFData; +#endif + +#ifdef _SMAF_PARSER +extern EAS_VOID_PTR eas_SMAFData; +#endif + +#ifdef _OTA_PARSER +extern EAS_VOID_PTR eas_OTAData; +#endif + +#ifdef _IMELODY_PARSER +extern EAS_VOID_PTR eas_iMelodyData; +#endif + +#ifdef _RTTTL_PARSER +extern EAS_VOID_PTR eas_RTTTLData; +#endif + +#ifdef _WAVE_PARSER +extern EAS_VOID_PTR eas_WaveData; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) +extern EAS_VOID_PTR eas_CMFData; +#endif +#endif + +/*---------------------------------------------------------------------------- + * + * Effects Modules + * + * These declarations are used by the EAS library to locate + * effects modules. + *---------------------------------------------------------------------------- +*/ + +#ifdef _ENHANCER_ENABLED +extern EAS_VOID_PTR EAS_Enhancer; +#define EAS_ENHANCER_INTERFACE &EAS_Enhancer +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_EnhancerData; +#define EAS_ENHANCER_DATA &eas_EnhancerData +#else +#define EAS_ENHANCER_DATA NULL +#endif +#else +#define EAS_ENHANCER_INTERFACE NULL +#define EAS_ENHANCER_DATA NULL +#endif + +#ifdef _COMPRESSOR_ENABLED +extern EAS_VOID_PTR EAS_Compressor; +#define EAS_COMPRESSOR_INTERFACE &EAS_Compressor +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_CompressorData; +#define EAS_COMPRESSOR_DATA &eas_CompressorData +#else +#define EAS_COMPRESSOR_DATA NULL +#endif +#else +#define EAS_COMPRESSOR_INTERFACE NULL +#define EAS_COMPRESSOR_DATA NULL +#endif + +#ifdef _MAXIMIZER_ENABLED +extern EAS_VOID_PTR EAS_Maximizer; +#define EAS_MAXIMIZER_INTERFACE &EAS_Maximizer +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_MaximizerData; +#define EAS_MAXIMIZER_DATA &eas_MaximizerData +#else +#define EAS_MAXIMIZER_DATA NULL +#endif +#else +#define EAS_MAXIMIZER_INTERFACE NULL +#define EAS_MAXIMIZER_DATA NULL +#endif + + +#ifdef _REVERB_ENABLED +extern EAS_VOID_PTR EAS_Reverb; +#define EAS_REVERB_INTERFACE &EAS_Reverb +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ReverbData; +#define EAS_REVERB_DATA &eas_ReverbData +#else +#define EAS_REVERB_DATA NULL +#endif +#else +#define EAS_REVERB_INTERFACE NULL +#define EAS_REVERB_DATA NULL +#endif + +#ifdef _CHORUS_ENABLED +extern EAS_VOID_PTR EAS_Chorus; +#define EAS_CHORUS_INTERFACE &EAS_Chorus +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ChorusData; +#define EAS_CHORUS_DATA &eas_ChorusData +#else +#define EAS_CHORUS_DATA NULL +#endif +#else +#define EAS_CHORUS_INTERFACE NULL +#define EAS_CHORUS_DATA NULL +#endif + +#ifdef _WIDENER_ENABLED +extern EAS_VOID_PTR EAS_Widener; +#define EAS_WIDENER_INTERFACE &EAS_Widener +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_WidenerData; +#define EAS_WIDENER_DATA &eas_WidenerData +#else +#define EAS_WIDENER_DATA NULL +#endif +#else +#define EAS_WIDENER_INTERFACE NULL +#define EAS_WIDENER_DATA NULL +#endif + +#ifdef _GRAPHIC_EQ_ENABLED +extern EAS_VOID_PTR EAS_GraphicEQ; +#define EAS_GRAPHIC_EQ_INTERFACE &EAS_GraphicEQ +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_GraphicEQData; +#define EAS_GRAPHIC_EQ_DATA &eas_GraphicEQData +#else +#define EAS_GRAPHIC_EQ_DATA NULL +#endif +#else +#define EAS_GRAPHIC_EQ_INTERFACE NULL +#define EAS_GRAPHIC_EQ_DATA NULL +#endif + +#ifdef _WOW_ENABLED +extern EAS_VOID_PTR EAS_Wow; +#define EAS_WOW_INTERFACE &EAS_Wow +#ifdef _STATIC_MEMORY +#error "WOW module requires dynamic memory model" +#else +#define EAS_WOW_DATA NULL +#endif +#else +#define EAS_WOW_INTERFACE NULL +#define EAS_WOW_DATA NULL +#endif + +#ifdef _TONECONTROLEQ_ENABLED +extern EAS_VOID_PTR EAS_ToneControlEQ; +#define EAS_TONECONTROLEQ_INTERFACE &EAS_ToneControlEQ +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ToneControlEQData; +#define EAS_TONECONTROLEQ_DATA &eas_ToneControlEQData +#else +#define EAS_TONECONTROLEQ_DATA NULL +#endif +#else +#define EAS_TONECONTROLEQ_INTERFACE NULL +#define EAS_TONECONTROLEQ_DATA NULL +#endif + +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const effectsModules[] = +{ + EAS_ENHANCER_INTERFACE, + EAS_COMPRESSOR_INTERFACE, + EAS_REVERB_INTERFACE, + EAS_CHORUS_INTERFACE, + EAS_WIDENER_INTERFACE, + EAS_GRAPHIC_EQ_INTERFACE, + EAS_WOW_INTERFACE, + EAS_MAXIMIZER_INTERFACE, + EAS_TONECONTROLEQ_INTERFACE +}; + +EAS_VOID_PTR const effectsData[] = +{ + EAS_ENHANCER_DATA, + EAS_COMPRESSOR_DATA, + EAS_REVERB_DATA, + EAS_CHORUS_DATA, + EAS_WIDENER_DATA, + EAS_GRAPHIC_EQ_DATA, + EAS_WOW_DATA, + EAS_MAXIMIZER_DATA, + EAS_TONECONTROLEQ_DATA +}; + +/*---------------------------------------------------------------------------- + * + * Optional Modules + * + * These declarations are used by the EAS library to locate + * effects modules. + *---------------------------------------------------------------------------- +*/ + +#ifdef _METRICS_ENABLED +extern EAS_VOID_PTR EAS_Metrics; +#define EAS_METRICS_INTERFACE &EAS_Metrics +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_MetricsData; +#define EAS_METRICS_DATA &eas_MetricsData +#else +#define EAS_METRICS_DATA NULL +#endif +#else +#define EAS_METRICS_INTERFACE NULL +#define EAS_METRICS_DATA NULL +#endif + +#ifdef MMAPI_SUPPORT +extern EAS_VOID_PTR EAS_TC_Parser; +#define EAS_TONE_CONTROL_PARSER &EAS_TC_Parser +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_TCData; +#define EAS_TONE_CONTROL_DATA &eas_TCData +#else +#define EAS_TONE_CONTROL_DATA NULL +#endif +#else +#define EAS_TONE_CONTROL_PARSER NULL +#define EAS_TONE_CONTROL_DATA NULL +#endif + +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const optionalModules[] = +{ + EAS_TONE_CONTROL_PARSER, + EAS_METRICS_INTERFACE +}; + +EAS_VOID_PTR const optionalData[] = +{ + EAS_TONE_CONTROL_DATA, + EAS_METRICS_DATA +}; + +/*---------------------------------------------------------------------------- + * EAS_CMStaticMemoryModel() + *---------------------------------------------------------------------------- + * Purpose: + * This function returns true if EAS has been configured for + * a static memory model. There are some limitations in the + * static memory model, see the documentation for more + * information. + * + * Outputs: + * returns EAS_TRUE if a module is found + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_CMStaticMemoryModel (void) +{ +#ifdef _STATIC_MEMORY + return EAS_TRUE; +#else + return EAS_FALSE; +#endif +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - module number + * + * Outputs: + * returns a pointer to the module function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module) +{ + + if (module >= (EAS_INT) NUM_PARSER_MODULES) + return NULL; + return parserModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, dataModule) used only when _STATIC_MEMORY is defined */ +EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule) +{ + +#ifdef _STATIC_MEMORY + switch (dataModule) + { + + /* main instance data for synthesizer */ + case EAS_CM_EAS_DATA: + return &eas_Data; + + /* mix buffer for mix engine */ + case EAS_CM_MIX_BUFFER: + /*lint -e{545} lint doesn't like this because it sees the underlying type */ + return &eas_MixBuffer; + + /* instance data for synth */ + case EAS_CM_SYNTH_DATA: + return &eas_Synth; + + /* instance data for MIDI parser */ + case EAS_CM_MIDI_DATA: + return &eas_MIDI; + + /* instance data for SMF parser */ + case EAS_CM_SMF_DATA: + return &eas_SMFData; + +#ifdef _XMF_PARSER + /* instance data for XMF parser */ + case EAS_CM_XMF_DATA: + return &eas_XMFData; +#endif + +#ifdef _SMAF_PARSER + /* instance data for SMAF parser */ + case EAS_CM_SMAF_DATA: + return &eas_SMAFData; +#endif + + /* instance data for the PCM engine */ + case EAS_CM_PCM_DATA: + /*lint -e{545} lint doesn't like this because it sees the underlying type */ + return &eas_PCMData; + + case EAS_CM_MIDI_STREAM_DATA: + return &eas_MIDIData; + +#ifdef _OTA_PARSER + /* instance data for OTA parser */ + case EAS_CM_OTA_DATA: + return &eas_OTAData; +#endif + +#ifdef _IMELODY_PARSER + /* instance data for iMelody parser */ + case EAS_CM_IMELODY_DATA: + return &eas_iMelodyData; +#endif + +#ifdef _RTTTL_PARSER + /* instance data for RTTTL parser */ + case EAS_CM_RTTTL_DATA: + return &eas_RTTTLData; +#endif + +#ifdef _WAVE_PARSER + /* instance data for WAVE parser */ + case EAS_CM_WAVE_DATA: + return &eas_WaveData; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) + /* instance data for CMF parser */ + case EAS_CM_CMF_DATA: + return &eas_CMFData; +#endif + + default: + return NULL; + } + +#else + return NULL; +#endif +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional effects modules. + * + * Inputs: + * module - enumerated module number + * pModule - pointer to module interface + * + * Outputs: + * Returns pointer to function table or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module) +{ + + if (module >= NUM_EFFECTS_MODULES) + return NULL; + return effectsModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * pData - pointer to handle variable + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule) +{ + + if (dataModule >= NUM_EFFECTS_MODULES) + return NULL; + return effectsData[dataModule]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - enumerated module number + * + * Outputs: + * returns pointer to function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module) +{ + + /* sanity check */ + if (module >= NUM_OPTIONAL_MODULES) + return EAS_FALSE; + return optionalModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule) +{ + + if (dataModule >= NUM_OPTIONAL_MODULES) + return NULL; + return optionalData[dataModule]; +} + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_config.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_config.h new file mode 100755 index 0000000..49c2ef2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_config.h @@ -0,0 +1,191 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_config.h + * + * Contents and purpose: + * This header declares the Configuration Module interface (CM). The CM + * is a module compiled external to the library that sets the configuration + * for this build. It allows the library to find optional components and + * links to static memory allocations (when used in a static configuration). + * + * NOTE: This module is not intended to be modified by the customer. It + * needs to be included in the build process with the correct configuration + * defines (see the library documentation for information on how to configure + * the library). + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// sentinel +#ifndef _EAS_CONFIG_H +#define _EAS_CONFIG_H + +#include "eas_types.h" + +/* list of enumerators for optional modules */ +typedef enum { + EAS_CM_FILE_PARSERS = 1 +} E_CM_ENUM_MODULES; + +/* list of enumerators for module and memory pointers */ +typedef enum { + EAS_CM_EAS_DATA = 1, + EAS_CM_MIX_BUFFER, + EAS_CM_SYNTH_DATA, + EAS_CM_MIDI_DATA, + EAS_CM_SMF_DATA, + EAS_CM_XMF_DATA, + EAS_CM_SMAF_DATA, + EAS_CM_PCM_DATA, + EAS_CM_MIDI_STREAM_DATA, + EAS_CM_METRICS_DATA, + EAS_CM_OTA_DATA, + EAS_CM_IMELODY_DATA, + EAS_CM_RTTTL_DATA, + EAS_CM_WAVE_DATA, + EAS_CM_CMF_DATA +} E_CM_DATA_MODULES; + +typedef struct +{ + int maxSMFStreams; + void *pSMFData; + void *pSMFStream; +} S_EAS_SMF_PTRS; + +typedef struct +{ + int maxSMAFStreams; + void *pSMAFData; + void *pSMAFStream; +} S_EAS_SMAF_PTRS; + +/*---------------------------------------------------------------------------- + * EAS_CMStaticMemoryModel() + *---------------------------------------------------------------------------- + * Purpose: + * This function returns true if EAS has been configured for + * a static memory model. There are some limitations in the + * static memory model, see the documentation for more + * information. + * + * Outputs: + * returns EAS_TRUE if a module is found + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_CMStaticMemoryModel (void); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - module number + * + * Outputs: + * returns a pointer to the module function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional effects modules. + * + * Inputs: + * module - enumerated module number + * pModule - pointer to module interface + * + * Outputs: + * Returns pointer to function table or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * pData - pointer to handle variable + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - enumerated module number + * + * Outputs: + * returns pointer to function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule); + +#endif /* end _EAS_CONFIG_H */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_debugmsgs.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_debugmsgs.h new file mode 100755 index 0000000..df120bc --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_debugmsgs.h @@ -0,0 +1,44 @@ +/* Auto-generated from source file: eas_chorusdata.c */ +/* Auto-generated from source file: eas_imelodydata.c */ +/* Auto-generated from source file: eas_mididata.c */ +/* Auto-generated from source file: eas_pan.c */ +/* Auto-generated from source file: eas_wavefiledata.c */ +/* Auto-generated from source file: eas_voicemgt.c */ +/* Auto-generated from source file: eas_ota.c */ +/* Auto-generated from source file: eas_mixbuf.c */ +/* Auto-generated from source file: eas_rtttl.c */ +/* Auto-generated from source file: eas_reverb.c */ +/* Auto-generated from source file: eas_fmsynth.c */ +/* Auto-generated from source file: eas_pcmdata.c */ +/* Auto-generated from source file: eas_chorus.c */ +/* Auto-generated from source file: eas_math.c */ +/* Auto-generated from source file: eas_fmengine.c */ +/* Auto-generated from source file: eas_smfdata.c */ +/* Auto-generated from source file: eas_fmtables.c */ +/* Auto-generated from source file: eas_imelody.c */ +/* Auto-generated from source file: eas_public.c */ +/* Auto-generated from source file: eas_rtttldata.c */ +/* Auto-generated from source file: eas_reverbdata.c */ +/* Auto-generated from source file: eas_wtengine.c */ +/* Auto-generated from source file: eas_imaadpcm.c */ +{ 0x2380b977, 0x00000006, "eas_imaadpcm.c[305]: IMADecoderLocate: Time=%d, samples=%d\n" }, +{ 0x2380b977, 0x00000007, "eas_imaadpcm.c[328]: IMADecoderLocate: Looped sample, numBlocks=%d, samplesPerLoop=%d, samplesInLastBlock=%d, samples=%d\n" }, +{ 0x2380b977, 0x00000008, "eas_imaadpcm.c[335]: IMADecoderLocate: Byte location in audio = %d\n" }, +{ 0x2380b977, 0x00000009, "eas_imaadpcm.c[345]: IMADecoderLocate: bytesLeft = %d\n" }, +/* Auto-generated from source file: eas_midi.c */ +/* Auto-generated from source file: eas_otadata.c */ +/* Auto-generated from source file: eas_ima_tables.c */ +/* Auto-generated from source file: eas_data.c */ +/* Auto-generated from source file: eas_pcm.c */ +/* Auto-generated from source file: eas_mixer.c */ +/* Auto-generated from source file: eas_wavefile.c */ +/* Auto-generated from source file: eas_wtsynth.c */ +/* Auto-generated from source file: eas_smf.c */ +/* Auto-generated from source file: eas_wave.c */ +/* Auto-generated from source file: eas_hostmm.c */ +{ 0x1a54b6e8, 0x00000001, "eas_hostmm.c[586]: Vibrate state: %d\n" }, +{ 0x1a54b6e8, 0x00000002, "eas_hostmm.c[601]: LED state: %d\n" }, +{ 0x1a54b6e8, 0x00000003, "eas_hostmm.c[616]: Backlight state: %d\n" }, +/* Auto-generated from source file: eas_config.c */ +/* Auto-generated from source file: eas_main.c */ +{ 0xe624f4d9, 0x00000005, "eas_main.c[106]: Play length: %d.%03d (secs)\n" }, diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_host.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_host.h new file mode 100755 index 0000000..b356982 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_host.h @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_host.h + * + * Contents and purpose: + * This header defines the host wrapper functions for stdio, stdlib, etc. + * The host application must provide an abstraction layer for these functions + * to support certain features, such as SMAF and SMF-1 conversion. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// sentinel +#ifndef _EAS_HOST_H +#define _EAS_HOST_H + +#include "eas_types.h" + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +/* initialization and shutdown routines */ +extern EAS_RESULT EAS_HWInit(EAS_HW_DATA_HANDLE *hwInstData); +extern EAS_RESULT EAS_HWShutdown(EAS_HW_DATA_HANDLE hwInstData); + +/* memory functions */ +extern void *EAS_HWMemSet(void *s, int c, EAS_I32 n); +extern void *EAS_HWMemCpy(void *s1, const void *s2, EAS_I32 n); +extern EAS_I32 EAS_HWMemCmp(const void *s1, const void *s2, EAS_I32 n); + +/* memory allocation */ +extern void *EAS_HWMalloc(EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size); +extern void EAS_HWFree(EAS_HW_DATA_HANDLE hwInstData, void *p); + +/* file I/O */ +extern EAS_RESULT EAS_HWOpenFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode); +extern EAS_RESULT EAS_HWReadFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead); +extern EAS_RESULT EAS_HWGetByte(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p); +extern EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst); +extern EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst); +extern EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition); +extern EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position); +extern EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position); +extern EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength); +extern EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pFile); +extern EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file); + +/* vibrate, LED, and backlight functions */ +extern EAS_RESULT EAS_HWVibrate(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); +extern EAS_RESULT EAS_HWLED(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); +extern EAS_RESULT EAS_HWBackLight(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + + +/* host yield function */ +extern EAS_BOOL EAS_HWYield(EAS_HW_DATA_HANDLE hwInstData); +#endif /* end _EAS_HOST_H */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_hostmm.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_hostmm.c new file mode 100755 index 0000000..df24cf2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_hostmm.c @@ -0,0 +1,660 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_hostmm.c + * + * Contents and purpose: + * This file contains the host wrapper functions for stdio, stdlib, etc. + * This is a sample version that maps the requested files to an + * allocated memory block and uses in-memory pointers to replace + * file system calls. The file locator (EAS_FILE_LOCATOR) handle passed + * HWOpenFile is the same one that is passed to EAS_OpenFile. If your + * system stores data in fixed locations (such as flash) instead of + * using a file system, you can use the locator handle to point to + * your memory. You will need a way of knowing the length of the + * data stored at that location in order to respond correctly in the + * HW_FileLength function. + * + * Modify this file to suit the needs of your particular system. + * + * EAS_MAX_FILE_HANDLES sets the maximum number of MIDI streams within + * a MIDI type 1 file that can be played. + * + * EAS_HW_FILE is a structure to support the file I/O functions. It + * comprises the base memory pointer, the file read pointer, and + * the dup flag, which when sets, indicates that the file handle has + * been duplicated. If your system uses in-memory resources, you + * can eliminate the duplicate handle logic, and simply copy the + * base memory pointer and file read pointer to the duplicate handle. + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#endif + +#include "eas_host.h" + +/* Only for debugging LED, vibrate, and backlight functions */ +#include "eas_report.h" + +/* this module requires dynamic memory support */ +#ifdef _STATIC_MEMORY +#error "eas_hostmm.c requires the dynamic memory model!\n" +#endif + +#ifndef EAS_MAX_FILE_HANDLES +#define EAS_MAX_FILE_HANDLES 32 +#endif + +/* + * this structure and the related function are here + * to support the ability to create duplicate handles + * and buffering it in memory. If your system uses + * in-memory resources, you can eliminate the calls + * to malloc and free, the dup flag, and simply track + * the file size and read position. + */ +typedef struct eas_hw_file_tag +{ + EAS_I32 fileSize; + EAS_I32 filePos; + EAS_BOOL dup; + EAS_U8 *buffer; +} EAS_HW_FILE; + +typedef struct eas_hw_inst_data_tag +{ + EAS_HW_FILE files[EAS_MAX_FILE_HANDLES]; +} EAS_HW_INST_DATA; + +/*---------------------------------------------------------------------------- + * EAS_HWInit + * + * Initialize host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData) +{ + + /* need to track file opens for duplicate handles */ + *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA)); + if (!(*pHWInstData)) + return EAS_ERROR_MALLOC_FAILED; + + EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA)); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_HWShutdown + * + * Shut down host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData) +{ + + free(hwInstData); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMalloc + * + * Allocates dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size) +{ + return malloc((size_t) size); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFree + * + * Frees dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p) +{ + free(p); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCpy + * + * Copy memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount) +{ + return memcpy(dest, src, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemSet + * + * Set memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount) +{ + return memset(dest, val, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCmp + * + * Compare memory wrapper + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount) +{ + return (EAS_I32) memcmp(s1, s2, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWOpenFile + * + * Open a file for read or write + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) +{ + EAS_HW_FILE *file; + FILE *ioFile; + int i, temp; + + /* set return value to NULL */ + *pFile = NULL; + + /* only support read mode at this time */ + if (mode != EAS_FILE_READ) + return EAS_ERROR_INVALID_FILE_MODE; + + /* find an empty entry in the file table */ + file = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (file->buffer == NULL) + { + /* open the file */ + if ((ioFile = fopen(locator,"rb")) == NULL) + return EAS_ERROR_FILE_OPEN_FAILED; + + /* determine the file size */ + if (fseek(ioFile, 0L, SEEK_END) != 0) + return EAS_ERROR_FILE_LENGTH; + if ((file->fileSize = ftell(ioFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(ioFile, 0L, SEEK_SET) != 0) + return EAS_ERROR_FILE_LENGTH; + + /* allocate a buffer */ + file->buffer = EAS_HWMalloc(hwInstData, file->fileSize); + if (file->buffer == NULL) + { + fclose(ioFile); + return EAS_ERROR_MALLOC_FAILED; + } + + /* read the file into memory */ + temp = (int) fread(file->buffer, (size_t) file->fileSize, 1, ioFile); + + /* close the file - don't need it any more */ + fclose(ioFile); + + /* check for error reading file */ + if (temp != 1) + return EAS_ERROR_FILE_READ_FAILED; + + /* initialize some values */ + file->filePos = 0; + file->dup = EAS_FALSE; + + *pFile = file; + return EAS_SUCCESS; + } + file++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWReadFile + * + * Read data from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) +{ + EAS_I32 count; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* calculate the bytes to read */ + count = file->fileSize - file->filePos; + if (n < count) + count = n; + + /* copy the data to the requested location, and advance the pointer */ + if (count) + EAS_HWMemCpy(pBuffer, &file->buffer[file->filePos], count); + file->filePos += count; + *pBytesRead = count; + + /* were n bytes read? */ + if (count!= n) + return EAS_EOF; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetByte + * + * Read a byte from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for end of file */ + if (file->filePos >= file->fileSize) + { + *((EAS_U8*) p) = 0; + return EAS_EOF; + } + + /* get a character from the buffer */ + *((EAS_U8*) p) = file->buffer[file->filePos++]; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2; + + /* read 2 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2; + else + *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetDWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2,c3,c4; + + /* read 4 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4; + else + *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFilePos + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pPosition = file->filePos; + return EAS_SUCCESS; +} /* end EAS_HWFilePos */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeek + * + * Seek to a specific location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* validate new position */ + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeekOfs + * + * Seek forward or back relative to the current position + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* determine the file position */ + position += file->filePos; + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileLength + * + * Return the file length + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) +{ + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pLength = file->fileSize; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWDupHandle + * + * Duplicate a file handle + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile) +{ + EAS_HW_FILE *dupFile; + int i; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* find an empty entry in the file table */ + dupFile = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (dupFile->buffer == NULL) + { + + /* copy info from the handle to be duplicated */ + dupFile->filePos = file->filePos; + dupFile->fileSize = file->fileSize; + dupFile->buffer = file->buffer; + + /* set the duplicate handle flag */ + dupFile->dup = file->dup = EAS_TRUE; + + *pDupFile = dupFile; + return EAS_SUCCESS; + } + dupFile++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWClose + * + * Wrapper for fclose function + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) +{ + EAS_HW_FILE *file2,*dupFile; + int i; + + + /* make sure we have a valid handle */ + if (file1->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for duplicate handle */ + if (file1->dup) + { + dupFile = NULL; + file2 = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* check for duplicate */ + if ((file1 != file2) && (file2->buffer == file1->buffer)) + { + /* is there more than one duplicate? */ + if (dupFile != NULL) + { + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; + } + + /* this is the first duplicate found */ + else + dupFile = file2; + } + file2++; + } + + /* there is only one duplicate, clear the dup flag */ + if (dupFile) + dupFile->dup = EAS_FALSE; + else + /* if we get here, there's a serious problem */ + return EAS_ERROR_HANDLE_INTEGRITY; + + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; + } + + /* no duplicates -free the buffer */ + EAS_HWFree(hwInstData, file1->buffer); + + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWVibrate + * + * Turn on/off vibrate function + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000001 , state); + return EAS_SUCCESS; +} /* end EAS_HWVibrate */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWLED + * + * Turn on/off LED + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000002 , state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWBackLight + * + * Turn on/off backlight + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000003 , state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWYield + * + * This function is called periodically by the EAS library to give the + * host an opportunity to allow other tasks to run. There are two ways to + * use this call: + * + * If you have a multi-tasking OS, you can call the yield function in the + * OS to allow other tasks to run. In this case, return EAS_FALSE to tell + * the EAS library to continue processing when control returns from this + * function. + * + * If tasks run in a single thread by sequential function calls (sometimes + * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to + * return to the caller. Be sure to check the number of bytes rendered + * before passing the audio buffer to the codec - it may not be filled. + * The next call to EAS_Render will continue processing until the buffer + * has been filled. + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData) +{ + /* put your code here */ + return EAS_FALSE; +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_main.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_main.c new file mode 100755 index 0000000..6ebb13e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_main.c @@ -0,0 +1,461 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_main.c + * + * Contents and purpose: + * The entry point and high-level functions for the EAS Synthesizer test + * harness. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 775 $ + * $Date: 2007-07-20 10:11:11 -0700 (Fri, 20 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#include +#endif + +#include "eas.h" +#include "eas_wave.h" +#include "eas_report.h" + +/* determines how many EAS buffers to fill a host buffer */ +#define NUM_BUFFERS 8 + +/* default file to play if no filename is specified on the command line */ +static const char defaultTestFile[] = "test.mid"; + +EAS_I32 polyphony; + +/* prototypes for helper functions */ +static void StrCopy(char *dest, const char *src, EAS_I32 size); +static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size); +static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize); +static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig); + +/* main is defined after playfile to avoid the need for two passes through lint */ + +/*---------------------------------------------------------------------------- + * PlayFile() + *---------------------------------------------------------------------------- + * Purpose: + * This function plays the file requested by filename + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize) +{ + EAS_HANDLE handle; + EAS_RESULT result, reportResult; + EAS_I32 count; + EAS_STATE state; + EAS_I32 playTime; + char waveFilename[256]; + WAVE_FILE *wFile; + EAS_INT i; + EAS_PCM *p; + + /* determine the name of the output file */ + wFile = NULL; + if (outputFile == NULL) + { + StrCopy(waveFilename, filename, sizeof(waveFilename)); + if (!ChangeFileExt(waveFilename, "wav", sizeof(waveFilename))) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error in output filename %s\n", waveFilename); */ } + return EAS_FAILURE; + } + outputFile = waveFilename; + } + + /* call EAS library to open file */ + if ((reportResult = EAS_OpenFile(easData, filename, &handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_OpenFile returned %ld\n", reportResult); */ } + return reportResult; + } + + /* prepare to play the file */ + if ((result = EAS_Prepare(easData, handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Prepare returned %ld\n", result); */ } + reportResult = result; + } + + /* get play length */ + if ((result = EAS_ParseMetaData(easData, handle, &playTime)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_ParseMetaData returned %ld\n", result); */ } + return result; + } + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0xe624f4d9, 0x00000005 , playTime / 1000, playTime % 1000); + + if (reportResult == EAS_SUCCESS) + { + /* create the output file */ + wFile = WaveFileCreate(outputFile, pLibConfig->numChannels, pLibConfig->sampleRate, sizeof(EAS_PCM) * 8); + if (!wFile) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to create output file %s\n", waveFilename); */ } + reportResult = EAS_FAILURE; + } + } + + /* rendering loop */ + while (reportResult == EAS_SUCCESS) + { + + /* we may render several buffers here to fill one host buffer */ + for (i = 0, p = buffer; i < NUM_BUFFERS; i++, p+= pLibConfig->mixBufferSize * pLibConfig->numChannels) + { + + /* get the current time */ + if ((result = EAS_GetLocation(easData, handle, &playTime)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_GetLocation returned %d\n",result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + break; + } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Parser time: %d.%03d\n", playTime / 1000, playTime % 1000); */ } + + /* render a buffer of audio */ + if ((result = EAS_Render(easData, p, pLibConfig->mixBufferSize, &count)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Render returned %d\n",result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + + if (result == EAS_SUCCESS) + { + /* write it to the wave file */ + if (WaveFileWrite(wFile, buffer, bufferSize) != bufferSize) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "WaveFileWrite failed\n"); */ } + reportResult = EAS_FAILURE; + } + } + + if (reportResult == EAS_SUCCESS) + { + /* check stream state */ + if ((result = EAS_State(easData, handle, &state)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_State returned %d\n", result); */ } + reportResult = result; + } + + /* is playback complete */ + if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) + break; + } + } + + /* close the output file */ + if (wFile) + { + if (!WaveFileClose(wFile)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error closing wave file %s\n", waveFilename); */ } + if (reportResult == EAS_SUCCESS) + result = EAS_FAILURE; + } + } + + /* close the input file */ + if ((result = EAS_CloseFile(easData,handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Close returned %ld\n", result); */ } + if (reportResult == EAS_SUCCESS) + result = EAS_FAILURE; + } + + return reportResult; +} /* end PlayFile */ + +/*---------------------------------------------------------------------------- + * main() + *---------------------------------------------------------------------------- + * Purpose: The entry point for the EAS sample application + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +int main( int argc, char **argv ) +{ + EAS_DATA_HANDLE easData; + const S_EAS_LIB_CONFIG *pLibConfig; + void *buffer; + EAS_RESULT result, playResult; + EAS_I32 bufferSize; + int i; + int temp; + FILE *debugFile; + char *outputFile = NULL; + + /* set the error reporting level */ + EAS_SetDebugLevel(_EAS_SEVERITY_INFO); + debugFile = NULL; + + /* process command-line arguments */ + for (i = 1; i < argc; i++) + { + /* check for switch */ + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'd': + temp = argv[i][2]; + if ((temp >= '0') || (temp <= '9')) + EAS_SetDebugLevel(temp); + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid debug level %d\n", temp); */ } + break; + case 'f': + if ((debugFile = fopen(&argv[i][2],"w")) == NULL) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unable to create debug file %s\n", &argv[i][2]); */ } + else + EAS_SetDebugFile(debugFile, EAS_TRUE); + break; + case 'o': + outputFile = &argv[i][2]; + break; + case 'p': + polyphony = atoi(&argv[i][2]); + if (polyphony < 1) + polyphony = 1; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Polyphony set to %d\n", polyphony); */ } + break; + default: + break; + } + continue; + } + } + + /* assume success */ + playResult = EAS_SUCCESS; + + /* get the library configuration */ + pLibConfig = EAS_Config(); + if (!EASLibraryCheck(pLibConfig)) + return -1; + if (polyphony > pLibConfig->maxVoices) + polyphony = pLibConfig->maxVoices; + + /* calculate buffer size */ + bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS; + + /* allocate output buffer memory */ + buffer = malloc((EAS_U32)bufferSize); + if (!buffer) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Error allocating memory for audio buffer\n"); */ } + return EAS_FAILURE; + } + + /* initialize the EAS library */ + polyphony = pLibConfig->maxVoices; + if ((result = EAS_Init(&easData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Init returned %ld - aborting!\n", result); */ } + free(buffer); + return result; + } + + /* + * Some debugging environments don't allow for passed parameters. + * In this case, just play the default MIDI file "test.mid" + */ + if (argc < 2) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", defaultTestFile); */ } + if ((playResult = PlayFile(easData, defaultTestFile, NULL, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, defaultTestFile); */ } + } + } + /* iterate through the list of files to be played */ + else + { + for (i = 1; i < argc; i++) + { + /* check for switch */ + if (argv[i][0] != '-') + { + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", argv[i]); */ } + if ((playResult = PlayFile(easData, argv[i], outputFile, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, argv[i]); */ } + break; + } + } + } + } + + /* shutdown the EAS library */ + if ((result = EAS_Shutdown(easData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Shutdown returned %ld\n", result); */ } + } + + /* free the output buffer */ + free(buffer); + + /* close the debug file */ + if (debugFile) + fclose(debugFile); + + /* play errors take precedence over shutdown errors */ + if (playResult != EAS_SUCCESS) + return playResult; + return result; +} /* end main */ + +/*---------------------------------------------------------------------------- + * StrCopy() + *---------------------------------------------------------------------------- + * Purpose: + * Safe string copy + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void StrCopy(char *dest, const char *src, EAS_I32 size) +{ + int len; + + strncpy(dest, src, (size_t) size-1); + len = (int) strlen(src); + if (len < size) + dest[len] = 0; +} /* end StrCopy */ + +/*---------------------------------------------------------------------------- + * ChangeFileExt() + *---------------------------------------------------------------------------- + * Purpose: + * Changes the file extension of a filename + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size) +{ + char *p; + + /* find the extension, if any */ + p = strrchr(str,'.'); + if (!p) + { + if ((EAS_I32)(strlen(str) + 5) > size) + return EAS_FALSE; + strcat(str,"."); + strcat(str,ext); + return EAS_TRUE; + } + + /* make sure there's room for the extension */ + p++; + *p = 0; + if ((EAS_I32)(strlen(str) + 4) > size) + return EAS_FALSE; + strcat(str,ext); + return EAS_TRUE; +} /* end ChangeFileExt */ + +/*---------------------------------------------------------------------------- + * EASLibraryCheck() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the library version and checks it against the header + * file used to build this code. + * + * Inputs: + * pLibConfig - library configuration retrieved from the library + * + * Outputs: + * returns EAS_TRUE if matched + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig) +{ + + /* display the library version */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "EAS Library Version %d.%d.%d.%d\n", + pLibConfig->libVersion >> 24, + (pLibConfig->libVersion >> 16) & 0x0f, + (pLibConfig->libVersion >> 8) & 0x0f, + pLibConfig->libVersion & 0x0f); */ } + + /* display some info about the library build */ + if (pLibConfig->checkedVersion) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tChecked library\n"); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMaximum polyphony: %d\n", pLibConfig->maxVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tNumber of channels: %d\n", pLibConfig->numChannels); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tSample rate: %d\n", pLibConfig->sampleRate); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMix buffer size: %d\n", pLibConfig->mixBufferSize); */ } + if (pLibConfig->filterEnabled) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tFilter enabled\n"); */ } +#ifndef _WIN32_WCE + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build Timestamp: %s", ctime((time_t*)&pLibConfig->buildTimeStamp)); */ } +#endif + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build ID: %s\n", pLibConfig->buildGUID); */ } + + /* check it against the header file used to build this code */ + /*lint -e{778} constant expression used for display purposes may evaluate to zero */ + if (LIB_VERSION != pLibConfig->libVersion) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Library version does not match header files. EAS Header Version %d.%d.%d.%d\n", + LIB_VERSION >> 24, + (LIB_VERSION >> 16) & 0x0f, + (LIB_VERSION >> 8) & 0x0f, + LIB_VERSION & 0x0f); */ } + return EAS_FALSE; + } + return EAS_TRUE; +} /* end EASLibraryCheck */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_report.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_report.c new file mode 100755 index 0000000..04a828c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_report.c @@ -0,0 +1,264 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_report.c + * + * Contents and purpose: + * This file contains the debug message handling routines for the EAS library. + * These routines should be modified as needed for your system. + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 659 $ + * $Date: 2007-04-24 13:36:35 -0700 (Tue, 24 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#endif + +#include "eas_report.h" + +static int severityLevel = 9999; + +/* debug file */ +static FILE *debugFile = NULL; +int flush = 0; + +#ifndef _NO_DEBUG_PREPROCESSOR + +/* structure should have an #include for each error message header file */ +S_DEBUG_MESSAGES debugMessages[] = +{ +#ifndef UNIFIED_DEBUG_MESSAGES +#include "eas_config_msgs.h" + + +#include "eas_host_msgs.h" +#include "eas_hostmm_msgs.h" +#include "eas_math_msgs.h" +#include "eas_midi_msgs.h" +#include "eas_mixer_msgs.h" +#include "eas_pcm_msgs.h" +#include "eas_public_msgs.h" +#include "eas_smf_msgs.h" +#include "eas_wave_msgs.h" +#include "eas_voicemgt_msgs.h" + +#ifdef _FM_SYNTH +#include "eas_fmsynth_msgs.h" +#include "eas_fmengine_msgs.h" +#endif + +#ifdef _WT_SYNTH +#include "eas_wtsynth_msgs.h" +#include "eas_wtengine_msgs.h" +#endif + +#ifdef _ARM_TEST_MAIN +#include "arm_main_msgs.h" +#endif + +#ifdef _EAS_MAIN +#include "eas_main_msgs.h" +#endif + +#ifdef _EAS_MAIN_IPC +#include "eas_main_ipc_msgs.h" +#endif + +#ifdef _METRICS_ENABLED +#include "eas_perf_msgs.h" +#endif + +#ifdef _COMPRESSOR_ENABLED +#include "eas_compressor_msgs.h" +#endif + +#ifdef _ENHANCER_ENABLED +#include "eas_enhancer_msgs.h" +#endif + +#ifdef _WOW_ENABLED +#include "eas_wow_msgs.h" +#endif + +#ifdef _SMAF_PARSER +#include "eas_smaf_msgs.h" +#endif + +#ifdef _OTA_PARSER +#include "eas_ota_msgs.h" +#endif + +#ifdef _IMELODY_PARSER +#include "eas_imelody_msgs.h" +#endif + +#ifdef _WAVE_PARSER +#include "eas_wavefile_msgs.h" +#endif + +#if defined(_CMX_PARSER) || defined(_MFI_PARSER) +#include "eas_cmf_msgs.h" +#endif + +#if defined(_CMX_PARSER) || defined(_MFI_PARSER) || defined(_WAVE_PARSER) +#include "eas_imaadpcm_msgs.h" +#endif + +#else +#include "eas_debugmsgs.h" +#endif + +/* denotes end of error messages */ +{ 0,0,0 } +}; + +/*---------------------------------------------------------------------------- + * EAS_ReportEx() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...) +{ + va_list vargs; + int i; + + /* check severity level */ + if (severity > severityLevel) + return; + + /* find the error message and output to stdout */ + /*lint -e{661} we check for NULL pointer - no fence post error here */ + for (i = 0; debugMessages[i].m_pDebugMsg; i++) + { + if ((debugMessages[i].m_nHashCode == hashCode) && + (debugMessages[i].m_nSerialNum == serialNum)) + { + /*lint -e{826} */ + va_start(vargs, serialNum); + if (debugFile) + { + vfprintf(debugFile, debugMessages[i].m_pDebugMsg, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(debugMessages[i].m_pDebugMsg, vargs); + } + va_end(vargs); + return; + } + } + printf("Unrecognized error: Severity=%d; HashCode=%lu; SerialNum=%d\n", severity, hashCode, serialNum); +} /* end EAS_ReportEx */ + +#else +/*---------------------------------------------------------------------------- + * EAS_Report() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_Report (int severity, const char *fmt, ...) +{ + va_list vargs; + + /* check severity level */ + if (severity > severityLevel) + return; + + /*lint -e{826} */ + va_start(vargs, fmt); + if (debugFile) + { + vfprintf(debugFile, fmt, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(fmt, vargs); + } + va_end(vargs); +} /* end EAS_Report */ + +/*---------------------------------------------------------------------------- + * EAS_ReportX() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_ReportX (int severity, const char *fmt, ...) +{ + va_list vargs; + + /* check severity level */ + if (severity > severityLevel) + return; + + /*lint -e{826} */ + va_start(vargs, fmt); + if (debugFile) + { + vfprintf(debugFile, fmt, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(fmt, vargs); + } + va_end(vargs); +} /* end EAS_ReportX */ +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetDebugLevel() + * + * Sets the level for debug message output + *---------------------------------------------------------------------------- +*/ + +void EAS_SetDebugLevel (int severity) +{ + severityLevel = severity; +} /* end EAS_SetDebugLevel */ + +/*---------------------------------------------------------------------------- + * EAS_SetDebugFile() + * + * Redirect debugger output to the specified file. + *---------------------------------------------------------------------------- +*/ +void EAS_SetDebugFile (void *file, int flushAfterWrite) +{ + debugFile = (FILE*) file; + flush = flushAfterWrite; +} /* end EAS_SetDebugFile */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_report.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_report.h new file mode 100755 index 0000000..b603b12 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_report.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_report.h + * + * Contents and purpose: + * This file contains the debug message handling routines for the EAS library. + * These routines should be modified as needed for your system. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +/* sentinel */ +#ifndef _EAS_REPORT_H +#define _EAS_REPORT_H + +#define _EAS_SEVERITY_NOFILTER 0 +#define _EAS_SEVERITY_FATAL 1 +#define _EAS_SEVERITY_ERROR 2 +#define _EAS_SEVERITY_WARNING 3 +#define _EAS_SEVERITY_INFO 4 +#define _EAS_SEVERITY_DETAIL 5 + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _NO_DEBUG_PREPROCESSOR + +/* structure for included debug message header files */ +typedef struct +{ + unsigned long m_nHashCode; + int m_nSerialNum; + char *m_pDebugMsg; +} S_DEBUG_MESSAGES; + +/* debug message handling prototypes */ +extern void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...); + +#else + +/* these prototypes are used if the debug preprocessor is not used */ +extern void EAS_Report (int severity, const char* fmt, ...); +extern void EAS_ReportX (int severity, const char* fmt, ...); + +#endif + +extern void EAS_SetDebugLevel (int severity); +extern void EAS_SetDebugFile (void *file, int flushAfterWrite); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_reverb.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_reverb.h new file mode 100755 index 0000000..559abed --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_reverb.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverb.h + * + * Contents and purpose: + * Contains parameter enumerations for the Reverb effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 300 $ + * $Date: 2006-09-11 17:37:20 -0700 (Mon, 11 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_REVERB_H +#define _EAS_REVERB_H + + +/* enumerated parameter settings for Reverb effect */ +typedef enum +{ + EAS_PARAM_REVERB_BYPASS, + EAS_PARAM_REVERB_PRESET, + EAS_PARAM_REVERB_WET, + EAS_PARAM_REVERB_DRY +} E_REVERB_PARAMS; + + +typedef enum +{ + EAS_PARAM_REVERB_LARGE_HALL, + EAS_PARAM_REVERB_HALL, + EAS_PARAM_REVERB_CHAMBER, + EAS_PARAM_REVERB_ROOM, +} E_REVERB_PRESETS; + + +#endif /* _REVERB_H */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_types.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_types.h new file mode 100755 index 0000000..45fa4b2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_types.h @@ -0,0 +1,268 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_types.h + * + * Contents and purpose: + * The public interface header for the EAS synthesizer. + * + * This header only contains declarations that are specific + * to this implementation. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 726 $ + * $Date: 2007-06-14 23:10:46 -0700 (Thu, 14 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_TYPES_H +#define _EAS_TYPES_H + +/* EAS_RESULT return codes */ +typedef long EAS_RESULT; +#define EAS_SUCCESS 0 +#define EAS_FAILURE -1 +#define EAS_ERROR_INVALID_MODULE -2 +#define EAS_ERROR_MALLOC_FAILED -3 +#define EAS_ERROR_FILE_POS -4 +#define EAS_ERROR_INVALID_FILE_MODE -5 +#define EAS_ERROR_FILE_SEEK -6 +#define EAS_ERROR_FILE_LENGTH -7 +#define EAS_ERROR_NOT_IMPLEMENTED -8 +#define EAS_ERROR_CLOSE_FAILED -9 +#define EAS_ERROR_FILE_OPEN_FAILED -10 +#define EAS_ERROR_INVALID_HANDLE -11 +#define EAS_ERROR_NO_MIX_BUFFER -12 +#define EAS_ERROR_PARAMETER_RANGE -13 +#define EAS_ERROR_MAX_FILES_OPEN -14 +#define EAS_ERROR_UNRECOGNIZED_FORMAT -15 +#define EAS_BUFFER_SIZE_MISMATCH -16 +#define EAS_ERROR_FILE_FORMAT -17 +#define EAS_ERROR_SMF_NOT_INITIALIZED -18 +#define EAS_ERROR_LOCATE_BEYOND_END -19 +#define EAS_ERROR_INVALID_PCM_TYPE -20 +#define EAS_ERROR_MAX_PCM_STREAMS -21 +#define EAS_ERROR_NO_VOICE_ALLOCATED -22 +#define EAS_ERROR_INVALID_CHANNEL -23 +#define EAS_ERROR_ALREADY_STOPPED -24 +#define EAS_ERROR_FILE_READ_FAILED -25 +#define EAS_ERROR_HANDLE_INTEGRITY -26 +#define EAS_ERROR_MAX_STREAMS_OPEN -27 +#define EAS_ERROR_INVALID_PARAMETER -28 +#define EAS_ERROR_FEATURE_NOT_AVAILABLE -29 +#define EAS_ERROR_SOUND_LIBRARY -30 +#define EAS_ERROR_NOT_VALID_IN_THIS_STATE -31 +#define EAS_ERROR_NO_VIRTUAL_SYNTHESIZER -32 +#define EAS_ERROR_FILE_ALREADY_OPEN -33 +#define EAS_ERROR_FILE_ALREADY_CLOSED -34 +#define EAS_ERROR_INCOMPATIBLE_VERSION -35 +#define EAS_ERROR_QUEUE_IS_FULL -36 +#define EAS_ERROR_QUEUE_IS_EMPTY -37 +#define EAS_ERROR_FEATURE_ALREADY_ACTIVE -38 + +/* special return codes */ +#define EAS_EOF 3 +#define EAS_STREAM_BUFFERING 4 +#define EAS_BUFFER_FULL 5 + +/* EAS_STATE return codes */ +typedef long EAS_STATE; +typedef enum +{ + EAS_STATE_READY = 0, + EAS_STATE_PLAY, + EAS_STATE_STOPPING, + EAS_STATE_PAUSING, + EAS_STATE_STOPPED, + EAS_STATE_PAUSED, + EAS_STATE_OPEN, + EAS_STATE_ERROR, + EAS_STATE_EMPTY +} E_EAS_STATE; + +/* constants */ +#ifndef EAS_CONST +#define EAS_CONST const +#endif + +/* definition for public interface functions */ +#ifndef EAS_PUBLIC +#define EAS_PUBLIC +#endif + +/* boolean values */ +typedef unsigned EAS_BOOL; +typedef unsigned char EAS_BOOL8; + +#define EAS_FALSE 0 +#define EAS_TRUE 1 + +/* scalar variable definitions */ +typedef unsigned char EAS_U8; +typedef signed char EAS_I8; +typedef char EAS_CHAR; + +typedef unsigned short EAS_U16; +typedef short EAS_I16; + +typedef unsigned long EAS_U32; +typedef long EAS_I32; + +typedef unsigned EAS_UINT; +typedef int EAS_INT; +typedef long EAS_LONG; + +/* audio output type */ +typedef short EAS_PCM; + +/* file open modes */ +typedef EAS_I32 EAS_FILE_MODE; +#define EAS_FILE_READ 1 +#define EAS_FILE_WRITE 2 + +/* file locator e.g. filename or memory pointer */ +typedef const void *EAS_FILE_LOCATOR; + +/* handle to stream */ +typedef struct s_eas_stream_tag *EAS_HANDLE; + +/* handle to file */ +typedef struct eas_hw_file_tag *EAS_FILE_HANDLE; + +/* handle for synthesizer data */ +typedef struct s_eas_data_tag *EAS_DATA_HANDLE; + +/* handle to persistent data for host wrapper interface */ +typedef struct eas_hw_inst_data_tag *EAS_HW_DATA_HANDLE; + +/* handle to sound library */ +typedef struct s_eas_sndlib_tag *EAS_SNDLIB_HANDLE; +typedef struct s_eas_dls_tag *EAS_DLSLIB_HANDLE; + +/* pointer to frame buffer - used in split architecture only */ +typedef struct s_eas_frame_buffer_tag *EAS_FRAME_BUFFER_HANDLE; + +/* untyped pointer for instance data */ +typedef void *EAS_VOID_PTR; + +/* inline functions */ +#ifndef EAS_INLINE +#if defined (__XCC__) +#define EAS_INLINE __inline__ +#elif defined (__GNUC__) +#define EAS_INLINE inline static +#else +#define EAS_INLINE __inline +#endif +#endif + +/* define NULL value */ +#ifndef NULL +#define NULL 0 +#endif + +/* metadata types for metadata return codes */ +typedef enum +{ + EAS_METADATA_UNKNOWN = 0, + EAS_METADATA_TITLE, + EAS_METADATA_AUTHOR, + EAS_METADATA_COPYRIGHT, + EAS_METADATA_LYRIC, + EAS_METADATA_TEXT +} E_EAS_METADATA_TYPE; + +/* metadata callback function */ +typedef void (*EAS_METADATA_CBFUNC) (E_EAS_METADATA_TYPE metaDataType, char *metaDataBuf, EAS_VOID_PTR pUserData); + +/* file types for metadata return codes */ +typedef enum +{ + EAS_FILE_UNKNOWN = 0, + EAS_FILE_SMF0, + EAS_FILE_SMF1, + EAS_FILE_SMAF_UNKNOWN, + EAS_FILE_SMAF_MA2, + EAS_FILE_SMAF_MA3, + EAS_FILE_SMAF_MA5, + EAS_FILE_CMX, + EAS_FILE_MFI, + EAS_FILE_OTA, + EAS_FILE_IMELODY, + EAS_FILE_RTTTL, + EAS_FILE_XMF0, + EAS_FILE_XMF1, + EAS_FILE_WAVE_PCM, + EAS_FILE_WAVE_IMA_ADPCM, + EAS_FILE_MMAPI_TONE_CONTROL +} E_EAS_FILE_TYPE; + +/* enumeration for synthesizers */ +typedef enum +{ + EAS_MCU_SYNTH = 0, + EAS_DSP_SYNTH +} E_SYNTHESIZER; + +/* external audio callback program change */ +typedef struct s_ext_audio_prg_chg_tag +{ + EAS_U16 bank; + EAS_U8 program; + EAS_U8 channel; +} S_EXT_AUDIO_PRG_CHG; + +/* external audio callback event */ +typedef struct s_ext_audio_event_tag +{ + EAS_U8 channel; + EAS_U8 note; + EAS_U8 velocity; + EAS_BOOL8 noteOn; +} S_EXT_AUDIO_EVENT; + +typedef struct s_midi_controllers_tag +{ + EAS_U8 modWheel; /* CC1 */ + EAS_U8 volume; /* CC7 */ + EAS_U8 pan; /* CC10 */ + EAS_U8 expression; /* CC11 */ + EAS_U8 channelPressure; /* MIDI channel pressure */ + +#ifdef _REVERB + EAS_U8 reverbSend; /* CC91 */ +#endif + +#ifdef _CHORUS + EAS_U8 chorusSend; /* CC93 */ +#endif +} S_MIDI_CONTROLLERS; + +/* iMode play modes enumeration for EAS_SetPlayMode */ +typedef enum +{ + IMODE_PLAY_ALL = 0, + IMODE_PLAY_PARTIAL +} E_I_MODE_PLAY_MODE; + +typedef EAS_BOOL (*EAS_EXT_PRG_CHG_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_PRG_CHG *pPrgChg); +typedef EAS_BOOL (*EAS_EXT_EVENT_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_EVENT *pEvent); + +#endif /* #ifndef _EAS_TYPES_H */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_wave.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_wave.c new file mode 100755 index 0000000..4f6ffbd --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_wave.c @@ -0,0 +1,423 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wave.c + * + * Contents and purpose: + * This module contains .WAV file functions for the EAS synthesizer + * test harness. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 658 $ + * $Date: 2007-04-24 13:35:49 -0700 (Tue, 24 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* lint complaints about most C library headers, so we use our own during lint step */ +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#endif + +#include "eas_wave.h" + +/* .WAV file format tags */ +const EAS_U32 riffTag = 0x46464952; +const EAS_U32 waveTag = 0x45564157; +const EAS_U32 fmtTag = 0x20746d66; +const EAS_U32 dataTag = 0x61746164; + +#ifdef _BIG_ENDIAN +/*---------------------------------------------------------------------------- + * FlipDWord() + *---------------------------------------------------------------------------- + * Purpose: Endian flip a DWORD for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipDWord (EAS_U32 *pValue) +{ + EAS_U8 *p; + EAS_U32 temp; + + p = (EAS_U8*) pValue; + temp = (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; + *pValue = temp; +} + +/*---------------------------------------------------------------------------- + * FlipWord() + *---------------------------------------------------------------------------- + * Purpose: Endian flip a WORD for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipWord (EAS_U16 *pValue) +{ + EAS_U8 *p; + EAS_U16 temp; + + p = (EAS_U8*) pValue; + temp = (p[1] << 8) | p[0]; + *pValue = temp; +} + +/*---------------------------------------------------------------------------- + * FlipWaveHeader() + *---------------------------------------------------------------------------- + * Purpose: Endian flip the wave header for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipWaveHeader (WAVE_HEADER *p) +{ + + FlipDWord(&p->nRiffTag); + FlipDWord(&p->nRiffSize); + FlipDWord(&p->nWaveTag); + FlipDWord(&p->nFmtTag); + FlipDWord(&p->nFmtSize); + FlipDWord(&p->nDataTag); + FlipDWord(&p->nDataSize); + FlipWord(&p->fc.wFormatTag); + FlipWord(&p->fc.nChannels); + FlipDWord(&p->fc.nSamplesPerSec); + FlipDWord(&p->fc.nAvgBytesPerSec); + FlipWord(&p->fc.nBlockAlign); + FlipWord(&p->fc.wBitsPerSample); + +} +#endif + +/*---------------------------------------------------------------------------- + * WaveFileCreate() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for writing and writes the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample) +{ + WAVE_FILE *wFile; + + /* allocate memory */ + wFile = malloc(sizeof(WAVE_FILE)); + if (!wFile) + return NULL; + wFile->write = EAS_TRUE; + + /* create the file */ + wFile->file = fopen(filename,"wb"); + if (!wFile->file) + { + free(wFile); + return NULL; + } + + /* initialize PCM format .WAV file header */ + wFile->wh.nRiffTag = riffTag; + wFile->wh.nRiffSize = sizeof(WAVE_HEADER) - 8; + wFile->wh.nWaveTag = waveTag; + wFile->wh.nFmtTag = fmtTag; + wFile->wh.nFmtSize = sizeof(FMT_CHUNK); + + /* initalize 'fmt' chunk */ + wFile->wh.fc.wFormatTag = 1; + wFile->wh.fc.nChannels = (EAS_U16) nChannels; + wFile->wh.fc.nSamplesPerSec = (EAS_U32) nSamplesPerSec; + wFile->wh.fc.wBitsPerSample = (EAS_U16) wBitsPerSample; + wFile->wh.fc.nBlockAlign = (EAS_U16) (nChannels * (EAS_U16) (wBitsPerSample / 8)); + wFile->wh.fc.nAvgBytesPerSec = wFile->wh.fc.nBlockAlign * (EAS_U32) nSamplesPerSec; + + /* initialize 'data' chunk */ + wFile->wh.nDataTag = dataTag; + wFile->wh.nDataSize = 0; + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + + /* write the header */ + if (fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file) != 1) + { + fclose(wFile->file); + free(wFile); + return NULL; + } + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + + /* return the file handle */ + return wFile; +} /* end WaveFileCreate */ + +/*---------------------------------------------------------------------------- + * WaveFileWrite() + *---------------------------------------------------------------------------- + * Purpose: Writes data to the wave file + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n) +{ + EAS_I32 count; + + /* make sure we have an open file */ + if (wFile == NULL) + { + return 0; + } + +#ifdef _BIG_ENDIAN + { + EAS_I32 i; + EAS_U16 *p; + p = buffer; + i = n >> 1; + while (i--) + FlipWord(p++); + } +#endif + + /* write the data */ + count = (EAS_I32) fwrite(buffer, 1, (size_t) n, wFile->file); + + /* add the number of bytes written */ + wFile->wh.nRiffSize += (EAS_U32) count; + wFile->wh.nDataSize += (EAS_U32) count; + + /* return the count of bytes written */ + return count; +} /* end WriteWaveHeader */ + +/*---------------------------------------------------------------------------- + * WaveFileClose() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for writing and writes the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +EAS_BOOL WaveFileClose (WAVE_FILE *wFile) +{ + EAS_I32 count = 1; + + /* return to beginning of file and write the header */ + if (wFile->write) + { + if (fseek(wFile->file, 0L, SEEK_SET) == 0) + { + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + count = (EAS_I32) fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file); +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + } + } + + /* close the file */ + if (fclose(wFile->file) != 0) + count = 0; + + /* free the memory */ + free(wFile); + + /* return the file handle */ + return (count == 1 ? EAS_TRUE : EAS_FALSE); +} /* end WaveFileClose */ + +#ifdef _WAVE_FILE_READ +#ifdef _BIG_ENDIAN +#error "WaveFileOpen not currently supported on big-endian processors" +#endif +/*---------------------------------------------------------------------------- + * WaveFileOpen() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for reading and reads the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +WAVE_FILE *WaveFileOpen (const char *filename) +{ + WAVE_FILE *wFile; + struct + { + EAS_U32 tag; + EAS_U32 size; + } chunk; + EAS_U32 tag; + EAS_I32 startChunkPos; + EAS_INT state; + EAS_BOOL done; + + /* allocate memory */ + wFile = malloc(sizeof(WAVE_FILE)); + if (!wFile) + return NULL; + + /* open the file */ + wFile->write = EAS_FALSE; + wFile->file = fopen(filename,"rb"); + if (!wFile->file) + { + free(wFile); + return NULL; + } + + /* make lint happy */ + chunk.tag = chunk.size = 0; + startChunkPos = 0; + + /* read the RIFF tag and file size */ + state = 0; + done = EAS_FALSE; + while (!done) + { + + switch(state) + { + /* read the RIFF tag */ + case 0: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + if (chunk.tag != riffTag) + done = EAS_TRUE; + else + state++; + } + break; + + /* read the WAVE tag */ + case 1: + if (fread(&tag, sizeof(tag), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + if (tag != waveTag) + done = EAS_TRUE; + else + state++; + } + break; + + /* looking for fmt chunk */ + case 2: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + startChunkPos = ftell(wFile->file); + + /* not fmt tag, skip it */ + if (chunk.tag != fmtTag) + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + else + state++; + } + break; + + /* read fmt chunk */ + case 3: + if (fread(&wFile->wh.fc, sizeof(FMT_CHUNK), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + state++; + } + break; + + /* looking for data chunk */ + case 4: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + startChunkPos = ftell(wFile->file); + + /* not data tag, skip it */ + if (chunk.tag != dataTag) + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + else + { + wFile->dataSize = chunk.size; + state++; + done = EAS_TRUE; + } + } + break; + + default: + done = EAS_TRUE; + break; + } + } + + /* if not final state, an error occurred */ + if (state != 5) + { + fclose(wFile->file); + free(wFile); + return NULL; + } + + /* return the file handle */ + return wFile; +} /* end WaveFileOpen */ +#endif + + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_wave.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_wave.h new file mode 100755 index 0000000..968782f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/host_src/eas_wave.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wave.h + * + * Contents and purpose: + * Writes output to a .WAV file + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" + +/* sentinel */ +#ifndef _EAS_WAVE_H +#define _EAS_WAVE_H + +/* .WAV file format chunk */ +typedef struct { + EAS_U16 wFormatTag; + EAS_U16 nChannels; + EAS_U32 nSamplesPerSec; + EAS_U32 nAvgBytesPerSec; + EAS_U16 nBlockAlign; + EAS_U16 wBitsPerSample; +} FMT_CHUNK; + +/* .WAV file header */ +typedef struct { + EAS_U32 nRiffTag; + EAS_U32 nRiffSize; + EAS_U32 nWaveTag; + EAS_U32 nFmtTag; + EAS_U32 nFmtSize; + FMT_CHUNK fc; + EAS_U32 nDataTag; + EAS_U32 nDataSize; +} WAVE_HEADER; + +typedef struct { + WAVE_HEADER wh; + FILE *file; + EAS_BOOL write; + EAS_U32 dataSize; +} WAVE_FILE; + +WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample); +EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n); +EAS_BOOL WaveFileClose (WAVE_FILE *wFile); +WAVE_FILE *WaveFileOpen (const char *filename); + +#endif /* end #ifndef _EAS_WAVE_H */ + + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib/libarm-hybrid-22k.a b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib/libarm-hybrid-22k.a new file mode 100755 index 0000000..f3999f0 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib/libarm-hybrid-22k.a differ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_filter_gnu.s b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_filter_gnu.s new file mode 100755 index 0000000..871cd7d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_filter_gnu.s @@ -0,0 +1,134 @@ +@*********************************************************** +@ Function: WT_VoiceFilter +@ Processor: ARM +@ Description: +@ Implements a 2-pole low-pass filter with resonanance +@ +@ Usage: +@ void WT_VoiceFilter( +@ S_FILTER CONTROL *pFilter, +@ S_WT_FRAME *pWTFrame); +@ +@ Copyright 2005 Sonic Network, Inc. +@**************************************************************** +@ Revision Control: +@ $Revision: 496 $ +@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $ +@**************************************************************** +@ +@ where: +@ S_FILTER_CONTROL *pFilter +@ PASSED IN: r0 +@ +@ S_WT_FRAME *pWTFrame +@ PASSED IN: r1 +@**************************************************************** + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + + .global WT_VoiceFilter + + +@ Register usage +@ -------------- +pFilter .req r0 +pWTFrame .req r1 +pBuffer .req r2 +numSamples .req r3 + +z1 .req r4 +z2 .req r5 +b1 .req r6 +b2 .req r7 +K .req r8 + +tmp0 .req r1 @ reuse register +tmp1 .req r9 +tmp2 .req r10 + + +@SaveRegs RLIST {r4-r10, lr} +@RestoreRegs RLIST {r4-r10, pc} + + + .func WT_VoiceFilter +WT_VoiceFilter: + + STMFD sp!, {r4-r10, lr} + +@ +@ Setup passed parameters in their destination registers +@---------------------------------------------------------------- + + LDR pBuffer, [pWTFrame, #m_pAudioBuffer] + LDR numSamples, [pWTFrame, #m_numSamples] + + @load state variables from pFilter structure + LDRSH z1, [pFilter, #m_z1] + LDRSH z2, [pFilter, #m_z2] + + @load coefficients from pWTFrame structure + LDR K, [pWTFrame, #m_k] + LDR b1, [pWTFrame, #m_b1] + LDR b2, [pWTFrame, #m_b2] + + RSB b1, b1, #0 @ b1 = -b1 + RSB b2, b2, #0 @ b2 = -b2 + MOV b2, b2, ASR #1 @ b2 = b2 >> 1 + MOV K, K, ASR #1 @ K = K >> 1 + +@ +@ Start processing +@---------------------------------------------------------------- + + LDRSH tmp0, [pBuffer] @ fetch sample + +FilterLoop: + SMULBB tmp2, z1, b1 @ tmp2 = z1 * -b1 + SMLABB tmp2, z2, b2, tmp2 @ tmp2 = (-b1 * z1) + (-b2 * z2) + + MOV z2, z1 @ delay line + + SMLABB tmp0, tmp0, K, tmp2 @ tmp1 = (K * x[n]) + (-b1 * z1) + (-b2 * z2) + + LDRSH tmp1, [pBuffer, #NEXT_OUTPUT_PCM] @ fetch next sample + + MOV z1, tmp0, ASR #14 @ shift result to low word + STRH z1, [pBuffer], #NEXT_OUTPUT_PCM @ write back to buffer + + SMULBB tmp2, z1, b1 @ tmp2 = z1 * -b1 + + SUBS numSamples, numSamples, #2 @ unroll loop once + + SMLABB tmp2, z2, b2, tmp2 @ tmp2 = (-b1 * z1) + (-b2 * z2) + + SMLABB tmp1, tmp1, K, tmp2 @ tmp1 = (K * x[n]) + (-b1 * z1) + (-b2 * z2) + + MOV z2, z1 @ delay line + + MOV z1, tmp1, ASR #14 @ shift result to low word + + LDRGTSH tmp0, [pBuffer, #NEXT_OUTPUT_PCM] @ fetch next sample + + STRH z1, [pBuffer], #NEXT_OUTPUT_PCM @ write back to buffer + + BGT FilterLoop +@ save z terms +@---------------------------------------------------------------- + + STRH z1, [pFilter, #m_z1] + STRH z2, [pFilter, #m_z2] + +@ Return to calling function +@---------------------------------------------------------------- + + LDMFD sp!,{r4-r10, lr} + BX lr + + .endfunc + .end + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_interpolate_loop_gnu.s b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_interpolate_loop_gnu.s new file mode 100755 index 0000000..847a7f0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_interpolate_loop_gnu.s @@ -0,0 +1,131 @@ +@*********************************************************** +@ Function: WT_Interpolate +@ Processor: ARM-E +@ Description: the main synthesis function when fetching +@ wavetable samples. +@ C-callable. +@ +@ Usage: +@ void WT_Interpolate( +@ S_WT_VOICE *pWTVoice, +@ S_WT_FRAME *pWTFrame); +@ +@ Copyright Sonic Network Inc. 2004 +@**************************************************************** +@ Revision Control: +@ $Revision: 496 $ +@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $ +@**************************************************************** +@ +@ where: +@ S_WT_VOICE *pWTVoice +@ PASSED IN: r0 +@ +@ S_WT_FRAME *pWTFrame; +@ PASSED IN: r1 +@**************************************************************** + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + .global WT_Interpolate + + +@ Register usage +@ -------------- +pWTVoice .req r0 +pWTFrame .req r1 + +numSamples .req r2 +phaseIncrement .req r3 +pOutputBuffer .req r4 + +tmp0 .req r1 @reuse register +tmp1 .req r5 +tmp2 .req r6 + +pLoopEnd .req r7 +pLoopStart .req r8 + +pPhaseAccum .req r9 +phaseFrac .req r10 +phaseFracMask .req r11 + +@SaveRegs RLIST {r4-r11,lr} +@RestoreRegs RLIST {r4-r11,pc} + + .func WT_Interpolate +WT_Interpolate: + + STMFD sp!,{r4-r11,lr} + +@ +@ Fetch parameters from structures +@---------------------------------------------------------------- + + LDR pOutputBuffer, [pWTFrame, #m_pAudioBuffer] + LDR numSamples, [pWTFrame, #m_numSamples] + + LDR phaseIncrement, [pWTFrame, #m_phaseIncrement] + LDR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] + LDR phaseFrac, [pWTVoice, #m_phaseFrac] + LDR phaseFracMask,=PHASE_FRAC_MASK + + LDR pLoopStart, [pWTVoice, #m_pLoopStart] + LDR pLoopEnd, [pWTVoice, #m_pLoopEnd] + ADD pLoopEnd, pLoopEnd, #1 @ need loop end to equal last sample + 1 + +InterpolationLoop: + SUBS tmp0, pPhaseAccum, pLoopEnd @ check for loop end + ADDGE pPhaseAccum, pLoopStart, tmp0 @ loop back to start + + .ifdef SAMPLES_8_BIT + LDRSB tmp0, [pPhaseAccum] @ tmp0 = x0 + LDRSB tmp1, [pPhaseAccum, #1] @ tmp1 = x1 + .else + LDRSH tmp0, [pPhaseAccum] @ tmp0 = x0 + LDRSH tmp1, [pPhaseAccum, #2] @ tmp1 = x1 + .endif + + ADD tmp2, phaseIncrement, phaseFrac @ increment pointer here to avoid pipeline stall + + SUB tmp1, tmp1, tmp0 @ tmp1 = x1 - x0 + SMULBB tmp1, phaseFrac, tmp1 @ tmp1 = phaseFrac * tmp2 + +@ This section performs a gain adjustment of -12dB for 16-bit samples +@ or +36dB for 8-bit samples. For a high quality synthesizer, the output +@ can be set to full scale, however if the filter is used, it can overflow +@ with certain coefficients and signal sources. In this case, either a +@ saturation operation should take in the filter before scaling back to +@ 16 bits or the signal path should be increased to 18 bits or more. + + .ifdef SAMPLES_8_BIT + MOV tmp0, tmp0, LSL #6 @ boost 8-bit signal by 36dB + .else + MOV tmp0, tmp0, ASR #2 @ reduce 16-bit signal by 12dB + .endif + + ADD tmp1, tmp0, tmp1, ASR #(NUM_EG1_FRAC_BITS-6) @ tmp1 = tmp0 + (tmp1 >> (15-6)) + @ = x0 + f * (x1 - x0) == interpolated result + + STRH tmp1, [pOutputBuffer], #NEXT_OUTPUT_PCM @ *pOutputBuffer++ = interpolated result + +@ carry overflow from fraction to integer portion + ADD pPhaseAccum, pPhaseAccum, tmp2, LSR #(NUM_PHASE_FRAC_BITS - NEXT_INPUT_PCM_SHIFT) + AND phaseFrac, tmp2, phaseFracMask @ nphaseFrac = frac part + + SUBS numSamples, numSamples, #1 + BGT InterpolationLoop + +@ update and store phase + STR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] + STR phaseFrac, [pWTVoice, #m_phaseFrac] + + LDMFD sp!,{r4-r11,lr} + BX lr + + .endfunc + .end + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_interpolate_noloop_gnu.s b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_interpolate_noloop_gnu.s new file mode 100755 index 0000000..6343762 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_interpolate_noloop_gnu.s @@ -0,0 +1,130 @@ +@*********************************************************** +@ Function: WT_InterpolateNoLoop +@ Processor: ARM-E +@ Description: the main synthesis function when fetching +@ wavetable samples. +@ C-callable. +@ +@ Usage: +@ void WT_InterpolateNoLoop( +@ S_WT_VOICE *pWTVoice, +@ S_WT_FRAME *pWTFrame); +@ +@ Copyright Sonic Network Inc. 2004 +@**************************************************************** +@ Revision Control: +@ $Revision: 496 $ +@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $ +@**************************************************************** +@ +@ where: +@ S_WT_VOICE *pWTVoice +@ PASSED IN: r0 +@ +@ S_WT_FRAME *pWTFrame; +@ PASSED IN: r1 +@**************************************************************** + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + + .global WT_InterpolateNoLoop + + +@ Register usage +@ -------------- +pWTVoice .req r0 +pWTFrame .req r1 +pOutputBuffer .req r2 +numSamples .req r3 + +phaseIncrement .req r4 +pPhaseAccum .req r5 +phaseFrac .req r6 +phaseFracMask .req r7 + +tmp0 .req r1 @ reuse register +tmp1 .req r8 +tmp2 .req r9 + + +@SaveRegs RLIST {r4-r9,lr} +@RestoreRegs RLIST {r4-r9,pc} + + .func WT_InterpolateNoLoop +WT_InterpolateNoLoop: + + STMFD sp!, {r4-r9,lr} + +@ +@ Fetch parameters from structures +@---------------------------------------------------------------- + + LDR pOutputBuffer, [pWTFrame, #m_pAudioBuffer] + LDR numSamples, [pWTFrame, #m_numSamples] + + LDR phaseIncrement, [pWTFrame, #m_phaseIncrement] + LDR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] + LDR phaseFrac, [pWTVoice, #m_phaseFrac] + LDR phaseFracMask,=PHASE_FRAC_MASK + +InterpolationLoop: + + .ifdef SAMPLES_8_BIT + LDRSB tmp0, [pPhaseAccum] @ tmp0 = x0 + LDRSB tmp1, [pPhaseAccum, #1] @ tmp1 = x1 + .else + LDRSH tmp0, [pPhaseAccum] @ tmp0 = x0 + LDRSH tmp1, [pPhaseAccum, #2] @ tmp1 = x1 + .endif + + ADD tmp2, phaseIncrement, phaseFrac @ increment pointer here to avoid pipeline stall + + SUB tmp1, tmp1, tmp0 @ tmp1 = x1 - x0 + SMULBB tmp1, phaseFrac, tmp1 @ tmp1 = phaseFrac * tmp2 + +@ This section performs a gain adjustment of -12dB for 16-bit samples +@ or +36dB for 8-bit samples. For a high quality synthesizer, the output +@ can be set to full scale, however if the filter is used, it can overflow +@ with certain coefficients and signal sources. In this case, either a +@ saturation operation should take in the filter before scaling back to +@ 16 bits or the signal path should be increased to 18 bits or more. + + .ifdef SAMPLES_8_BIT + MOV tmp0, tmp0, LSL #6 @ boost 8-bit signal by 36dB + .else + MOV tmp0, tmp0, ASR #2 @ reduce 16-bit signal by 12dB + .endif + + ADD tmp1, tmp0, tmp1, ASR #(NUM_EG1_FRAC_BITS-6) @ tmp1 = tmp0 + (tmp1 >> (15-6)) + @ = x0 + f * (x1 - x0) == interpolated result + + STRH tmp1, [pOutputBuffer], #NEXT_OUTPUT_PCM @ *pOutputBuffer++ = interpolated result + +@ carry overflow from fraction to integer portion + ADD pPhaseAccum, pPhaseAccum, tmp2, LSR #(NUM_PHASE_FRAC_BITS - NEXT_INPUT_PCM_SHIFT) + AND phaseFrac, tmp2, phaseFracMask @ nphaseFrac = frac part + + SUBS numSamples, numSamples, #1 + BGT InterpolationLoop + +@ Clean up and store any changes that were caused during the loop +@---------------------------------------------------------------- + + @ update and store phase + STR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] + STR phaseFrac, [pWTVoice, #m_phaseFrac] + +@ +@ Return to calling function +@---------------------------------------------------------------- + + LDMFD sp!,{r4-r9,lr} + BX lr + + .endfunc + .end + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_mastergain_gnu.s b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_mastergain_gnu.s new file mode 100755 index 0000000..b4e905b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_mastergain_gnu.s @@ -0,0 +1,109 @@ +@*********************************************************** +@ Function: SynthMasterGain +@ Processor: ARM-E +@ Description: Copies 32-bit synth output to 16-bit buffer +@ with saturated gain control +@ C-callable. +@ +@ Usage: +@ SynthMasterGain( +@ pInputBuffer +@ pOutputBuffer, +@ nGain, +@ nNumLoopSamples +@ ); +@ +@ Copyright Sonic Network Inc. 2004 +@**************************************************************** +@ Revision Control: +@ $Revision: 496 $ +@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $ +@**************************************************************** +@ +@ where: +@ long *pInputBuffer +@ PASSED IN: r0 +@ +@ EAS_PCM *pOutputBuffer +@ PASSED IN: r1 +@ +@ short nGain +@ PASSED IN: r2 +@ +@ EAS_U16 nNumLoopSamples +@ PASSED IN: r3 +@ +@**************************************************************** + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + .func SynthMasterGain +SynthMasterGain: + + .global SynthMasterGain @ allow other files to use this function + + + + + +@ Stack frame +@ ----------- + .equ RET_ADDR_SZ, 0 @return address + .equ REG_SAVE_SZ, 0 @save-on-entry registers saved + .equ FRAME_SZ, (8) @local variables + .equ ARG_BLK_SZ, 0 @argument block + + .equ PARAM_OFFSET, (ARG_BLK_SZ + FRAME_SZ + REG_SAVE_SZ + RET_ADDR_SZ) + +@ Register usage +@ -------------- +pnInputBuffer .req r0 +pnOutputBuffer .req r1 +nGain .req r2 +nNumLoopSamples .req r3 + + STMFD sp!,{r4-r6,r14} @Save any save-on-entry registers that are used + + LDR r6, =0x7fff @constant for saturation tests + +loop: + LDR r4, [pnInputBuffer], #4 @fetch 1st output sample + + LDR r5, [pnInputBuffer], #4 @fetch 2nd output sample + + SMULWB r4, r4, nGain @output = gain * input + + CMP r4, r6 @check for positive saturation + MOVGT r4, r6 @saturate + CMN r4, r6 @check for negative saturation + MVNLT r4, r6 @saturate + + SMULWB r5, r5, nGain @output = gain * input + + STRH r4, [pnOutputBuffer], #NEXT_OUTPUT_PCM @save 1st output sample + + CMP r5, r6 @check for positive saturation + MOVGT r5, r6 @saturate + CMN r5, r6 @check for negative saturation + MVNLT r5, r6 @saturate + STRH r5, [pnOutputBuffer], #NEXT_OUTPUT_PCM @save 2nd output sample + + SUBS nNumLoopSamples, nNumLoopSamples, #2 + BGT loop + +@ +@ Return to calling function +@---------------------------------------------------------------- + + LDMFD sp!,{r4-r6, lr} @ return to calling function + BX lr + +@***************************************************************************** + + .endfunc @ end of function/procedure + + .end @ end of assembly code + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_voice_gain_gnu.s b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_voice_gain_gnu.s new file mode 100755 index 0000000..4517a3d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM-E_voice_gain_gnu.s @@ -0,0 +1,166 @@ +@*********************************************************** +@ Function: WT_VoiceGain +@ Processor: ARM-E +@ Description: the main synthesis function when fetching +@ wavetable samples. +@ C-callable. +@ +@ Usage: +@ Usage: +@ WT_VoiceGain( +@ S_WT_VOICE *pWTVoice, +@ S_WT_FRAME *pWTFrame); +@ +@ Copyright 2004, 2005 Sonic Network, Inc. +@**************************************************************** +@ Revision Control: +@ $Revision: 814 $ +@ $Date: 2007-08-02 10:34:53 -0700 (Thu, 02 Aug 2007) $ +@**************************************************************** +@ +@ where: +@ S_WT_VOICE *psVoice +@ PASSED IN: r0 +@ +@ S_WT_FRAME *pWTFrame +@ PASSED IN: r1 +@**************************************************************** + + + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + .global WT_VoiceGain + +@ Register usage +@ -------------- +pWTVoice .req r0 +pWTFrame .req r1 +pInputBuffer .req r2 +pMixBuffer .req r3 + +tmp0 .req r4 +tmp1 .req r5 +tmp2 .req r1 @ reuse register +tmp3 .req r6 + +numSamples .req r9 + + .if STEREO_OUTPUT +gainIncLeft .req r7 +gainIncRight .req r8 +gainLeft .req r10 +gainRight .req r11 + .else +gainIncrement .req r7 +gain .req r8 + .endif + + +@ register context for local variables +@SaveRegs RLIST {r4-r11,lr} +@RestoreRegs RLIST {r4-r11,pc} + + .func WT_VoiceGain +WT_VoiceGain: + + STMFD sp!, {r4-r11,lr} + + LDR pInputBuffer, [pWTFrame, #m_pAudioBuffer] + LDR pMixBuffer, [pWTFrame, #m_pMixBuffer] + LDR numSamples, [pWTFrame, #m_numSamples] + +@---------------------------------------------------------------- +@ Stereo version +@---------------------------------------------------------------- +@ NOTE: instructions are reordered to reduce the effect of latency +@ due to storage and computational dependencies. +@---------------------------------------------------------------- + + .if STEREO_OUTPUT + + LDR tmp0, [pWTFrame, #m_prevGain] + LDR tmp1, [pWTFrame, #m_gainTarget] + + LDRSH gainLeft, [pWTVoice, #m_gainLeft] + LDRSH gainRight, [pWTVoice, #m_gainRight] + + MOV gainIncLeft, gainLeft + SMULBB gainLeft, tmp0, gainLeft + + SMULBB gainIncLeft, tmp1, gainIncLeft + SUB gainIncLeft, gainIncLeft, gainLeft + MOV gainLeft, gainLeft, ASR #(NUM_MIXER_GUARD_BITS - 2) + MOV gainIncLeft, gainIncLeft, ASR #(SYNTH_UPDATE_PERIOD_IN_BITS + NUM_MIXER_GUARD_BITS - 2) + + MOV gainIncRight, gainRight + SMULBB gainRight, tmp0, gainRight + + SMULBB gainIncRight, tmp1, gainIncRight + SUB gainIncRight, gainIncRight, gainRight + MOV gainRight, gainRight, ASR #(NUM_MIXER_GUARD_BITS - 2) + MOV gainIncRight, gainIncRight, ASR #(SYNTH_UPDATE_PERIOD_IN_BITS + NUM_MIXER_GUARD_BITS - 2) + + LDRSH tmp0, [pInputBuffer], #2 + +StereoGainLoop: + LDR tmp1, [pMixBuffer] + + ADD gainLeft, gainLeft, gainIncLeft + + SMLAWB tmp1, gainLeft, tmp0, tmp1 + + LDR tmp2, [pMixBuffer, #4] + + ADD gainRight, gainRight, gainIncRight + + STR tmp1, [pMixBuffer], #4 + + SMLAWB tmp2, gainRight, tmp0, tmp2 + + SUBS numSamples, numSamples, #1 + + LDRGTSH tmp0, [pInputBuffer], #2 + + STR tmp2, [pMixBuffer], #4 + + BGT StereoGainLoop + +@---------------------------------------------------------------- +@ Mono version +@---------------------------------------------------------------- + .else + + LDR gain, [pWTFrame, #m_prevGain] + MOV gain, gain, LSL #(NUM_MIXER_GUARD_BITS + 4) + LDR gainIncrement, [pWTFrame, #m_gainTarget] + MOV gainIncrement, gainIncrement, LSL #(NUM_MIXER_GUARD_BITS + 4) + SUB gainIncrement, gainIncrement, gain + MOV gainIncrement, gainIncrement, ASR #SYNTH_UPDATE_PERIOD_IN_BITS + +MonoGainLoop: + + LDRSH tmp0, [pInputBuffer], #NEXT_OUTPUT_PCM @ fetch voice output + + LDR tmp1, [pMixBuffer] @ get left channel output sample + ADD gain, gain, gainIncrement @ gain step to eliminate zipper noise + SMULWB tmp0, gain, tmp0 @ sample * local gain + + MOV tmp0, tmp0, ASR #1 @ add 6dB headroom + ADD tmp1, tmp0, tmp1 + STR tmp1, [pMixBuffer], #4 @ save and bump pointer + + SUBS numSamples, numSamples, #1 + BGT MonoGainLoop + + .endif @end Mono version + + LDMFD sp!,{r4-r11,lr} + BX lr + + .endfunc + .end + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM_synth_constants_gnu.inc b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM_synth_constants_gnu.inc new file mode 100755 index 0000000..c0f8df3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/ARM_synth_constants_gnu.inc @@ -0,0 +1,153 @@ +@*********************************************************** +@ File: ARM_synth_constants.inc +@ Processor: ARM +@ Description: Contains constants and defines, most of which +@ are mirrored in synth.h +@ +@ Copyright Sonic Network Inc. 2004 +@**************************************************************** +@ Revision Control: +@ $Revision: 741 $ +@ $Date: 2007-06-22 16:39:21 -0700 (Fri, 22 Jun 2007) $ +@**************************************************************** + + + .ifdef SAMPLE_RATE_8000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 5 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 32 + .endif + + .ifdef SAMPLE_RATE_16000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 6 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 64 + .endif + + .ifdef SAMPLE_RATE_20000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128 + .endif + + .ifdef SAMPLE_RATE_22050 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128 + .endif + + .ifdef SAMPLE_RATE_24000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128 + .endif + + .ifdef SAMPLE_RATE_32000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128 + .endif + + .ifdef SAMPLE_RATE_44100 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 8 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 256 + .endif + + .ifdef SAMPLE_RATE_48000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 8 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 256 + .endif + + +@ if the OUTPUT PCM sample is 16-bits, then when using indexed addressing, +@ the next sample is this many bytes away + .equ NEXT_OUTPUT_PCM, 2 + +@**************************************************************************** +@/* macros for fractional phase accumulator */ + .equ NUM_PHASE_FRAC_BITS, 15 + + .equ PHASE_FRAC_MASK, 0x7FFF + +@ shift for phase accumulator when fraction carries over + .ifdef SAMPLES_8_BIT + .equ NEXT_INPUT_PCM_SHIFT, 0 + .endif + + .ifdef SAMPLES_16_BIT + .equ NEXT_INPUT_PCM_SHIFT, 1 + .endif + +@**************************************************************************** + .equ NUM_MIXER_GUARD_BITS, 4 + +@**************************************************************************** +@/* Envelope 1 (EG1) calculation macros */ + .equ NUM_EG1_FRAC_BITS, 15 + +@**************************************************************************** + + .equ NUM_ENHANCER_FILTER_COEF_FRAC_BITS, 5 + +@**************************************************************************** + +@ +@ I've temporarily given up on the idea of getting ADS/RV and gcc to +@ handle a struct in a compatible fashion. Switching to old fashion EQU +@ + + .if FILTER_ENABLED +@************************************** +@ typedef struct s_filter_tag + .equ m_z1, 0 + .equ m_z2, 2 + .endif + +@************************************** +@ typedef struct s_wt_frame_tag + .equ m_gainTarget, 0 + .equ m_phaseIncrement, 4 + + .if FILTER_ENABLED + .equ m_k, 8 + .equ m_b1, 12 + .equ m_b2, 16 + .equ m_pAudioBuffer, 20 + .equ m_pMixBuffer, 24 + .equ m_numSamples, 28 + .equ m_prevGain, 32 + .else + .equ m_pAudioBuffer, 8 + .equ m_pMixBuffer, 12 + .equ m_numSamples, 16 + .equ m_prevGain, 20 + .endif + + +@************************************** +@ typedef struct s_wt_voice_tag + .equ m_pLoopEnd, 0 @ /* points to last PCM sample (not 1 beyond last) */ + .equ m_pLoopStart, 4 @ /* points to first sample at start of loop */ + .equ m_pPhaseAccum, 8 @ /* points to first sample at start of loop */ + .equ m_phaseFrac, 12 @ /* points to first sample at start of loop */ + + .if STEREO_OUTPUT + .equ m_gainLeft, 16 @ /* current gain, left ch */ + .equ m_gainRight, 18 @ /* current gain, right ch */ + .endif + + +@**************************************************************************** +@ enhancer + .equ m_nEnhancerFeedForward1, 0 + .equ m_nEnhancerFeedback1, 1 + .equ m_nDriveCoef, 2 + .equ m_nEnhancerFeedback2, 3 + .equ m_nWet, 4 + .equ m_nDry, 5 + + .equ m_zF0L, 6 @ filter 1 zero state var, left + .equ m_zF1L, 8 @ filter 1 pole state var, left + .equ m_zF2L, 10 @ filter 2 zero state var, left + .equ m_zF0R, 12 @ filter 1 zero state var, right + .equ m_zF1R, 14 @ filter 1 pole state var, right + .equ m_zF2R, 16 @ filter 2 zero state var, right + +@**************************************************************************** + + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/arm-hybrid-22k_lib.mak b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/arm-hybrid-22k_lib.mak new file mode 100755 index 0000000..43edd6d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/arm-hybrid-22k_lib.mak @@ -0,0 +1,25 @@ +# +# Auto-generated sample makefile +# +# This makefile is intended for use with GNU make. +# Set the paths to the tools (CC, AR, LD, etc.) +# + +vpath %.c lib_src + +CC = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AS = C:\Program Files\GNUARM\bin\arm-elf-as.exe +LD = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AR = C:\Program Files\GNUARM\bin\arm-elf-ar.exe + +%.o: %.c + $(CC) -c -O2 -o $@ -I lib_src -I host_src -D NUM_OUTPUT_CHANNELS=2 -D _SAMPLE_RATE_22050 -D MAX_SYNTH_VOICES=32 -D NUM_PRIMARY_VOICES=8 -D EAS_HYBRID_SYNTH -D _8_BIT_SAMPLES -D _FILTER_ENABLED -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED -D _IMA_DECODER -D NATIVE_EAS_KERNEL $< + +%.o: %.s + $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa -I lib_src --defsym CHECK_STACK=0 --defsym REVERB=0 --defsym CHORUS=0 --defsym STEREO_OUTPUT=1 --defsym SAMPLE_RATE_22050=1 --defsym SAMPLES_8_BIT=1 --defsym FILTER_ENABLED=1 $< + +OBJS = eas_mididata.o eas_pan.o eas_wavefiledata.o eas_wavefile.o eas_smfdata.o eas_imelody.o eas_math.o eas_fmengine.o ARM-E_filter_gnu.o eas_chorusdata.o eas_wtengine.o eas_ota.o eas_rtttldata.o eas_reverbdata.o eas_public.o ARM-E_interpolate_loop_gnu.o eas_rtttl.o eas_reverb.o ARM-E_voice_gain_gnu.o eas_fmsynth.o eas_midi.o eas_otadata.o eas_wtsynth.o eas_mixbuf.o eas_imaadpcm.o hybrid_22khz_mcu.o eas_smf.o eas_chorus.o eas_pcm.o eas_mixer.o eas_data.o eas_imelodydata.o eas_pcmdata.o eas_ima_tables.o eas_fmtables.o ARM-E_interpolate_noloop_gnu.o ARM-E_mastergain_gnu.o eas_voicemgt.o + +arm-hybrid-22k.a: $(OBJS) + $(AR) rc lib$@ $(OBJS) + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_audioconst.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_audioconst.h new file mode 100755 index 0000000..066148e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_audioconst.h @@ -0,0 +1,97 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_audioconst.h + * + * Contents and purpose: + * Defines audio constants related to the sample rate, bit size, etc. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_AUDIOCONST_H +#define _EAS_AUDIOCONST_H + +/*---------------------------------------------------------------------------- + * These macros define the various characteristics of the defined sample rates + *---------------------------------------------------------------------------- + * BUFFER_SIZE_IN_MONO_SAMPLES size of buffer in samples + * _OUTPUT_SAMPLE_RATE compiled output sample rate + * AUDIO_FRAME_LENGTH length of an audio frame in 256ths of a millisecond + * SYNTH_UPDATE_PERIOD_IN_BITS length of an audio frame (2^x samples) + *---------------------------------------------------------------------------- +*/ + +#if defined (_SAMPLE_RATE_8000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 32 +#define _OUTPUT_SAMPLE_RATE 8000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 5 + +#elif defined (_SAMPLE_RATE_16000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 64 +#define _OUTPUT_SAMPLE_RATE 16000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 6 + +#elif defined (_SAMPLE_RATE_20000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 20000 +#define AUDIO_FRAME_LENGTH 1638 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_22050) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 22050 +#define AUDIO_FRAME_LENGTH 1486 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_24000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 24000 +#define AUDIO_FRAME_LENGTH 1365 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_32000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 32000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_44100) +#define BUFFER_SIZE_IN_MONO_SAMPLES 256 +#define _OUTPUT_SAMPLE_RATE 44100 +#define AUDIO_FRAME_LENGTH 1486 +#define SYNTH_UPDATE_PERIOD_IN_BITS 8 + +#elif defined (_SAMPLE_RATE_48000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 256 +#define _OUTPUT_SAMPLE_RATE 48000 +#define AUDIO_FRAME_LENGTH 1365 +#define SYNTH_UPDATE_PERIOD_IN_BITS 8 + +#else +#error "_SAMPLE_RATE_XXXXX must be defined to valid rate" +#endif + +#endif /* #ifndef _EAS_AUDIOCONST_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorus.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorus.c new file mode 100755 index 0000000..4a2c8d0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorus.c @@ -0,0 +1,604 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorus.c + * + * Contents and purpose: + * Contains the implementation of the Chorus effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 499 $ + * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_effects.h" +#include "eas_math.h" +#include "eas_chorusdata.h" +#include "eas_chorus.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" + +/* prototypes for effects interface */ +static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); +static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); +static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + +/* common effects interface for configuration module */ +const S_EFFECTS_INTERFACE EAS_Chorus = +{ + ChorusInit, + ChorusProcess, + ChorusShutdown, + ChorusGetParam, + ChorusSetParam +}; + + + +//LFO shape table used by the chorus, larger table would sound better +//this is a sine wave, where 32767 = 1.0 +static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = { + 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170, + 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728, + 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329, + 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212, + 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519, + -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785, + -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621, + -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010, + -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608 +}; + +/*---------------------------------------------------------------------------- + * InitializeChorus() + *---------------------------------------------------------------------------- + * Purpose: Initializes chorus parameters + * + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) +{ + S_CHORUS_OBJECT *pChorusData; + S_CHORUS_PRESET *pPreset; + EAS_I32 index; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS); + + /* allocate dynamic memory */ + else + pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT)); + + if (pChorusData == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* clear the structure */ + EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT)); + + ChorusReadInPresets(pChorusData); + + /* set some default values */ + pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT; + pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT; + pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT; + pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT; + pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT; + + //chorus rate and depth need some massaging from preset value (which is sample rate independent) + + //convert rate from steps of .05 Hz to value which can be used as phase increment, + //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits + //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate; + //computing it as below allows rate steps to be evenly spaced + //uses 32 bit divide, but only once when new value is selected + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction + //want to compute ((depth * sampleRate)/20000) + //use the following approximation since 105/32 is roughly 65536/20000 + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + pChorusData->m_nLevel = pChorusData->m_nLevel; + + //zero delay memory for chorus + for (index = CHORUS_L_SIZE - 1; index >= 0; index--) + { + pChorusData->chorusDelayL[index] = 0; + } + for (index = CHORUS_R_SIZE - 1; index >= 0; index--) + { + pChorusData->chorusDelayR[index] = 0; + } + + //init delay line index, these are used to implement circular delay buffer + pChorusData->chorusIndexL = 0; + pChorusData->chorusIndexR = 0; + + //init LFO phase + //16 bit whole part, 16 bit fraction + pChorusData->lfoLPhase = 0; + pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase; + + //init chorus delay position + //right now chorus delay is a compile-time value, as is sample rate + pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000); + + //now copy from the new preset into Chorus + pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; + + pChorusData->m_nLevel = pPreset->m_nLevel; + pChorusData->m_nRate = pPreset->m_nRate; + pChorusData->m_nDepth = pPreset->m_nDepth; + + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + *pInstData = pChorusData; + + return EAS_SUCCESS; +} /* end ChorusInit */ + +/*---------------------------------------------------------------------------- + * WeightedTap() + *---------------------------------------------------------------------------- + * Purpose: Does fractional array look-up using linear interpolation + * + * first convert indexDesired to actual desired index by taking into account indexReference + * then do linear interpolation between two actual samples using fractional part + * + * Inputs: + * array: pointer to array of signed 16 bit values, typically either PCM data or control data + * indexReference: the circular buffer relative offset + * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) + * indexLimit: the total size of the array, used to compute buffer wrap + * + * Outputs: + * Value from the input array, linearly interpolated between two actual data values + * + *---------------------------------------------------------------------------- +*/ +static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit) +{ + EAS_I16 index; + EAS_I16 fraction; + EAS_I16 val1; + EAS_I16 val2; + + //separate indexDesired into whole and fractional parts + /*lint -e{704} use shift for performance */ + index = (EAS_I16)(indexDesired >> 16); + /*lint -e{704} use shift for performance */ + fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part + + //adjust whole part by indexReference + index = indexReference - index; + //make sure we stay within array bounds, this implements circular buffer + while (index < 0) + { + index += indexLimit; + } + + //get two adjacent values from the array + val1 = array[index]; + + //handle special case when index == 0, else typical case + if (index == 0) + { + val2 = array[indexLimit-1]; //get last value from array + } + else + { + val2 = array[index-1]; //get previous value from array + } + + //compute linear interpolation as (val1 + ((val2-val1)*fraction)) + return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction)); +} + +/*---------------------------------------------------------------------------- + * ChorusProcess() + *---------------------------------------------------------------------------- + * Purpose: compute the chorus on the input buffer, and mix into output buffer + * + * + * Inputs: + * src: pointer to input buffer of PCM values to be processed + * dst: pointer to output buffer of PCM values we are to sume the result with + * bufSize: the number of sample frames (i.e. stereo samples) in the buffer + * + * Outputs: + * None + * + *---------------------------------------------------------------------------- +*/ +//compute the chorus, and mix into output buffer +static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) +{ + EAS_I32 ix; + EAS_I32 nChannelNumber; + EAS_I16 lfoValueLeft; + EAS_I16 lfoValueRight; + EAS_I32 positionOffsetL; + EAS_I32 positionOffsetR; + EAS_PCM tapL; + EAS_PCM tapR; + EAS_I32 tempValue; + EAS_PCM nInputSample; + EAS_I32 nOutputSample; + EAS_PCM *pIn; + EAS_PCM *pOut; + + S_CHORUS_OBJECT *pChorusData; + + pChorusData = (S_CHORUS_OBJECT*) pInstData; + + //if the chorus is disabled or turned all the way down + if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0) + { + if (pSrc != pDst) + EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); + return; + } + + if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus) + { + ChorusUpdate(pChorusData); + } + + for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++) + { + + pIn = pSrc + nChannelNumber; + pOut = pDst + nChannelNumber; + + if(nChannelNumber==0) + { + for (ix = 0; ix < numSamples; ix++) + { + nInputSample = *pIn; + pIn += NUM_OUTPUT_CHANNELS; + + //feed input into chorus delay line + pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample; + + //compute chorus lfo value using phase as fractional index into chorus shape table + //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number + lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE); + + //scale chorus depth by lfo value to get relative fractional sample index + //index is expressed as 32 bit number with 16 bit fractional part + /*lint -e{703} use shift for performance */ + positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1); + + //add fixed chorus delay to get actual fractional sample index + positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16; + + //get tap value from chorus delay using fractional sample index + tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE); + + //scale by chorus level, then sum with input buffer contents and saturate + tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel); + nOutputSample = SATURATE(tempValue + nInputSample); + + *pOut = (EAS_I16)SATURATE(nOutputSample); + pOut += NUM_OUTPUT_CHANNELS; + + + //increment chorus delay index and make it wrap as needed + //this implements circular buffer + if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE) + pChorusData->chorusIndexL = 0; + + //increment fractional lfo phase, and make it wrap as needed + pChorusData->lfoLPhase += pChorusData->m_nRate; + while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16)) + { + pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16); + } + } + } + else + { + for (ix = 0; ix < numSamples; ix++) + { + nInputSample = *pIn; + pIn += NUM_OUTPUT_CHANNELS; + + //feed input into chorus delay line + pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample; + + //compute chorus lfo value using phase as fractional index into chorus shape table + //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number + lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE); + + //scale chorus depth by lfo value to get relative fractional sample index + //index is expressed as 32 bit number with 16 bit fractional part + /*lint -e{703} use shift for performance */ + positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1); + + //add fixed chorus delay to get actual fractional sample index + positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16; + + //get tap value from chorus delay using fractional sample index + tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE); + + //scale by chorus level, then sum with output buffer contents and saturate + tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel); + nOutputSample = SATURATE(tempValue + nInputSample); + + *pOut = (EAS_I16)SATURATE(nOutputSample); + pOut += NUM_OUTPUT_CHANNELS; + + //increment chorus delay index and make it wrap as needed + //this implements circular buffer + if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE) + pChorusData->chorusIndexR = 0; + + //increment fractional lfo phase, and make it wrap as needed + pChorusData->lfoRPhase += pChorusData->m_nRate; + while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16)) + { + pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16); + } + } + } + + } +} /* end ChorusProcess */ + + + +/*---------------------------------------------------------------------------- + * ChorusShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the Chorus effect. + * + * Inputs: + * pInstData - handle to instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) +{ + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pInstData); + return EAS_SUCCESS; +} /* end ChorusShutdown */ + +/*---------------------------------------------------------------------------- + * ChorusGetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Get a Chorus parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - pointer to variable to hold retrieved value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_CHORUS_OBJECT *p; + + p = (S_CHORUS_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_CHORUS_BYPASS: + *pValue = (EAS_I32) p->bypass; + break; + case EAS_PARAM_CHORUS_PRESET: + *pValue = (EAS_I8) p->m_nCurrentChorus; + break; + case EAS_PARAM_CHORUS_RATE: + *pValue = (EAS_I32) p->m_nRate; + break; + case EAS_PARAM_CHORUS_DEPTH: + *pValue = (EAS_I32) p->m_nDepth; + break; + case EAS_PARAM_CHORUS_LEVEL: + *pValue = (EAS_I32) p->m_nLevel; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ChorusGetParam */ + + +/*---------------------------------------------------------------------------- + * ChorusSetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Set a Chorus parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - new paramter value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_CHORUS_OBJECT *p; + + p = (S_CHORUS_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_CHORUS_BYPASS: + p->bypass = (EAS_BOOL) value; + break; + case EAS_PARAM_CHORUS_PRESET: + if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 && + value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nNextChorus = (EAS_I8)value; + break; + case EAS_PARAM_CHORUS_RATE: + if(valueEAS_CHORUS_RATE_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nRate = (EAS_I16) value; + break; + case EAS_PARAM_CHORUS_DEPTH: + if(valueEAS_CHORUS_DEPTH_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nDepth = (EAS_I16) value; + break; + case EAS_PARAM_CHORUS_LEVEL: + if(valueEAS_CHORUS_LEVEL_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nLevel = (EAS_I16) value; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ChorusSetParam */ + + +/*---------------------------------------------------------------------------- + * ChorusReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global Chorus preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData) +{ + + int preset = 0; + int defaultPreset = 0; + + //now init any remaining presets to defaults + for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++) + { + S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset]; + if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1) + { + pPreset->m_nDepth = 39; + pPreset->m_nRate = 30; + pPreset->m_nLevel = 32767; + } + else if (defaultPreset == 1) + { + pPreset->m_nDepth = 21; + pPreset->m_nRate = 45; + pPreset->m_nLevel = 25000; + } + else if (defaultPreset == 2) + { + pPreset->m_nDepth = 53; + pPreset->m_nRate = 25; + pPreset->m_nLevel = 32000; + } + else if (defaultPreset == 3) + { + pPreset->m_nDepth = 32; + pPreset->m_nRate = 37; + pPreset->m_nLevel = 29000; + } + } + + return EAS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + * ChorusUpdate + *---------------------------------------------------------------------------- + * Purpose: + * Update the Chorus preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - chorus paramters will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData) +{ + S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; + + pChorusData->m_nLevel = pPreset->m_nLevel; + pChorusData->m_nRate = pPreset->m_nRate; + pChorusData->m_nDepth = pPreset->m_nDepth; + + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus; + + return EAS_SUCCESS; + +} /* end ChorusUpdate */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorusdata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorusdata.c new file mode 100755 index 0000000..ec71ff8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorusdata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorusdata.c + * + * Contents and purpose: + * Contains the static data allocation for the Chorus effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_chorusdata.h" + +S_CHORUS_OBJECT eas_ChorusData; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorusdata.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorusdata.h new file mode 100755 index 0000000..ec8daa4 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_chorusdata.h @@ -0,0 +1,160 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorusdata.h + * + * Contents and purpose: + * Contains the prototypes for the Chorus effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 309 $ + * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_CHORUS_H +#define _EAS_CHORUS_H + +#include "eas_types.h" +#include "eas_audioconst.h" + +//defines for chorus + +#define EAS_CHORUS_BYPASS_DEFAULT 1 +#define EAS_CHORUS_PRESET_DEFAULT 0 +#define EAS_CHORUS_RATE_DEFAULT 30 +#define EAS_CHORUS_DEPTH_DEFAULT 39 +#define EAS_CHORUS_LEVEL_DEFAULT 32767 + +#define EAS_CHORUS_LEVEL_MIN 0 +#define EAS_CHORUS_LEVEL_MAX 32767 + +#define EAS_CHORUS_RATE_MIN 10 +#define EAS_CHORUS_RATE_MAX 50 + +#define EAS_CHORUS_DEPTH_MIN 15 +#define EAS_CHORUS_DEPTH_MAX 60 + +#define CHORUS_SIZE_MS 20 +#define CHORUS_L_SIZE ((CHORUS_SIZE_MS*_OUTPUT_SAMPLE_RATE)/1000) +#define CHORUS_R_SIZE CHORUS_L_SIZE +#define CHORUS_SHAPE_SIZE 128 +#define CHORUS_DELAY_MS 10 + +#define CHORUS_MAX_TYPE 4 // any Chorus numbers larger than this are invalid + +typedef struct +{ + EAS_I16 m_nRate; + EAS_I16 m_nDepth; + EAS_I16 m_nLevel; + +} S_CHORUS_PRESET; + +typedef struct +{ + S_CHORUS_PRESET m_sPreset[CHORUS_MAX_TYPE]; //array of presets + +} S_CHORUS_PRESET_BANK; + +/* parameters for each Chorus */ +typedef struct +{ + EAS_I32 lfoLPhase; + EAS_I32 lfoRPhase; + EAS_I16 chorusIndexL; + EAS_I16 chorusIndexR; + EAS_U16 chorusTapPosition; + + EAS_I16 m_nRate; + EAS_I16 m_nDepth; + EAS_I16 m_nLevel; + + //delay lines used by the chorus, longer would sound better + EAS_PCM chorusDelayL[CHORUS_L_SIZE]; + EAS_PCM chorusDelayR[CHORUS_R_SIZE]; + + EAS_BOOL bypass; + EAS_I8 preset; + + EAS_I16 m_nCurrentChorus; // preset number for current Chorus + EAS_I16 m_nNextChorus; // preset number for next Chorus + + S_CHORUS_PRESET pPreset; + + S_CHORUS_PRESET_BANK m_sPreset; + +} S_CHORUS_OBJECT; + + +/*---------------------------------------------------------------------------- + * WeightedTap() + *---------------------------------------------------------------------------- + * Purpose: Does fractional array look-up using linear interpolation + * + * first convert indexDesired to actual desired index by taking into account indexReference + * then do linear interpolation between two actual samples using fractional part + * + * Inputs: + * array: pointer to array of signed 16 bit values, typically either PCM data or control data + * indexReference: the circular buffer relative offset + * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) + * indexLimit: the total size of the array, used to compute buffer wrap + * + * Outputs: + * Value from the input array, linearly interpolated between two actual data values + * + *---------------------------------------------------------------------------- +*/ +static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit); + +/*---------------------------------------------------------------------------- + * ChorusReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global Chorus preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData); + +/*---------------------------------------------------------------------------- + * ChorusUpdate + *---------------------------------------------------------------------------- + * Purpose: + * Update the Chorus preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - chorus paramters will be changed + * - m_nCurrentChorus := m_nNextChorus + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT* pChorusData); + +#endif /* #ifndef _EAS_CHORUSDATA_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ctype.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ctype.h new file mode 100755 index 0000000..14fa96f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ctype.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ctype.h + * + * Contents and purpose: + * This is a replacement for the CRT ctype.h functions. These + * functions are currently ASCII only, but eventually, we will want + * to support wide-characters for localization. + * + * Copyright (c) 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 429 $ + * $Date: 2006-10-19 23:50:15 -0700 (Thu, 19 Oct 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_CTYPE_H +#define _EAS_CTYPE_H + +EAS_INLINE EAS_I8 IsDigit (EAS_I8 c) { return ((c >= '0') && (c <= '9')); } +EAS_INLINE EAS_I8 IsSpace (EAS_I8 c) { return (((c >= 9) && (c <= 13)) || (c == ' ')); } +EAS_INLINE EAS_I8 ToUpper (EAS_I8 c) { if ((c >= 'a') && (c <= 'z')) return c & ~0x20; else return c; } +EAS_INLINE EAS_I8 ToLower (EAS_I8 c) { if ((c >= 'A') && (c <= 'Z')) return c |= 0x20; else return c; } + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_data.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_data.c new file mode 100755 index 0000000..31a4e6a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_data.c @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_data.c + * + * Contents and purpose: + * Contains a data allocation for synthesizer + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" + +// globals +S_EAS_DATA eas_Data; +S_VOICE_MGR eas_Synth; +S_SYNTH eas_MIDI; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_data.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_data.h new file mode 100755 index 0000000..e2fcb1a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_data.h @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_data.h + * + * Contents and purpose: + * This header defines all types, to support dynamic allocation of the + * memory resources needed for persistent EAS data. + * + * Copyright 2004 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 842 $ + * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_DATA_H +#define _EAS_DATA_H + +#include "eas_types.h" +#include "eas_synthcfg.h" +#include "eas.h" +#include "eas_audioconst.h" +#include "eas_sndlib.h" +#include "eas_pcm.h" +#include "eas_pcmdata.h" +#include "eas_synth.h" +#include "eas_miditypes.h" +#include "eas_effects.h" + +#ifdef AUX_MIXER +#include "eas_auxmixdata.h" +#endif + +#ifdef JET_INTERFACE +#include "jet.h" +#endif + +#ifdef _METRICS_ENABLED +#include "eas_perf.h" +#endif + +#ifndef MAX_NUMBER_STREAMS +#define MAX_NUMBER_STREAMS 4 +#endif + +/* flags for S_EAS_STREAM */ +#define STREAM_FLAGS_PARSED 1 +#define STREAM_FLAGS_PAUSE 2 +#define STREAM_FLAGS_LOCATE 4 +#define STREAM_FLAGS_RESUME 8 + +/* structure for parsing a stream */ +typedef struct s_eas_stream_tag +{ + void *pParserModule; + EAS_U32 time; + EAS_U32 frameLength; + EAS_I32 repeatCount; + EAS_VOID_PTR handle; + EAS_U8 volume; + EAS_BOOL8 streamFlags; +} S_EAS_STREAM; + +/* default master volume is -10dB */ +#define DEFAULT_VOLUME 90 +#define DEFAULT_STREAM_VOLUME 100 +#define DEFAULT_STREAM_GAIN 14622 + +/* 10 dB of boost available for individual parsers */ +#define STREAM_VOLUME_HEADROOM 10 + +/* amalgamated persistent data type */ +typedef struct s_eas_data_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; +#endif + EAS_HW_DATA_HANDLE hwInstData; + + S_EFFECTS_MODULE effectsModules[NUM_EFFECTS_MODULES]; + +#ifdef _METRICS_ENABLED + S_METRICS_INTERFACE *pMetricsModule; + EAS_VOID_PTR pMetricsData; +#endif + + EAS_I32 *pMixBuffer; + EAS_PCM *pOutputAudioBuffer; + +#ifdef AUX_MIXER + S_EAS_AUX_MIXER auxMixer; +#endif + +#ifdef _MAXIMIZER_ENABLED + EAS_VOID_PTR pMaximizerData; +#endif + + S_EAS_STREAM streams[MAX_NUMBER_STREAMS]; + + S_PCM_STATE *pPCMStreams; + + S_VOICE_MGR *pVoiceMgr; + +#ifdef JET_INTERFACE + JET_DATA_HANDLE jetHandle; +#endif + + EAS_U32 renderTime; + EAS_I16 masterGain; + EAS_U8 masterVolume; + EAS_BOOL8 staticMemoryModel; + EAS_BOOL8 searchHeaderFlag; +} S_EAS_DATA; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_effects.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_effects.h new file mode 100755 index 0000000..86dedac --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_effects.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_effects.h + * + * Contents and purpose: + * Defines a generic effects interface. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_EFFECTS_H +#define _EAS_EFFECTS_H + +#include "eas_types.h" + +typedef struct +{ + EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); + void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_PCM *in, EAS_PCM *out, EAS_I32 numSamples); + EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +} S_EFFECTS_INTERFACE; + +typedef struct +{ + EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); + void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_I32 *in, EAS_I32 *out, EAS_I32 numSamples); + EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +} S_EFFECTS32_INTERFACE; + +/* mixer instance data */ +typedef struct +{ + S_EFFECTS_INTERFACE *effect; + EAS_VOID_PTR effectData; +} S_EFFECTS_MODULE; + +#endif /* end _EAS_EFFECTS_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmengine.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmengine.c new file mode 100755 index 0000000..ea7f69c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmengine.c @@ -0,0 +1,785 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_fmengine.c + * + * Contents and purpose: + * Implements the low-level FM synthesizer functions. + * + * Copyright Sonic Network Inc. 2004, 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* includes */ +#include "eas_types.h" +#include "eas_math.h" +#include "eas_audioconst.h" +#include "eas_fmengine.h" + +#if defined(EAS_FM_SYNTH) || defined(EAS_HYBRID_SYNTH) || defined(EAS_SPLIT_HYBRID_SYNTH) || defined(EAS_SPLIT_FM_SYNTH) +#include "eas_data.h" +#endif + +/* externals */ +extern const EAS_I16 sineTable[]; +extern const EAS_U8 fmScaleTable[16]; + +// saturation constants for 32-bit to 16-bit conversion +#define _EAS_MAX_OUTPUT 32767 +#define _EAS_MIN_OUTPUT -32767 + +static S_FM_ENG_VOICE voices[NUM_FM_VOICES]; + +/* local prototypes */ +void FM_SynthMixVoice (S_FM_ENG_VOICE *p, EAS_U16 gainTarget, EAS_I32 numSamplesToAdd, EAS_PCM *pInputBuffer, EAS_I32 *pBuffer); + +/* used in development environment */ +#if defined(_SATURATION_MONITOR) +static EAS_BOOL bSaturated = EAS_FALSE; + +/*---------------------------------------------------------------------------- + * FM_CheckSaturation() + *---------------------------------------------------------------------------- + * Purpose: + * Allows the sound development tool to check for saturation at the voice + * level. Useful for tuning the level controls. + * + * Inputs: + * + * Outputs: + * Returns true if saturation has occurred since the last time the function + * was called. + * + * Side Effects: + * Resets the saturation flag + *---------------------------------------------------------------------------- +*/ +EAS_BOOL FM_CheckSaturation () +{ + EAS_BOOL bTemp; + bTemp = bSaturated; + bSaturated = EAS_FALSE; + return bTemp; +} +#endif + +/*---------------------------------------------------------------------------- + * FM_Saturate() + *---------------------------------------------------------------------------- + * Purpose: + * This inline function saturates a 32-bit number to 16-bits + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Returns a 16-bit integer + *---------------------------------------------------------------------------- +*/ +EAS_INLINE EAS_I16 FM_Saturate (EAS_I32 nValue) +{ + if (nValue > _EAS_MAX_OUTPUT) + { +#if defined(_SATURATION_MONITOR) + bSaturated = EAS_TRUE; +#endif + return _EAS_MAX_OUTPUT; + } + if (nValue < _EAS_MIN_OUTPUT) + { +#if defined(_SATURATION_MONITOR) + bSaturated = EAS_TRUE; +#endif + return _EAS_MIN_OUTPUT; + } + return (EAS_I16) nValue; +} + +/*---------------------------------------------------------------------------- + * FM_Noise() + *---------------------------------------------------------------------------- + * Purpose: + * A 31-bit low-cost linear congruential PRNG algorithm used to + * generate noise. + * + * Inputs: + * pnSeed - pointer to 32-bit PRNG seed + * + * Outputs: + * Returns a 16-bit integer + *---------------------------------------------------------------------------- +*/ +EAS_INLINE EAS_I16 FM_Noise (EAS_U32 *pnSeed) +{ + *pnSeed = *pnSeed * 214013L + 2531011L; + return (EAS_I16) ((*pnSeed >> 15) & 0xffff); +} + +/*---------------------------------------------------------------------------- + * FM_PhaseInc() + *---------------------------------------------------------------------------- + * Purpose: + * Transform pitch cents to linear phase increment + * + * Inputs: + * nCents - measured in cents + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_I32 FM_PhaseInc (EAS_I32 nCents) +{ + EAS_I32 nDents; + EAS_I32 nExponentInt, nExponentFrac; + EAS_I32 nTemp1, nTemp2; + EAS_I32 nResult; + + /* convert cents to dents */ + nDents = FMUL_15x15(nCents, CENTS_TO_DENTS); + nExponentInt = GET_DENTS_INT_PART(nDents) + (32 - SINE_TABLE_SIZE_IN_BITS - NUM_EG1_FRAC_BITS); + nExponentFrac = GET_DENTS_FRAC_PART(nDents); + + /* implement 2^(fracPart) as a power series */ + nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3); + nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1); + nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2); + + /* + implement 2^(intPart) as + a left shift for intPart >= 0 or + a left shift for intPart < 0 + */ + if (nExponentInt >= 0) + { + /* left shift for positive exponents */ + /*lint -e{703} */ + nResult = nTemp1 << nExponentInt; + } + else + { + /* right shift for negative exponents */ + nExponentInt = -nExponentInt; + nResult = nTemp1 >> nExponentInt; + } + + return nResult; +} + +#if (NUM_OUTPUT_CHANNELS == 2) +/*---------------------------------------------------------------------------- + * FM_CalculatePan() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the left and right gain values corresponding to the given pan value. + * + * Inputs: + * psVoice - ptr to the voice we have assigned for this channel + * psArticulation - ptr to this voice's articulation + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * the given voice's m_nGainLeft and m_nGainRight are assigned + *---------------------------------------------------------------------------- +*/ +static void FM_CalculatePan (EAS_I16 pan, EAS_U16 *pGainLeft, EAS_U16 *pGainRight) +{ + EAS_I32 nTemp; + EAS_INT nNetAngle; + + /* + Implement the following + sin(x) = (2-4*c)*x^2 + c + x + cos(x) = (2-4*c)*x^2 + c - x + + where c = 1/sqrt(2) + using the a0 + x*(a1 + x*a2) approach + */ + + /* + Get the Midi CC10 pan value for this voice's channel + convert the pan value to an "angle" representation suitable for + our sin, cos calculator. This representation is NOT necessarily the same + as the transform in the GM manuals because of our sin, cos calculator. + "angle" = (CC10 - 64)/128 + */ + /*lint -e{703} */ + nNetAngle = ((EAS_I32) pan) << (NUM_EG1_FRAC_BITS -7); + + /* calculate sin */ + nTemp = EG1_ONE + FMUL_15x15(COEFF_PAN_G2, nNetAngle); + nTemp = COEFF_PAN_G0 + FMUL_15x15(nTemp, nNetAngle); + + if (nTemp > SYNTH_FULL_SCALE_EG1_GAIN) + nTemp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (nTemp < 0) + nTemp = 0; + + *pGainRight = (EAS_U16) nTemp; + + /* calculate cos */ + nTemp = -EG1_ONE + FMUL_15x15(COEFF_PAN_G2, nNetAngle); + nTemp = COEFF_PAN_G0 + FMUL_15x15(nTemp, nNetAngle); + + if (nTemp > SYNTH_FULL_SCALE_EG1_GAIN) + nTemp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (nTemp < 0) + nTemp = 0; + + *pGainLeft = (EAS_U16) nTemp; +} +#endif /* #if (NUM_OUTPUT_CHANNELS == 2) */ + +/*---------------------------------------------------------------------------- + * FM_Operator() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesizes a buffer of samples based on passed parameters. + * + * Inputs: + * nNumSamplesToAdd - number of samples to synthesize + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void FM_Operator ( + S_FM_ENG_OPER *p, + EAS_I32 numSamplesToAdd, + EAS_PCM *pBuffer, + EAS_PCM *pModBuffer, + EAS_BOOL mix, + EAS_U16 gainTarget, + EAS_I16 pitch, + EAS_U8 feedback, + EAS_I16 *pLastOutput) +{ + EAS_I32 gain; + EAS_I32 gainInc; + EAS_U32 phase; + EAS_U32 phaseInc; + EAS_U32 phaseTemp; + EAS_I32 temp; + EAS_I32 temp2; + + /* establish local gain variable */ + gain = (EAS_I32) p->gain << 16; + + /* calculate gain increment */ + /*lint -e{703} use shift for performance */ + gainInc = ((EAS_I32) gainTarget - (EAS_I32) p->gain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + + /* establish local phase variables */ + phase = p->phase; + + /* calculate the new phase increment */ + phaseInc = (EAS_U32) FM_PhaseInc(pitch); + + /* restore final output from previous frame for feedback loop */ + if (pLastOutput) + temp = *pLastOutput; + else + temp = 0; + + /* generate a buffer of samples */ + while (numSamplesToAdd--) + { + + /* incorporate modulation */ + if (pModBuffer) + { + /*lint -e{701} use shift for performance */ + temp = *pModBuffer++ << FM_MODULATOR_INPUT_SHIFT; + } + + /* incorporate feedback */ + else + { + /*lint -e{703} use shift for performance */ + temp = (temp * (EAS_I32) feedback) << FM_FEEDBACK_SHIFT; + } + + /*lint -e{737} */ + phaseTemp = phase + temp; + + /* fetch sample from wavetable */ + temp = sineTable[phaseTemp >> (32 - SINE_TABLE_SIZE_IN_BITS)]; + + /* increment operator phase */ + phase += phaseInc; + + /* internal gain for modulation effects */ + temp = FMUL_15x15(temp, (gain >> 16)); + + /* output gain calculation */ + temp2 = FMUL_15x15(temp, p->outputGain); + + /* saturating add to buffer */ + if (mix) + { + temp2 += *pBuffer; + *pBuffer++ = FM_Saturate(temp2); + } + + /* output to buffer */ + else + *pBuffer++ = (EAS_I16) temp2; + + /* increment gain */ + gain += gainInc; + + } + + /* save phase and gain */ + p->phase = phase; + p->gain = gainTarget; + + /* save last output for feedback in next frame */ + if (pLastOutput) + *pLastOutput = (EAS_I16) temp; +} + +/*---------------------------------------------------------------------------- + * FM_NoiseOperator() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesizes a buffer of samples based on passed parameters. + * + * Inputs: + * nNumSamplesToAdd - number of samples to synthesize + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void FM_NoiseOperator ( + S_FM_ENG_OPER *p, + EAS_I32 numSamplesToAdd, + EAS_PCM *pBuffer, + EAS_BOOL mix, + EAS_U16 gainTarget, + EAS_U8 feedback, + EAS_I16 *pLastOutput) +{ + EAS_I32 gain; + EAS_I32 gainInc; + EAS_U32 phase; + EAS_I32 temp; + EAS_I32 temp2; + + /* establish local gain variable */ + gain = (EAS_I32) p->gain << 16; + + /* calculate gain increment */ + /*lint -e{703} use shift for performance */ + gainInc = ((EAS_I32) gainTarget - (EAS_I32) p->gain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + + /* establish local phase variables */ + phase = p->phase; + + /* establish local phase variables */ + phase = p->phase; + + /* recall last sample for filter Z-1 term */ + temp = 0; + if (pLastOutput) + temp = *pLastOutput; + + /* generate a buffer of samples */ + while (numSamplesToAdd--) + { + + /* if using filter */ + if (pLastOutput) + { + /* use PRNG for noise */ + temp2 = FM_Noise(&phase); + + /*lint -e{704} use shift for performance */ + temp += ((temp2 -temp) * feedback) >> 8; + } + else + { + temp = FM_Noise(&phase); + } + + /* internal gain for modulation effects */ + temp2 = FMUL_15x15(temp, (gain >> 16)); + + /* output gain calculation */ + temp2 = FMUL_15x15(temp2, p->outputGain); + + /* saturating add to buffer */ + if (mix) + { + temp2 += *pBuffer; + *pBuffer++ = FM_Saturate(temp2); + } + + /* output to buffer */ + else + *pBuffer++ = (EAS_I16) temp2; + + /* increment gain */ + gain += gainInc; + + } + + /* save phase and gain */ + p->phase = phase; + p->gain = gainTarget; + + /* save last output for feedback in next frame */ + if (pLastOutput) + *pLastOutput = (EAS_I16) temp; +} + +/*---------------------------------------------------------------------------- + * FM_ConfigVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Receives parameters to start a new voice. + * + * Inputs: + * voiceNum - voice number to start + * vCfg - configuration data + * pMixBuffer - pointer to host supplied buffer + * + * Outputs: + * + * Side Effects: + * + * Notes: + * pFrameBuffer is not used in the test version, but is passed as a + * courtesy to split architecture implementations. It can be used as + * as pointer to the interprocessor communications buffer when the + * synthesis parameters are passed off to a DSP for synthesis. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pFrameBuffer) pFrameBuffer not used in test version - see above */ +void FM_ConfigVoice (EAS_I32 voiceNum, S_FM_VOICE_CONFIG *vCfg, EAS_FRAME_BUFFER_HANDLE pFrameBuffer) +{ + S_FM_ENG_VOICE *pVoice; + EAS_INT i; + + /* establish pointer to voice data */ + pVoice = &voices[voiceNum]; + + /* save data */ + pVoice->feedback = vCfg->feedback; + pVoice->flags = vCfg->flags; + pVoice->voiceGain = vCfg->voiceGain; + + /* initialize Z-1 terms */ + pVoice->op1Out = 0; + pVoice->op3Out = 0; + + /* initialize operators */ + for (i = 0; i < 4; i++) + { + /* save operator data */ + pVoice->oper[i].gain = vCfg->gain[i]; + pVoice->oper[i].outputGain = vCfg->outputGain[i]; + pVoice->oper[i].outputGain = vCfg->outputGain[i]; + + /* initalize operator */ + pVoice->oper[i].phase = 0; + } + + /* calculate pan */ +#if NUM_OUTPUT_CHANNELS == 2 + FM_CalculatePan(vCfg->pan, &pVoice->gainLeft, &pVoice->gainRight); +#endif +} + +/*---------------------------------------------------------------------------- + * FM_ProcessVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesizes a buffer of samples based on calculated parameters. + * + * Inputs: + * nNumSamplesToAdd - number of samples to synthesize + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + * Notes: + * pOut is not used in the test version, but is passed as a + * courtesy to split architecture implementations. It can be used as + * as pointer to the interprocessor communications buffer when the + * synthesis parameters are passed off to a DSP for synthesis. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pOut) pOut not used in test version - see above */ +void FM_ProcessVoice ( + EAS_I32 voiceNum, + S_FM_VOICE_FRAME *pFrame, + EAS_I32 numSamplesToAdd, + EAS_PCM *pTempBuffer, + EAS_PCM *pBuffer, + EAS_I32 *pMixBuffer, + EAS_FRAME_BUFFER_HANDLE pFrameBuffer) +{ + S_FM_ENG_VOICE *p; + EAS_PCM *pOutBuf; + EAS_PCM *pMod; + EAS_BOOL mix; + EAS_U8 feedback1; + EAS_U8 feedback3; + EAS_U8 mode; + + /* establish pointer to voice data */ + p = &voices[voiceNum]; + mode = p->flags & 0x07; + + /* lookup feedback values */ + feedback1 = fmScaleTable[p->feedback >> 4]; + feedback3 = fmScaleTable[p->feedback & 0x0f]; + + /* operator 3 is on output bus in modes 0, 1, and 3 */ + if ((mode == 0) || (mode == 1) || (mode == 3)) + pOutBuf = pBuffer; + else + pOutBuf = pTempBuffer; + + if (p->flags & FLAG_FM_ENG_VOICE_OP3_NOISE) + { + FM_NoiseOperator( + p->oper + 2, + numSamplesToAdd, + pOutBuf, + EAS_FALSE, + pFrame->gain[2], + feedback3, + &p->op3Out); + } + else + { + FM_Operator( + p->oper + 2, + numSamplesToAdd, + pOutBuf, + 0, + EAS_FALSE, + pFrame->gain[2], + pFrame->pitch[2], + feedback3, + &p->op3Out); + } + + /* operator 4 is on output bus in modes 0, 1, and 2 */ + if (mode < 3) + pOutBuf = pBuffer; + else + pOutBuf = pTempBuffer; + + /* operator 4 is modulated in modes 2, 4, and 5 */ + if ((mode == 2) || (mode == 4) || (mode == 5)) + pMod = pTempBuffer; + else + pMod = 0; + + /* operator 4 is in mix mode in modes 0 and 1 */ + mix = (mode < 2); + + if (p->flags & FLAG_FM_ENG_VOICE_OP4_NOISE) + { + FM_NoiseOperator( + p->oper + 3, + numSamplesToAdd, + pOutBuf, + mix, + pFrame->gain[3], + 0, + 0); + } + else + { + FM_Operator( + p->oper + 3, + numSamplesToAdd, + pOutBuf, + pMod, + mix, + pFrame->gain[3], + pFrame->pitch[3], + 0, + 0); + } + + /* operator 1 is on output bus in mode 0 */ + if (mode == 0) + pOutBuf = pBuffer; + else + pOutBuf = pTempBuffer; + + /* operator 1 is modulated in modes 3 and 4 */ + if ((mode == 3) || (mode == 4)) + pMod = pTempBuffer; + else + pMod = 0; + + /* operator 1 is in mix mode in modes 0 and 5 */ + mix = ((mode == 0) || (mode == 5)); + + if (p->flags & FLAG_FM_ENG_VOICE_OP1_NOISE) + { + FM_NoiseOperator( + p->oper, + numSamplesToAdd, + pOutBuf, + mix, + pFrame->gain[0], + feedback1, + &p->op1Out); + } + else + { + FM_Operator( + p->oper, + numSamplesToAdd, + pOutBuf, + pMod, + mix, + pFrame->gain[0], + pFrame->pitch[0], + feedback1, + &p->op1Out); + } + + /* operator 2 is modulated in all modes except 0 */ + if (mode != 0) + pMod = pTempBuffer; + else + pMod = 0; + + /* operator 1 is in mix mode in modes 0 -3 */ + mix = (mode < 4); + + if (p->flags & FLAG_FM_ENG_VOICE_OP2_NOISE) + { + FM_NoiseOperator( + p->oper + 1, + numSamplesToAdd, + pBuffer, + mix, + pFrame->gain[1], + 0, + 0); + } + else + { + FM_Operator( + p->oper + 1, + numSamplesToAdd, + pBuffer, + pMod, + mix, + pFrame->gain[1], + pFrame->pitch[1], + 0, + 0); + } + + /* mix voice output to synthesizer output buffer */ + FM_SynthMixVoice(p, pFrame->voiceGain, numSamplesToAdd, pBuffer, pMixBuffer); +} + +/*---------------------------------------------------------------------------- + * FM_SynthMixVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Mixes the voice output buffer into the final mix using an anti-zipper + * filter. + * + * Inputs: + * nNumSamplesToAdd - number of samples to synthesize + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void FM_SynthMixVoice(S_FM_ENG_VOICE *p, EAS_U16 nGainTarget, EAS_I32 numSamplesToAdd, EAS_PCM *pInputBuffer, EAS_I32 *pBuffer) +{ + EAS_I32 nGain; + EAS_I32 nGainInc; + EAS_I32 nTemp; + + /* restore previous gain */ + /*lint -e{703} */ + nGain = (EAS_I32) p->voiceGain << 16; + + /* calculate gain increment */ + /*lint -e{703} */ + nGainInc = ((EAS_I32) nGainTarget - (EAS_I32) p->voiceGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + + /* mix the output buffer */ + while (numSamplesToAdd--) + { + /* output gain calculation */ + nTemp = *pInputBuffer++; + + /* sum to output buffer */ +#if (NUM_OUTPUT_CHANNELS == 2) + + /*lint -e{704} */ + nTemp = ((EAS_I32) nTemp * (nGain >> 16)) >> FM_GAIN_SHIFT; + + /*lint -e{704} */ + { + EAS_I32 nTemp2; + nTemp = nTemp >> FM_STEREO_PRE_GAIN_SHIFT; + nTemp2 = (nTemp * p->gainLeft) >> FM_STEREO_POST_GAIN_SHIFT; + *pBuffer++ += nTemp2; + nTemp2 = (nTemp * p->gainRight) >> FM_STEREO_POST_GAIN_SHIFT; + *pBuffer++ += nTemp2; + } +#else + /*lint -e{704} */ + nTemp = ((EAS_I32) nTemp * (nGain >> 16)) >> FM_MONO_GAIN_SHIFT; + *pBuffer++ += nTemp; +#endif + + /* increment gain for anti-zipper filter */ + nGain += nGainInc; + } + + /* save gain */ + p->voiceGain = nGainTarget; +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmengine.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmengine.h new file mode 100755 index 0000000..dd248f8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmengine.h @@ -0,0 +1,121 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_fmengine.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for FM synthesize low-level. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 664 $ + * $Date: 2007-04-25 13:11:22 -0700 (Wed, 25 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* sentinel */ +#ifndef _FMENGINE_H +#define _FMENGINE_H + +/* check for split architecture */ +#if defined (EAS_SPLIT_HYBRID_SYNTH) || defined(EAS_SPLIT_FM_SYNTH) +#define FM_OFFBOARD +#endif + +/* output level to mix buffer (3 = -24dB) */ +#define FM_GAIN_SHIFT 3 +#define FM_MONO_GAIN_SHIFT 9 + +/* voice output level for stereo 15 = +6dB */ +#define FM_STEREO_PRE_GAIN_SHIFT 11 +#define FM_STEREO_POST_GAIN_SHIFT 10 + +/* modulator input level shift (21 = -30dB) */ +#define FM_MODULATOR_INPUT_SHIFT 21 + +/* feedback control level shift (7 = 0dB) */ +#define FM_FEEDBACK_SHIFT 7 + +/* synth final output level */ +#define SYNTH_POST_GAIN_SHIFT 14 + +/* LFO modulation to gain control */ +#define FM_LFO_GAIN_SHIFT 12 + +/* sine table is always a power of 2 - saves cycles in inner loop */ +#define SINE_TABLE_SIZE_IN_BITS 11 +#define SINE_TABLE_SIZE 2048 + +/* operator structure for FM engine */ +typedef struct +{ + EAS_U32 phase; /* current waveform phase */ + EAS_U16 gain; /* current internal gain */ + EAS_U16 outputGain; /* current output gain */ +} S_FM_ENG_OPER; + +typedef struct +{ + S_FM_ENG_OPER oper[4]; /* operator data */ + EAS_I16 op1Out; /* op1 output for feedback loop */ + EAS_I16 op3Out; /* op3 output for feedback loop */ + EAS_U16 voiceGain; /* LFO + channel parameters */ +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_U16 gainLeft; /* left gain multiplier */ + EAS_U16 gainRight; /* right gain multiplier */ +#endif + EAS_U8 flags; /* mode bits and noise waveform flags */ + EAS_U8 feedback; /* feedback for Op1 and Op3 */ +} S_FM_ENG_VOICE; + +typedef struct +{ + EAS_U16 gain[4]; /* initial operator gain value */ + EAS_U16 outputGain[4]; /* initial operator output gain value */ + EAS_U16 voiceGain; /* initial voice gain */ + EAS_U8 flags; /* mode bits and noise waveform flags */ + EAS_U8 feedback; /* feedback for Op1 and Op3 */ +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I8 pan; /* pan value +/-64 */ +#endif +} S_FM_VOICE_CONFIG; + +typedef struct +{ + EAS_U16 gain[4]; /* new operator gain value */ + EAS_I16 pitch[4]; /* new pitch value */ + EAS_U16 voiceGain; /* new voice gain */ +} S_FM_VOICE_FRAME; + +/* bit definitions for S_FM_ENG_VOICE.flags */ +#define FLAG_FM_ENG_VOICE_OP1_NOISE 0x10 /* operator 1 source is PRNG */ +#define FLAG_FM_ENG_VOICE_OP2_NOISE 0x20 /* operator 2 source is PRNG */ +#define FLAG_FM_ENG_VOICE_OP3_NOISE 0x40 /* operator 3 source is PRNG */ +#define FLAG_FM_ENG_VOICE_OP4_NOISE 0x80 /* operator 4 source is PRNG */ + +#ifdef FM_OFFBOARD +extern EAS_BOOL FM_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +extern EAS_BOOL FM_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffe, EAS_I32 *pMixBuffer, EAS_I16 masterGain); +#endif + +/* FM engine prototypes */ +extern void FM_ConfigVoice (EAS_I32 voiceNum, S_FM_VOICE_CONFIG *vCfg, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +extern void FM_ProcessVoice (EAS_I32 voiceNum, S_FM_VOICE_FRAME *pFrame, EAS_I32 numSamplesToAdd, EAS_PCM *pTempBuffer, EAS_PCM *pBuffer, EAS_I32 *pMixBuffer, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); + +#endif +/* #ifndef _FMENGINE_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmsynth.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmsynth.c new file mode 100755 index 0000000..629506a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmsynth.c @@ -0,0 +1,910 @@ +/*---------------------------------------------------------------------------- + * + * File: + * fmsynth.c + * + * Contents and purpose: + * Implements the high-level FM synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_host.h" +#include "eas_report.h" + +#include "eas_data.h" +#include "eas_synth_protos.h" +#include "eas_audioconst.h" +#include "eas_fmengine.h" +#include "eas_math.h" + +/* option sanity check */ +#ifdef _REVERB +#error "No reverb for FM synthesizer" +#endif +#ifdef _CHORUS +#error "No chorus for FM synthesizer" +#endif + +/* + * WARNING: These macros can cause unwanted side effects. Use them + * with care. For example, min(x++,y++) will cause either x or y to be + * incremented twice. + */ +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define max(a,b) ((a) > (b) ? (a) : (b)) + +/* pivot point for keyboard scalars */ +#define EG_SCALE_PIVOT_POINT 64 +#define KEY_SCALE_PIVOT_POINT 36 + +/* This number is the negative of the frequency of the note (in cents) of + * the sine wave played at unity. The number can be calculated as follows: + * + * MAGIC_NUMBER = 1200 * log(base2) (SINE_TABLE_SIZE * 8.175798916 / SAMPLE_RATE) + * + * 8.17578 is a reference to the frequency of MIDI note 0 + */ +#if defined (_SAMPLE_RATE_8000) +#define MAGIC_NUMBER 1279 +#elif defined (_SAMPLE_RATE_16000) +#define MAGIC_NUMBER 79 +#elif defined (_SAMPLE_RATE_20000) +#define MAGIC_NUMBER -308 +#elif defined (_SAMPLE_RATE_22050) +#define MAGIC_NUMBER -477 +#elif defined (_SAMPLE_RATE_24000) +#define MAGIC_NUMBER -623 +#elif defined (_SAMPLE_RATE_32000) +#define MAGIC_NUMBER -1121 +#elif defined (_SAMPLE_RATE_44100) +#define MAGIC_NUMBER -1677 +#elif defined (_SAMPLE_RATE_48000) +#define MAGIC_NUMBER -1823 +#endif + +/* externs */ +extern const EAS_I16 fmControlTable[128]; +extern const EAS_U16 fmRateTable[256]; +extern const EAS_U16 fmAttackTable[16]; +extern const EAS_U8 fmDecayTable[16]; +extern const EAS_U8 fmReleaseTable[16]; +extern const EAS_U8 fmScaleTable[16]; + +/* local prototypes */ +/*lint -esym(715, pVoiceMgr) standard synthesizer interface - pVoiceMgr not used */ +static EAS_RESULT FM_Initialize (S_VOICE_MGR *pVoiceMgr) { return EAS_SUCCESS; } +static EAS_RESULT FM_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); +static EAS_BOOL FM_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); +static void FM_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +static void FM_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +static void FM_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); +static void FM_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + + +/*---------------------------------------------------------------------------- + * Synthesizer interface + *---------------------------------------------------------------------------- +*/ +const S_SYNTH_INTERFACE fmSynth = +{ + FM_Initialize, + FM_StartVoice, + FM_UpdateVoice, + FM_ReleaseVoice, + FM_MuteVoice, + FM_SustainPedal, + FM_UpdateChannel +}; + +#ifdef FM_OFFBOARD +const S_FRAME_INTERFACE fmFrameInterface = +{ + FM_StartFrame, + FM_EndFrame +}; +#endif + +/*---------------------------------------------------------------------------- + * inline functions + *---------------------------------------------------------------------------- + */ +EAS_INLINE S_FM_VOICE *GetFMVoicePtr (S_VOICE_MGR *pVoiceMgr, EAS_INT voiceNum) +{ + return &pVoiceMgr->fmVoices[voiceNum]; +} +EAS_INLINE S_SYNTH_CHANNEL *GetChannelPtr (S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice) +{ + return &pSynth->channels[pVoice->channel & 15]; +} +EAS_INLINE const S_FM_REGION *GetFMRegionPtr (S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice) +{ +#ifdef _SECONDARY_SYNTH + return &pSynth->pEAS->pFMRegions[pVoice->regionIndex & REGION_INDEX_MASK]; +#else + return &pSynth->pEAS->pFMRegions[pVoice->regionIndex]; +#endif +} + +/*---------------------------------------------------------------------------- + * FM_SynthIsOutputOperator + *---------------------------------------------------------------------------- + * Purpose: + * Returns true if the operator is a direct output and not muted + * + * Inputs: + * + * Outputs: + * Returns boolean + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL FM_SynthIsOutputOperator (const S_FM_REGION *pRegion, EAS_INT operIndex) +{ + + /* see if voice is muted */ + if ((pRegion->oper[operIndex].gain & 0xfc) == 0) + return 0; + + /* check based on mode */ + switch (pRegion->region.keyGroupAndFlags & 7) + { + + /* mode 0 - all operators are external */ + case 0: + return EAS_TRUE; + + /* mode 1 - operators 1-3 are external */ + case 1: + if (operIndex != 0) + return EAS_TRUE; + break; + + /* mode 2 - operators 1 & 3 are external */ + case 2: + if ((operIndex == 1) || (operIndex == 3)) + return EAS_TRUE; + break; + + /* mode 2 - operators 1 & 2 are external */ + case 3: + if ((operIndex == 1) || (operIndex == 2)) + return EAS_TRUE; + break; + + /* modes 4 & 5 - operator 1 is external */ + case 4: + case 5: + if (operIndex == 1) + return EAS_TRUE; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL,"Invalid voice mode: %d", + pRegion->region.keyGroupAndFlags & 7); */ } + } + + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * FM_CalcEGRate() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * nKeyNumber - MIDI note + * nLogRate - logarithmic scale rate from patch data + * nKeyScale - key scaling factor for this EG + * + * Outputs: + * 16-bit linear multiplier + *---------------------------------------------------------------------------- +*/ + +static EAS_U16 FM_CalcEGRate (EAS_U8 nKeyNumber, EAS_U8 nLogRate, EAS_U8 nEGScale) +{ + EAS_I32 temp; + + /* incorporate key scaling on release rate */ + temp = (EAS_I32) nLogRate << 7; + temp += ((EAS_I32) nKeyNumber - EG_SCALE_PIVOT_POINT) * (EAS_I32) nEGScale; + + /* saturate */ + temp = max(temp, 0); + temp = min(temp, 32767); + + /* look up in rate table */ + /*lint -e{704} use shift for performance */ + return fmRateTable[temp >> 8]; +} + +/*---------------------------------------------------------------------------- + * FM_ReleaseVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being released. + * + * Inputs: + * psEASData - pointer to S_EAS_DATA + * pVoice - pointer to voice to release + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static void FM_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + EAS_INT operIndex; + const S_FM_REGION *pRegion; + S_FM_VOICE *pFMVoice; + + /* check to see if voice responds to NOTE-OFF's */ + pRegion = GetFMRegionPtr(pSynth, pVoice); + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_ONE_SHOT) + return; + + /* set all envelopes to release state */ + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + for (operIndex = 0; operIndex < 4; operIndex++) + { + pFMVoice->oper[operIndex].envState = eFMEnvelopeStateRelease; + + /* incorporate key scaling on release rate */ + pFMVoice->oper[operIndex].envRate = FM_CalcEGRate( + pVoice->note, + fmReleaseTable[pRegion->oper[operIndex].velocityRelease & 0x0f], + fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]); + } /* end for (operIndex = 0; operIndex < 4; operIndex++) */ +} + +/*---------------------------------------------------------------------------- + * FM_MuteVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being muted. + * + * Inputs: + * pVoice - pointer to voice to release + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pSynth) standard interface, pVoiceMgr not used */ +static void FM_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + S_FM_VOICE *pFMVoice; + + /* clear deferred action flags */ + pVoice->voiceFlags &= + ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | + VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF | + VOICE_FLAG_DEFER_MUTE); + + /* set all envelopes to muted state */ + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + pFMVoice->oper[0].envState = eFMEnvelopeStateMuted; + pFMVoice->oper[1].envState = eFMEnvelopeStateMuted; + pFMVoice->oper[2].envState = eFMEnvelopeStateMuted; + pFMVoice->oper[3].envState = eFMEnvelopeStateMuted; +} + +/*---------------------------------------------------------------------------- + * FM_SustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is held due to sustain pedal + * + * Inputs: + * pVoice - pointer to voice to sustain + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pChannel) standard interface, pVoiceMgr not used */ +static void FM_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) +{ + const S_FM_REGION *pRegion; + S_FM_VOICE *pFMVoice; + EAS_INT operIndex; + + pRegion = GetFMRegionPtr(pSynth, pVoice); + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + + /* check to see if any envelopes are above the sustain level */ + for (operIndex = 0; operIndex < 4; operIndex++) + { + + /* if level control or envelope gain is zero, skip this envelope */ + if (((pRegion->oper[operIndex].gain & 0xfc) == 0) || + (pFMVoice->oper[operIndex].envGain == 0)) + { + continue; + } + + /* if the envelope gain is above the sustain level, we need to catch this voice */ + if (pFMVoice->oper[operIndex].envGain >= ((EAS_U16) (pRegion->oper[operIndex].sustain & 0xfc) << 7)) + { + + /* reset envelope to decay state */ + pFMVoice->oper[operIndex].envState = eFMEnvelopeStateDecay; + + pFMVoice->oper[operIndex].envRate = FM_CalcEGRate( + pVoice->note, + fmDecayTable[pRegion->oper[operIndex].attackDecay & 0x0f], + fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]); + + /* set voice to decay state */ + pVoice->voiceState = eVoiceStatePlay; + + /* set sustain flag */ + pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + } + } /* end for (operIndex = 0; operIndex < 4; operIndex++) */ +} + +/*---------------------------------------------------------------------------- + * FM_StartVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the region for the given instrument using the midi key number + * and the RPN2 (coarse tuning) value. By using RPN2 as part of the + * region selection process, we reduce the amount a given sample has + * to be transposed by selecting the closest recorded root instead. + * + * This routine is the second half of SynthAssignRegion(). + * If the region was successfully found by SynthFindRegionIndex(), + * then assign the region's parameters to the voice. + * + * Setup and initialize the following voice parameters: + * m_nRegionIndex + * + * Inputs: + * pVoice - ptr to the voice we have assigned for this channel + * nRegionIndex - index of the region + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * success - could find and assign the region for this voice's note otherwise + * failure - could not find nor assign the region for this voice's note + * + * Side Effects: + * psSynthObject->m_sVoice[].m_nRegionIndex is assigned + * psSynthObject->m_sVoice[] parameters are assigned + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT FM_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) +{ + S_FM_VOICE *pFMVoice; + S_SYNTH_CHANNEL *pChannel; + const S_FM_REGION *pRegion; + EAS_I32 temp; + EAS_INT operIndex; + + /* establish pointers to data */ + pVoice->regionIndex = regionIndex; + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + pChannel = GetChannelPtr(pSynth, pVoice); + pRegion = GetFMRegionPtr(pSynth, pVoice); + + /* update static channel parameters */ + if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS) + FM_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15); + + /* init the LFO */ + pFMVoice->lfoValue = 0; + pFMVoice->lfoPhase = 0; + pFMVoice->lfoDelay = (EAS_U16) (fmScaleTable[pRegion->lfoFreqDelay & 0x0f] >> 1); + +#if (NUM_OUTPUT_CHANNELS == 2) + /* calculate pan gain values only if stereo output */ + /* set up panning only at note start */ + temp = (EAS_I32) pChannel->pan - 64; + temp += (EAS_I32) pRegion->pan; + if (temp < -64) + temp = -64; + if (temp > 64) + temp = 64; + pFMVoice->pan = (EAS_I8) temp; +#endif /* #if (NUM_OUTPUT_CHANNELS == 2) */ + + /* no samples have been synthesized for this note yet */ + pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + + /* initialize gain value for anti-zipper filter */ + pFMVoice->voiceGain = (EAS_I16) EAS_LogToLinear16(pChannel->staticGain); + pFMVoice->voiceGain = (EAS_I16) FMUL_15x15(pFMVoice->voiceGain, pSynth->masterVolume); + + /* initialize the operators */ + for (operIndex = 0; operIndex < 4; operIndex++) + { + + /* establish operator output gain level */ + /*lint -e{701} */ + pFMVoice->oper[operIndex].outputGain = EAS_LogToLinear16(((EAS_I16) (pRegion->oper[operIndex].gain & 0xfc) - 0xfc) << 7); + + /* check for linear velocity flag */ + /*lint -e{703} */ + if (pRegion->oper[operIndex].flags & FM_OPER_FLAG_LINEAR_VELOCITY) + temp = (EAS_I32) (pVoice->velocity - 127) << 5; + else + temp = (EAS_I32) fmControlTable[pVoice->velocity]; + + /* scale velocity */ + /*lint -e{704} use shift for performance */ + temp = (temp * (EAS_I32)(pRegion->oper[operIndex].velocityRelease & 0xf0)) >> 7; + + /* include key scalar */ + temp -= ((EAS_I32) pVoice->note - KEY_SCALE_PIVOT_POINT) * (EAS_I32) fmScaleTable[pRegion->oper[operIndex].egKeyScale & 0x0f]; + + /* saturate */ + temp = min(temp, 0); + temp = max(temp, -32768); + + /* save static gain parameters */ + pFMVoice->oper[operIndex].baseGain = (EAS_I16) EAS_LogToLinear16(temp); + + /* incorporate key scaling on decay rate */ + pFMVoice->oper[operIndex].envRate = FM_CalcEGRate( + pVoice->note, + fmDecayTable[pRegion->oper[operIndex].attackDecay & 0x0f], + fmScaleTable[pRegion->oper[operIndex].egKeyScale >> 4]); + + /* if zero attack time, max out envelope and jump to decay state */ + if ((pRegion->oper[operIndex].attackDecay & 0xf0) == 0xf0) + { + + /* start out envelope at max */ + pFMVoice->oper[operIndex].envGain = 0x7fff; + + /* set envelope to decay state */ + pFMVoice->oper[operIndex].envState = eFMEnvelopeStateDecay; + } + + /* start envelope at zero and start in attack state */ + else + { + pFMVoice->oper[operIndex].envGain = 0; + pFMVoice->oper[operIndex].envState = eFMEnvelopeStateAttack; + } + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateChannel() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate and assign static channel parameters + * These values only need to be updated if one of the controller values + * for this channel changes. + * Called when CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS flag is set. + * + * Inputs: + * nChannel - channel to update + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - the given channel's static gain and static pitch are updated + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) standard interface, pVoiceMgr not used */ +static void FM_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_I32 temp; + + pChannel = &pSynth->channels[channel]; + + /* convert CC7 volume controller to log scale */ + temp = fmControlTable[pChannel->volume]; + + /* incorporate CC11 expression controller */ + temp += fmControlTable[pChannel->expression]; + + /* saturate */ + pChannel->staticGain = (EAS_I16) max(temp,-32768); + + /* calculate pitch bend */ + /*lint -e{703} */ + temp = (((EAS_I32)(pChannel->pitchBend) << 2) - 32768); + + temp = FMUL_15x15(temp, pChannel->pitchBendSensitivity); + + /* include "magic number" compensation for sample rate and lookup table size */ + temp += MAGIC_NUMBER; + + /* if this is not a drum channel, then add in the per-channel tuning */ + if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL)) + temp += (pChannel->finePitch + (pChannel->coarsePitch * 100)); + + /* save static pitch */ + pChannel->staticPitch = temp; + + /* Calculate LFO modulation depth */ + /* mod wheel to LFO depth */ + temp = FMUL_15x15(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS, + pChannel->modWheel << (NUM_EG1_FRAC_BITS -7)); + + /* channel pressure to LFO depth */ + pChannel->lfoAmt = (EAS_I16) (temp + + FMUL_15x15(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS, + pChannel->channelPressure << (NUM_EG1_FRAC_BITS -7))); + + /* clear update flag */ + pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + return; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateLFO() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the LFO for the given voice + * + * Inputs: + * pVoice - ptr to the voice whose LFO we want to update + * psEASData - pointer to overall EAS data structure - used for debug only + * + * Outputs: + * + * Side Effects: + * - updates LFO values for the given voice + *---------------------------------------------------------------------------- +*/ +static void FM_UpdateLFO (S_FM_VOICE *pFMVoice, const S_FM_REGION *pRegion) +{ + + /* increment the LFO phase if the delay time has elapsed */ + if (!pFMVoice->lfoDelay) + { + /*lint -e{701} */ + pFMVoice->lfoPhase = pFMVoice->lfoPhase + (EAS_U16) (-fmControlTable[((15 - (pRegion->lfoFreqDelay >> 4)) << 3) + 4]); + + /* square wave LFO? */ + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_SQUARE_WAVE) + pFMVoice->lfoValue = (EAS_I16)(pFMVoice->lfoPhase & 0x8000 ? -32767 : 32767); + + /* trick to get a triangle wave out of a sawtooth */ + else + { + pFMVoice->lfoValue = (EAS_I16) (pFMVoice->lfoPhase << 1); + /*lint -e{502} */ + if ((pFMVoice->lfoPhase > 0x3fff) && (pFMVoice->lfoPhase < 0xC000)) + pFMVoice->lfoValue = ~pFMVoice->lfoValue; + } + } + + /* still in delay */ + else + pFMVoice->lfoDelay--; + + return; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateEG() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the synthesis parameters for an operator to be used during + * the next buffer + * + * Inputs: + * pVoice - pointer to the voice being updated + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL FM_UpdateEG (S_SYNTH_VOICE *pVoice, S_OPERATOR *pOper, const S_FM_OPER *pOperData, EAS_BOOL oneShot) +{ + EAS_U32 temp; + EAS_BOOL done; + + /* set flag assuming the envelope is not done */ + done = EAS_FALSE; + + /* take appropriate action based on state */ + switch (pOper->envState) + { + + case eFMEnvelopeStateAttack: + + /* the envelope is linear during the attack, so add the value */ + temp = pOper->envGain + fmAttackTable[pOperData->attackDecay >> 4]; + + /* check for end of attack */ + if (temp >= 0x7fff) + { + pOper->envGain = 0x7fff; + pOper->envState = eFMEnvelopeStateDecay; + } + else + pOper->envGain = (EAS_U16) temp; + break; + + case eFMEnvelopeStateDecay: + + /* decay is exponential, multiply by decay rate */ + pOper->envGain = (EAS_U16) FMUL_15x15(pOper->envGain, pOper->envRate); + + /* check for sustain level reached */ + temp = (EAS_U32) (pOperData->sustain & 0xfc) << 7; + if (pOper->envGain <= (EAS_U16) temp) + { + /* if this is a one-shot patch, go directly to release phase */ + if (oneShot) + { + pOper->envRate = FM_CalcEGRate( + pVoice->note, + fmReleaseTable[pOperData->velocityRelease & 0x0f], + fmScaleTable[pOperData->egKeyScale >> 4]); + pOper->envState = eFMEnvelopeStateRelease; + } + + /* normal sustaining type */ + else + { + pOper->envGain = (EAS_U16) temp; + pOper->envState = eFMEnvelopeStateSustain; + } + } + break; + + case eFMEnvelopeStateSustain: + pOper->envGain = (EAS_U16)((EAS_U16)(pOperData->sustain & 0xfc) << 7); + break; + + case eFMEnvelopeStateRelease: + + /* release is exponential, multiply by release rate */ + pOper->envGain = (EAS_U16) FMUL_15x15(pOper->envGain, pOper->envRate); + + /* fully released */ + if (pOper->envGain == 0) + { + pOper->envGain = 0; + pOper->envState = eFMEnvelopeStateMuted; + done = EAS_TRUE; + } + break; + + case eFMEnvelopeStateMuted: + pOper->envGain = 0; + done = EAS_TRUE; + break; + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL,"Invalid operator state: %d", pOper->envState); */ } + } /* end switch (pOper->m_eState) */ + + return done; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateDynamic() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the synthesis parameters for this voice that will be used to + * synthesize the next buffer + * + * Inputs: + * pVoice - pointer to the voice being updated + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Returns EAS_TRUE if voice will be fully ramped to zero at the end of + * the next synthesized buffer. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL FM_UpdateDynamic (S_SYNTH_VOICE *pVoice, S_FM_VOICE *pFMVoice, const S_FM_REGION *pRegion, S_SYNTH_CHANNEL *pChannel) +{ + EAS_I32 temp; + EAS_I32 pitch; + EAS_I32 lfoPitch; + EAS_INT operIndex; + EAS_BOOL done; + + /* increment LFO phase */ + FM_UpdateLFO(pFMVoice, pRegion); + + /* base pitch in cents */ + pitch = pVoice->note * 100; + + /* LFO amount includes LFO depth from programming + channel dynamics */ + temp = (fmScaleTable[pRegion->vibTrem >> 4] >> 1) + pChannel->lfoAmt; + + /* multiply by LFO output to get final pitch modulation */ + lfoPitch = FMUL_15x15(pFMVoice->lfoValue, temp); + + /* flag to indicate this voice is done */ + done = EAS_TRUE; + + /* iterate through operators to establish parameters */ + for (operIndex = 0; operIndex < 4; operIndex++) + { + EAS_BOOL bTemp; + + /* set base phase increment for each operator */ + temp = pRegion->oper[operIndex].tuning + + pChannel->staticPitch; + + /* add vibrato effect unless it is disabled for this operator */ + if ((pRegion->oper[operIndex].flags & FM_OPER_FLAG_NO_VIBRATO) == 0) + temp += lfoPitch; + + /* if note is monotonic, bias to MIDI note 60 */ + if (pRegion->oper[operIndex].flags & FM_OPER_FLAG_MONOTONE) + temp += 6000; + else + temp += pitch; + pFMVoice->oper[operIndex].pitch = (EAS_I16) temp; + + /* calculate envelope, returns true if done */ + bTemp = FM_UpdateEG(pVoice, &pFMVoice->oper[operIndex], &pRegion->oper[operIndex], pRegion->region.keyGroupAndFlags & REGION_FLAG_ONE_SHOT); + + /* check if all output envelopes have completed */ + if (FM_SynthIsOutputOperator(pRegion, operIndex)) + done = done && bTemp; + } + + return done; +} + +/*---------------------------------------------------------------------------- + * FM_UpdateVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize a block of samples for the given voice. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL FM_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples) +{ + S_SYNTH_CHANNEL *pChannel; + const S_FM_REGION *pRegion; + S_FM_VOICE *pFMVoice; + S_FM_VOICE_CONFIG vCfg; + S_FM_VOICE_FRAME vFrame; + EAS_I32 temp; + EAS_INT oper; + EAS_U16 voiceGainTarget; + EAS_BOOL done; + + /* setup some pointers */ + pChannel = GetChannelPtr(pSynth, pVoice); + pRegion = GetFMRegionPtr(pSynth, pVoice); + pFMVoice = GetFMVoicePtr(pVoiceMgr, voiceNum); + + /* if the voice is just starting, get the voice configuration data */ + if (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + { + + /* split architecture may limit the number of voice starts */ +#ifdef MAX_VOICE_STARTS + if (pVoiceMgr->numVoiceStarts == MAX_VOICE_STARTS) + return EAS_FALSE; + pVoiceMgr->numVoiceStarts++; +#endif + + /* get initial parameters */ + vCfg.feedback = pRegion->feedback; + vCfg.voiceGain = (EAS_U16) pFMVoice->voiceGain; + +#if (NUM_OUTPUT_CHANNELS == 2) + vCfg.pan = pFMVoice->pan; +#endif + + /* get voice mode */ + vCfg.flags = pRegion->region.keyGroupAndFlags & 7; + + /* get operator parameters */ + for (oper = 0; oper < 4; oper++) + { + /* calculate initial gain */ + vCfg.gain[oper] = (EAS_U16) FMUL_15x15(pFMVoice->oper[oper].baseGain, pFMVoice->oper[oper].envGain); + vCfg.outputGain[oper] = pFMVoice->oper[oper].outputGain; + + /* copy noise waveform flag */ + if (pRegion->oper[oper].flags & FM_OPER_FLAG_NOISE) + vCfg.flags |= (EAS_U8) (FLAG_FM_ENG_VOICE_OP1_NOISE << oper); + } + +#ifdef FM_OFFBOARD + FM_ConfigVoice(voiceNum, &vCfg, pVoiceMgr->pFrameBuffer); +#else + FM_ConfigVoice(voiceNum, &vCfg, NULL); +#endif + + /* clear startup flag */ + pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + } + + /* calculate new synthesis parameters */ + done = FM_UpdateDynamic(pVoice, pFMVoice, pRegion, pChannel); + + /* calculate LFO gain modulation */ + /*lint -e{702} */ + temp = ((fmScaleTable[pRegion->vibTrem & 0x0f] >> 1) * pFMVoice->lfoValue) >> FM_LFO_GAIN_SHIFT; + + /* include channel gain */ + temp += pChannel->staticGain; + + /* -32768 or lower is infinite attenuation */ + if (temp < -32767) + voiceGainTarget = 0; + + /* translate to linear gain multiplier */ + else + voiceGainTarget = EAS_LogToLinear16(temp); + + /* include synth master volume */ + voiceGainTarget = (EAS_U16) FMUL_15x15(voiceGainTarget, pSynth->masterVolume); + + /* save target values for this frame */ + vFrame.voiceGain = voiceGainTarget; + + /* assume voice output is zero */ + pVoice->gain = 0; + + /* save operator targets for this frame */ + for (oper = 0; oper < 4; oper++) + { + vFrame.gain[oper] = (EAS_U16) FMUL_15x15(pFMVoice->oper[oper].baseGain, pFMVoice->oper[oper].envGain); + vFrame.pitch[oper] = pFMVoice->oper[oper].pitch; + + /* use the highest output envelope level as the gain for the voice stealing algorithm */ + if (FM_SynthIsOutputOperator(pRegion, oper)) + pVoice->gain = max(pVoice->gain, (EAS_I16) vFrame.gain[oper]); + } + + /* consider voice gain multiplier in calculating gain for stealing algorithm */ + pVoice->gain = (EAS_I16) FMUL_15x15(voiceGainTarget, pVoice->gain); + + /* synthesize samples */ +#ifdef FM_OFFBOARD + FM_ProcessVoice(voiceNum, &vFrame, numSamples, pVoiceMgr->operMixBuffer, pVoiceMgr->voiceBuffer, pMixBuffer, pVoiceMgr->pFrameBuffer); +#else + FM_ProcessVoice(voiceNum, &vFrame, numSamples, pVoiceMgr->operMixBuffer, pVoiceMgr->voiceBuffer, pMixBuffer, NULL); +#endif + + return done; +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmsynth.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmsynth.h new file mode 100755 index 0000000..8ceda46 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmsynth.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_fmsynth.h + * + * Contents and purpose: + * Implements the FM synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 90 $ + * $Date: 2006-07-11 20:18:13 -0700 (Tue, 11 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef fmsynthH +#define fmsynthH + +#include "eas_data.h" + +#if defined (_FM_SYNTH) + +/* FM envelope state */ +typedef enum { + eFMEnvelopeStateAttack = 0, + eFMEnvelopeStateDecay, + eFMEnvelopeStateSustain, + eFMEnvelopeStateRelease, + eFMEnvelopeStateMuted, + eFMEnvelopeStateInvalid /* should never be in this state! */ +} E_FM_ENVELOPE_STATE; + +/*------------------------------------ + * S_OPERATOR data structure + *------------------------------------ +*/ +typedef struct s_operator_tag +{ + EAS_I16 pitch; /* operator pitch in cents */ + EAS_U16 envGain; /* envelope target */ + EAS_I16 baseGain; /* patch gain (inc. vel & key scale) */ + EAS_U16 outputGain; /* current output gain */ + EAS_U16 envRate; /* calculated envelope rate */ + EAS_U8 envState; /* envelope state */ + EAS_U8 pad; /* pad to 16-bits */ +} S_OPERATOR; +#endif + +typedef struct s_fm_voice_tag +{ + S_OPERATOR oper[4]; /* operator data */ + EAS_I16 voiceGain; /* LFO + channel parameters */ + EAS_U16 lfoPhase; /* LFO current phase */ + EAS_I16 lfoValue; /* LFO current value */ + EAS_U16 lfoDelay; /* keeps track of elapsed delay time */ + EAS_I8 pan; /* stereo pan value (-64 to +64) */ + EAS_I8 pad; /* reserved to maintain alignment */ +} S_FM_VOICE; + +#ifdef _FM_EDITOR +extern S_FM_REGION newPatch; +extern S_FM_REGION OriginalPatch; +#endif + +extern EAS_U32 freqTable[]; + +#endif diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmtables.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmtables.c new file mode 100755 index 0000000..a8ff0a2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_fmtables.c @@ -0,0 +1,368 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_fmtables.c + * + * Contents and purpose: + * Contains lookup tables for the FM synthesizer + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + * + *---------------------------------------------------------------------------- +*/ + + +#include "eas_types.h" + +/* this table is needed by the DSP and the main processor */ +const EAS_U8 fmScaleTable[16] = +{ + 0,8,16,24,32,40,48,56,64,72,80,96,128,160,192,255 +}; + +/* these tables are needed on the main processor */ +#ifndef _DSP_CODE +const EAS_I16 fmControlTable[128] = +{ + -32768,-14313,-12265,-11067,-10217,-9558,-9019,-8563, + -8169,-7821,-7510,-7228,-6971,-6734,-6515,-6312, + -6121,-5942,-5773,-5613,-5462,-5317,-5180,-5049, + -4923,-4802,-4686,-4575,-4467,-4364,-4264,-4167, + -4073,-3982,-3894,-3808,-3725,-3644,-3565,-3488, + -3414,-3341,-3269,-3200,-3132,-3066,-3001,-2937, + -2875,-2814,-2754,-2696,-2638,-2582,-2527,-2473, + -2419,-2367,-2316,-2265,-2216,-2167,-2119,-2071, + -2025,-1979,-1934,-1889,-1846,-1803,-1760,-1718, + -1677,-1636,-1596,-1556,-1517,-1478,-1440,-1403, + -1366,-1329,-1293,-1257,-1221,-1186,-1152,-1118, + -1084,-1051,-1018,-985,-953,-921,-889,-858, + -827,-796,-766,-736,-706,-677,-648,-619, + -590,-562,-534,-506,-479,-452,-425,-398, + -371,-345,-319,-293,-268,-242,-217,-192, + -168,-143,-119,-95,-71,-47,-23,0 +}; + +const EAS_U16 fmRateTable[128] = +{ + 32767,32764,32758,32747,32731,32712,32688,32659, + 32627,32590,32548,32503,32453,32398,32340,32277, + 32211,32140,32065,31985,31902,31815,31724,31628, + 31529,31426,31319,31208,31094,30976,30854,30728, + 30599,30466,30330,30191,30048,29902,29752,29599, + 29443,29285,29123,28958,28790,28619,28445,28269, + 28090,27909,27725,27538,27349,27158,26964,26769, + 26571,26371,26169,25965,25760,25552,25343,25132, + 24920,24706,24490,24274,24056,23836,23616,23394, + 23172,22948,22724,22499,22273,22046,21819,21591, + 21363,21135,20906,20676,20447,20217,19987,19758, + 19528,19298,19069,18840,18610,18382,18153,17926, + 17698,17471,17245,17020,16795,16571,16347,16125, + 15903,15683,15463,15245,15027,14811,14596,14382, + 14169,13957,13747,13538,13331,13125,12920,12717, + 12516,12316,12117,11921,11725,11532,11340,0 +}; + +const EAS_U16 fmAttackTable[15] = +{ + 27,54,109,327,655,1310,2730,4095, + 4681,5461,6553,8191,10922,16383,32767 +}; + +const EAS_U8 fmDecayTable[16] = +{ + 4,7,10,15,20,25,30,35,40,50,60,70,80,90,100,127 +}; + +const EAS_U8 fmReleaseTable[16] = +{ + 10,15,20,25,30,35,40,45,50,60,70,80,90,100,113,127 +}; +#endif + +/* this table is needed only on the DSP */ +#if defined(_DSP_CODE) || !defined(_SPLIT_ARCHITECTURE) +//--------------------------------------------------------------------- +// sineTable +// +// Contains sine lookup table +//--------------------------------------------------------------------- + +const EAS_I16 sineTable[2048] = +{ + 0,101,201,302,402,503,603,704, + 804,905,1005,1106,1206,1307,1407,1507, + 1608,1708,1809,1909,2009,2110,2210,2310, + 2410,2511,2611,2711,2811,2911,3012,3112, + 3212,3312,3412,3512,3612,3712,3811,3911, + 4011,4111,4210,4310,4410,4509,4609,4708, + 4808,4907,5007,5106,5205,5305,5404,5503, + 5602,5701,5800,5899,5998,6096,6195,6294, + 6393,6491,6590,6688,6786,6885,6983,7081, + 7179,7277,7375,7473,7571,7669,7767,7864, + 7962,8059,8157,8254,8351,8448,8545,8642, + 8739,8836,8933,9030,9126,9223,9319,9416, + 9512,9608,9704,9800,9896,9992,10087,10183, + 10278,10374,10469,10564,10659,10754,10849,10944, + 11039,11133,11228,11322,11417,11511,11605,11699, + 11793,11886,11980,12074,12167,12260,12353,12446, + 12539,12632,12725,12817,12910,13002,13094,13187, + 13279,13370,13462,13554,13645,13736,13828,13919, + 14010,14101,14191,14282,14372,14462,14553,14643, + 14732,14822,14912,15001,15090,15180,15269,15358, + 15446,15535,15623,15712,15800,15888,15976,16063, + 16151,16238,16325,16413,16499,16586,16673,16759, + 16846,16932,17018,17104,17189,17275,17360,17445, + 17530,17615,17700,17784,17869,17953,18037,18121, + 18204,18288,18371,18454,18537,18620,18703,18785, + 18868,18950,19032,19113,19195,19276,19357,19438, + 19519,19600,19680,19761,19841,19921,20000,20080, + 20159,20238,20317,20396,20475,20553,20631,20709, + 20787,20865,20942,21019,21096,21173,21250,21326, + 21403,21479,21554,21630,21705,21781,21856,21930, + 22005,22079,22154,22227,22301,22375,22448,22521, + 22594,22667,22739,22812,22884,22956,23027,23099, + 23170,23241,23311,23382,23452,23522,23592,23662, + 23731,23801,23870,23938,24007,24075,24143,24211, + 24279,24346,24413,24480,24547,24613,24680,24746, + 24811,24877,24942,25007,25072,25137,25201,25265, + 25329,25393,25456,25519,25582,25645,25708,25770, + 25832,25893,25955,26016,26077,26138,26198,26259, + 26319,26378,26438,26497,26556,26615,26674,26732, + 26790,26848,26905,26962,27019,27076,27133,27189, + 27245,27300,27356,27411,27466,27521,27575,27629, + 27683,27737,27790,27843,27896,27949,28001,28053, + 28105,28157,28208,28259,28310,28360,28411,28460, + 28510,28560,28609,28658,28706,28755,28803,28850, + 28898,28945,28992,29039,29085,29131,29177,29223, + 29268,29313,29358,29403,29447,29491,29534,29578, + 29621,29664,29706,29749,29791,29832,29874,29915, + 29956,29997,30037,30077,30117,30156,30195,30234, + 30273,30311,30349,30387,30424,30462,30498,30535, + 30571,30607,30643,30679,30714,30749,30783,30818, + 30852,30885,30919,30952,30985,31017,31050,31082, + 31113,31145,31176,31206,31237,31267,31297,31327, + 31356,31385,31414,31442,31470,31498,31526,31553, + 31580,31607,31633,31659,31685,31710,31736,31760, + 31785,31809,31833,31857,31880,31903,31926,31949, + 31971,31993,32014,32036,32057,32077,32098,32118, + 32137,32157,32176,32195,32213,32232,32250,32267, + 32285,32302,32318,32335,32351,32367,32382,32397, + 32412,32427,32441,32455,32469,32482,32495,32508, + 32521,32533,32545,32556,32567,32578,32589,32599, + 32609,32619,32628,32637,32646,32655,32663,32671, + 32678,32685,32692,32699,32705,32711,32717,32722, + 32728,32732,32737,32741,32745,32748,32752,32755, + 32757,32759,32761,32763,32765,32766,32766,32767, + 32767,32767,32766,32766,32765,32763,32761,32759, + 32757,32755,32752,32748,32745,32741,32737,32732, + 32728,32722,32717,32711,32705,32699,32692,32685, + 32678,32671,32663,32655,32646,32637,32628,32619, + 32609,32599,32589,32578,32567,32556,32545,32533, + 32521,32508,32495,32482,32469,32455,32441,32427, + 32412,32397,32382,32367,32351,32335,32318,32302, + 32285,32267,32250,32232,32213,32195,32176,32157, + 32137,32118,32098,32077,32057,32036,32014,31993, + 31971,31949,31926,31903,31880,31857,31833,31809, + 31785,31760,31736,31710,31685,31659,31633,31607, + 31580,31553,31526,31498,31470,31442,31414,31385, + 31356,31327,31297,31267,31237,31206,31176,31145, + 31113,31082,31050,31017,30985,30952,30919,30885, + 30852,30818,30783,30749,30714,30679,30643,30607, + 30571,30535,30498,30462,30424,30387,30349,30311, + 30273,30234,30195,30156,30117,30077,30037,29997, + 29956,29915,29874,29832,29791,29749,29706,29664, + 29621,29578,29534,29491,29447,29403,29358,29313, + 29268,29223,29177,29131,29085,29039,28992,28945, + 28898,28850,28803,28755,28706,28658,28609,28560, + 28510,28460,28411,28360,28310,28259,28208,28157, + 28105,28053,28001,27949,27896,27843,27790,27737, + 27683,27629,27575,27521,27466,27411,27356,27300, + 27245,27189,27133,27076,27019,26962,26905,26848, + 26790,26732,26674,26615,26556,26497,26438,26378, + 26319,26259,26198,26138,26077,26016,25955,25893, + 25832,25770,25708,25645,25582,25519,25456,25393, + 25329,25265,25201,25137,25072,25007,24942,24877, + 24811,24746,24680,24613,24547,24480,24413,24346, + 24279,24211,24143,24075,24007,23938,23870,23801, + 23731,23662,23592,23522,23452,23382,23311,23241, + 23170,23099,23027,22956,22884,22812,22739,22667, + 22594,22521,22448,22375,22301,22227,22154,22079, + 22005,21930,21856,21781,21705,21630,21554,21479, + 21403,21326,21250,21173,21096,21019,20942,20865, + 20787,20709,20631,20553,20475,20396,20317,20238, + 20159,20080,20000,19921,19841,19761,19680,19600, + 19519,19438,19357,19276,19195,19113,19032,18950, + 18868,18785,18703,18620,18537,18454,18371,18288, + 18204,18121,18037,17953,17869,17784,17700,17615, + 17530,17445,17360,17275,17189,17104,17018,16932, + 16846,16759,16673,16586,16499,16413,16325,16238, + 16151,16063,15976,15888,15800,15712,15623,15535, + 15446,15358,15269,15180,15090,15001,14912,14822, + 14732,14643,14553,14462,14372,14282,14191,14101, + 14010,13919,13828,13736,13645,13554,13462,13370, + 13279,13187,13094,13002,12910,12817,12725,12632, + 12539,12446,12353,12260,12167,12074,11980,11886, + 11793,11699,11605,11511,11417,11322,11228,11133, + 11039,10944,10849,10754,10659,10564,10469,10374, + 10278,10183,10087,9992,9896,9800,9704,9608, + 9512,9416,9319,9223,9126,9030,8933,8836, + 8739,8642,8545,8448,8351,8254,8157,8059, + 7962,7864,7767,7669,7571,7473,7375,7277, + 7179,7081,6983,6885,6786,6688,6590,6491, + 6393,6294,6195,6096,5998,5899,5800,5701, + 5602,5503,5404,5305,5205,5106,5007,4907, + 4808,4708,4609,4509,4410,4310,4210,4111, + 4011,3911,3811,3712,3612,3512,3412,3312, + 3212,3112,3012,2911,2811,2711,2611,2511, + 2410,2310,2210,2110,2009,1909,1809,1708, + 1608,1507,1407,1307,1206,1106,1005,905, + 804,704,603,503,402,302,201,101, + 0,-101,-201,-302,-402,-503,-603,-704, + -804,-905,-1005,-1106,-1206,-1307,-1407,-1507, + -1608,-1708,-1809,-1909,-2009,-2110,-2210,-2310, + -2410,-2511,-2611,-2711,-2811,-2911,-3012,-3112, + -3212,-3312,-3412,-3512,-3612,-3712,-3811,-3911, + -4011,-4111,-4210,-4310,-4410,-4509,-4609,-4708, + -4808,-4907,-5007,-5106,-5205,-5305,-5404,-5503, + -5602,-5701,-5800,-5899,-5998,-6096,-6195,-6294, + -6393,-6491,-6590,-6688,-6786,-6885,-6983,-7081, + -7179,-7277,-7375,-7473,-7571,-7669,-7767,-7864, + -7962,-8059,-8157,-8254,-8351,-8448,-8545,-8642, + -8739,-8836,-8933,-9030,-9126,-9223,-9319,-9416, + -9512,-9608,-9704,-9800,-9896,-9992,-10087,-10183, + -10278,-10374,-10469,-10564,-10659,-10754,-10849,-10944, + -11039,-11133,-11228,-11322,-11417,-11511,-11605,-11699, + -11793,-11886,-11980,-12074,-12167,-12260,-12353,-12446, + -12539,-12632,-12725,-12817,-12910,-13002,-13094,-13187, + -13279,-13370,-13462,-13554,-13645,-13736,-13828,-13919, + -14010,-14101,-14191,-14282,-14372,-14462,-14553,-14643, + -14732,-14822,-14912,-15001,-15090,-15180,-15269,-15358, + -15446,-15535,-15623,-15712,-15800,-15888,-15976,-16063, + -16151,-16238,-16325,-16413,-16499,-16586,-16673,-16759, + -16846,-16932,-17018,-17104,-17189,-17275,-17360,-17445, + -17530,-17615,-17700,-17784,-17869,-17953,-18037,-18121, + -18204,-18288,-18371,-18454,-18537,-18620,-18703,-18785, + -18868,-18950,-19032,-19113,-19195,-19276,-19357,-19438, + -19519,-19600,-19680,-19761,-19841,-19921,-20000,-20080, + -20159,-20238,-20317,-20396,-20475,-20553,-20631,-20709, + -20787,-20865,-20942,-21019,-21096,-21173,-21250,-21326, + -21403,-21479,-21554,-21630,-21705,-21781,-21856,-21930, + -22005,-22079,-22154,-22227,-22301,-22375,-22448,-22521, + -22594,-22667,-22739,-22812,-22884,-22956,-23027,-23099, + -23170,-23241,-23311,-23382,-23452,-23522,-23592,-23662, + -23731,-23801,-23870,-23938,-24007,-24075,-24143,-24211, + -24279,-24346,-24413,-24480,-24547,-24613,-24680,-24746, + -24811,-24877,-24942,-25007,-25072,-25137,-25201,-25265, + -25329,-25393,-25456,-25519,-25582,-25645,-25708,-25770, + -25832,-25893,-25955,-26016,-26077,-26138,-26198,-26259, + -26319,-26378,-26438,-26497,-26556,-26615,-26674,-26732, + -26790,-26848,-26905,-26962,-27019,-27076,-27133,-27189, + -27245,-27300,-27356,-27411,-27466,-27521,-27575,-27629, + -27683,-27737,-27790,-27843,-27896,-27949,-28001,-28053, + -28105,-28157,-28208,-28259,-28310,-28360,-28411,-28460, + -28510,-28560,-28609,-28658,-28706,-28755,-28803,-28850, + -28898,-28945,-28992,-29039,-29085,-29131,-29177,-29223, + -29268,-29313,-29358,-29403,-29447,-29491,-29534,-29578, + -29621,-29664,-29706,-29749,-29791,-29832,-29874,-29915, + -29956,-29997,-30037,-30077,-30117,-30156,-30195,-30234, + -30273,-30311,-30349,-30387,-30424,-30462,-30498,-30535, + -30571,-30607,-30643,-30679,-30714,-30749,-30783,-30818, + -30852,-30885,-30919,-30952,-30985,-31017,-31050,-31082, + -31113,-31145,-31176,-31206,-31237,-31267,-31297,-31327, + -31356,-31385,-31414,-31442,-31470,-31498,-31526,-31553, + -31580,-31607,-31633,-31659,-31685,-31710,-31736,-31760, + -31785,-31809,-31833,-31857,-31880,-31903,-31926,-31949, + -31971,-31993,-32014,-32036,-32057,-32077,-32098,-32118, + -32137,-32157,-32176,-32195,-32213,-32232,-32250,-32267, + -32285,-32302,-32318,-32335,-32351,-32367,-32382,-32397, + -32412,-32427,-32441,-32455,-32469,-32482,-32495,-32508, + -32521,-32533,-32545,-32556,-32567,-32578,-32589,-32599, + -32609,-32619,-32628,-32637,-32646,-32655,-32663,-32671, + -32678,-32685,-32692,-32699,-32705,-32711,-32717,-32722, + -32728,-32732,-32737,-32741,-32745,-32748,-32752,-32755, + -32757,-32759,-32761,-32763,-32765,-32766,-32766,-32767, + -32767,-32767,-32766,-32766,-32765,-32763,-32761,-32759, + -32757,-32755,-32752,-32748,-32745,-32741,-32737,-32732, + -32728,-32722,-32717,-32711,-32705,-32699,-32692,-32685, + -32678,-32671,-32663,-32655,-32646,-32637,-32628,-32619, + -32609,-32599,-32589,-32578,-32567,-32556,-32545,-32533, + -32521,-32508,-32495,-32482,-32469,-32455,-32441,-32427, + -32412,-32397,-32382,-32367,-32351,-32335,-32318,-32302, + -32285,-32267,-32250,-32232,-32213,-32195,-32176,-32157, + -32137,-32118,-32098,-32077,-32057,-32036,-32014,-31993, + -31971,-31949,-31926,-31903,-31880,-31857,-31833,-31809, + -31785,-31760,-31736,-31710,-31685,-31659,-31633,-31607, + -31580,-31553,-31526,-31498,-31470,-31442,-31414,-31385, + -31356,-31327,-31297,-31267,-31237,-31206,-31176,-31145, + -31113,-31082,-31050,-31017,-30985,-30952,-30919,-30885, + -30852,-30818,-30783,-30749,-30714,-30679,-30643,-30607, + -30571,-30535,-30498,-30462,-30424,-30387,-30349,-30311, + -30273,-30234,-30195,-30156,-30117,-30077,-30037,-29997, + -29956,-29915,-29874,-29832,-29791,-29749,-29706,-29664, + -29621,-29578,-29534,-29491,-29447,-29403,-29358,-29313, + -29268,-29223,-29177,-29131,-29085,-29039,-28992,-28945, + -28898,-28850,-28803,-28755,-28706,-28658,-28609,-28560, + -28510,-28460,-28411,-28360,-28310,-28259,-28208,-28157, + -28105,-28053,-28001,-27949,-27896,-27843,-27790,-27737, + -27683,-27629,-27575,-27521,-27466,-27411,-27356,-27300, + -27245,-27189,-27133,-27076,-27019,-26962,-26905,-26848, + -26790,-26732,-26674,-26615,-26556,-26497,-26438,-26378, + -26319,-26259,-26198,-26138,-26077,-26016,-25955,-25893, + -25832,-25770,-25708,-25645,-25582,-25519,-25456,-25393, + -25329,-25265,-25201,-25137,-25072,-25007,-24942,-24877, + -24811,-24746,-24680,-24613,-24547,-24480,-24413,-24346, + -24279,-24211,-24143,-24075,-24007,-23938,-23870,-23801, + -23731,-23662,-23592,-23522,-23452,-23382,-23311,-23241, + -23170,-23099,-23027,-22956,-22884,-22812,-22739,-22667, + -22594,-22521,-22448,-22375,-22301,-22227,-22154,-22079, + -22005,-21930,-21856,-21781,-21705,-21630,-21554,-21479, + -21403,-21326,-21250,-21173,-21096,-21019,-20942,-20865, + -20787,-20709,-20631,-20553,-20475,-20396,-20317,-20238, + -20159,-20080,-20000,-19921,-19841,-19761,-19680,-19600, + -19519,-19438,-19357,-19276,-19195,-19113,-19032,-18950, + -18868,-18785,-18703,-18620,-18537,-18454,-18371,-18288, + -18204,-18121,-18037,-17953,-17869,-17784,-17700,-17615, + -17530,-17445,-17360,-17275,-17189,-17104,-17018,-16932, + -16846,-16759,-16673,-16586,-16499,-16413,-16325,-16238, + -16151,-16063,-15976,-15888,-15800,-15712,-15623,-15535, + -15446,-15358,-15269,-15180,-15090,-15001,-14912,-14822, + -14732,-14643,-14553,-14462,-14372,-14282,-14191,-14101, + -14010,-13919,-13828,-13736,-13645,-13554,-13462,-13370, + -13279,-13187,-13094,-13002,-12910,-12817,-12725,-12632, + -12539,-12446,-12353,-12260,-12167,-12074,-11980,-11886, + -11793,-11699,-11605,-11511,-11417,-11322,-11228,-11133, + -11039,-10944,-10849,-10754,-10659,-10564,-10469,-10374, + -10278,-10183,-10087,-9992,-9896,-9800,-9704,-9608, + -9512,-9416,-9319,-9223,-9126,-9030,-8933,-8836, + -8739,-8642,-8545,-8448,-8351,-8254,-8157,-8059, + -7962,-7864,-7767,-7669,-7571,-7473,-7375,-7277, + -7179,-7081,-6983,-6885,-6786,-6688,-6590,-6491, + -6393,-6294,-6195,-6096,-5998,-5899,-5800,-5701, + -5602,-5503,-5404,-5305,-5205,-5106,-5007,-4907, + -4808,-4708,-4609,-4509,-4410,-4310,-4210,-4111, + -4011,-3911,-3811,-3712,-3612,-3512,-3412,-3312, + -3212,-3112,-3012,-2911,-2811,-2711,-2611,-2511, + -2410,-2310,-2210,-2110,-2009,-1909,-1809,-1708, + -1608,-1507,-1407,-1307,-1206,-1106,-1005,-905, + -804,-704,-603,-503,-402,-302,-201,-101 +}; +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ima_tables.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ima_tables.c new file mode 100755 index 0000000..b03b4d4 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ima_tables.c @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ima_tables.c + * + * Contents and purpose: + * Contains the constant tables for IMA encode/decode + * + * Copyright (c) 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 760 $ + * $Date: 2007-07-17 23:09:36 -0700 (Tue, 17 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" + +/*---------------------------------------------------------------------------- + * ADPCM decode tables + *---------------------------------------------------------------------------- +*/ +const EAS_I16 imaIndexTable[16] = +{ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +const EAS_I16 imaStepSizeTable[89] = +{ + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 +}; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imaadpcm.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imaadpcm.c new file mode 100755 index 0000000..41280b5 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imaadpcm.c @@ -0,0 +1,368 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imaadpcm.c + * + * Contents and purpose: + * Implements the IMA ADPCM decoder + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_host.h" +#include "eas_pcm.h" +#include "eas_math.h" +#include "eas_report.h" + +// #define _DEBUG_IMA_ADPCM_LOCATE + +/*---------------------------------------------------------------------------- + * externs + *---------------------------------------------------------------------------- +*/ +extern const EAS_I16 imaIndexTable[]; +extern const EAS_I16 imaStepSizeTable[]; + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble); +static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); + +/*---------------------------------------------------------------------------- + * IMA ADPCM Decoder interface + *---------------------------------------------------------------------------- +*/ +const S_DECODER_INTERFACE IMADecoder = +{ + IMADecoderInit, + IMADecoderSample, + IMADecoderLocate +}; + +/*---------------------------------------------------------------------------- + * IMADecoderInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the IMA ADPCM decoder + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + pState->decoderL.step = 0; + pState->decoderR.step = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMADecoderSample() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes an IMA ADPCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + EAS_RESULT result; + EAS_I16 sTemp; + + /* if high nibble, decode */ + if (pState->hiNibble) + { + IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte >> 4)); + pState->hiNibble = EAS_FALSE; + } + + /* low nibble, need to fetch another byte */ + else + { + /* check for loop */ + if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) + { + /* seek to start of loop */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) + return result; + pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; + pState->blockCount = 0; + pState->flags &= ~PCM_FLAGS_EMPTY; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMADecoderSample: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } + } + + /* if start of block, fetch new predictor and step index */ + if ((pState->blockSize != 0) && (pState->blockCount == 0) && (pState->bytesLeft != 0)) + { + + /* get predicted sample for left channel */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Predictor: Was %d, now %d\n", pState->decoderL.acc, sTemp); */ } +#endif + pState->decoderL.acc = pState->decoderL.x1 = sTemp; + + /* get step index for left channel - upper 8 bits are reserved */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderL.step, sTemp); */ } +#endif + pState->decoderL.step = sTemp & 0xff; + + if (pState->flags & PCM_FLAGS_STEREO) + { + /* get predicted sample for right channel */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->decoderR.acc = pState->decoderR.x1 = sTemp; + + /* get step index for right channel - upper 8 bits are reserved */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderR.step, sTemp); */ } +#endif + pState->decoderR.step = sTemp & 0xff; + + pState->blockCount = pState->blockSize - 8; + pState->bytesLeft -= 8; + } + else + { + pState->blockCount = pState->blockSize - 4; + pState->bytesLeft -= 4; + } + } + else + { + + /* get another ADPCM data pair */ + if (pState->bytesLeft) + { + + if ((result = EAS_HWGetByte(pEASData->hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* decode the low nibble */ + pState->bytesLeft--; + pState->blockCount--; + IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte & 0x0f)); + + if (pState->flags & PCM_FLAGS_STEREO) + IMADecoderADPCM(&pState->decoderR, (EAS_U8)(pState->srcByte >> 4)); + else + pState->hiNibble = EAS_TRUE; + } + + /* out of ADPCM data, generate enough samples to fill buffer */ + else + { + pState->decoderL.x1 = pState->decoderL.x0; + pState->decoderR.x1 = pState->decoderR.x0; + } + } + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMADecoderADPCM() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes an IMA ADPCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble) +{ + EAS_INT delta; + EAS_INT stepSize; + + /* get stepsize from table */ + stepSize = imaStepSizeTable[pState->step]; + + /* delta = (abs(delta) + 0.5) * step / 4 */ + delta = 0; + if (nibble & 4) + delta += stepSize; + + if (nibble & 2) + /*lint -e{702} use shift for performance */ + delta += stepSize >> 1; + + if (nibble & 1) + /*lint -e{702} use shift for performance */ + delta += stepSize >> 2; + + /*lint -e{702} use shift for performance */ + delta += stepSize >> 3; + + /* integrate the delta */ + if (nibble & 8) + pState->acc -= delta; + else + pState->acc += delta; + + /* saturate */ + if (pState->acc > 32767) + pState->acc = 32767; + if (pState->acc < -32768) + pState->acc = -32768; + pState->x1 = (EAS_PCM) pState->acc; + + /* compute new step size */ + pState->step += imaIndexTable[nibble]; + if (pState->step < 0) + pState->step = 0; + if (pState->step > 88) + pState->step = 88; + +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "In=%u, Pred=%d, Step=%d\n", nibble, pState->acc, imaStepSizeTable[pState->step]); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * IMADecoderLocate() + *---------------------------------------------------------------------------- + * Locate in an IMA ADPCM stream + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_I32 samplesPerBlock; + EAS_I32 secs, msecs; + + /* no need to calculate if time is zero */ + if (time == 0) + temp = 0; + + /* not zero */ + else + { + + /* can't seek if not a blocked file */ + if (pState->blockSize == 0) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* calculate number of samples per block */ + if (pState->flags & PCM_FLAGS_STEREO) + samplesPerBlock = pState->blockSize - 7; + else + samplesPerBlock = (pState->blockSize << 1) - 7; + + /* break down into secs and msecs */ + secs = time / 1000; + msecs = time - (secs * 1000); + + /* calculate sample number fraction from msecs */ + temp = (msecs * pState->sampleRate); + temp = (temp >> 10) + ((temp * 49) >> 21); + + /* add integer sample count */ + temp += secs * pState->sampleRate; + +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000006 , time, temp); +#endif + + /* for looped samples, calculate position in the loop */ + if ((temp > pState->byteCount) && (pState->loopSamples != 0)) + { + EAS_I32 numBlocks; + EAS_I32 samplesPerLoop; + EAS_I32 samplesInLastBlock; + + numBlocks = (EAS_I32) (pState->loopStart / pState->blockSize); + samplesInLastBlock = (EAS_I32) pState->loopStart - (numBlocks * pState->blockSize); + if (samplesInLastBlock) + { + if (pState->flags & PCM_FLAGS_STEREO) + samplesInLastBlock = samplesInLastBlock - 7; + else + /*lint -e{703} use shift for performance */ + samplesInLastBlock = (samplesInLastBlock << 1) - 7; + } + samplesPerLoop = numBlocks * samplesPerBlock + samplesInLastBlock; + temp = temp % samplesPerLoop; +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000007 , numBlocks, samplesPerLoop, samplesInLastBlock, temp); +#endif + } + + /* find start of block for requested sample */ + temp = (temp / samplesPerBlock) * pState->blockSize; +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000008 , temp); +#endif + + } + + /* seek to new location */ + if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000009 , pState->bytesLeft); +#endif + + /* reset state */ + pState->blockCount = 0; + pState->hiNibble = EAS_FALSE; + if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) + pState->state = EAS_STATE_READY; + + return EAS_SUCCESS; +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelody.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelody.c new file mode 100755 index 0000000..698c7df --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelody.c @@ -0,0 +1,1738 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelody.c + * + * Contents and purpose: + * iMelody parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 797 $ + * $Date: 2007-08-01 00:15:56 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* lint doesn't like the way some string.h files look */ +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#endif + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_imelodydata.h" +#include "eas_ctype.h" + +// #define _DEBUG_IMELODY + +/* increase gain for mono ringtones */ +#define IMELODY_GAIN_OFFSET 8 + +/* length of 32nd note in 1/256ths of a msec for 120 BPM tempo */ +#define DEFAULT_TICK_CONV 16000 +#define TICK_CONVERT 1920000 + +/* default channel and program for iMelody playback */ +#define IMELODY_CHANNEL 0 +#define IMELODY_PROGRAM 80 +#define IMELODY_VEL_MUL 4 +#define IMELODY_VEL_OFS 67 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +static const char* const tokens[] = +{ + "BEGIN:IMELODY", + "VERSION:", + "FORMAT:CLASS", + "NAME:", + "COMPOSER:", + "BEAT:", + "STYLE:", + "VOLUME:", + "MELODY:", + "END:IMELODY" +}; + +/* ledon or ledoff */ +static const char ledStr[] = "edo"; + +/* vibeon or vibeoff */ +static const char vibeStr[] = "ibeo"; + +/* backon or backoff */ +static const char backStr[] = "cko"; + +typedef enum +{ + TOKEN_BEGIN, + TOKEN_VERSION, + TOKEN_FORMAT, + TOKEN_NAME, + TOKEN_COMPOSER, + TOKEN_BEAT, + TOKEN_STYLE, + TOKEN_VOLUME, + TOKEN_MELODY, + TOKEN_END, + TOKEN_INVALID +} ENUM_IMELODY_TOKENS; + +/* lookup table for note values */ +static const EAS_I8 noteTable[] = { 9, 11, 0, 2, 4, 5, 7 }; + +/* inline functions */ +#ifdef _DEBUG_IMELODY +static void PutBackChar (S_IMELODY_DATA *pData) +{ + if (pData->index) + pData->index--; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "PutBackChar '%c'\n", pData->buffer[pData->index]); */ } +} +#else +EAS_INLINE void PutBackChar (S_IMELODY_DATA *pData) { if (pData->index) pData->index--; } +#endif + + +/* local prototypes */ +static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode); +static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration); +static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader); +static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader); +static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData); +static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader); +static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine); +static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex); + + +/*---------------------------------------------------------------------------- + * + * EAS_iMelody_Parser + * + * This structure contains the functional interface for the iMelody parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_iMelody_Parser = +{ + IMY_CheckFileType, + IMY_Prepare, + IMY_Time, + IMY_Event, + IMY_State, + IMY_Close, + IMY_Reset, + IMY_Pause, + IMY_Resume, + NULL, + IMY_SetData, + IMY_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * IMY_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_IMELODY_DATA* pData; + EAS_I8 buffer[MAX_LINE_SIZE+1]; + EAS_U8 index; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_CheckFileType\n"); */ } +#endif + + /* read the first line of the file */ + *ppHandle = NULL; + if (IMY_ReadLine(pEASData->hwInstData, fileHandle, buffer, NULL) != EAS_SUCCESS) + return EAS_SUCCESS; + + /* check for header string */ + if (IMY_ParseLine(buffer, &index) == TOKEN_BEGIN) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_IMELODY_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_IMELODY_DATA)); + if (!pData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pData, 0, sizeof(S_IMELODY_DATA)); + + /* initialize */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_ERROR; + pData->state = EAS_STATE_OPEN; + + /* return a pointer to the instance data */ + *ppHandle = pData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_Prepare\n"); */ } +#endif + + /* check for valid state */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + /* parse the header */ + if ((result = IMY_ParseHeader(pEASData, pData)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Prepare: state set to EAS_STATE_READY\n"); */ } +#endif + + pData ->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + EAS_I8 c; + EAS_BOOL eof; + EAS_INT temp; + + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: Reset\n"); */ } +#endif + /* set program to square lead */ + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, IMELODY_PROGRAM); + + /* set channel volume to max */ + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Stopping note %d\n", pData->note); */ } +#endif + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* parse the next event */ + eof = EAS_FALSE; + while (!eof) + { + + /* get next character */ + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + + switch (c) + { + /* start repeat */ + case '(': + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter repeat section\n", c); */ } +#endif + + if (pData->repeatOffset < 0) + { + pData->repeatOffset = pData->startLine + (EAS_I32) pData->index; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat offset = %d\n", pData->repeatOffset); */ } +#endif + } + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring nested repeat section\n"); */ } + break; + + /* end repeat */ + case ')': + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "End repeat section, repeat offset = %d\n", pData->repeatOffset); */ } +#endif + /* ignore invalid repeats */ + if (pData->repeatCount >= 0) + { + + /* decrement repeat count (repeatCount == 0 means infinite loop) */ + if (pData->repeatCount > 0) + { + if (--pData->repeatCount == 0) + { + pData->repeatCount = -1; +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat loop complete\n"); */ } +#endif + } + } + +//2 TEMPORARY FIX: If locating, don't do infinite loops. +//3 We need a different mode for metadata parsing where we don't loop at all + if ((parserMode == eParserModePlay) || (pData->repeatCount != 0)) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Rewinding file for repeat\n"); */ } +#endif + /* rewind to start of loop */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS) + return result; + IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine); + pData->index = 0; + + /* if last loop, prevent future loops */ + if (pData->repeatCount == -1) + pData->repeatOffset = -1; + } + } + break; + + /* repeat count */ + case '@': + if (!IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_FALSE)) + eof = EAS_TRUE; + else if (pData->repeatOffset > 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat count = %dt", pData->repeatCount); */ } +#endif + if (pData->repeatCount < 0) + pData->repeatCount = (EAS_I16) temp; + } + break; + + /* volume */ + case 'V': + if (!IMY_GetVolume(pEASData->hwInstData, pData, EAS_FALSE)) + eof = EAS_TRUE; + break; + + /* flat */ + case '&': + pData->noteModifier = -1; + break; + + /* sharp */ + case '#': + pData->noteModifier = +1; + break; + + /* octave */ + case '*': + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (IsDigit(c)) + pData->octave = (EAS_U8) ((c - '0' + 1) * 12); + else if (!c) + eof = EAS_TRUE; + break; + + /* ledon or ledoff */ + case 'l': + if (!IMY_GetLEDState(pEASData, pData)) + eof = EAS_TRUE; + break; + + /* vibeon or vibeoff */ + case 'v': + if (!IMY_GetVibeState(pEASData, pData)) + eof = EAS_TRUE; + break; + + /* either a B note or backon or backoff */ + case 'b': + if (IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE) == 'a') + { + if (!IMY_GetBackState(pEASData, pData)) + eof = EAS_TRUE; + } + else + { + PutBackChar(pData); + if (IMY_PlayNote(pEASData, pData, c, parserMode)) + return EAS_SUCCESS; + eof = EAS_TRUE; + } + break; + + /* rest */ + case 'r': + case 'R': + if (IMY_PlayRest(pEASData, pData)) + return EAS_SUCCESS; + eof = EAS_TRUE; + break; + + /* EOF */ + case 0: +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: end of iMelody file detected\n"); */ } +#endif + eof = EAS_TRUE; + break; + + /* must be a note */ + default: + c = ToLower(c); + if ((c >= 'a') && (c <= 'g')) + { + if (IMY_PlayNote(pEASData, pData, c, parserMode)) + return EAS_SUCCESS; + eof = EAS_TRUE; + } + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unexpected character '%c' [0x%02x]\n", c, c); */ } + break; + } + } + + /* handle EOF */ +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: state set to EAS_STATE_STOPPING\n"); */ } +#endif + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_IMELODY_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_IMELODY_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + { + pData->state = EAS_STATE_STOPPED; +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_STOPPED\n"); */ } +#endif + } + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_PAUSED\n"); */ } +#endif + pData->state = EAS_STATE_PAUSED; + } + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Close: close file\n"); */ } +#endif + + pData = (S_IMELODY_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: reset file\n"); */ } +#endif + pData = (S_IMELODY_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + + /* reset time to zero */ + pData->time = 0; + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + if ((result = IMY_ParseHeader (pEASData, pData)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: state set to EAS_STATE_ERROR\n"); */ } +#endif + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA *pData; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Pause: pause file\n"); */ } +#endif + + /* can't pause a stopped stream */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA *pData; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Resume: resume file\n"); */ } +#endif + + /* can't resume a stopped stream */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Adjust tempo relative to song tempo + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pInstData - pointer to iMelody instance data + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return the file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pInstData - pointer to iMelody instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + + switch (param) + { + /* return file type as iMelody */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_IMELODY; + break; + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = IMELODY_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_PlayNote() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode) +{ + EAS_I32 duration; + EAS_U8 velocity; + + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: start note %d\n", note); */ } +#endif + + /* get the duration */ + if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration)) + return EAS_FALSE; + + /* save note value */ + pData->note = (EAS_U8) (pData->octave + noteTable[note - 'a'] + pData->noteModifier); + velocity = (EAS_U8) (pData->volume ? pData->volume * IMELODY_VEL_MUL + IMELODY_VEL_OFS : 0); + + /* start note only if in play mode */ + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, velocity); + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: Start note %d, duration %d\n", pData->note, duration); */ } +#endif + + /* determine note length */ + switch (pData->style) + { + case 0: + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 4; + break; + case 1: + pData->restTicks = 0; + break; + case 2: + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 1; + break; + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "IMY_PlayNote: Note style out of range: %d\n", pData->style); */ } + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 4; + break; + } + + /* next event is at end of this note */ + pData->time += duration - pData->restTicks; + + /* reset the flat/sharp modifier */ + pData->noteModifier = 0; + + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_PlayRest() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I32 duration; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_PlayRest]n"); */ } +#endif + + /* get the duration */ + if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration)) + return EAS_FALSE; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayRest: note duration %d\n", duration); */ } +#endif + + /* next event is at end of this note */ + pData->time += duration; + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetDuration() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ + +static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration) +{ + EAS_I32 duration; + EAS_I8 c; + + /* get the duration */ + *pDuration = 0; + c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + if ((c < '0') || (c > '5')) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetDuration: error in duration '%c'\n", c); */ } +#endif + return EAS_FALSE; + } + + /* calculate total length of note */ + duration = pData->tick * (1 << ('5' - c)); + + /* check for duration modifier */ + c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE); + if (c) + { + if (c == '.') + /*lint -e{704} shift for performance */ + duration += duration >> 1; + else if (c == ':') + /*lint -e{704} shift for performance */ + duration += (duration >> 1) + (duration >> 2); + else if (c == ';') + /*lint -e{704} shift for performance */ + duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT; + else + PutBackChar(pData); + } + + *pDuration = duration; + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetLEDState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetLEDState\n"); */ } +#endif + + for (i = 0; i < 5; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 3: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED on\n"); */ } +#endif + EAS_HWLED(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 4: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED off\n"); */ } +#endif + EAS_HWLED(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != ledStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetVibeState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVibeState\n"); */ } +#endif + + for (i = 0; i < 6; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 4: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate on\n"); */ } +#endif + EAS_HWVibrate(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 5: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate off\n"); */ } +#endif + EAS_HWVibrate(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != vibeStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetBackState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetBackState\n"); */ } +#endif + + for (i = 0; i < 5; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 3: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight on\n"); */ } +#endif + EAS_HWBackLight(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 4: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight off\n"); */ } +#endif + EAS_HWBackLight(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != backStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader) +{ + EAS_INT temp; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVolume\n"); */ } +#endif + + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (c == '+') + { + if (pData->volume < 15) + pData->volume++; + return EAS_TRUE; + } + else if (c == '-') + { + if (pData->volume > 0) + pData->volume--; + return EAS_TRUE; + } + else if (IsDigit(c)) + temp = c - '0'; + else + return EAS_FALSE; + + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (IsDigit(c)) + temp = temp * 10 + c - '0'; + else if (c) + PutBackChar(pData); + if ((temp >= 0) && (temp <= 15)) + { + if (inHeader && (temp == 0)) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring V0 encountered in header\n"); */ } + else + pData->volume = (EAS_U8) temp; + } + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetNumber() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader) +{ + EAS_BOOL ok; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetNumber\n"); */ } +#endif + + *temp = 0; + ok = EAS_FALSE; + for (;;) + { + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (IsDigit(c)) + { + *temp = *temp * 10 + c - '0'; + ok = EAS_TRUE; + } + else + { + if (c) + PutBackChar(pData); + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNumber: value %d\n", *temp); */ } +#endif + + return ok; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_GetVersion() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVersion (S_IMELODY_DATA *pData, EAS_INT *pVersion) +{ + EAS_I8 c; + EAS_INT temp; + EAS_INT version; + + version = temp = 0; + for (;;) + { + c = pData->buffer[pData->index++]; + if ((c == 0) || (c == '.')) + { + /*lint -e{701} use shift for performance */ + version = (version << 8) + temp; + if (c == 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVersion: version 0x%04x\n", version); */ } +#endif + + *pVersion = version; + return EAS_TRUE; + } + temp = 0; + } + else if (IsDigit(c)) + temp = (temp * 10) + c - '0'; + } +} + +/*---------------------------------------------------------------------------- + * IMY_MetaData() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void IMY_MetaData (S_IMELODY_DATA *pData, E_EAS_METADATA_TYPE metaType, EAS_I8 *buffer) +{ + EAS_I32 len; + + /* check for callback */ + if (!pData->metadata.callback) + return; + + /* copy data to host buffer */ + len = (EAS_I32) strlen((char*) buffer); + if (len >pData->metadata.bufferSize) + len = pData->metadata.bufferSize; + strncpy((char*) pData->metadata.buffer, (char*) buffer, (size_t) len); + pData->metadata.buffer[len] = 0; + + /* callback to host */ + pData->metadata.callback(metaType, pData->metadata.buffer, pData->metadata.pUserData); +} + +/*---------------------------------------------------------------------------- + * IMY_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData) +{ + EAS_RESULT result; + EAS_INT token; + EAS_INT temp; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_ParseHeader\n"); */ } +#endif + + /* initialize some defaults */ + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->note = 0; + pData->noteModifier = 0; + pData ->restTicks = 0; + pData->volume = 7; + pData->octave = 60; + pData->repeatOffset = -1; + pData->repeatCount = -1; + pData->style = 0; + + /* force the read of the first line */ + pData->index = 1; + + /* read data until we get to melody */ + for (;;) + { + /* read a line from the file and parse the token */ + if (pData->index != 0) + { + if ((result = IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine)) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: IMY_ReadLine returned %d\n", result); */ } +#endif + return result; + } + } + token = IMY_ParseLine(pData->buffer, &pData->index); + + switch (token) + { + /* ignore these valid tokens */ + case TOKEN_BEGIN: + break; + + case TOKEN_FORMAT: + if (!IMY_GetVersion(pData, &temp)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid FORMAT field '%s'\n", pData->buffer); */ } + return EAS_ERROR_FILE_FORMAT; + } + if ((temp != 0x0100) && (temp != 0x0200)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported FORMAT %02x\n", temp); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + break; + + case TOKEN_VERSION: + if (!IMY_GetVersion(pData, &temp)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid VERSION field '%s'\n", pData->buffer); */ } + return EAS_ERROR_FILE_FORMAT; + } + if ((temp != 0x0100) && (temp != 0x0102)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported VERSION %02x\n", temp); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + break; + + case TOKEN_NAME: + IMY_MetaData(pData, EAS_METADATA_TITLE, pData->buffer + pData->index); + break; + + case TOKEN_COMPOSER: + IMY_MetaData(pData, EAS_METADATA_AUTHOR, pData->buffer + pData->index); + break; + + /* handle beat */ + case TOKEN_BEAT: + IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_TRUE); + if ((temp >= 25) && (temp <= 900)) + pData->tick = TICK_CONVERT / temp; + break; + + /* handle style */ + case TOKEN_STYLE: + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if (c == 'S') + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if ((c >= '0') && (c <= '2')) + pData->style = (EAS_U8) (c - '0'); + else + { + PutBackChar(pData); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in style command: %s\n", pData->buffer); */ } + } + break; + + /* handle volume */ + case TOKEN_VOLUME: + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if (c != 'V') + { + PutBackChar(pData); + if (!IsDigit(c)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in volume command: %s\n", pData->buffer); */ } + break; + } + } + IMY_GetVolume(pEASData->hwInstData, pData, EAS_TRUE); + break; + + case TOKEN_MELODY: +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Header successfully parsed\n"); */ } +#endif + return EAS_SUCCESS; + + case TOKEN_END: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unexpected END:IMELODY encountered\n"); */ } + return EAS_ERROR_FILE_FORMAT; + + default: + /* force a read of the next line */ + pData->index = 1; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized token in iMelody file: %s\n", pData->buffer); */ } + break; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_GetNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader) +{ + EAS_I8 c; + EAS_U8 index; + + for (;;) + { + /* get next character */ + c = pData->buffer[pData->index++]; + + /* buffer empty, read more */ + if (!c) + { + /* don't read the next line in the header */ + if (inHeader) + return 0; + + pData->index = 0; + pData->buffer[0] = 0; + if (IMY_ReadLine(hwInstData, pData->fileHandle, pData->buffer, &pData->startLine) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: EOF\n"); */ } +#endif + return 0; + } + + /* check for END:IMELODY token */ + if (IMY_ParseLine(pData->buffer, &index) == TOKEN_END) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: found END:IMELODY\n"); */ } +#endif + pData->buffer[0] = 0; + return 0; + } + continue; + } + + /* ignore white space */ + if (!IsSpace(c)) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar returned '%c'\n", c); */ } +#endif + return c; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_ReadLine() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a line of input from the file, discarding the CR/LF + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine) +{ + EAS_RESULT result; + EAS_INT i; + EAS_I8 c; + + /* fetch current file position and save it */ + if (pStartLine != NULL) + { + if ((result = EAS_HWFilePos(hwInstData, fileHandle, pStartLine)) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: EAS_HWFilePos returned %d\n", result); */ } +#endif + return result; + } + } + + buffer[0] = 0; + for (i = 0; i < MAX_LINE_SIZE; ) + { + if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) + { + if ((result == EAS_EOF) && (i > 0)) + break; + return result; + } + + /* return on LF or end of data */ + if (c == '\n') + break; + + /* store characters in buffer */ + if (c != '\r') + buffer[i++] = c; + } + buffer[i] = 0; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ReadLine read %s\n", buffer); */ } +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_ParseLine() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex) +{ + EAS_INT i; + EAS_INT j; + + /* there's no strnicmp() in stdlib, so we have to roll our own */ + for (i = 0; i < TOKEN_INVALID; i++) + { + for (j = 0; ; j++) + { + /* end of token, must be a match */ + if (tokens[i][j] == 0) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine found token %d\n", i); */ } +#endif + *pIndex = (EAS_U8) j; + return i; + } + if (tokens[i][j] != ToUpper(buffer[j])) + break; + } + } +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine: no token found\n"); */ } +#endif + return TOKEN_INVALID; +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelodydata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelodydata.c new file mode 100755 index 0000000..9437e08 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelodydata.c @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelodydata.c + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_imelodydata.h" + +/*---------------------------------------------------------------------------- + * + * eas_iMelodyData + * + * Static memory allocation for iMelody parser + *---------------------------------------------------------------------------- +*/ +S_IMELODY_DATA eas_iMelodyData; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelodydata.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelodydata.h new file mode 100755 index 0000000..57c1ed0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_imelodydata.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelodydata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data declarations for the iMelody parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_IMELODYDATA_H +#define EAS_IMELODYDATA_H + +#include "eas_data.h" + +/* maximum line size as specified in iMelody V1.2 spec */ +#define MAX_LINE_SIZE 75 + +/*---------------------------------------------------------------------------- + * + * S_IMELODY_DATA + * + * This structure contains the state data for the iMelody parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* pointer to synth */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_I32 tickBase; /* basline length of 32nd note in 256th of a msec */ + EAS_I32 tick; /* actual length of 32nd note in 256th of a msec */ + EAS_I32 restTicks; /* ticks to rest after current note */ + EAS_I32 startLine; /* file offset at start of line (for repeats) */ + EAS_I32 repeatOffset; /* file offset to start of repeat section */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I16 repeatCount; /* repeat counter */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 style; /* from STYLE */ + EAS_U8 index; /* index into buffer */ + EAS_U8 octave; /* octave prefix */ + EAS_U8 volume; /* current volume */ + EAS_U8 note; /* MIDI note number */ + EAS_I8 noteModifier; /* sharp or flat */ + EAS_I8 buffer[MAX_LINE_SIZE+1]; /* buffer for ASCII data */ +} S_IMELODY_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_math.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_math.c new file mode 100755 index 0000000..dc85051 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_math.c @@ -0,0 +1,168 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_math.c + * + * Contents and purpose: + * Contains common math routines for the various audio engines. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 586 $ + * $Date: 2007-03-08 20:33:04 -0800 (Thu, 08 Mar 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas.h" +#include "eas_math.h" + +/* anything less than this converts to a fraction too small to represent in 32-bits */ +#define MIN_CENTS -18000 + +/*---------------------------------------------------------------------------- + * EAS_Calculate2toX() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate 2^x + * + * Inputs: + * nCents - measured in cents + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_Calculate2toX (EAS_I32 nCents) +{ + EAS_I32 nDents; + EAS_I32 nExponentInt, nExponentFrac; + EAS_I32 nTemp1, nTemp2; + EAS_I32 nResult; + + /* check for minimum value */ + if (nCents < MIN_CENTS) + return 0; + + /* for the time being, convert cents to dents */ + nDents = FMUL_15x15(nCents, CENTS_TO_DENTS); + + nExponentInt = GET_DENTS_INT_PART(nDents); + nExponentFrac = GET_DENTS_FRAC_PART(nDents); + + /* + implement 2^(fracPart) as a power series + */ + nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3); + nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1); + nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2); + + /* + implement 2^(intPart) as + a left shift for intPart >= 0 or + a left shift for intPart < 0 + */ + if (nExponentInt >= 0) + { + /* left shift for positive exponents */ + /*lint -e{703} */ + nResult = nTemp1 << nExponentInt; + } + else + { + /* right shift for negative exponents */ + nExponentInt = -nExponentInt; + nResult = nTemp1 >> nExponentInt; + } + + return nResult; +} + +/*---------------------------------------------------------------------------- + * EAS_LogToLinear16() + *---------------------------------------------------------------------------- + * Purpose: + * Transform log value to linear gain multiplier using piece-wise linear + * approximation + * + * Inputs: + * nGain - log scale value in 20.10 format. Even though gain is normally + * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate + * the need for saturation checking when combining gain values. + * + * Outputs: + * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain) +{ + EAS_INT nExp; + EAS_U16 nTemp; + + /* bias to positive */ + nGain += 32767; + + /* check for infinite attenuation */ + if (nGain < 0) + return 0; + + /* extract the exponent */ + nExp = 31 - (nGain >> 10); + + /* check for maximum output */ + if (nExp < 0) + return 0x7fff; + + /* extract mantissa and restore implied 1 bit */ + nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp); + + /* use shift to approximate power-of-2 operation */ + return nTemp; +} + +/*---------------------------------------------------------------------------- + * EAS_VolumeToGain() + *---------------------------------------------------------------------------- + * Purpose: + * Transform volume control in 1dB increments to gain multiplier + * + * Inputs: + * volume - 100 = 0dB, 99 = -1dB, 0 = -inf + * + * Outputs: + * Returns a 16-bit linear value + *---------------------------------------------------------------------------- +*/ +EAS_I16 EAS_VolumeToGain (EAS_INT volume) +{ + /* check for limits */ + if (volume <= 0) + return 0; + if (volume >= 100) + return 0x7fff; + + /*lint -e{702} use shift instead of division */ + return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1); +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_math.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_math.h new file mode 100755 index 0000000..f240b51 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_math.h @@ -0,0 +1,412 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_math.h + * + * Contents and purpose: + * Contains common math routines for the various audio engines. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 584 $ + * $Date: 2007-03-08 09:49:24 -0800 (Thu, 08 Mar 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MATH_H +#define _EAS_MATH_H + + +/** coefs for pan, generates sin, cos */ +#define COEFF_PAN_G2 -27146 /* -0.82842712474619 = 2 - 4/sqrt(2) */ +#define COEFF_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ + +/* +coefficients for approximating +2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3 +where x is a int.frac number representing number of octaves. +Actually, we approximate only the 2^(frac) using the power series +and implement the 2^(int) as a shift, so that +2^x == 2^(int.frac) == 2^(int) * 2^(fract) + == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int) + +The gn2toX.. were generated using a best fit for a 3rd +order polynomial, instead of taking the coefficients from +a truncated Taylor (or Maclaurin?) series. +*/ + +#define GN2_TO_X0 32768 /* 1 */ +#define GN2_TO_X1 22833 /* 0.696807861328125 */ +#define GN2_TO_X2 7344 /* 0.22412109375 */ +#define GN2_TO_X3 2588 /* 0.0789794921875 */ + +/*---------------------------------------------------------------------------- + * Fixed Point Math + *---------------------------------------------------------------------------- + * These macros are used for fixed point multiplies. If the processor + * supports fixed point multiplies, replace these macros with inline + * assembly code to improve performance. + *---------------------------------------------------------------------------- +*/ + +/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */ +#define FMUL_15x15(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b)) >> 15) + +/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */ +#define FMUL_7x7(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b) ) << 1) + +/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */ +#define FMUL_8x8(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b) ) >> 1) + +/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */ +#define FMUL_8x15(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)((a) << 7) * (EAS_I32)(b)) >> 15) + +/* macros for fractional phase accumulator */ +/* +Note: changed the _U32 to _I32 on 03/14/02. This should not +affect the phase calculations, and should allow us to reuse these +macros for other audio sample related math. +*/ +#define HARDWARE_BIT_WIDTH 32 + +#define NUM_PHASE_INT_BITS 1 +#define NUM_PHASE_FRAC_BITS 15 + +#define PHASE_FRAC_MASK (EAS_U32) ((0x1L << NUM_PHASE_FRAC_BITS) -1) + +#define GET_PHASE_INT_PART(x) (EAS_U32)((EAS_U32)(x) >> NUM_PHASE_FRAC_BITS) +#define GET_PHASE_FRAC_PART(x) (EAS_U32)((EAS_U32)(x) & PHASE_FRAC_MASK) + +#define DEFAULT_PHASE_FRAC 0 +#define DEFAULT_PHASE_INT 0 + +/* +Linear interpolation calculates: +output = (1-frac) * sample[n] + (frac) * sample[n+1] + +where conceptually 0 <= frac < 1 + +For a fixed point implementation, frac is actually an integer value +with an implied binary point one position to the left. The value of +one (unity) is given by PHASE_ONE +one half and one quarter are useful for 4-point linear interp. +*/ +#define PHASE_ONE (EAS_I32) (0x1L << NUM_PHASE_FRAC_BITS) + +/* + Multiply the signed audio sample by the unsigned fraction. +- a is the signed audio sample +- b is the unsigned fraction (cast to signed int as long as coef + uses (n-1) or less bits, where n == hardware bit width) +*/ +#define MULT_AUDIO_COEF(audio,coef) /*lint -e704 */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_PHASE_FRAC_BITS \ + ) \ + /* lint +704 */ + +/* wet / dry calculation macros */ +#define NUM_WET_DRY_FRAC_BITS 7 // 15 +#define NUM_WET_DRY_INT_BITS 9 // 1 + +/* define a 1.0 */ +#define WET_DRY_ONE (EAS_I32) ((0x1L << NUM_WET_DRY_FRAC_BITS)) +#define WET_DRY_MINUS_ONE (EAS_I32) (~WET_DRY_ONE) +#define WET_DRY_FULL_SCALE (EAS_I32) (WET_DRY_ONE - 1) + +#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_WET_DRY_FRAC_BITS \ + ) + +/* Envelope 1 (EG1) calculation macros */ +#define NUM_EG1_INT_BITS 1 +#define NUM_EG1_FRAC_BITS 15 + +/* the max positive gain used in the synth for EG1 */ +/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas +converter, otherwise, the values we read from the .eas file are bogus. */ +#define SYNTH_FULL_SCALE_EG1_GAIN (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS) -1) + +/* define a 1.0 */ +#define EG1_ONE (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS)) +#define EG1_MINUS_ONE (EAS_I32) (~SYNTH_FULL_SCALE_EG1_GAIN) + +#define EG1_HALF (EAS_I32) (EG1_ONE/2) +#define EG1_MINUS_HALF (EAS_I32) (EG1_MINUS_ONE/2) + +/* +We implement the EG1 using a linear gain value, which means that the +attack segment is handled by incrementing (adding) the linear gain. +However, EG1 treats the Decay, Sustain, and Release differently than +the Attack portion. For Decay, Sustain, and Release, the gain is +linear on dB scale, which is equivalent to exponential damping on +a linear scale. Because we use a linear gain for EG1, we implement +the Decay and Release as multiplication (instead of incrementing +as we did for the attack segment). +Therefore, we need the following macro to implement the multiplication +(i.e., exponential damping) during the Decay and Release segments of +the EG1 +*/ +#define MULT_EG1_EG1(gain,damping) /*lint -e(704) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \ + ) \ + >> NUM_EG1_FRAC_BITS \ + ) + +// Use the following macro specifically for the filter, when multiplying +// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow +// in certain conditions because we store b1 as a 1.15 value. +// Instead, we could store b1 as b1p (b1' == b1 "prime") where +// b1p == b1/2, thus ensuring no potential overflow for b1p because +// 0 <= |b1p| < 1 +// However, during the filter calculation, we must account for the fact +// that we are using b1p instead of b1, and thereby multiply by +// an extra factor of 2. Rather than multiply by an extra factor of 2, +// we can instead shift the result right by one less, hence the +// modified shift right value of (NUM_EG1_FRAC_BITS -1) +#define MULT_EG1_EG1_X2(gain,damping) /*lint -e(702) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \ + ) \ + >> (NUM_EG1_FRAC_BITS -1) \ + ) + +#define SATURATE_EG1(x) /*lint -e{734} saturation operation */ \ + ((EAS_I32)(x) > SYNTH_FULL_SCALE_EG1_GAIN) ? (SYNTH_FULL_SCALE_EG1_GAIN) : \ + ((EAS_I32)(x) < EG1_MINUS_ONE) ? (EG1_MINUS_ONE) : (x); + + +/* use "digital cents" == "dents" instead of cents */ +/* we coudl re-use the phase frac macros, but if we do, +we must change the phase macros to cast to _I32 instead of _U32, +because using a _U32 cast causes problems when shifting the exponent +for the 2^x calculation, because right shift a negative values MUST +be sign extended, or else the 2^x calculation is wrong */ + +/* use "digital cents" == "dents" instead of cents */ +#define NUM_DENTS_FRAC_BITS 12 +#define NUM_DENTS_INT_BITS (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS) + +#define DENTS_FRAC_MASK (EAS_I32) ((0x1L << NUM_DENTS_FRAC_BITS) -1) + +#define GET_DENTS_INT_PART(x) /*lint -e(704) */ \ + (EAS_I32)((EAS_I32)(x) >> NUM_DENTS_FRAC_BITS) + +#define GET_DENTS_FRAC_PART(x) (EAS_I32)((EAS_I32)(x) & DENTS_FRAC_MASK) + +#define DENTS_ONE (EAS_I32) (0x1L << NUM_DENTS_FRAC_BITS) + +/* use CENTS_TO_DENTS to convert a value in cents to dents */ +#define CENTS_TO_DENTS (EAS_I32) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L) \ + + +/* +For gain, the LFO generates a value that modulates in terms +of dB. However, we use a linear gain value, so we must convert +the LFO value in dB to a linear gain. Normally, we would use +linear gain = 10^x, where x = LFO value in dB / 20. +Instead, we implement 10^x using our 2^x approximation. +because + + 10^x = 2^(log2(10^x)) = 2^(x * log2(10)) + +so we need to multiply by log2(10) which is just a constant. +Ah, but just wait -- our 2^x actually doesn't exactly implement +2^x, but it actually assumes that the input is in cents, and within +the 2^x approximation converts its input from cents to octaves +by dividing its input by 1200. + +So, in order to convert the LFO gain value in dB to something +that our existing 2^x approximation can use, multiply the LFO gain +by log2(10) * 1200 / 20 + +The divide by 20 helps convert dB to linear gain, and we might +as well incorporate that operation into this conversion. +Of course, we need to keep some fractional bits, so multiply +the constant by NUM_EG1_FRAC_BITS +*/ + +/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */ +#if 0 +#define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */ + +#define DOUBLE_LFO_GAIN_TO_CENTS (double) \ + ( \ + (DOUBLE_LOG2_10) * \ + 1200.0 / \ + 20.0 \ + ) + +#define LFO_GAIN_TO_CENTS (EAS_I32) \ + ( \ + DOUBLE_LFO_GAIN_TO_CENTS * \ + (0x1L << NUM_EG1_FRAC_BITS) \ + ) +#endif + +#define LFO_GAIN_TO_CENTS (EAS_I32) (1671981156L >> (23 - NUM_EG1_FRAC_BITS)) + + +#define MULT_DENTS_COEF(dents,coef) /*lint -e704 */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(dents)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_DENTS_FRAC_BITS \ + ) \ + /* lint +e704 */ + +/* we use 16-bits in the PC per audio sample */ +#define BITS_PER_AUDIO_SAMPLE 16 + +/* we define 1 as 1.0 - 1 LSbit */ +#define DISTORTION_ONE (EAS_I32)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1) +#define DISTORTION_MINUS_ONE (EAS_I32)(~DISTORTION_ONE) + +/* drive coef is given as int.frac */ +#define NUM_DRIVE_COEF_INT_BITS 1 +#define NUM_DRIVE_COEF_FRAC_BITS 4 + +#define MULT_AUDIO_DRIVE(audio,drive) /*lint -e(702) */ \ + (EAS_I32) ( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(drive)) \ + ) \ + >> NUM_DRIVE_COEF_FRAC_BITS \ + ) + +#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) */ \ + (EAS_I32) ( \ + ( \ + ((EAS_I32)(audio1)) * ((EAS_I32)(audio2)) \ + ) \ + >> (BITS_PER_AUDIO_SAMPLE-1) \ + ) + +#define SATURATE(x) \ + ((((EAS_I32)(x)) > DISTORTION_ONE) ? (DISTORTION_ONE) : \ + (((EAS_I32)(x)) < DISTORTION_MINUS_ONE) ? (DISTORTION_MINUS_ONE) : ((EAS_I32)(x))); + + + +/*---------------------------------------------------------------------------- + * EAS_Calculate2toX() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate 2^x + * + * Inputs: + * nCents - measured in cents + * + * Outputs: + * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_Calculate2toX (EAS_I32 nCents); + +/*---------------------------------------------------------------------------- + * EAS_LogToLinear16() + *---------------------------------------------------------------------------- + * Purpose: + * Transform log value to linear gain multiplier using piece-wise linear + * approximation + * + * Inputs: + * nGain - log scale value in 20.10 format. Even though gain is normally + * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate + * the need for saturation checking when combining gain values. + * + * Outputs: + * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain); + +/*---------------------------------------------------------------------------- + * EAS_VolumeToGain() + *---------------------------------------------------------------------------- + * Purpose: + * Transform volume control in 1dB increments to gain multiplier + * + * Inputs: + * volume - 100 = 0dB, 99 = -1dB, 0 = -inf + * + * Outputs: + * Returns a 16-bit linear value + *---------------------------------------------------------------------------- +*/ +EAS_I16 EAS_VolumeToGain (EAS_INT volume); + +/*---------------------------------------------------------------------------- + * EAS_fsqrt() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the square root of a 32-bit fixed point value + * + * Inputs: + * n = value of interest + * + * Outputs: + * returns the square root of n + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_fsqrt (EAS_U32 n); + +/*---------------------------------------------------------------------------- + * EAS_flog2() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the log2 of a 32-bit fixed point value + * + * Inputs: + * n = value of interest + * + * Outputs: + * returns the log2 of n + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_flog2 (EAS_U32 n); + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midi.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midi.c new file mode 100755 index 0000000..2c0c793 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midi.c @@ -0,0 +1,569 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midi.c + * + * Contents and purpose: + * This file implements the MIDI stream parser. It is called by eas_smf.c to parse MIDI messages + * that are streamed out of the file. It can also parse live MIDI streams. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 794 $ + * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_miditypes.h" +#include "eas_midi.h" +#include "eas_vm_protos.h" +#include "eas_parser.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + + +/* state enumerations for ProcessSysExMessage */ +typedef enum +{ + eSysEx, + eSysExUnivNonRealTime, + eSysExUnivNrtTargetID, + eSysExGMControl, + eSysExUnivRealTime, + eSysExUnivRtTargetID, + eSysExDeviceControl, + eSysExMasterVolume, + eSysExMasterVolLSB, + eSysExSPMIDI, + eSysExSPMIDIchan, + eSysExSPMIDIMIP, + eSysExMfgID1, + eSysExMfgID2, + eSysExMfgID3, + eSysExEnhancer, + eSysExEnhancerSubID, + eSysExEnhancerFeedback1, + eSysExEnhancerFeedback2, + eSysExEnhancerDrive, + eSysExEnhancerWet, + eSysExEOX, + eSysExIgnore +} E_SYSEX_STATES; + +/* local prototypes */ +static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode); +static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode); + +/*---------------------------------------------------------------------------- + * EAS_InitMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the MIDI stream state for parsing. + * + * Inputs: + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream) +{ + pMIDIStream->byte3 = EAS_FALSE; + pMIDIStream->pending = EAS_FALSE; + pMIDIStream->runningStatus = 0; + pMIDIStream->status = 0; +} + +/*---------------------------------------------------------------------------- + * EAS_ParseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled) + * so the interface works equally well for both file and stream I/O. + * + * Inputs: + * c - character from MIDI stream + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) +{ + + /* check for new status byte */ + if (c & 0x80) + { + /* save new running status */ + if (c < 0xf8) + { + pMIDIStream->runningStatus = c; + pMIDIStream->byte3 = EAS_FALSE; + + /* deal with SysEx */ + if ((c == 0xf7) || (c == 0xf0)) + { + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode); + } + + /* inform the file parser that we're in the middle of a message */ + if ((c < 0xf4) || (c > 0xf6)) + pMIDIStream->pending = EAS_TRUE; + } + + /* real-time message - ignore it */ + return EAS_SUCCESS; + } + + /* 3rd byte of a 3-byte message? */ + if (pMIDIStream->byte3) + { + pMIDIStream->d2 = c; + pMIDIStream->byte3 = EAS_FALSE; + pMIDIStream->pending = EAS_FALSE; + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode); + } + + /* check for status received */ + if (pMIDIStream->runningStatus) + { + + /* save new status and data byte */ + pMIDIStream->status = pMIDIStream->runningStatus; + + /* check for 3-byte messages */ + if (pMIDIStream->status < 0xc0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_TRUE; + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + + /* check for 2-byte messages */ + if (pMIDIStream->status < 0xe0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_FALSE; + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode); + } + + /* check for more 3-bytes message */ + if (pMIDIStream->status < 0xf0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_TRUE; + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + + /* SysEx message? */ + if (pMIDIStream->status == 0xF0) + { + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode); + } + + /* remaining messages all clear running status */ + pMIDIStream->runningStatus = 0; + + /* F2 is 3-byte message */ + if (pMIDIStream->status == 0xf2) + { + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + } + + /* no status byte received, provide a warning, but we should be able to recover */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Received MIDI data without a valid status byte: %d\n",c); */ } + pMIDIStream->pending = EAS_FALSE; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * ProcessMIDIMessage() + *---------------------------------------------------------------------------- + * Purpose: + * This function processes a typical MIDI message. All of the data has been received, just need + * to take appropriate action. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode) +{ + EAS_U8 channel; + + channel = pMIDIStream->status & 0x0f; + switch (pMIDIStream->status & 0xf0) + { + case 0x80: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode < eParserModeMute) + VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + break; + + case 0x90: + if (pMIDIStream->d2) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOn: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + pMIDIStream->flags |= MIDI_FLAG_FIRST_NOTE; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + } + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode < eParserModeMute) + VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + } + break; + + case 0xa0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PolyPres: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + break; + + case 0xb0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Control: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode < eParserModeMute) + VMControlChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); +#ifdef JET_INTERFACE + if (pMIDIStream->jetData & MIDI_FLAGS_JET_CB) + { + JET_Event(pEASData, pMIDIStream->jetData & (JET_EVENT_SEG_MASK | JET_EVENT_TRACK_MASK), + channel, pMIDIStream->d1, pMIDIStream->d2); + } +#endif + break; + + case 0xc0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Program: %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1); */ } + if (parserMode < eParserModeMute) + VMProgramChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1); + break; + + case 0xd0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"ChanPres: %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1); */ } + if (parserMode < eParserModeMute) + VMChannelPressure(pSynth, channel, pMIDIStream->d1); + break; + + case 0xe0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PBend: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode < eParserModeMute) + VMPitchBend(pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Unknown: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * ProcessSysExMessage() + *---------------------------------------------------------------------------- + * Purpose: + * Process a SysEx character byte from the MIDI stream. Since we cannot + * simply wait for the next character to arrive, we are forced to save + * state after each character. It would be easier to parse at the file + * level, but then we lose the nice feature of being able to support + * these messages in a real-time MIDI stream. + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * c - character to be processed + * locating - if true, the sequencer is relocating to a new position + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * These are the SysEx messages we can receive: + * + * SysEx messages + * { f0 7e 7f 09 01 f7 } GM 1 On + * { f0 7e 7f 09 02 f7 } GM 1/2 Off + * { f0 7e 7f 09 03 f7 } GM 2 On + * { f0 7f 7f 04 01 lsb msb } Master Volume + * { f0 7f 7f 0b 01 ch mip [ch mip ...] f7 } SP-MIDI + * { f0 00 01 3a 04 01 fdbk1 fdbk2 drive wet dry f7 } Enhancer + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) +{ + + /* check for start byte */ + if (c == 0xf0) + { + pMIDIStream->sysExState = eSysEx; + } + /* check for end byte */ + else if (c == 0xf7) + { + /* if this was a MIP message, update the MIP table */ + if ((pMIDIStream->sysExState == eSysExSPMIDIchan) && (parserMode != eParserModeMetaData)) + VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); + pMIDIStream->sysExState = eSysExIgnore; + } + + /* process SysEx message */ + else + { + switch (pMIDIStream->sysExState) + { + case eSysEx: + + /* first byte, determine message class */ + switch (c) + { + case 0x7e: + pMIDIStream->sysExState = eSysExUnivNonRealTime; + break; + case 0x7f: + pMIDIStream->sysExState = eSysExUnivRealTime; + break; + case 0x00: + pMIDIStream->sysExState = eSysExMfgID1; + break; + default: + pMIDIStream->sysExState = eSysExIgnore; + break; + } + break; + + /* process GM message */ + case eSysExUnivNonRealTime: + if (c == 0x7f) + pMIDIStream->sysExState = eSysExUnivNrtTargetID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExUnivNrtTargetID: + if (c == 0x09) + pMIDIStream->sysExState = eSysExGMControl; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExGMControl: + if ((c == 1) || (c == 3)) + { + /* GM 1 or GM2 On, reset synth */ + if (parserMode != eParserModeMetaData) + { + pMIDIStream->flags |= MIDI_FLAG_GM_ON; + VMReset(pEASData->pVoiceMgr, pSynth, EAS_FALSE); + VMInitMIPTable(pSynth); + } + pMIDIStream->sysExState = eSysExEOX; + } + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + /* Process Master Volume and SP-MIDI */ + case eSysExUnivRealTime: + if (c == 0x7f) + pMIDIStream->sysExState = eSysExUnivRtTargetID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExUnivRtTargetID: + if (c == 0x04) + pMIDIStream->sysExState = eSysExDeviceControl; + else if (c == 0x0b) + pMIDIStream->sysExState = eSysExSPMIDI; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + /* process master volume */ + case eSysExDeviceControl: + if (c == 0x01) + pMIDIStream->sysExState = eSysExMasterVolume; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMasterVolume: + /* save LSB */ + pMIDIStream->d1 = c; + pMIDIStream->sysExState = eSysExMasterVolLSB; + break; + + case eSysExMasterVolLSB: + if (parserMode != eParserModeMetaData) + { + EAS_I32 gain = ((EAS_I32) c << 8) | ((EAS_I32) pMIDIStream->d1 << 1); + gain = (gain * gain) >> 15; + VMSetVolume(pSynth, (EAS_U16) gain); + } + pMIDIStream->sysExState = eSysExEOX; + break; + + /* process SP-MIDI MIP message */ + case eSysExSPMIDI: + if (c == 0x01) + { + /* assume all channels are muted */ + if (parserMode != eParserModeMetaData) + VMInitMIPTable(pSynth); + pMIDIStream->d1 = 0; + pMIDIStream->sysExState = eSysExSPMIDIchan; + } + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExSPMIDIchan: + if (c < NUM_SYNTH_CHANNELS) + { + pMIDIStream->d2 = c; + pMIDIStream->sysExState = eSysExSPMIDIMIP; + } + else + { + /* bad MIP message - unmute channels */ + if (parserMode != eParserModeMetaData) + VMInitMIPTable(pSynth); + pMIDIStream->sysExState = eSysExIgnore; + } + break; + + case eSysExSPMIDIMIP: + /* process MIP entry here */ + if (parserMode != eParserModeMetaData) + VMSetMIPEntry(pEASData->pVoiceMgr, pSynth, pMIDIStream->d2, pMIDIStream->d1, c); + pMIDIStream->sysExState = eSysExSPMIDIchan; + + /* if 16 channels received, update MIP table */ + if (++pMIDIStream->d1 == NUM_SYNTH_CHANNELS) + { + if (parserMode != eParserModeMetaData) + VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); + pMIDIStream->sysExState = eSysExEOX; + } + break; + + /* process Enhancer */ + case eSysExMfgID1: + if (c == 0x01) + pMIDIStream->sysExState = eSysExMfgID1; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMfgID2: + if (c == 0x3a) + pMIDIStream->sysExState = eSysExMfgID1; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMfgID3: + if (c == 0x04) + pMIDIStream->sysExState = eSysExEnhancer; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExEnhancer: + if (c == 0x01) + pMIDIStream->sysExState = eSysExEnhancerSubID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExEnhancerSubID: + pMIDIStream->sysExState = eSysExEnhancerFeedback1; + break; + + case eSysExEnhancerFeedback1: + pMIDIStream->sysExState = eSysExEnhancerFeedback2; + break; + + case eSysExEnhancerFeedback2: + pMIDIStream->sysExState = eSysExEnhancerDrive; + break; + + case eSysExEnhancerDrive: + pMIDIStream->sysExState = eSysExEnhancerWet; + break; + + case eSysExEnhancerWet: + pMIDIStream->sysExState = eSysExEOX; + break; + + case eSysExEOX: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Expected F7, received %02x\n", c); */ } + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExIgnore: + break; + + default: + pMIDIStream->sysExState = eSysExIgnore; + break; + } + } + + if (pMIDIStream->sysExState == eSysExIgnore) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Ignoring SysEx byte %02x\n", c); */ } + return EAS_SUCCESS; +} /* end ProcessSysExMessage */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midi.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midi.h new file mode 100755 index 0000000..10649a0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midi.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midi.h + * + * Contents and purpose: + * Prototypes for MIDI stream parsing functions + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDI_H +#define _EAS_MIDI_H + +/*---------------------------------------------------------------------------- + * EAS_InitMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the MIDI stream state for parsing. + * + * Inputs: + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream); + +/*---------------------------------------------------------------------------- + * EAS_ParseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled) + * so the interface works equally well for both file and stream I/O. + * + * Inputs: + * c - character from MIDI stream + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode); + +#endif /* #define _EAS_MIDI_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midictrl.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midictrl.h new file mode 100755 index 0000000..46fdc4f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_midictrl.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midictrl.h + * + * Contents and purpose: + * MIDI controller definitions + * + * This header only contains declarations that are specific + * to this implementation. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDICTRL_H +#define _EAS_MIDICTRL_H + +/* define controller types */ +/* + Note that these controller types are specified in base 10 (decimal) + and not in hexadecimal. The above midi messages are specified + in hexadecimal. +*/ +#define MIDI_CONTROLLER_BANK_SELECT 0 +#define MIDI_CONTROLLER_BANK_SELECT_MSB 0 +#define MIDI_CONTROLLER_MOD_WHEEL 1 +#define MIDI_CONTROLLER_ENTER_DATA_MSB 6 +#define MIDI_CONTROLLER_VOLUME 7 +#define MIDI_CONTROLLER_PAN 10 +#define MIDI_CONTROLLER_EXPRESSION 11 +#define MIDI_CONTROLLER_BANK_SELECT_LSB 32 +#define MIDI_CONTROLLER_ENTER_DATA_LSB 38 /* 0x26 */ +#define MIDI_CONTROLLER_SUSTAIN_PEDAL 64 +#define MIDI_CONTROLLER_SELECT_NRPN_LSB 98 +#define MIDI_CONTROLLER_SELECT_NRPN_MSB 99 +#define MIDI_CONTROLLER_SELECT_RPN_LSB 100 /* 0x64 */ +#define MIDI_CONTROLLER_SELECT_RPN_MSB 101 /* 0x65 */ +#define MIDI_CONTROLLER_ALL_SOUND_OFF 120 +#define MIDI_CONTROLLER_RESET_CONTROLLERS 121 +#define MIDI_CONTROLLER_ALL_NOTES_OFF 123 +#define MIDI_CONTROLLER_OMNI_OFF 124 +#define MIDI_CONTROLLER_OMNI_ON 125 +#define MIDI_CONTROLLER_MONO_ON_POLY_OFF 126 +#define MIDI_CONTROLLER_POLY_ON_MONO_OFF 127 + +#endif /* #ifndef _EAS_MIDICTRL_H */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mididata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mididata.c new file mode 100755 index 0000000..4463b7e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mididata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mididata.c + * + * Contents and purpose: + * Data module for MIDI stream interface + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_miditypes.h" + +S_INTERACTIVE_MIDI eas_MIDIData; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_miditypes.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_miditypes.h new file mode 100755 index 0000000..015f08b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_miditypes.h @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_miditypes.h + * + * Contents and purpose: + * Contains declarations for the MIDI stream parser. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDITYPES_H +#define _EAS_MIDITYPES_H + +#include "eas_data.h" +#include "eas_parser.h" + +/*---------------------------------------------------------------------------- + * S_MIDI_STREAM + * + * Maintains parser state for the MIDI stream parser + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_midi_stream_tag +{ + EAS_BOOL8 byte3; /* flag indicates 3rd byte expected */ + EAS_BOOL8 pending; /* flag indicates more data expected */ + EAS_U8 sysExState; /* maintains the SysEx state */ + EAS_U8 runningStatus; /* last running status received */ + EAS_U8 status; /* status byte */ + EAS_U8 d1; /* first data byte */ + EAS_U8 d2; /* second data byte */ + EAS_U8 flags; /* flags - see below for definition */ +#ifdef JET_INTERFACE + EAS_U32 jetData; /* JET data */ +#endif +} S_MIDI_STREAM; + +/* flags for S_MIDI_STREAM.flags */ +#define MIDI_FLAG_GM_ON 0x01 /* GM System On message received */ +#define MIDI_FLAG_FIRST_NOTE 0x02 /* first note received */ + +/* flags for S_MIDI_STREAM.jetFlags */ +#define MIDI_FLAGS_JET_MUTE 0x00000001 /* track is muted */ +#define MIDI_FLAGS_JET_CB 0x00000002 /* JET callback enabled */ + +/*---------------------------------------------------------------------------- + * + * S_SMF_STREAM + * + * This structure contains data required to parse an SMF stream. For SMF0 files, there + * will be a single instance of this per file. For SMF1 files, there will be multiple instance, + * one for each separate stream in the file. + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_smf_stream_tag +{ + EAS_FILE_HANDLE fileHandle; /* host wrapper file handle */ + EAS_U32 ticks; /* time of next event in stream */ + EAS_I32 startFilePos; /* start location of track within file */ + S_MIDI_STREAM midiStream; /* MIDI stream state */ +} S_SMF_STREAM; + +/*---------------------------------------------------------------------------- + * + * S_SMF_DATA + * + * This structure contains the instance data required to parse an SMF stream. + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_smf_data_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + S_SMF_STREAM *streams; /* pointer to individual streams in file */ + S_SMF_STREAM *nextStream; /* pointer to next stream with event */ + S_SYNTH *pSynth; /* pointer to synth */ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I32 fileOffset; /* for embedded files */ + EAS_I32 time; /* current time in milliseconds/256 */ + EAS_U16 numStreams; /* actual number of streams */ + EAS_U16 tickConv; /* current MIDI tick to msec conversion */ + EAS_U16 ppqn; /* ticks per quarter note */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 flags; /* flags - see definitions below */ +} S_SMF_DATA; + +#define SMF_FLAGS_CHASE_MODE 0x01 /* chase mode - skip to first note */ +#define SMF_FLAGS_HAS_TIME_SIG 0x02 /* time signature encountered at time 0 */ +#define SMF_FLAGS_HAS_TEMPO 0x04 /* tempo encountered at time 0 */ +#define SMF_FLAGS_HAS_GM_ON 0x08 /* GM System On encountered at time 0 */ +#define SMF_FLAGS_JET_STREAM 0x80 /* JET in use - keep strict timing */ + +/* combo flags indicate setup bar */ +#define SMF_FLAGS_SETUP_BAR (SMF_FLAGS_HAS_TIME_SIG | SMF_FLAGS_HAS_TEMPO | SMF_FLAGS_HAS_GM_ON) + +/*---------------------------------------------------------------------------- + * Interactive MIDI structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_interactive_midi_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + S_SYNTH *pSynth; /* pointer to synth */ + S_MIDI_STREAM stream; /* stream data */ +} S_INTERACTIVE_MIDI; + +#endif /* #ifndef _EAS_MIDITYPES_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixbuf.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixbuf.c new file mode 100755 index 0000000..db5bd02 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixbuf.c @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixbuf.c + * + * Contents and purpose: + * Contains a data allocation for synthesizer + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" +#include "eas_mixer.h" + +// globals +EAS_I32 eas_MixBuffer[BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS]; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixer.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixer.c new file mode 100755 index 0000000..0a839a8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixer.c @@ -0,0 +1,464 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixer.c + * + * Contents and purpose: + * This file contains the critical components of the mix engine that + * must be optimized for best performance. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 706 $ + * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +//3 dls: This module is in the midst of being converted from a synth +//3 specific module to a general purpose mix engine + +/*------------------------------------ + * includes + *------------------------------------ +*/ +#include "eas_data.h" +#include "eas_host.h" +#include "eas_math.h" +#include "eas_mixer.h" +#include "eas_config.h" +#include "eas_report.h" + +#ifdef _MAXIMIZER_ENABLED +EAS_I32 MaximizerProcess (EAS_VOID_PTR pInstData, EAS_I32 *pSrc, EAS_I32 *pDst, EAS_I32 numSamples); +#endif + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +/* need to boost stereo by ~3dB to compensate for the panner */ +#define STEREO_3DB_GAIN_BOOST 512 + +/*---------------------------------------------------------------------------- + * EAS_MixEngineInit() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the mix engine for work, allocates buffers, locates effects modules, etc. + * + * Inputs: + * pEASData - instance data + * pInstData - pointer to variable to receive instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineInit (S_EAS_DATA *pEASData) +{ + + /* check Configuration Module for mix buffer allocation */ + if (pEASData->staticMemoryModel) + pEASData->pMixBuffer = EAS_CMEnumData(EAS_CM_MIX_BUFFER); + else + pEASData->pMixBuffer = EAS_HWMalloc(pEASData->hwInstData, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32)); + if (pEASData->pMixBuffer == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate mix buffer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet((void *)(pEASData->pMixBuffer), 0, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32)); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePrep() + *---------------------------------------------------------------------------- + * Purpose: + * Performs prep before synthesize a buffer of audio, such as clearing + * audio buffers, etc. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePrep (S_EAS_DATA *pEASData, EAS_I32 numSamples) +{ + + /* clear the mix buffer */ +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_HWMemSet(pEASData->pMixBuffer, 0, numSamples * (EAS_I32) sizeof(long) * 2); +#else + EAS_HWMemSet(pEASData->pMixBuffer, 0, (EAS_I32) numSamples * (EAS_I32) sizeof(long)); +#endif + + /* need to clear other side-chain effect buffers (chorus & reverb) */ +} + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePost + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the post-processing after all voices have been + * synthesized. It calls any sweeteners and does the final mixdown to + * the output buffer. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePost (S_EAS_DATA *pEASData, EAS_I32 numSamples) +{ + EAS_U16 gain; + +//3 dls: Need to restore the mix engine metrics + + /* calculate the gain multiplier */ +#ifdef _MAXIMIZER_ENABLED + if (pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effect) + { + EAS_I32 temp; + temp = MaximizerProcess(pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effectData, pEASData->pMixBuffer, pEASData->pMixBuffer, numSamples); + temp = (temp * pEASData->masterGain) >> 15; + if (temp > 32767) + gain = 32767; + else + gain = (EAS_U16) temp; + } + else + gain = (EAS_U16) pEASData->masterGain; +#else + gain = (EAS_U16) pEASData->masterGain; +#endif + + /* Not using all the gain bits for now + * Reduce the input to the compressor by 6dB to prevent saturation + */ +#ifdef _COMPRESSOR_ENABLED + if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData) + gain = gain >> 5; + else + gain = gain >> 4; +#else + gain = gain >> 4; +#endif + + /* convert 32-bit mix buffer to 16-bit output format */ +#if (NUM_OUTPUT_CHANNELS == 2) + SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) ((EAS_U16) numSamples * 2)); +#else + SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) numSamples); +#endif + +#ifdef _ENHANCER_ENABLED + /* enhancer effect */ + if (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData) + (*pEASData->effectsModules[EAS_MODULE_ENHANCER].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _GRAPHIC_EQ_ENABLED + /* graphic EQ effect */ + if (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData) + (*pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _COMPRESSOR_ENABLED + /* compressor effect */ + if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData) + (*pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _WOW_ENABLED + /* WOW requires a 32-bit buffer, borrow the mix buffer and + * pass it as the destination buffer + */ + /*lint -e{740} temporarily passing a parameter through an existing I/F */ + if (pEASData->effectsModules[EAS_MODULE_WOW].effectData) + (*pEASData->effectsModules[EAS_MODULE_WOW].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_WOW].effectData, + pEASData->pOutputAudioBuffer, + (EAS_PCM*) pEASData->pMixBuffer, + numSamples); +#endif + +#ifdef _TONECONTROLEQ_ENABLED + /* ToneControlEQ effect */ + if (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData) + (*pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _REVERB_ENABLED + /* Reverb effect */ + if (pEASData->effectsModules[EAS_MODULE_REVERB].effectData) + (*pEASData->effectsModules[EAS_MODULE_REVERB].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_REVERB].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _CHORUS_ENABLED + /* Chorus effect */ + if (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData) + (*pEASData->effectsModules[EAS_MODULE_CHORUS].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +} + +#ifndef NATIVE_EAS_KERNEL +/*---------------------------------------------------------------------------- + * SynthMasterGain + *---------------------------------------------------------------------------- + * Purpose: + * Mixes down audio from 32-bit to 16-bit target buffer + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void SynthMasterGain (long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 numSamples) { + + /* loop through the buffer */ + while (numSamples--) { + long s; + + /* read a sample from the input buffer and add some guard bits */ + s = *pInputBuffer++; + + /* add some guard bits */ + /*lint -e{704} */ + s = s >> 7; + + /* apply master gain */ + s *= (long) nGain; + + /* shift to lower 16-bits */ + /*lint -e{704} */ + s = s >> 9; + + /* saturate */ + s = SATURATE(s); + + *pOutputBuffer++ = (EAS_PCM)s; + } +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_MixEngineShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down effects modules and deallocates memory + * + * Inputs: + * pEASData - instance data + * pInstData - instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineShutdown (S_EAS_DATA *pEASData) +{ + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel && (pEASData->pMixBuffer != NULL)) + EAS_HWFree(pEASData->hwInstData, pEASData->pMixBuffer); + + return EAS_SUCCESS; +} + +#ifdef UNIFIED_MIXER +#ifndef NATIVE_MIX_STREAM +/*---------------------------------------------------------------------------- + * EAS_MixStream + *---------------------------------------------------------------------------- + * Mix a 16-bit stream into a 32-bit buffer + * + * pInputBuffer 16-bit input buffer + * pMixBuffer 32-bit mix buffer + * numSamples number of samples to mix + * gainLeft initial gain left or mono + * gainRight initial gain right + * gainLeft left gain increment per sample + * gainRight right gain increment per sample + * flags bit 0 = stereo source + * bit 1 = stereo output + *---------------------------------------------------------------------------- +*/ +void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags) +{ + EAS_I32 temp; + EAS_INT src, dest; + + /* NOTE: There are a lot of optimizations that can be done + * in the native implementations based on register + * availability, etc. For example, it may make sense to + * break this down into 8 separate routines: + * + * 1. Mono source to mono output + * 2. Mono source to stereo output + * 3. Stereo source to mono output + * 4. Stereo source to stereo output + * 5. Mono source to mono output - no gain change + * 6. Mono source to stereo output - no gain change + * 7. Stereo source to mono output - no gain change + * 8. Stereo source to stereo output - no gain change + * + * Other possibilities include loop unrolling, skipping + * a gain calculation every 2 or 4 samples, etc. + */ + + /* no gain change, use fast loops */ + if ((gainIncLeft == 0) && (gainIncRight == 0)) + { + switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT)) + { + /* mono to mono */ + case 0: + gainLeft >>= 15; + for (src = dest = 0; src < numSamples; src++, dest++) + { + + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* mono to stereo */ + case MIX_FLAGS_STEREO_OUTPUT: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src++, dest+=2) + { + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src] * gainRight) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* stereo to mono */ + case MIX_FLAGS_STEREO_SOURCE: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src+=2, dest++) + { + temp = (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + temp += ((pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS); + pMixBuffer[dest] += temp; + } + break; + + /* stereo to stereo */ + case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src+=2, dest+=2) + { + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS; + } + break; + } + } + + /* gain change - do gain increment */ + else + { + switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT)) + { + /* mono to mono */ + case 0: + for (src = dest = 0; src < numSamples; src++, dest++) + { + gainLeft += gainIncLeft; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* mono to stereo */ + case MIX_FLAGS_STEREO_OUTPUT: + for (src = dest = 0; src < numSamples; src++, dest+=2) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* stereo to mono */ + case MIX_FLAGS_STEREO_SOURCE: + for (src = dest = 0; src < numSamples; src+=2, dest++) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + temp = (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + temp += ((pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS); + pMixBuffer[dest] += temp; + } + break; + + /* stereo to stereo */ + case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT: + for (src = dest = 0; src < numSamples; src+=2, dest+=2) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + } + } +} +#endif +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixer.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixer.h new file mode 100755 index 0000000..b2eb33b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_mixer.h @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixer.h + * + * Contents and purpose: + * This file contains the critical components of the mix engine that + * must be optimized for best performance. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 706 $ + * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIXER_H +#define _EAS_MIXER_H + +//3 dls: This module is in the midst of being converted from a synth +//3 specific module to a general purpose mix engine + +#define MIX_FLAGS_STEREO_SOURCE 1 +#define MIX_FLAGS_STEREO_OUTPUT 2 +#define NUM_MIXER_GUARD_BITS 4 + +#include "eas_effects.h" + +extern void SynthMasterGain( long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 nNumLoopSamples); + +/*---------------------------------------------------------------------------- + * EAS_MixEngineInit() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the mix engine for work, allocates buffers, locates effects modules, etc. + * + * Inputs: + * pEASData - instance data + * pInstData - pointer to variable to receive instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineInit (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePrep() + *---------------------------------------------------------------------------- + * Purpose: + * Performs prep before synthesize a buffer of audio, such as clearing + * audio buffers, etc. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePrep (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePost + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the post-processing after all voices have been + * synthesized. It calls any sweeteners and does the final mixdown to + * the output buffer. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePost (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * EAS_MixEngineShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down effects modules and deallocates memory + * + * Inputs: + * pEASData - instance data + * pInstData - instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineShutdown (EAS_DATA_HANDLE pEASData); + +#ifdef UNIFIED_MIXER +/*---------------------------------------------------------------------------- + * EAS_MixStream + *---------------------------------------------------------------------------- + * Mix a 16-bit stream into a 32-bit buffer + * + * pInputBuffer 16-bit input buffer + * pMixBuffer 32-bit mix buffer + * numSamples number of samples to mix + * gainLeft initial gain left or mono + * gainRight initial gain right + * gainLeft left gain increment per sample + * gainRight right gain increment per sample + * flags bit 0 = stereo source + * bit 1 = stereo output + *---------------------------------------------------------------------------- +*/ +void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags); +#endif + +#endif /* #ifndef _EAS_MIXER_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ota.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ota.c new file mode 100755 index 0000000..5bc9062 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_ota.c @@ -0,0 +1,1077 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ota.c + * + * Contents and purpose: + * OTA parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_otadata.h" + +/* increase gain for mono ringtones */ +#define OTA_GAIN_OFFSET 8 + +/* file definitions */ +#define OTA_RINGTONE 0x25 +#define OTA_SOUND 0x1d +#define OTA_UNICODE 0x22 + +/* song type definitions */ +#define OTA_BASIC_SONG_TYPE 0x01 +#define OTA_TEMPORARY_SONG_TYPE 0x02 + +/* instruction ID coding */ +#define OTA_PATTERN_HEADER_ID 0x00 +#define OTA_NOTE_INST_ID 0x01 +#define OTA_SCALE_INST_ID 0x02 +#define OTA_STYLE_INST_ID 0x03 +#define OTA_TEMPO_INST_ID 0x04 +#define OTA_VOLUME_INST_ID 0x05 + +/* note durations */ +#define OTA_NORMAL_DURATION 0x00 +#define OTA_DOTTED_NOTE 0x01 +#define OTA_DOUBLE_DOTTED_NOTE 0x02 +#define OTA_TRIPLET_NOTE 0x03 + +/* loop count value for infinite loop */ +#define OTA_INFINITE_LOOP 0x0f + +/* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */ +#define DEFAULT_TICK_CONV 30476 + +/* default channel and program for OTA playback */ +#define OTA_CHANNEL 0 +#define OTA_PROGRAM 80 +#define OTA_VEL_MUL 4 +#define OTA_VEL_OFS 67 +#define OTA_VEL_DEFAULT 95 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +/* local prototypes */ +static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData); +static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue); +static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc); +static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc); + + +/*---------------------------------------------------------------------------- + * + * EAS_OTA_Parser + * + * This structure contains the functional interface for the OTA parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_OTA_Parser = +{ + OTA_CheckFileType, + OTA_Prepare, + OTA_Time, + OTA_Event, + OTA_State, + OTA_Close, + OTA_Reset, + OTA_Pause, + OTA_Resume, + NULL, + OTA_SetData, + OTA_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * + * bpmTable + * + * BPM conversion table. Converts bpm values to 256ths of a millisecond for a 32nd note + *---------------------------------------------------------------------------- +*/ +static const EAS_U32 bpmTable[32] = +{ + 76800, 68571, 61935, 54857, + 48000, 42667, 38400, 34286, + 30476, 27429, 24000, 21333, + 19200, 17143, 15360, 13714, + 12000, 10667, 9600, 8533, + 7680, 6737, 6000, 5408, + 4800, 4267, 3840, 3398, + 3024, 2685, 2400, 2133 +}; + +/*---------------------------------------------------------------------------- + * OTA_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + EAS_INT cmdLen; + EAS_INT state; + EAS_U8 temp; + + /* read the first byte, should be command length */ + *ppHandle = NULL; + if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS) + return result; + + /* read all the commands */ + cmdLen = temp; + state = 0; + while (cmdLen--) + { + + /* read the command, upper 7 bits */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS) + return result; + temp = temp >> 1; + + if (state == 0) + { + if (temp != OTA_RINGTONE) + break; + state++; + } + else + { + + if (temp == OTA_SOUND) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_OTA_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_OTA_DATA)); + if (!pData) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Malloc failed in OTA_Prepare\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pData, 0, sizeof(S_OTA_DATA)); + + /* return a pointer to the instance data */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_OPEN; + *ppHandle = pData; + break; + } + + if (temp != OTA_UNICODE) + break; + } + } + + /* not recognized */ + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + /* check for valid state */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + pData->state = EAS_STATE_ERROR; + if ((result = OTA_ParseHeader(pEASData, pData)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + EAS_U32 duration; + EAS_U8 temp; + + pData = (S_OTA_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + /* set program to square lead */ + if (parserMode != eParserModeMetaData) + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, OTA_PROGRAM); + + /* set channel volume to max */ + if (parserMode != eParserModeMetaData) + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += (EAS_I32) pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* if not in a pattern, read the pattern header */ + while (pData->current.patternLen == 0) + { + + /* check for loop - don't do infinite loops when locating */ + if (pData->loopCount && ((parserMode == eParserModePlay) || (pData->loopCount != OTA_INFINITE_LOOP))) + { + /* if not infinite loop, decrement loop count */ + if (pData->loopCount != OTA_INFINITE_LOOP) + pData->loopCount--; + + /* back to start of pattern*/ + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* if no previous position to restore, continue forward */ + else if (pData->restore.fileOffset < 0) + { + + /* check for end of song */ + if (pData->numPatterns == 0) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* read the next pattern header */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + if (temp != OTA_PATTERN_HEADER_ID) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA pattern header\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* get the pattern ID */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->currentPattern)) != EAS_SUCCESS) + return result; + + /* get the loop count */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->loopCount)) != EAS_SUCCESS) + return result; + + /* get the pattern length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->current.patternLen)) != EAS_SUCCESS) + return result; + + /* if pattern definition, save the current position */ + if (pData->current.patternLen) + { + if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* if pattern length is zero, repeat a previous pattern */ + else + { + /* make sure it's a valid pattern */ + if (pData->patterns[pData->currentPattern].fileOffset < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA pattern error, invalid pattern specified\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* save current position and data */ + if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS) + return result; + + /* seek to the pattern in the file */ + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* decrement pattern count */ + pData->numPatterns--; + } + + /* restore previous position */ + else + { + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS) + return result; + } + } + + /* get the next event */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + + switch (temp) + { + case OTA_NOTE_INST_ID: + /* fetch note value */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->note)) != EAS_SUCCESS) + return result; + + /* fetch note duration */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + duration = pData->tick * (0x20 >> temp); + + /* fetch note duration modifier */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS) + return result; + switch (temp) + { + case OTA_NORMAL_DURATION: + break; + + case OTA_DOTTED_NOTE: + duration += duration >> 1; + break; + + case OTA_DOUBLE_DOTTED_NOTE: + duration += (duration >> 1) + (duration >> 2); + break; + + case OTA_TRIPLET_NOTE: + duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note duration ignored\n"); */ } + break; + } + + /* check for note */ + if (pData->note) + { + + /* determine note length based on style */ + switch (pData->style) + { + case 0: + pData->restTicks = duration >> 4; + break; + case 1: + pData->restTicks = 0; + break; + case 2: + pData->restTicks = duration >> 1; + break; + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note style ignored\n"); */ } + } + + /* add octave */ + pData->note += pData->octave; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, pData->velocity); + pData->time += (EAS_I32) duration - (EAS_I32) pData->restTicks; + } + + /* this is a rest */ + else + pData->time += (EAS_I32) duration; + break; + + case OTA_SCALE_INST_ID: + /* fetch octave */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS) + return result; + pData->octave = (EAS_U8) (temp * 12 + 59); + break; + + case OTA_STYLE_INST_ID: + /* fetch note style */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->style)) != EAS_SUCCESS) + return result; + break; + + case OTA_TEMPO_INST_ID: + /* fetch tempo */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 5, &temp)) != EAS_SUCCESS) + return result; + pData->tick = bpmTable[temp]; + break; + + case OTA_VOLUME_INST_ID: + /* fetch volume */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &temp)) != EAS_SUCCESS) + return result; + pData->velocity = temp ? (EAS_U8) (temp * OTA_VEL_MUL + OTA_VEL_OFS) : 0; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected instruction ID in OTA stream\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* decrement pattern length */ + pData->current.patternLen--; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_OTA_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_OTA_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_STOPPED; + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + pData = (S_OTA_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + pData = (S_OTA_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = OTA_ParseHeader (pEASData, pData)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA *pData; + + /* can't pause a stopped stream */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA *pData; + + /* can't resume a stopped stream */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA *) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA*) pInstData; + switch (param) + { + /* return file type as OTA */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_OTA; + break; + +#if 0 + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = OTA_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData) +{ + EAS_RESULT result; + EAS_INT i; + EAS_INT state; + EAS_U8 temp; + EAS_U8 titleLen; + + /* initialize some data */ + pData->flags = 0; + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->patterns[0].fileOffset = pData->patterns[1].fileOffset = + pData->patterns[2].fileOffset = pData->patterns[3].fileOffset = -1; + pData->current.bitCount = 0; + pData->current.patternLen = 0; + pData->loopCount = 0; + pData->restore.fileOffset = -1; + pData->note = 0; + pData->restTicks = 0; + pData->velocity = OTA_VEL_DEFAULT; + pData->style = 0; + pData->octave = 59; + + /* seek to start of data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + + /* read the first byte, should be command length */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + + /* read all the commands */ + i = temp; + state = 0; + while (i--) + { + + /* fetch command, always starts on byte boundary */ + pData->current.bitCount = 0; + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 7, &temp)) != EAS_SUCCESS) + return result; + + if (state == 0) + { + if (temp != OTA_RINGTONE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Ring Tone Programming type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + state++; + } + else + { + + if (temp == OTA_SOUND) + break; + + if (temp == OTA_UNICODE) + pData->flags |= OTA_FLAGS_UNICODE; + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Sound or Unicode type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + } + } + + /* get song type */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + + /* check for basic song type */ + if (temp == OTA_BASIC_SONG_TYPE) + { + /* fetch title length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &titleLen)) != EAS_SUCCESS) + return result; + + /* if unicode, double the length */ + if (pData->flags & OTA_FLAGS_UNICODE) + titleLen = (EAS_U8) (titleLen << 1); + + /* zero the metadata buffer */ + if (pData->metadata.buffer) + EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize); + + /* read the song title */ + for (i = 0; i < titleLen; i++) + { + /* fetch character */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &temp)) != EAS_SUCCESS) + return result; + + /* check for metadata callback */ + if (pData->metadata.callback) + { + if (i < (pData->metadata.bufferSize - 1)) + pData->metadata.buffer[i] = (char) temp; + } + } + + /* if host has registered callback, call it now */ + if (pData->metadata.callback) + (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData); + } + + /* must be temporary song */ + else if (temp != OTA_TEMPORARY_SONG_TYPE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA basic or temporary song type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* get the song length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->numPatterns)) != EAS_SUCCESS) + return result; + + /* sanity check */ + if (pData->numPatterns == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA number of patterns is zero\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* at start of first pattern */ + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_FetchBitField() + *---------------------------------------------------------------------------- + * Purpose: + * Fetch a specified number of bits from the input stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue) +{ + EAS_RESULT result; + EAS_I32 bitsLeft; + EAS_U8 value; + + value = 0; + + /* do we have enough bits? */ + bitsLeft = pData->current.bitCount - numBits; + + /* not enough bits, assemble them from 2 characters */ + if (bitsLeft < 0) + { + /* grab the remaining bits from the previous byte */ + if (pData->current.bitCount) + /*lint -e{504,734} this is a legitimate shift operation */ + value = pData->current.dataByte << -bitsLeft; + + /* read the next byte */ + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->current.dataByte)) != EAS_SUCCESS) + return result; + bitsLeft += 8; + } + + /* more bits than needed? */ + if (bitsLeft > 0) + { + value |= pData->current.dataByte >> bitsLeft; + pData->current.bitCount = (EAS_U8) bitsLeft; + pData->current.dataByte = pData->current.dataByte & (0xff >> (8 - bitsLeft)); + } + + /* exactly the right number of bits */ + else + { + value |= pData->current.dataByte; + pData->current.bitCount = 0; + } + + *pValue = value; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_SavePosition() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc) +{ + EAS_HWMemCpy(pLoc, &pData->current, sizeof(S_OTA_LOC)); + return EAS_HWFilePos(hwInstData, pData->fileHandle, &pLoc->fileOffset); +} + +/*---------------------------------------------------------------------------- + * OTA_RestorePosition() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc) +{ + EAS_HWMemCpy(&pData->current, pLoc, sizeof(S_OTA_LOC)); + pData->restore.fileOffset = -1; + return EAS_HWFileSeek(hwInstData, pData->fileHandle, pLoc->fileOffset); +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_otadata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_otadata.c new file mode 100755 index 0000000..7463a0c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_otadata.c @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_otadata..c + * + * Contents and purpose: + * OTA Stream Parser data module for static memory model + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_otadata.h" + +/*---------------------------------------------------------------------------- + * + * eas_OTAData + * + * Static memory allocation for OTA parser + *---------------------------------------------------------------------------- +*/ +S_OTA_DATA eas_OTAData; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_otadata.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_otadata.h new file mode 100755 index 0000000..c06e3d3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_otadata.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_otadata.h + * + * Contents and purpose: + * OTA File Parser + * + * This file contains data declarations for the OTA parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_OTADATA_H +#define EAS_OTADATA_H + +#include "eas_data.h" + +/* definition for state flags */ +#define OTA_FLAGS_UNICODE 0x01 /* unicode text */ + +/*---------------------------------------------------------------------------- + * + * S_OTA_DATA + * + * This structure contains the state data for the OTA parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_I32 fileOffset; /* offset to location in file */ + EAS_U8 patternLen; /* length of current pattern */ + EAS_U8 dataByte; /* previous char from file */ + EAS_U8 bitCount; /* bit count in char */ +} S_OTA_LOC; + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* synth handle */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_U32 tick; /* length of 32nd note in 256th of a msec */ + EAS_U32 restTicks; /* ticks to rest after current note */ + S_OTA_LOC patterns[4]; /* pattern locations */ + S_OTA_LOC current; /* current location */ + S_OTA_LOC restore; /* previous location */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_U8 flags; /* bit flags */ + EAS_U8 numPatterns; /* number of patterns left in song */ + EAS_U8 currentPattern; /* current pattern for loop */ + EAS_U8 note; /* MIDI note number */ + EAS_U8 octave; /* octave modifier */ + EAS_U8 style; /* from STYLE */ + EAS_U8 velocity; /* current volume */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 loopCount; /* loop count for pattern */ +} S_OTA_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pan.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pan.c new file mode 100755 index 0000000..ae4c69d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pan.c @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pan.c + * + * Contents and purpose: + * Calculates left and right gain multipliers based on a pan value from -63 to +63 + * + * NOTES: + * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine + * whether the parser works for those particular file formats. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_pan.h" +#include "eas_math.h" + +/*---------------------------------------------------------------------------- + * EAS_CalcPanControl() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the left and right gain values corresponding to the given pan value. + * + * This routine uses sin/cos approximations for an equal power curve: + * + * sin(x) = (2-4*c)*x^2 + c + x + * cos(x) = (2-4*c)*x^2 + c - x + * + * where c = 1/sqrt(2) + * using the a0 + x*(a1 + x*a2) approach + * + * Inputs: + * pan - pan value (-63 to + 63) + * + * Outputs: + * pGainLeft linear gain multiplier for left channel (15-bit fraction) + * pGainRight linear gain multiplier for left channel (15-bit fraction) + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight) +{ + EAS_INT temp; + EAS_INT netAngle; + + /* impose hard limit */ + if (pan < -63) + netAngle = -63; + else if (pan > 63) + netAngle = 63; + else + netAngle = pan; + + /*lint -e{701} */ + netAngle = netAngle << 8; + + /* calculate sin */ + temp = EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle); + temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle); + + if (temp > SYNTH_FULL_SCALE_EG1_GAIN) + temp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (temp < 0) + temp = 0; + + *pGainRight = (EAS_I16) temp; + + /* calculate cos */ + temp = -EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle); + temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle); + if (temp > SYNTH_FULL_SCALE_EG1_GAIN) + temp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (temp < 0) + temp = 0; + + *pGainLeft = (EAS_I16) temp; +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pan.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pan.h new file mode 100755 index 0000000..cb0a90d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pan.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pan.h + * + * Contents and purpose: + * Calculates left and right gain multipliers based on a pan value from -63 to +63 + * + * NOTES: + * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine + * whether the parser works for those particular file formats. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_PAN_H +#define _EAS_PAN_H + +#include "eas_types.h" + +/*---------------------------------------------------------------------------- + * EAS_CalcPanControl() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the left and right gain values corresponding to the given pan value. + * + * This routine uses sin/cos approximations for an equal power curve: + * + * sin(x) = (2-4*c)*x^2 + c + x + * cos(x) = (2-4*c)*x^2 + c - x + * + * where c = 1/sqrt(2) + * using the a0 + x*(a1 + x*a2) approach + * + * Inputs: + * pan - pan value (-63 to + 63) + * + * Outputs: + * pGainLeft linear gain multiplier for left channel (15-bit fraction) + * pGainRight linear gain multiplier for left channel (15-bit fraction) + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight); + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_parser.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_parser.h new file mode 100755 index 0000000..96ec35b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_parser.h @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_parser.h + * + * Contents and purpose: + * Interface declarations for the generic parser interface + * + * This header only contains declarations that are specific + * to this implementation. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 767 $ + * $Date: 2007-07-19 13:47:31 -0700 (Thu, 19 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PARSER_H +#define _EAS_PARSER_H + +#include "eas_types.h" + + +/* metadata callback */ +typedef struct s_metadata_cb_tag +{ + EAS_METADATA_CBFUNC callback; + char *buffer; + EAS_VOID_PTR pUserData; + EAS_I32 bufferSize; +} S_METADATA_CB; + +/* generic parser interface */ +typedef struct +{ + EAS_RESULT (* EAS_CONST pfCheckFileType)(struct s_eas_data_tag *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); + EAS_RESULT (* EAS_CONST pfPrepare)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfTime)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); + EAS_RESULT (* EAS_CONST pfEvent)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_INT parseMode); + EAS_RESULT (* EAS_CONST pfState)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); + EAS_RESULT (* EAS_CONST pfClose)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfReset)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfPause)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfResume)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfLocate)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate); + EAS_RESULT (* EAS_CONST pfSetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + EAS_RESULT (* EAS_CONST pfGetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (* EAS_CONST pfGetMetaData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength); +} S_FILE_PARSER_INTERFACE; + +typedef enum +{ + eParserModePlay, + eParserModeLocate, + eParserModeMute, + eParserModeMetaData +} E_PARSE_MODE; + +typedef enum +{ + PARSER_DATA_FILE_TYPE, + PARSER_DATA_PLAYBACK_RATE, + PARSER_DATA_TRANSPOSITION, + PARSER_DATA_VOLUME, + PARSER_DATA_SYNTH_HANDLE, + PARSER_DATA_METADATA_CB, + PARSER_DATA_DLS_COLLECTION, + PARSER_DATA_EAS_LIBRARY, + PARSER_DATA_POLYPHONY, + PARSER_DATA_PRIORITY, + PARSER_DATA_FORMAT, + PARSER_DATA_MEDIA_LENGTH, + PARSER_DATA_JET_CB, + PARSER_DATA_MUTE_FLAGS, + PARSER_DATA_SET_MUTE, + PARSER_DATA_CLEAR_MUTE, + PARSER_DATA_NOTE_COUNT, + PARSER_DATA_MAX_PCM_STREAMS, + PARSER_DATA_GAIN_OFFSET, + PARSER_DATA_PLAY_MODE +} E_PARSER_DATA; + +#endif /* #ifndef _EAS_PARSER_H */ diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcm.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcm.c new file mode 100755 index 0000000..ff3f6f9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcm.c @@ -0,0 +1,1482 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcm.c + * + * Contents and purpose: + * Implements the PCM engine including ADPCM decode for SMAF and CMX audio playback. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 849 $ + * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_config.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_math.h" +#include "eas_mixer.h" + +#define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1) + +/*---------------------------------------------------------------------------- + * Decoder interfaces + *---------------------------------------------------------------------------- +*/ + +static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); + +static const S_DECODER_INTERFACE PCMDecoder = +{ + NULL, + LinearPCMDecode, + LinearPCMLocate, +}; + +/* SMAF ADPCM decoder */ +#ifdef _SMAF_PARSER +extern S_DECODER_INTERFACE SmafDecoder; +#define SMAF_DECODER &SmafDecoder +extern S_DECODER_INTERFACE Smaf7BitDecoder; +#define SMAF_7BIT_DECODER &Smaf7BitDecoder +#else +#define SMAF_DECODER NULL +#define SMAF_7BIT_DECODER NULL +#endif + +/* IMA ADPCM decoder */ +#ifdef _IMA_DECODER +extern S_DECODER_INTERFACE IMADecoder; +#define IMA_DECODER &IMADecoder +#else +#define IMA_DECODER NULL +#endif + +static const S_DECODER_INTERFACE * const decoders[] = +{ + &PCMDecoder, + SMAF_DECODER, + IMA_DECODER, + SMAF_7BIT_DECODER +}; + +/*---------------------------------------------------------------------------- + * Sample rate conversion + *---------------------------------------------------------------------------- +*/ + +#define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE) + +#ifdef _LOOKUP_SAMPLE_RATE +static const EAS_U32 srcConvRate[][2] = +{ + 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE, + 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE, + 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE, + 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE, + 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE, + 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE, + 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE, + 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE +}; +static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate); +#define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2) +#endif + + +/* interface prototypes */ +static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples); + + +/* local prototypes */ +static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData); +static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_PEInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData) +{ + S_PCM_STATE *pState; + EAS_INT i; + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA); + /* allocate dynamic memory */ + else + pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); + + if (!pEASData->pPCMStreams) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + //zero the memory to insure complete initialization + EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); + + /* initialize the state data */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + pState->fileHandle = NULL; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData) +{ + + /* free any dynamic memory */ + if (!pEASData->staticMemoryModel) + { + if (pEASData->pPCMStreams) + { + EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams); + pEASData->pPCMStreams = NULL; + } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PERender() + *---------------------------------------------------------------------------- + * Purpose: + * Render a buffer of PCM audio + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples) +{ + S_PCM_STATE *pState; + EAS_RESULT result; + EAS_INT i; + + /* render all the active streams */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + { + if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED)) + if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS) + return result; + } + return EAS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + * EAS_PEState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState) +{ + /* return current state */ + *pState = pInstData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_RESULT result; + + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS) + return result; + + pState->fileHandle = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * PCM_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_RESULT result; + + /* reset file position to first byte of data in the stream */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ } + return result; + } + + /* re-initialize stream */ + return InitPCMStream(pEASData, pState); +} + +/*---------------------------------------------------------------------------- + * EAS_PEOpenStream() + *---------------------------------------------------------------------------- + * Purpose: + * Starts up a PCM playback + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle) +{ + EAS_RESULT result; + S_PCM_STATE *pState; + EAS_I32 filePos; + + /* make sure we support this decoder */ + if (pParams->decoder >= NUM_DECODER_MODULES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ } + return EAS_ERROR_PARAMETER_RANGE; + } + if (decoders[pParams->decoder] == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ } + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + } + + /* find a slot for the new stream */ + if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ } + return EAS_ERROR_MAX_PCM_STREAMS; + } + + /* get the current file position */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ } + pState->fileHandle = NULL; + return result; + } + + pState->pDecoder = decoders[pParams->decoder]; + pState->startPos = filePos; + pState->bytesLeftLoop = pState->byteCount = pParams->size; + pState->loopStart = pParams->loopStart; + pState->samplesTilLoop = (EAS_I32) pState->loopStart; + pState->loopSamples = pParams->loopSamples; + pState->samplesInLoop = 0; + pState->blockSize = (EAS_U16) pParams->blockSize; + pState->flags = pParams->flags; + pState->envData = pParams->envData; + pState->volume = pParams->volume; + pState->sampleRate = (EAS_U16) pParams->sampleRate; + + /* set the base frequency */ + pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15; + + /* calculate shift for frequencies > 1.0 */ + pState->rateShift = 0; + while (pState->basefreq > 32767) + { + pState->basefreq = pState->basefreq >> 1; + pState->rateShift++; + } + + /* initialize */ + if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS) + return result; + + *pHandle = pState; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n", + pState->startPos, pState->byteCount, pState->loopSamples); */ } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEContinueStream() + *---------------------------------------------------------------------------- + * Purpose: + * Continues a PCM stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{715} reserved for future use */ +EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size) +{ + + /* add new samples to count */ + pState->bytesLeft += size; + if (pState->bytesLeft > 0) + pState->flags &= ~PCM_FLAGS_EMPTY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEGetFileHandle() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the file handle of a stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle) +{ + *pFileHandle = pState->fileHandle; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateParams() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch and volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * pitch - pitch shift in cents + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +/*lint -esym(715, gainRight) used only in 2-channel version */ +EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight) +{ + + pState->gainLeft = gainLeft; + +#if (NUM_OUTPUT_CHANNELS == 2) + pState->gainRight = gainRight; +#endif + + pState->pitch = pitch; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PELocate() + *---------------------------------------------------------------------------- + * Purpose: + * This function seeks to the requested place in the file. Accuracy + * is dependent on the sample rate and block size. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pState - stream handle + * time - media time in milliseconds + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time) +{ + if (pState->pDecoder->pfLocate == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + return pState->pDecoder->pfLocate(pEASData, pState, time); +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Update the volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume) +{ + pState->volume = volume; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdatePitch() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch parameter for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * pState - pointer to S_PCM_STATE for this stream + * pitch - new pitch value in pitch cents + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch) +{ + pState->pitch = pitch; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEPause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + /* set state to stopping */ + pState->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + /* set state to stopping */ + pState->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +EAS_U32 getDecayScale(EAS_U32 index) +{ + EAS_U32 utemp; + + //envelope decay segment + switch (index) + { + case 0: //no decay + utemp = 512;//32768; + break; + case 1: //.0156 dB per update + utemp = 511;//32709; + break; + case 2: //.03125 + utemp = 510;//32649; + break; + case 3: //.0625 + utemp = 508;//32532; + break; + case 4: //.125 + utemp = 505;//32298; + break; + case 5: //.25 + utemp = 497;//31835; + break; + case 6: //.5 + utemp = 483;//30929; + break; + case 7: //1.0 + utemp = 456;//29193; + break; + case 8: //2.0 + utemp = 406;//26008; + break; + case 9: //4.0 + utemp = 323;//20642; + break; + case 10: //8.0 + utemp = 203;//13004; + break; + case 11: //16.0 + utemp = 81;//5160; + break; + case 12: //32.0 + utemp = 13;//813; + break; + case 13: //64.0 + utemp = 0;//20; + break; + case 14: //128.0 + utemp = 0; + break; + case 15: //256.0 + default: + utemp = 0; + break; + } + //printf("getdecayscale returned %d\n",utemp); + return utemp; +} + +EAS_U32 getAttackIncrement(EAS_U32 index) +{ + EAS_U32 utemp; + + //envelope decay segment + switch (index) + { + case 0: + utemp = 32; + break; + case 1: + utemp = 64; + break; + case 2: + utemp = 128; + break; + case 3: + utemp = 256; + break; + case 4: + utemp = 512; + break; + case 5: + utemp = 1024; + break; + case 6: + utemp = 2048; + break; + case 7: + utemp = 4096; + break; + case 8: + utemp = 8192; + break; + case 9: + utemp = 16384; + break; + case 10: + utemp = 32768; + break; + case 11: + utemp = 65536; + break; + case 12: + utemp = 65536; + break; + case 13: + utemp = 65536; + break; + case 14: + utemp = 65535; + break; + case 15: + default: + utemp = 0; + break; + } + //printf("getattackincrement returned %d\n",utemp); + return utemp; +} + +/*---------------------------------------------------------------------------- + * EAS_PERelease() + *---------------------------------------------------------------------------- + * Purpose: + * Put the PCM stream envelope into release. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_U32 utemp; + + //printf("handling note-off part of envelope\n"); + /*if the note is not ignore release or sustained*/ + if (((pState->envData >> 24) & 0x0F)==0) + { + /* set envelope state to release */ + pState->envState = PCM_ENV_RELEASE; + utemp = ((pState->envData >> 20) & 0x0F); + pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp); + } + else + { + /*else change envelope state to sustain */ + pState->envState = PCM_ENV_SUSTAIN; + utemp = ((pState->envData >> 28) & 0x0F); + pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); + } + //since we are in release, don't let anything hang around too long + //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale); + if (pState->envScale > 505) + pState->envScale = 505; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * FindSlot() + *---------------------------------------------------------------------------- + * Purpose: + * Locates an empty stream slot and assigns the file handle + * + * Inputs: + * pEASData - pointer to EAS library instance data + * fileHandle - file handle + * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED + * + * Outputs: + * returns handle to slot or NULL if all slots are used + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData) +{ + EAS_INT i; + S_PCM_STATE *pState; + +#ifndef NO_PCM_STEAL + S_PCM_STATE *foundState = NULL; + EAS_INT count = 0; + EAS_U32 startOrder = 0xFFFFFFFF; + S_PCM_STATE *stealState = NULL; + EAS_U32 youngest = 0; + + /* find an empty slot, count total in use, and find oldest in use (lowest start order) */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + { + /* if this one is available */ + if (pState->fileHandle == NULL) + { + foundState = pState; + } + /* else this one is in use, so see if it is the oldest, and count total in use */ + /* also find youngest */ + else + { + /*one more voice in use*/ + count++; + /* is this the oldest? (lowest start order) */ + if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder)) + { + /* remember this one */ + stealState = pState; + /* remember the oldest so far */ + startOrder = pState->startOrder; + } + /* is this the youngest? (highest start order) */ + if (pState->startOrder >= youngest) + { + youngest = pState->startOrder; + } + } + } + + /* if there are too many voices active, stop the oldest one */ + if (count > PCM_STREAM_THRESHOLD) + { + //printf("stealing!!!\n"); + /* make sure we got one, although we should always have one at this point */ + if (stealState != NULL) + { + //flag this as stopping, so it will get shut off + stealState->state = EAS_STATE_STOPPING; + } + } + + /* if there are no available open streams (we won't likely see this, due to stealing) */ + if (foundState == NULL) + return NULL; + + /* save info */ + foundState->startOrder = youngest + 1; + foundState->fileHandle = fileHandle; + foundState->pCallback = pCallbackFunc; + foundState->cbInstData = cbInstData; + return foundState; +#else + /* find an empty slot*/ + for (i = 0; i < MAX_PCM_STREAMS; i++) + { + pState = &pEASData->pPCMStreams[i]; + if (pState->fileHandle != NULL) + continue; + + pState->fileHandle = fileHandle; + pState->pCallback = pCallbackFunc; + pState->cbInstData = cbInstData; + return pState; + } + return NULL; +#endif +} + +#ifdef _LOOKUP_SAMPLE_RATE +/*---------------------------------------------------------------------------- + * CalcBaseFreq() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the fractional phase increment for the sample rate converter + * + * Inputs: + * sampleRate - sample rate in samples/sec + * + * Outputs: + * Returns fractional sample rate with a 15-bit fraction + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate) +{ + EAS_INT i; + + /* look up the conversion rate */ + for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++) + { + if (srcConvRate[i][0] == sampleRate) + return srcConvRate[i][1]; + } + + /* if not found in table, do it the long way */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ } + + return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15; +} +#endif + +/*---------------------------------------------------------------------------- + * InitPCMStream() + *---------------------------------------------------------------------------- + * Purpose: + * Start an ADPCM stream playback. Decodes the header, preps the engine. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState) +{ + + /* initialize the data structure */ + pState->bytesLeft = pState->byteCount; + pState->phase = 0; + pState->srcByte = 0; + pState->decoderL.acc = 0; + pState->decoderL.output = 0; + pState->decoderL.x0 = pState->decoderL.x1 = 0; + pState->decoderL.step = 0; + pState->decoderR.acc = 0; + pState->decoderR.output = 0; + pState->decoderR.x0 = pState->decoderR.x1 = 0; + pState->decoderR.step = 0; + pState->hiNibble = EAS_FALSE; + pState->pitch = 0; + pState->blockCount = 0; + pState->gainLeft = PCM_DEFAULT_GAIN_SETTING; +// pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING; + pState->envValue = 0; + pState->envState = PCM_ENV_START; + +#if (NUM_OUTPUT_CHANNELS == 2) + pState->gainRight = PCM_DEFAULT_GAIN_SETTING; +// pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING; +#endif + pState->state = EAS_STATE_READY; + + /* initialize the decoder */ + if (pState->pDecoder->pfInit) + return (*pState->pDecoder->pfInit)(pEASData, pState); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RenderPCMStream() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes a buffer of ADPCM data. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples) +{ + EAS_RESULT result; + EAS_U32 phaseInc; + EAS_I32 gainLeft, gainIncLeft; + EAS_I32 *pOut; + EAS_I32 temp; + EAS_U32 utemp; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I32 gainRight, gainIncRight; +#endif + +#if 0 + printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n", + ((pState->envData >> 12) & 0x0F), + ((pState->envData >> 16) & 0x0F), + ((pState->envData >> 8) & 0x0F), + ((pState->envData >> 28) & 0x0F), + ((pState->envData >> 20) & 0x0F)); +#endif + + if (pState->envState == PCM_ENV_START) + { + //printf("env start\n"); + utemp = ((pState->envData >> 12) & 0x0F); + //if fastest rate, attack is already completed + //do the same for slowest rate, since that allows zero to be passed for default envelope + if (utemp == 0x0F || utemp == 0x00) + { + //start envelope at full + pState->envValue = (32768<<7); + //jump right into decay + utemp = ((pState->envData >> 16) & 0x0F); + pState->envScale = getDecayScale(utemp); + pState->envState = PCM_ENV_DECAY; + pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume); + pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume); + } + //else attack has a ramp + else + { + //start the envelope very low + pState->envValue = (2<<7); + pState->currentGainLeft = 0; + pState->currentGainRight = 0; + //get envelope attack scaling value + pState->envScale = getAttackIncrement(utemp); + //go to attack state + pState->envState = PCM_ENV_ATTACK; + } + } + if (pState->envState == PCM_ENV_ATTACK) + { + //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = pState->envValue + (pState->envScale << 7); + //check envelope level and update state if needed + if (pState->envValue >= (32768<<7)) + { + pState->envValue = (32768<<7); + utemp = ((pState->envData >> 16) & 0x0F); + pState->envScale = getDecayScale(utemp); + pState->envState = PCM_ENV_DECAY; + } + } + else if (pState->envState == PCM_ENV_DECAY) + { + //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against sustain level and update state if needed + utemp = ((pState->envData >> 8) & 0x0F); + if (utemp == (EAS_U32)0x0F) + utemp = (2<<7); + else + { + utemp = ((32769<<7) >> (utemp>>1)); + } + if (pState->envValue <= utemp) + { + utemp = ((pState->envData >> 28) & 0x0F); + pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); + pState->envState = PCM_ENV_SUSTAIN; + } + } + else if (pState->envState == PCM_ENV_SUSTAIN) + { + //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against bottom level and update state if needed + if (pState->envValue <= (2<<7)) + { + //no more decay + pState->envScale = 512; + pState->envState = PCM_ENV_END; + } + } + else if (pState->envState == PCM_ENV_RELEASE) + { + //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against bottom level and update state if needed + if (pState->envValue <= (2<<7)) + { + //no more decay + pState->envScale = 512; + pState->envState = PCM_ENV_END; + } + } + else if (pState->envState == PCM_ENV_END) + { + //printf("env end\n"); + /* set state to stopping, already ramped down */ + pState->state = EAS_STATE_STOPPING; + } + + //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15); + //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15); + + /* gain to 32-bits to increase resolution on anti-zipper filter */ + /*lint -e{703} use shift for performance */ + gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS; +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{703} use shift for performance */ + gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS; +#endif + + /* calculate a new gain increment, gain target is zero if pausing */ + if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED)) + { + gainIncLeft = -pState->currentGainLeft; +#if (NUM_OUTPUT_CHANNELS == 2) + gainIncRight= -pState->currentGainRight; +#endif + } + else + { + EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume); + gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft; +#if (NUM_OUTPUT_CHANNELS == 2) + gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight; +#endif + } + + /* calculate phase increment */ + phaseInc = pState->basefreq; + + /* convert pitch cents to linear multiplier */ + if (pState->pitch) + { + temp = EAS_Calculate2toX(pState->pitch); + phaseInc = FMUL_15x15(phaseInc, temp); + } + phaseInc = phaseInc << pState->rateShift; + + /* pointer to mix buffer */ + pOut = pEASData->pMixBuffer; + + /* render a buffer of samples */ + while (numSamples--) + { + + /* interpolate an output sample */ + pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK); + + /* stereo output */ +#if (NUM_OUTPUT_CHANNELS == 2) + + /* stereo stream? */ + if (pState->flags & PCM_FLAGS_STEREO) + pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); + + /* gain scale and mix */ + /*lint -e{704} use shift instead of division */ + *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + gainLeft += gainIncLeft; + + /*lint -e{704} use shift instead of division */ + if (pState->flags & PCM_FLAGS_STEREO) + *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + else + *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + + gainRight += gainIncRight; + + /* mono output */ +#else + /* if stereo stream, decode right channel and mix to mono */ + if (pState->flags & PCM_FLAGS_STEREO) + { + pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); + + /* for mono, sum stereo ADPCM to mono */ + /*lint -e{704} use shift instead of division */ + *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + } + else + /*lint -e{704} use shift instead of division */ + *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + + gainLeft += gainIncLeft; +#endif + + /* advance phase accumulator */ + pState->phase += phaseInc; + + /* if integer part of phase accumulator is non-zero, advance to next sample */ + while (pState->phase & ~PHASE_FRAC_MASK) + { + pState->decoderL.x0 = pState->decoderL.x1; + pState->decoderR.x0 = pState->decoderR.x1; + + /* give the source a chance to continue the stream */ + if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0)) + { + pState->flags |= PCM_FLAGS_EMPTY; + (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ } + } + + /* decode the next sample */ + if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS) + return result; + + /* adjust phase by one sample */ + pState->phase -= (1L << NUM_PHASE_FRAC_BITS); + } + + } + + /* save new gain */ + /*lint -e{704} use shift instead of division */ + pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS); + +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{704} use shift instead of division */ + pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS); +#endif + + /* if pausing, set new state and notify */ + if (pState->state == EAS_STATE_PAUSING) + { + pState->state = EAS_STATE_PAUSED; + if (pState->pCallback) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); + } + + /* if out of data, set stopped state and notify */ + if (pState->bytesLeft == 0 || pState->state == EAS_STATE_STOPPING) + { + pState->state = EAS_STATE_STOPPED; + + /* do callback unless the file has already been closed */ + if (pState->pCallback && pState->fileHandle) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); + } + + if (pState->state == EAS_STATE_READY) + pState->state = EAS_STATE_PLAY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * LinearPCMDecode() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes a PCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + EAS_RESULT result; + EAS_HW_DATA_HANDLE hwInstData; + + hwInstData = ((S_EAS_DATA*) pEASData)->hwInstData; + + /* if out of data, check for loop */ + if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) + { + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) + return result; + pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; + pState->flags &= ~PCM_FLAGS_EMPTY; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "LinearPCMDecode: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } + } + + if (pState->bytesLeft) + { + + /* check format byte for 8-bit samples */ + if (pState->flags & PCM_FLAGS_8_BIT) + { + /* fetch left or mono sample */ + if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* if unsigned */ + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ + pState->decoderL.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); + } + else + { + /*lint -e{734} converting signed 8-bit to signed 16-bit */ + pState->decoderL.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); + } + pState->bytesLeft--; + + /* fetch right sample */ + if(pState->flags & PCM_FLAGS_STEREO) + { + if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* if unsigned */ + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ + pState->decoderR.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); + } + else + { + /*lint -e{734} converting signed 8-bit to signed 16-bit */ + pState->decoderR.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); + } + pState->bytesLeft--; + } + } + + /* must be 16-bit samples */ + else + { + //unsigned 16 bit currently not supported + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + return EAS_ERROR_INVALID_PCM_TYPE; + } + + /* fetch left or mono sample */ + if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderL.x1, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->bytesLeft -= 2; + + /* fetch right sample */ + if(pState->flags & PCM_FLAGS_STEREO) + { + if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderR.x1, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->bytesLeft -= 2; + } + } + } + + /* no more data, force zero samples */ + else + pState->decoderL.x1 = pState->decoderR.x1 = 0; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * LinearPCMLocate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate in a linear PCM stream + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_I32 secs, msecs; + EAS_INT shift; + + /* calculate size of sample frame */ + if (pState->flags & PCM_FLAGS_8_BIT) + shift = 0; + else + shift = 1; + if (pState->flags & PCM_FLAGS_STEREO) + shift++; + + /* break down into secs and msecs */ + secs = time / 1000; + msecs = time - (secs * 1000); + + /* calculate sample number fraction from msecs */ + temp = (msecs * pState->sampleRate); + temp = (temp >> 10) + ((temp * 49) >> 21); + + /* add integer sample count */ + temp += secs * pState->sampleRate; + + /* calculate the position based on sample frame size */ + /*lint -e{703} use shift for performance */ + temp <<= shift; + + /* past end of sample? */ + if (temp > (EAS_I32) pState->loopStart) + { + /* if not looped, flag error */ + if (pState->loopSamples == 0) + { + pState->bytesLeft = 0; + pState->flags |= PCM_FLAGS_EMPTY; + return EAS_ERROR_LOCATE_BEYOND_END; + } + + /* looped sample - calculate position in loop */ + while (temp > (EAS_I32) pState->loopStart) + temp -= (EAS_I32) pState->loopStart; + } + + /* seek to new position */ + if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) + return result; + + /* reset state */ + if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) + pState->state = EAS_STATE_READY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PESeek + *---------------------------------------------------------------------------- + * Purpose: + * Locate to a particular byte in a PCM stream + *---------------------------------------------------------------------------- + * This bit is tricky because the chunks may not be contiguous, + * so we have to rely on the parser to position in the file. We + * do this by seeking to the end of each chunk and simulating an + * empty buffer condition until we get to where we want to go. + * + * A better solution would be a parser API for re-positioning, + * but there isn't time at the moment to re-factor all the + * parsers to support a new API. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PESeek (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation) +{ + EAS_RESULT result; + + /* seek to start of audio */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + pState->bytesLeft = pState->bytesLeftLoop; + + /* skip through chunks until we find the right chunk */ + while (*pLocation > (EAS_I32) pState->bytesLeft) + { + /* seek to end of audio chunk */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", pState->bytesLeft); */ } + if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, pState->bytesLeft)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + *pLocation -= pState->bytesLeft; + pState->bytesLeft = 0; + pState->flags |= PCM_FLAGS_EMPTY; + + /* retrieve more data */ + if (pState->pCallback) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: bytesLeft=%d, byte location = %d\n", pState->bytesLeft, *pLocation); */ } + + /* no more samples */ + if (pState->bytesLeft == 0) + return EAS_ERROR_LOCATE_BEYOND_END; + } + + /* seek to new offset in current chunk */ + if (*pLocation > 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", *pLocation); */ } + if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, *pLocation)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + + /* if not streamed, calculate number of bytes left */ + if (pState->flags & PCM_FLAGS_STREAMING) + pState->bytesLeft = 0x7fffffff; + else + pState->bytesLeft -= *pLocation; + } + return EAS_SUCCESS; +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcm.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcm.h new file mode 100755 index 0000000..4fc77e9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcm.h @@ -0,0 +1,359 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcm.h + * + * Contents and purpose: + * External function prototypes for eas_pcm.c module + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PCM_H +#define _EAS_PCM_H + +/* default gain setting - roughly unity gain */ +#define PCM_DEFAULT_GAIN_SETTING 0x6000 + +typedef struct s_pcm_state_tag *EAS_PCM_HANDLE; +typedef void (*EAS_PCM_CALLBACK) (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR cbInstData, EAS_PCM_HANDLE pcmHandle, EAS_STATE state); + +/* parameters for EAS_PEOpenStream */ +typedef struct s_pcm_open_params_tag +{ + EAS_FILE_HANDLE fileHandle; + EAS_I32 decoder; + EAS_U32 sampleRate; + EAS_I32 size; + EAS_U32 loopStart; + EAS_U32 loopSamples; + EAS_I32 blockSize; + EAS_U32 flags; + EAS_U32 envData; + EAS_I16 volume; + EAS_PCM_CALLBACK pCallbackFunc; + EAS_VOID_PTR cbInstData; + } S_PCM_OPEN_PARAMS; + +/*---------------------------------------------------------------------------- + * EAS_PEInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEInit (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_PEShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEShutdown (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_PEOpenStream() + *---------------------------------------------------------------------------- + * Purpose: + * Starts up a PCM playback + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEOpenStream (EAS_DATA_HANDLE pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle); + +/*---------------------------------------------------------------------------- + * EAS_PEContinueStream() + *---------------------------------------------------------------------------- + * Purpose: + * Continues a PCM stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEContinueStream (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_I32 size); + +/*---------------------------------------------------------------------------- + * EAS_PEGetFileHandle() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the file handle of a stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEGetFileHandle (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_FILE_HANDLE *pFileHandle); + +/*---------------------------------------------------------------------------- + * EAS_PERender() + *---------------------------------------------------------------------------- + * Purpose: + * Render a buffer of PCM audio + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERender (EAS_DATA_HANDLE pEASData, EAS_I32 numSamples); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateParams() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch and volume parameters using MIDI controls + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEUpdateParams (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight); + +/*---------------------------------------------------------------------------- + * EAS_PELocate() + *---------------------------------------------------------------------------- + * Purpose: + * This function seeks to the requested place in the file. Accuracy + * is dependent on the sample rate and block size. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pState - stream handle + * time - media time in milliseconds + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PELocate (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I32 time); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Update the volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdateVolume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdatePitch() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch parameter for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * pState - pointer to S_PCM_STATE for this stream + * pitch - new pitch value in pitch cents + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdatePitch (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch); + +/*---------------------------------------------------------------------------- + * EAS_PEState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEState (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_PEClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEClose (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEReset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEReset (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEPause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and pause rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEPause (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEResume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PERelease() + *---------------------------------------------------------------------------- + * Purpose: + * Put the PCM stream envelope into release. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERelease (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +#endif /* end _EAS_PCM_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcmdata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcmdata.c new file mode 100755 index 0000000..2d85ac2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcmdata.c @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcmdata.c + * + * Contents and purpose: + * Contains the static data for the PCM engine. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" + +/* static data allocation */ +S_PCM_STATE eas_PCMData[MAX_PCM_STREAMS]; + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcmdata.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcmdata.h new file mode 100755 index 0000000..ae18d6d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_pcmdata.h @@ -0,0 +1,157 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcmdata.h + * + * Contents and purpose: + * Data declarations for the PCM engine + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PCMDATA_H +#define _EAS_PCMDATA_H + +/* sets the maximum number of simultaneous PCM streams */ +#ifndef MAX_PCM_STREAMS +#define MAX_PCM_STREAMS 16 +#define PCM_STREAM_THRESHOLD (MAX_PCM_STREAMS - 4) +#endif + +/* coefficents for high-pass filter in ADPCM */ +#define INTEGRATOR_COEFFICIENT 100 /* coefficient for leaky integrator */ + +/* additional flags in S_PCM_STATE.flags used internal to module */ +#define PCM_FLAGS_EMPTY 0x01000000 /* unsigned format */ + +/*---------------------------------------------------------------------------- + * S_PCM_STATE + * + * Retains state information for PCM streams. + *---------------------------------------------------------------------------- +*/ +typedef struct s_decoder_state_tag +{ + EAS_I32 output; /* last output for DC offset filter */ + EAS_I32 acc; /* accumulator for DC offset filter */ + EAS_I32 step; /* current ADPCM step size */ + EAS_PCM x1; /* current generated sample */ + EAS_PCM x0; /* previous generated sample */ +} S_DECODER_STATE; + +typedef enum +{ + PCM_ENV_START = 0, + PCM_ENV_ATTACK, + PCM_ENV_DECAY, + PCM_ENV_SUSTAIN, + PCM_ENV_RELEASE, + PCM_ENV_END +} E_PCM_ENV_STATE; + +typedef struct s_pcm_state_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + EAS_FILE_HANDLE fileHandle; /* pointer to input file */ + EAS_PCM_CALLBACK pCallback; /* pointer to callback function */ + EAS_VOID_PTR cbInstData; /* instance data for callback function */ + struct s_decoder_interface_tag EAS_CONST * pDecoder; /* pointer to decoder interface */ + EAS_STATE state; /* stream state */ + EAS_I32 time; /* media time */ + EAS_I32 startPos; /* start of PCM stream */ + EAS_I32 loopLocation; /* file location where loop starts */ + EAS_I32 byteCount; /* size of file */ + EAS_U32 loopStart; /* loop start, offset in samples from startPos */ + /* NOTE: For CMF, we use this to store total sample size */ + EAS_U32 loopSamples; /* total loop length, in samples, 0 means no loop */ + /* NOTE: For CMF, non-zero means looped */ + EAS_U32 samplesInLoop; /* samples left in the loop to play back */ + EAS_I32 samplesTilLoop; /* samples left to play until top of loop */ + EAS_I32 bytesLeft; /* count of bytes left in stream */ + EAS_I32 bytesLeftLoop; /* count of bytes left in stream, value at start of loop */ + EAS_U32 phase; /* current phase for interpolator */ + EAS_U32 basefreq; /* frequency multiplier */ + EAS_U32 flags; /* stream flags */ + EAS_U32 envData; /* envelope data (and LFO data) */ + EAS_U32 envValue; /* current envelope value */ + EAS_U32 envScale; /* current envelope scale */ + EAS_U32 startOrder; /* start order index, first is 0, next is 1, etc. */ + S_DECODER_STATE decoderL; /* left (mono) ADPCM state */ + S_DECODER_STATE decoderR; /* right ADPCM state */ + S_DECODER_STATE decoderLLoop; /* left (mono) ADPCM state, value at start of loop */ + S_DECODER_STATE decoderRLoop; /* right ADPCM state, value at start of loop */ + E_PCM_ENV_STATE envState; /* current envelope state */ + EAS_I16 volume; /* volume for stream */ + EAS_I16 pitch; /* relative pitch in cents - zero is unity playback */ + EAS_I16 gainLeft; /* requested gain */ + EAS_I16 gainRight; /* requested gain */ + EAS_I16 currentGainLeft; /* current gain for anti-zipper filter */ + EAS_I16 currentGainRight; /* current gain for anti-zipper filter */ + EAS_U16 blockSize; /* block size for ADPCM decoder */ + EAS_U16 blockCount; /* block counter for ADPCM decoder */ + EAS_U16 sampleRate; /* input sample rate */ + EAS_U8 srcByte; /* source byte */ + EAS_U8 msBitCount; /* count keeps track of MS bits */ + EAS_U8 msBitMask; /* mask keeps track of MS bits */ + EAS_U8 msBitValue; /* value keeps track of MS bits */ + EAS_U8 msBitCountLoop; /* count keeps track of MS bits, value at loop start */ + EAS_U8 msBitMaskLoop; /* mask keeps track of MS bits, value at loop start */ + EAS_U8 msBitValueLoop; /* value keeps track of MS bits, value at loop start */ + EAS_BOOL8 hiNibble; /* indicates high/low nibble is next */ + EAS_BOOL8 hiNibbleLoop; /* indicates high/low nibble is next, value loop start */ + EAS_U8 rateShift; /* for playback rate greater than 1.0 */ +} S_PCM_STATE; + +/*---------------------------------------------------------------------------- + * S_DECODER_INTERFACE + * + * Generic interface for audio decoders + *---------------------------------------------------------------------------- +*/ +typedef struct s_decoder_interface_tag +{ + EAS_RESULT (* EAS_CONST pfInit)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); + EAS_RESULT (* EAS_CONST pfDecodeSample)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); + EAS_RESULT (* EAS_CONST pfLocate)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); +} S_DECODER_INTERFACE; + + +/* header chunk for SMAF ADPCM */ +#define TAG_YAMAHA_ADPCM 0x4d776100 +#define TAG_MASK 0xffffff00 +#define TAG_RIFF_FILE 0x52494646 +#define TAG_WAVE_CHUNK 0x57415645 +#define TAG_FMT_CHUNK 0x666d7420 + +/*---------------------------------------------------------------------------- + * EAS_PESeek + *---------------------------------------------------------------------------- + * Purpose: + * Locate to a particular byte in a PCM stream + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PESeek (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation); + +#endif /* _EAS_PCMDATA_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_public.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_public.c new file mode 100755 index 0000000..394a9a1 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_public.c @@ -0,0 +1,2597 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_public.c + * + * Contents and purpose: + * Contains EAS library public interface + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 842 $ + * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_synthcfg.h" +#include "eas.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" +#include "eas_data.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_midi.h" +#include "eas_mixer.h" +#include "eas_build.h" +#include "eas_vm_protos.h" +#include "eas_math.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + +#ifdef DLS_SYNTHESIZER +#include "eas_mdls.h" +#endif + +/* number of events to parse before calling EAS_HWYield function */ +#define YIELD_EVENT_COUNT 10 + +/*---------------------------------------------------------------------------- + * easLibConfig + * + * This structure is available through the EAS public interface to allow + * the user to check the configuration of the library. + *---------------------------------------------------------------------------- +*/ +static const S_EAS_LIB_CONFIG easLibConfig = +{ + LIB_VERSION, +#ifdef _CHECKED_BUILD + EAS_TRUE, +#else + EAS_FALSE, +#endif + MAX_SYNTH_VOICES, + NUM_OUTPUT_CHANNELS, + _OUTPUT_SAMPLE_RATE, + BUFFER_SIZE_IN_MONO_SAMPLES, +#ifdef _FILTER_ENABLED + EAS_TRUE, +#else + EAS_FALSE, +#endif + _BUILD_TIME_, + _BUILD_VERSION_ +}; + +/* local prototypes */ +static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, S_EAS_STREAM *pStream, EAS_U32 endTime, EAS_INT parseMode); + +/*---------------------------------------------------------------------------- + * EAS_SetStreamParameter + *---------------------------------------------------------------------------- + * Sets the specified parameter in the stream. Allows access to + * customizable settings within the individual file parsers. + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * param - enumerated parameter (see eas_parser.h) + * value - new value + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 value) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfSetData) + return (*pParserModule->pfSetData)(pEASData, pStream->handle, param, value); + return EAS_ERROR_FEATURE_NOT_AVAILABLE; +} + +/*---------------------------------------------------------------------------- + * EAS_GetStreamParameter + *---------------------------------------------------------------------------- + * Sets the specified parameter in the stream. Allows access to + * customizable settings within the individual file parsers. + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * param - enumerated parameter (see eas_parser.h) + * pValue - pointer to variable to receive current setting + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_GetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 *pValue) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfGetData) + return (*pParserModule->pfGetData)(pEASData, pStream->handle, param, pValue); + return EAS_ERROR_FEATURE_NOT_AVAILABLE; +} + +/*---------------------------------------------------------------------------- + * EAS_StreamReady() + *---------------------------------------------------------------------------- + * This routine sets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_SetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * set the parameter directly on the synth. This eliminates duplicate + * code in the parser. + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_StreamReady (S_EAS_DATA *pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfState(pEASData, pStream->handle, &state) != EAS_SUCCESS) + return EAS_FALSE; + return (state < EAS_STATE_OPEN); +} + +/*---------------------------------------------------------------------------- + * EAS_IntSetStrmParam() + *---------------------------------------------------------------------------- + * This routine sets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_SetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * set the parameter directly on the synth. This eliminates duplicate + * code in the parser. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value) +{ + S_SYNTH *pSynth; + + /* try to set the parameter using stream interface */ + if (EAS_SetStreamParameter(pEASData, pStream, param, value) == EAS_SUCCESS) + return EAS_SUCCESS; + + /* get a pointer to the synth object and set it directly */ + /*lint -e{740} we are cheating by passing a pointer through this interface */ + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + switch (param) + { + +#ifdef DLS_SYNTHESIZER + case PARSER_DATA_DLS_COLLECTION: + { + EAS_RESULT result = VMSetDLSLib(pSynth, (EAS_DLSLIB_HANDLE) value); + if (result == EAS_SUCCESS) + { + DLSAddRef((S_DLS*) value); + VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); + } + return result; + } +#endif + + case PARSER_DATA_EAS_LIBRARY: + return VMSetEASLib(pSynth, (EAS_SNDLIB_HANDLE) value); + + case PARSER_DATA_POLYPHONY: + return VMSetPolyphony(pEASData->pVoiceMgr, pSynth, value); + + case PARSER_DATA_PRIORITY: + return VMSetPriority(pEASData->pVoiceMgr, pSynth, value); + + case PARSER_DATA_TRANSPOSITION: + VMSetTranposition(pSynth, value); + break; + + case PARSER_DATA_VOLUME: + VMSetVolume(pSynth, (EAS_U16) value); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_IntGetStrmParam() + *---------------------------------------------------------------------------- + * This routine gets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_GetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * get the parameter directly on the synth. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_IntGetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 *pValue) +{ + S_SYNTH *pSynth; + + /* try to set the parameter */ + if (EAS_GetStreamParameter(pEASData, pStream, param, pValue) == EAS_SUCCESS) + return EAS_SUCCESS; + + /* get a pointer to the synth object and retrieve data directly */ + /*lint -e{740} we are cheating by passing a pointer through this interface */ + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + switch (param) + { + case PARSER_DATA_POLYPHONY: + return VMGetPolyphony(pEASData->pVoiceMgr, pSynth, pValue); + + case PARSER_DATA_PRIORITY: + return VMGetPriority(pEASData->pVoiceMgr, pSynth, pValue); + + case PARSER_DATA_TRANSPOSITION: + VMGetTranposition(pSynth, pValue); + break; + + case PARSER_DATA_NOTE_COUNT: + *pValue = VMGetNoteCount(pSynth); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_AllocateStream() + *---------------------------------------------------------------------------- + * Purpose: + * Allocates a stream handle + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_INT EAS_AllocateStream (EAS_DATA_HANDLE pEASData) +{ + EAS_INT streamNum; + + /* check for static allocation, only one stream allowed */ + if (pEASData->staticMemoryModel) + { + if (pEASData->streams[0].handle != NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Attempt to open multiple streams in static model\n"); */ } + return -1; + } + return 0; + } + + /* dynamic model */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + if (pEASData->streams[streamNum].handle == NULL) + break; + if (streamNum == MAX_NUMBER_STREAMS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Exceeded maximum number of open streams\n"); */ } + return -1; + } + return streamNum; +} + +/*---------------------------------------------------------------------------- + * EAS_InitStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize a stream + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void EAS_InitStream (S_EAS_STREAM *pStream, EAS_VOID_PTR pParserModule, EAS_VOID_PTR streamHandle) +{ + pStream->pParserModule = pParserModule; + pStream->handle = streamHandle; + pStream->time = 0; + pStream->frameLength = AUDIO_FRAME_LENGTH; + pStream->repeatCount = 0; + pStream->volume = DEFAULT_STREAM_VOLUME; +} + +/*---------------------------------------------------------------------------- + * EAS_Config() + *---------------------------------------------------------------------------- + * Purpose: + * Returns a pointer to a structure containing the configuration options + * in this library build. + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void) +{ + return &easLibConfig; +} + +/*---------------------------------------------------------------------------- + * EAS_Init() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the synthesizer library + * + * Inputs: + * ppEASData - pointer to data handle variable for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData) +{ + EAS_HW_DATA_HANDLE pHWInstData; + EAS_RESULT result; + S_EAS_DATA *pEASData; + EAS_INT module; + EAS_BOOL staticMemoryModel; + + /* get the memory model */ + staticMemoryModel = EAS_CMStaticMemoryModel(); + + /* initialize the host wrapper interface */ + *ppEASData = NULL; + if ((result = EAS_HWInit(&pHWInstData)) != EAS_SUCCESS) + return result; + + /* check Configuration Module for S_EAS_DATA allocation */ + if (staticMemoryModel) + pEASData = EAS_CMEnumData(EAS_CM_EAS_DATA); + else + pEASData = EAS_HWMalloc(pHWInstData, sizeof(S_EAS_DATA)); + if (!pEASData) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate EAS library memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* initialize some data */ + EAS_HWMemSet(pEASData, 0, sizeof(S_EAS_DATA)); + pEASData->staticMemoryModel = (EAS_BOOL8) staticMemoryModel; + pEASData->hwInstData = pHWInstData; + pEASData->renderTime = 0; + + /* set header search flag */ +#ifdef FILE_HEADER_SEARCH + pEASData->searchHeaderFlag = EAS_TRUE; +#endif + + /* initalize parameters */ + EAS_SetVolume(pEASData, NULL, DEFAULT_VOLUME); + +#ifdef _METRICS_ENABLED + /* initalize the metrics module */ + pEASData->pMetricsModule = EAS_CMEnumOptModules(EAS_MODULE_METRICS); + if (pEASData->pMetricsModule != NULL) + { + if ((result = (*pEASData->pMetricsModule->pfInit)(pEASData, &pEASData->pMetricsData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld initializing metrics module\n", result); */ } + return result; + } + } +#endif + + /* initailize the voice manager & synthesizer */ + if ((result = VMInitialize(pEASData)) != EAS_SUCCESS) + return result; + + /* initialize mix engine */ + if ((result = EAS_MixEngineInit(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld starting up mix engine\n", result); */ } + return result; + } + + /* initialize effects modules */ + for (module = 0; module < NUM_EFFECTS_MODULES; module++) + { + pEASData->effectsModules[module].effect = EAS_CMEnumFXModules(module); + if (pEASData->effectsModules[module].effect != NULL) + { + if ((result = (*pEASData->effectsModules[module].effect->pfInit)(pEASData, &pEASData->effectsModules[module].effectData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Initialization of effects module %d returned %d\n", module, result); */ } + return result; + } + } + } + + /* initialize PCM engine */ + if ((result = EAS_PEInit(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_PEInit failed with error code %ld\n", result); */ } + return result; + } + + /* return instance data pointer to host */ + *ppEASData = pEASData; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_Shutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the library. Deallocates any memory associated with the + * synthesizer (dynamic memory model only) + * + * Inputs: + * pEASData - handle to data for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData) +{ + EAS_HW_DATA_HANDLE hwInstData; + EAS_RESULT result, reportResult; + EAS_INT i; + + /* establish pointers */ + hwInstData = pEASData->hwInstData; + + /* check for NULL handle */ + if (!pEASData) + return EAS_ERROR_HANDLE_INTEGRITY; + + /* if there are streams open, close them */ + reportResult = EAS_SUCCESS; + for (i = 0; i < MAX_NUMBER_STREAMS; i++) + { + if (pEASData->streams[i].pParserModule && pEASData->streams[i].handle) + { + if ((result = (*((S_FILE_PARSER_INTERFACE*)(pEASData->streams[i].pParserModule))->pfClose)(pEASData, pEASData->streams[i].handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down parser module\n", result); */ } + reportResult = result; + } + } + } + + /* shutdown PCM engine */ + if ((result = EAS_PEShutdown(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down PCM engine\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + + /* shutdown mix engine */ + if ((result = EAS_MixEngineShutdown(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down mix engine\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + + /* shutdown effects modules */ + for (i = 0; i < NUM_EFFECTS_MODULES; i++) + { + if (pEASData->effectsModules[i].effect) + { + if ((result = (*pEASData->effectsModules[i].effect->pfShutdown)(pEASData, pEASData->effectsModules[i].effectData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Shutdown of effects module %d returned %d\n", i, result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + } + + /* shutdown the voice manager & synthesizer */ + VMShutdown(pEASData); + +#ifdef _METRICS_ENABLED + /* shutdown the metrics module */ + if (pEASData->pMetricsModule != NULL) + { + if ((result = (*pEASData->pMetricsModule->pfShutdown)(pEASData, pEASData->pMetricsData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down metrics module\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } +#endif + + /* release allocated memory */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(hwInstData, pEASData); + + /* shutdown host wrappers */ + if (hwInstData) + { + if ((result = EAS_HWShutdown(hwInstData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down host wrappers\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + + return reportResult; +} + +#ifdef JET_INTERFACE +/*---------------------------------------------------------------------------- + * EAS_OpenJETStream() + *---------------------------------------------------------------------------- + * Private interface for JET to open an SMF stream with an offset + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for SMF parser */ + *ppStream = NULL; + streamHandle = NULL; + pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(0); + if (pParserModule == NULL) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* see if SMF parser recognizes the file */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, offset)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser recognized the file, return the handle */ + if (streamHandle) + { + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_OpenFile() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_FILE_HANDLE fileHandle; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + EAS_INT moduleNum; + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for file parsers */ + pParserModule = NULL; + *ppStream = NULL; + streamHandle = NULL; + for (moduleNum = 0; ; moduleNum++) + { + pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(moduleNum); + if (pParserModule == NULL) + break; + + /* see if this parser recognizes it */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser recognized the file, return the handle */ + if (streamHandle) + { + + /* save the parser pointer and file handle */ + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + /* rewind the file for the next parser */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, 0L)) != EAS_SUCCESS) + return result; + } + + /* no parser was able to recognize the file, close it and return an error */ + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * EAS_MMAPIToneControl() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a ToneControl file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_FILE_HANDLE fileHandle; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + + /* check if the tone control parser is available */ + *ppStream = NULL; + streamHandle = NULL; + pParserModule = EAS_CMEnumOptModules(EAS_MODULE_MMAPI_TONE_CONTROL); + if (pParserModule == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_MMAPIToneControl: ToneControl parser not available\n"); */ } + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + } + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* see if ToneControl parser recognizes it */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser accepted the file, return the handle */ + if (streamHandle) + { + + /* save the parser pointer and file handle */ + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + /* parser did not recognize the file, close it and return an error */ + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} + +/*---------------------------------------------------------------------------- + * EAS_GetWaveFmtChunk + *---------------------------------------------------------------------------- + * Helper function to retrieve WAVE file fmt chunk for MMAPI + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * pFmtChunk - pointer to variable to receive current setting + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_VOID_PTR *ppFmtChunk) +{ + EAS_RESULT result; + EAS_I32 value; + + if ((result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FORMAT, &value)) != EAS_SUCCESS) + return result; + *ppFmtChunk = (EAS_VOID_PTR) value; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_GetFileType + *---------------------------------------------------------------------------- + * Returns the file type (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * pFileType - pointer to variable to receive file type + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetFileType (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 *pFileType) +{ + if (!EAS_StreamReady (pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FILE_TYPE, pFileType); +} + +/*---------------------------------------------------------------------------- + * EAS_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the synthesizer to play the file or stream. Parses the first + * frame of data from the file and arms the synthesizer. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + /* prepare the stream */ + if (state == EAS_STATE_OPEN) + { + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + result = (*pParserModule->pfPrepare)(pEASData, pStream->handle); + + /* set volume */ + if (result == EAS_SUCCESS) + result = EAS_SetVolume(pEASData, pStream, pStream->volume); + } + else + result = EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_Render() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the Midi data and render PCM audio data. + * + * Inputs: + * pEASData - buffer for internal EAS data + * pOut - output buffer pointer + * nNumRequested - requested num samples to generate + * pnNumGenerated - actual number of samples generated + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_I32 voicesRendered; + EAS_STATE parserState; + EAS_INT streamNum; + + /* assume no samples generated and reset workload */ + *pNumGenerated = 0; + VMInitWorkload(pEASData->pVoiceMgr); + + /* no support for other buffer sizes yet */ + if (numRequested != BUFFER_SIZE_IN_MONO_SAMPLES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "This library supports only %ld samples in buffer, host requested %ld samples\n", + (EAS_I32) BUFFER_SIZE_IN_MONO_SAMPLES, numRequested); */ } + return EAS_BUFFER_SIZE_MISMATCH; + } + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); +#endif + + /* prep the frame buffer, do mix engine prep only if TRUE */ +#ifdef _SPLIT_ARCHITECTURE + if (VMStartFrame(pEASData)) + EAS_MixEnginePrep(pEASData, numRequested); +#else + /* prep the mix engine */ + EAS_MixEnginePrep(pEASData, numRequested); +#endif + + /* save the output buffer pointer */ + pEASData->pOutputAudioBuffer = pOut; + + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); +#endif + + /* if we haven't finished parsing from last time, do it now */ + /* need to parse another frame of events before we render again */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + { + /* clear the locate flag */ + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_LOCATE; + + if (pEASData->streams[streamNum].pParserModule) + { + + /* establish pointer to parser module */ + pParserModule = pEASData->streams[streamNum].pParserModule; + + /* handle pause */ + if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PAUSE) + { + if (pParserModule->pfPause) + result = pParserModule->pfPause(pEASData, pEASData->streams[streamNum].handle); + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PAUSE; + } + + /* get current state */ + if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) + return result; + + /* handle resume */ + if (parserState == EAS_STATE_PAUSED) + { + if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_RESUME) + { + if (pParserModule->pfResume) + result = pParserModule->pfResume(pEASData, pEASData->streams[streamNum].handle); + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_RESUME; + } + } + + /* if necessary, parse stream */ + if ((pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PARSED) == 0) + if ((result = EAS_ParseEvents(pEASData, &pEASData->streams[streamNum], pEASData->streams[streamNum].time + pEASData->streams[streamNum].frameLength, eParserModePlay)) != EAS_SUCCESS) + return result; + + /* check for an early abort */ + if ((pEASData->streams[streamNum].streamFlags) == 0) + { + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); +#endif + + return EAS_SUCCESS; + } + + /* check for repeat */ + if (pEASData->streams[streamNum].repeatCount) + { + + /* check for stopped state */ + if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) + return result; + if (parserState == EAS_STATE_STOPPED) + { + + /* decrement repeat count, unless it is negative */ + if (pEASData->streams[streamNum].repeatCount > 0) + pEASData->streams[streamNum].repeatCount--; + + /* reset the parser */ + if ((result = (*pParserModule->pfReset)(pEASData, pEASData->streams[streamNum].handle)) != EAS_SUCCESS) + return result; + pEASData->streams[streamNum].time = 0; + } + } + } + } + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); +#endif + +#ifdef _METRICS_ENABLED + /* start the render timer */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); +#endif + + /* render audio */ + if ((result = VMRender(pEASData->pVoiceMgr, BUFFER_SIZE_IN_MONO_SAMPLES, pEASData->pMixBuffer, &voicesRendered)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "pfRender function returned error %ld\n", result); */ } + return result; + } + +#ifdef _METRICS_ENABLED + /* stop the render timer */ + if (pEASData->pMetricsData) { + (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_FRAME_COUNT, 1); + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); + (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_TOTAL_VOICE_COUNT, (EAS_U32) voicesRendered); + (void)(*pEASData->pMetricsModule->pfRecordMaxValue)(pEASData->pMetricsData, EAS_PM_MAX_VOICES, (EAS_U32) voicesRendered); + } +#endif + + //2 Do we really need frameParsed? + /* need to parse another frame of events before we render again */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + if (pEASData->streams[streamNum].pParserModule != NULL) + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PARSED; + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); +#endif + + /* render PCM audio */ + if ((result = EAS_PERender(pEASData, numRequested)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_PERender returned error %ld\n", result); */ } + return result; + } + +#ifdef _METRICS_ENABLED + /* stop the stream timer */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); +#endif + +#ifdef _METRICS_ENABLED + /* start the post timer */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); +#endif + + /* for split architecture, send DSP vectors. Do post only if return is TRUE */ +#ifdef _SPLIT_ARCHITECTURE + if (VMEndFrame(pEASData)) + { + /* now do post-processing */ + EAS_MixEnginePost(pEASData, numRequested); + *pNumGenerated = numRequested; + } +#else + /* now do post-processing */ + EAS_MixEnginePost(pEASData, numRequested); + *pNumGenerated = numRequested; +#endif + +#ifdef _METRICS_ENABLED + /* stop the post timer */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); +#endif + + /* advance render time */ + pEASData->renderTime += AUDIO_FRAME_LENGTH; + +#if 0 + /* dump workload for debug */ + if (pEASData->pVoiceMgr->workload) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Workload = %d\n", pEASData->pVoiceMgr->workload); */ } +#endif + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + { + PERF_TIMER temp; + temp = (*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); + + /* if max render time, record the number of voices and time */ + if ((*pEASData->pMetricsModule->pfRecordMaxValue) + (pEASData->pMetricsData, EAS_PM_MAX_CYCLES, (EAS_U32) temp)) + { + (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_VOICES, (EAS_U32) voicesRendered); + (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_TIME, (EAS_I32) (pEASData->renderTime >> 8)); + } + } +#endif + +#ifdef JET_INTERFACE + /* let JET to do its thing */ + if (pEASData->jetHandle != NULL) + { + result = JET_Process(pEASData); + if (result != EAS_SUCCESS) + return result; + } +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Set the selected stream to repeat. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * repeatCount - repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 repeatCount) +{ + pStream->repeatCount = repeatCount; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the current repeat count for the selected stream. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * pRrepeatCount - pointer to variable to hold repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pRepeatCount) +{ + *pRepeatCount = pStream->repeatCount; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPlaybackRate() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the playback rate. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U32 rate) +{ + + /* check range */ + if ((rate < (1 << 27)) || (rate > (1 << 29))) + return EAS_ERROR_INVALID_PARAMETER; + + /* calculate new frame length + * + * NOTE: The maximum frame length we can accomodate based on a + * maximum rate of 2.0 (2^28) is 2047 (2^13-1). To accomodate a + * longer frame length or a higher maximum rate, the fixed point + * divide below will need to be adjusted + */ + pStream->frameLength = (AUDIO_FRAME_LENGTH * (rate >> 8)) >> 20; + + /* notify stream of new playback rate */ + EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_PLAYBACK_RATE, (EAS_I32) rate); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetTransposition) + *---------------------------------------------------------------------------- + * Purpose: + * Sets the key tranposition for the synthesizer. Transposes all + * melodic instruments by the specified amount. Range is limited + * to +/-12 semitones. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * transposition - +/-12 semitones + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 transposition) +{ + + /* check range */ + if ((transposition < -12) || (transposition > 12)) + return EAS_ERROR_INVALID_PARAMETER; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_TRANSPOSITION, transposition); +} + +/*---------------------------------------------------------------------------- + * EAS_ParseEvents() + *---------------------------------------------------------------------------- + * Purpose: + * Parse events in the current streams until the desired time is reached. + * + * Inputs: + * pEASData - buffer for internal EAS data + * endTime - stop parsing if this time is reached + * parseMode - play, locate, or metadata + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_U32 endTime, EAS_INT parseMode) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_I32 parserState; + EAS_BOOL done; + EAS_INT yieldCount = YIELD_EVENT_COUNT; + EAS_U32 time = 0; + + /* does this parser have a time function? */ + pParserModule = pStream->pParserModule; + if (pParserModule->pfTime == NULL) + { + /* check state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) + return result; + /* if play state, advance time */ + if ((parserState >= EAS_STATE_READY) && (parserState <= EAS_STATE_PAUSING)) + pStream->time += pStream->frameLength; + done = EAS_TRUE; + } + + /* assume we're not done, in case we abort out */ + else + { + pStream->streamFlags &= ~STREAM_FLAGS_PARSED; + done = EAS_FALSE; + } + + while (!done) + { + + /* check for stopped state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) + return result; + if (parserState > EAS_STATE_PLAY) + { + /* save current time if we're not in play mode */ + if (parseMode != eParserModePlay) + pStream->time = time << 8; + done = EAS_TRUE; + break; + } + + /* get the next event time */ + if (pParserModule->pfTime) + { + if ((result = (*pParserModule->pfTime)(pEASData, pStream->handle, &time)) != EAS_SUCCESS) + return result; + + /* if next event is within this frame, parse it */ + if (time < (endTime >> 8)) + { + + /* parse the next event */ + if (pParserModule->pfEvent) + if ((result = (*pParserModule->pfEvent)(pEASData, pStream->handle, parseMode)) != EAS_SUCCESS) + return result; + } + + /* no more events in this frame, advance time */ + else + { + pStream->time = endTime; + done = EAS_TRUE; + } + } + + /* check for max workload exceeded */ + if (VMCheckWorkload(pEASData->pVoiceMgr)) + { + /* stop even though we may not have parsed + * all the events in this frame. The parser will try to + * catch up on the next frame. + */ + break; + } + + /* give host a chance for an early abort */ + if (--yieldCount == 0) + { + if (EAS_HWYield(pEASData->hwInstData)) + break; + yieldCount = YIELD_EVENT_COUNT; + } + } + + /* if no early abort, parsing is complete for this frame */ + if (done) + pStream->streamFlags |= STREAM_FLAGS_PARSED; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_ParseMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * playLength - pointer to variable to store the play length (in msecs) + * + * Outputs: + * + * + * Side Effects: + * - resets the parser to the start of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *playLength) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_STATE state; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check parser state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) + return result; + if (state >= EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* if parser has metadata function, use that */ + if (pParserModule->pfGetMetaData != NULL) + return pParserModule->pfGetMetaData(pEASData, pStream->handle, playLength); + + /* reset the parser to the beginning */ + if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) + return result; + + /* parse the file to end */ + pStream->time = 0; + VMInitWorkload(pEASData->pVoiceMgr); + if ((result = EAS_ParseEvents(pEASData, pStream, 0x7fffffff, eParserModeMetaData)) != EAS_SUCCESS) + return result; + + /* get the parser time */ + if ((result = EAS_GetLocation(pEASData, pStream, playLength)) != EAS_SUCCESS) + return result; + + /* reset the parser to the beginning */ + pStream->time = 0; + return (*pParserModule->pfReset)(pEASData, pStream->handle); +} + +/*---------------------------------------------------------------------------- + * EAS_RegisterMetaDataCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers a metadata callback function for parsed metadata. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * cbFunc - pointer to host callback function + * metaDataBuffer - pointer to metadata buffer + * metaDataBufSize - maximum size of the metadata buffer + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( + EAS_DATA_HANDLE pEASData, + EAS_HANDLE pStream, + EAS_METADATA_CBFUNC cbFunc, + char *metaDataBuffer, + EAS_I32 metaDataBufSize, + EAS_VOID_PTR pUserData) +{ + S_METADATA_CB metadata; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* register callback function */ + metadata.callback = cbFunc; + metadata.buffer = metaDataBuffer; + metadata.bufferSize = metaDataBufSize; + metadata.pUserData = pUserData; + return EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_METADATA_CB, (EAS_I32) &metadata); +} + +/*---------------------------------------------------------------------------- + * EAS_GetNoteCount () + *---------------------------------------------------------------------------- + * Returns the total number of notes played in this stream + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_NOTE_COUNT, pNoteCount); +} + +/*---------------------------------------------------------------------------- + * EAS_CloseFile() + *---------------------------------------------------------------------------- + * Purpose: + * Closes an audio file or stream. Playback should have either paused or + * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + + /* call the close function */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + result = (*pParserModule->pfClose)(pEASData, pStream->handle); + + /* clear the handle and parser interface pointer */ + pStream->handle = NULL; + pStream->pParserModule = NULL; + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_OpenMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to variable to hold file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *ppStream, EAS_HANDLE streamHandle) +{ + EAS_RESULT result; + S_INTERACTIVE_MIDI *pMIDIStream; + EAS_INT streamNum; + + /* initialize some pointers */ + *ppStream = NULL; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for S_EAS_DATA allocation */ + if (pEASData->staticMemoryModel) + pMIDIStream = EAS_CMEnumData(EAS_CM_MIDI_STREAM_DATA); + else + pMIDIStream = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_INTERACTIVE_MIDI)); + + /* allocate dynamic memory */ + if (!pMIDIStream) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate MIDI stream data\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* zero the memory to insure complete initialization */ + EAS_HWMemSet(pMIDIStream, 0, sizeof(S_INTERACTIVE_MIDI)); + EAS_InitStream(&pEASData->streams[streamNum], NULL, pMIDIStream); + + /* instantiate a new synthesizer */ + if (streamHandle == NULL) + { + result = VMInitMIDI(pEASData, &pMIDIStream->pSynth); + } + + /* use an existing synthesizer */ + else + { + EAS_I32 value; + result = EAS_GetStreamParameter(pEASData, streamHandle, PARSER_DATA_SYNTH_HANDLE, &value); + pMIDIStream->pSynth = (S_SYNTH*) value; + VMIncRefCount(pMIDIStream->pSynth); + } + if (result != EAS_SUCCESS) + { + EAS_CloseMIDIStream(pEASData, &pEASData->streams[streamNum]); + return result; + } + + /* initialize the MIDI stream data */ + EAS_InitMIDIStream(&pMIDIStream->stream); + + *ppStream = (EAS_HANDLE) &pEASData->streams[streamNum]; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_WriteMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Send data to the MIDI stream device + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - stream handle + * pBuffer - pointer to buffer + * count - number of bytes to write + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 *pBuffer, EAS_I32 count) +{ + S_INTERACTIVE_MIDI *pMIDIStream; + EAS_RESULT result; + + pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; + + /* send the entire buffer */ + while (count--) + { + if ((result = EAS_ParseMIDIStream(pEASData, pMIDIStream->pSynth, &pMIDIStream->stream, *pBuffer++, eParserModePlay)) != EAS_SUCCESS) + return result; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_CloseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Closes a raw MIDI stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_INTERACTIVE_MIDI *pMIDIStream; + + pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; + + /* close synth */ + if (pMIDIStream->pSynth != NULL) + { + VMMIDIShutdown(pEASData, pMIDIStream->pSynth); + pMIDIStream->pSynth = NULL; + } + + /* release allocated memory */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(((S_EAS_DATA*) pEASData)->hwInstData, pMIDIStream); + + pStream->handle = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the state of an audio file or stream. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_STATE *pState) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + + /* call the parser to return state */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, pState)) != EAS_SUCCESS) + return result; + + /* if repeat count is set for this parser, mask the stopped state from the application */ + if (pStream->repeatCount && (*pState == EAS_STATE_STOPPED)) + *pState = EAS_STATE_PLAY; + + /* if we're not ready or playing, we don't need to hide state from host */ + if (*pState > EAS_STATE_PLAY) + return EAS_SUCCESS; + + /* if stream is about to be paused, report it as paused */ + if (pStream->streamFlags & STREAM_FLAGS_PAUSE) + { + if (pStream->streamFlags & STREAM_FLAGS_LOCATE) + *pState = EAS_STATE_PAUSED; + else + *pState = EAS_STATE_PAUSING; + } + + /* if stream is about to resume, report it as playing */ + if (pStream->streamFlags & STREAM_FLAGS_RESUME) + *pState = EAS_STATE_PLAY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the stream. A value of 0 allows the stream + * to use all voices (set by EAS_SetSynthPolyphony). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 polyphonyCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, polyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_GetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPolyphonyCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, pPolyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_SetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the synth . Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount) +{ + return VMSetSynthPolyphony(pEASData->pVoiceMgr, synthNum, polyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_GetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the synth + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount) +{ + return VMGetSynthPolyphony(pEASData->pVoiceMgr, synthNum, pPolyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_SetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the priority of the stream. Determines which stream's voices + * are stolen when there are insufficient voices for all notes. + * Value must be in the range of 1-15, lower values are higher + * priority. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 priority) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, priority); +} + +/*---------------------------------------------------------------------------- + * EAS_GetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current priority setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPriority - pointer to variable to receive priority + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPriority) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, pPriority); +} + +/*---------------------------------------------------------------------------- + * EAS_SetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master gain for the mix engine in 1dB increments + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master gain (100 is max) + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 volume) +{ + EAS_I16 gain; + + /* check range */ + if ((volume < 0) || (volume > EAS_MAX_VOLUME)) + return EAS_ERROR_PARAMETER_RANGE; + + /* stream volume */ + if (pStream != NULL) + { + EAS_I32 gainOffset; + EAS_RESULT result; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* get gain offset */ + pStream->volume = (EAS_U8) volume; + result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_GAIN_OFFSET, &gainOffset); + if (result == EAS_SUCCESS) + volume += gainOffset; + + /* set stream volume */ + gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM); + + /* convert to linear scalar */ + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_VOLUME, gain); + } + + /* master volume */ + pEASData->masterVolume = (EAS_U8) volume; +#if (NUM_OUTPUT_CHANNELS == 1) + /* leave 3dB headroom for mono output */ + volume -= 3; +#endif + + gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM); + pEASData->masterGain = gain; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the master volume for the synthesizer. The default volume setting is + * 50. The volume range is 0 to 100; + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + if (pStream == NULL) + return pEASData->masterVolume; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return pStream->volume; +} + +/*---------------------------------------------------------------------------- + * EAS_SetMaxLoad() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the maximum workload the parsers will do in a single call to + * EAS_Render. The units are currently arbitrary, but should correlate + * well to the actual CPU cycles consumed. The primary effect is to + * reduce the occasional peaks in CPU cycles consumed when parsing + * dense parts of a MIDI score. + * + * Inputs: + * pEASData - handle to data for this instance + * maxLoad - the desired maximum workload + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad) +{ + VMSetWorkload(pEASData->pVoiceMgr, maxLoad); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetMaxPCMStreams() + *---------------------------------------------------------------------------- + * Sets the maximum number of PCM streams allowed in parsers that + * use PCM streaming. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * maxNumStreams - maximum number of PCM streams + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_MAX_PCM_STREAMS, maxNumStreams); +} + +/*---------------------------------------------------------------------------- + * EAS_Locate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate into the file associated with the handle. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file handle + * milliseconds - playback offset from start of file in milliseconds + * + * Outputs: + * + * + * Side Effects: + * the actual offset will be quantized to the closest update period, typically + * a resolution of 5.9ms. Notes that are started prior to this time will not + * sound. Any notes currently playing will be shut off. + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 milliseconds, EAS_BOOL offset) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_U32 requestedTime; + EAS_STATE state; + + /* get pointer to parser function table */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) + return result; + if (state >= EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* handle offset and limit to start of file */ + /*lint -e{704} use shift for performance*/ + if (offset) + milliseconds += (EAS_I32) pStream->time >> 8; + if (milliseconds < 0) + milliseconds = 0; + + /* check to see if the request is different from the current time */ + requestedTime = (EAS_U32) milliseconds; + if (requestedTime == (pStream->time >> 8)) + return EAS_SUCCESS; + + /* set the locate flag */ + pStream->streamFlags |= STREAM_FLAGS_LOCATE; + + /* use the parser locate function, if available */ + if (pParserModule->pfLocate != NULL) + { + EAS_BOOL parserLocate = EAS_FALSE; + result = pParserModule->pfLocate(pEASData, pStream->handle, (EAS_I32) requestedTime, &parserLocate); + if (!parserLocate) + { + if (result == EAS_SUCCESS) + pStream->time = requestedTime << 8; + return result; + } + } + + /* if we were paused and not going to resume, set pause request flag */ + if (((state == EAS_STATE_PAUSING) || (state == EAS_STATE_PAUSED)) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) + pStream->streamFlags |= STREAM_FLAGS_PAUSE; + + /* reset the synth and parser */ + if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) + return result; + pStream->time = 0; + + /* locating forward, clear parsed flag and parse data until we get to the requested location */ + if ((result = EAS_ParseEvents(pEASData, pStream, requestedTime << 8, eParserModeLocate)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetLocation() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file handle + * + * Outputs: + * The offset in milliseconds from the start of the current sequence, quantized + * to the nearest update period. Actual resolution is typically 5.9 ms. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pTime) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + *pTime = pStream->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetRenderTime() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * Gets the render time clock in msecs. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime) +{ + *pTime = pEASData->renderTime >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the playback of the data associated with this handle. The audio + * is gracefully ramped down to prevent clicks and pops. It may take several + * buffers of audio before the audio is muted. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + if ((state != EAS_STATE_PLAY) && (state != EAS_STATE_READY) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* make sure parser implements pause */ + if (pParserModule->pfPause == NULL) + result = EAS_ERROR_NOT_IMPLEMENTED; + + /* clear resume flag */ + pStream->streamFlags &= ~STREAM_FLAGS_RESUME; + + /* set pause flag */ + pStream->streamFlags |= STREAM_FLAGS_PAUSE; + +#if 0 + /* pause the stream */ + if (pParserModule->pfPause) + result = pParserModule->pfPause(pEASData, pStream->handle); + else + result = EAS_ERROR_NOT_IMPLEMENTED; +#endif + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resumes the playback of the data associated with this handle. The audio + * is gracefully ramped up to prevent clicks and pops. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + if ((state != EAS_STATE_PAUSED) && (state != EAS_STATE_PAUSING) && ((pStream->streamFlags & STREAM_FLAGS_PAUSE) == 0)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* make sure parser implements this function */ + if (pParserModule->pfResume == NULL) + result = EAS_ERROR_NOT_IMPLEMENTED; + + /* clear pause flag */ + pStream->streamFlags &= ~STREAM_FLAGS_PAUSE; + + /* set resume flag */ + pStream->streamFlags |= STREAM_FLAGS_RESUME; + +#if 0 + /* resume the stream */ + if (pParserModule->pfResume) + result = pParserModule->pfResume(pEASData, pStream->handle); + else + result = EAS_ERROR_NOT_IMPLEMENTED; +#endif + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_GetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * pValue - pointer to variable to receive parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue) +{ + + if (module >= NUM_EFFECTS_MODULES) + return EAS_ERROR_INVALID_MODULE; + + if (pEASData->effectsModules[module].effectData == NULL) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->effectsModules[module].effect->pFGetParam) + (pEASData->effectsModules[module].effectData, param, pValue); +} + +/*---------------------------------------------------------------------------- + * EAS_SetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * value - new parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value) +{ + + if (module >= NUM_EFFECTS_MODULES) + return EAS_ERROR_INVALID_MODULE; + + if (pEASData->effectsModules[module].effectData == NULL) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->effectsModules[module].effect->pFSetParam) + (pEASData->effectsModules[module].effectData, param, value); +} + +#ifdef _METRICS_ENABLED +/*---------------------------------------------------------------------------- + * EAS_MetricsReport() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the metrics interface. + * + * Inputs: + * p - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData) +{ + if (!pEASData->pMetricsModule) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->pMetricsModule->pfReport)(pEASData->pMetricsData); +} + +/*---------------------------------------------------------------------------- + * EAS_MetricsReset() + *---------------------------------------------------------------------------- + * Purpose: + * Resets the metrics. + * + * Inputs: + * p - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData) +{ + + if (!pEASData->pMetricsModule) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->pMetricsModule->pfReset)(pEASData->pMetricsData); +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetSoundLibrary() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_SNDLIB_HANDLE pSndLib) +{ + if (pStream) + { + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_EAS_LIBRARY, (EAS_I32) pSndLib); + } + + return VMSetGlobalEASLib(pEASData->pVoiceMgr, pSndLib); +} + +/*---------------------------------------------------------------------------- + * EAS_SetHeaderSearchFlag() + *---------------------------------------------------------------------------- + * By default, when EAS_OpenFile is called, the parsers check the + * first few bytes of the file looking for a specific header. Some + * mobile devices may add a header to the start of a file, which + * will prevent the parser from recognizing the file. If the + * searchFlag is set to EAS_TRUE, the parser will search the entire + * file looking for the header. This may enable EAS to recognize + * some files that it would ordinarily reject. The negative is that + * it make take slightly longer to process the EAS_OpenFile request. + * + * Inputs: + * pEASData - instance data handle + * searchFlag - search flag (EAS_TRUE or EAS_FALSE) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag) +{ + pEASData->searchHeaderFlag = (EAS_BOOL8) searchFlag; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPlayMode() + *---------------------------------------------------------------------------- + * Some file formats support special play modes, such as iMode partial + * play mode. This call can be used to change the play mode. The + * default play mode (usually straight playback) is always zero. + * + * Inputs: + * pEASData - instance data handle + * handle - file or stream handle + * playMode - play mode (see file parser for specifics) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode) +{ + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PLAY_MODE, playMode); +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * EAS_LoadDLSCollection() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_FILE_LOCATOR locator) +{ + EAS_FILE_HANDLE fileHandle; + EAS_RESULT result; + EAS_DLSLIB_HANDLE pDLS; + + if (pStream != NULL) + { + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + } + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* parse the file */ + result = DLSParser(pEASData->hwInstData, fileHandle, 0, &pDLS); + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + + if (result == EAS_SUCCESS) + { + + /* if a stream pStream is specified, point it to the DLS collection */ + if (pStream) + result = EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_DLS_COLLECTION, (EAS_I32) pDLS); + + /* global DLS load */ + else + result = VMSetGlobalDLSLib(pEASData, pDLS); + } + + return result; +} +#endif + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers callback functions for audio events. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * cbProgChgFunc - pointer to host callback function for program change + * cbEventFunc - pointer to host callback functio for note events + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, + EAS_HANDLE pStream, + EAS_VOID_PTR pInstData, + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, + EAS_EXT_EVENT_FUNC cbEventFunc) +{ + S_SYNTH *pSynth; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + VMRegExtAudioCallback(pSynth, pInstData, cbProgChgFunc, cbEventFunc); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetMIDIControllers() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of MIDI controllers on the requested channel. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * pControl - pointer to structure to receive data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) +{ + S_SYNTH *pSynth; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + VMGetMIDIControllers(pSynth, channel, pControl); + return EAS_SUCCESS; +} +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * EAS_SetFrameBuffer() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the frame buffer pointer passed to the IPC communications functions + * + * Inputs: + * pEASData - instance data handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer) +{ + if (pEASData->pVoiceMgr) + pEASData->pVoiceMgr->pFrameBuffer = pFrameBuffer; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_SearchFile + *---------------------------------------------------------------------------- + * Search file for specific sequence starting at current file + * position. Returns offset to start of sequence. + * + * Inputs: + * pEASData - pointer to EAS persistent data object + * fileHandle - file handle + * searchString - pointer to search sequence + * len - length of search sequence + * pOffset - pointer to variable to store offset to sequence + * + * Returns EAS_EOF if end-of-file is reached + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SearchFile (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset) +{ + EAS_RESULT result; + EAS_INT index; + EAS_U8 c; + + *pOffset = -1; + index = 0; + for (;;) + { + result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &c); + if (result != EAS_SUCCESS) + return result; + if (c == searchString[index]) + { + index++; + if (index == 4) + { + result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, pOffset); + if (result != EAS_SUCCESS) + return result; + *pOffset -= len; + break; + } + } + else + index = 0; + } + return EAS_SUCCESS; +} + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverb.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverb.c new file mode 100755 index 0000000..cd5befe --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverb.c @@ -0,0 +1,1154 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverb.c + * + * Contents and purpose: + * Contains the implementation of the Reverb effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 510 $ + * $Date: 2006-12-19 01:47:33 -0800 (Tue, 19 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +/*------------------------------------ + * includes + *------------------------------------ +*/ + +#include "eas_data.h" +#include "eas_effects.h" +#include "eas_math.h" +#include "eas_reverbdata.h" +#include "eas_reverb.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" + +/* prototypes for effects interface */ +static EAS_RESULT ReverbInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); +static void ReverbProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); +static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + +/* common effects interface for configuration module */ +const S_EFFECTS_INTERFACE EAS_Reverb = +{ + ReverbInit, + ReverbProcess, + ReverbShutdown, + ReverbGetParam, + ReverbSetParam +}; + + + +/*---------------------------------------------------------------------------- + * InitializeReverb() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbInit(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) +{ + EAS_I32 i; + EAS_U16 nOffset; + EAS_INT temp; + + S_REVERB_OBJECT *pReverbData; + S_REVERB_PRESET *pPreset; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pReverbData = EAS_CMEnumFXData(EAS_MODULE_REVERB); + + /* allocate dynamic memory */ + else + pReverbData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_REVERB_OBJECT)); + + if (pReverbData == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Reverb memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* clear the structure */ + EAS_HWMemSet(pReverbData, 0, sizeof(S_REVERB_OBJECT)); + + ReverbReadInPresets(pReverbData); + + pReverbData->m_nMinSamplesToAdd = REVERB_UPDATE_PERIOD_IN_SAMPLES; + + pReverbData->m_nRevOutFbkR = 0; + pReverbData->m_nRevOutFbkL = 0; + + pReverbData->m_sAp0.m_zApIn = AP0_IN; + pReverbData->m_sAp0.m_zApOut = AP0_IN + DEFAULT_AP0_LENGTH; + pReverbData->m_sAp0.m_nApGain = DEFAULT_AP0_GAIN; + + pReverbData->m_zD0In = DELAY0_IN; + + pReverbData->m_sAp1.m_zApIn = AP1_IN; + pReverbData->m_sAp1.m_zApOut = AP1_IN + DEFAULT_AP1_LENGTH; + pReverbData->m_sAp1.m_nApGain = DEFAULT_AP1_GAIN; + + pReverbData->m_zD1In = DELAY1_IN; + + pReverbData->m_zLpf0 = 0; + pReverbData->m_zLpf1 = 0; + pReverbData->m_nLpfFwd = 8837; + pReverbData->m_nLpfFbk = 6494; + + pReverbData->m_nSin = 0; + pReverbData->m_nCos = 0; + pReverbData->m_nSinIncrement = 0; + pReverbData->m_nCosIncrement = 0; + + // set xfade parameters + pReverbData->m_nXfadeInterval = (EAS_U16)REVERB_XFADE_PERIOD_IN_SAMPLES; + pReverbData->m_nXfadeCounter = pReverbData->m_nXfadeInterval + 1; // force update on first iteration + pReverbData->m_nPhase = -32768; + pReverbData->m_nPhaseIncrement = REVERB_XFADE_PHASE_INCREMENT; + + pReverbData->m_nNoise = (EAS_I16)0xABCD; + + pReverbData->m_nMaxExcursion = 0x007F; + + // set delay tap lengths + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD1Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD0Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD0Self = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD1Self = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + // for debugging purposes, allow noise generator + pReverbData->m_bUseNoise = EAS_FALSE; + + // for debugging purposes, allow bypass + pReverbData->m_bBypass = EAS_TRUE; //EAS_FALSE; + + pReverbData->m_nNextRoom = 1; + + pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom + 1; // force update on first iteration + + pReverbData->m_nWet = REVERB_DEFAULT_WET; + + pReverbData->m_nDry = REVERB_DEFAULT_DRY; + + // set base index into circular buffer + pReverbData->m_nBaseIndex = 0; + + // set the early reflections, L + pReverbData->m_sEarlyL.m_nLpfFbk = 4915; + pReverbData->m_sEarlyL.m_nLpfFwd = 27852; + pReverbData->m_sEarlyL.m_zLpf = 0; + + for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) + { + pReverbData->m_sEarlyL.m_nGain[i] = 0; + pReverbData->m_sEarlyL.m_zDelay[i] = 0; + } + + // set the early reflections, R + pReverbData->m_sEarlyR.m_nLpfFbk = 4915; + pReverbData->m_sEarlyR.m_nLpfFwd = 27852; + pReverbData->m_sEarlyR.m_zLpf = 0; + + for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) + { + pReverbData->m_sEarlyR.m_nGain[i] = 0; + pReverbData->m_sEarlyR.m_zDelay[i] = 0; + } + + // clear the reverb delay line + for (i=0; i < REVERB_BUFFER_SIZE_IN_SAMPLES; i++) + { + pReverbData->m_nDelayLine[i] = 0; + } + + //////////////////////////////// + ///code from the EAS DEMO Reverb + //now copy from the new preset into the reverb + pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; + + pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; + pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; + + pReverbData->m_nEarly = pPreset->m_nEarly; + pReverbData->m_nWet = pPreset->m_nWet; + pReverbData->m_nDry = pPreset->m_nDry; + + pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_nXfadeInterval = (EAS_U16) temp; + //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval; + + pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); + //gsReverbObject.m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; + + pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); + //gsReverbObject.m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + ///code from the EAS DEMO Reverb + //////////////////////////////// + + *pInstData = pReverbData; + + return EAS_SUCCESS; + +} /* end InitializeReverb */ + + + +/*---------------------------------------------------------------------------- + * ReverbProcess() + *---------------------------------------------------------------------------- + * Purpose: + * Reverberate the requested number of samples (block based processing) + * + * Inputs: + * pInputBuffer - src buffer + * pOutputBuffer - dst buffer + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +static void ReverbProcess(EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) +{ + S_REVERB_OBJECT *pReverbData; + + pReverbData = (S_REVERB_OBJECT*) pInstData; + + //if bypassed or the preset forces the signal to be completely dry + if (pReverbData->m_bBypass || + (pReverbData->m_nWet == 0 && pReverbData->m_nDry == 32767)) + { + if (pSrc != pDst) + EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); + return; + } + + if (pReverbData->m_nNextRoom != pReverbData->m_nCurrentRoom) + { + ReverbUpdateRoom(pReverbData); + } + + ReverbUpdateXfade(pReverbData, numSamples); + + Reverb(pReverbData, numSamples, pDst, pSrc); + + /* check if update counter needs to be reset */ + if (pReverbData->m_nUpdateCounter >= REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES) + { + /* update interval has elapsed, so reset counter */ + pReverbData->m_nUpdateCounter = 0; + } /* end if m_nUpdateCounter >= update interval */ + + /* increment update counter */ + pReverbData->m_nUpdateCounter += (EAS_I16)numSamples; + +} /* end ComputeReverb */ + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd) +{ + EAS_U16 nOffset; + EAS_I16 tempCos; + EAS_I16 tempSin; + + if (pReverbData->m_nXfadeCounter >= pReverbData->m_nXfadeInterval) + { + /* update interval has elapsed, so reset counter */ + pReverbData->m_nXfadeCounter = 0; + + // Pin the sin,cos values to min / max values to ensure that the + // modulated taps' coefs are zero (thus no clicks) + if (pReverbData->m_nPhaseIncrement > 0) + { + // if phase increment > 0, then sin -> 1, cos -> 0 + pReverbData->m_nSin = 32767; + pReverbData->m_nCos = 0; + + // reset the phase to match the sin, cos values + pReverbData->m_nPhase = 32767; + + // modulate the cross taps because their tap coefs are zero + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD1Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD0Cross = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + } + else + { + // if phase increment < 0, then sin -> 0, cos -> 1 + pReverbData->m_nSin = 0; + pReverbData->m_nCos = 32767; + + // reset the phase to match the sin, cos values + pReverbData->m_nPhase = -32768; + + // modulate the self taps because their tap coefs are zero + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD0Self = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD1Self = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + } // end if-else (pReverbData->m_nPhaseIncrement > 0) + + // Reverse the direction of the sin,cos so that the + // tap whose coef was previously increasing now decreases + // and vice versa + pReverbData->m_nPhaseIncrement = -pReverbData->m_nPhaseIncrement; + + } // end if counter >= update interval + + //compute what phase will be next time + pReverbData->m_nPhase += pReverbData->m_nPhaseIncrement; + + //calculate what the new sin and cos need to reach by the next update + ReverbCalculateSinCos(pReverbData->m_nPhase, &tempSin, &tempCos); + + //calculate the per-sample increment required to get there by the next update + /*lint -e{702} shift for performance */ + pReverbData->m_nSinIncrement = + (tempSin - pReverbData->m_nSin) >> REVERB_UPDATE_PERIOD_IN_BITS; + + /*lint -e{702} shift for performance */ + pReverbData->m_nCosIncrement = + (tempCos - pReverbData->m_nCos) >> REVERB_UPDATE_PERIOD_IN_BITS; + + + /* increment update counter */ + pReverbData->m_nXfadeCounter += (EAS_U16) nNumSamplesToAdd; + + return EAS_SUCCESS; + +} /* end ReverbUpdateXfade */ + + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * nMaxExcursion - noise value is limited to this value + * pnNoise - return new noise sample in this (not limited) + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - *pnNoise noise value is updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise) +{ + // calculate new noise value + *pnNoise = (EAS_I16) (*pnNoise * 5 + 1); + +#if 0 // 1xxx, test + *pnNoise = 0; +#endif // 1xxx, test + + // return the limited noise value + return (nMaxExcursion & (*pnNoise)); + +} /* end ReverbCalculateNoise */ + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos) +{ + EAS_I32 nTemp; + EAS_I32 nNetAngle; + + // -1 <= nPhase < 1 + // However, for the calculation, we need a value + // that ranges from -1/2 to +1/2, so divide the phase by 2 + /*lint -e{702} shift for performance */ + nNetAngle = nPhase >> 1; + + /* + Implement the following + sin(x) = (2-4*c)*x^2 + c + x + cos(x) = (2-4*c)*x^2 + c - x + + where c = 1/sqrt(2) + using the a0 + x*(a1 + x*a2) approach + */ + + /* limit the input "angle" to be between -0.5 and +0.5 */ + if (nNetAngle > EG1_HALF) + { + nNetAngle = EG1_HALF; + } + else if (nNetAngle < EG1_MINUS_HALF) + { + nNetAngle = EG1_MINUS_HALF; + } + + /* calculate sin */ + nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnSin = (EAS_I16) SATURATE_EG1(nTemp); + + /* calculate cos */ + nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnCos = (EAS_I16) SATURATE_EG1(nTemp); + + return EAS_SUCCESS; +} /* end ReverbCalculateSinCos */ + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Reverb(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer) +{ + EAS_I32 i; + EAS_I32 nDelayOut; + EAS_U16 nBase; + + EAS_U32 nAddr; + EAS_I32 nTemp1; + EAS_I32 nTemp2; + EAS_I32 nApIn; + EAS_I32 nApOut; + + EAS_I32 j; + EAS_I32 nEarlyOut; + + EAS_I32 tempValue; + + + // get the base address + nBase = pReverbData->m_nBaseIndex; + + for (i=0; i < nNumSamplesToAdd; i++) + { + // ********** Left Allpass - start + // left input = (left dry/4) + right feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkR; +// nApIn = *pInputBuffer++; // 1xxx test and debug ap + + // fetch allpass delay line out + //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, REVERB_BUFFER_MASK); + nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApOut, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp0.m_nApGain); + nApOut = SATURATE(nDelayOut - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp0.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApIn, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverbData->m_zD0In, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; + + // ********** Left Allpass - end + + // ********** Right Allpass - start + // right input = (right dry/4) + left feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkL; +// nApIn = *pInputBuffer++; // 1xxx test and debug ap + + // fetch allpass delay line out + nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApOut, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp1.m_nApGain); + nApOut = SATURATE(nDelayOut - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp1.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApIn, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverbData->m_zD1In, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; + + // ********** Right Allpass - end + + // ********** D0 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverbData->m_zD0Self, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverbData->m_zD1Cross, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); + + // calculate unfiltered delay out + nDelayOut = SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf0, pReverbData->m_nLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_zLpf0 + pReverbData->m_zLpf0 = (EAS_PCM) SATURATE(nTemp1 + nTemp2); + + // ********** D0 output - end + + // ********** D1 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverbData->m_zD1Self, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverbData->m_zD0Cross, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); + + // calculate unfiltered delay out + nDelayOut = SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf1, pReverbData->m_nLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_zLpf1 + pReverbData->m_zLpf1 = (EAS_PCM)SATURATE(nTemp1 + nTemp2); + + // ********** D1 output - end + + // ********** mixer and feedback - start + // sum is fedback to right input (R + L) + pReverbData->m_nRevOutFbkL = + (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 + (EAS_I32)pReverbData->m_zLpf0); + + // difference is feedback to left input (R - L) + /*lint -e{685} lint complains that it can't saturate negative */ + pReverbData->m_nRevOutFbkR = + (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 - (EAS_I32)pReverbData->m_zLpf0); + + // ********** mixer and feedback - end + + // ********** start early reflection generator, left + //psEarly = &(pReverbData->m_sEarlyL); + + nEarlyOut = 0; + + for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + { + // fetch delay line out + //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], REVERB_BUFFER_MASK); + nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyL.m_zDelay[j], REVERB_BUFFER_MASK); + + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate reflection + //nTemp1 = MULT_EG1_EG1(nDelayOut, psEarly->m_nGain[j]); + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyL.m_nGain[j]); + + nEarlyOut = SATURATE(nEarlyOut + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nLpfFwd); + nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyL.m_nLpfFwd); + + //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk); + nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyL.m_zLpf, pReverbData->m_sEarlyL.m_nLpfFbk); + + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zLpf1 + //psEarly->m_zLpf = SATURATE(nTemp1 + nTemp2); + pReverbData->m_sEarlyL.m_zLpf = (EAS_PCM) SATURATE(nTemp1 + nTemp2); + + // combine filtered early and late reflections for output + //*pOutputBuffer++ = inL; + //tempValue = SATURATE(psEarly->m_zLpf + pReverbData->m_nRevOutFbkL); + tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyL.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkL); + //scale reverb output by wet level + /*lint -e{701} use shift for performance */ + tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet<<1)); + //sum with output buffer + tempValue += *pOutputBuffer; + *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); + + // ********** end early reflection generator, left + + // ********** start early reflection generator, right + //psEarly = &(pReverbData->m_sEarlyR); + + nEarlyOut = 0; + + for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + { + // fetch delay line out + nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyR.m_zDelay[j], REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate reflection + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyR.m_nGain[j]); + + nEarlyOut = SATURATE(nEarlyOut + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyR.m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyR.m_zLpf, pReverbData->m_sEarlyR.m_nLpfFbk); + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zLpf1 + pReverbData->m_sEarlyR.m_zLpf = (EAS_PCM)SATURATE(nTemp1 + nTemp2); + + // combine filtered early and late reflections for output + //*pOutputBuffer++ = inR; + tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyR.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkR); + //scale reverb output by wet level + /*lint -e{701} use shift for performance */ + tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet << 1)); + //sum with output buffer + tempValue = tempValue + *pOutputBuffer; + *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); + + // ********** end early reflection generator, right + + // decrement base addr for next sample period + nBase--; + + pReverbData->m_nSin += pReverbData->m_nSinIncrement; + pReverbData->m_nCos += pReverbData->m_nCosIncrement; + + } // end for (i=0; i < nNumSamplesToAdd; i++) + + // store the most up to date version + pReverbData->m_nBaseIndex = nBase; + + return EAS_SUCCESS; +} /* end Reverb */ + + + +/*---------------------------------------------------------------------------- + * ReverbShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the Reverb effect. + * + * Inputs: + * pInstData - handle to instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) +{ + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pInstData); + return EAS_SUCCESS; +} /* end ReverbShutdown */ + +/*---------------------------------------------------------------------------- + * ReverbGetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Get a Reverb parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - pointer to variable to hold retrieved value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_REVERB_OBJECT *p; + + p = (S_REVERB_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_REVERB_BYPASS: + *pValue = (EAS_I32) p->m_bBypass; + break; + case EAS_PARAM_REVERB_PRESET: + *pValue = (EAS_I8) p->m_nCurrentRoom; + break; + case EAS_PARAM_REVERB_WET: + *pValue = p->m_nWet; + break; + case EAS_PARAM_REVERB_DRY: + *pValue = p->m_nDry; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ReverbGetParam */ + + +/*---------------------------------------------------------------------------- + * ReverbSetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Set a Reverb parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - new paramter value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_REVERB_OBJECT *p; + + p = (S_REVERB_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_REVERB_BYPASS: + p->m_bBypass = (EAS_BOOL) value; + break; + case EAS_PARAM_REVERB_PRESET: + if(value!=EAS_PARAM_REVERB_LARGE_HALL && value!=EAS_PARAM_REVERB_HALL && + value!=EAS_PARAM_REVERB_CHAMBER && value!=EAS_PARAM_REVERB_ROOM) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nNextRoom = (EAS_I16)value; + break; + case EAS_PARAM_REVERB_WET: + if(value>EAS_REVERB_WET_MAX || valuem_nWet = (EAS_I16)value; + break; + case EAS_PARAM_REVERB_DRY: + if(value>EAS_REVERB_DRY_MAX || valuem_nDry = (EAS_I16)value; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ReverbSetParam */ + + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT *pReverbData) +{ + EAS_INT temp; + + S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; + + pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; + pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; + + pReverbData->m_nEarly = pPreset->m_nEarly; + pReverbData->m_nWet = pPreset->m_nWet; + pReverbData->m_nDry = pPreset->m_nDry; + + + pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_nXfadeInterval = (EAS_U16) temp; + //gpsReverbObject->m_nXfadeInterval = pPreset->m_nXfadeInterval; + pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); + //gpsReverbObject->m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; + pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); + //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + + pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom; + + return EAS_SUCCESS; + +} /* end ReverbUpdateRoom */ + + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT *pReverbData) +{ + + int preset = 0; + int defaultPreset = 0; + + //now init any remaining presets to defaults + for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++) + { + S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[defaultPreset]; + if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE-1) + { + pPreset->m_nLpfFbk = 8307; + pPreset->m_nLpfFwd = 14768; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 27690; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6388; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 711; + pPreset->m_nAp1_ApGain = 17999; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 1) + { + pPreset->m_nLpfFbk = 6461; + pPreset->m_nLpfFwd = 14307; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 27690; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6391; + pPreset->m_nAp0_ApGain = 15230; + pPreset->m_nAp0_ApOut = 708; + pPreset->m_nAp1_ApGain = 9692; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 2) + { + pPreset->m_nLpfFbk = 5077; + pPreset->m_nLpfFwd = 12922; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 24460; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6449; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 774; + pPreset->m_nAp1_ApGain = 15691; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 3) + { + pPreset->m_nLpfFbk = 5077; + pPreset->m_nLpfFwd = 11076; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 23075; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6470; //6483; + pPreset->m_nAp0_ApGain = 14768; + pPreset->m_nAp0_ApOut = 792; + pPreset->m_nAp1_ApGain = 15783; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + + } + } + + return EAS_SUCCESS; +} diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverbdata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverbdata.c new file mode 100755 index 0000000..db34b48 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverbdata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverbdata.c + * + * Contents and purpose: + * Contains the static data allocation for the Reverb effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_reverbdata.h" + +S_REVERB_OBJECT eas_ReverbData; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverbdata.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverbdata.h new file mode 100755 index 0000000..926ea2e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_reverbdata.h @@ -0,0 +1,486 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverbdata.h + * + * Contents and purpose: + * Contains the prototypes for the Reverb effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 499 $ + * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_REVERBDATA_H +#define _EAS_REVERBDATA_H + +#include "eas_types.h" +#include "eas_audioconst.h" + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +/* +CIRCULAR() calculates the array index using modulo arithmetic. +The "trick" is that modulo arithmetic is simplified by masking +the effective address where the mask is (2^n)-1. This only works +if the buffer size is a power of two. +*/ +#define CIRCULAR(base,offset,size) (EAS_U32)( \ + ( \ + ((EAS_I32)(base)) + ((EAS_I32)(offset)) \ + ) \ + & size \ + ) + +/* reverb parameters are updated every 2^(REVERB_UPDATE_PERIOD_IN_BITS) samples */ +#if defined (_SAMPLE_RATE_8000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 5 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 2048 + +#elif defined (_SAMPLE_RATE_16000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 6 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 + +#elif defined (_SAMPLE_RATE_22050) + +#define REVERB_UPDATE_PERIOD_IN_BITS 7 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 + +#elif defined (_SAMPLE_RATE_32000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 7 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#elif defined (_SAMPLE_RATE_44100) + +#define REVERB_UPDATE_PERIOD_IN_BITS 8 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#elif defined (_SAMPLE_RATE_48000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 8 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#endif + +// Define a mask for circular addressing, so that array index +// can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1) +// The buffer size MUST be a power of two +#define REVERB_BUFFER_MASK (REVERB_BUFFER_SIZE_IN_SAMPLES -1) + +#define REVERB_MAX_ROOM_TYPE 4 // any room numbers larger than this are invalid +#define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ +#define REVERB_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << REVERB_UPDATE_PERIOD_IN_BITS) + +/* +calculate the update counter by bitwise ANDING with this value to +generate a 2^n modulo value +*/ +#define REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(REVERB_UPDATE_PERIOD_IN_SAMPLES -1) + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SECONDS seconds */ +#define REVERB_UPDATE_PERIOD_IN_SECONDS (REVERB_UPDATE_PERIOD_IN_SAMPLES / _OUTPUT_SAMPLE_RATE) + +// xfade parameters +#define REVERB_XFADE_PERIOD_IN_SECONDS (100.0 / 1000.0) // xfade once every this many seconds + +#define REVERB_XFADE_PERIOD_IN_SAMPLES (REVERB_XFADE_PERIOD_IN_SECONDS * _OUTPUT_SAMPLE_RATE) + +#define REVERB_XFADE_PHASE_INCREMENT (EAS_I16)(65536 / ((EAS_I16)REVERB_XFADE_PERIOD_IN_SAMPLES/(EAS_I16)REVERB_UPDATE_PERIOD_IN_SAMPLES)) + +/**********/ +/* the entire synth uses various flags in a bit field */ + +/* if flag is set, synth reset has been requested */ +#define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */ +#define MASK_REVERB_RESET_IS_REQUESTED 0x01 +#define MASK_REVERB_RESET_IS_NOT_REQUESTED (EAS_U32)(~MASK_REVERB_RESET_IS_REQUESTED) + +/* +by default, we always want to update ALL channel parameters +when we reset the synth (e.g., during GM ON) +*/ +#define DEFAULT_REVERB_FLAGS 0x0 + +/* coefficients for generating sin, cos */ +#define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */ +/* +EAS_I32 nPanG1 = +1.0 for sin +EAS_I32 nPanG1 = -1.0 for cos +*/ +#define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ + +/*************************************************************/ +// define the input injection points +#define GUARD 5 // safety guard of this many samples + +#define MAX_AP_TIME (double) (20.0/1000.0) // delay time in milliseconds +#define MAX_DELAY_TIME (double) (65.0/1000.0) // delay time in milliseconds + +#define MAX_AP_SAMPLES (int)(((double) MAX_AP_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) +#define MAX_DELAY_SAMPLES (int)(((double) MAX_DELAY_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) + +#define AP0_IN 0 +#define AP1_IN (AP0_IN + MAX_AP_SAMPLES + GUARD) +#define DELAY0_IN (AP1_IN + MAX_AP_SAMPLES + GUARD) +#define DELAY1_IN (DELAY0_IN + MAX_DELAY_SAMPLES + GUARD) + +// Define the max offsets for the end points of each section +// i.e., we don't expect a given section's taps to go beyond +// the following limits +#define AP0_OUT (AP0_IN + MAX_AP_SAMPLES -1) +#define AP1_OUT (AP1_IN + MAX_AP_SAMPLES -1) +#define DELAY0_OUT (DELAY0_IN + MAX_DELAY_SAMPLES -1) +#define DELAY1_OUT (DELAY1_IN + MAX_DELAY_SAMPLES -1) + +#define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number +#define DEFAULT_AP0_LENGTH (int)(((double) (17.0/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) +#define DEFAULT_AP0_GAIN 19400 +#define DEFAULT_AP1_LENGTH (int)(((double) (16.5/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) +#define DEFAULT_AP1_GAIN -19400 + +#define REVERB_DEFAULT_WET 32767 +#define REVERB_DEFAULT_DRY 0 + +#define EAS_REVERB_WET_MAX 32767 +#define EAS_REVERB_WET_MIN 0 +#define EAS_REVERB_DRY_MAX 32767 +#define EAS_REVERB_DRY_MIN 0 + +/* parameters for each allpass */ +typedef struct +{ + EAS_U16 m_zApOut; // delay offset for ap out + + EAS_I16 m_nApGain; // gain for ap + + EAS_U16 m_zApIn; // delay offset for ap in + +} S_ALLPASS_OBJECT; + + +/* parameters for each allpass */ +typedef struct +{ + EAS_PCM m_zLpf; // actual state variable, not a length + + EAS_I16 m_nLpfFwd; // lpf forward gain + + EAS_I16 m_nLpfFbk; // lpf feedback gain + + EAS_U16 m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out + + EAS_I16 m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap + +} S_EARLY_REFLECTION_OBJECT; + +//demo +typedef struct +{ + EAS_I16 m_nLpfFbk; + EAS_I16 m_nLpfFwd; + + EAS_I16 m_nEarly; + EAS_I16 m_nWet; + EAS_I16 m_nDry; + + EAS_I16 m_nEarlyL_LpfFbk; + EAS_I16 m_nEarlyL_LpfFwd; + + EAS_I16 m_nEarlyL_Delay0; //8 + EAS_I16 m_nEarlyL_Gain0; + EAS_I16 m_nEarlyL_Delay1; + EAS_I16 m_nEarlyL_Gain1; + EAS_I16 m_nEarlyL_Delay2; + EAS_I16 m_nEarlyL_Gain2; + EAS_I16 m_nEarlyL_Delay3; + EAS_I16 m_nEarlyL_Gain3; + EAS_I16 m_nEarlyL_Delay4; + EAS_I16 m_nEarlyL_Gain4; + + EAS_I16 m_nEarlyR_Delay0; //18 + EAS_I16 m_nEarlyR_Gain0; + EAS_I16 m_nEarlyR_Delay1; + EAS_I16 m_nEarlyR_Gain1; + EAS_I16 m_nEarlyR_Delay2; + EAS_I16 m_nEarlyR_Gain2; + EAS_I16 m_nEarlyR_Delay3; + EAS_I16 m_nEarlyR_Gain3; + EAS_I16 m_nEarlyR_Delay4; + EAS_I16 m_nEarlyR_Gain4; + + EAS_U16 m_nMaxExcursion; //28 + EAS_I16 m_nXfadeInterval; + + EAS_I16 m_nAp0_ApGain; //30 + EAS_I16 m_nAp0_ApOut; + EAS_I16 m_nAp1_ApGain; + EAS_I16 m_nAp1_ApOut; + + EAS_I16 m_rfu4; + EAS_I16 m_rfu5; + EAS_I16 m_rfu6; + EAS_I16 m_rfu7; + EAS_I16 m_rfu8; + EAS_I16 m_rfu9; + EAS_I16 m_rfu10; //43 + +} S_REVERB_PRESET; + +typedef struct +{ + S_REVERB_PRESET m_sPreset[REVERB_MAX_ROOM_TYPE]; //array of presets + +} S_REVERB_PRESET_BANK; + +/* parameters for each reverb */ +typedef struct +{ + /* controls entire reverb playback volume */ + /* to conserve memory, use the MSB and ignore the LSB */ + EAS_U8 m_nMasterVolume; + + /* update counter keeps track of when synth params need updating */ + /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */ + EAS_I16 m_nUpdateCounter; + + EAS_U16 m_nMinSamplesToAdd; /* ComputeReverb() generates this many samples */ + + EAS_U8 m_nFlags; /* misc flags/bit fields */ + + EAS_PCM *m_pOutputBuffer; + EAS_PCM *m_pInputBuffer; + + EAS_U16 m_nNumSamplesInOutputBuffer; + EAS_U16 m_nNumSamplesInInputBuffer; + + EAS_U16 m_nNumInputSamplesRead; // if m_nNumInputSamplesRead >= NumSamplesInInputBuffer + // then get a new input buffer + EAS_PCM *m_pNextInputSample; + + EAS_U16 m_nBaseIndex; // base index for circular buffer + + // reverb delay line offsets, allpass parameters, etc: + + EAS_PCM m_nRevOutFbkR; // combine feedback reverb right out with dry left in + + S_ALLPASS_OBJECT m_sAp0; // allpass 0 (left channel) + + EAS_U16 m_zD0In; // delay offset for delay line D0 in + + EAS_PCM m_nRevOutFbkL; // combine feedback reverb left out with dry right in + + S_ALLPASS_OBJECT m_sAp1; // allpass 1 (right channel) + + EAS_U16 m_zD1In; // delay offset for delay line D1 in + + // delay output taps, notice criss cross order + EAS_U16 m_zD0Self; // self feeds forward d0 --> d0 + + EAS_U16 m_zD1Cross; // cross feeds across d1 --> d0 + + EAS_PCM m_zLpf0; // actual state variable, not a length + + EAS_U16 m_zD1Self; // self feeds forward d1 --> d1 + + EAS_U16 m_zD0Cross; // cross feeds across d0 --> d1 + + EAS_PCM m_zLpf1; // actual state variable, not a length + + EAS_I16 m_nSin; // gain for self taps + + EAS_I16 m_nCos; // gain for cross taps + + EAS_I16 m_nSinIncrement; // increment for gain + + EAS_I16 m_nCosIncrement; // increment for gain + + EAS_I16 m_nLpfFwd; // lpf forward gain (includes scaling for mixer) + + EAS_I16 m_nLpfFbk; // lpf feedback gain + + EAS_U16 m_nXfadeInterval; // update/xfade after this many samples + + EAS_U16 m_nXfadeCounter; // keep track of when to xfade + + EAS_I16 m_nPhase; // -1 <= m_nPhase < 1 + // but during sin,cos calculations + // use m_nPhase/2 + + EAS_I16 m_nPhaseIncrement; // add this to m_nPhase each frame + + EAS_I16 m_nNoise; // random noise sample + + EAS_U16 m_nMaxExcursion; // the taps can excurse +/- this amount + + EAS_BOOL m_bUseNoise; // if EAS_TRUE, use noise as input signal + + EAS_BOOL m_bBypass; // if EAS_TRUE, then bypass reverb and copy input to output + + EAS_I16 m_nCurrentRoom; // preset number for current room + + EAS_I16 m_nNextRoom; // preset number for next room + + EAS_I16 m_nWet; // gain for wet (processed) signal + + EAS_I16 m_nDry; // gain for dry (unprocessed) signal + + EAS_I16 m_nEarly; // gain for early (widen) signal + + S_EARLY_REFLECTION_OBJECT m_sEarlyL; // left channel early reflections + S_EARLY_REFLECTION_OBJECT m_sEarlyR; // right channel early reflections + + EAS_PCM m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES]; // one large delay line for all reverb elements + + S_REVERB_PRESET pPreset; + + S_REVERB_PRESET_BANK m_sPreset; + + //EAS_I8 preset; + +} S_REVERB_OBJECT; + + +/*------------------------------------ + * prototypes + *------------------------------------ +*/ + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * nMaxExcursion - noise value is limited to this value + * pnNoise - return new noise sample in this (not limited) + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - *pnNoise noise value is updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise); + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos); + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Reverb(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer); + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT* pReverbData); + + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT* pReverbData); + +#endif /* #ifndef _EAS_REVERBDATA_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttl.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttl.c new file mode 100755 index 0000000..d8253fb --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttl.c @@ -0,0 +1,1197 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttl.c + * + * Contents and purpose: + * RTTTL parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_rtttldata.h" +#include "eas_ctype.h" + +/* increase gain for mono ringtones */ +#define RTTTL_GAIN_OFFSET 8 + +/* maximum title length including colon separator */ +#define RTTTL_MAX_TITLE_LEN 32 +#define RTTTL_INFINITE_LOOP 15 + +/* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */ +#define DEFAULT_TICK_CONV 30476 +#define TICK_CONVERT 1920000 + +/* default channel and program for RTTTL playback */ +#define RTTTL_CHANNEL 0 +#define RTTTL_PROGRAM 80 +#define RTTTL_VELOCITY 127 + +/* note used for rest */ +#define RTTTL_REST 1 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +/* local prototypes */ +static EAS_RESULT RTTTL_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT RTTTL_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT RTTTL_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT RTTTL_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT RTTTL_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT RTTTL_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT RTTTL_GetStyle (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData); +static EAS_RESULT RTTTL_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pDuration); +static EAS_RESULT RTTTL_GetOctave (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_U8 *pOctave); +static EAS_RESULT RTTTL_GetTempo (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData); +static EAS_RESULT RTTTL_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I32 *pValue); +static EAS_RESULT RTTTL_ParseHeader (S_EAS_DATA *pEASData, S_RTTTL_DATA* pData, EAS_BOOL metaData); +static EAS_RESULT RTTTL_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue); +static EAS_RESULT RTTTL_PeekNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue); + +/* inline functions */ +EAS_INLINE void RTTTL_PutBackChar (S_RTTTL_DATA *pData, EAS_I8 value) { pData->dataByte = value; } + + +/* lookup table for note values */ +static const EAS_U8 noteTable[] = { 21, 23, 12, 14, 16, 17, 19, 23 }; + +/*---------------------------------------------------------------------------- + * + * EAS_RTTTL_Parser + * + * This structure contains the functional interface for the iMelody parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_RTTTL_Parser = +{ + RTTTL_CheckFileType, + RTTTL_Prepare, + RTTTL_Time, + RTTTL_Event, + RTTTL_State, + RTTTL_Close, + RTTTL_Reset, + RTTTL_Pause, + RTTTL_Resume, + NULL, + RTTTL_SetData, + RTTTL_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * RTTTL_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_RTTTL_DATA data; + S_RTTTL_DATA *pData; + + /* see if we can parse the header */ + data.fileHandle = fileHandle; + data.fileOffset = offset; + *ppHandle= NULL; + if (RTTTL_ParseHeader (pEASData, &data, EAS_FALSE) == EAS_SUCCESS) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_RTTTL_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_RTTTL_DATA)); + if (!pData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pData, 0, sizeof(S_RTTTL_DATA)); + + /* return a pointer to the instance data */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_OPEN; + *ppHandle = pData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + /* check for valid state */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + pData->state = EAS_STATE_ERROR; + if ((result = RTTTL_ParseHeader (pEASData, pData, (EAS_BOOL) (pData->metadata.callback != NULL))) != EAS_SUCCESS) + { + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + return result; + } + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + EAS_I32 ticks; + EAS_I32 temp; + EAS_I8 c; + EAS_U8 note; + EAS_U8 octave; + + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + /* set program to square lead */ + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, RTTTL_PROGRAM); + + /* set channel volume to max */ + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* parse the next event */ + octave = pData->octave; + note = 0; + ticks = pData->duration * pData->tick; + for (;;) + { + + /* get next character */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + { + if (result != EAS_EOF) + return result; + + /* end of file, if no notes to process, check for looping */ + if (!note) + { + /* if no loop set state to stopping */ + if (pData->repeatCount == 0) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* decrement loop count */ + if (pData->repeatCount != RTTTL_INFINITE_LOOP) + pData->repeatCount--; + + /* if locating, ignore infinite loops */ + else if (parserMode != eParserModePlay) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* loop back to start of notes */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS) + return result; + continue; + } + + /* still have a note to process */ + else + c = ','; + } + + /* bpm */ + if (c == 'b') + { + /* peek at next character */ + if ((result = RTTTL_PeekNextChar(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + return result; + + /* if a number, must be octave or tempo */ + if (IsDigit(c)) + { + if ((result = RTTTL_GetNumber(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + + /* check for octave first */ + if ((temp >= 4) && (temp <= 7)) + { + octave = (EAS_U8) temp; + } + + /* check for tempo */ + else if ((temp >= 25) && (temp <= 900)) + { + pData->tick = TICK_CONVERT / (EAS_U32) temp; + } + + /* don't know what it was */ + else + return EAS_ERROR_FILE_FORMAT; + } + + /* must be a note */ + else + { + note = noteTable[1]; + } + } + + /* octave */ + else if (c == 'o') + { + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &pData->octave)) != EAS_SUCCESS) + return result; + } + + /* style */ + else if (c == 's') + { + if ((result = RTTTL_GetStyle(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + } + + /* duration or octave */ + else if (IsDigit(c)) + { + RTTTL_PutBackChar(pData, c); + + /* duration comes before note */ + if (!note) + { + if ((result = RTTTL_GetDuration(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + return result; + ticks = c * pData->tick; + } + + /* octave comes after note */ + else + { + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &octave)) != EAS_SUCCESS) + return result; + } + } + + /* note or rest */ + else if ((c >= 'a') && (c <= 'h')) + { + note = noteTable[c - 'a']; + } + + else if (c == 'p') + { + note = RTTTL_REST; + } + + /* dotted note */ + else if (c == '.') + { + /*lint -e{704} shift for performance */ + ticks += ticks >> 1; + } + + /* accidental */ + else if (c == '#') + { + if (note) + note++; + } + + /* end of event */ + else if ((c == ',') && note) + { + + /* handle note events */ + if (note != RTTTL_REST) + { + + /* save note and start it */ + pData->note = note + octave; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, pData->note, RTTTL_VELOCITY); + + /* determine note length */ + switch (pData->style) + { + /* natural */ + case 'n': + /*lint -e{704} shift for performance */ + pData->restTicks = ticks >> 4; + break; + /* continuous */ + + case 'c': + pData->restTicks = 0; + break; + + /* staccato */ + case 's': + /*lint -e{704} shift for performance */ + pData->restTicks = ticks >> 1; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "RTTTL_Event: Unexpected style type %c\n", pData->style); */ } + break; + } + + /* next event is at end of this note */ + pData->time += ticks - pData->restTicks; + } + + /* rest */ + else + pData->time += ticks; + + /* event found, return to caller */ + break; + } + } + + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_RTTTL_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_RTTTL_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_STOPPED; + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + pData = (S_RTTTL_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + pData = (S_RTTTL_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + + /* reset time to zero */ + pData->time = 0; + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + if ((result = RTTTL_ParseHeader (pEASData, pData, EAS_TRUE)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA *pData; + + /* can't pause a stopped stream */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA *pData; + + /* can't resume a stopped stream */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA *) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA *) pInstData; + switch (param) + { + /* return file type as RTTTL */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_RTTTL; + break; + +#if 0 + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = RTTTL_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetStyle() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetStyle (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData) +{ + EAS_RESULT result; + EAS_I8 style; + + /* get style */ + if ((result = RTTTL_GetNextChar(hwInstData, pData, &style)) != EAS_SUCCESS) + return result; + + if ((style != 's') && (style != 'n') && (style != 'c')) + return EAS_ERROR_FILE_FORMAT; + + pData->style = style; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetDuration() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pDuration) +{ + EAS_RESULT result; + EAS_I32 duration; + EAS_I8 temp; + + /* get the duration */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &duration)) != EAS_SUCCESS) + return result; + + if ((duration != 1) && (duration != 2) && (duration != 4) && (duration != 8) && (duration != 16) && (duration != 32)) + return EAS_ERROR_FILE_FORMAT; + + temp = 64; + while (duration) + { + /*lint -e{704} shift for performance */ + duration = duration >> 1; + /*lint -e{702} use shift for performance */ + temp = temp >> 1; + } + + *pDuration = temp; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetOctave() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetOctave (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_U8 *pOctave) +{ + EAS_RESULT result; + EAS_I32 octave; + + /* get the tempo */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &octave)) != EAS_SUCCESS) + return result; + + if ((octave < 4) || (octave > 7)) + return EAS_ERROR_FILE_FORMAT; + + *pOctave = (EAS_U8) (octave * 12); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetTempo() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetTempo (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData) +{ + EAS_RESULT result; + EAS_I32 tempo; + + /* get the tempo */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &tempo)) != EAS_SUCCESS) + return result; + + if ((tempo < 25) || (tempo > 900)) + return EAS_ERROR_FILE_FORMAT; + + pData->tick = TICK_CONVERT / (EAS_U32) tempo; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetNumber() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I32 *pValue) +{ + EAS_RESULT result; + EAS_INT temp; + EAS_I8 c; + + *pValue = -1; + temp = 0; + for (;;) + { + if ((result = RTTTL_PeekNextChar(hwInstData, pData, &c)) != EAS_SUCCESS) + { + if ((result == EAS_EOF) && (*pValue != -1)) + return EAS_SUCCESS; + return result; + } + + if (IsDigit(c)) + { + pData->dataByte = 0; + temp = temp * 10 + c - '0'; + *pValue = temp; + } + else + return EAS_SUCCESS; + } +} + +/*---------------------------------------------------------------------------- + * RTTTL_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_ParseHeader (S_EAS_DATA *pEASData, S_RTTTL_DATA* pData, EAS_BOOL metaData) +{ + EAS_RESULT result; + EAS_I32 i; + EAS_I8 temp; + EAS_I8 control; + + /* initialize some defaults */ + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->note = 0; + pData->duration = 4; + pData ->restTicks = 0; + pData->octave = 60; + pData->repeatOffset = -1; + pData->repeatCount = 0; + pData->style = 'n'; + pData->dataByte = 0; + + metaData = metaData && (pData->metadata.buffer != NULL) && (pData->metadata.callback != NULL); + + /* seek to start of data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + + /* zero the metadata buffer */ + if (metaData) + EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize); + + /* read the title */ + for (i = 0; i < RTTTL_MAX_TITLE_LEN; i++) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + + if (temp == ':') + break; + + /* pass along metadata */ + if (metaData) + { + if (i < (pData->metadata.bufferSize- 1)) + pData->metadata.buffer[i] = (char) temp; + } + } + + /* check for error in title */ + if (i == RTTTL_MAX_TITLE_LEN) + return EAS_ERROR_FILE_FORMAT; + + /* pass along metadata */ + if (metaData) + (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData); + + /* control fields */ + for (;;) + { + + /* get control type */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &control)) != EAS_SUCCESS) + return result; + + /* next char should be equal sign */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + if (temp != '=') + return EAS_ERROR_FILE_FORMAT; + + /* get the control value */ + switch (control) + { + + /* bpm */ + case 'b': + if ((result = RTTTL_GetTempo(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + break; + + /* duration */ + case 'd': + if ((result = RTTTL_GetDuration(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + pData->duration = temp; + break; + + /* loop */ + case 'l': + if ((result = RTTTL_GetNumber(pEASData->hwInstData, pData, &i)) != EAS_SUCCESS) + return result; + if ((i < 0) || (i > 15)) + return EAS_ERROR_FILE_FORMAT; + pData->repeatCount = (EAS_U8) i; + break; + + /* octave */ + case 'o': + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &pData->octave)) != EAS_SUCCESS) + return result; + break; + + /* get style */ + case 's': + if ((result = RTTTL_GetStyle(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + break; + + /* unrecognized control */ + default: + return EAS_ERROR_FILE_FORMAT; + } + + /* next character should be comma or colon */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + + /* check for end of control field */ + if (temp == ':') + break; + + /* must be a comma */ + if (temp != ',') + return EAS_ERROR_FILE_FORMAT; + } + + /* should be at the start of the music block */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pData->fileHandle, &pData->repeatOffset)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue) +{ + EAS_RESULT result; + EAS_I8 temp; + + *pValue = 0; + for(;;) + { + + /* check for character that has been put back */ + if (pData->dataByte) + { + temp = pData->dataByte; + pData->dataByte = 0; + } + else + { + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + } + + /* ignore white space */ + if (!IsSpace(temp)) + { + *pValue = ToLower(temp); + return EAS_SUCCESS; + } + } +} + +/*---------------------------------------------------------------------------- + * RTTTL_PeekNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_PeekNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue) +{ + EAS_RESULT result; + EAS_I8 temp; + + *pValue = 0; + for(;;) + { + + /* read a character from the file, if necessary */ + if (!pData->dataByte) + { + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->dataByte)) != EAS_SUCCESS) + return result; + + } + temp = pData->dataByte; + + /* ignore white space */ + if (!IsSpace(temp)) + { + *pValue = ToLower(temp); + return EAS_SUCCESS; + } + pData->dataByte = 0; + } +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttldata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttldata.c new file mode 100755 index 0000000..708a1d9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttldata.c @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttldata.c + * + * Contents and purpose: + * RTTTL File Parser data module for static memory models + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_rtttldata.h" + +/*---------------------------------------------------------------------------- + * + * eas_RTTTLData + * + * Static memory allocation for RTTTL parser + *---------------------------------------------------------------------------- +*/ +S_RTTTL_DATA eas_RTTTLData; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttldata.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttldata.h new file mode 100755 index 0000000..31dd522 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_rtttldata.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttldata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data declarations for the RTTTL parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_RTTTLDATA_H +#define EAS_RTTTLDATA_H + +#include "eas_data.h" + + +/* maximum line size as specified in iMelody V1.2 spec */ +#define MAX_LINE_SIZE 75 + +/*---------------------------------------------------------------------------- + * + * S_RTTTL_DATA + * + * This structure contains the state data for the iMelody parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* synthesizer handle */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_I32 tick; /* length of 32nd note in 256th of a msec */ + EAS_I32 restTicks; /* ticks to rest after current note */ + EAS_I32 repeatOffset; /* file offset to start of repeat section */ + EAS_U8 repeatCount; /* repeat counter */ + EAS_I8 dataByte; /* storage for characters that are "put back" */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_I8 style; /* from STYLE */ + EAS_U8 note; /* MIDI note number */ + EAS_U8 octave; /* decault octave prefix */ + EAS_I8 duration; /* default note duration */ +} S_RTTTL_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smf.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smf.c new file mode 100755 index 0000000..e609583 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smf.c @@ -0,0 +1,1203 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smf.c + * + * Contents and purpose: + * SMF Type 0 and 1 File Parser + * + * For SMF timebase analysis, see "MIDI Sequencer Analysis.xls". + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 803 $ + * $Date: 2007-08-01 09:57:00 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_smfdata.h" +#include "eas_smf.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + +//3 dls: The timebase for this module is adequate to keep MIDI and +//3 digital audio synchronized for only a few minutes. It should be +//3 sufficient for most mobile applications. If better accuracy is +//3 required, more fractional bits should be added to the timebase. + +static const EAS_U8 smfHeader[] = { 'M', 'T', 'h', 'd' }; + +/* local prototypes */ +static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData); +static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream); +static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode); +static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode); +static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream); +static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks); + + +/*---------------------------------------------------------------------------- + * + * SMF_Parser + * + * This structure contains the functional interface for the SMF parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_SMF_Parser = +{ + SMF_CheckFileType, + SMF_Prepare, + SMF_Time, + SMF_Event, + SMF_State, + SMF_Close, + SMF_Reset, + SMF_Pause, + SMF_Resume, + NULL, + SMF_SetData, + SMF_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * SMF_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + + /* seek to starting offset - usually 0 */ + *ppHandle = NULL; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS) + return result; + + /* search through file for header - slow method */ + if (pEASData->searchHeaderFlag) + { + result = EAS_SearchFile(pEASData, fileHandle, smfHeader, sizeof(smfHeader), &offset); + if (result != EAS_SUCCESS) + return (result == EAS_EOF) ? EAS_SUCCESS : result; + } + + /* read the first 4 bytes of the file - quick method */ + else { + EAS_U8 header[4]; + EAS_I32 count; + if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, header, sizeof(header), &count)) != EAS_SUCCESS) + return result; + + /* check for 'MTrk' - return if no match */ + if ((header[0] != 'M') || (header[1] != 'T') || (header[2] != 'h') || (header[3] != 'd')) + return EAS_SUCCESS; + } + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pSMFData = EAS_CMEnumData(EAS_CM_SMF_DATA); + else + { + pSMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SMF_DATA)); + EAS_HWMemSet((void *)pSMFData,0, sizeof(S_SMF_DATA)); + } + if (!pSMFData) + return EAS_ERROR_MALLOC_FAILED; + + /* initialize some critical data */ + pSMFData->fileHandle = fileHandle; + pSMFData->fileOffset = offset; + pSMFData->pSynth = NULL; + pSMFData->time = 0; + pSMFData->state = EAS_STATE_OPEN; + *ppHandle = pSMFData; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + + /* check for valid state */ + pSMFData = (S_SMF_DATA *) pInstData; + if (pSMFData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pSMFData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + /* parse the file header and setup the individual stream parsers */ + if ((result = SMF_ParseHeader(pEASData->hwInstData, pSMFData)) != EAS_SUCCESS) + return result; + + /* ready to play */ + pSMFData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* sanity check */ +#ifdef _CHECKED_BUILD + if (pSMFData->state == EAS_STATE_STOPPED) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Can't ask for time on a stopped stream\n"); */ } + } + + if (pSMFData->nextStream == NULL) + { + { /* dpp: EAS_ReportEx( _EAS_SEVERITY_ERROR, "no is NULL\n"); */ } + } +#endif + +#if 0 + /* return time in milliseconds */ + /* if chase mode, lie about time */ + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + *pTime = 0; + + else +#endif + + /*lint -e{704} use shift instead of division */ + *pTime = pSMFData->time >> 8; + + *pTime = pSMFData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + EAS_I32 i; + EAS_U32 ticks; + EAS_U32 temp; + + /* establish pointer to instance data */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* get current ticks */ + ticks = pSMFData->nextStream->ticks; + + /* assume that an error occurred */ + pSMFData->state = EAS_STATE_ERROR; + +#ifdef JET_INTERFACE + /* if JET has track muted, set parser mode to mute */ + if (pSMFData->nextStream->midiStream.jetData & MIDI_FLAGS_JET_MUTE) + parserMode = eParserModeMute; +#endif + + /* parse the next event from all the streams */ + if ((result = SMF_ParseEvent(pEASData, pSMFData, pSMFData->nextStream, parserMode)) != EAS_SUCCESS) + { + /* check for unexpected end-of-file */ + if (result != EAS_EOF) + return result; + + /* indicate end of track for this stream */ + pSMFData->nextStream->ticks = SMF_END_OF_TRACK; + } + + /* get next delta time, unless already at end of track */ + else if (pSMFData->nextStream->ticks != SMF_END_OF_TRACK) + { + if ((result = SMF_GetDeltaTime(pEASData->hwInstData, pSMFData->nextStream)) != EAS_SUCCESS) + { + /* check for unexpected end-of-file */ + if (result != EAS_EOF) + return result; + + /* indicate end of track for this stream */ + pSMFData->nextStream->ticks = SMF_END_OF_TRACK; + } + + /* if zero delta to next event, stay with this stream */ + else if (pSMFData->nextStream->ticks == ticks) + { + pSMFData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; + } + } + + /* find next event in all streams */ + temp = 0x7ffffff; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + if (pSMFData->streams[i].ticks < temp) + { + temp = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + } + + /* are there any more events to parse? */ + if (pSMFData->nextStream) + { + pSMFData->state = EAS_STATE_PLAY; + + /* update the time of the next event */ + SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks - ticks); + } + else + { + pSMFData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth); + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_SMF_DATA* pSMFData; + + /* establish pointer to instance data */ + pSMFData = (S_SMF_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pSMFData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pSMFData->pSynth) == 0) + pSMFData->state = EAS_STATE_STOPPED; + } + + if (pSMFData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pSMFData->pSynth) == 0) + pSMFData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pSMFData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_I32 i; + EAS_RESULT result; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* close all the streams */ + for (i = 0; i < pSMFData->numStreams; i++) + { + if (pSMFData->streams[i].fileHandle != NULL) + { + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->streams[i].fileHandle)) != EAS_SUCCESS) + return result; + } + } + if (pSMFData->fileHandle != NULL) + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pSMFData->pSynth != NULL) + VMMIDIShutdown(pEASData, pSMFData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + { + if (pSMFData->streams) + EAS_HWFree(pEASData->hwInstData, pSMFData->streams); + + /* free the instance data */ + EAS_HWFree(pEASData->hwInstData, pSMFData); + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_I32 i; + EAS_RESULT result; + EAS_U32 ticks; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* reset time to zero */ + pSMFData->time = 0; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pSMFData->pSynth, EAS_TRUE); + + /* find the start of each track */ + ticks = 0x7fffffffL; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + + /* reset file position to first byte of data in track */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFData->streams[i].fileHandle, pSMFData->streams[i].startFilePos)) != EAS_SUCCESS) + return result; + + /* initalize some data */ + pSMFData->streams[i].ticks = 0; + + /* initalize the MIDI parser data */ + EAS_InitMIDIStream(&pSMFData->streams[i].midiStream); + + /* parse the first delta time in each stream */ + if ((result = SMF_GetDeltaTime(pEASData->hwInstData,&pSMFData->streams[i])) != EAS_SUCCESS) + return result; + if (pSMFData->streams[i].ticks < ticks) + { + ticks = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + } + + + pSMFData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA *pSMFData; + + /* can't pause a stopped stream */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth); + pSMFData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA *pSMFData; + + /* can't resume a stopped stream */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pSMFData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Sets parser parameters + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pSMFData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + +#ifdef JET_INTERFACE + /* set jet segment and track ID of all tracks for callback function */ + case PARSER_DATA_JET_CB: + { + EAS_U32 i; + EAS_U32 bit = (EAS_U32) value; + bit = (bit << JET_EVENT_SEG_SHIFT) & JET_EVENT_SEG_MASK; + for (i = 0; i < pSMFData->numStreams; i++) + pSMFData->streams[i].midiStream.jetData = + (pSMFData->streams[i].midiStream.jetData & + ~(JET_EVENT_TRACK_MASK | JET_EVENT_SEG_MASK)) | + i << JET_EVENT_TRACK_SHIFT | bit | MIDI_FLAGS_JET_CB; + pSMFData->flags |= SMF_FLAGS_JET_STREAM; + } + break; + + /* set state of all mute flags at once */ + case PARSER_DATA_MUTE_FLAGS: + { + EAS_INT i; + EAS_U32 bit = (EAS_U32) value; + for (i = 0; i < pSMFData->numStreams; i++) + { + if (bit & 1) + pSMFData->streams[i].midiStream.jetData |= MIDI_FLAGS_JET_MUTE; + else + pSMFData->streams[i].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE; + bit >>= 1; + } + } + break; + + /* set track mute */ + case PARSER_DATA_SET_MUTE: + if (value < pSMFData->numStreams) + pSMFData->streams[value].midiStream.jetData |= MIDI_FLAGS_JET_MUTE; + else + return EAS_ERROR_PARAMETER_RANGE; + break; + + /* clear track mute */ + case PARSER_DATA_CLEAR_MUTE: + if (value < pSMFData->numStreams) + pSMFData->streams[value].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE; + else + return EAS_ERROR_PARAMETER_RANGE; + break; +#endif + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Retrieves parser parameters + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + switch (param) + { + /* return file type */ + case PARSER_DATA_FILE_TYPE: + if (pSMFData->numStreams == 1) + *pValue = EAS_FILE_SMF0; + else + *pValue = EAS_FILE_SMF1; + break; + +/* now handled in eas_public.c */ +#if 0 + case PARSER_DATA_POLYPHONY: + if (pSMFData->pSynth) + VMGetPolyphony(pEASData->pVoiceMgr, pSMFData->pSynth, pValue); + else + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + break; + + case PARSER_DATA_PRIORITY: + if (pSMFData->pSynth) + VMGetPriority(pEASData->pVoiceMgr, pSMFData->pSynth, pValue); + break; + + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pSMFData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pSMFData->pSynth; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetVarLenData() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData) +{ + EAS_RESULT result; + EAS_U32 data; + EAS_U8 c; + + /* read until bit 7 is zero */ + data = 0; + do + { + if ((result = EAS_HWGetByte(hwInstData, fileHandle,&c)) != EAS_SUCCESS) + return result; + data = (data << 7) | (c & 0x7f); + } while (c & 0x80); + *pData = data; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetDeltaTime() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream) +{ + EAS_RESULT result; + EAS_U32 ticks; + + if ((result = SMF_GetVarLenData(hwInstData, pSMFStream->fileHandle, &ticks)) != EAS_SUCCESS) + return result; + + pSMFStream->ticks += ticks; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseMetaEvent() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream) +{ + EAS_RESULT result; + EAS_U32 len; + EAS_I32 pos; + EAS_U32 temp; + EAS_U8 c; + + /* get the meta-event type */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + + /* get the length */ + if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS) + return result; + + /* get the current file position so we can skip the event */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pSMFStream->fileHandle, &pos)) != EAS_SUCCESS) + return result; + pos += (EAS_I32) len; + + /* end of track? */ + if (c == SMF_META_END_OF_TRACK) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: end of track\n", c, len); */ } + pSMFStream->ticks = SMF_END_OF_TRACK; + } + + /* tempo event? */ + else if (c == SMF_META_TEMPO) + { + /* read the 3-byte timebase value */ + temp = 0; + while (len--) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + temp = (temp << 8) | c; + } + + pSMFData->tickConv = (EAS_U16) (((temp * 1024) / pSMFData->ppqn + 500) / 1000); + pSMFData->flags |= SMF_FLAGS_HAS_TEMPO; + } + + /* check for time signature - see iMelody spec V1.4 section 4.1.2.2.3.6 */ + else if (c == SMF_META_TIME_SIGNATURE) + { + pSMFData->flags |= SMF_FLAGS_HAS_TIME_SIG; + } + + /* if the host has registered a metadata callback return the metadata */ + else if (pSMFData->metadata.callback) + { + EAS_I32 readLen; + E_EAS_METADATA_TYPE metaType; + + metaType = EAS_METADATA_UNKNOWN; + + /* only process title on the first track */ + if (c == SMF_META_SEQTRK_NAME) + metaType = EAS_METADATA_TITLE; + else if (c == SMF_META_TEXT) + metaType = EAS_METADATA_TEXT; + else if (c == SMF_META_COPYRIGHT) + metaType = EAS_METADATA_COPYRIGHT; + else if (c == SMF_META_LYRIC) + metaType = EAS_METADATA_LYRIC; + + if (metaType != EAS_METADATA_UNKNOWN) + { + readLen = pSMFData->metadata.bufferSize - 1; + if ((EAS_I32) len < readLen) + readLen = (EAS_I32) len; + if ((result = EAS_HWReadFile(pEASData->hwInstData, pSMFStream->fileHandle, pSMFData->metadata.buffer, readLen, &readLen)) != EAS_SUCCESS) + return result; + pSMFData->metadata.buffer[readLen] = 0; + pSMFData->metadata.callback(metaType, pSMFData->metadata.buffer, pSMFData->metadata.pUserData); + } + } + + /* position file to next event - in case we ignored all or part of the meta-event */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFStream->fileHandle, pos)) != EAS_SUCCESS) + return result; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: type=%02x, len=%d\n", c, len); */ } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseSysEx() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode) +{ + EAS_RESULT result; + EAS_U32 len; + EAS_U8 c; + + /* get the length */ + if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS) + return result; + + /* start of SysEx message? */ + if (f0 == 0xf0) + { + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, f0, parserMode)) != EAS_SUCCESS) + return result; + } + + /* feed the SysEx to the stream parser */ + while (len--) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + + /* check for GM system ON */ + if (pSMFStream->midiStream.flags & MIDI_FLAG_GM_ON) + pSMFData->flags |= SMF_FLAGS_HAS_GM_ON; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseEvent() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode) +{ + EAS_RESULT result; + EAS_U8 c; + + /* get the event type */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + + /* parse meta-event */ + if (c == 0xff) + { + if ((result = SMF_ParseMetaEvent(pEASData, pSMFData, pSMFStream)) != EAS_SUCCESS) + return result; + } + + /* parse SysEx */ + else if ((c == 0xf0) || (c == 0xf7)) + { + if ((result = SMF_ParseSysEx(pEASData, pSMFData, pSMFStream, c, parserMode)) != EAS_SUCCESS) + return result; + } + + /* parse MIDI message */ + else + { + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + + /* keep streaming data to the MIDI parser until the message is complete */ + while (pSMFStream->midiStream.pending) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + } + + } + + /* chase mode logic */ + if (pSMFData->time == 0) + { + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + { + if (pSMFStream->midiStream.flags & MIDI_FLAG_FIRST_NOTE) + pSMFData->flags &= ~SMF_FLAGS_CHASE_MODE; + } + else if ((pSMFData->flags & SMF_FLAGS_SETUP_BAR) == SMF_FLAGS_SETUP_BAR) + pSMFData->flags = (pSMFData->flags & ~SMF_FLAGS_SETUP_BAR) | SMF_FLAGS_CHASE_MODE; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Parses the header of an SMF file, allocates memory the stream parsers and initializes the + * stream parsers. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pSMFData - pointer to parser instance data + * fileHandle - file handle + * fileOffset - offset in the file where the header data starts, usually 0 + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{801} we know that 'goto' is deprecated - but it's cleaner in this case */ +EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData) +{ + EAS_RESULT result; + EAS_I32 i; + EAS_U16 division; + EAS_U32 chunkSize; + EAS_U32 chunkStart; + EAS_U32 temp; + EAS_U32 ticks; + + /* rewind the file and find the end of the header chunk */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_HEADER_SIZE)) != EAS_SUCCESS) + goto ReadError; + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* determine the number of tracks */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_NUM_TRACKS)) != EAS_SUCCESS) + goto ReadError; + if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &pSMFData->numStreams, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* limit the number of tracks */ + if (pSMFData->numStreams > MAX_SMF_STREAMS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "SMF file contains %u tracks, playing %d tracks\n", pSMFData->numStreams, MAX_SMF_STREAMS); */ } + pSMFData->numStreams = MAX_SMF_STREAMS; + } + + /* get the time division */ + if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &division, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* setup default timebase for 120 bpm */ + pSMFData->ppqn = 192; + if (division & 0x8000) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"No support for SMPTE code timebase\n"); */ } + else + pSMFData->ppqn = (division & 0x7fff); + pSMFData->tickConv = (EAS_U16) (((SMF_DEFAULT_TIMEBASE * 1024) / pSMFData->ppqn + 500) / 1000); + + /* dynamic memory allocation, allocate memory for streams */ + if (pSMFData->streams == NULL) + { + pSMFData->streams = EAS_HWMalloc(hwInstData,sizeof(S_SMF_STREAM) * pSMFData->numStreams); + if (pSMFData->streams == NULL) + return EAS_ERROR_MALLOC_FAILED; + + /* zero the memory to insure complete initialization */ + EAS_HWMemSet((void *)(pSMFData->streams), 0, sizeof(S_SMF_STREAM) * pSMFData->numStreams); + } + + /* find the start of each track */ + chunkStart = (EAS_U32) pSMFData->fileOffset; + ticks = 0x7fffffffL; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + + for (;;) + { + + /* calculate start of next chunk - checking for errors */ + temp = chunkStart + SMF_CHUNK_INFO_SIZE + chunkSize; + if (temp <= chunkStart) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Error in chunk size at offset %d\n", chunkStart); */ } + return EAS_ERROR_FILE_FORMAT; + } + chunkStart = temp; + + /* seek to the start of the next chunk */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, (EAS_I32) chunkStart)) != EAS_SUCCESS) + goto ReadError; + + /* read the chunk identifier */ + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* read the chunk size */ + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* make sure this is an 'MTrk' chunk */ + if (temp == SMF_CHUNK_TYPE_TRACK) + break; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Unexpected chunk type: 0x%08x\n", temp); */ } + } + + /* initalize some data */ + pSMFData->streams[i].ticks = 0; + pSMFData->streams[i].fileHandle = pSMFData->fileHandle; + + /* NULL the file handle so we don't try to close it twice */ + pSMFData->fileHandle = NULL; + + /* save this file position as the start of the track */ + pSMFData->streams[i].startFilePos = (EAS_I32) chunkStart + SMF_CHUNK_INFO_SIZE; + + /* initalize the MIDI parser data */ + EAS_InitMIDIStream(&pSMFData->streams[i].midiStream); + + /* parse the first delta time in each stream */ + if ((result = SMF_GetDeltaTime(hwInstData, &pSMFData->streams[i])) != EAS_SUCCESS) + goto ReadError; + + if (pSMFData->streams[i].ticks < ticks) + { + ticks = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + + /* more tracks to do, create a duplicate file handle */ + if (i < (pSMFData->numStreams - 1)) + { + if ((result = EAS_HWDupHandle(hwInstData, pSMFData->streams[i].fileHandle, &pSMFData->fileHandle)) != EAS_SUCCESS) + goto ReadError; + } + } + + /* update the time of the next event */ + if (pSMFData->nextStream) + SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks); + + return EAS_SUCCESS; + + /* ugly goto: but simpler than structured */ + ReadError: + if (result == EAS_EOF) + return EAS_ERROR_FILE_FORMAT; + return result; +} + +/*---------------------------------------------------------------------------- + * SMF_UpdateTime() + *---------------------------------------------------------------------------- + * Purpose: + * Update the millisecond time base by converting the ticks into millieconds + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks) +{ + EAS_U32 temp1, temp2; + + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + return; + + temp1 = (ticks >> 10) * pSMFData->tickConv; + temp2 = (ticks & 0x3ff) * pSMFData->tickConv; + pSMFData->time += (EAS_I32)((temp1 << 8) + (temp2 >> 2)); +} + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smf.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smf.h new file mode 100755 index 0000000..37c0790 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smf.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smf.h + * + * Contents and purpose: + * SMF Type 0 and 1 File Parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SMF_H +#define _EAS_SMF_H + +/* prototypes for private interface to SMF parser */ +EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData); + +#endif /* end _EAS_SMF_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smfdata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smfdata.c new file mode 100755 index 0000000..383d7f3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smfdata.c @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smfdata.c + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_miditypes.h" +#include "eas_smfdata.h" + +/*---------------------------------------------------------------------------- + * + * S_SMF_STREAM + * + * Static memory allocation for SMF parser + *---------------------------------------------------------------------------- +*/ +static S_SMF_STREAM eas_SMFStreams[MAX_SMF_STREAMS]; + +/*---------------------------------------------------------------------------- + * + * eas_SMFData + * + * Static memory allocation for SMF parser + *---------------------------------------------------------------------------- +*/ +S_SMF_DATA eas_SMFData = +{ + eas_SMFStreams, /* pointer to individual streams in file */ + 0, /* pointer to next stream with event */ + 0, /* pointer to synth */ + 0, /* file handle */ + { 0, 0, 0, 0}, /* metadata callback */ + 0, /* file offset */ + 0, /* current time in milliseconds/256 */ + 0, /* actual number of streams */ + 0, /* current MIDI tick to msec conversion */ + 0, /* ticks per quarter note */ + 0, /* current state EAS_STATE_XXXX */ + 0 /* flags */ +}; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smfdata.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smfdata.h new file mode 100755 index 0000000..8861d90 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_smfdata.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smfdata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 686 $ + * $Date: 2007-05-03 14:10:54 -0700 (Thu, 03 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SMF_DATA_H +#define _EAS_SMF_DATA_H + +#ifndef MAX_SMF_STREAMS +#define MAX_SMF_STREAMS 17 +#endif + +/* offsets in to the SMF file */ +#define SMF_OFS_HEADER_SIZE 4 +#define SMF_OFS_FILE_TYPE 8 +#define SMF_OFS_NUM_TRACKS 10 + +/* size of chunk info (chunk ID + chunk size) */ +#define SMF_CHUNK_INFO_SIZE 8 + +/* 'MTrk' track chunk ID */ +#define SMF_CHUNK_TYPE_TRACK 0x4d54726bL + +/* some useful meta-events */ +#define SMF_META_TEXT 0x01 +#define SMF_META_COPYRIGHT 0x02 +#define SMF_META_SEQTRK_NAME 0x03 +#define SMF_META_LYRIC 0x05 +#define SMF_META_END_OF_TRACK 0x2f +#define SMF_META_TEMPO 0x51 +#define SMF_META_TIME_SIGNATURE 0x58 + +/* default timebase (120BPM) */ +#define SMF_DEFAULT_TIMEBASE 500000L + +/* value for pSMFStream->ticks to signify end of track */ +#define SMF_END_OF_TRACK 0xffffffff + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_sndlib.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_sndlib.h new file mode 100755 index 0000000..416be6e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_sndlib.h @@ -0,0 +1,406 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_sndlib.h + * + * Contents and purpose: + * Declarations for the sound library + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SNDLIB_H +#define _EAS_SNDLIB_H + +#include "eas_types.h" +#include "eas_synthcfg.h" + +#ifdef _WT_SYNTH +#include "eas_wtengine.h" +#endif + +/*---------------------------------------------------------------------------- + * This is bit of a hack to allow us to keep the same structure + * declarations for the DLS parser. Normally, the data is located + * in read-only memory, but for DLS, we store the data in RW + * memory. + *---------------------------------------------------------------------------- +*/ +#ifndef SCNST +#define SCNST const +#endif + +/*---------------------------------------------------------------------------- + * sample size + *---------------------------------------------------------------------------- +*/ +#ifdef _16_BIT_SAMPLES +typedef EAS_I16 EAS_SAMPLE; +#else +typedef EAS_I8 EAS_SAMPLE; +#endif + +/*---------------------------------------------------------------------------- + * EAS Library ID - quick check for valid library and version + *---------------------------------------------------------------------------- +*/ +#define _EAS_LIBRARY_VERSION 0x01534145 + +#define NUM_PROGRAMS_IN_BANK 128 +#define INVALID_REGION_INDEX 0xffff + +/* this bit in region index indicates that region is for secondary synth */ +#define FLAG_RGN_IDX_FM_SYNTH 0x8000 +#define FLAG_RGN_IDX_DLS_SYNTH 0x4000 +#define REGION_INDEX_MASK 0x3fff + +/*---------------------------------------------------------------------------- + * Generic region data structure + * + * This must be the first element in each region structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_region_tag +{ + EAS_U16 keyGroupAndFlags; + EAS_U8 rangeLow; + EAS_U8 rangeHigh; +} S_REGION; + +/* + * Bit fields for m_nKeyGroupAndFlags + * Bits 0-2 are mode bits in FM synth + * Bits 8-11 are the key group + */ +#define REGION_FLAG_IS_LOOPED 0x01 +#define REGION_FLAG_USE_WAVE_GENERATOR 0x02 +#define REGION_FLAG_USE_ADPCM 0x04 +#define REGION_FLAG_ONE_SHOT 0x08 +#define REGION_FLAG_SQUARE_WAVE 0x10 +#define REGION_FLAG_OFF_CHIP 0x20 +#define REGION_FLAG_NON_SELF_EXCLUSIVE 0x40 +#define REGION_FLAG_LAST_REGION 0x8000 + +/*---------------------------------------------------------------------------- + * Envelope data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_envelope_tag +{ + EAS_I16 attackTime; + EAS_I16 decayTime; + EAS_I16 sustainLevel; + EAS_I16 releaseTime; +} S_ENVELOPE; + +/*---------------------------------------------------------------------------- + * DLS envelope data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_dls_envelope_tag +{ + EAS_I16 delayTime; + EAS_I16 attackTime; + EAS_I16 holdTime; + EAS_I16 decayTime; + EAS_I16 sustainLevel; + EAS_I16 releaseTime; + EAS_I16 velToAttack; + EAS_I16 keyNumToDecay; + EAS_I16 keyNumToHold; +} S_DLS_ENVELOPE; + +/*---------------------------------------------------------------------------- + * LFO data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_lfo_params_tag +{ + EAS_I16 lfoFreq; + EAS_I16 lfoDelay; +} S_LFO_PARAMS; + +/*---------------------------------------------------------------------------- + * Articulation data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_articulation_tag +{ + S_ENVELOPE eg1; + S_ENVELOPE eg2; + EAS_I16 lfoToPitch; + EAS_I16 lfoDelay; + EAS_I16 lfoFreq; + EAS_I16 eg2ToPitch; + EAS_I16 eg2ToFc; + EAS_I16 filterCutoff; + EAS_I8 lfoToGain; + EAS_U8 filterQ; + EAS_I8 pan; +} S_ARTICULATION; + +/*---------------------------------------------------------------------------- + * DLS articulation data structure + *---------------------------------------------------------------------------- +*/ + +typedef struct s_dls_articulation_tag +{ + S_LFO_PARAMS modLFO; + S_LFO_PARAMS vibLFO; + + S_DLS_ENVELOPE eg1; + S_DLS_ENVELOPE eg2; + + EAS_I16 eg1ShutdownTime; + + EAS_I16 filterCutoff; + EAS_I16 modLFOToFc; + EAS_I16 modLFOCC1ToFc; + EAS_I16 modLFOChanPressToFc; + EAS_I16 eg2ToFc; + EAS_I16 velToFc; + EAS_I16 keyNumToFc; + + EAS_I16 modLFOToGain; + EAS_I16 modLFOCC1ToGain; + EAS_I16 modLFOChanPressToGain; + + EAS_I16 tuning; + EAS_I16 keyNumToPitch; + EAS_I16 vibLFOToPitch; + EAS_I16 vibLFOCC1ToPitch; + EAS_I16 vibLFOChanPressToPitch; + EAS_I16 modLFOToPitch; + EAS_I16 modLFOCC1ToPitch; + EAS_I16 modLFOChanPressToPitch; + EAS_I16 eg2ToPitch; + + /* pad to 4-byte boundary */ + EAS_U16 pad; + + EAS_I8 pan; + EAS_U8 filterQandFlags; + +#ifdef _REVERB + EAS_I16 reverbSend; + EAS_I16 cc91ToReverbSend; +#endif + +#ifdef _CHORUS + EAS_I16 chorusSend; + EAS_I16 cc93ToChorusSend; +#endif +} S_DLS_ARTICULATION; + +/* flags in filterQandFlags + * NOTE: Q is stored in bottom 5 bits + */ +#define FLAG_DLS_VELOCITY_SENSITIVE 0x80 +#define FILTER_Q_MASK 0x1f + +/*---------------------------------------------------------------------------- + * Wavetable region data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_region_tag +{ + S_REGION region; + EAS_I16 tuning; + EAS_I16 gain; + EAS_U32 loopStart; + EAS_U32 loopEnd; + EAS_U16 waveIndex; + EAS_U16 artIndex; +} S_WT_REGION; + +/*---------------------------------------------------------------------------- + * DLS region data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_dls_region_tag +{ + S_WT_REGION wtRegion; + EAS_U8 velLow; + EAS_U8 velHigh; +} S_DLS_REGION; + +/*---------------------------------------------------------------------------- + * FM synthesizer data structures + *---------------------------------------------------------------------------- +*/ +typedef struct s_fm_oper_tag +{ + EAS_I16 tuning; + EAS_U8 attackDecay; + EAS_U8 velocityRelease; + EAS_U8 egKeyScale; + EAS_U8 sustain; + EAS_U8 gain; + EAS_U8 flags; +} S_FM_OPER; + +/* defines for S_FM_OPER.m_nFlags */ +#define FM_OPER_FLAG_MONOTONE 0x01 +#define FM_OPER_FLAG_NO_VIBRATO 0x02 +#define FM_OPER_FLAG_NOISE 0x04 +#define FM_OPER_FLAG_LINEAR_VELOCITY 0x08 + +/* NOTE: The first two structure elements are common with S_WT_REGION + * and we will rely on that in the voice management code and must + * remain there unless the voice management code is revisited. + */ +typedef struct s_fm_region_tag +{ + S_REGION region; + EAS_U8 vibTrem; + EAS_U8 lfoFreqDelay; + EAS_U8 feedback; + EAS_I8 pan; + S_FM_OPER oper[4]; +} S_FM_REGION; + +/*---------------------------------------------------------------------------- + * Common data structures + *---------------------------------------------------------------------------- +*/ + +/*---------------------------------------------------------------------------- + * Program data structure + * Used for individual programs not stored as a complete bank. + *---------------------------------------------------------------------------- +*/ +typedef struct s_program_tag +{ + EAS_U32 locale; + EAS_U16 regionIndex; +} S_PROGRAM; + +/*---------------------------------------------------------------------------- + * Bank data structure + * + * A bank always consists of 128 programs. If a bank is less than 128 + * programs, it should be stored as a spare matrix in the pPrograms + * array. + * + * bankNum: MSB/LSB of MIDI bank select controller + * regionIndex: Index of first region in program + *---------------------------------------------------------------------------- +*/ +typedef struct s_bank_tag +{ + EAS_U16 locale; + EAS_U16 regionIndex[NUM_PROGRAMS_IN_BANK]; +} S_BANK; + + +/* defines for libFormat field + * bits 0-17 are the sample rate + * bit 18 is true if wavetable is present + * bit 19 is true if FM is present + * bit 20 is true if filter is enabled + * bit 21 is sample depth (0 = 8-bits, 1 = 16-bits) + * bits 22-31 are reserved + */ +#define LIBFORMAT_SAMPLE_RATE_MASK 0x0003ffff +#define LIB_FORMAT_TYPE_MASK 0x000c0000 +#define LIB_FORMAT_WAVETABLE 0x00000000 +#define LIB_FORMAT_FM 0x00040000 +#define LIB_FORMAT_HYBRID 0x00080000 +#define LIB_FORMAT_FILTER_ENABLED 0x00100000 +#define LIB_FORMAT_16_BIT_SAMPLES 0x00200000 + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * DLS data structure + * + * pDLSPrograms pointer to array of DLS programs + * pDLSRegions pointer to array of DLS regions + * pDLSArticulations pointer to array of DLS articulations + * pSampleLen pointer to array of sample lengths + * ppSamples pointer to array of sample pointers + * numDLSPrograms number of DLS programs + * numDLSRegions number of DLS regions + * numDLSArticulations number of DLS articulations + * numDLSSamples number of DLS samples + *---------------------------------------------------------------------------- +*/ +typedef struct s_eas_dls_tag +{ + S_PROGRAM *pDLSPrograms; + S_DLS_REGION *pDLSRegions; + S_DLS_ARTICULATION *pDLSArticulations; + EAS_U32 *pDLSSampleLen; + EAS_U32 *pDLSSampleOffsets; + EAS_SAMPLE *pDLSSamples; + EAS_U16 numDLSPrograms; + EAS_U16 numDLSRegions; + EAS_U16 numDLSArticulations; + EAS_U16 numDLSSamples; + EAS_U8 refCount; +} S_DLS; +#endif + +/*---------------------------------------------------------------------------- + * Sound library data structure + * + * pBanks pointer to array of banks + * pPrograms pointer to array of programs + * pWTRegions pointer to array of wavetable regions + * pFMRegions pointer to array of FM regions + * pArticulations pointer to array of articulations + * pSampleLen pointer to array of sample lengths + * ppSamples pointer to array of sample pointers + * numBanks number of banks + * numPrograms number of individual program + * numRegions number of regions + * numArticulations number of articulations + * numSamples number of samples + *---------------------------------------------------------------------------- +*/ +typedef struct s_eas_sndlib_tag +{ + SCNST EAS_U32 identifier; + SCNST EAS_U32 libAttr; + + SCNST S_BANK *pBanks; + SCNST S_PROGRAM *pPrograms; + + SCNST S_WT_REGION *pWTRegions; + SCNST S_ARTICULATION *pArticulations; + SCNST EAS_U32 *pSampleLen; + SCNST EAS_U32 *pSampleOffsets; + SCNST EAS_SAMPLE *pSamples; + + SCNST S_FM_REGION *pFMRegions; + + SCNST EAS_U16 numBanks; + SCNST EAS_U16 numPrograms; + + SCNST EAS_U16 numWTRegions; + SCNST EAS_U16 numArticulations; + SCNST EAS_U16 numSamples; + + SCNST EAS_U16 numFMRegions; +} S_EAS; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synth.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synth.h new file mode 100755 index 0000000..6274b7d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synth.h @@ -0,0 +1,395 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synth.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for synth. + * + * Copyright Sonic Network Inc. 2004, 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 718 $ + * $Date: 2007-06-08 16:43:16 -0700 (Fri, 08 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTH_H +#define _EAS_SYNTH_H + +#include "eas_types.h" +#include "eas_sndlib.h" + +#ifdef _WT_SYNTH +#include "eas_wtsynth.h" +#endif + +#ifdef _FM_SYNTH +#include "eas_fmsynth.h" +#endif + +#ifndef NUM_OUTPUT_CHANNELS +#define NUM_OUTPUT_CHANNELS 2 +#endif + +#ifndef MAX_SYNTH_VOICES +#define MAX_SYNTH_VOICES 64 +#endif + +#ifndef MAX_VIRTUAL_SYNTHESIZERS +#define MAX_VIRTUAL_SYNTHESIZERS 4 +#endif + +/* defines */ +#ifndef NUM_PRIMARY_VOICES +#define NUM_PRIMARY_VOICES MAX_SYNTH_VOICES +#elif !defined(NUM_SECONDARY_VOICES) +#define NUM_SECONDARY_VOICES (MAX_SYNTH_VOICES - NUM_PRIMARY_VOICES) +#endif + +#if defined(EAS_WT_SYNTH) +#define NUM_WT_VOICES MAX_SYNTH_VOICES + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +#define NUM_FM_VOICES MAX_SYNTH_VOICES + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +#define NUM_WT_VOICES MAX_SYNTH_VOICES + +/* wavetable drums and FM melodic on MCU */ +#elif defined(EAS_HYBRID_SYNTH) +#define NUM_WT_VOICES NUM_PRIMARY_VOICES +#define NUM_FM_VOICES NUM_SECONDARY_VOICES + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +#define NUM_WT_VOICES NUM_PRIMARY_VOICES +#define NUM_FM_VOICES NUM_SECONDARY_VOICES + +/* FM synth on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +#define NUM_FM_VOICES MAX_SYNTH_VOICES + +#else +#error "Unrecognized architecture option" +#endif + +#define NUM_SYNTH_CHANNELS 16 + +#define DEFAULT_SYNTH_VOICES MAX_SYNTH_VOICES + +/* use the following values to specify unassigned channels or voices */ +#define UNASSIGNED_SYNTH_CHANNEL NUM_SYNTH_CHANNELS +#define UNASSIGNED_SYNTH_VOICE MAX_SYNTH_VOICES + + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ +#define SYNTH_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << SYNTH_UPDATE_PERIOD_IN_BITS) + +/* stealing weighting factors */ +#define NOTE_AGE_STEAL_WEIGHT 1 +#define NOTE_GAIN_STEAL_WEIGHT 4 +#define CHANNEL_POLY_STEAL_WEIGHT 12 +#define CHANNEL_PRIORITY_STEAL_WEIGHT 2 +#define NOTE_MATCH_PENALTY 128 +#define SYNTH_PRIORITY_WEIGHT 8 + +/* default synth master volume */ +#define DEFAULT_SYNTH_MASTER_VOLUME 0x7fff + +#define DEFAULT_SYNTH_PRIORITY 5 + +/* default tuning values */ +#define DEFAULT_PITCH_BEND_SENSITIVITY 200 /* 2 semitones */ +#define DEFAULT_FINE_PITCH 0 /* 0 cents */ +#define DEFAULT_COARSE_PITCH 0 /* 0 semitones */ + +/* default drum channel is 10, but is internally 9 due to unit offset */ +#define DEFAULT_DRUM_CHANNEL 9 + +/* drum channel can simultaneously play this many voices at most */ +#define DEFAULT_CHANNEL_POLYPHONY_LIMIT 2 + +/* default instrument is acoustic piano */ +#define DEFAULT_MELODY_BANK_MSB 0x79 +#define DEFAULT_RHYTHM_BANK_MSB 0x78 +#define DEFAULT_MELODY_BANK_NUMBER (DEFAULT_MELODY_BANK_MSB << 8) +#define DEFAULT_RHYTHM_BANK_NUMBER (DEFAULT_RHYTHM_BANK_MSB << 8) +#define DEFAULT_SYNTH_PROGRAM_NUMBER 0 + +#define DEFAULT_PITCH_BEND 0x2000 /* 0x2000 == (0x40 << 7) | 0x00 */ +#define DEFAULT_MOD_WHEEL 0 +#define DEFAULT_CHANNEL_VOLUME 0x64 +#define DEFAULT_PAN 0x40 /* decimal 64, center */ + +#ifdef _REVERB +#define DEFAULT_REVERB_SEND 40 /* some reverb */ +#endif + +#ifdef _CHORUS +#define DEFAULT_CHORUS_SEND 0 /* no chorus */ +#endif + +#define DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY 0 /* EAS synth uses a different default */ +#define DEFAULT_FILTER_RESONANCE 0 +#define DEFAULT_EXPRESSION 0x7F + +#define DEFAULT_CHANNEL_PRESSURE 0 + +#define DEFAULT_REGISTERED_PARAM 0x3FFF + +#define DEFAULT_CHANNEL_STATIC_GAIN 0 +#define DEFAULT_CHANNEL_STATIC_PITCH 0 + +#define DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS 50 +#define DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS 50 + +#define DEFAULT_KEY_NUMBER 0x69 +#define DEFAULT_VELOCITY 0x64 +#define DEFAULT_REGION_INDEX 0 +#define DEFAULT_ARTICULATION_INDEX 0 +#define DEFAULT_VOICE_GAIN 0 +#define DEFAULT_AGE 0 +#define DEFAULT_SP_MIDI_PRIORITY 16 + + +/* filter defines */ +#define DEFAULT_FILTER_ZERO 0 +#define FILTER_CUTOFF_MAX_PITCH_CENTS 1919 +#define FILTER_CUTOFF_MIN_PITCH_CENTS -4467 +#define A5_PITCH_OFFSET_IN_CENTS 6900 + +/*------------------------------------ + * S_SYNTH_CHANNEL data structure + *------------------------------------ +*/ + +/* S_SYNTH_CHANNEL.m_nFlags */ +#define CHANNEL_FLAG_SUSTAIN_PEDAL 0x01 +#define CHANNEL_FLAG_MUTE 0x02 +#define CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS 0x04 +#define CHANNEL_FLAG_RHYTHM_CHANNEL 0x08 +#define CHANNEL_FLAG_EXTERNAL_AUDIO 0x10 +#define DEFAULT_CHANNEL_FLAGS 0 + +/* macros for extracting virtual synth and channel numbers */ +#define GET_VSYNTH(a) ((a) >> 4) +#define GET_CHANNEL(a) ((a) & 15) + +typedef struct s_synth_channel_tag +{ + /* use static channel parameters to reduce MIPs */ + /* parameters shared by multiple voices assigned to same channel */ + EAS_I32 staticPitch; /* (pitch bend * pitch sens) + fine pitch */ + EAS_I16 staticGain; /* (CC7 * CC11 * master vol)^2 */ + + EAS_U16 regionIndex; /* index of first region in program */ + + EAS_U16 bankNum; /* play programs from this bank */ + EAS_I16 pitchBend; /* pitch wheel value */ + EAS_I16 pitchBendSensitivity; + EAS_I16 registeredParam; /* currently selected registered param */ + + +#if defined(_FM_SYNTH) + EAS_I16 lfoAmt; /* amount of LFO to apply to voice */ +#endif + + EAS_U8 programNum; /* play this instrument number */ + EAS_U8 modWheel; /* CC1 */ + EAS_U8 volume; /* CC7 */ + EAS_U8 pan; /* CC10 */ + + EAS_U8 expression; /* CC11 */ + + /* the following parameters are controlled by RPNs */ + EAS_I8 finePitch; + EAS_I8 coarsePitch; + + EAS_U8 channelPressure; /* applied to all voices on a given channel */ + + EAS_U8 channelFlags; /* bit field channelFlags for */ + /* CC64, SP-MIDI channel masking */ + + EAS_U8 pool; /* SPMIDI channel voice pool */ + EAS_U8 mip; /* SPMIDI MIP setting */ + +#ifdef _REVERB + EAS_U8 reverbSend; /* CC91 */ +#endif + +#ifdef _CHORUS + EAS_U8 chorusSend; /* CC93 */ +#endif +} S_SYNTH_CHANNEL; + +/*------------------------------------ + * S_SYNTH_VOICE data structure + *------------------------------------ +*/ + +/* S_SYNTH_VOICE.m_nFlags */ +#define VOICE_FLAG_UPDATE_VOICE_PARAMETERS 0x01 +#define VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF 0x02 +#define VOICE_FLAG_DEFER_MIDI_NOTE_OFF 0x04 +#define VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET 0x08 +#define VOICE_FLAG_DEFER_MUTE 0x40 +#define DEFAULT_VOICE_FLAGS 0 + +/* S_SYNTH_VOICE.m_eState */ +typedef enum { + + eVoiceStateFree = 0, + eVoiceStateStart, + eVoiceStatePlay, + eVoiceStateRelease, + eVoiceStateMuting, + eVoiceStateStolen, + eVoiceStateInvalid /* should never be in this state! */ + +} E_VOICE_STATE; +#define DEFAULT_VOICE_STATE eVoiceStateFree + +typedef struct s_synth_voice_tag +{ + +/* These parameters are common to both wavetable and FM + * synthesizers. The voice manager should only access this data. + * Any other data should be manipulated by the code that is + * specific to that synthesizer and reflected back through the + * common state data available here. + */ + EAS_U16 regionIndex; /* index to wave and playback params */ + EAS_I16 gain; /* current gain */ + EAS_U16 age; /* large value means old note */ + EAS_U16 nextRegionIndex; /* index to wave and playback params */ + EAS_U8 voiceState; /* current voice state */ + EAS_U8 voiceFlags; /* misc flags/bit fields */ + EAS_U8 channel; /* this voice plays on this synth channel */ + EAS_U8 note; /* 12 <= key number <= 108 */ + EAS_U8 velocity; /* 0 <= velocity <= 127 */ + EAS_U8 nextChannel; /* play stolen voice on this channel */ + EAS_U8 nextNote; /* 12 <= key number <= 108 */ + EAS_U8 nextVelocity; /* 0 <= velocity <= 127 */ +} S_SYNTH_VOICE; + +/*------------------------------------ + * S_SYNTH data structure + * + * One instance for each MIDI stream + *------------------------------------ +*/ + +/* S_SYNTH.m_nFlags */ +#define SYNTH_FLAG_RESET_IS_REQUESTED 0x01 +#define SYNTH_FLAG_SP_MIDI_ON 0x02 +#define SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS 0x04 +#define SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING 0x08 +#define DEFAULT_SYNTH_FLAGS SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS + +typedef struct s_synth_tag +{ + struct s_eas_data_tag *pEASData; + const S_EAS *pEAS; + +#ifdef DLS_SYNTHESIZER + S_DLS *pDLS; +#endif + +#ifdef EXTERNAL_AUDIO + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc; + EAS_EXT_EVENT_FUNC cbEventFunc; + EAS_VOID_PTR *pExtAudioInstData; +#endif + + S_SYNTH_CHANNEL channels[NUM_SYNTH_CHANNELS]; + EAS_I32 totalNoteCount; + EAS_U16 maxPolyphony; + EAS_U16 numActiveVoices; + EAS_U16 masterVolume; + EAS_U8 channelsByPriority[NUM_SYNTH_CHANNELS]; + EAS_U8 poolCount[NUM_SYNTH_CHANNELS]; + EAS_U8 poolAlloc[NUM_SYNTH_CHANNELS]; + EAS_U8 synthFlags; + EAS_I8 globalTranspose; + EAS_U8 vSynthNum; + EAS_U8 refCount; + EAS_U8 priority; +} S_SYNTH; + +/*------------------------------------ + * S_VOICE_MGR data structure + * + * One instance for each EAS library instance + *------------------------------------ +*/ +typedef struct s_voice_mgr_tag +{ + S_SYNTH *pSynth[MAX_VIRTUAL_SYNTHESIZERS]; + EAS_PCM voiceBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES]; + +#ifdef _FM_SYNTH + EAS_PCM operMixBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES]; + S_FM_VOICE fmVoices[NUM_FM_VOICES]; +#endif + +#ifdef _WT_SYNTH + S_WT_VOICE wtVoices[NUM_WT_VOICES]; +#endif + +#ifdef _REVERB + EAS_PCM reverbSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES]; +#endif + +#ifdef _CHORUS + EAS_PCM chorusSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES]; +#endif + S_SYNTH_VOICE voices[MAX_SYNTH_VOICES]; + + EAS_SNDLIB_HANDLE pGlobalEAS; + +#ifdef DLS_SYNTHESIZER + S_DLS *pGlobalDLS; +#endif + +#ifdef _SPLIT_ARCHITECTURE + EAS_FRAME_BUFFER_HANDLE pFrameBuffer; +#endif + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + EAS_U16 maxPolyphonyPrimary; + EAS_U16 maxPolyphonySecondary; +#endif + + EAS_I32 workload; + EAS_I32 maxWorkLoad; + + EAS_U16 activeVoices; + EAS_U16 maxPolyphony; + + EAS_U16 age; + +/* limits the number of voice starts in a frame for split architecture */ +#ifdef MAX_VOICE_STARTS + EAS_U16 numVoiceStarts; +#endif +} S_VOICE_MGR; + +#endif /* #ifdef _EAS_SYNTH_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synth_protos.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synth_protos.h new file mode 100755 index 0000000..b03af0f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synth_protos.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synth_protos.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for synth. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTH_PROTOS_H +#define _EAS_SYNTH_PROTOS_H + +/* includes */ +#include "eas_data.h" +#include "eas_sndlib.h" + +#ifdef _SPLIT_ARCHITECTURE +typedef struct s_frame_interface_tag +{ + EAS_BOOL (* EAS_CONST pfStartFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer); + EAS_BOOL (* EAS_CONST pfEndFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain); +} S_FRAME_INTERFACE; +#endif + +/* generic synthesizer interface */ +typedef struct +{ + EAS_RESULT (* EAS_CONST pfInitialize)(S_VOICE_MGR *pVoiceMgr); + EAS_RESULT (* EAS_CONST pfStartVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); + EAS_BOOL (* EAS_CONST pfUpdateVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); + void (* EAS_CONST pfReleaseVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); + void (* EAS_CONST pfMuteVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); + void (* EAS_CONST pfSustainPedal)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); + void (* EAS_CONST pfUpdateChannel)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); +} S_SYNTH_INTERFACE; + +#endif + + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synthcfg.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synthcfg.h new file mode 100755 index 0000000..78a4178 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_synthcfg.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synthcfg.h + * + * Contents and purpose: + * Defines for various synth configurations + * + * Copyright Sonic Network Inc. 2004, 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 664 $ + * $Date: 2007-04-25 13:11:22 -0700 (Wed, 25 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTHCFG_H +#define _EAS_SYNTHCFG_H + +#if defined(EAS_WT_SYNTH) +#define _WT_SYNTH + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +#define _FM_SYNTH + +/* wavetable drums and FM melodic on MCU */ +#elif defined(EAS_HYBRID_SYNTH) +#define _WT_SYNTH +#define _FM_SYNTH +#define _SECONDARY_SYNTH +#define _HYBRID_SYNTH + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +#define _WT_SYNTH +#define _SPLIT_ARCHITECTURE + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +#define _WT_SYNTH +#define _FM_SYNTH +#define _SECONDARY_SYNTH +#define _SPLIT_ARCHITECTURE +#define _HYBRID_SYNTH + +/* FM synth on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +#define _FM_SYNTH +#define _SPLIT_ARCHITECTURE + +#else +#error "Unrecognized architecture option" +#endif + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_vm_protos.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_vm_protos.h new file mode 100755 index 0000000..20f7c09 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_vm_protos.h @@ -0,0 +1,1086 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_vm_protos.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for voice manager. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 736 $ + * $Date: 2007-06-22 13:51:24 -0700 (Fri, 22 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_VM_PROTOS_H +#define _EAS_VM_PROTOS_H + +// includes +#include "eas_data.h" +#include "eas_sndlib.h" + +/*---------------------------------------------------------------------------- + * VMInitialize() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitialize (S_EAS_DATA *pEASData); + +/*---------------------------------------------------------------------------- + * VMInitMIDI() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitMIDI (S_EAS_DATA *pEASData, S_SYNTH **ppSynth); + +/*---------------------------------------------------------------------------- + * VMInitializeAllChannels() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllChannels (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMResetControllers() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMResetControllers (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMInitMIPTable() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the SP-MIDI MIP table + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * mute - EAS_FALSE to unmute channels, EAS_TRUE to mute + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitMIPTable (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMSetMIPEntry() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the priority and MIP level for a MIDI channel + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * channel - MIDI channel number + * priority - priority (0-15 with 0 = highest priority) + * mip - maximum instantaneous polyphony + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetMIPEntry (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 priority, EAS_U8 mip); + +/*---------------------------------------------------------------------------- + * VMUpdateMIPTable() + *---------------------------------------------------------------------------- + * Purpose: + * This routine is called when the polyphony count in the synthesizer changes + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMUpdateMIPTable (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMInitializeAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllVoices (S_VOICE_MGR *pVoiceMgr, EAS_INT vSynthNum); + +/*---------------------------------------------------------------------------- + * VMStartNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to play the requested note on the requested + * channel if possible. + * + * Inputs: + * nChannel - the MIDI channel + * nKeyNumber - the MIDI key number for this note + * nNoteVelocity - the key velocity for this note + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMStartNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity); + +/*---------------------------------------------------------------------------- + * VMCheckKeyGroup() + *---------------------------------------------------------------------------- + * Purpose: + * If the note that we've been asked to start is in the same key group as + * any currently playing notes, then we must shut down the currently playing + * note in the same key group and then start the newly requested note. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nRegionIndex - calling routine finds this index and gives to us + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * + * Side Effects: + * gsSynthObject.m_sVoice[free voice num].m_nKeyNumber may be assigned + * gsSynthObject.m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +void VMCheckKeyGroup (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U16 keyGroup, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMCheckPolyphonyLimiting() + *---------------------------------------------------------------------------- + * Purpose: + * We only play at most 2 of the same note on a MIDI channel. + * E.g., if we are asked to start note 36, and there are already two voices + * that are playing note 36, then we must steal the voice playing + * the oldest note 36 and use that stolen voice to play the new note 36. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * * + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber may be assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckPolyphonyLimiting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to end the requested note on the requested + * channel. + * + * Inputs: + * nChannel - the MIDI channel + * nKeyNumber - the key number of the note to stop + * nNoteVelocity - the note-off velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sVoice[free voice num].m_nSynthChannel may be assigned + * gsSynthObject.m_sVoice[free voice num].m_nKeyNumber is assigned + * gsSynthObject.m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +void VMStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 key, EAS_U8 velocity); + +/*---------------------------------------------------------------------------- + * VMFindAvailableVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Find an available voice and return the voice number if available. + * + * Inputs: + * pnVoiceNumber - really an output, see below + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - returns the voice number of available voice if found + * success - if there is an available voice + * failure - otherwise + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindAvailableVoice (S_VOICE_MGR *pVoiceMgr, EAS_INT *pVoiceNumber, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMStealVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Steal a voice and return the voice number + * + * Stealing algorithm: steal the best choice with minimal work, taking into + * account SP-Midi channel priorities and polyphony allocation. + * + * In one pass through all the voices, figure out which voice to steal + * taking into account a number of different factors: + * Priority of the voice's MIDI channel + * Number of voices over the polyphony allocation for voice's MIDI channel + * Amplitude of the voice + * Note age + * Key velocity (for voices that haven't been started yet) + * If any matching notes are found + * + * Inputs: + * nChannel - the channel that this voice wants to be started on + * nKeyNumber - the key number for this new voice + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - voice stolen + * EAS_RESULT EAS_SUCCESS - always successful + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMStealVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_INT *pVoiceNumber, EAS_U8 channel, EAS_U8 note, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMAddSamples() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize the requested number of samples. + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMAddSamples (S_VOICE_MGR *pVoiceMgr, EAS_I32 *pMixBuffer, EAS_I32 numSamplesToAdd); + +/*---------------------------------------------------------------------------- + * VMProgramChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the instrument (program) for the given channel. + * + * Depending on the program number, and the bank selected for this channel, the + * program may be in ROM, RAM (from SMAF or CMX related RAM wavetable), or + * Alternate wavetable (from mobile DLS or other DLS file) + * + * This function figures out what wavetable should be used, and sets it up as the + * wavetable to use for this channel. Also the channel may switch from a melodic + * channel to a rhythm channel, or vice versa. + * + * Inputs: + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nProgramNumber is likely changed + * gsSynthObject.m_sChannel[nChannel].m_psEAS may be changed + * gsSynthObject.m_sChannel[nChannel].m_bRhythmChannel may be changed + * + *---------------------------------------------------------------------------- +*/ +void VMProgramChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 program); + +/*---------------------------------------------------------------------------- + * VMChannelPressure() + *---------------------------------------------------------------------------- + * Purpose: + * Change the channel pressure for the given channel + * + * Inputs: + * nChannel - the MIDI channel + * nVelocity - the channel pressure value + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nChannelPressure is updated + *---------------------------------------------------------------------------- +*/ +void VMChannelPressure (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMPitchBend() + *---------------------------------------------------------------------------- + * Purpose: + * Change the pitch wheel value for the given channel. + * This routine constructs the proper 14-bit argument when the calling routine + * passes the pitch LSB and MSB. + * + * Note: some midi disassemblers display a bipolar pitch bend value. + * We can display the bipolar value using + * if m_nPitchBend >= 0x2000 + * bipolar pitch bend = postive (m_nPitchBend - 0x2000) + * else + * bipolar pitch bend = negative (0x2000 - m_nPitchBend) + * + * Inputs: + * nChannel - the MIDI channel + * nPitchLSB - the LSB byte from the pitch bend message + * nPitchMSB - the MSB byte from the message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nPitchBend is changed + * + *---------------------------------------------------------------------------- +*/ +void VMPitchBend (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 pitchLSB, EAS_U8 pitchMSB); + +/*---------------------------------------------------------------------------- + * VMControlChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the controller (or mode) for the given channel. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the controller number + * nControlValue - the controller number for this control change + * nControlValue - the value for this control change + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel] controller is changed + * + *---------------------------------------------------------------------------- +*/ +void VMControlChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMUpdateRPNStateMachine() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when we want to parse a stream of RPN messages. + * NOTE: The synth has only one set of global RPN data instead of RPN data + * per channel. + * So actually, we don't really need to look at the nChannel parameter, + * but we pass it to facilitate future upgrades. Furthermore, we only + * support RPN0 (pitch bend sensitivity), RPN1 (fine tuning) and + * RPN2 (coarse tuning). Any other RPNs are rejected. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the RPN controller number + * nControlValue - the value for this control change + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * gsSynthObject.m_RPN0 (or m_RPN1 or m_RPN2) may be updated if the + * proper RPN message sequence is parsed. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMUpdateRPNStateMachine (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMUpdateStaticChannelParameters() + *---------------------------------------------------------------------------- + * Purpose: + * Update all of the static channel parameters for channels that have had + * a controller change values + * Or if the synth has signalled that all channels must forcibly + * be updated + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * none + * + * Side Effects: + * - psSynthObject->m_sChannel[].m_nStaticGain and m_nStaticPitch + * are updated for channels whose controller values have changed + * or if the synth has signalled that all channels must forcibly + * be updated + *---------------------------------------------------------------------------- +*/ +void VMUpdateStaticChannelParameters (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReleaseAllDeferredNoteOffs() + *---------------------------------------------------------------------------- + * Purpose: + * Call this functin when the sustain flag is presently set but + * we are now transitioning from damper pedal on to + * damper pedal off. This means all notes in this channel + * that received a note off while the damper pedal was on, and + * had their note-off requests deferred, should now proceed to + * the release state. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllDeferredNoteOffs (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMCatchNotesForSustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when the sustain flag is presently clear and + * the damper pedal is off and we are transitioning from damper pedal OFF to + * damper pedal ON. Currently sounding notes should be left + * unchanged. However, we should try to "catch" notes if possible. + * If any notes have levels >= sustain level, catch them, + * otherwise, let them continue to release. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * psVoice->m_sEG1.m_eState = eEnvelopeStateSustainPedal + *---------------------------------------------------------------------------- +*/ +void VMCatchNotesForSustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMUpdateAllNotesAge() + *---------------------------------------------------------------------------- + * Purpose: + * Increment the note age for all voices older than the age of the voice + * that is stopping, effectively making the voices "younger". + * + * Inputs: + * nAge - age of voice that is going away + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * m_nAge for some voices is incremented + *---------------------------------------------------------------------------- +*/ +void VMUpdateAllNotesAge (S_VOICE_MGR *pVoiceMgr, EAS_U16 nAge); + +/*---------------------------------------------------------------------------- + * VMFindRegionIndex() + *---------------------------------------------------------------------------- + * Purpose: + * Find the region index for the given instrument using the midi key number + * and the RPN2 (coarse tuning) value. By using RPN2 as part of the + * region selection process, we reduce the amount a given sample has + * to be transposed by selecting the closest recorded root instead. + * + * Inputs: + * nChannel - current channel for this note + * nKeyNumber - current midi note number + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnRegionIndex - valid only if we returned success + * success if we found the region index number, otherwise + * failure + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindRegionIndex (S_VOICE_MGR *pVoiceMgr, EAS_U8 channel, EAS_U8 note, EAS_U16 *pRegionIndex); + +/*---------------------------------------------------------------------------- + * VMIncRefCount() + *---------------------------------------------------------------------------- + * Increment reference count for virtual synth + *---------------------------------------------------------------------------- +*/ +void VMIncRefCount (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReset() + *---------------------------------------------------------------------------- + * Purpose: + * We call this routine to start the process of reseting the synth. + * This routine sets a flag for the entire synth indicating that we want + * to reset. + * We also force all voices to mute quickly. + * However, we do not actually perform any synthesis in this routine. That + * is, we do not ramp the voices down from this routine, but instead, we + * let the "regular" synth processing steps take care of adding the ramp + * down samples to the output buffer. After we are sure that all voices + * have completed ramping down, we continue the process of resetting the + * synth (from another routine). + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - set a flag (in gsSynthObject.m_nFlags) indicating synth reset requested. + * - force all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMReset (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_BOOL force); + +/*---------------------------------------------------------------------------- + * VMMuteAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this in an emergency reset situation. + * This forces all voices to mute quickly. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMMuteVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum); +void VMMuteAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReleaseAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this after we've encountered the end of the Midi file. + * This ensures all voice are either in release (because we received their + * note off already) or forces them to mute quickly. + * We use this as a safety to prevent bad midi files from playing forever. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to release or mute + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMAllNotesOff() + *---------------------------------------------------------------------------- + * Purpose: + * Quickly mute all notes on the given channel. + * + * Inputs: + * nChannel - quickly turn off all notes on this channel + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices on this channel to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMAllNotesOff (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMDeferredStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Stop the notes that had deferred note-off requests. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None. + * + * Side Effects: + * voices that have had deferred note-off requests are now put into release + * gsSynthObject.m_sVoice[i].m_nFlags has the VOICE_FLAG_DEFER_MIDI_NOTE_OFF + * cleared + *---------------------------------------------------------------------------- +*/ +void VMDeferredStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMSetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * VMGetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * VMSetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth polyphony. 0 = no limit (i.e. can use + * all available voices). + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * VMGetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pSynth pointer to virtual synth + * pPolyphonyCount pointer to variable to receive data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * VMSetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * priority new priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 priority); + +/*---------------------------------------------------------------------------- + * VMGetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPriority pointer to variable to hold priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPriority); + +/*---------------------------------------------------------------------------- + * VMSetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for this sequence + * + * Inputs: + * nSynthVolume - the desired master volume + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +void VMSetVolume (S_SYNTH *pSynth, EAS_U16 masterVolume); + +/*---------------------------------------------------------------------------- + * VMSetPitchBendRange() + *---------------------------------------------------------------------------- + * Set the pitch bend range for the given channel. + *---------------------------------------------------------------------------- +*/ +void VMSetPitchBendRange (S_SYNTH *pSynth, EAS_INT channel, EAS_I16 pitchBendRange); + +/*---------------------------------------------------------------------------- + * VMSetEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the pointer to the sound library + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalEASLib (S_VOICE_MGR *pVoiceMgr, EAS_SNDLIB_HANDLE pEAS); +EAS_RESULT VMSetEASLib (S_SYNTH *pSynth, EAS_SNDLIB_HANDLE pEAS); + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMSetDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the pointer to the sound library + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalDLSLib (EAS_DATA_HANDLE pEASData, EAS_DLSLIB_HANDLE pDLS); +EAS_RESULT VMSetDLSLib (S_SYNTH *pSynth, EAS_DLSLIB_HANDLE pDLS); +#endif + +/*---------------------------------------------------------------------------- + * VMSetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * transposition - transpose amount (+/-12) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetTranposition (S_SYNTH *pSynth, EAS_I32 transposition); + +/*---------------------------------------------------------------------------- + * VMGetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMGetTranposition (S_SYNTH *pSynth, EAS_I32 *pTransposition); + +/*---------------------------------------------------------------------------- + * VMGetNoteCount() + *---------------------------------------------------------------------------- +* Returns the total note count +*---------------------------------------------------------------------------- +*/ +EAS_I32 VMGetNoteCount (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMRender() + *---------------------------------------------------------------------------- + * Purpose: + * This routine renders a frame of audio + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pVoicesRendered - number of voices rendered this frame + * + * Side Effects: + * sets psMidiObject->m_nMaxWorkloadPerFrame + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMRender (S_VOICE_MGR *pVoiceMgr, EAS_I32 numSamples, EAS_I32 *pMixBuffer, EAS_I32 *pVoicesRendered); + +/*---------------------------------------------------------------------------- + * VMInitWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Clears the workload counter + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitWorkload (S_VOICE_MGR *pVoiceMgr); + +/*---------------------------------------------------------------------------- + * VMSetWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the max workload for a single frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetWorkload (S_VOICE_MGR *pVoiceMgr, EAS_I32 maxWorkLoad); + +/*---------------------------------------------------------------------------- + * VMCheckWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Checks to see if work load has been exceeded on this frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckWorkload (S_VOICE_MGR *pVoiceMgr); + +/*---------------------------------------------------------------------------- + * VMActiveVoices() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the number of active voices in the synthesizer. + * + * Inputs: + * pEASData - pointer to instance data + * + * Outputs: + * Returns the number of active voices + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMActiveVoices (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMMIDIShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMMIDIShutdown (S_EAS_DATA *pEASData, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMShutdown (S_EAS_DATA *pEASData); + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Register a callback for external audio processing + *---------------------------------------------------------------------------- +*/ +void VMRegExtAudioCallback (S_SYNTH *pSynth, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc); + +/*---------------------------------------------------------------------------- + * VMGetMIDIControllers() + *---------------------------------------------------------------------------- + * Returns the MIDI controller values on the specified channel + *---------------------------------------------------------------------------- +*/ +void VMGetMIDIControllers (S_SYNTH *pSynth, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl); +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * VMStartFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Starts an audio frame + * + * Inputs: + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMStartFrame (S_EAS_DATA *pEASData); + +/*---------------------------------------------------------------------------- + * VMEndFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Stops an audio frame + * + * Inputs: + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMEndFrame (S_EAS_DATA *pEASData); +#endif + +#endif /* #ifdef _EAS_VM_PROTOS_H */ + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_voicemgt.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_voicemgt.c new file mode 100755 index 0000000..ab0b776 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_voicemgt.c @@ -0,0 +1,3971 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_voicemgt.c + * + * Contents and purpose: + * Implements the synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 794 $ + * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* includes */ +#include "eas.h" +#include "eas_data.h" +#include "eas_config.h" +#include "eas_report.h" +#include "eas_midictrl.h" +#include "eas_host.h" +#include "eas_synth_protos.h" +#include "eas_vm_protos.h" + +#ifdef DLS_SYNTHESIZER +#include "eas_mdls.h" +#endif + +// #define _DEBUG_VM + +/* some defines for workload */ +#define WORKLOAD_AMOUNT_SMALL_INCREMENT 5 +#define WORKLOAD_AMOUNT_START_NOTE 10 +#define WORKLOAD_AMOUNT_STOP_NOTE 10 +#define WORKLOAD_AMOUNT_KEY_GROUP 10 +#define WORKLOAD_AMOUNT_POLY_LIMIT 10 + +/* pointer to base sound library */ +extern S_EAS easSoundLib; + +#ifdef TEST_HARNESS +extern S_EAS easTestLib; +EAS_SNDLIB_HANDLE VMGetLibHandle(EAS_INT libNum) +{ + switch (libNum) + { + case 0: + return &easSoundLib; +#ifdef _WT_SYNTH + case 1: + return &easTestLib; +#endif + default: + return NULL; + } +} +#endif + +/* pointer to synthesizer interface(s) */ +#ifdef _WT_SYNTH +extern const S_SYNTH_INTERFACE wtSynth; +#endif + +#ifdef _FM_SYNTH +extern const S_SYNTH_INTERFACE fmSynth; +#endif + +typedef S_SYNTH_INTERFACE *S_SYNTH_INTERFACE_HANDLE; + +/* wavetable on MCU */ +#if defined(EAS_WT_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &fmSynth; + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_HYBRID_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +const S_SYNTH_INTERFACE *const pSecondarySynth = &fmSynth; + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +extern const S_FRAME_INTERFACE wtFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &wtFrameInterface; + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +const S_SYNTH_INTERFACE *const pSecondarySynth = &fmSynth; +extern const S_FRAME_INTERFACE fmFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &fmFrameInterface; + +/* FM on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &fmSynth; +extern const S_FRAME_INTERFACE fmFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &fmFrameInterface; + +#else +#error "Undefined architecture option" +#endif + +/*---------------------------------------------------------------------------- + * inline functions + *---------------------------------------------------------------------------- +*/ +EAS_INLINE const S_REGION* GetRegionPtr (S_SYNTH *pSynth, EAS_U16 regionIndex) +{ +#if defined(DLS_SYNTHESIZER) + if (regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + return &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK].wtRegion.region; +#endif +#if defined(_HYBRID_SYNTH) + if (regionIndex & FLAG_RGN_IDX_FM_SYNTH) + return &pSynth->pEAS->pFMRegions[regionIndex & REGION_INDEX_MASK].region; + else + return &pSynth->pEAS->pWTRegions[regionIndex].region; +#elif defined(_WT_SYNTH) + return &pSynth->pEAS->pWTRegions[regionIndex].region; +#elif defined(_FM_SYNTH) + return &pSynth->pEAS->pFMRegions[regionIndex].region; +#endif +} + +/*lint -esym(715, voiceNum) used in some implementation */ +EAS_INLINE const S_SYNTH_INTERFACE* GetSynthPtr (EAS_INT voiceNum) +{ +#if defined(_HYBRID_SYNTH) + if (voiceNum < NUM_PRIMARY_VOICES) + return pPrimarySynth; + else + return pSecondarySynth; +#else + return pPrimarySynth; +#endif +} + +EAS_INLINE EAS_INT GetAdjustedVoiceNum (EAS_INT voiceNum) +{ +#if defined(_HYBRID_SYNTH) + if (voiceNum >= NUM_PRIMARY_VOICES) + return voiceNum - NUM_PRIMARY_VOICES; +#endif + return voiceNum; +} + +EAS_INLINE EAS_U8 VSynthToChannel (S_SYNTH *pSynth, EAS_U8 channel) +{ + /*lint -e{734} synthNum is always 0-15 */ + return channel | (pSynth->vSynthNum << 4); +} + +/*---------------------------------------------------------------------------- + * InitVoice() + *---------------------------------------------------------------------------- + * Initialize a synthesizer voice + *---------------------------------------------------------------------------- +*/ +void InitVoice (S_SYNTH_VOICE *pVoice) +{ + pVoice->channel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->nextChannel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->note = pVoice->nextNote = DEFAULT_KEY_NUMBER; + pVoice->velocity = pVoice->nextVelocity = DEFAULT_VELOCITY; + pVoice->regionIndex = DEFAULT_REGION_INDEX; + pVoice->age = DEFAULT_AGE; + pVoice->voiceFlags = DEFAULT_VOICE_FLAGS; + pVoice->voiceState = DEFAULT_VOICE_STATE; +} + +/*---------------------------------------------------------------------------- + * IncVoicePoolCount() + *---------------------------------------------------------------------------- + * Updates the voice pool count when a voice changes state + *---------------------------------------------------------------------------- +*/ +static void IncVoicePoolCount (S_VOICE_MGR *pVoiceMgr, S_SYNTH_VOICE *pVoice) +{ + S_SYNTH *pSynth; + EAS_INT pool; + + /* ignore muting voices */ + if (pVoice->voiceState == eVoiceStateMuting) + return; + + if (pVoice->voiceState == eVoiceStateStolen) + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool; + } + else + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->channel)].pool; + } + + pSynth->poolCount[pool]++; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IncVoicePoolCount: Synth=%d pool=%d\n", pSynth->vSynthNum, pool); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * DecVoicePoolCount() + *---------------------------------------------------------------------------- + * Updates the voice pool count when a voice changes state + *---------------------------------------------------------------------------- +*/ +static void DecVoicePoolCount (S_VOICE_MGR *pVoiceMgr, S_SYNTH_VOICE *pVoice) +{ + S_SYNTH *pSynth; + EAS_INT pool; + + /* ignore muting voices */ + if (pVoice->voiceState == eVoiceStateMuting) + return; + + if (pVoice->voiceState == eVoiceStateStolen) + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool; + } + else + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->channel)].pool; + } + + pSynth->poolCount[pool]--; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "DecVoicePoolCount: Synth=%d pool=%d\n", pSynth->vSynthNum, pool); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * VMInitialize() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitialize (S_EAS_DATA *pEASData) +{ + S_VOICE_MGR *pVoiceMgr; + EAS_INT i; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pVoiceMgr = EAS_CMEnumData(EAS_CM_SYNTH_DATA); + else + pVoiceMgr = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_VOICE_MGR)); + if (!pVoiceMgr) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitialize: Failed to allocate synthesizer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pVoiceMgr, 0, sizeof(S_VOICE_MGR)); + + /* initialize non-zero variables */ + pVoiceMgr->pGlobalEAS = (S_EAS*) &easSoundLib; + pVoiceMgr->maxPolyphony = (EAS_U16) MAX_SYNTH_VOICES; + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + pVoiceMgr->maxPolyphonyPrimary = NUM_PRIMARY_VOICES; + pVoiceMgr->maxPolyphonySecondary = NUM_SECONDARY_VOICES; +#endif + + /* set max workload to zero */ + pVoiceMgr->maxWorkLoad = 0; + + /* initialize the voice manager parameters */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + InitVoice(&pVoiceMgr->voices[i]); + + /* initialize the synth */ + /*lint -e{522} return unused at this time */ + pPrimarySynth->pfInitialize(pVoiceMgr); + + /* initialize the off-chip synth */ +#ifdef _HYBRID_SYNTH + /*lint -e{522} return unused at this time */ + pSecondarySynth->pfInitialize(pVoiceMgr); +#endif + + pEASData->pVoiceMgr = pVoiceMgr; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMInitMIDI() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitMIDI (S_EAS_DATA *pEASData, S_SYNTH **ppSynth) +{ + EAS_RESULT result; + S_SYNTH *pSynth; + EAS_INT virtualSynthNum; + + *ppSynth = NULL; + + /* static memory model only allows one synth */ + if (pEASData->staticMemoryModel) + { + if (pEASData->pVoiceMgr->pSynth[0] != NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: No virtual synthesizer support for static memory model\n"); */ } + return EAS_ERROR_NO_VIRTUAL_SYNTHESIZER; + } + + /* check Configuration Module for data allocation */ + pSynth = EAS_CMEnumData(EAS_CM_MIDI_DATA); + virtualSynthNum = 0; + } + + /* dynamic memory model */ + else + { + for (virtualSynthNum = 0; virtualSynthNum < MAX_VIRTUAL_SYNTHESIZERS; virtualSynthNum++) + if (pEASData->pVoiceMgr->pSynth[virtualSynthNum] == NULL) + break; + if (virtualSynthNum == MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: Exceeded number of active virtual synthesizers"); */ } + return EAS_ERROR_NO_VIRTUAL_SYNTHESIZER; + } + pSynth = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SYNTH)); + } + + /* make sure we have a valid memory pointer */ + if (pSynth == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: Failed to allocate synthesizer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pSynth, 0, sizeof(S_SYNTH)); + + /* set the sound library pointer */ + if ((result = VMSetEASLib(pSynth, pEASData->pVoiceMgr->pGlobalEAS)) != EAS_SUCCESS) + { + VMMIDIShutdown(pEASData, pSynth); + return result; + } + + /* link in DLS bank if downloaded */ +#ifdef DLS_SYNTHESIZER + if (pEASData->pVoiceMgr->pGlobalDLS) + { + pSynth->pDLS = pEASData->pVoiceMgr->pGlobalDLS; + DLSAddRef(pSynth->pDLS); + } +#endif + + /* initialize MIDI state variables */ + pSynth->synthFlags = DEFAULT_SYNTH_FLAGS; + pSynth->masterVolume = DEFAULT_SYNTH_MASTER_VOLUME; + pSynth->refCount = 1; + pSynth->priority = DEFAULT_SYNTH_PRIORITY; + pSynth->poolAlloc[0] = (EAS_U8) pEASData->pVoiceMgr->maxPolyphony; + + VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); + + pSynth->vSynthNum = (EAS_U8) virtualSynthNum; + pEASData->pVoiceMgr->pSynth[virtualSynthNum] = pSynth; + + *ppSynth = pSynth; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMIncRefCount() + *---------------------------------------------------------------------------- + * Increment reference count for virtual synth + *---------------------------------------------------------------------------- +*/ +void VMIncRefCount (S_SYNTH *pSynth) +{ + pSynth->refCount++; +} + +/*---------------------------------------------------------------------------- + * VMReset() + *---------------------------------------------------------------------------- + * Purpose: + * We call this routine to start the process of reseting the synth. + * This routine sets a flag for the entire synth indicating that we want + * to reset. + * We also force all voices to mute quickly. + * However, we do not actually perform any synthesis in this routine. That + * is, we do not ramp the voices down from this routine, but instead, we + * let the "regular" synth processing steps take care of adding the ramp + * down samples to the output buffer. After we are sure that all voices + * have completed ramping down, we continue the process of resetting the + * synth (from another routine). + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * force - force reset even if voices are active + * + * Outputs: + * + * Side Effects: + * - set a flag (in psSynthObject->m_nFlags) indicating synth reset requested. + * - force all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMReset (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_BOOL force) +{ + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReset: request to reset synth. Force = %d\n", force); */ } +#endif + + /* force voices to off state - may cause audio artifacts */ + if (force) + { + pVoiceMgr->activeVoices -= pSynth->numActiveVoices; + pSynth->numActiveVoices = 0; + VMInitializeAllVoices(pVoiceMgr, pSynth->vSynthNum); + } + else + VMMuteAllVoices(pVoiceMgr, pSynth); + + /* don't reset if voices are still playing */ + if (pSynth->numActiveVoices == 0) + { + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReset: complete the reset process\n"); */ } +#endif + + VMInitializeAllChannels(pVoiceMgr, pSynth); + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + pSynth->poolCount[i] = 0; + + /* set polyphony */ + if (pSynth->maxPolyphony < pVoiceMgr->maxPolyphony) + pSynth->poolAlloc[0] = (EAS_U8) pVoiceMgr->maxPolyphony; + else + pSynth->poolAlloc[0] = (EAS_U8) pSynth->maxPolyphony; + + /* clear reset flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_RESET_IS_REQUESTED; + } + + /* handle reset after voices are muted */ + else + pSynth->synthFlags |= SYNTH_FLAG_RESET_IS_REQUESTED; +} + +/*---------------------------------------------------------------------------- + * VMInitializeAllChannels() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllChannels (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + + VMResetControllers(pSynth); + + /* init each channel */ + pChannel = pSynth->channels; + + for (i = 0; i < NUM_SYNTH_CHANNELS; i++, pChannel++) + { + pChannel->channelFlags = DEFAULT_CHANNEL_FLAGS; + pChannel->staticGain = DEFAULT_CHANNEL_STATIC_GAIN; + pChannel->staticPitch = DEFAULT_CHANNEL_STATIC_PITCH; + pChannel->pool = 0; + + /* the drum channel needs a different init */ + if (i == DEFAULT_DRUM_CHANNEL) + { + pChannel->bankNum = DEFAULT_RHYTHM_BANK_NUMBER; + pChannel->channelFlags |= CHANNEL_FLAG_RHYTHM_CHANNEL; + } + else + pChannel->bankNum = DEFAULT_MELODY_BANK_NUMBER; + + VMProgramChange(pVoiceMgr, pSynth, (EAS_U8) i, DEFAULT_SYNTH_PROGRAM_NUMBER); + } + +} + +/*---------------------------------------------------------------------------- + * VMResetControllers() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMResetControllers (S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + + pChannel = pSynth->channels; + + for (i = 0; i < NUM_SYNTH_CHANNELS; i++, pChannel++) + { + pChannel->pitchBend = DEFAULT_PITCH_BEND; + pChannel->modWheel = DEFAULT_MOD_WHEEL; + pChannel->volume = DEFAULT_CHANNEL_VOLUME; + pChannel->pan = DEFAULT_PAN; + pChannel->expression = DEFAULT_EXPRESSION; + +#ifdef _REVERB + pSynth->channels[i].reverbSend = DEFAULT_REVERB_SEND; +#endif + +#ifdef _CHORUS + pSynth->channels[i].chorusSend = DEFAULT_CHORUS_SEND; +#endif + + pChannel->channelPressure = DEFAULT_CHANNEL_PRESSURE; + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + pChannel->pitchBendSensitivity = DEFAULT_PITCH_BEND_SENSITIVITY; + pChannel->finePitch = DEFAULT_FINE_PITCH; + pChannel->coarsePitch = DEFAULT_COARSE_PITCH; + + /* update all voices on this channel */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + } +} + +/*---------------------------------------------------------------------------- + * VMInitializeAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllVoices (S_VOICE_MGR *pVoiceMgr, EAS_INT vSynthNum) +{ + EAS_INT i; + + /* initialize the voice manager parameters */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + if (pVoiceMgr->voices[i].voiceState != eVoiceStateStolen) + { + if (GET_VSYNTH(pVoiceMgr->voices[i].channel) == vSynthNum) + InitVoice(&pVoiceMgr->voices[i]); + } + else + { + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == vSynthNum) + InitVoice(&pVoiceMgr->voices[i]); + } + } +} + +/*---------------------------------------------------------------------------- + * VMMuteVoice() + *---------------------------------------------------------------------------- + * Mute the selected voice + *---------------------------------------------------------------------------- +*/ +void VMMuteVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum) +{ + S_SYNTH *pSynth; + S_SYNTH_VOICE *pVoice; + + /* take no action if voice is already muted */ + pVoice = &pVoiceMgr->voices[voiceNum]; + if ((pVoice->voiceState == eVoiceStateMuting) || (pVoice->voiceState == eVoiceStateFree)) + return; + + /* one less voice in pool */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pSynth, pVoice, GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateMuting; + +} + +/*---------------------------------------------------------------------------- + * VMReleaseVoice() + *---------------------------------------------------------------------------- + * Release the selected voice + *---------------------------------------------------------------------------- +*/ +void VMReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 voiceNum) +{ + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + + /* take no action if voice is already free, muting, or releasing */ + if (( pVoice->voiceState == eVoiceStateMuting) || + (pVoice->voiceState == eVoiceStateFree) || + (pVoice->voiceState == eVoiceStateRelease)) + return; + + /* stolen voices should just be muted */ + if (pVoice->voiceState == eVoiceStateStolen) + VMMuteVoice(pVoiceMgr, voiceNum); + + /* release this voice */ + GetSynthPtr(voiceNum)->pfReleaseVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateRelease; +} + +/*---------------------------------------------------------------------------- + * VMInitMIPTable() + *---------------------------------------------------------------------------- + * Initialize the SP-MIDI MIP table in preparation for receiving MIP message + *---------------------------------------------------------------------------- +*/ +void VMInitMIPTable (S_SYNTH *pSynth) +{ + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMInitMIPTable\n"); */ } +#endif + + /* clear SP-MIDI flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_SP_MIDI_ON; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + pSynth->channels[i].pool = 0; + pSynth->channels[i].mip = 0; + } +} + +/*---------------------------------------------------------------------------- + * VMSetMIPEntry() + *---------------------------------------------------------------------------- + * Sets the priority and MIP level for a MIDI channel + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMSetMIPEntry (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 priority, EAS_U8 mip) +{ + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMSetMIPEntry: channel=%d, priority=%d, MIP=%d\n", channel, priority, mip); */ } +#endif + + /* save data for use by MIP message processing */ + if (priority < NUM_SYNTH_CHANNELS) + { + pSynth->channels[channel].pool = priority; + pSynth->channels[channel].mip = mip; + } +} + +/*---------------------------------------------------------------------------- + * VMMIPUpdateChannelMuting() + *---------------------------------------------------------------------------- + * This routine is called after an SP-MIDI message is received and + * any time the allocated polyphony changes. It mutes or unmutes + * channels based on polyphony. + *---------------------------------------------------------------------------- +*/ +void VMMIPUpdateChannelMuting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + EAS_INT maxPolyphony; + EAS_INT channel; + EAS_INT vSynthNum; + EAS_INT pool; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateMIPTable\n"); */ } +#endif + + /* determine max polyphony */ + if (pSynth->maxPolyphony) + maxPolyphony = pSynth->maxPolyphony; + else + maxPolyphony = pVoiceMgr->maxPolyphony; + + /* process channels */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + + /* channel must be in MIP message and must meet allocation target */ + if ((pSynth->channels[i].mip != 0) && (pSynth->channels[i].mip <= maxPolyphony)) + pSynth->channels[i].channelFlags &= ~CHANNEL_FLAG_MUTE; + else + pSynth->channels[i].channelFlags |= CHANNEL_FLAG_MUTE; + + /* reset voice pool count */ + pSynth->poolCount[i] = 0; + } + + /* mute any voices on muted channels, and count unmuted voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + /* ignore free voices */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateFree) + continue; + + /* get channel and virtual synth */ + if (pVoiceMgr->voices[i].voiceState != eVoiceStateStolen) + { + vSynthNum = GET_VSYNTH(pVoiceMgr->voices[i].channel); + channel = GET_CHANNEL(pVoiceMgr->voices[i].channel); + } + else + { + vSynthNum = GET_VSYNTH(pVoiceMgr->voices[i].nextChannel); + channel = GET_CHANNEL(pVoiceMgr->voices[i].nextChannel); + } + + /* ignore voices on other synths */ + if (vSynthNum != pSynth->vSynthNum) + continue; + + /* count voices */ + pool = pSynth->channels[channel].pool; + + /* deal with muted channels */ + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_MUTE) + { + /* mute stolen voices scheduled to play on this channel */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateStolen) + pVoiceMgr->voices[i].voiceState = eVoiceStateMuting; + + /* release voices that aren't already muting */ + else if (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting) + { + VMReleaseVoice(pVoiceMgr, pSynth, i); + pSynth->poolCount[pool]++; + } + } + + /* not muted, count this voice */ + else + pSynth->poolCount[pool]++; + } +} + +/*---------------------------------------------------------------------------- + * VMUpdateMIPTable() + *---------------------------------------------------------------------------- + * This routine is called at the end of the SysEx message to allow + * the Voice Manager to complete the initialization of the MIP + * table. It assigns channels to the appropriate voice pool based + * on the MIP setting and calculates the voices allocated for each + * pool. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMUpdateMIPTable (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + EAS_INT currentMIP; + EAS_INT currentPool; + EAS_INT priority[NUM_SYNTH_CHANNELS]; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateMIPTable\n"); */ } +#endif + + /* set SP-MIDI flag */ + pSynth->synthFlags |= SYNTH_FLAG_SP_MIDI_ON; + + /* sort channels into priority order */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + priority[i] = -1; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + if (pSynth->channels[i].pool != DEFAULT_SP_MIDI_PRIORITY) + priority[pSynth->channels[i].pool] = i; + } + + /* process channels in priority order */ + currentMIP = 0; + currentPool = -1; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + /* stop when we run out of channels */ + if (priority[i] == -1) + break; + + pChannel = &pSynth->channels[priority[i]]; + + /* when 2 or more channels have the same MIP setting, they + * share a common voice pool + */ + if (pChannel->mip == currentMIP) + pChannel->pool = (EAS_U8) currentPool; + + /* new voice pool */ + else + { + currentPool++; + pSynth->poolAlloc[currentPool] = (EAS_U8) (pChannel->mip - currentMIP); + currentMIP = pChannel->mip; + } + } + + /* set SP-MIDI flag */ + pSynth->synthFlags |= SYNTH_FLAG_SP_MIDI_ON; + + /* update channel muting */ + VMMIPUpdateChannelMuting (pVoiceMgr, pSynth); +} + +/*---------------------------------------------------------------------------- + * VMMuteAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this in an emergency reset situation. + * This forces all voices to mute quickly. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMMuteAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMMuteAllVoices: about to mute all voices!!\n"); */ } +#endif + + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + /* for stolen voices, check new channel */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateStolen) + { + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == pSynth->vSynthNum) + VMMuteVoice(pVoiceMgr, i); + } + + else if (pSynth->vSynthNum == GET_VSYNTH(pVoiceMgr->voices[i].channel)) + VMMuteVoice(pVoiceMgr, i); + } +} + +/*---------------------------------------------------------------------------- + * VMReleaseAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this after we've encountered the end of the Midi file. + * This ensures all voices are either in release (because we received their + * note off already) or forces them to mute quickly. + * We use this as a safety to prevent bad midi files from playing forever. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to release or mute + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + + /* release sustain pedal on all channels */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + if (pSynth->channels[ i ].channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + VMReleaseAllDeferredNoteOffs(pVoiceMgr, pSynth, (EAS_U8) i); + pSynth->channels[i].channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + } + } + + /* release all voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + switch (pVoiceMgr->voices[i].voiceState) + { + case eVoiceStateStart: + case eVoiceStatePlay: + /* only release voices on this synth */ + if (GET_VSYNTH(pVoiceMgr->voices[i].channel) == pSynth->vSynthNum) + VMReleaseVoice(pVoiceMgr, pSynth, i); + break; + + case eVoiceStateStolen: + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == pSynth->vSynthNum) + VMMuteVoice(pVoiceMgr, i); + break; + + case eVoiceStateFree: + case eVoiceStateRelease: + case eVoiceStateMuting: + break; + + case eVoiceStateInvalid: + default: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReleaseAllVoices: error, %d is an unrecognized state\n", + pVoiceMgr->voices[i].voiceState); */ } +#endif + break; + } + } +} + +/*---------------------------------------------------------------------------- + * VMAllNotesOff() + *---------------------------------------------------------------------------- + * Purpose: + * Quickly mute all notes on the given channel. + * + * Inputs: + * nChannel - quickly turn off all notes on this channel + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices on this channel to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMAllNotesOff (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + EAS_INT voiceNum; + S_SYNTH_VOICE *pVoice; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMAllNotesOff: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif + + /* increment workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + + /* check each voice */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + pVoice = &pVoiceMgr->voices[voiceNum]; + if (pVoice->voiceState != eVoiceStateFree) + { + if (((pVoice->voiceState != eVoiceStateStolen) && (channel == pVoice->channel)) || + ((pVoice->voiceState == eVoiceStateStolen) && (channel == pVoice->nextChannel))) + { + /* this voice is assigned to the requested channel */ + GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pSynth, pVoice, GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateMuting; + } + } + } +} + +/*---------------------------------------------------------------------------- + * VMDeferredStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Stop the notes that had deferred note-off requests. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None. + * + * Side Effects: + * voices that have had deferred note-off requests are now put into release + * psSynthObject->m_sVoice[i].m_nFlags has the VOICE_FLAG_DEFER_MIDI_NOTE_OFF + * cleared + *---------------------------------------------------------------------------- +*/ +void VMDeferredStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT voiceNum; + EAS_INT channel; + EAS_BOOL deferredNoteOff; + + deferredNoteOff = EAS_FALSE; + + /* check each voice to see if it requires a deferred note off */ + for (voiceNum=0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_DEFER_MIDI_NOTE_OFF) + { + /* check if this voice was stolen */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) + { + /* + This voice was stolen, AND it also has a deferred note-off. + The stolen note must be completely ramped down at this point. + The note that caused the stealing to occur, however, must + have received a note-off request before the note that caused + stealing ever had a chance to even start. We want to give + the note that caused the stealing a chance to play, so we + start it on the next update interval, and we defer sending + the note-off request until the subsequent update interval. + So do not send the note-off request for this voice because + this voice was stolen and should have completed ramping down, + Also, do not clear the global flag nor this voice's flag + because we must indicate that the subsequent update interval, + after the note that caused stealing has started, should + then send the deferred note-off request. + */ + deferredNoteOff = EAS_TRUE; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: defer request to stop voice %d (channel=%d note=%d) - voice not started\n", + voiceNum, + pVoiceMgr->voices[voiceNum].nextChannel, + pVoiceMgr->voices[voiceNum].note); */ } + + /* sanity check: this stolen voice better be ramped to zero */ + if (0 != pVoiceMgr->voices[voiceNum].gain) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: warning, this voice did not complete its ramp to zero\n"); */ } + } +#endif // #ifdef _DEBUG_VM + + } + else + { + /* clear the flag using exor */ + pVoiceMgr->voices[voiceNum].voiceFlags ^= + VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: Stop voice %d (channel=%d note=%d)\n", + voiceNum, + pVoiceMgr->voices[voiceNum].nextChannel, + pVoiceMgr->voices[voiceNum].note); */ } +#endif + + channel = pVoiceMgr->voices[voiceNum].channel & 15; + + /* check if sustain pedal is on */ + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + GetSynthPtr(voiceNum)->pfSustainPedal(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], &pSynth->channels[channel], GetAdjustedVoiceNum(voiceNum)); + } + + /* release this voice */ + else + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + } + + } + + } + + /* clear the deferred note-off flag, unless there's another one pending */ + if (deferredNoteOff == EAS_FALSE) + pSynth->synthFlags ^= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; +} + +/*---------------------------------------------------------------------------- + * VMReleaseAllDeferredNoteOffs() + *---------------------------------------------------------------------------- + * Purpose: + * Call this functin when the sustain flag is presently set but + * we are now transitioning from damper pedal on to + * damper pedal off. This means all notes in this channel + * that received a note off while the damper pedal was on, and + * had their note-off requests deferred, should now proceed to + * the release state. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * pVoice->m_sEG1.m_eState = eEnvelopeStateRelease + * pVoice->m_sEG1.m_nIncrement = release increment + * pVoice->m_nFlags = clear the deferred note off flag + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllDeferredNoteOffs (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + S_SYNTH_VOICE *pVoice; + EAS_INT voiceNum; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReleaseAllDeferredNoteOffs: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif /* #ifdef _DEBUG_VM */ + + /* increment workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + + /* find all the voices assigned to this channel */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + pVoice = &pVoiceMgr->voices[voiceNum]; + if (channel == pVoice->channel) + { + + /* does this voice have a deferred note off? */ + if (pVoice->voiceFlags & VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF) + { + /* release voice */ + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + /* use exor to flip bit, clear the flag */ + pVoice->voiceFlags &= ~VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + + } + + } + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMCatchNotesForSustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when the sustain flag is presently clear and + * the damper pedal is off and we are transitioning from damper pedal OFF to + * damper pedal ON. Currently sounding notes should be left + * unchanged. However, we should try to "catch" notes if possible. + * If any notes are in release and have levels >= sustain level, catch them, + * otherwise, let them continue to release. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +void VMCatchNotesForSustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + EAS_INT voiceNum; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCatchNotesForSustainPedal: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif + + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + channel = VSynthToChannel(pSynth, channel); + + /* find all the voices assigned to this channel */ + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (channel == pVoiceMgr->voices[voiceNum].channel) + { + if (eVoiceStateRelease == pVoiceMgr->voices[voiceNum].voiceState) + GetSynthPtr(voiceNum)->pfSustainPedal(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], &pSynth->channels[channel], GetAdjustedVoiceNum(voiceNum)); + } + } +} + +/*---------------------------------------------------------------------------- + * VMUpdateAllNotesAge() + *---------------------------------------------------------------------------- + * Purpose: + * Increment the note age for all of the active voices. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * m_nAge for all voices is incremented + *---------------------------------------------------------------------------- +*/ +void VMUpdateAllNotesAge (S_VOICE_MGR *pVoiceMgr, EAS_U16 age) +{ + EAS_INT i; + + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + if (age - pVoiceMgr->voices[i].age > 0) + pVoiceMgr->voices[i].age++; + } +} + +/*---------------------------------------------------------------------------- + * VMStolenVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being stolen. Sets the parameters so that the + * voice will begin playing the new sound on the next buffer. + * + * Inputs: + * pVoice - pointer to voice to steal + * nChannel - the channel to start a note on + * nKeyNumber - the key number to start a note for + * nNoteVelocity - the key velocity from this note + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static void VMStolenVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 voiceNum, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex) +{ + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + + /* one less voice in old pool */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + /* mute the sound that is currently playing */ + GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)], &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateStolen; + + /* set new note data */ + pVoice->nextChannel = VSynthToChannel(pSynth, channel); + pVoice->nextNote = note; + pVoice->nextVelocity = velocity; + pVoice->nextRegionIndex = regionIndex; + + /* one more voice in new pool */ + IncVoicePoolCount(pVoiceMgr, pVoice); + + /* clear the deferred flags */ + pVoice->voiceFlags &= + ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | + VOICE_FLAG_DEFER_MUTE | + VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF); + + /* all notes older than this one get "younger" */ + VMUpdateAllNotesAge(pVoiceMgr, pVoice->age); + + /* assign current age to this note and increment for the next note */ + pVoice->age = pVoiceMgr->age++; +} + +/*---------------------------------------------------------------------------- + * VMFreeVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is done playing and being returned to the + * pool of free voices + * + * Inputs: + * pVoice - pointer to voice to free + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static void VMFreeVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice) +{ + + /* do nothing if voice is already free */ + if (pVoice->voiceState == eVoiceStateFree) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMFreeVoice: Attempt to free voice that is already free\n"); */ } + return; + } + + /* if we jump directly to free without passing muting stage, + * we need to adjust the voice count */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMFreeVoice: Synth=%d\n", pSynth->vSynthNum); */ } +#endif + + /* return to free voice pool */ + pVoiceMgr->activeVoices--; + pSynth->numActiveVoices--; + InitVoice(pVoice); + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMFreeVoice: free voice %d\n", pVoice - pVoiceMgr->voices); */ } +#endif + + /* all notes older than this one get "younger" */ + VMUpdateAllNotesAge(pVoiceMgr, pVoice->age); + } + +/*---------------------------------------------------------------------------- + * VMRetargetStolenVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice has been stolen and needs to be initalized with + * the paramters of its new note. + * + * Inputs: + * pVoice - pointer to voice to retarget + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL VMRetargetStolenVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum) +{ + EAS_U8 flags; + S_SYNTH_CHANNEL *pMIDIChannel; + S_SYNTH_VOICE *pVoice; + S_SYNTH *pSynth; + S_SYNTH *pNextSynth; + + /* establish some pointers */ + pVoice = &pVoiceMgr->voices[voiceNum]; + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pMIDIChannel = &pSynth->channels[pVoice->channel & 15]; + pNextSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + +#ifdef _DEBUG_VM +{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetStolenVoice: retargeting stolen voice %d on channel %d\n", + voiceNum, pVoice->channel); */ } + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\to channel %d note: %d velocity: %d\n", + pVoice->nextChannel, pVoice->nextNote, pVoice->nextVelocity); */ } +#endif + + /* make sure new channel hasn't been muted by SP-MIDI since the voice was stolen */ + if ((pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) && + (pMIDIChannel->channelFlags & CHANNEL_FLAG_MUTE)) + { + VMFreeVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum]); + return EAS_FALSE; + } + + /* if assigned to a new synth, correct the active voice count */ + if (pVoice->channel != pVoice->nextChannel) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetStolenVoice: Note assigned to different virtual synth, adjusting numActiveVoices\n"); */ } +#endif + pSynth->numActiveVoices--; + pNextSynth->numActiveVoices++; + } + + /* assign new channel number, and increase channel voice count */ + pVoice->channel = pVoice->nextChannel; + pMIDIChannel = &pNextSynth->channels[pVoice->channel & 15]; + + /* assign other data */ + pVoice->note = pVoice->nextNote; + pVoice->velocity = pVoice->nextVelocity; + pVoice->nextChannel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->regionIndex = pVoice->nextRegionIndex; + + /* save the flags, pfStartVoice() will clear them */ + flags = pVoice->voiceFlags; + + /* keep track of the note-start related workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_START_NOTE; + + /* setup the voice parameters */ + pVoice->voiceState = eVoiceStateStart; + + /*lint -e{522} return not used at this time */ + GetSynthPtr(voiceNum)->pfStartVoice(pVoiceMgr, pNextSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), pVoice->regionIndex); + + /* did the new note already receive a MIDI note-off request? */ + if (flags & VOICE_FLAG_DEFER_MIDI_NOTE_OFF) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetVoice: stolen note note-off request deferred\n"); */ } +#endif + pVoice->voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + pNextSynth->synthFlags |= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; + } + + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * VMCheckKeyGroup() + *---------------------------------------------------------------------------- + * If the note that we've been asked to start is in the same key group as + * any currently playing notes, then we must shut down the currently playing + * note in the same key group + *---------------------------------------------------------------------------- +*/ +void VMCheckKeyGroup (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U16 keyGroup, EAS_U8 channel) +{ + const S_REGION *pRegion; + EAS_INT voiceNum; + + /* increment frame workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_KEY_GROUP; + + /* need to check all voices in case this is a layered sound */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateStolen) + { + /* voice must be on the same channel */ + if (channel == pVoiceMgr->voices[voiceNum].channel) + { + /* check key group */ + pRegion = GetRegionPtr(pSynth, pVoiceMgr->voices[voiceNum].regionIndex); + if (keyGroup == (pRegion->keyGroupAndFlags & 0x0f00)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckKeyGroup: voice %d matches key group %d\n", voiceNum, keyGroup >> 8); */ } +#endif + + /* if this voice was just started, set it to mute on the next buffer */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MUTE; + + /* mute immediately */ + else + VMMuteVoice(pVoiceMgr, voiceNum); + } + } + } + + /* for stolen voice, check new values */ + else + { + /* voice must be on the same channel */ + if (channel == pVoiceMgr->voices[voiceNum].nextChannel) + { + /* check key group */ + pRegion = GetRegionPtr(pSynth, pVoiceMgr->voices[voiceNum].nextRegionIndex); + if (keyGroup == (pRegion->keyGroupAndFlags & 0x0f00)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckKeyGroup: voice %d matches key group %d\n", voiceNum, keyGroup >> 8); */ } +#endif + + /* if this voice was just started, set it to mute on the next buffer */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MUTE; + + /* mute immediately */ + else + VMMuteVoice(pVoiceMgr, voiceNum); + } + } + + } + } +} + +/*---------------------------------------------------------------------------- + * VMCheckPolyphonyLimiting() + *---------------------------------------------------------------------------- + * Purpose: + * We only play at most 2 of the same note on a MIDI channel. + * E.g., if we are asked to start note 36, and there are already two voices + * that are playing note 36, then we must steal the voice playing + * the oldest note 36 and use that stolen voice to play the new note 36. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * * + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber may be assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckPolyphonyLimiting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + EAS_INT voiceNum; + EAS_INT oldestVoiceNum; + EAS_INT numVoicesPlayingNote; + EAS_U16 age; + EAS_U16 oldestNoteAge; + + pVoiceMgr->workload += WORKLOAD_AMOUNT_POLY_LIMIT; + + numVoicesPlayingNote = 0; + oldestVoiceNum = MAX_SYNTH_VOICES; + oldestNoteAge = 0; + channel = VSynthToChannel(pSynth, channel); + + /* examine each voice on this channel playing this note */ + for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) + { + /* check stolen notes separately */ + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateStolen) + { + + /* same channel and note ? */ + if ((channel == pVoiceMgr->voices[voiceNum].channel) && (note == pVoiceMgr->voices[voiceNum].note)) + { + numVoicesPlayingNote++; + age = pVoiceMgr->age - pVoiceMgr->voices[voiceNum].age; + + /* is this the oldest voice for this note? */ + if (age >= oldestNoteAge) + { + oldestNoteAge = age; + oldestVoiceNum = voiceNum; + } + } + } + + /* handle stolen voices */ + else + { + /* same channel and note ? */ + if ((channel == pVoiceMgr->voices[voiceNum].nextChannel) && (note == pVoiceMgr->voices[voiceNum].nextNote)) + { + numVoicesPlayingNote++; + } + } + } + + /* check to see if we exceeded poly limit */ + if (numVoicesPlayingNote < DEFAULT_CHANNEL_POLYPHONY_LIMIT) + return EAS_FALSE; + + /* make sure we have a voice to steal */ + if (oldestVoiceNum != MAX_SYNTH_VOICES) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckPolyphonyLimiting: voice %d has the oldest note\n", oldestVoiceNum); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMCheckPolyphonyLimiting: polyphony limiting requires shutting down note %d \n", pVoiceMgr->voices[oldestVoiceNum].note); */ } +#endif + VMStolenVoice(pVoiceMgr, pSynth, oldestVoiceNum, channel, note, velocity, regionIndex); + return EAS_TRUE; + } + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMCheckPolyphonyLimiting: No oldest voice to steal\n"); */ } +#endif + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * VMStartVoice() + *---------------------------------------------------------------------------- + * Starts a voice given a region index + *---------------------------------------------------------------------------- +*/ +void VMStartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex) +{ + const S_REGION *pRegion; + S_SYNTH_CHANNEL *pChannel; + EAS_INT voiceNum; + EAS_INT maxSynthPoly; + EAS_I32 lowVoice, highVoice; + EAS_U16 keyGroup; + + pChannel = &pSynth->channels[channel]; + pRegion = GetRegionPtr(pSynth, regionIndex); + + /* select correct synth */ +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + { +#ifdef EAS_SPLIT_WT_SYNTH + if ((pRegion->keyGroupAndFlags & REGION_FLAG_OFF_CHIP) == 0) +#else + if ((regionIndex & FLAG_RGN_IDX_FM_SYNTH) == 0) +#endif + { + lowVoice = 0; + highVoice = NUM_PRIMARY_VOICES - 1; + } + else + { + lowVoice = NUM_PRIMARY_VOICES; + highVoice = MAX_SYNTH_VOICES - 1; + } + } +#else + lowVoice = 0; + highVoice = MAX_SYNTH_VOICES - 1; +#endif + + /* keep track of the note-start related workload */ + pVoiceMgr->workload+= WORKLOAD_AMOUNT_START_NOTE; + + /* other voices in pool, check for key group and poly limiting */ + if (pSynth->poolCount[pChannel->pool] != 0) + { + + /* check for key group exclusivity */ + keyGroup = pRegion->keyGroupAndFlags & 0x0f00; + if (keyGroup!= 0) + VMCheckKeyGroup(pVoiceMgr, pSynth, keyGroup, channel); + + /* check polyphony limit and steal a voice if necessary */ + if ((pRegion->keyGroupAndFlags & REGION_FLAG_NON_SELF_EXCLUSIVE) == 0) + { + if (VMCheckPolyphonyLimiting(pVoiceMgr, pSynth, channel, note, velocity, regionIndex, lowVoice, highVoice) == EAS_TRUE) + return; + } + } + + /* check max poly allocation */ + if ((pSynth->maxPolyphony == 0) || (pVoiceMgr->maxPolyphony < pSynth->maxPolyphony)) + maxSynthPoly = pVoiceMgr->maxPolyphony; + else + maxSynthPoly = pSynth->maxPolyphony; + + /* any free voices? */ + if ((pVoiceMgr->activeVoices < pVoiceMgr->maxPolyphony) && + (pSynth->numActiveVoices < maxSynthPoly) && + (EAS_SUCCESS == VMFindAvailableVoice(pVoiceMgr, &voiceNum, lowVoice, highVoice))) + { + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMStartVoice: Synth=%d\n", pSynth->vSynthNum); */ } +#endif + + /* bump voice counts */ + pVoiceMgr->activeVoices++; + pSynth->numActiveVoices++; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStartVoice: voice %d assigned to channel %d note %d velocity %d\n", + voiceNum, channel, note, velocity); */ } +#endif + + /* save parameters */ + pVoiceMgr->voices[voiceNum].channel = VSynthToChannel(pSynth, channel); + pVoiceMgr->voices[voiceNum].note = note; + pVoiceMgr->voices[voiceNum].velocity = velocity; + + /* establish note age for voice stealing */ + pVoiceMgr->voices[voiceNum].age = pVoiceMgr->age++; + + /* setup the synthesis parameters */ + pVoiceMgr->voices[voiceNum].voiceState = eVoiceStateStart; + + /* increment voice pool count */ + IncVoicePoolCount(pVoiceMgr, pVoice); + + /* start voice on correct synth */ + /*lint -e{522} return not used at this time */ + GetSynthPtr(voiceNum)->pfStartVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), regionIndex); + return; + } + + /* no free voices, we have to steal one using appropriate algorithm */ + if (VMStealVoice(pVoiceMgr, pSynth, &voiceNum, channel, note, lowVoice, highVoice) == EAS_SUCCESS) + VMStolenVoice(pVoiceMgr, pSynth, voiceNum, channel, note, velocity, regionIndex); + +#ifdef _DEBUG_VM + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStartVoice: Could not steal a voice for channel %d note %d velocity %d\n", + channel, note, velocity); */ } + } +#endif + + return; +} + +/*---------------------------------------------------------------------------- + * VMStartNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to play the requested note on the requested + * channel if possible. + * + * Inputs: + * nChannel - the channel to start a note on + * nKeyNumber - the key number to start a note for + * nNoteVelocity - the key velocity from this note + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_nNumActiveVoices may be incremented + * psSynthObject->m_sVoice[free voice num].m_nSynthChannel may be assigned + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber is assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +void VMStartNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_U16 regionIndex; + EAS_I16 adjustedNote; + + /* bump note count */ + pSynth->totalNoteCount++; + + pChannel = &pSynth->channels[channel]; + + /* check channel mute */ + if (pChannel->channelFlags & CHANNEL_FLAG_MUTE) + return; + +#ifdef EXTERNAL_AUDIO + /* pass event to external audio when requested */ + if ((pChannel->channelFlags & CHANNEL_FLAG_EXTERNAL_AUDIO) && (pSynth->cbEventFunc != NULL)) + { + S_EXT_AUDIO_EVENT event; + event.channel = channel; + event.note = note; + event.velocity = velocity; + event.noteOn = EAS_TRUE; + if (pSynth->cbEventFunc(pSynth->pExtAudioInstData, &event)) + return; + } +#endif + + /* start search at first region */ + regionIndex = pChannel->regionIndex; + + /* handle transposition */ + adjustedNote = note; + if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) + adjustedNote += pChannel->coarsePitch; + else + adjustedNote += pChannel->coarsePitch + pSynth->globalTranspose; + + /* limit adjusted key number so it does not wraparound, over/underflow */ + if (adjustedNote < 0) + { + adjustedNote = 0; + } + else if (adjustedNote > 127) + { + adjustedNote = 127; + } + +#if defined(DLS_SYNTHESIZER) + if (regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + /* DLS voice */ + for (;;) + { + /*lint -e{740,826} cast OK, we know this is actually a DLS region */ + const S_DLS_REGION *pDLSRegion = (S_DLS_REGION*) GetRegionPtr(pSynth, regionIndex); + + /* check key against this region's key and velocity range */ + if (((adjustedNote >= pDLSRegion->wtRegion.region.rangeLow) && (adjustedNote <= pDLSRegion->wtRegion.region.rangeHigh)) && + ((velocity >= pDLSRegion->velLow) && (velocity <= pDLSRegion->velHigh))) + { + VMStartVoice(pVoiceMgr, pSynth, channel, note, velocity, regionIndex); + } + + /* last region in program? */ + if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_LAST_REGION) + break; + + /* advance to next region */ + regionIndex++; + } + } + else +#endif + + /* braces here for #if clause */ + { + /* EAS voice */ + for (;;) + { + const S_REGION *pRegion = GetRegionPtr(pSynth, regionIndex); + + /* check key against this region's keyrange */ + if ((adjustedNote >= pRegion->rangeLow) && (adjustedNote <= pRegion->rangeHigh)) + { + VMStartVoice(pVoiceMgr, pSynth, channel, note, velocity, regionIndex); + break; + } + + /* last region in program? */ + if (pRegion->keyGroupAndFlags & REGION_FLAG_LAST_REGION) + break; + + /* advance to next region */ + regionIndex++; + } + } +} + +/*---------------------------------------------------------------------------- + * VMStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to end the requested note on the requested + * channel. + * + * Inputs: + * nChannel - the channel to stop a note on + * nKeyNumber - the key number for this note off + * nNoteVelocity - the note-off velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nSynthChannel may be assigned + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber is assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, velocity) reserved for future use */ +void VMStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT voiceNum; + + pChannel = &(pSynth->channels[channel]); + +#ifdef EXTERNAL_AUDIO + if ((pChannel->channelFlags & CHANNEL_FLAG_EXTERNAL_AUDIO) && (pSynth->cbEventFunc != NULL)) + { + S_EXT_AUDIO_EVENT event; + event.channel = channel; + event.note = note; + event.velocity = velocity; + event.noteOn = EAS_FALSE; + if (pSynth->cbEventFunc(pSynth->pExtAudioInstData, &event)) + return; + } +#endif + + /* keep track of the note-start workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_STOP_NOTE; + + channel = VSynthToChannel(pSynth, channel); + + for (voiceNum=0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + /* stolen notes are handled separately */ + if (eVoiceStateStolen != pVoiceMgr->voices[voiceNum].voiceState) + { + + /* channel and key number must match */ + if ((channel == pVoiceMgr->voices[voiceNum].channel) && (note == pVoiceMgr->voices[voiceNum].note)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStopNote: voice %d channel %d note %d\n", + voiceNum, channel, note); */ } +#endif + + /* if sustain pedal is down, set deferred note-off flag */ + if (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + continue; + } + + /* if this note just started, wait before we stop it */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tDeferred: Not started yet\n"); */ } +#endif + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + pSynth->synthFlags |= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; + } + + /* release voice */ + else + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + } + } + + /* process stolen notes, new channel and key number must match */ + else if ((channel == pVoiceMgr->voices[voiceNum].nextChannel) && (note == pVoiceMgr->voices[voiceNum].nextNote)) + { + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStopNote: voice %d channel %d note %d\n\tDeferred: Stolen voice\n", + voiceNum, channel, note); */ } +#endif + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + } + } +} + +/*---------------------------------------------------------------------------- + * VMFindAvailableVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Find an available voice and return the voice number if available. + * + * Inputs: + * pnVoiceNumber - really an output, returns the voice number found + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * success - if there is an available voice + * failure - otherwise + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindAvailableVoice (S_VOICE_MGR *pVoiceMgr, EAS_INT *pVoiceNumber, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + EAS_INT voiceNum; + + /* Check each voice to see if it has been assigned to a synth channel */ + for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) + { + /* check if this voice has been assigned to a synth channel */ + if ( pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateFree) + { + *pVoiceNumber = voiceNum; /* this voice is available */ + return EAS_SUCCESS; + } + } + + /* if we reach here, we have not found a free voice */ + *pVoiceNumber = UNASSIGNED_SYNTH_VOICE; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMFindAvailableVoice: error, could not find an available voice\n"); */ } +#endif + return EAS_FAILURE; +} + +/*---------------------------------------------------------------------------- + * VMStealVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Steal a voice and return the voice number + * + * Stealing algorithm: steal the best choice with minimal work, taking into + * account SP-Midi channel priorities and polyphony allocation. + * + * In one pass through all the voices, figure out which voice to steal + * taking into account a number of different factors: + * Priority of the voice's MIDI channel + * Number of voices over the polyphony allocation for voice's MIDI channel + * Amplitude of the voice + * Note age + * Key velocity (for voices that haven't been started yet) + * If any matching notes are found + * + * Inputs: + * pnVoiceNumber - really an output, see below + * nChannel - the channel that this voice wants to be started on + * nKeyNumber - the key number for this new voice + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - voice number of the voice that was stolen + * EAS_RESULT EAS_SUCCESS - always successful + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMStealVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_INT *pVoiceNumber, EAS_U8 channel, EAS_U8 note, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + S_SYNTH_VOICE *pCurrVoice; + S_SYNTH *pCurrSynth; + EAS_INT voiceNum; + EAS_INT bestCandidate; + EAS_U8 currChannel; + EAS_U8 currNote; + EAS_I32 bestPriority; + EAS_I32 currentPriority; + + /* determine which voice to steal */ + bestPriority = 0; + bestCandidate = MAX_SYNTH_VOICES; + + for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) + { + pCurrVoice = &pVoiceMgr->voices[voiceNum]; + + /* ignore free voices */ + if (pCurrVoice->voiceState == eVoiceStateFree) + continue; + + /* for stolen voices, use the new parameters, not the old */ + if (pCurrVoice->voiceState == eVoiceStateStolen) + { + pCurrSynth = pVoiceMgr->pSynth[GET_VSYNTH(pCurrVoice->nextChannel)]; + currChannel = pCurrVoice->nextChannel; + currNote = pCurrVoice->nextNote; + } + else + { + pCurrSynth = pVoiceMgr->pSynth[GET_VSYNTH(pCurrVoice->channel)]; + currChannel = pCurrVoice->channel; + currNote = pCurrVoice->note; + } + + /* ignore voices that are higher priority */ + if (pSynth->priority > pCurrSynth->priority) + continue; +#ifdef _DEBUG_VM +// { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: New priority = %d exceeds old priority = %d\n", pSynth->priority, pCurrSynth->priority); */ } +#endif + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pCurrVoice->voiceState == eVoiceStateStolen) || (pCurrVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + currentPriority = 128 - pCurrVoice->nextVelocity; + } + else + { + /* compute the priority of this voice, higher means better for stealing */ + /* use not age */ + currentPriority = (EAS_I32) pCurrVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pCurrVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + } + + /* in SP-MIDI mode, include over poly allocation and channel priority */ + if (pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + { + S_SYNTH_CHANNEL *pChannel = &pCurrSynth->channels[GET_CHANNEL(currChannel)]; + /*lint -e{701} use shift for performance */ + if (pSynth->poolCount[pChannel->pool] >= pSynth->poolAlloc[pChannel->pool]) + currentPriority += (pSynth->poolCount[pChannel->pool] -pSynth->poolAlloc[pChannel->pool] + 1) << CHANNEL_POLY_STEAL_WEIGHT; + + /* include channel priority */ + currentPriority += (EAS_I32)(pChannel->pool << CHANNEL_PRIORITY_STEAL_WEIGHT); + } + + /* if a note is already playing that matches this note, consider stealing it more readily */ + if ((note == currNote) && (channel == currChannel)) + currentPriority += NOTE_MATCH_PENALTY; + + /* is this the best choice so far? */ + if (currentPriority >= bestPriority) + { + bestPriority = currentPriority; + bestCandidate = voiceNum; + } + } + + /* may happen if all voices are allocated to a higher priority virtual synth */ + if (bestCandidate == MAX_SYNTH_VOICES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: Unable to allocate a voice\n"); */ } + return EAS_ERROR_NO_VOICE_ALLOCATED; + } + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: Voice %d stolen\n", bestCandidate); */ } + + /* are we stealing a stolen voice? */ + if (pVoiceMgr->voices[bestCandidate].voiceState == eVoiceStateStolen) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMStealVoice: Voice %d is already marked as stolen and was scheduled to play ch: %d note: %d vel: %d\n", + bestCandidate, + pVoiceMgr->voices[bestCandidate].nextChannel, + pVoiceMgr->voices[bestCandidate].nextNote, + pVoiceMgr->voices[bestCandidate].nextVelocity); */ } + } +#endif + + *pVoiceNumber = (EAS_U16) bestCandidate; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMChannelPressure() + *---------------------------------------------------------------------------- + * Purpose: + * Change the channel pressure for the given channel + * + * Inputs: + * nChannel - the MIDI channel + * nVelocity - the channel pressure value + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sChannel[nChannel].m_nChannelPressure is updated + *---------------------------------------------------------------------------- +*/ +void VMChannelPressure (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + pChannel->channelPressure = value; + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMPitchBend() + *---------------------------------------------------------------------------- + * Purpose: + * Change the pitch wheel value for the given channel. + * This routine constructs the proper 14-bit argument when the calling routine + * passes the pitch LSB and MSB. + * + * Note: some midi disassemblers display a bipolar pitch bend value. + * We can display the bipolar value using + * if m_nPitchBend >= 0x2000 + * bipolar pitch bend = postive (m_nPitchBend - 0x2000) + * else + * bipolar pitch bend = negative (0x2000 - m_nPitchBend) + * + * Inputs: + * nChannel - the MIDI channel + * nPitchLSB - the LSB byte of the pitch bend message + * nPitchMSB - the MSB byte of the pitch bend message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * psSynthObject->m_sChannel[nChannel].m_nPitchBend is changed + * + *---------------------------------------------------------------------------- +*/ +void VMPitchBend (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 nPitchLSB, EAS_U8 nPitchMSB) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + pChannel->pitchBend = (EAS_I16) ((nPitchMSB << 7) | nPitchLSB); + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMControlChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the controller (or mode) for the given channel. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the MIDI controller number + * nControlValue - the value for this controller message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sChannel[nChannel] controller is changed + * + *---------------------------------------------------------------------------- +*/ +void VMControlChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + switch ( controller ) + { + case MIDI_CONTROLLER_BANK_SELECT_MSB: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: Bank Select MSB: msb 0x%X\n", value); */ } +#endif + /* use this MSB with a zero LSB, until we get an LSB message */ + pChannel->bankNum = value << 8; + break; + + case MIDI_CONTROLLER_MOD_WHEEL: + /* we treat mod wheel as a 7-bit controller and only use the MSB */ + pChannel->modWheel = value; + break; + + case MIDI_CONTROLLER_VOLUME: + /* we treat volume as a 7-bit controller and only use the MSB */ + pChannel->volume = value; + break; + + case MIDI_CONTROLLER_PAN: + /* we treat pan as a 7-bit controller and only use the MSB */ + pChannel->pan = value; + break; + + case MIDI_CONTROLLER_EXPRESSION: + /* we treat expression as a 7-bit controller and only use the MSB */ + pChannel->expression = value; + break; + + case MIDI_CONTROLLER_BANK_SELECT_LSB: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: Bank Select LSB: lsb 0x%X\n", value); */ } +#endif + /* + construct bank number as 7-bits (stored as 8) of existing MSB + and 7-bits of new LSB (also stored as 8( + */ + pChannel->bankNum = + (pChannel->bankNum & 0xFF00) | value; + + break; + + case MIDI_CONTROLLER_SUSTAIN_PEDAL: + /* we treat sustain pedal as a boolean on/off bit flag */ + if (value < 64) + { + /* + we are requested to turn the pedal off, but first check + if the pedal is already on + */ + if (0 != + (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + ) + { + /* + The sustain flag is presently set and the damper pedal is on. + We are therefore transitioning from damper pedal ON to + damper pedal OFF. This means all notes in this channel + that received a note off while the damper pedal was on, and + had their note-off requests deferred, should now proceed to + the release state. + */ + VMReleaseAllDeferredNoteOffs(pVoiceMgr, pSynth, channel); + } /* end if sustain pedal is already on */ + + /* turn the sustain pedal off */ + pChannel->channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + } + else + { + /* + we are requested to turn the pedal on, but first check + if the pedal is already off + */ + if (0 == + (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + ) + { + /* + The sustain flag is presently clear and the damper pedal is off. + We are therefore transitioning from damper pedal OFF to + damper pedal ON. Currently sounding notes should be left + unchanged. However, we should try to "catch" notes if possible. + If any notes have levels >= sustain level, catch them, + otherwise, let them continue to release. + */ + VMCatchNotesForSustainPedal(pVoiceMgr, pSynth, channel); + } + + /* turn the sustain pedal on */ + pChannel->channelFlags |= CHANNEL_FLAG_SUSTAIN_PEDAL; + } + + break; +#ifdef _REVERB + case MIDI_CONTROLLER_REVERB_SEND: + /* we treat send as a 7-bit controller and only use the MSB */ + pSynth->channels[channel].reverbSend = value; + break; +#endif +#ifdef _CHORUS + case MIDI_CONTROLLER_CHORUS_SEND: + /* we treat send as a 7-bit controller and only use the MSB */ + pSynth->channels[channel].chorusSend = value; + break; +#endif + case MIDI_CONTROLLER_RESET_CONTROLLERS: + /* despite the Midi message name, not ALL controllers are reset */ + pChannel->modWheel = DEFAULT_MOD_WHEEL; + pChannel->expression = DEFAULT_EXPRESSION; + + /* turn the sustain pedal off as default/reset */ + pChannel->channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + pChannel->pitchBend = DEFAULT_PITCH_BEND; + + /* reset channel pressure */ + pChannel->channelPressure = DEFAULT_CHANNEL_PRESSURE; + + /* reset RPN values */ + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + pChannel->pitchBendSensitivity = DEFAULT_PITCH_BEND_SENSITIVITY; + pChannel->finePitch = DEFAULT_FINE_PITCH; + pChannel->coarsePitch = DEFAULT_COARSE_PITCH; + + /* + program change, bank select, channel volume CC7, pan CC10 + are NOT reset + */ + break; + + /* + For logical reasons, the RPN data entry are grouped together. + However, keep in mind that these cases are not necessarily in + ascending order. + e.g., MIDI_CONTROLLER_DATA_ENTRY_MSB == 6, + whereas MIDI_CONTROLLER_SUSTAIN_PEDAL == 64. + So arrange these case statements in whatever manner is more efficient for + the processor / compiler. + */ + case MIDI_CONTROLLER_ENTER_DATA_MSB: + case MIDI_CONTROLLER_ENTER_DATA_LSB: + case MIDI_CONTROLLER_SELECT_RPN_LSB: + case MIDI_CONTROLLER_SELECT_RPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_LSB: + VMUpdateRPNStateMachine(pSynth, channel, controller, value); + break; + + case MIDI_CONTROLLER_ALL_SOUND_OFF: + case MIDI_CONTROLLER_ALL_NOTES_OFF: + case MIDI_CONTROLLER_OMNI_OFF: + case MIDI_CONTROLLER_OMNI_ON: + case MIDI_CONTROLLER_MONO_ON_POLY_OFF: + case MIDI_CONTROLLER_POLY_ON_MONO_OFF: + /* NOTE: we treat all sounds off the same as all notes off */ + VMAllNotesOff(pVoiceMgr, pSynth, channel); + break; + + default: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: controller %d not yet implemented\n", controller); */ } +#endif + break; + + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMUpdateRPNStateMachine() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when we want to parse RPN related controller messages. + * We only support RPN0 (pitch bend sensitivity), RPN1 (fine tuning) and + * RPN2 (coarse tuning). Any other RPNs or NRPNs are ignored for now. + *. + * Supports any order, so not a state machine anymore. This function was + * rewritten to work correctly regardless of order. + * + * Inputs: + * nChannel - the channel this controller message is coming from + * nControllerNumber - which RPN related controller + * nControlValue - the value of the RPN related controller + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * returns EAS_RESULT, which is typically EAS_SUCCESS, since there are + * few possible errors + * + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nPitchBendSensitivity + * (or m_nFinePitch or m_nCoarsePitch) + * will be updated if the proper RPN message is received. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMUpdateRPNStateMachine (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateRPNStateMachines: error, %d invalid channel number\n", + channel); */ } + return EAS_FAILURE; + } +#endif + + pChannel = &(pSynth->channels[channel]); + + switch (controller) + { + case MIDI_CONTROLLER_SELECT_NRPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_LSB: + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + break; + case MIDI_CONTROLLER_SELECT_RPN_MSB: + pChannel->registeredParam = + (pChannel->registeredParam & 0x7F) | (value<<7); + break; + case MIDI_CONTROLLER_SELECT_RPN_LSB: + pChannel->registeredParam = + (pChannel->registeredParam & 0x7F00) | value; + break; + case MIDI_CONTROLLER_ENTER_DATA_MSB: + switch (pChannel->registeredParam) + { + case 0: + pChannel->pitchBendSensitivity = value * 100; + break; + case 1: + /*lint -e{702} */ + pChannel->finePitch = (EAS_I8)((((value << 7) - 8192) * 100) >> 13); + break; + case 2: + pChannel->coarsePitch = (EAS_I8)(value - 64); + break; + default: + break; + } + break; + case MIDI_CONTROLLER_ENTER_DATA_LSB: + switch (pChannel->registeredParam) + { + case 0: + //ignore lsb + break; + case 1: + //ignore lsb + break; + case 2: + //ignore lsb + break; + default: + break; + } + break; + default: + return EAS_FAILURE; //not a RPN related controller + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMUpdateStaticChannelParameters() + *---------------------------------------------------------------------------- + * Purpose: + * Update all of the static channel parameters for channels that have had + * a controller change values + * Or if the synth has signalled that all channels must forcibly + * be updated + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * none + * + * Side Effects: + * - psSynthObject->m_sChannel[].m_nStaticGain and m_nStaticPitch + * are updated for channels whose controller values have changed + * or if the synth has signalled that all channels must forcibly + * be updated + *---------------------------------------------------------------------------- +*/ +void VMUpdateStaticChannelParameters (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT channel; + + if (pSynth->synthFlags & SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS) + { + /* + the synth wants us to forcibly update all channel + parameters. This event occurs when we are about to + finish resetting the synth + */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + { +#ifdef _HYBRID_SYNTH + if (pSynth->channels[channel].regionIndex & FLAG_RGN_IDX_FM_SYNTH) + pSecondarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); + else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#endif + } + + /* + clear the flag to indicates we have now forcibly + updated all channel parameters + */ + pSynth->synthFlags &= ~SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS; + } + else + { + + /* only update channel params if signalled by a channel flag */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + { + if ( 0 != (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS)) + { +#ifdef _HYBRID_SYNTH + if (pSynth->channels[channel].regionIndex & FLAG_RGN_IDX_FM_SYNTH) + pSecondarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); + else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#endif + } + } + + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMFindProgram() + *---------------------------------------------------------------------------- + * Purpose: + * Look up an individual program in sound library. This function + * searches the bank list for a program, then the individual program + * list. + * + * Inputs: + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT VMFindProgram (const S_EAS *pEAS, EAS_U32 bank, EAS_U8 programNum, EAS_U16 *pRegionIndex) +{ + EAS_U32 locale; + const S_PROGRAM *p; + EAS_U16 i; + EAS_U16 regionIndex; + + /* make sure we have a valid sound library */ + if (pEAS == NULL) + return EAS_FAILURE; + + /* search the banks */ + for (i = 0; i < pEAS->numBanks; i++) + { + if (bank == (EAS_U32) pEAS->pBanks[i].locale) + { + regionIndex = pEAS->pBanks[i].regionIndex[programNum]; + if (regionIndex != INVALID_REGION_INDEX) + { + *pRegionIndex = regionIndex; + return EAS_SUCCESS; + } + break; + } + } + + /* establish locale */ + locale = ( bank << 8) | programNum; + + /* search for program */ + for (i = 0, p = pEAS->pPrograms; i < pEAS->numPrograms; i++, p++) + { + if (p->locale == locale) + { + *pRegionIndex = p->regionIndex; + return EAS_SUCCESS; + } + } + + return EAS_FAILURE; +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMFindDLSProgram() + *---------------------------------------------------------------------------- + * Purpose: + * Look up an individual program in sound library. This function + * searches the bank list for a program, then the individual program + * list. + * + * Inputs: + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT VMFindDLSProgram (const S_DLS *pDLS, EAS_U32 bank, EAS_U8 programNum, EAS_U16 *pRegionIndex) +{ + EAS_U32 locale; + const S_PROGRAM *p; + EAS_U16 i; + + /* make sure we have a valid sound library */ + if (pDLS == NULL) + return EAS_FAILURE; + + /* establish locale */ + locale = (bank << 8) | programNum; + + /* search for program */ + for (i = 0, p = pDLS->pDLSPrograms; i < pDLS->numDLSPrograms; i++, p++) + { + if (p->locale == locale) + { + *pRegionIndex = p->regionIndex; + return EAS_SUCCESS; + } + } + + return EAS_FAILURE; +} +#endif + +/*---------------------------------------------------------------------------- + * VMProgramChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the instrument (program) for the given channel. + * + * Depending on the program number, and the bank selected for this channel, the + * program may be in ROM, RAM (from SMAF or CMX related RAM wavetable), or + * Alternate wavetable (from mobile DLS or other DLS file) + * + * This function figures out what wavetable should be used, and sets it up as the + * wavetable to use for this channel. Also the channel may switch from a melodic + * channel to a rhythm channel, or vice versa. + * + * Inputs: + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nProgramNumber is likely changed + * gsSynthObject.m_sChannel[nChannel].m_psEAS may be changed + * gsSynthObject.m_sChannel[nChannel].m_bRhythmChannel may be changed + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMProgramChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 program) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_U32 bank; + EAS_U16 regionIndex; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMProgramChange: vSynthNum=%d, channel=%d, program=%d\n", pSynth->vSynthNum, channel, program); */ } +#endif + + /* setup pointer to MIDI channel data */ + pChannel = &pSynth->channels[channel]; + bank = pChannel->bankNum; + + /* allow channels to switch between being melodic or rhythm channels, using GM2 CC values */ + if ((bank & 0xFF00) == DEFAULT_RHYTHM_BANK_NUMBER) + { + /* make it a rhythm channel */ + pChannel->channelFlags |= CHANNEL_FLAG_RHYTHM_CHANNEL; + } + else if ((bank & 0xFF00) == DEFAULT_MELODY_BANK_NUMBER) + { + /* make it a melody channel */ + pChannel->channelFlags &= ~CHANNEL_FLAG_RHYTHM_CHANNEL; + } + + regionIndex = DEFAULT_REGION_INDEX; + +#ifdef EXTERNAL_AUDIO + /* give the external audio interface a chance to handle it */ + if (pSynth->cbProgChgFunc != NULL) + { + S_EXT_AUDIO_PRG_CHG prgChg; + prgChg.channel = channel; + prgChg.bank = (EAS_U16) bank; + prgChg.program = program; + if (pSynth->cbProgChgFunc(pSynth->pExtAudioInstData, &prgChg)) + pChannel->channelFlags |= CHANNEL_FLAG_EXTERNAL_AUDIO; + } + +#endif + + +#ifdef DLS_SYNTHESIZER + /* first check for DLS program that may overlay the internal instrument */ + if (VMFindDLSProgram(pSynth->pDLS, bank, program, ®ionIndex) != EAS_SUCCESS) +#endif + + /* braces to support 'if' clause above */ + { + + /* look in the internal banks */ + if (VMFindProgram(pSynth->pEAS, bank, program, ®ionIndex) != EAS_SUCCESS) + + /* fall back to default bank */ + { + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) + bank = DEFAULT_RHYTHM_BANK_NUMBER; + else + bank = DEFAULT_MELODY_BANK_NUMBER; + + if (VMFindProgram(pSynth->pEAS, bank, program, ®ionIndex) != EAS_SUCCESS) + + /* switch to program 0 in the default bank */ + { + if (VMFindProgram(pSynth->pEAS, bank, 0, ®ionIndex) != EAS_SUCCESS) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMProgramChange: No program @ %03d:%03d:%03d\n", + (bank >> 8) & 0x7f, bank & 0x7f, program); */ } + } + } + } + + /* we have our new program change for this channel */ + pChannel->programNum = program; + pChannel->regionIndex = regionIndex; + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + return; +} + +/*---------------------------------------------------------------------------- + * VMAddSamples() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize the requested number of samples (block based processing) + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * number of voices rendered + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMAddSamples (S_VOICE_MGR *pVoiceMgr, EAS_I32 *pMixBuffer, EAS_I32 numSamples) +{ + S_SYNTH *pSynth; + EAS_INT voicesRendered; + EAS_INT voiceNum; + EAS_BOOL done; + +#ifdef _REVERB + EAS_PCM *pReverbSendBuffer; +#endif // ifdef _REVERB + +#ifdef _CHORUS + EAS_PCM *pChorusSendBuffer; +#endif // ifdef _CHORUS + + voicesRendered = 0; + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + /* retarget stolen voices */ + if ((pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) && (pVoiceMgr->voices[voiceNum].gain <= 0)) + VMRetargetStolenVoice(pVoiceMgr, voiceNum); + + /* get pointer to virtual synth */ + pSynth = pVoiceMgr->pSynth[pVoiceMgr->voices[voiceNum].channel >> 4]; + + /* synthesize active voices */ + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateFree) + { + done = GetSynthPtr(voiceNum)->pfUpdateVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), pMixBuffer, numSamples); + voicesRendered++; + + /* voice is finished */ + if (done == EAS_TRUE) + { + /* set gain of stolen voice to zero so it will be restarted */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) + pVoiceMgr->voices[voiceNum].gain = 0; + + /* or return it to the free voice pool */ + else + VMFreeVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum]); + } + + /* if this voice is scheduled to be muted, set the mute flag */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_DEFER_MUTE) + { + pVoiceMgr->voices[voiceNum].voiceFlags &= ~(VOICE_FLAG_DEFER_MUTE | VOICE_FLAG_DEFER_MIDI_NOTE_OFF); + VMMuteVoice(pVoiceMgr, voiceNum); + } + + /* if voice just started, advance state to play */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStart) + pVoiceMgr->voices[voiceNum].voiceState = eVoiceStatePlay; + } + } + + return voicesRendered; +} + +/*---------------------------------------------------------------------------- + * VMRender() + *---------------------------------------------------------------------------- + * Purpose: + * This routine renders a frame of audio + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pVoicesRendered - number of voices rendered this frame + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMRender (S_VOICE_MGR *pVoiceMgr, EAS_I32 numSamples, EAS_I32 *pMixBuffer, EAS_I32 *pVoicesRendered) +{ + S_SYNTH *pSynth; + EAS_INT i; + EAS_INT channel; + +#ifdef _CHECKED_BUILD + SanityCheck(pVoiceMgr); +#endif + + /* update MIDI channel parameters */ + *pVoicesRendered = 0; + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pVoiceMgr->pSynth[i] != NULL) + VMUpdateStaticChannelParameters(pVoiceMgr, pVoiceMgr->pSynth[i]); + } + + /* synthesize a buffer of audio */ + *pVoicesRendered = VMAddSamples(pVoiceMgr, pMixBuffer, numSamples); + + /* + * check for deferred note-off messages + * If flag is set, that means one or more voices are expecting deferred + * midi note-off messages because the midi note-on and corresponding midi + * note-off requests occurred during the same update interval. The goal + * is the defer the note-off request so that the note can at least start. + */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + pSynth = pVoiceMgr->pSynth[i]; + + if (pSynth== NULL) + continue; + + if (pSynth->synthFlags & SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING) + VMDeferredStopNote(pVoiceMgr, pSynth); + + /* check if we need to reset the synth */ + if ((pSynth->synthFlags & SYNTH_FLAG_RESET_IS_REQUESTED) && + (pSynth->numActiveVoices == 0)) + { + /* + complete the process of resetting the synth now that + all voices have muted + */ +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMAddSamples: complete the reset process\n"); */ } +#endif + + VMInitializeAllChannels(pVoiceMgr, pSynth); + VMInitializeAllVoices(pVoiceMgr, pSynth->vSynthNum); + + /* clear the reset flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_RESET_IS_REQUESTED; + } + + /* clear channel update flags */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + pSynth->channels[channel].channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + } + +#ifdef _CHECKED_BUILD + SanityCheck(pVoiceMgr); +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMInitWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Clears the workload counter + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitWorkload (S_VOICE_MGR *pVoiceMgr) +{ + pVoiceMgr->workload = 0; +} + +/*---------------------------------------------------------------------------- + * VMSetWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the max workload for a single frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetWorkload (S_VOICE_MGR *pVoiceMgr, EAS_I32 maxWorkLoad) +{ + pVoiceMgr->maxWorkLoad = maxWorkLoad; +} + +/*---------------------------------------------------------------------------- + * VMCheckWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Checks to see if work load has been exceeded on this frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckWorkload (S_VOICE_MGR *pVoiceMgr) +{ + if (pVoiceMgr->maxWorkLoad > 0) + return (EAS_BOOL) (pVoiceMgr->workload >= pVoiceMgr->maxWorkLoad); + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * VMActiveVoices() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the number of active voices in the synthesizer. + * + * Inputs: + * pEASData - pointer to instance data + * + * Outputs: + * Returns the number of active voices + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMActiveVoices (S_SYNTH *pSynth) +{ + return pSynth->numActiveVoices; +} + +/*---------------------------------------------------------------------------- + * VMSetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * synth synthesizer number (0 = onboard, 1 = DSP) + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 polyphonyCount) +{ + EAS_INT i; + EAS_INT activeVoices; + + /* lower limit */ + if (polyphonyCount < 1) + polyphonyCount = 1; + + /* split architecture */ +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + if (synth == EAS_MCU_SYNTH) + { + if (polyphonyCount > NUM_PRIMARY_VOICES) + polyphonyCount = NUM_PRIMARY_VOICES; + if (pVoiceMgr->maxPolyphonyPrimary == polyphonyCount) + return EAS_SUCCESS; + pVoiceMgr->maxPolyphonyPrimary = (EAS_U16) polyphonyCount; + } + else if (synth == EAS_DSP_SYNTH) + { + if (polyphonyCount > NUM_SECONDARY_VOICES) + polyphonyCount = NUM_SECONDARY_VOICES; + if (pVoiceMgr->maxPolyphonySecondary == polyphonyCount) + return EAS_SUCCESS; + pVoiceMgr->maxPolyphonySecondary = (EAS_U16) polyphonyCount; + } + else + return EAS_ERROR_PARAMETER_RANGE; + + /* setting for SP-MIDI */ + pVoiceMgr->maxPolyphony = pVoiceMgr->maxPolyphonyPrimary + pVoiceMgr->maxPolyphonySecondary; + + /* standard architecture */ +#else + if (synth != EAS_MCU_SYNTH) + return EAS_ERROR_PARAMETER_RANGE; + + /* pin desired value to possible limits */ + if (polyphonyCount > MAX_SYNTH_VOICES) + polyphonyCount = MAX_SYNTH_VOICES; + + /* set polyphony, if value is different than current value */ + if (pVoiceMgr->maxPolyphony == polyphonyCount) + return EAS_SUCCESS; + + pVoiceMgr->maxPolyphony = (EAS_U16) polyphonyCount; +#endif + + /* if SPMIDI enabled, update channel masking based on new polyphony */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pVoiceMgr->pSynth[i]) + { + if (pVoiceMgr->pSynth[i]->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + VMMIPUpdateChannelMuting(pVoiceMgr, pVoiceMgr->pSynth[i]); + else + pVoiceMgr->pSynth[i]->poolAlloc[0] = (EAS_U8) polyphonyCount; + } + } + + /* are we under polyphony limit? */ + if (pVoiceMgr->activeVoices <= polyphonyCount) + return EAS_SUCCESS; + + /* count the number of active voices */ + activeVoices = 0; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + /* is voice active? */ + if ((pVoiceMgr->voices[i].voiceState != eVoiceStateFree) && (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting)) + activeVoices++; + } + + /* we may have to mute voices to reach new target */ + while (activeVoices > polyphonyCount) + { + S_SYNTH *pSynth; + S_SYNTH_VOICE *pVoice; + EAS_I32 currentPriority, bestPriority; + EAS_INT bestCandidate; + + /* find the lowest priority voice */ + bestPriority = bestCandidate = -1; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + pVoice = &pVoiceMgr->voices[i]; + + /* ignore free and muting voices */ + if ((pVoice->voiceState == eVoiceStateFree) || (pVoice->voiceState == eVoiceStateMuting)) + continue; + + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pVoice->voiceState == eVoiceStateStolen) || (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + /* include velocity */ + currentPriority = 128 - pVoice->nextVelocity; + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + else + { + /* include age */ + currentPriority = (EAS_I32) pVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->channel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + + /* include synth priority */ + currentPriority += pSynth->priority << SYNTH_PRIORITY_WEIGHT; + + /* is this the best choice so far? */ + if (currentPriority > bestPriority) + { + bestPriority = currentPriority; + bestCandidate = i; + } + } + + /* shutdown best candidate */ + if (bestCandidate < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMSetPolyphony: Unable to reduce polyphony\n"); */ } + break; + } + + /* shut down this voice */ + /*lint -e{771} pSynth is initialized if bestCandidate >= 0 */ + VMMuteVoice(pVoiceMgr, bestCandidate); + activeVoices--; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * + * Outputs: + * Returns actual polyphony value set, as pinned by limits + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 *pPolyphonyCount) +{ + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + if (synth == EAS_MCU_SYNTH) + *pPolyphonyCount = pVoiceMgr->maxPolyphonyPrimary; + else if (synth == EAS_DSP_SYNTH) + *pPolyphonyCount = pVoiceMgr->maxPolyphonySecondary; + else + return EAS_ERROR_PARAMETER_RANGE; +#else + if (synth != EAS_MCU_SYNTH) + return EAS_ERROR_PARAMETER_RANGE; + *pPolyphonyCount = pVoiceMgr->maxPolyphony; +#endif + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth polyphony. 0 = no limit (i.e. can use + * all available voices). + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 polyphonyCount) +{ + EAS_INT i; + EAS_INT activeVoices; + + /* check limits */ + if (polyphonyCount < 0) + return EAS_ERROR_PARAMETER_RANGE; + + /* zero is max polyphony */ + if ((polyphonyCount == 0) || (polyphonyCount > MAX_SYNTH_VOICES)) + { + pSynth->maxPolyphony = 0; + return EAS_SUCCESS; + } + + /* set new polyphony */ + pSynth->maxPolyphony = (EAS_U16) polyphonyCount; + + /* max polyphony is minimum of virtual synth and actual synth */ + if (polyphonyCount > pVoiceMgr->maxPolyphony) + polyphonyCount = pVoiceMgr->maxPolyphony; + + /* if SP-MIDI mode, update the channel muting */ + if (pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + VMMIPUpdateChannelMuting(pVoiceMgr, pSynth); + else + pSynth->poolAlloc[0] = (EAS_U8) polyphonyCount; + + /* are we under polyphony limit? */ + if (pSynth->numActiveVoices <= polyphonyCount) + return EAS_SUCCESS; + + /* count the number of active voices */ + activeVoices = 0; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + /* this synth? */ + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) != pSynth->vSynthNum) + continue; + + /* is voice active? */ + if ((pVoiceMgr->voices[i].voiceState != eVoiceStateFree) && (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting)) + activeVoices++; + } + + /* we may have to mute voices to reach new target */ + while (activeVoices > polyphonyCount) + { + S_SYNTH_VOICE *pVoice; + EAS_I32 currentPriority, bestPriority; + EAS_INT bestCandidate; + + /* find the lowest priority voice */ + bestPriority = bestCandidate = -1; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + pVoice = &pVoiceMgr->voices[i]; + + /* this synth? */ + if (GET_VSYNTH(pVoice->nextChannel) != pSynth->vSynthNum) + continue; + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pVoice->voiceState == eVoiceStateStolen) || (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + /* include velocity */ + currentPriority = 128 - pVoice->nextVelocity; + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + else + { + /* include age */ + currentPriority = (EAS_I32) pVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + + /* is this the best choice so far? */ + if (currentPriority > bestPriority) + { + bestPriority = currentPriority; + bestCandidate = i; + } + } + + /* shutdown best candidate */ + if (bestCandidate < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMSetPolyphony: Unable to reduce polyphony\n"); */ } + break; + } + + /* shut down this voice */ + VMMuteVoice(pVoiceMgr, bestCandidate); + activeVoices--; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth polyphony + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPolyphonyCount pointer to variable to hold polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMGetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPolyphonyCount) +{ + *pPolyphonyCount = (EAS_U16) pSynth->maxPolyphony; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * priority new priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMSetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 priority) +{ + pSynth->priority = (EAS_U8) priority ; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPriority pointer to variable to hold priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMGetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPriority) +{ + *pPriority = pSynth->priority; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for this synthesizer for this sequence. + * + * Inputs: + * nSynthVolume - the desired master volume + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +void VMSetVolume (S_SYNTH *pSynth, EAS_U16 masterVolume) +{ + pSynth->masterVolume = masterVolume; + pSynth->synthFlags |= SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMSetPitchBendRange() + *---------------------------------------------------------------------------- + * Set the pitch bend range for the given channel. + *---------------------------------------------------------------------------- +*/ +void VMSetPitchBendRange (S_SYNTH *pSynth, EAS_INT channel, EAS_I16 pitchBendRange) +{ + pSynth->channels[channel].pitchBendSensitivity = pitchBendRange; +} + +/*---------------------------------------------------------------------------- + * VMValidateEASLib() + *---------------------------------------------------------------------------- + * Validates an EAS library + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMValidateEASLib (EAS_SNDLIB_HANDLE pEAS) +{ + /* validate the sound library */ + if (pEAS) + { + if (pEAS->identifier != _EAS_LIBRARY_VERSION) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Sound library mismatch in sound library: Read 0x%08x, expected 0x%08x\n", + pEAS->identifier, _EAS_LIBRARY_VERSION); */ } + return EAS_ERROR_SOUND_LIBRARY; + } + + /* check sample rate */ + if ((pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK) != _OUTPUT_SAMPLE_RATE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Sample rate mismatch in sound library: Read %lu, expected %lu\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } + +#ifdef _WT_SYNTH + /* check sample bit depth */ +#ifdef _8_BIT_SAMPLES + if (pEAS->libAttr & LIB_FORMAT_16_BIT_SAMPLES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Expected 8-bit samples and found 16-bit\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } +#endif +#ifdef _16_BIT_SAMPLES + if ((pEAS->libAttr & LIB_FORMAT_16_BIT_SAMPLES) == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Expected 16-bit samples and found 8-bit\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } +#endif +#endif + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetGlobalEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the EAS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalEASLib (S_VOICE_MGR *pVoiceMgr, EAS_SNDLIB_HANDLE pEAS) +{ + EAS_RESULT result; + + result = VMValidateEASLib(pEAS); + if (result != EAS_SUCCESS) + return result; + + pVoiceMgr->pGlobalEAS = pEAS; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the EAS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetEASLib (S_SYNTH *pSynth, EAS_SNDLIB_HANDLE pEAS) +{ + EAS_RESULT result; + + result = VMValidateEASLib(pEAS); + if (result != EAS_SUCCESS) + return result; + + pSynth->pEAS = pEAS; + return EAS_SUCCESS; +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMSetGlobalDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the DLS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalDLSLib (EAS_DATA_HANDLE pEASData, EAS_DLSLIB_HANDLE pDLS) +{ + + if (pEASData->pVoiceMgr->pGlobalDLS) + DLSCleanup(pEASData->hwInstData, pEASData->pVoiceMgr->pGlobalDLS); + + pEASData->pVoiceMgr->pGlobalDLS = pDLS; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the DLS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetDLSLib (S_SYNTH *pSynth, EAS_DLSLIB_HANDLE pDLS) +{ + pSynth->pDLS = pDLS; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * VMSetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetTranposition (S_SYNTH *pSynth, EAS_I32 transposition) +{ + pSynth->globalTranspose = (EAS_I8) transposition; +} + +/*---------------------------------------------------------------------------- + * VMGetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMGetTranposition (S_SYNTH *pSynth, EAS_I32 *pTransposition) +{ + *pTransposition = pSynth->globalTranspose; +} + +/*---------------------------------------------------------------------------- + * VMGetNoteCount() + *---------------------------------------------------------------------------- +* Returns the total note count +*---------------------------------------------------------------------------- +*/ +EAS_I32 VMGetNoteCount (S_SYNTH *pSynth) +{ + return pSynth->totalNoteCount; +} + +/*---------------------------------------------------------------------------- + * VMMIDIShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMMIDIShutdown (S_EAS_DATA *pEASData, S_SYNTH *pSynth) +{ + EAS_INT vSynthNum; + + /* decrement reference count, free if all references are gone */ + if (--pSynth->refCount > 0) + return; + + vSynthNum = pSynth->vSynthNum; + + /* cleanup DLS load */ +#ifdef DLS_SYNTHESIZER + /*lint -e{550} result used only in debugging code */ + if (pSynth->pDLS != NULL) + { + EAS_RESULT result; + if ((result = DLSCleanup(pEASData->hwInstData, pSynth->pDLS)) != EAS_SUCCESS) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMMIDIShutdown: Error %ld cleaning up DLS collection\n", result); */ } + pSynth->pDLS = NULL; + } +#endif + + VMReset(pEASData->pVoiceMgr, pSynth, EAS_TRUE); + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pSynth); + + /* clear pointer to MIDI state */ + pEASData->pVoiceMgr->pSynth[vSynthNum] = NULL; +} + +/*---------------------------------------------------------------------------- + * VMShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMShutdown (S_EAS_DATA *pEASData) +{ + + /* don't free a NULL pointer */ + if (pEASData->pVoiceMgr == NULL) + return; + +#ifdef DLS_SYNTHESIZER + /* if we have a global DLS collection, clean it up */ + if (pEASData->pVoiceMgr->pGlobalDLS) + { + DLSCleanup(pEASData->hwInstData, pEASData->pVoiceMgr->pGlobalDLS); + pEASData->pVoiceMgr->pGlobalDLS = NULL; + } +#endif + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pEASData->pVoiceMgr); + pEASData->pVoiceMgr = NULL; +} + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Register a callback for external audio processing + *---------------------------------------------------------------------------- +*/ +void VMRegExtAudioCallback (S_SYNTH *pSynth, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc) +{ + pSynth->pExtAudioInstData = pInstData; + pSynth->cbProgChgFunc = cbProgChgFunc; + pSynth->cbEventFunc = cbEventFunc; +} + +/*---------------------------------------------------------------------------- + * VMGetMIDIControllers() + *---------------------------------------------------------------------------- + * Returns the MIDI controller values on the specified channel + *---------------------------------------------------------------------------- +*/ +void VMGetMIDIControllers (S_SYNTH *pSynth, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) +{ + pControl->modWheel = pSynth->channels[channel].modWheel; + pControl->volume = pSynth->channels[channel].volume; + pControl->pan = pSynth->channels[channel].pan; + pControl->expression = pSynth->channels[channel].expression; + pControl->channelPressure = pSynth->channels[channel].channelPressure; + +#ifdef _REVERB + pControl->reverbSend = pSynth->channels[channel].reverbSend; +#endif + +#ifdef _CHORUSE + pControl->chorusSend = pSynth->channels[channel].chorusSend; +#endif +} +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * VMStartFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Starts an audio frame + * + * Inputs: + * + * Outputs: + * Returns true if EAS_MixEnginePrep should be called (onboard mixing) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMStartFrame (S_EAS_DATA *pEASData) +{ + + /* init counter for voices starts in split architecture */ +#ifdef MAX_VOICE_STARTS + pVoiceMgr->numVoiceStarts = 0; +#endif + + return pFrameInterface->pfStartFrame(pEASData->pVoiceMgr->pFrameBuffer); +} + +/*---------------------------------------------------------------------------- + * VMEndFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Stops an audio frame + * + * Inputs: + * + * Outputs: + * Returns true if EAS_MixEnginePost should be called (onboard mixing) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMEndFrame (S_EAS_DATA *pEASData) +{ + + return pFrameInterface->pfEndFrame(pEASData->pVoiceMgr->pFrameBuffer, pEASData->pMixBuffer, pEASData->masterGain); +} +#endif + +#ifdef TEST_HARNESS +/*---------------------------------------------------------------------------- + * SanityCheck() + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSanityCheck (EAS_DATA_HANDLE pEASData) +{ + S_SYNTH_VOICE *pVoice; + S_SYNTH *pSynth; + EAS_INT i; + EAS_INT j; + EAS_INT freeVoices; + EAS_INT activeVoices; + EAS_INT playingVoices; + EAS_INT stolenVoices; + EAS_INT releasingVoices; + EAS_INT mutingVoices; + EAS_INT poolCount[MAX_VIRTUAL_SYNTHESIZERS][NUM_SYNTH_CHANNELS]; + EAS_INT vSynthNum; + EAS_RESULT result = EAS_SUCCESS; + + /* initialize counts */ + EAS_HWMemSet(poolCount, 0, sizeof(poolCount)); + freeVoices = activeVoices = playingVoices = stolenVoices = releasingVoices = mutingVoices = 0; + + /* iterate through all voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + pVoice = &pEASData->pVoiceMgr->voices[i]; + if (pVoice->voiceState != eVoiceStateFree) + { + vSynthNum = GET_VSYNTH(pVoice->channel); + if (vSynthNum >= MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Voice %d has invalid virtual synth number %d\n", i, vSynthNum); */ } + result = EAS_FAILURE; + continue; + } + pSynth = pEASData->pVoiceMgr->pSynth[vSynthNum]; + + switch (pVoice->voiceState) + { + case eVoiceStateMuting: + activeVoices++; + mutingVoices++; + break; + + case eVoiceStateStolen: + vSynthNum = GET_VSYNTH(pVoice->nextChannel); + if (vSynthNum >= MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Voice %d has invalid virtual synth number %d\n", i, vSynthNum); */ } + result = EAS_FAILURE; + continue; + } + pSynth = pEASData->pVoiceMgr->pSynth[vSynthNum]; + activeVoices++; + stolenVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool]++; + break; + + case eVoiceStateStart: + case eVoiceStatePlay: + activeVoices++; + playingVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->channel)].pool]++; + break; + + case eVoiceStateRelease: + activeVoices++; + releasingVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->channel)].pool]++; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck : voice %d in invalid state\n", i); */ } + result = EAS_FAILURE; + break; + } + } + + /* count free voices */ + else + freeVoices++; + } + + /* dump state info */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d free\n", freeVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d active\n", activeVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d playing\n", playingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d releasing\n", releasingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d muting\n", mutingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d stolen\n", stolenVoices); */ } + + if (pEASData->pVoiceMgr->activeVoices != activeVoices) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Active voice mismatch was %d should be %d\n", + pEASData->pVoiceMgr->activeVoices, activeVoices); */ } + result = EAS_FAILURE; + } + + /* check virtual synth status */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pEASData->pVoiceMgr->pSynth[i] == NULL) + continue; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Synth %d numActiveVoices: %d\n", i, pEASData->pVoiceMgr->pSynth[i]->numActiveVoices); */ } + if (pEASData->pVoiceMgr->pSynth[i]->numActiveVoices > MAX_SYNTH_VOICES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Synth %d illegal count for numActiveVoices: %d\n", i, pEASData->pVoiceMgr->pSynth[i]->numActiveVoices); */ } + result = EAS_FAILURE; + } + for (j = 0; j < NUM_SYNTH_CHANNELS; j++) + { + if (poolCount[i][j] != pEASData->pVoiceMgr->pSynth[i]->poolCount[j]) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Pool count mismatch synth %d pool %d, was %d, should be %d\n", + i, j, pEASData->pVoiceMgr->pSynth[i]->poolCount[j], poolCount[i][j]); */ } + result = EAS_FAILURE; + } + } + } + + return result; +} +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefile.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefile.c new file mode 100755 index 0000000..f24bde2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefile.c @@ -0,0 +1,867 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefile.c + * + * Contents and purpose: + * This file implements the wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 852 $ + * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_config.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_wavefile.h" + +/* lint is choking on the ARM math.h file, so we declare the log10 function here */ +extern double log10(double x); + +/* increase gain to compensate for loss in mixer */ +#define WAVE_GAIN_OFFSET 6 + +/* constant for 1200 / log10(2.0) */ +#define PITCH_CENTS_CONVERSION 3986.313714 + +/*---------------------------------------------------------------------------- + * WAVE file defines + *---------------------------------------------------------------------------- +*/ +/* RIFF chunks */ +#define CHUNK_TYPE(a,b,c,d) ( \ + ( ((EAS_U32)(a) & 0xFF) << 24 ) \ + + ( ((EAS_U32)(b) & 0xFF) << 16 ) \ + + ( ((EAS_U32)(c) & 0xFF) << 8 ) \ + + ( ((EAS_U32)(d) & 0xFF) ) ) + +#define CHUNK_RIFF CHUNK_TYPE('R','I','F','F') +#define CHUNK_WAVE CHUNK_TYPE('W','A','V','E') +#define CHUNK_FMT CHUNK_TYPE('f','m','t',' ') +#define CHUNK_DATA CHUNK_TYPE('d','a','t','a') +#define CHUNK_LIST CHUNK_TYPE('L','I','S','T') +#define CHUNK_INFO CHUNK_TYPE('I','N','F','O') +#define CHUNK_INAM CHUNK_TYPE('I','N','A','M') +#define CHUNK_ICOP CHUNK_TYPE('I','C','O','P') +#define CHUNK_IART CHUNK_TYPE('I','A','R','T') + +/* wave file format identifiers */ +#define WAVE_FORMAT_PCM 0x0001 +#define WAVE_FORMAT_IMA_ADPCM 0x0011 + +/* file size for streamed file */ +#define FILE_SIZE_STREAMING 0x80000000 + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset); +static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate); +static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData); +static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength); + +#ifdef MMAPI_SUPPORT +static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 size); +#endif + +/*---------------------------------------------------------------------------- + * + * EAS_Wave_Parser + * + * This structure contains the functional interface for the Wave file parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_Wave_Parser = +{ + WaveCheckFileType, + WavePrepare, + NULL, + NULL, + WaveState, + WaveClose, + WaveReset, + WavePause, + WaveResume, + WaveLocate, + WaveSetData, + WaveGetData, + WaveGetMetaData +}; + +/*---------------------------------------------------------------------------- + * WaveCheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset) +{ + S_WAVE_STATE *pWaveData; + + /* zero the memory to insure complete initialization */ + *pHandle = NULL; + + /* read the file header */ + if (WaveParseHeader(pEASData, fileHandle, NULL) == EAS_SUCCESS) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pWaveData = EAS_CMEnumData(EAS_CM_WAVE_DATA); + else + pWaveData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_WAVE_STATE)); + if (!pWaveData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pWaveData, 0, sizeof(S_WAVE_STATE)); + + /* return a pointer to the instance data */ + pWaveData->fileHandle = fileHandle; + pWaveData->fileOffset = offset; + *pHandle = pWaveData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WavePrepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + + /* validate parser state */ + pWaveData = (S_WAVE_STATE*) pInstData; + if (pWaveData->streamHandle != NULL) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* back to start of file */ + pWaveData->time = 0; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->fileOffset)) != EAS_SUCCESS) + return result; + + /* parse the file header */ + if ((result = WaveParseHeader(pEASData, pWaveData->fileHandle, pWaveData)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState) +{ + S_WAVE_STATE *pWaveData; + + /* return current state */ + pWaveData = (S_WAVE_STATE*) pInstData; + if (pWaveData->streamHandle) + return EAS_PEState(pEASData, pWaveData->streamHandle, pState); + + /* if no stream handle, and time is not zero, we are done */ + if (pWaveData->time > 0) + *pState = EAS_STATE_STOPPED; + else + *pState = EAS_STATE_OPEN; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + + pWaveData = (S_WAVE_STATE*) pInstData; + + /* close the stream */ + if (pWaveData->streamHandle) + { + if ((result = EAS_PEClose(pEASData, pWaveData->streamHandle)) != EAS_SUCCESS) + return result; + pWaveData->streamHandle = NULL; + } + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + { + +#ifdef MMAPI_SUPPORT + /* need to free the fmt chunk */ + if (pWaveData->fmtChunk != NULL) + EAS_HWFree(pEASData->hwInstData, pWaveData->fmtChunk); +#endif + + /* free the instance data */ + EAS_HWFree(pEASData->hwInstData, pWaveData); + + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveReset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* reset to first byte of data in the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEReset(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveLocate() + *---------------------------------------------------------------------------- + * Purpose: + * Rewind/fast-forward in file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * time - time (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pParserLocate) reserved for future use */ +static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate) +{ + EAS_PCM_HANDLE streamHandle; + + /* reset to first byte of data in the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PELocate(pEASData, streamHandle, time); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WavePause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* pause the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEPause(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* resume the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEResume(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveSetData() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_WAVE_STATE *pWaveData = (S_WAVE_STATE*) pInstData; + + switch (param) + { + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pWaveData->metadata, (void*) value, sizeof(S_METADATA_CB)); + return EAS_SUCCESS; + + case PARSER_DATA_PLAYBACK_RATE: + value = (EAS_I32) (PITCH_CENTS_CONVERSION * log10((double) value / (double) (1 << 28))); + return EAS_PEUpdatePitch(pEASData, pWaveData->streamHandle, (EAS_I16) value); + + case PARSER_DATA_VOLUME: + return EAS_PEUpdateVolume(pEASData, pWaveData->streamHandle, (EAS_I16) value); + + default: + return EAS_ERROR_INVALID_PARAMETER; + } +} + +/*---------------------------------------------------------------------------- + * WaveGetData() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_WAVE_STATE *pWaveData; + + pWaveData = (S_WAVE_STATE*) pInstData; + switch (param) + { + /* return file type as WAVE */ + case PARSER_DATA_FILE_TYPE: + *pValue = pWaveData->fileType; + break; + +#ifdef MMAPI_SUPPORT + /* return pointer to 'fmt' chunk */ + case PARSER_DATA_FORMAT: + *pValue = (EAS_I32) pWaveData->fmtChunk; + break; +#endif + + case PARSER_DATA_GAIN_OFFSET: + *pValue = WAVE_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the WAVE file header. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData) +{ + S_PCM_OPEN_PARAMS params; + EAS_RESULT result; + EAS_U32 tag; + EAS_U32 fileSize; + EAS_U32 size; + EAS_I32 pos; + EAS_I32 audioOffset; + EAS_U16 usTemp; + EAS_BOOL parseDone; + EAS_U32 avgBytesPerSec; + + /* init some data (and keep lint happy) */ + params.sampleRate = 0; + params.size = 0; + audioOffset = 0; + params.decoder = 0; + params.blockSize = 0; + params.pCallbackFunc = NULL; + params.cbInstData = NULL; + params.loopSamples = 0; + params.fileHandle = fileHandle; + params.volume = 0x7fff; + params.envData = 0; + avgBytesPerSec = 8000; + + /* check for 'RIFF' tag */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag != CHUNK_RIFF) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get size */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &fileSize, EAS_FALSE)) != EAS_FALSE) + return result; + + /* check for 'WAVE' tag */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag != CHUNK_WAVE) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* this is enough to say we recognize the file */ + if (pWaveData == NULL) + return EAS_SUCCESS; + + /* check for streaming mode */ + pWaveData->flags = 0; + pWaveData->mediaLength = -1; + pWaveData->infoChunkPos = -1; + pWaveData->infoChunkSize = -1; + if (fileSize== FILE_SIZE_STREAMING) + { + pWaveData->flags |= PCM_FLAGS_STREAMING; + fileSize = 0x7fffffff; + } + + /* find out where we're at */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS) + return result; + fileSize -= 4; + + parseDone = EAS_FALSE; + for (;;) + { + /* get tag and size for next chunk */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &size, EAS_FALSE)) != EAS_FALSE) + return result; + + /* process chunk */ + pos += 8; + switch (tag) + { + case CHUNK_FMT: + +#ifdef MMAPI_SUPPORT + if ((result = SaveFmtChunk(pEASData, fileHandle, pWaveData, (EAS_I32) size)) != EAS_SUCCESS) + return result; +#endif + + /* get audio format */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + if (usTemp == WAVE_FORMAT_PCM) + { + params.decoder = EAS_DECODER_PCM; + pWaveData->fileType = EAS_FILE_WAVE_PCM; + } + else if (usTemp == WAVE_FORMAT_IMA_ADPCM) + { + params.decoder = EAS_DECODER_IMA_ADPCM; + pWaveData->fileType = EAS_FILE_WAVE_IMA_ADPCM; + } + else + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get number of channels */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + if (usTemp == 2) + pWaveData->flags |= PCM_FLAGS_STEREO; + else if (usTemp != 1) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get sample rate */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, ¶ms.sampleRate, EAS_FALSE)) != EAS_FALSE) + return result; + + /* get stream rate */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &avgBytesPerSec, EAS_FALSE)) != EAS_FALSE) + return result; + + /* get block alignment */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + params.blockSize = usTemp; + + /* get bits per sample */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + + /* PCM, must be 8 or 16 bit samples */ + if (params.decoder == EAS_DECODER_PCM) + { + if (usTemp == 8) + pWaveData->flags |= PCM_FLAGS_8_BIT | PCM_FLAGS_UNSIGNED; + else if (usTemp != 16) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* for IMA ADPCM, we only support mono 4-bit ADPCM */ + else + { + if ((usTemp != 4) || (pWaveData->flags & PCM_FLAGS_STEREO)) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + break; + + case CHUNK_DATA: + audioOffset = pos; + if (pWaveData->flags & PCM_FLAGS_STREAMING) + { + params.size = 0x7fffffff; + parseDone = EAS_TRUE; + } + else + { + params.size = (EAS_I32) size; + params.loopStart = size; + /* use more accurate method if possible */ + if (size <= (0x7fffffff / 1000)) + pWaveData->mediaLength = (EAS_I32) ((size * 1000) / avgBytesPerSec); + else + pWaveData->mediaLength = (EAS_I32) (size / (avgBytesPerSec / 1000)); + } + break; + + case CHUNK_LIST: + /* get the list type */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag == CHUNK_INFO) + { + pWaveData->infoChunkPos = pos + 4; + pWaveData->infoChunkSize = (EAS_I32) size - 4; + } + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + if (parseDone) + break; + + /* subtract header size */ + fileSize -= 8; + + /* account for zero-padding on odd length chunks */ + if (size & 1) + size++; + + /* this check works for files with odd length last chunk and no zero-pad */ + if (size >= fileSize) + { + if (size > fileSize) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: '%c%c%c%c' chunk size exceeds length of file or is not zero-padded\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + /* subtract size of data chunk (including any zero-pad) */ + fileSize -= size; + + /* seek to next chunk */ + pos += (EAS_I32) size; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos)) != EAS_SUCCESS) + return result; + } + + /* check for valid header */ + if ((params.sampleRate == 0) || (params.size == 0)) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* save the pertinent information */ + pWaveData->audioOffset = audioOffset; + params.flags = pWaveData->flags; + + /* seek to data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, audioOffset)) != EAS_SUCCESS) + return result; + + /* open a stream in the PCM engine */ + return EAS_PEOpenStream(pEASData, ¶ms, &pWaveData->streamHandle); +} + +/*---------------------------------------------------------------------------- + * WaveGetMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * Process the INFO chunk and return metadata to host + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + EAS_I32 pos; + EAS_U32 size; + EAS_I32 infoSize; + EAS_U32 tag; + EAS_I32 restorePos; + E_EAS_METADATA_TYPE metaType; + EAS_I32 metaLen; + + /* get current position so we can restore it */ + pWaveData = (S_WAVE_STATE*) pInstData; + + /* return media length */ + *pMediaLength = pWaveData->mediaLength; + + /* did we encounter an INFO chunk? */ + if (pWaveData->infoChunkPos < 0) + return EAS_SUCCESS; + + if ((result = EAS_HWFilePos(pEASData->hwInstData, pWaveData->fileHandle, &restorePos)) != EAS_SUCCESS) + return result; + + /* offset to start of first chunk in INFO chunk */ + pos = pWaveData->infoChunkPos; + infoSize = pWaveData->infoChunkSize; + + /* read all the chunks in the INFO chunk */ + for (;;) + { + + /* seek to next chunk */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get tag and size for next chunk */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &size, EAS_FALSE)) != EAS_FALSE) + return result; + + /* process chunk */ + pos += 8; + metaType = EAS_METADATA_UNKNOWN; + switch (tag) + { + case CHUNK_INAM: + metaType = EAS_METADATA_TITLE; + break; + + case CHUNK_IART: + metaType = EAS_METADATA_AUTHOR; + break; + + case CHUNK_ICOP: + metaType = EAS_METADATA_COPYRIGHT; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + /* process known metadata */ + if (metaType != EAS_METADATA_UNKNOWN) + { + metaLen = pWaveData->metadata.bufferSize - 1; + if (metaLen > (EAS_I32) size) + metaLen = (EAS_I32) size; + if ((result = EAS_HWReadFile(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->metadata.buffer, metaLen, &metaLen)) != EAS_SUCCESS) + return result; + pWaveData->metadata.buffer[metaLen] = 0; + pWaveData->metadata.callback(metaType, pWaveData->metadata.buffer, pWaveData->metadata.pUserData); + } + + /* subtract this block */ + if (size & 1) + size++; + infoSize -= (EAS_I32) size + 8; + if (infoSize == 0) + break; + pos += (EAS_I32) size; + } + + + /* restore original position */ + return EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, restorePos); +} + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * SaveFmtChunk() + *---------------------------------------------------------------------------- + * Purpose: + * Save the fmt chunk for the MMAPI library + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 fmtSize) +{ + EAS_RESULT result; + EAS_I32 pos; + EAS_I32 count; + + /* save current file position */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS) + return result; + + /* allocate a chunk of memory */ + pWaveData->fmtChunk = EAS_HWMalloc(pEASData->hwInstData, fmtSize); + if (!pWaveData->fmtChunk) + return EAS_ERROR_MALLOC_FAILED; + + /* read the fmt chunk into memory */ + if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, pWaveData->fmtChunk, fmtSize, &count)) != EAS_SUCCESS) + return result; + if (count != fmtSize) + return EAS_ERROR_FILE_READ_FAILED; + + /* restore file position */ + return EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos); +} +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefile.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefile.h new file mode 100755 index 0000000..f8814a8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefile.h @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefile.h + * + * Contents and purpose: + * Static data block for wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 439 $ + * $Date: 2006-10-26 11:53:18 -0700 (Thu, 26 Oct 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WAVEFILE_H +#define _EAS_WAVEFILE_H + +#include "eas_data.h" +#include "eas_pcm.h" + +/*---------------------------------------------------------------------------- + * + * S_WAVE_STATE + * + * This structure contains the WAVE file parser state information + *---------------------------------------------------------------------------- +*/ +typedef struct s_wave_state_tag +{ + EAS_FILE_HANDLE fileHandle; + EAS_PCM_HANDLE streamHandle; + S_METADATA_CB metadata; + EAS_U32 time; + EAS_I32 fileOffset; + EAS_I32 audioOffset; + EAS_I32 mediaLength; + EAS_U32 audioSize; + EAS_U32 flags; + EAS_I16 fileType; +#ifdef MMAPI_SUPPORT + EAS_VOID_PTR fmtChunk; +#endif + EAS_I32 infoChunkPos; + EAS_I32 infoChunkSize; +} S_WAVE_STATE; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefiledata.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefiledata.c new file mode 100755 index 0000000..c224a6c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wavefiledata.c @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefiledata.c + * + * Contents and purpose: + * Static data block for wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_wavefile.h" + +S_WAVE_STATE eas_WaveData; + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wt_IPC_frame.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wt_IPC_frame.h new file mode 100755 index 0000000..29d77aa --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wt_IPC_frame.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wt_IPC_frame.h + * + * Contents and purpose: + * This module contains data definitions for the interprocessor + * communications framework for a split-architecture synthesizer. + * + * This sample version writes IPC data to a file that can be used + * as a test vector for the DSP simulator. For a real-time system + * the file I/O is replaced with an IPC protocol in the hardware. + * + * Synchronization with the DSP is accomplished at the API level, + * i.e. the host code should call EAS_Render when it is ready to + * buffer another block of data for transmission to the DSP. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 818 $ + * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WT_IPC_FRAME_H +#define _EAS_WT_IPC_FRAME_H + +/*---------------------------------------------------------------------------- + * S_WT_FRAME + * + * This structure contains the common parameters that are updated + *for each frame of audio. + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_frame_tag +{ + EAS_I32 gainTarget; + EAS_I32 phaseIncrement; + +#if defined(_FILTER_ENABLED) + EAS_I32 k; + EAS_I32 b1; + EAS_I32 b2; +#endif +} S_WT_FRAME; + +/*---------------------------------------------------------------------------- + * S_WT_CONFIG + * + * This structure contains state data for the wavetable engine + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_config_tag +{ + EAS_U32 loopEnd; /* points to last PCM sample (not 1 beyond last) */ + EAS_U32 loopStart; /* points to first sample at start of loop */ + EAS_U32 phaseAccum; /* current sample, integer portion of phase */ + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I16 gainLeft; /* left channel gain */ + EAS_I16 gainRight; /* right channel gain */ +#endif + + EAS_I16 gain; /* current voice gain */ +} S_WT_CONFIG; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtengine.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtengine.c new file mode 100755 index 0000000..8407634 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtengine.c @@ -0,0 +1,661 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wtengine.c + * + * Contents and purpose: + * This file contains the critical synthesizer components that need to + * be optimized for best performance. + * + * Copyright Sonic Network Inc. 2004-2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 844 $ + * $Date: 2007-08-23 14:33:32 -0700 (Thu, 23 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/*------------------------------------ + * includes + *------------------------------------ +*/ +#include "eas_types.h" +#include "eas_math.h" +#include "eas_audioconst.h" +#include "eas_sndlib.h" +#include "eas_wtengine.h" +#include "eas_mixer.h" + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +extern void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); +extern void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); + +#if defined(_OPTIMIZED_MONO) +extern void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); +#else +extern void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); +extern void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); +#endif + +#if defined(_FILTER_ENABLED) +extern void WT_VoiceFilter (S_FILTER_CONTROL*pFilter, S_WT_INT_FRAME *pWTIntFrame); +#endif + +#if defined(_OPTIMIZED_MONO) || !defined(NATIVE_EAS_KERNEL) +/*---------------------------------------------------------------------------- + * WT_VoiceGain + *---------------------------------------------------------------------------- + * Purpose: + * Output gain for individual voice + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pWTVoice) reserved for future use */ +void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_I32 *pMixBuffer; + EAS_PCM *pInputBuffer; + EAS_I32 gain; + EAS_I32 gainIncrement; + EAS_I32 tmp0; + EAS_I32 tmp1; + EAS_I32 tmp2; + EAS_I32 numSamples; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I32 gainLeft, gainRight; +#endif + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pMixBuffer = pWTIntFrame->pMixBuffer; + pInputBuffer = pWTIntFrame->pAudioBuffer; + + /*lint -e{703} */ + gainIncrement = (pWTIntFrame->frame.gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + if (gainIncrement < 0) + gainIncrement++; + /*lint -e{703} */ + gain = pWTIntFrame->prevGain << 16; + +#if (NUM_OUTPUT_CHANNELS == 2) + gainLeft = pWTVoice->gainLeft; + gainRight = pWTVoice->gainRight; +#endif + + while (numSamples--) { + + /* incremental gain step to prevent zipper noise */ + tmp0 = *pInputBuffer++; + gain += gainIncrement; + /*lint -e{704} */ + tmp2 = gain >> 16; + + /* scale sample by gain */ + tmp2 *= tmp0; + + + /* stereo output */ +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{704} */ + tmp2 = tmp2 >> 14; + + /* get the current sample in the final mix buffer */ + tmp1 = *pMixBuffer; + + /* left channel */ + tmp0 = tmp2 * gainLeft; + /*lint -e{704} */ + tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; + tmp1 += tmp0; + *pMixBuffer++ = tmp1; + + /* get the current sample in the final mix buffer */ + tmp1 = *pMixBuffer; + + /* right channel */ + tmp0 = tmp2 * gainRight; + /*lint -e{704} */ + tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; + tmp1 += tmp0; + *pMixBuffer++ = tmp1; + + /* mono output */ +#else + + /* get the current sample in the final mix buffer */ + tmp1 = *pMixBuffer; + /*lint -e{704} */ + tmp2 = tmp2 >> (NUM_MIXER_GUARD_BITS - 1); + tmp1 += tmp2; + *pMixBuffer++ = tmp1; +#endif + + } +} +#endif + +#ifndef NATIVE_EAS_KERNEL +/*---------------------------------------------------------------------------- + * WT_Interpolate + *---------------------------------------------------------------------------- + * Purpose: + * Interpolation engine for wavetable synth + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_PCM *pOutputBuffer; + EAS_I32 phaseInc; + EAS_I32 phaseFrac; + EAS_I32 acc0; + const EAS_SAMPLE *pSamples; + const EAS_SAMPLE *loopEnd; + EAS_I32 samp1; + EAS_I32 samp2; + EAS_I32 numSamples; + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pOutputBuffer = pWTIntFrame->pAudioBuffer; + + loopEnd = (const EAS_SAMPLE*) pWTVoice->loopEnd + 1; + pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; + /*lint -e{713} truncation is OK */ + phaseFrac = pWTVoice->phaseFrac; + phaseInc = pWTIntFrame->frame.phaseIncrement; + + /* fetch adjacent samples */ +#if defined(_8_BIT_SAMPLES) + /*lint -e{701} */ + samp1 = pSamples[0] << 8; + /*lint -e{701} */ + samp2 = pSamples[1] << 8; +#else + samp1 = pSamples[0]; + samp2 = pSamples[1]; +#endif + + while (numSamples--) { + + /* linear interpolation */ + acc0 = samp2 - samp1; + acc0 = acc0 * phaseFrac; + /*lint -e{704} */ + acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); + + /* save new output sample in buffer */ + /*lint -e{704} */ + *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); + + /* increment phase */ + phaseFrac += phaseInc; + /*lint -e{704} */ + acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; + + /* next sample */ + if (acc0 > 0) { + + /* advance sample pointer */ + pSamples += acc0; + phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); + + /* check for loop end */ + acc0 = (EAS_I32) (pSamples - loopEnd); + if (acc0 >= 0) + pSamples = (const EAS_SAMPLE*) pWTVoice->loopStart + acc0; + + /* fetch new samples */ +#if defined(_8_BIT_SAMPLES) + /*lint -e{701} */ + samp1 = pSamples[0] << 8; + /*lint -e{701} */ + samp2 = pSamples[1] << 8; +#else + samp1 = pSamples[0]; + samp2 = pSamples[1]; +#endif + } + } + + /* save pointer and phase */ + pWTVoice->phaseAccum = (EAS_U32) pSamples; + pWTVoice->phaseFrac = (EAS_U32) phaseFrac; +} +#endif + +#ifndef NATIVE_EAS_KERNEL +/*---------------------------------------------------------------------------- + * WT_InterpolateNoLoop + *---------------------------------------------------------------------------- + * Purpose: + * Interpolation engine for wavetable synth + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_PCM *pOutputBuffer; + EAS_I32 phaseInc; + EAS_I32 phaseFrac; + EAS_I32 acc0; + const EAS_SAMPLE *pSamples; + EAS_I32 samp1; + EAS_I32 samp2; + EAS_I32 numSamples; + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pOutputBuffer = pWTIntFrame->pAudioBuffer; + + phaseInc = pWTIntFrame->frame.phaseIncrement; + pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; + phaseFrac = (EAS_I32)pWTVoice->phaseFrac; + + /* fetch adjacent samples */ +#if defined(_8_BIT_SAMPLES) + /*lint -e{701} */ + samp1 = pSamples[0] << 8; + /*lint -e{701} */ + samp2 = pSamples[1] << 8; +#else + samp1 = pSamples[0]; + samp2 = pSamples[1]; +#endif + + while (numSamples--) { + + + /* linear interpolation */ + acc0 = samp2 - samp1; + acc0 = acc0 * phaseFrac; + /*lint -e{704} */ + acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); + + /* save new output sample in buffer */ + /*lint -e{704} */ + *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); + + /* increment phase */ + phaseFrac += phaseInc; + /*lint -e{704} */ + acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; + + /* next sample */ + if (acc0 > 0) { + + /* advance sample pointer */ + pSamples += acc0; + phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); + + /* fetch new samples */ +#if defined(_8_BIT_SAMPLES) + /*lint -e{701} */ + samp1 = pSamples[0] << 8; + /*lint -e{701} */ + samp2 = pSamples[1] << 8; +#else + samp1 = pSamples[0]; + samp2 = pSamples[1]; +#endif + } + } + + /* save pointer and phase */ + pWTVoice->phaseAccum = (EAS_U32) pSamples; + pWTVoice->phaseFrac = (EAS_U32) phaseFrac; +} +#endif + +#if defined(_FILTER_ENABLED) && !defined(NATIVE_EAS_KERNEL) +/*---------------------------------------------------------------------------- + * WT_VoiceFilter + *---------------------------------------------------------------------------- + * Purpose: + * Implements a 2-pole filter + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void WT_VoiceFilter (S_FILTER_CONTROL *pFilter, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_PCM *pAudioBuffer; + EAS_I32 k; + EAS_I32 b1; + EAS_I32 b2; + EAS_I32 z1; + EAS_I32 z2; + EAS_I32 acc0; + EAS_I32 acc1; + EAS_I32 numSamples; + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pAudioBuffer = pWTIntFrame->pAudioBuffer; + + z1 = pFilter->z1; + z2 = pFilter->z2; + b1 = -pWTIntFrame->frame.b1; + + /*lint -e{702} */ + b2 = -pWTIntFrame->frame.b2 >> 1; + + /*lint -e{702} */ + k = pWTIntFrame->frame.k >> 1; + + while (numSamples--) + { + + /* do filter calculations */ + acc0 = *pAudioBuffer; + acc1 = z1 * b1; + acc1 += z2 * b2; + acc0 = acc1 + k * acc0; + z2 = z1; + + /*lint -e{702} */ + z1 = acc0 >> 14; + *pAudioBuffer++ = (EAS_I16) z1; + } + + /* save delay values */ + pFilter->z1 = (EAS_I16) z1; + pFilter->z2 = (EAS_I16) z2; +} +#endif + +/*---------------------------------------------------------------------------- + * WT_NoiseGenerator + *---------------------------------------------------------------------------- + * Purpose: + * Generate pseudo-white noise using PRNG and interpolation engine + * + * Inputs: + * + * Outputs: + * + * Notes: + * This output is scaled -12dB to prevent saturation in the filter. For a + * high quality synthesizer, the output can be set to full scale, however + * if the filter is used, it can overflow with certain coefficients. In this + * case, either a saturation operation should take in the filter before + * scaling back to 16 bits or the signal path should be increased to 18 bits + * or more. + *---------------------------------------------------------------------------- +*/ + void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) + { + EAS_PCM *pOutputBuffer; + EAS_I32 phaseInc; + EAS_I32 tmp0; + EAS_I32 tmp1; + EAS_I32 nInterpolatedSample; + EAS_I32 numSamples; + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pOutputBuffer = pWTIntFrame->pAudioBuffer; + phaseInc = pWTIntFrame->frame.phaseIncrement; + + /* get last two samples generated */ + /*lint -e{704} */ + tmp0 = (EAS_I32) (pWTVoice->phaseAccum) >> 18; + /*lint -e{704} */ + tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; + + /* generate a buffer of noise */ + while (numSamples--) { + nInterpolatedSample = MULT_AUDIO_COEF( tmp0, (PHASE_ONE - pWTVoice->phaseFrac)); + nInterpolatedSample += MULT_AUDIO_COEF( tmp1, pWTVoice->phaseFrac); + *pOutputBuffer++ = (EAS_PCM) nInterpolatedSample; + + /* update PRNG */ + pWTVoice->phaseFrac += (EAS_U32) phaseInc; + if (GET_PHASE_INT_PART(pWTVoice->phaseFrac)) { + tmp0 = tmp1; + pWTVoice->phaseAccum = pWTVoice->loopEnd; + pWTVoice->loopEnd = (5 * pWTVoice->loopEnd + 1); + tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; + pWTVoice->phaseFrac = GET_PHASE_FRAC_PART(pWTVoice->phaseFrac); + } + + } +} + +#ifndef _OPTIMIZED_MONO +/*---------------------------------------------------------------------------- + * WT_ProcessVoice + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the block processing for one voice. It is isolated + * from the main synth code to allow for various implementation-specific + * optimizations. It calls the interpolator, filter, and gain routines + * appropriate for a particular configuration. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + + /* use noise generator */ + if (pWTVoice->loopStart == WT_NOISE_GENERATOR) + WT_NoiseGenerator(pWTVoice, pWTIntFrame); + + /* generate interpolated samples for looped waves */ + else if (pWTVoice->loopStart != pWTVoice->loopEnd) + WT_Interpolate(pWTVoice, pWTIntFrame); + + /* generate interpolated samples for unlooped waves */ + else + { + WT_InterpolateNoLoop(pWTVoice, pWTIntFrame); + } + +#ifdef _FILTER_ENABLED + if (pWTIntFrame->frame.k != 0) + WT_VoiceFilter(&pWTVoice->filter, pWTIntFrame); +#endif + +//2 TEST NEW MIXER FUNCTION +#ifdef UNIFIED_MIXER + { + EAS_I32 gainLeft, gainIncLeft; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I32 gainRight, gainIncRight; +#endif + + gainLeft = (pWTIntFrame->prevGain * pWTVoice->gainLeft) << 1; + gainIncLeft = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainLeft) << 1) - gainLeft) >> SYNTH_UPDATE_PERIOD_IN_BITS; + +#if (NUM_OUTPUT_CHANNELS == 2) + gainRight = (pWTIntFrame->prevGain * pWTVoice->gainRight) << 1; + gainIncRight = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainRight) << 1) - gainRight) >> SYNTH_UPDATE_PERIOD_IN_BITS; + EAS_MixStream( + pWTIntFrame->pAudioBuffer, + pWTIntFrame->pMixBuffer, + pWTIntFrame->numSamples, + gainLeft, + gainRight, + gainIncLeft, + gainIncRight, + MIX_FLAGS_STEREO_OUTPUT); + +#else + EAS_MixStream( + pWTIntFrame->pAudioBuffer, + pWTIntFrame->pMixBuffer, + pWTIntFrame->numSamples, + gainLeft, + 0, + gainIncLeft, + 0, + 0); +#endif + } + +#else + /* apply gain, and left and right gain */ + WT_VoiceGain(pWTVoice, pWTIntFrame); +#endif +} +#endif + +#if defined(_OPTIMIZED_MONO) && !defined(NATIVE_EAS_KERNEL) +/*---------------------------------------------------------------------------- + * WT_InterpolateMono + *---------------------------------------------------------------------------- + * Purpose: + * A C version of the sample interpolation + gain routine, optimized for mono. + * It's not pretty, but it matches the assembly code exactly. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_I32 *pMixBuffer; + const EAS_I8 *pLoopEnd; + const EAS_I8 *pCurrentPhaseInt; + EAS_I32 numSamples; + EAS_I32 gain; + EAS_I32 gainIncrement; + EAS_I32 currentPhaseFrac; + EAS_I32 phaseInc; + EAS_I32 tmp0; + EAS_I32 tmp1; + EAS_I32 tmp2; + EAS_I8 *pLoopStart; + + numSamples = pWTIntFrame->numSamples; + pMixBuffer = pWTIntFrame->pMixBuffer; + + /* calculate gain increment */ + gainIncrement = (pWTIntFrame->gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + if (gainIncrement < 0) + gainIncrement++; + gain = pWTIntFrame->prevGain << 16; + + pCurrentPhaseInt = pWTVoice->pPhaseAccum; + currentPhaseFrac = pWTVoice->phaseFrac; + phaseInc = pWTIntFrame->phaseIncrement; + + pLoopStart = pWTVoice->pLoopStart; + pLoopEnd = pWTVoice->pLoopEnd + 1; + +InterpolationLoop: + tmp0 = (EAS_I32)(pCurrentPhaseInt - pLoopEnd); + if (tmp0 >= 0) + pCurrentPhaseInt = pLoopStart + tmp0; + + tmp0 = *pCurrentPhaseInt; + tmp1 = *(pCurrentPhaseInt + 1); + + tmp2 = phaseInc + currentPhaseFrac; + + tmp1 = tmp1 - tmp0; + tmp1 = tmp1 * currentPhaseFrac; + + tmp1 = tmp0 + (tmp1 >> NUM_EG1_FRAC_BITS); + + pCurrentPhaseInt += (tmp2 >> NUM_PHASE_FRAC_BITS); + currentPhaseFrac = tmp2 & PHASE_FRAC_MASK; + + gain += gainIncrement; + tmp2 = (gain >> SYNTH_UPDATE_PERIOD_IN_BITS); + + tmp0 = *pMixBuffer; + tmp2 = tmp1 * tmp2; + tmp2 = (tmp2 >> 9); + tmp0 = tmp2 + tmp0; + *pMixBuffer++ = tmp0; + + numSamples--; + if (numSamples) + goto InterpolationLoop; + + pWTVoice->pPhaseAccum = pCurrentPhaseInt; + pWTVoice->phaseFrac = currentPhaseFrac; + /*lint -e{702} */ + pWTVoice->gain = (EAS_I16)(gain >> SYNTH_UPDATE_PERIOD_IN_BITS); +} +#endif + +#ifdef _OPTIMIZED_MONO +/*---------------------------------------------------------------------------- + * WT_ProcessVoice + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the block processing for one voice. It is isolated + * from the main synth code to allow for various implementation-specific + * optimizations. It calls the interpolator, filter, and gain routines + * appropriate for a particular configuration. + * + * Inputs: + * + * Outputs: + * + * Notes: + * This special version works handles an optimized mono-only signal + * without filters + *---------------------------------------------------------------------------- +*/ +void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + + /* use noise generator */ + if (pWTVoice->loopStart== WT_NOISE_GENERATOR) + { + WT_NoiseGenerator(pWTVoice, pWTIntFrame); + WT_VoiceGain(pWTVoice, pWTIntFrame); + } + + /* or generate interpolated samples */ + else + { + WT_InterpolateMono(pWTVoice, pWTIntFrame); + } +} +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtengine.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtengine.h new file mode 100755 index 0000000..bba7a5e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtengine.h @@ -0,0 +1,171 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wtengine.h + * + * Contents and purpose: + * This file defines the interface for wavetable synthesis engine + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 818 $ + * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WTENGINE_H +#define _EAS_WTENGINE_H + +/* option sanity check */ +#if defined(_OPTIMIZED_MONO) && defined(_FILTER_ENABLED) +#error "Incompatible build settings: _OPTIMIZED_MONO cannot be used with _FILTER_ENABLED" +#endif + +#if defined(_OPTIMIZED_MONO) && (NUM_OUTPUT_CHANNELS != 1) +#error "Incompatible build settings: _OPTIMIZED_MONO can only be used with NUM_OUTPUT_CHANNELS = 1" +#endif + +#include "eas_wt_IPC_frame.h" + +/*---------------------------------------------------------------------------- + * defines + *---------------------------------------------------------------------------- +*/ +#define WT_NOISE_GENERATOR 0xffffffff + +/*---------------------------------------------------------------------------- + * typedefs + *---------------------------------------------------------------------------- +*/ + +/*---------------------------------------------------------------------------- + * S_WT_INT_FRAME + * + * This structure includes S_WT_FRAME plus the bus mixing + * parameters for the internal voices. + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_int_frame_tag +{ + S_WT_FRAME frame; + EAS_PCM *pAudioBuffer; + EAS_I32 *pMixBuffer; + EAS_I32 numSamples; + EAS_I32 prevGain; +} S_WT_INT_FRAME; + +#if defined(_FILTER_ENABLED) +/*---------------------------------------------------------------------------- + * S_FILTER_CONTROL data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_filter_control_tag +{ + EAS_I16 z1; /* 1 sample delay state variable */ + EAS_I16 z2; /* 2 sample delay state variable */ +} S_FILTER_CONTROL; +#endif + +/*------------------------------------ + * S_LFO_CONTROL data structure + *------------------------------------ +*/ +typedef struct s_lfo_control_tag +{ + EAS_I16 lfoValue; /* LFO current output value */ + EAS_I16 lfoPhase; /* LFO current phase */ +} S_LFO_CONTROL; + +/* bit definitions for S_WT_VOICE:flags */ +#define WT_FLAGS_ADPCM_NIBBLE 1 /* high/low nibble flag */ +#define WT_FLAGS_ADPCM_READY 2 /* first 2 samples are decoded */ +#define WT_FLAGS_USE_ADPCM 4 /* sample is ADPCM encoded */ + +/* eg1State and eg2State */ +typedef enum { + eEnvelopeStateInit = 0, + eEnvelopeStateDelay, + eEnvelopeStateAttack, + eEnvelopeStateHold, + eEnvelopeStateDecay, + eEnvelopeStateSustain, + eEnvelopeStateRelease, + eEnvelopeStateMuting, + eEnvelopeStateMuted, + eEnvelopeStateInvalid /* should never be in this state! */ +} E_ENVELOPE_STATE; + +#define DEFAULT_EG1_STATE eEnvelopeStateAttack +#define DEFAULT_EG1_VALUE 0 +#define DEFAULT_EG1_INCREMENT 0 +#define DEFAULT_EG2_STATE eEnvelopeStateAttack +#define DEFAULT_EG2_VALUE 0 +#define DEFAULT_EG2_INCREMENT 0 + +/*---------------------------------------------------------------------------- + * S_WT_VOICE + * + * This structure contains state data for the wavetable engine + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_voice_tag +{ + EAS_U32 loopEnd; /* points to last PCM sample (not 1 beyond last) */ + EAS_U32 loopStart; /* points to first sample at start of loop */ + EAS_U32 phaseAccum; /* current sample, integer portion of phase */ + EAS_U32 phaseFrac; /* fractional portion of phase */ + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I16 gainLeft; /* current gain, left ch */ + EAS_I16 gainRight; /* current gain, right ch */ +#endif + +#if defined(_FILTER_ENABLED) + S_FILTER_CONTROL filter; /* low pass filter */ +#endif + + S_LFO_CONTROL modLFO; /* modulator LFO */ + +#ifdef DLS_SYNTHESIZER + S_LFO_CONTROL vibLFO; /* vibrato LFO */ +#endif + + /* envelope control */ + EAS_I16 eg1Value; + EAS_I16 eg2Value; + EAS_I16 eg1Increment; + EAS_I16 eg2Increment; + EAS_U8 eg1State; + EAS_U8 eg2State; + + EAS_U16 artIndex; /* index to articulation params */ + +} S_WT_VOICE; + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update); +void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); + +#ifdef EAS_SPLIT_WT_SYNTH +void WTE_ConfigVoice (EAS_I32 voiceNum, S_WT_CONFIG *pWTConfig, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +void WTE_ProcessVoice (EAS_I32 voiceNum, S_WT_FRAME *pWTParams, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +#endif + +#endif diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtsynth.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtsynth.c new file mode 100755 index 0000000..788b34f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtsynth.c @@ -0,0 +1,1251 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wtsynth.c + * + * Contents and purpose: + * Implements the synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_math.h" +#include "eas_synth_protos.h" +#include "eas_wtsynth.h" +#include "eas_pan.h" + +#ifdef DLS_SYNTHESIZER +#include "eas_dlssynth.h" +#endif + +#ifdef _METRICS_ENABLED +#include "eas_perf.h" +#endif + +/* local prototypes */ +static EAS_RESULT WT_Initialize(S_VOICE_MGR *pVoiceMgr); +static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); +static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); +static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); +static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); +static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents); +static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain); +static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv); +static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv); + +#ifdef EAS_SPLIT_WT_SYNTH +extern EAS_BOOL WTE_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +extern EAS_BOOL WTE_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain); +#endif + +#ifdef _FILTER_ENABLED +static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt); +#endif + +#ifdef _STATS +extern double statsPhaseIncrement; +extern double statsMaxPhaseIncrement; +extern long statsPhaseSampleCount; +extern double statsSampleSize; +extern long statsSampleCount; +#endif + +/*---------------------------------------------------------------------------- + * Synthesizer interface + *---------------------------------------------------------------------------- +*/ + +const S_SYNTH_INTERFACE wtSynth = +{ + WT_Initialize, + WT_StartVoice, + WT_UpdateVoice, + WT_ReleaseVoice, + WT_MuteVoice, + WT_SustainPedal, + WT_UpdateChannel +}; + +#ifdef EAS_SPLIT_WT_SYNTH +const S_FRAME_INTERFACE wtFrameInterface = +{ + WTE_StartFrame, + WTE_EndFrame +}; +#endif + +/*---------------------------------------------------------------------------- + * WT_Initialize() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pVoice - pointer to voice to initialize + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WT_Initialize (S_VOICE_MGR *pVoiceMgr) +{ + EAS_INT i; + + for (i = 0; i < NUM_WT_VOICES; i++) + { + + pVoiceMgr->wtVoices[i].artIndex = DEFAULT_ARTICULATION_INDEX; + + pVoiceMgr->wtVoices[i].eg1State = DEFAULT_EG1_STATE; + pVoiceMgr->wtVoices[i].eg1Value = DEFAULT_EG1_VALUE; + pVoiceMgr->wtVoices[i].eg1Increment = DEFAULT_EG1_INCREMENT; + + pVoiceMgr->wtVoices[i].eg2State = DEFAULT_EG2_STATE; + pVoiceMgr->wtVoices[i].eg2Value = DEFAULT_EG2_VALUE; + pVoiceMgr->wtVoices[i].eg2Increment = DEFAULT_EG2_INCREMENT; + + /* left and right gain values are needed only if stereo output */ +#if (NUM_OUTPUT_CHANNELS == 2) + pVoiceMgr->wtVoices[i].gainLeft = DEFAULT_VOICE_GAIN; + pVoiceMgr->wtVoices[i].gainRight = DEFAULT_VOICE_GAIN; +#endif + + pVoiceMgr->wtVoices[i].phaseFrac = DEFAULT_PHASE_FRAC; + pVoiceMgr->wtVoices[i].phaseAccum = DEFAULT_PHASE_INT; + +#ifdef _FILTER_ENABLED + pVoiceMgr->wtVoices[i].filter.z1 = DEFAULT_FILTER_ZERO; + pVoiceMgr->wtVoices[i].filter.z2 = DEFAULT_FILTER_ZERO; +#endif + } + + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * WT_ReleaseVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being released. + * + * Inputs: + * pEASData - pointer to S_EAS_DATA + * pVoice - pointer to voice to release + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoice) used in some implementations */ +static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + S_WT_VOICE *pWTVoice; + const S_ARTICULATION *pArticulation; + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + DLS_ReleaseVoice(pVoiceMgr, pSynth, pVoice, voiceNum); + return; + } +#endif + + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pArticulation = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; + + /* release EG1 */ + pWTVoice->eg1State = eEnvelopeStateRelease; + pWTVoice->eg1Increment = pArticulation->eg1.releaseTime; + + /* + The spec says we should release EG2, but doing so with the current + voicing is causing clicks. This fix will need to be coordinated with + a new sound library release + */ + + /* release EG2 */ + pWTVoice->eg2State = eEnvelopeStateRelease; + pWTVoice->eg2Increment = pArticulation->eg2.releaseTime; +} + +/*---------------------------------------------------------------------------- + * WT_MuteVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being muted. + * + * Inputs: + * pVoice - pointer to voice to release + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pSynth) used in some implementations */ +static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + DLS_MuteVoice(pVoiceMgr, pSynth, pVoice, voiceNum); + return; + } +#endif + + /* clear deferred action flags */ + pVoice->voiceFlags &= + ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | + VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF | + VOICE_FLAG_DEFER_MUTE); + + /* set the envelope state */ + pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateMuted; + pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateMuted; +} + +/*---------------------------------------------------------------------------- + * WT_SustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is held due to sustain pedal + * + * Inputs: + * pVoice - pointer to voice to sustain + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pChannel) used in some implementations */ +static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) +{ + S_WT_VOICE *pWTVoice; + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + DLS_SustainPedal(pVoiceMgr, pSynth, pVoice, pChannel, voiceNum); + return; + } +#endif + + /* don't catch the voice if below the sustain level */ + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + if (pWTVoice->eg1Value < pSynth->pEAS->pArticulations[pWTVoice->artIndex].eg1.sustainLevel) + return; + + /* sustain flag is set, damper pedal is on */ + /* defer releasing this note until the damper pedal is off */ + pWTVoice->eg1State = eEnvelopeStateDecay; + pVoice->voiceState = eVoiceStatePlay; + + /* + because sustain pedal is on, this voice + should defer releasing its note + */ + pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_SustainPedal: defer note off because sustain pedal is on\n"); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * WT_StartVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the region for the given instrument using the midi key number + * and the RPN2 (coarse tuning) value. By using RPN2 as part of the + * region selection process, we reduce the amount a given sample has + * to be transposed by selecting the closest recorded root instead. + * + * This routine is the second half of SynthAssignRegion(). + * If the region was successfully found by SynthFindRegionIndex(), + * then assign the region's parameters to the voice. + * + * Setup and initialize the following voice parameters: + * m_nRegionIndex + * + * Inputs: + * pVoice - ptr to the voice we have assigned for this channel + * nRegionIndex - index of the region + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * success - could find and assign the region for this voice's note otherwise + * failure - could not find nor assign the region for this voice's note + * + * Side Effects: + * psSynthObject->m_sVoice[].m_nRegionIndex is assigned + * psSynthObject->m_sVoice[] parameters are assigned + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) +{ + S_WT_VOICE *pWTVoice; + const S_WT_REGION *pRegion; + const S_ARTICULATION *pArt; + S_SYNTH_CHANNEL *pChannel; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_INT pan; +#endif + +#ifdef EAS_SPLIT_WT_SYNTH + S_WT_CONFIG wtConfig; +#endif + + /* no samples have been synthesized for this note yet */ + pVoice->regionIndex = regionIndex; + pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + + /* get the articulation index for this region */ + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pChannel = &pSynth->channels[pVoice->channel & 15]; + + /* update static channel parameters */ + if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS) + WT_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15); + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + return DLS_StartVoice(pVoiceMgr, pSynth, pVoice, voiceNum, regionIndex); +#endif + + pRegion = &(pSynth->pEAS->pWTRegions[regionIndex]); + pWTVoice->artIndex = pRegion->artIndex; + +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ } +#endif + + pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; + + /* MIDI note on puts this voice into attack state */ + pWTVoice->eg1State = eEnvelopeStateAttack; + pWTVoice->eg1Value = 0; + pWTVoice->eg1Increment = pArt->eg1.attackTime; + pWTVoice->eg2State = eEnvelopeStateAttack; + pWTVoice->eg2Value = 0; + pWTVoice->eg2Increment = pArt->eg2.attackTime; + + /* init the LFO */ + pWTVoice->modLFO.lfoValue = 0; + pWTVoice->modLFO.lfoPhase = -pArt->lfoDelay; + + pVoice->gain = 0; + +#if (NUM_OUTPUT_CHANNELS == 2) + /* + Get the Midi CC10 pan value for this voice's channel + convert the pan value to an "angle" representation suitable for + our sin, cos calculator. This representation is NOT necessarily the same + as the transform in the GM manuals because of our sin, cos calculator. + "angle" = (CC10 - 64)/128 + */ + pan = (EAS_INT) pSynth->channels[pVoice->channel & 15].pan - 64; + pan += pArt->pan; + EAS_CalcPanControl(pan, &pWTVoice->gainLeft, &pWTVoice->gainRight); +#endif + +#ifdef _FILTER_ENABLED + /* clear out the filter states */ + pWTVoice->filter.z1 = 0; + pWTVoice->filter.z2 = 0; +#endif + + /* if this wave is to be generated using noise generator */ + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_USE_WAVE_GENERATOR) + { + pWTVoice->phaseAccum = 4574296; + pWTVoice->loopStart = WT_NOISE_GENERATOR; + pWTVoice->loopEnd = 4574295; + } + + /* normal sample */ + else + { + +#ifdef EAS_SPLIT_WT_SYNTH + if (voiceNum < NUM_PRIMARY_VOICES) + pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; + else + pWTVoice->phaseAccum = pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; +#else + pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; +#endif + + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED) + { + pWTVoice->loopStart = pWTVoice->phaseAccum + pRegion->loopStart; + pWTVoice->loopEnd = pWTVoice->phaseAccum + pRegion->loopEnd - 1; + } + else + pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pEAS->pSampleLen[pRegion->waveIndex] - 1; + } + +#ifdef EAS_SPLIT_WT_SYNTH + /* configure off-chip voices */ + if (voiceNum >= NUM_PRIMARY_VOICES) + { + wtConfig.phaseAccum = pWTVoice->phaseAccum; + wtConfig.loopStart = pWTVoice->loopStart; + wtConfig.loopEnd = pWTVoice->loopEnd; + wtConfig.gain = pVoice->gain; + +#if (NUM_OUTPUT_CHANNELS == 2) + wtConfig.gainLeft = pWTVoice->gainLeft; + wtConfig.gainRight = pWTVoice->gainRight; +#endif + + WTE_ConfigVoice(voiceNum - NUM_PRIMARY_VOICES, &wtConfig, pVoiceMgr->pFrameBuffer); + } +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WT_CheckSampleEnd + *---------------------------------------------------------------------------- + * Purpose: + * Check for end of sample and calculate number of samples to synthesize + * + * Inputs: + * + * Outputs: + * + * Notes: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update) +{ + EAS_U32 endPhaseAccum; + EAS_U32 endPhaseFrac; + EAS_I32 numSamples; + EAS_BOOL done = EAS_FALSE; + + /* check to see if we hit the end of the waveform this time */ + /*lint -e{703} use shift for performance */ + endPhaseFrac = pWTVoice->phaseFrac + (pWTIntFrame->frame.phaseIncrement << SYNTH_UPDATE_PERIOD_IN_BITS); + endPhaseAccum = pWTVoice->phaseAccum + GET_PHASE_INT_PART(endPhaseFrac); + if (endPhaseAccum >= pWTVoice->loopEnd) + { + /* calculate how far current ptr is from end */ + numSamples = (EAS_I32) (pWTVoice->loopEnd - pWTVoice->phaseAccum); + + /* now account for the fractional portion */ + /*lint -e{703} use shift for performance */ + numSamples = (EAS_I32) ((numSamples << NUM_PHASE_FRAC_BITS) - pWTVoice->phaseFrac); + pWTIntFrame->numSamples = 1 + (numSamples / pWTIntFrame->frame.phaseIncrement); + + /* sound will be done this frame */ + done = EAS_TRUE; + } + + /* update data for off-chip synth */ + if (update) + { + pWTVoice->phaseFrac = endPhaseFrac; + pWTVoice->phaseAccum = endPhaseAccum; + } + + return done; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize a block of samples for the given voice. + * Use linear interpolation. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples) +{ + S_WT_VOICE *pWTVoice; + S_WT_INT_FRAME intFrame; + S_SYNTH_CHANNEL *pChannel; + const S_WT_REGION *pWTRegion; + const S_ARTICULATION *pArt; + EAS_I32 temp; + EAS_BOOL done; + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + return DLS_UpdateVoice(pVoiceMgr, pSynth, pVoice, voiceNum, pMixBuffer, numSamples); +#endif + + /* establish pointers to critical data */ + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pWTRegion = &pSynth->pEAS->pWTRegions[pVoice->regionIndex & REGION_INDEX_MASK]; + pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; + pChannel = &pSynth->channels[pVoice->channel & 15]; + intFrame.prevGain = pVoice->gain; + + /* update the envelopes */ + WT_UpdateEG1(pWTVoice, &pArt->eg1); + WT_UpdateEG2(pWTVoice, &pArt->eg2); + + /* update the LFO */ + WT_UpdateLFO(&pWTVoice->modLFO, pArt->lfoFreq); + +#ifdef _FILTER_ENABLED + /* calculate filter if library uses filter */ + if (pSynth->pEAS->libAttr & LIB_FORMAT_FILTER_ENABLED) + WT_UpdateFilter(pWTVoice, &intFrame, pArt); + else + intFrame.frame.k = 0; +#endif + + /* update the gain */ + intFrame.frame.gainTarget = WT_UpdateGain(pVoice, pWTVoice, pArt, pChannel, pWTRegion->gain); + + /* calculate base pitch*/ + temp = pChannel->staticPitch + pWTRegion->tuning; + + /* include global transpose */ + if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) + temp += pVoice->note * 100; + else + temp += (pVoice->note + pSynth->globalTranspose) * 100; + intFrame.frame.phaseIncrement = WT_UpdatePhaseInc(pWTVoice, pArt, pChannel, temp); + + /* call into engine to generate samples */ + intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer; + intFrame.pMixBuffer = pMixBuffer; + intFrame.numSamples = numSamples; + + /* check for end of sample */ + if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd)) + done = WT_CheckSampleEnd(pWTVoice, &intFrame, (EAS_BOOL) (voiceNum >= NUM_PRIMARY_VOICES)); + else + done = EAS_FALSE; + +#ifdef EAS_SPLIT_WT_SYNTH + if (voiceNum < NUM_PRIMARY_VOICES) + { +#ifndef _SPLIT_WT_TEST_HARNESS + WT_ProcessVoice(pWTVoice, &intFrame); +#endif + } + else + WTE_ProcessVoice(voiceNum - NUM_PRIMARY_VOICES, &intFrame.frame, pVoiceMgr->pFrameBuffer); +#else + WT_ProcessVoice(pWTVoice, &intFrame); +#endif + + /* clear flag */ + pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + + /* if voice has finished, set flag for voice manager */ + if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted)) + done = EAS_TRUE; + + /* if the update interval has elapsed, then force the current gain to the next + * gain since we never actually reach the next gain when ramping -- we just get + * very close to the target gain. + */ + pVoice->gain = (EAS_I16) intFrame.frame.gainTarget; + + return done; +} + +/*---------------------------------------------------------------------------- + * WT_UpdatePhaseInc() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the phase increment + * + * Inputs: + * pVoice - pointer to the voice being updated + * psRegion - pointer to the region + * psArticulation - pointer to the articulation + * nChannelPitchForThisVoice - the portion of the pitch that is fixed for this + * voice during the duration of this synthesis + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * set the phase increment for this voice + *---------------------------------------------------------------------------- +*/ +static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents) +{ + EAS_I32 temp; + + /*pitchCents due to CC1 = LFO * (CC1 / 128) * DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS */ + temp = MULT_EG1_EG1(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS, + ((pChannel->modWheel) << (NUM_EG1_FRAC_BITS -7))); + + /* pitchCents due to channel pressure = LFO * (channel pressure / 128) * DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS */ + temp += MULT_EG1_EG1(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS, + ((pChannel->channelPressure) << (NUM_EG1_FRAC_BITS -7))); + + /* now multiply the (channel pressure + CC1) pitch values by the LFO value */ + temp = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, temp); + + /* + add in the LFO pitch due to + channel pressure and CC1 along with + the LFO pitch, the EG2 pitch, and the + "static" pitch for this voice on this channel + */ + temp += pitchCents + + (MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToPitch)) + + (MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToPitch)); + + /* convert from cents to linear phase increment */ + return EAS_Calculate2toX(temp); +} + +/*---------------------------------------------------------------------------- + * WT_UpdateChannel() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate and assign static channel parameters + * These values only need to be updated if one of the controller values + * for this channel changes + * + * Inputs: + * nChannel - channel to update + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - the given channel's static gain and static pitch are updated + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + EAS_I32 staticGain; + EAS_I32 pitchBend; + S_SYNTH_CHANNEL *pChannel; + + pChannel = &pSynth->channels[channel]; + + /* + nChannelGain = (CC7 * CC11)^2 * master volume + where CC7 == 100 by default, CC11 == 127, master volume == 32767 + */ + staticGain = MULT_EG1_EG1((pChannel->volume) << (NUM_EG1_FRAC_BITS - 7), + (pChannel->expression) << (NUM_EG1_FRAC_BITS - 7)); + + /* staticGain has to be squared */ + staticGain = MULT_EG1_EG1(staticGain, staticGain); + + pChannel->staticGain = (EAS_I16) MULT_EG1_EG1(staticGain, pSynth->masterVolume); + + /* + calculate pitch bend: RPN0 * ((2*pitch wheel)/16384 -1) + However, if we use the EG1 macros, remember that EG1 has a full + scale value of 32768 (instead of 16384). So instead of multiplying + by 2, multiply by 4 (left shift by 2), and subtract by 32768 instead + of 16384. This utilizes the fact that the EG1 macro places a binary + point 15 places to the left instead of 14 places. + */ + /*lint -e{703} */ + pitchBend = + (((EAS_I32)(pChannel->pitchBend) << 2) + - 32768); + + pChannel->staticPitch = + MULT_EG1_EG1(pitchBend, pChannel->pitchBendSensitivity); + + /* if this is not a drum channel, then add in the per-channel tuning */ + if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL)) + pChannel->staticPitch += pChannel->finePitch + (pChannel->coarsePitch * 100); + + /* clear update flag */ + pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + return; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateGain() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate and assign static voice parameters as part of WT_UpdateVoice() + * + * Inputs: + * pVoice - ptr to the synth voice that we want to synthesize + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - various voice parameters are calculated and assigned + * + *---------------------------------------------------------------------------- +*/ +static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain) +{ + EAS_I32 lfoGain; + EAS_I32 temp; + + /* + If this voice was stolen, then the velocity is actually + for the new note, not the note that we are currently ramping down. + So we really shouldn't use this velocity. However, that would require + more memory to store the velocity value, and the improvement may + not be sufficient to warrant the added memory. + */ + /* velocity is fixed at note start for a given voice and must be squared */ + temp = (pVoice->velocity) << (NUM_EG1_FRAC_BITS - 7); + temp = MULT_EG1_EG1(temp, temp); + + /* region gain is fixed as part of the articulation */ + temp = MULT_EG1_EG1(temp, gain); + + /* include the channel gain */ + temp = MULT_EG1_EG1(temp, pChannel->staticGain); + + /* calculate LFO gain using an approximation for 10^x */ + lfoGain = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToGain); + lfoGain = MULT_EG1_EG1(lfoGain, LFO_GAIN_TO_CENTS); + + /* convert from a dB-like value to linear gain */ + lfoGain = EAS_Calculate2toX(lfoGain); + temp = MULT_EG1_EG1(temp, lfoGain); + + /* calculate the voice's gain */ + temp = (EAS_I16)MULT_EG1_EG1(temp, pWTVoice->eg1Value); + + return temp; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateEG1() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the EG1 envelope for the given voice (but do not update any + * state) + * + * Inputs: + * pVoice - ptr to the voice whose envelope we want to update + * nVoice - this voice's number - used only for debug + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * nValue - the envelope value + * + * Side Effects: + * - updates EG1 state value for the given voice + *---------------------------------------------------------------------------- +*/ +static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv) +{ + EAS_I32 temp; + + switch (pWTVoice->eg1State) + { + case eEnvelopeStateAttack: + temp = pWTVoice->eg1Value + pWTVoice->eg1Increment; + + /* check if we have reached peak amplitude */ + if (temp >= SYNTH_FULL_SCALE_EG1_GAIN) + { + /* limit the volume */ + temp = SYNTH_FULL_SCALE_EG1_GAIN; + + /* prepare to move to decay state */ + pWTVoice->eg1State = eEnvelopeStateDecay; + pWTVoice->eg1Increment = pEnv->decayTime; + } + + break; + + /* exponential decay */ + case eEnvelopeStateDecay: + temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment); + + /* check if we have reached sustain level */ + if (temp <= pEnv->sustainLevel) + { + /* enforce the sustain level */ + temp = pEnv->sustainLevel; + + /* if sustain level is zero, skip sustain & release the voice */ + if (temp > 0) + pWTVoice->eg1State = eEnvelopeStateSustain; + + /* move to sustain state */ + else + pWTVoice->eg1State = eEnvelopeStateMuted; + } + + break; + + case eEnvelopeStateSustain: + return; + + case eEnvelopeStateRelease: + temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment); + + /* if we hit zero, this voice isn't contributing any audio */ + if (temp <= 0) + { + temp = 0; + pWTVoice->eg1State = eEnvelopeStateMuted; + } + break; + + /* voice is muted, set target to zero */ + case eEnvelopeStateMuted: + temp = 0; + break; + + case eEnvelopeStateInvalid: + default: + temp = 0; +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG1: error, %d is an unrecognized state\n", + pWTVoice->eg1State); */ } +#endif + break; + + } + + pWTVoice->eg1Value = (EAS_I16) temp; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateEG2() + *---------------------------------------------------------------------------- + * Purpose: + * Update the EG2 envelope for the given voice + * + * Inputs: + * pVoice - ptr to the voice whose envelope we want to update + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - updates EG2 values for the given voice + *---------------------------------------------------------------------------- +*/ + +static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv) +{ + EAS_I32 temp; + + switch (pWTVoice->eg2State) + { + case eEnvelopeStateAttack: + temp = pWTVoice->eg2Value + pWTVoice->eg2Increment; + + /* check if we have reached peak amplitude */ + if (temp >= SYNTH_FULL_SCALE_EG1_GAIN) + { + /* limit the volume */ + temp = SYNTH_FULL_SCALE_EG1_GAIN; + + /* prepare to move to decay state */ + pWTVoice->eg2State = eEnvelopeStateDecay; + + pWTVoice->eg2Increment = pEnv->decayTime; + } + + break; + + /* implement linear pitch decay in cents */ + case eEnvelopeStateDecay: + temp = pWTVoice->eg2Value -pWTVoice->eg2Increment; + + /* check if we have reached sustain level */ + if (temp <= pEnv->sustainLevel) + { + /* enforce the sustain level */ + temp = pEnv->sustainLevel; + + /* prepare to move to sustain state */ + pWTVoice->eg2State = eEnvelopeStateSustain; + } + break; + + case eEnvelopeStateSustain: + return; + + case eEnvelopeStateRelease: + temp = pWTVoice->eg2Value - pWTVoice->eg2Increment; + + if (temp <= 0) + { + temp = 0; + pWTVoice->eg2State = eEnvelopeStateMuted; + } + + break; + + /* voice is muted, set target to zero */ + case eEnvelopeStateMuted: + temp = 0; + break; + + case eEnvelopeStateInvalid: + default: + temp = 0; +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG2: error, %d is an unrecognized state\n", + pWTVoice->eg2State); */ } +#endif + break; + } + + pWTVoice->eg2Value = (EAS_I16) temp; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateLFO () + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the LFO for the given voice + * + * Inputs: + * pLFO - ptr to the LFO data + * phaseInc - phase increment + * + * Outputs: + * + * Side Effects: + * - updates LFO values for the given voice + *---------------------------------------------------------------------------- +*/ +void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc) +{ + + /* To save memory, if m_nPhaseValue is negative, we are in the + * delay phase, and m_nPhaseValue represents the time left + * in the delay. + */ + if (pLFO->lfoPhase < 0) + { + pLFO->lfoPhase++; + return; + } + + /* calculate LFO output from phase value */ + /*lint -e{701} Use shift for performance */ + pLFO->lfoValue = (EAS_I16) (pLFO->lfoPhase << 2); + /*lint -e{502} */ + if ((pLFO->lfoPhase > 0x1fff) && (pLFO->lfoPhase < 0x6000)) + pLFO->lfoValue = ~pLFO->lfoValue; + + /* update LFO phase */ + pLFO->lfoPhase = (pLFO->lfoPhase + phaseInc) & 0x7fff; +} + +#ifdef _FILTER_ENABLED +/*---------------------------------------------------------------------------- + * WT_UpdateFilter() + *---------------------------------------------------------------------------- + * Purpose: + * Update the Filter parameters + * + * Inputs: + * pVoice - ptr to the voice whose filter we want to update + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - updates Filter values for the given voice + *---------------------------------------------------------------------------- +*/ +static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt) +{ + EAS_I32 cutoff; + + /* no need to calculate filter coefficients if it is bypassed */ + if (pArt->filterCutoff == DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY) + { + pIntFrame->frame.k = 0; + return; + } + + /* determine the dynamic cutoff frequency */ + cutoff = MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToFc); + cutoff += pArt->filterCutoff; + + /* subtract the A5 offset and the sampling frequency */ + cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS; + + /* limit the cutoff frequency */ + if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS) + cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS; + else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS) + cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS; + + WT_SetFilterCoeffs(pIntFrame, cutoff, pArt->filterQ); +} +#endif + +#if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER) +/*---------------------------------------------------------------------------- + * coef + *---------------------------------------------------------------------------- + * Table of filter coefficients for low-pass filter + *---------------------------------------------------------------------------- + * + * polynomial coefficients are based on 8kHz sampling frequency + * filter coef b2 = k2 = k2g0*k^0 + k2g1*k^1*(2^x) + k2g2*k^2*(2^x) + * + *where k2g0, k2g1, k2g2 are from the truncated power series expansion on theta + *(k*2^x = theta, but we incorporate the k along with the k2g0, k2g1, k2g2) + *note: this is a power series in 2^x, not k*2^x + *where k = (2*pi*440)/8kHz == convert octaves to radians + * + * so actually, the following coefs listed as k2g0, k2g1, k2g2 are really + * k2g0*k^0 = k2g0 + * k2g1*k^1 + * k2g2*k^2 + * + * + * filter coef n1 = numerator = n1g0*k^0 + n1g1*k^1*(2^x) + n1g2*k^2*(2^x) + n1g3*k^3*(2^x) + * + *where n1g0, n1g1, n1g2, n1g3 are from the truncated power series expansion on theta + *(k*2^x = theta, but we incorporate the k along with the n1g0, n1g1, n1g2, n2g3) + *note: this is a power series in 2^x, not k*2^x + *where k = (2*pi*440)/8kHz == convert octaves to radians + *we also include the optimization factor of 0.81 + * + * so actually, the following coefs listed as n1g0, n1g1, n1g2, n2g3 are really + * n1g0*k^0 = n1g0 + * n1g1*k^1 + * n1g2*k^2 + * n1g3*k^3 + * + * NOTE that n1g0 == n1g1 == 0, always, so we only need to store n1g2 and n1g3 + *---------------------------------------------------------------------------- +*/ + +static const EAS_I16 nk1g0 = -32768; +static const EAS_I16 nk1g2 = 1580; +static const EAS_I16 k2g0 = 32767; + +static const EAS_I16 k2g1[] = +{ + -11324, /* k2g1[0] = -0.3455751918948761 */ + -10387, /* k2g1[1] = -0.3169878073928751 */ + -9528, /* k2g1[2] = -0.29076528753345476 */ + -8740, /* k2g1[3] = -0.2667120011011279 */ + -8017, /* k2g1[4] = -0.24464850028971705 */ + -7353, /* k2g1[5] = -0.22441018194495696 */ + -6745, /* k2g1[6] = -0.20584605955455101 */ + -6187, /* k2g1[7] = -0.18881763682420102 */ + -5675, /* k2g1[8] = -0.1731978744360067 */ + -5206, /* k2g1[9] = -0.15887024228080968 */ + -4775, /* k2g1[10] = -0.14572785009373057 */ + -4380, /* k2g1[11] = -0.13367265000706827 */ + -4018, /* k2g1[12] = -0.1226147050712642 */ + -3685, /* k2g1[13] = -0.11247151828678581 */ + -3381, /* k2g1[14] = -0.10316741714122014 */ + -3101, /* k2g1[15] = -0.0946329890599603 */ + -2844, /* k2g1[16] = -0.08680456355870586 */ + -2609, /* k2g1[17] = -0.07962373723441349 */ + -2393, /* k2g1[18] = -0.07303693805092666 */ + -2195, /* k2g1[19] = -0.06699502566866912 */ + -2014, /* k2g1[20] = -0.06145292483669077 */ + -1847, /* k2g1[21] = -0.056369289112013346 */ + -1694, /* k2g1[22] = -0.05170619239747895 */ + -1554, /* k2g1[23] = -0.04742884599684141 */ + -1426, /* k2g1[24] = -0.043505339076210514 */ + -1308, /* k2g1[25] = -0.03990640059558053 */ + -1199, /* k2g1[26] = -0.03660518093435039 */ + -1100, /* k2g1[27] = -0.03357705158166837 */ + -1009, /* k2g1[28] = -0.030799421397205727 */ + -926, /* k2g1[29] = -0.028251568071585884 */ + -849 /* k2g1[30] = -0.025914483529091967 */ +}; + +static const EAS_I16 k2g2[] = +{ + 1957, /* k2g2[0] = 0.059711106626580836 */ + 1646, /* k2g2[1] = 0.05024063501786333 */ + 1385, /* k2g2[2] = 0.042272226217199664 */ + 1165, /* k2g2[3] = 0.03556764576567844 */ + 981, /* k2g2[4] = 0.029926444346999134 */ + 825, /* k2g2[5] = 0.025179964880280382 */ + 694, /* k2g2[6] = 0.02118630011706455 */ + 584, /* k2g2[7] = 0.01782604998793514 */ + 491, /* k2g2[8] = 0.014998751854573014 */ + 414, /* k2g2[9] = 0.012619876941179595 */ + 348, /* k2g2[10] = 0.010618303146468736 */ + 293, /* k2g2[11] = 0.008934188679954682 */ + 246, /* k2g2[12] = 0.007517182949855368 */ + 207, /* k2g2[13] = 0.006324921212866403 */ + 174, /* k2g2[14] = 0.005321757979794424 */ + 147, /* k2g2[15] = 0.004477701309210577 */ + 123, /* k2g2[16] = 0.00376751612730811 */ + 104, /* k2g2[17] = 0.0031699697655869644 */ + 87, /* k2g2[18] = 0.00266719715992703 */ + 74, /* k2g2[19] = 0.0022441667321724647 */ + 62, /* k2g2[20] = 0.0018882309854916855 */ + 52, /* k2g2[21] = 0.0015887483774966232 */ + 44, /* k2g2[22] = 0.0013367651661223448 */ + 37, /* k2g2[23] = 0.0011247477162958733 */ + 31, /* k2g2[24] = 0.0009463572640678758 */ + 26, /* k2g2[25] = 0.0007962604042473498 */ + 22, /* k2g2[26] = 0.0006699696356181593 */ + 18, /* k2g2[27] = 0.0005637091964589207 */ + 16, /* k2g2[28] = 0.00047430217920125243 */ + 13, /* k2g2[29] = 0.00039907554925166274 */ + 11 /* k2g2[30] = 0.00033578022828973666 */ +}; + +static const EAS_I16 n1g2[] = +{ + 3170, /* n1g2[0] = 0.0967319927350769 */ + 3036, /* n1g2[1] = 0.0926446051254155 */ + 2908, /* n1g2[2] = 0.08872992911818503 */ + 2785, /* n1g2[3] = 0.08498066682523227 */ + 2667, /* n1g2[4] = 0.08138982872895201 */ + 2554, /* n1g2[5] = 0.07795072065216213 */ + 2446, /* n1g2[6] = 0.0746569312785634 */ + 2343, /* n1g2[7] = 0.07150232020051943 */ + 2244, /* n1g2[8] = 0.06848100647187474 */ + 2149, /* n1g2[9] = 0.06558735764447099 */ + 2058, /* n1g2[10] = 0.06281597926792246 */ + 1971, /* n1g2[11] = 0.06016170483307614 */ + 1888, /* n1g2[12] = 0.05761958614040857 */ + 1808, /* n1g2[13] = 0.05518488407540374 */ + 1732, /* n1g2[14] = 0.052853059773715245 */ + 1659, /* n1g2[15] = 0.05061976615964251 */ + 1589, /* n1g2[16] = 0.04848083984214659 */ + 1521, /* n1g2[17] = 0.046432293353298 */ + 1457, /* n1g2[18] = 0.04447030771468711 */ + 1396, /* n1g2[19] = 0.04259122531793907 */ + 1337, /* n1g2[20] = 0.040791543106060944 */ + 1280, /* n1g2[21] = 0.03906790604290942 */ + 1226, /* n1g2[22] = 0.037417100858604564 */ + 1174, /* n1g2[23] = 0.035836050059229754 */ + 1125, /* n1g2[24] = 0.03432180618965023 */ + 1077, /* n1g2[25] = 0.03287154633875494 */ + 1032, /* n1g2[26] = 0.03148256687687814 */ + 988, /* n1g2[27] = 0.030152278415589925 */ + 946, /* n1g2[28] = 0.028878200980459685 */ + 906, /* n1g2[29] = 0.02765795938779331 */ + 868 /* n1g2[30] = 0.02648927881672521 */ +}; + +static const EAS_I16 n1g3[] = +{ + -548, /* n1g3[0] = -0.016714088475899017 */ + -481, /* n1g3[1] = -0.014683605122742116 */ + -423, /* n1g3[2] = -0.012899791676436092 */ + -371, /* n1g3[3] = -0.01133268185193299 */ + -326, /* n1g3[4] = -0.00995594976868754 */ + -287, /* n1g3[5] = -0.008746467702146129 */ + -252, /* n1g3[6] = -0.00768391756106361 */ + -221, /* n1g3[7] = -0.006750449563854721 */ + -194, /* n1g3[8] = -0.005930382380083576 */ + -171, /* n1g3[9] = -0.005209939699767622 */ + -150, /* n1g3[10] = -0.004577018805123356 */ + -132, /* n1g3[11] = -0.004020987256990177 */ + -116, /* n1g3[12] = -0.003532504280467257 */ + -102, /* n1g3[13] = -0.00310336384922047 */ + -89, /* n1g3[14] = -0.002726356832432369 */ + -78, /* n1g3[15] = -0.002395149888601605 */ + -69, /* n1g3[16] = -0.0021041790717285314 */ + -61, /* n1g3[17] = -0.0018485563625771063 */ + -53, /* n1g3[18] = -0.001623987554831628 */ + -47, /* n1g3[19] = -0.0014267001167177025 */ + -41, /* n1g3[20] = -0.0012533798162347005 */ + -36, /* n1g3[21] = -0.0011011150453668693 */ + -32, /* n1g3[22] = -0.0009673479079754438 */ + -28, /* n1g3[23] = -0.0008498312496971563 */ + -24, /* n1g3[24] = -0.0007465909079943587 */ + -21, /* n1g3[25] = -0.0006558925481952733 */ + -19, /* n1g3[26] = -0.0005762125284029567 */ + -17, /* n1g3[27] = -0.0005062123038325457 */ + -15, /* n1g3[28] = -0.0004447159405951901 */ + -13, /* n1g3[29] = -0.00039069036118270117 */ + -11 /* n1g3[30] = -0.00034322798979677605 */ +}; + +/*---------------------------------------------------------------------------- + * WT_SetFilterCoeffs() + *---------------------------------------------------------------------------- + * Purpose: + * Update the Filter parameters + * + * Inputs: + * pVoice - ptr to the voice whose filter we want to update + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - updates Filter values for the given voice + *---------------------------------------------------------------------------- +*/ +void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance) +{ + EAS_I32 temp; + + /* + Convert the cutoff, which has had A5 subtracted, using the 2^x approx + Note, this cutoff is related to theta cutoff by + theta = k * 2^x + We use 2^x and incorporate k in the power series coefs instead + */ + cutoff = EAS_Calculate2toX(cutoff); + + /* calculate b2 coef */ + temp = k2g1[resonance] + MULT_AUDIO_COEF(cutoff, k2g2[resonance]); + temp = k2g0 + MULT_AUDIO_COEF(cutoff, temp); + pIntFrame->frame.b2 = temp; + + /* calculate b1 coef */ + temp = MULT_AUDIO_COEF(cutoff, nk1g2); + temp = nk1g0 + MULT_AUDIO_COEF(cutoff, temp); + temp += MULT_AUDIO_COEF(temp, pIntFrame->frame.b2); + pIntFrame->frame.b1 = temp >> 1; + + /* calculate K coef */ + temp = n1g2[resonance] + MULT_AUDIO_COEF(cutoff, n1g3[resonance]); + temp = MULT_AUDIO_COEF(cutoff, temp); + temp = MULT_AUDIO_COEF(cutoff, temp); + pIntFrame->frame.k = temp; +} +#endif + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtsynth.h b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtsynth.h new file mode 100755 index 0000000..90a7ad8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/eas_wtsynth.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wtsynth.h + * + * Contents and purpose: + * This file defines the interface for synthesizer engine + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WTSYNTH_H +#define _EAS_WTSYNTH_H + +#include "eas_sndlib.h" +#include "eas_wtengine.h" + +/* adjust the filter cutoff frequency to the sample rate */ +#if defined (_SAMPLE_RATE_8000) +#define FILTER_CUTOFF_FREQ_ADJUST 0 +#elif defined (_SAMPLE_RATE_16000) +#define FILTER_CUTOFF_FREQ_ADJUST 1200 +#elif defined (_SAMPLE_RATE_20000) +#define FILTER_CUTOFF_FREQ_ADJUST 1586 +#elif defined (_SAMPLE_RATE_22050) +#define FILTER_CUTOFF_FREQ_ADJUST 1756 +#elif defined (_SAMPLE_RATE_24000) +#define FILTER_CUTOFF_FREQ_ADJUST 1902 +#elif defined (_SAMPLE_RATE_32000) +#define FILTER_CUTOFF_FREQ_ADJUST 2400 +#elif defined (_SAMPLE_RATE_44100) +#define FILTER_CUTOFF_FREQ_ADJUST 2956 +#elif defined (_SAMPLE_RATE_48000) +#define FILTER_CUTOFF_FREQ_ADJUST 3102 +#else +#error "_SAMPLE_RATE_XXXXX must be defined to valid rate" +#endif + +/* function prototypes */ +void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc); + +#if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER) +void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance); +#endif + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/hybrid_22khz_mcu.c b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/hybrid_22khz_mcu.c new file mode 100755 index 0000000..1d6816b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-hybrid-22k/lib_src/hybrid_22khz_mcu.c @@ -0,0 +1,5149 @@ +/*---------------------------------------------------------------------------- + * + * Filename: C:\Sonic\Trunk\EASLib\WTLibrary\hybrid_22khz_mcu.c + * Source: C:\Sonic\Trunk\Wavetables\Sonic_20Khz_Drums.dls + * CmdLine: -w C:\Sonic\Trunk\EASLib\WTLibrary\hybrid_22khz_mcu.c -l C:\Sonic\Trunk\EASLib\WTLibrary\hybrid_22khz.log -d 0 -c -f C:\Sonic\Release3-5\EASLib\FMSynth\GMdblib-3.fml C:\Sonic\Trunk\Wavetables\Sonic_20Khz_Drums.dls -w -l -d -c -f C:\Sonic\Trunk\Wavetables\Sonic_20Khz_Drums.dls + * Purpose: Wavetable sound libary + * + * Copyright (c) 2006 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision:$ + * $Date:$ + *---------------------------------------------------------------------------- +*/ + +#include "eas_sndlib.h" + +/*---------------------------------------------------------------------------- + * Articulations + *---------------------------------------------------------------------------- +*/ +const S_ARTICULATION eas_articulations[] = +{ + { /* articulation 0 */ + { 32767, 30725, 0, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 1 */ + { 32767, 26863, 0, 26863 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 2 */ + { 32767, 30484, 0, 30668 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 3 */ + { 32767, 26439, 0, 26439 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 4 */ + { 32767, 0, 32767, 32715 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 5 */ + { 32767, 21333, 0, 21333 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 6 */ + { 32767, 31882, 0, 31938 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 7 */ + { 32767, 32663, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 8 */ + { 32767, 0, 32767, 0 }, + { 32767, 1902, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 9 */ + { 32767, 32349, 0, 32349 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 10 */ + { 32767, 0, 32767, 17213 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -1 + }, + { /* articulation 11 */ + { 32767, 32072, 0, 32072 }, + { 32767, 761, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -56 + }, + { /* articulation 12 */ + { 32767, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 13 */ + { 32767, 32010, 0, 32010 }, + { 32767, 761, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -31 + }, + { /* articulation 14 */ + { 9511, 21333, 0, 21333 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 15 */ + { 32767, 31844, 0, 31844 }, + { 32767, 761, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -6 + }, + { /* articulation 16 */ + { 32767, 32123, 0, 32194 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 17 */ + { 32767, 31730, 0, 31730 }, + { 32767, 761, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 6 + }, + { /* articulation 18 */ + { 32767, 31391, 0, 31391 }, + { 32767, 951, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 31 + }, + { /* articulation 19 */ + { 32767, 31964, 0, 31964 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 20 */ + { 32767, 31056, 0, 31056 }, + { 32767, 951, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 21 */ + { 32767, 32289, 0, 32271 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 22 */ + { 19021, 31882, 0, 31911 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 23 */ + { 32767, 31988, 0, 32032 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 24 */ + { 32767, 0, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 12 + }, + { /* articulation 25 */ + { 32767, 31352, 0, 31352 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -25 + }, + { /* articulation 26 */ + { 32767, 0, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 27 */ + { 32767, 31817, 0, 31781 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -25 + }, + { /* articulation 28 */ + { 32767, 30725, 0, 30725 }, + { 32767, 95, 0, 0 }, + 0, 0, 951, 240, 0, 0, 0, 0, -56 + }, + { /* articulation 29 */ + { 32767, 32230, 0, 32218 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 30 */ + { 32767, 26439, 0, 26439 }, + { 32767, 3804, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 50 + }, + { /* articulation 31 */ + { 32767, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -50 + }, + { /* articulation 32 */ + { 32767, 29434, 0, 29434 }, + { 32767, 3804, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -50 + }, + { /* articulation 33 */ + { 32767, 30240, 0, 30234 }, + { 32767, 3804, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -44 + }, + { /* articulation 34 */ + { 32767, 32558, 0, 32558 }, + { 32767, 254, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 35 */ + { 32767, 0, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -63 + }, + { /* articulation 36 */ + { 3804, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -63 + }, + { /* articulation 37 */ + { 32767, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -59 + }, + { /* articulation 38 */ + { 32767, 30725, 0, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 50 + }, + { /* articulation 39 */ + { 32767, 28809, 0, 28809 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 44 + }, + { /* articulation 40 */ + { 1902, 30725, 0, 30725 }, + { 32767, 380, 0, 0 }, + 0, 0, 951, -100, 0, 0, 0, 0, 44 + }, + { /* articulation 41 */ + { 32767, 9042, 0, 9042 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 42 */ + { 32767, 29889, 0, 29889 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 43 */ + { 32767, 30240, 0, 30234 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 44 */ + { 19021, 19970, 0, 19970 }, + { 951, 32767, 32767, 0 }, + 0, 0, 951, 100, 0, 0, 0, 0, -25 + }, + { /* articulation 45 */ + { 3804, 17213, 0, 17213 }, + { 951, 32767, 32767, 0 }, + 0, 0, 951, 500, 0, 0, 0, 0, -25 + }, + { /* articulation 46 */ + { 32767, 17213, 0, 17213 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -56 + }, + { /* articulation 47 */ + { 32767, 30725, 0, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -56 + }, + { /* articulation 48 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 49 */ + { 32767, 31180, 0, 31180 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 50 */ + { 19021, 31964, 0, 32071 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 51 */ + { 32767, 29669, 0, 29669 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 52 */ + { 32767, 31742, 0, 31352 }, + { 32767, 294, 0, 0 }, + 0, 0, 951, 0, 10000, 7121, 0, 0, 0 + } +}; /*end Articulations */ + +/*---------------------------------------------------------------------------- + * Regions + *---------------------------------------------------------------------------- +*/ +const S_WT_REGION eas_regions[] = +{ + { { 0, 27, 27 }, -2868, 16422, 0, 0, 19, 0 }, /* region 0 */ + { { 0, 28, 28 }, -3568, 32767, 0, 0, 13, 0 }, /* region 1 */ + { { 0, 29, 29 }, -4553, 32767, 0, 0, 9, 1 }, /* region 2 */ + { { 0, 30, 30 }, -4853, 32767, 0, 0, 9, 2 }, /* region 3 */ + { { 0, 31, 31 }, -3868, 23197, 0, 0, 15, 3 }, /* region 4 */ + { { 1536, 32, 32 }, -3368, 20675, 0, 0, 29, 4 }, /* region 5 */ + { { 1537, 33, 33 }, -3868, 20675, 792, 800, 17, 5 }, /* region 6 */ + { { 1537, 34, 34 }, -3968, 16422, 792, 800, 17, 6 }, /* region 7 */ + { { 0, 35, 35 }, -4968, 32767, 0, 0, 20, 7 }, /* region 8 */ + { { 0, 36, 36 }, -4968, 32767, 0, 0, 20, 7 }, /* region 9 */ + { { 0, 37, 37 }, -4051, 18426, 0, 0, 16, 8 }, /* region 10 */ + { { 0, 38, 38 }, -4151, 23197, 0, 0, 5, 9 }, /* region 11 */ + { { 0, 39, 39 }, -4668, 23197, 0, 0, 12, 10 }, /* region 12 */ + { { 0, 40, 40 }, -4151, 23197, 0, 0, 5, 4 }, /* region 13 */ + { { 1, 41, 41 }, -5855, 26028, 798, 993, 14, 11 }, /* region 14 */ + { { 257, 42, 42 }, -4368, 26028, 4288, 6792, 2, 12 }, /* region 15 */ + { { 1, 43, 43 }, -5755, 26028, 798, 993, 14, 13 }, /* region 16 */ + { { 257, 44, 44 }, -4568, 26028, 4288, 6792, 2, 14 }, /* region 17 */ + { { 1, 45, 45 }, -5755, 26028, 798, 993, 14, 15 }, /* region 18 */ + { { 257, 46, 46 }, -4768, 26028, 4288, 6792, 2, 16 }, /* region 19 */ + { { 1, 47, 47 }, -5455, 26028, 798, 993, 14, 17 }, /* region 20 */ + { { 1, 48, 48 }, -5355, 26028, 798, 993, 14, 18 }, /* region 21 */ + { { 1, 49, 49 }, -5368, 16422, 1294, 5241, 3, 19 }, /* region 22 */ + { { 1, 50, 50 }, -5255, 26028, 798, 993, 14, 20 }, /* region 23 */ + { { 1, 51, 51 }, -5268, 16422, 6592, 9921, 0, 21 }, /* region 24 */ + { { 1, 52, 52 }, -5768, 32767, 1294, 5241, 3, 22 }, /* region 25 */ + { { 1, 53, 53 }, -5418, 14636, 6592, 9921, 0, 23 }, /* region 26 */ + { { 0, 54, 54 }, -5751, 26028, 0, 0, 11, 24 }, /* region 27 */ + { { 1, 55, 55 }, -5468, 32767, 1294, 5241, 3, 25 }, /* region 28 */ + { { 0, 56, 56 }, -7255, 32767, 0, 0, 24, 26 }, /* region 29 */ + { { 1, 57, 57 }, -5868, 32767, 1294, 5241, 3, 27 }, /* region 30 */ + { { 1, 58, 58 }, -7053, 23197, 0, 166, 26, 28 }, /* region 31 */ + { { 1, 59, 59 }, -5968, 16422, 6592, 9921, 0, 29 }, /* region 32 */ + { { 1, 60, 60 }, -6453, 23197, 432, 582, 18, 30 }, /* region 33 */ + { { 1, 61, 61 }, -6853, 16422, 432, 582, 18, 30 }, /* region 34 */ + { { 1, 62, 62 }, -7253, 20675, 432, 582, 18, 31 }, /* region 35 */ + { { 1, 63, 63 }, -7353, 23197, 432, 582, 18, 32 }, /* region 36 */ + { { 1, 64, 64 }, -7953, 23197, 432, 582, 18, 33 }, /* region 37 */ + { { 0, 65, 65 }, -7555, 32767, 0, 0, 4, 34 }, /* region 38 */ + { { 0, 66, 66 }, -7955, 20675, 0, 0, 4, 34 }, /* region 39 */ + { { 512, 67, 67 }, -7155, 18426, 0, 0, 24, 35 }, /* region 40 */ + { { 512, 68, 68 }, -7755, 18426, 0, 0, 24, 35 }, /* region 41 */ + { { 0, 69, 69 }, -7755, 32767, 0, 0, 21, 36 }, /* region 42 */ + { { 0, 70, 70 }, -6855, 21900, 0, 0, 21, 37 }, /* region 43 */ + { { 769, 71, 71 }, -6355, 23197, 0, 1226, 10, 38 }, /* region 44 */ + { { 769, 72, 72 }, -6955, 26028, 0, 1226, 10, 38 }, /* region 45 */ + { { 1024, 73, 73 }, -7955, 32767, 0, 0, 7, 39 }, /* region 46 */ + { { 1024, 74, 74 }, -8455, 32767, 0, 0, 7, 40 }, /* region 47 */ + { { 1, 75, 75 }, -8068, 23197, 0, 29, 30, 41 }, /* region 48 */ + { { 0, 76, 76 }, -10455, 23197, 0, 0, 28, 42 }, /* region 49 */ + { { 0, 77, 77 }, -10055, 23197, 0, 0, 28, 43 }, /* region 50 */ + { { 0, 78, 78 }, -8853, 16422, 0, 0, 23, 44 }, /* region 51 */ + { { 0, 79, 79 }, -10253, 16422, 0, 0, 23, 45 }, /* region 52 */ + { { 1280, 80, 80 }, -6468, 13045, 0, 0, 25, 46 }, /* region 53 */ + { { 1280, 81, 81 }, -6568, 16422, 0, 0, 25, 47 }, /* region 54 */ + { { 0, 82, 82 }, -8455, 20675, 0, 0, 22, 48 }, /* region 55 */ + { { 0, 83, 83 }, -9068, 32767, 0, 0, 6, 49 }, /* region 56 */ + { { 1, 84, 84 }, -8568, 23197, 0, 9337, 1, 50 }, /* region 57 */ + { { 0, 85, 85 }, -9655, 32767, 0, 0, 27, 0 }, /* region 58 */ + { { 0, 86, 86 }, -9068, 16422, 0, 0, 8, 51 }, /* region 59 */ + { { 32769, 87, 87 }, -9168, 32767, 1335, 1603, 8, 52 } /* region 60 */ +}; /* end Regions */ + +/*---------------------------------------------------------------------------- + * FM Regions + *---------------------------------------------------------------------------- +*/ +const S_FM_REGION eas_fmRegions[] = +{ + + { /* FM region 0 */ + { 37, 0, 127 }, 0, 255, 8, 0, + { + { 514, 239, 47, 97, 0, 184, 3 }, + { 1, 244, 89, 114, 0, 248, 2 }, + { 3370, 244, 49, 76, 40, 192, 2 }, + { -1, 227, 97, 51, 160, 212, 2 } + } + }, + { /* FM region 1 */ + { 37, 0, 127 }, 160, 255, 8, 0, + { + { 2514, 223, 95, 72, 0, 176, 3 }, + { 1, 244, 73, 145, 0, 244, 2 }, + { 3600, 245, 81, 198, 40, 192, 2 }, + { 3, 246, 81, 163, 108, 212, 2 } + } + }, + { /* FM region 2 */ + { 37, 0, 127 }, 160, 255, 119, 0, + { + { 0, 216, 79, 72, 0, 216, 2 }, + { 2, 244, 73, 145, 0, 244, 2 }, + { 3370, 247, 33, 182, 60, 204, 2 }, + { 1200, 246, 65, 163, 108, 204, 2 } + } + }, + { /* FM region 3 */ + { 37, 0, 127 }, 160, 255, 1, 0, + { + { 3369, 248, 65, 71, 40, 208, 2 }, + { -3, 245, 88, 113, 0, 244, 2 }, + { 2784, 225, 65, 133, 80, 192, 2 }, + { 3, 241, 81, 113, 80, 216, 2 } + } + }, + { /* FM region 4 */ + { 34, 0, 127 }, 0, 255, 128, 0, + { + { 0, 229, 155, 183, 0, 228, 2 }, + { -3, 243, 90, 81, 0, 244, 2 }, + { 4800, 248, 109, 180, 36, 192, 2 }, + { 3, 245, 90, 85, 16, 244, 2 } + } + }, + { /* FM region 5 */ + { 34, 0, 127 }, 9, 96, 192, 0, + { + { 1200, 229, 157, 180, 0, 216, 2 }, + { -3, 244, 90, 81, 0, 244, 2 }, + { 1902, 255, 111, 182, 80, 208, 2 }, + { 3, 246, 92, 83, 0, 244, 2 } + } + }, + { /* FM region 6 */ + { 34, 0, 127 }, 0, 255, 154, 0, + { + { 3102, 244, 63, 102, 228, 228, 2 }, + { 1200, 247, 93, 97, 0, 236, 2 }, + { 1902, 255, 63, 98, 156, 220, 2 }, + { 1200, 244, 92, 98, 0, 236, 2 } + } + }, + { /* FM region 7 */ + { 37, 0, 127 }, 0, 255, 202, 0, + { + { 0, 251, 131, 19, 216, 220, 2 }, + { 1201, 247, 62, 113, 0, 240, 2 }, + { 0, 243, 154, 36, 240, 224, 2 }, + { 2784, 250, 61, 36, 240, 208, 2 } + } + }, + { /* FM region 8 */ + { 33, 0, 127 }, 0, 255, 80, 0, + { + { -1, 213, 191, 183, 0, 204, 2 }, + { 1, 245, 154, 129, 0, 244, 2 }, + { 3831, 252, 159, 100, 0, 200, 2 }, + { 1197, 246, 91, 182, 0, 244, 2 } + } + }, + { /* FM region 9 */ + { 34, 0, 127 }, 48, 80, 21, 0, + { + { 2982, 255, 43, 96, 0, 196, 3 }, + { 3, 247, 71, 130, 0, 244, 2 }, + { 3358, 253, 40, 98, 144, 208, 2 }, + { -2, 246, 70, 130, 0, 236, 2 } + } + }, + { /* FM region 10 */ + { 34, 0, 127 }, 48, 80, 26, 0, + { + { 3096, 249, 72, 100, 0, 208, 2 }, + { 2185, 249, 102, 130, 0, 240, 2 }, + { 3386, 247, 66, 100, 144, 212, 2 }, + { -2, 247, 102, 130, 0, 240, 2 } + } + }, + { /* FM region 11 */ + { 34, 0, 127 }, 92, 67, 21, 0, + { + { 2982, 255, 27, 146, 0, 200, 3 }, + { 3, 246, 68, 146, 0, 240, 2 }, + { 3358, 250, 149, 116, 144, 208, 2 }, + { -3, 245, 68, 146, 0, 240, 0 } + } + }, + { /* FM region 12 */ + { 34, 0, 127 }, 0, 67, 0, 0, + { + { 1500, 239, 60, 151, 0, 220, 2 }, + { 0, 247, 76, 146, 0, 240, 2 }, + { 2398, 234, 156, 151, 0, 212, 2 }, + { 0, 246, 105, 146, 0, 244, 2 } + } + }, + { /* FM region 13 */ + { 34, 0, 127 }, 0, 67, 0, 0, + { + { 2500, 255, 60, 151, 0, 220, 2 }, + { 0, 249, 92, 146, 0, 244, 2 }, + { 3369, 250, 156, 151, 0, 196, 2 }, + { 0, 248, 89, 146, 0, 244, 2 } + } + }, + { /* FM region 14 */ + { 37, 0, 127 }, 160, 255, 0, 0, + { + { 2300, 229, 112, 49, 0, 208, 2 }, + { -3, 247, 67, 50, 0, 248, 2 }, + { 1074, 255, 41, 49, 0, 196, 2 }, + { 686, 240, 97, 18, 0, 196, 2 } + } + }, + { /* FM region 15 */ + { 37, 0, 127 }, 160, 255, 219, 0, + { + { 3369, 255, 65, 70, 40, 216, 2 }, + { 1, 246, 72, 113, 0, 240, 2 }, + { 1902, 225, 33, 129, 80, 204, 2 }, + { 2400, 225, 97, 113, 80, 200, 2 } + } + }, + { /* FM region 16 */ + { 35, 0, 127 }, 32, 48, 151, 0, + { + { 1201, 215, 35, 66, 252, 208, 0 }, + { -9581, 254, 63, 177, 240, 240, 3 }, + { 1902, 248, 47, 64, 112, 244, 2 }, + { 0, 247, 35, 66, 208, 212, 2 } + } + }, + { /* FM region 17 */ + { 33, 0, 127 }, 0, 255, 153, 0, + { + { 1, 252, 31, 3, 244, 196, 2 }, + { -1, 208, 31, 4, 248, 244, 2 }, + { 1205, 209, 31, 4, 248, 236, 2 }, + { 1899, 250, 31, 32, 0, 240, 2 } + } + }, + { /* FM region 18 */ + { 34, 0, 127 }, 32, 49, 201, 0, + { + { 1, 220, 47, 3, 244, 220, 0 }, + { -10000, 208, 63, 1, 248, 240, 3 }, + { 1586, 255, 47, 3, 188, 216, 2 }, + { -1, 202, 63, 32, 80, 232, 2 } + } + }, + { /* FM region 19 */ + { 33, 0, 127 }, 0, 143, 29, 0, + { + { -1200, 223, 64, 0, 252, 216, 2 }, + { 1200, 96, 41, 35, 248, 240, 2 }, + { 1200, 143, 41, 64, 252, 224, 2 }, + { 3102, 161, 41, 96, 248, 216, 2 } + } + }, + { /* FM region 20 */ + { 34, 0, 127 }, 0, 143, 34, 0, + { + { -1200, 133, 79, 1, 252, 212, 2 }, + { 1201, 112, 46, 34, 248, 232, 2 }, + { 0, 116, 79, 65, 252, 200, 2 }, + { 1900, 161, 46, 98, 248, 232, 2 } + } + }, + { /* FM region 21 */ + { 34, 0, 127 }, 0, 143, 187, 0, + { + { 1202, 80, 74, 1, 252, 216, 2 }, + { 2402, 112, 46, 34, 248, 232, 2 }, + { 0, 99, 78, 97, 184, 216, 2 }, + { 1899, 81, 46, 98, 236, 232, 2 } + } + }, + { /* FM region 22 */ + { 37, 0, 127 }, 22, 141, 34, 0, + { + { 2787, 176, 79, 4, 252, 208, 2 }, + { 2785, 144, 45, 34, 248, 236, 2 }, + { 3369, 83, 77, 100, 184, 172, 2 }, + { 1902, 102, 45, 100, 172, 212, 0 } + } + }, + { /* FM region 23 */ + { 34, 0, 127 }, 0, 143, 135, 0, + { + { 1900, 112, 79, 3, 252, 220, 2 }, + { 2400, 128, 45, 34, 248, 232, 2 }, + { 1200, 115, 77, 98, 184, 220, 2 }, + { 1904, 97, 45, 98, 236, 232, 2 } + } + }, + { /* FM region 24 */ + { 37, 0, 127 }, 0, 255, 157, 0, + { + { 1200, 244, 54, 4, 20, 200, 2 }, + { 0, 245, 92, 130, 0, 244, 2 }, + { 3802, 247, 68, 21, 0, 196, 2 }, + { 1, 245, 43, 114, 0, 204, 2 } + } + }, + { /* FM region 25 */ + { 37, 0, 127 }, 0, 128, 83, 0, + { + { 0, 244, 51, 4, 200, 204, 0 }, + { 0, 247, 108, 129, 0, 248, 0 }, + { 2786, 243, 31, 70, 200, 220, 0 }, + { 1902, 246, 44, 113, 12, 188, 0 } + } + }, + { /* FM region 26 */ + { 37, 0, 127 }, 0, 128, 61, 0, + { + { 0, 246, 51, 97, 76, 204, 0 }, + { 0, 244, 60, 97, 0, 240, 0 }, + { 1786, 255, 31, 64, 0, 180, 0 }, + { 1200, 247, 60, 97, 12, 204, 0 } + } + }, + { /* FM region 27 */ + { 37, 0, 127 }, 0, 128, 153, 0, + { + { -2, 243, 53, 99, 96, 200, 0 }, + { 0, 243, 60, 97, 0, 240, 0 }, + { 3983, 247, 63, 100, 24, 204, 0 }, + { 2, 242, 53, 99, 52, 212, 0 } + } + }, + { /* FM region 28 */ + { 37, 0, 127 }, 0, 128, 205, 0, + { + { -2, 244, 47, 97, 20, 208, 0 }, + { 0, 252, 75, 193, 0, 248, 0 }, + { 0, 254, 63, 98, 132, 224, 0 }, + { 2786, 251, 63, 98, 52, 192, 0 } + } + }, + { /* FM region 29 */ + { 37, 0, 127 }, 0, 128, 221, 0, + { + { -1, 208, 191, 99, 220, 224, 0 }, + { 1200, 243, 92, 97, 0, 244, 0 }, + { 3984, 212, 11, 96, 168, 196, 0 }, + { 1, 242, 127, 98, 108, 204, 0 } + } + }, + { /* FM region 30 */ + { 37, 0, 127 }, 0, 128, 174, 0, + { + { -3, 212, 207, 99, 0, 228, 0 }, + { 1902, 241, 108, 97, 0, 248, 0 }, + { 3805, 212, 59, 98, 0, 220, 0 }, + { 1902, 146, 107, 98, 144, 196, 0 } + } + }, + { /* FM region 31 */ + { 41, 0, 127 }, 0, 255, 128, 0, + { + { 1206, 239, 43, 69, 0, 216, 2 }, + { 4, 254, 42, 66, 0, 244, 2 }, + { 702, 88, 55, 66, 0, 204, 2 }, + { -4, 71, 55, 66, 0, 240, 2 } + } + }, + { /* FM region 32 */ + { 37, 0, 127 }, 0, 255, 85, 0, + { + { 500, 239, 95, 82, 0, 184, 3 }, + { 0, 248, 73, 132, 0, 252, 2 }, + { 2786, 203, 59, 130, 0, 176, 2 }, + { 0, 216, 42, 100, 0, 208, 2 } + } + }, + { /* FM region 33 */ + { 37, 0, 127 }, 0, 128, 73, 0, + { + { 1, 229, 54, 131, 160, 208, 0 }, + { -1, 244, 62, 97, 0, 248, 0 }, + { 3986, 227, 127, 69, 140, 184, 0 }, + { 1201, 249, 92, 114, 0, 204, 0 } + } + }, + { /* FM region 34 */ + { 37, 0, 127 }, 0, 128, 73, 0, + { + { 1, 225, 54, 100, 200, 212, 0 }, + { -1, 244, 94, 97, 0, 248, 0 }, + { 3986, 249, 127, 88, 112, 188, 0 }, + { 1201, 249, 92, 85, 52, 208, 0 } + } + }, + { /* FM region 35 */ + { 37, 0, 127 }, 0, 128, 188, 0, + { + { -3, 198, 92, 179, 28, 212, 0 }, + { 0, 243, 90, 145, 0, 248, 0 }, + { 1901, 215, 95, 69, 28, 196, 0 }, + { 3, 84, 108, 196, 32, 208, 0 } + } + }, + { /* FM region 36 */ + { 37, 0, 127 }, 0, 136, 6, 0, + { + { 0, 226, 99, 36, 224, 216, 0 }, + { 1902, 248, 78, 33, 0, 252, 0 }, + { 3369, 239, 250, 33, 0, 204, 0 }, + { 0, 230, 253, 33, 0, 208, 0 } + } + }, + { /* FM region 37 */ + { 37, 0, 127 }, 0, 136, 195, 0, + { + { 0, 245, 99, 36, 152, 208, 0 }, + { 1200, 248, 78, 33, 0, 252, 0 }, + { 3369, 246, 250, 33, 0, 216, 0 }, + { 0, 246, 61, 33, 0, 180, 0 } + } + }, + { /* FM region 38 */ + { 34, 0, 127 }, 0, 133, 221, 0, + { + { 1, 244, 67, 35, 80, 220, 0 }, + { 3, 246, 94, 33, 0, 244, 0 }, + { -1, 245, 70, 35, 80, 236, 2 }, + { -3, 246, 63, 33, 0, 236, 2 } + } + }, + { /* FM region 39 */ + { 34, 0, 127 }, 0, 133, 220, 0, + { + { 0, 114, 51, 34, 132, 208, 0 }, + { 3, 214, 62, 33, 0, 248, 0 }, + { 0, 85, 54, 34, 44, 224, 2 }, + { -3, 214, 63, 33, 0, 236, 2 } + } + }, + { /* FM region 40 */ + { 37, 0, 127 }, 48, 142, 187, 0, + { + { -1, 33, 22, 33, 200, 208, 0 }, + { 0, 81, 105, 33, 220, 240, 0 }, + { 2786, 245, 19, 50, 208, 192, 0 }, + { 1, 245, 21, 82, 200, 220, 0 } + } + }, + { /* FM region 41 */ + { 37, 0, 127 }, 48, 126, 103, 0, + { + { -1, 193, 22, 33, 228, 212, 0 }, + { 0, 81, 105, 33, 220, 244, 0 }, + { 0, 245, 19, 50, 216, 228, 0 }, + { 1200, 245, 19, 82, 200, 188, 0 } + } + }, + { /* FM region 42 */ + { 37, 0, 127 }, 16, 126, 202, 0, + { + { -1, 49, 24, 41, 200, 212, 0 }, + { 0, 81, 71, 49, 220, 244, 0 }, + { 3371, 243, 19, 36, 232, 192, 0 }, + { 1, 242, 24, 36, 220, 212, 0 } + } + }, + { /* FM region 43 */ + { 37, 0, 127 }, 16, 124, 205, 0, + { + { 0, 129, 24, 49, 208, 200, 0 }, + { 0, 67, 102, 81, 224, 244, 0 }, + { 3804, 246, 23, 36, 160, 196, 0 }, + { 1200, 244, 24, 35, 208, 200, 0 } + } + }, + { /* FM region 44 */ + { 37, 0, 127 }, 48, 144, 208, 0, + { + { -3, 209, 22, 33, 200, 204, 2 }, + { 0, 81, 89, 33, 220, 240, 2 }, + { -5000, 208, 6, 33, 244, 188, 3 }, + { 3, 97, 89, 33, 224, 200, 0 } + } + }, + { /* FM region 45 */ + { 37, 0, 127 }, 0, 255, 186, 0, + { + { 500, 223, 95, 0, 0, 192, 3 }, + { 0, 247, 89, 100, 0, 248, 2 }, + { 3369, 255, 59, 168, 0, 212, 2 }, + { 0, 216, 42, 97, 0, 212, 2 } + } + }, + { /* FM region 46 */ + { 34, 0, 127 }, 0, 255, 221, 0, + { + { 1206, 235, 70, 69, 0, 216, 2 }, + { 4, 248, 84, 66, 0, 244, 2 }, + { 1902, 247, 52, 137, 80, 216, 2 }, + { -4, 245, 84, 131, 0, 240, 2 } + } + }, + { /* FM region 47 */ + { 37, 0, 127 }, 0, 255, 105, 0, + { + { 387, 231, 115, 34, 4, 216, 2 }, + { 0, 248, 37, 65, 0, 252, 2 }, + { 3308, 248, 117, 34, 8, 200, 2 }, + { 1900, 213, 82, 50, 0, 192, 2 } + } + }, + { /* FM region 48 */ + { 34, 0, 127 }, 32, 160, 221, 0, + { + { -7, 209, 22, 33, 200, 204, 2 }, + { -7, 81, 73, 33, 220, 244, 0 }, + { 7, 209, 22, 33, 200, 208, 0 }, + { 7, 97, 73, 33, 224, 244, 2 } + } + }, + { /* FM region 49 */ + { 34, 0, 127 }, 64, 128, 189, 0, + { + { -2, 209, 54, 32, 224, 216, 2 }, + { -7726, 97, 105, 33, 220, 240, 3 }, + { 1902, 209, 54, 34, 216, 208, 0 }, + { 2, 81, 105, 33, 224, 236, 0 } + } + }, + { /* FM region 50 */ + { 34, 0, 127 }, 80, 144, 206, 0, + { + { -3, 179, 38, 33, 160, 220, 2 }, + { -7726, 81, 69, 34, 220, 244, 3 }, + { 3, 193, 38, 33, 240, 212, 0 }, + { -8000, 65, 69, 34, 224, 236, 3 } + } + }, + { /* FM region 51 */ + { 37, 0, 127 }, 96, 128, 204, 0, + { + { -3, 97, 38, 33, 180, 216, 0 }, + { 0, 81, 69, 34, 220, 240, 2 }, + { 3369, 145, 38, 33, 240, 196, 2 }, + { -13190, 65, 69, 34, 240, 200, 3 } + } + }, + { /* FM region 52 */ + { 34, 0, 127 }, 64, 128, 108, 0, + { + { -3, 193, 37, 35, 236, 208, 0 }, + { 2394, 97, 90, 36, 224, 232, 2 }, + { 3, 65, 40, 35, 236, 204, 2 }, + { 1203, 97, 89, 33, 224, 240, 0 } + } + }, + { /* FM region 53 */ + { 37, 0, 127 }, 128, 128, 122, 0, + { + { 0, 193, 21, 34, 236, 188, 0 }, + { 3, 97, 74, 36, 224, 248, 2 }, + { 1906, 251, 24, 32, 96, 192, 3 }, + { 1200, 97, 73, 32, 224, 184, 0 } + } + }, + { /* FM region 54 */ + { 34, 0, 127 }, 64, 133, 135, 0, + { + { 0, 194, 25, 35, 120, 200, 2 }, + { 0, 97, 75, 36, 224, 240, 0 }, + { 2906, 254, 28, 48, 0, 184, 3 }, + { 0, 216, 75, 80, 204, 240, 2 } + } + }, + { /* FM region 55 */ + { 41, 0, 127 }, 208, 64, 255, 0, + { + { 475, 249, 16, 32, 252, 240, 2 }, + { 702, 248, 71, 32, 0, 244, 2 }, + { 1136, 232, 27, 32, 216, 248, 0 }, + { 0, 249, 23, 48, 0, 248, 2 } + } + }, + { /* FM region 56 */ + { 37, 0, 127 }, 0, 132, 233, 0, + { + { 0, 195, 95, 64, 240, 208, 0 }, + { 0, 225, 94, 64, 248, 240, 0 }, + { 0, 254, 127, 0, 4, 196, 4 }, + { 1902, 228, 95, 1, 248, 200, 0 } + } + }, + { /* FM region 57 */ + { 37, 0, 127 }, 16, 140, 238, 0, + { + { 0, 163, 90, 67, 228, 208, 0 }, + { 0, 209, 77, 65, 248, 240, 0 }, + { 1969, 173, 58, 65, 0, 176, 0 }, + { 0, 210, 61, 52, 204, 220, 0 } + } + }, + { /* FM region 58 */ + { 37, 0, 127 }, 16, 140, 222, 0, + { + { 0, 119, 74, 67, 160, 212, 0 }, + { 0, 146, 61, 65, 248, 244, 0 }, + { 1900, 137, 58, 65, 100, 196, 0 }, + { 0, 119, 61, 52, 120, 200, 0 } + } + }, + { /* FM region 59 */ + { 37, 0, 127 }, 16, 135, 219, 0, + { + { 0, 176, 79, 69, 240, 216, 0 }, + { 0, 193, 79, 64, 248, 236, 0 }, + { 0, 178, 123, 54, 92, 228, 0 }, + { 3369, 212, 95, 38, 144, 212, 0 } + } + }, + { /* FM region 60 */ + { 34, 0, 127 }, 0, 119, 203, 0, + { + { 2, 65, 77, 66, 228, 204, 0 }, + { 2, 161, 74, 64, 240, 240, 0 }, + { -2, 85, 60, 66, 180, 216, 2 }, + { -2, 162, 74, 64, 220, 240, 2 } + } + }, + { /* FM region 61 */ + { 34, 0, 127 }, 16, 154, 237, 0, + { + { 0, 179, 42, 64, 216, 208, 0 }, + { 0, 209, 61, 64, 248, 244, 0 }, + { -1200, 226, 55, 65, 244, 220, 2 }, + { 1902, 162, 62, 52, 204, 236, 2 } + } + }, + { /* FM region 62 */ + { 34, 0, 127 }, 48, 119, 221, 0, + { + { 2, 119, 79, 64, 208, 212, 0 }, + { 2, 209, 110, 64, 248, 236, 0 }, + { -2, 84, 79, 64, 136, 212, 2 }, + { -2, 209, 110, 64, 240, 240, 2 } + } + }, + { /* FM region 63 */ + { 34, 0, 127 }, 32, 135, 221, 0, + { + { 2, 165, 79, 64, 152, 216, 0 }, + { 2, 225, 110, 64, 248, 236, 0 }, + { -2, 132, 79, 64, 72, 224, 2 }, + { -2, 241, 110, 64, 252, 236, 2 } + } + }, + { /* FM region 64 */ + { 37, 0, 127 }, 17, 127, 190, 0, + { + { 0, 209, 60, 67, 244, 208, 0 }, + { 1200, 145, 94, 65, 248, 244, 2 }, + { 3369, 197, 47, 4, 128, 192, 0 }, + { 1902, 167, 94, 6, 200, 200, 0 } + } + }, + { /* FM region 65 */ + { 37, 0, 127 }, 17, 143, 190, 0, + { + { 0, 209, 60, 67, 244, 216, 0 }, + { 1902, 145, 62, 65, 248, 240, 2 }, + { 3369, 197, 47, 4, 128, 196, 0 }, + { 2400, 167, 94, 6, 200, 212, 2 } + } + }, + { /* FM region 66 */ + { 37, 0, 127 }, 17, 143, 190, 0, + { + { 0, 209, 60, 67, 244, 208, 0 }, + { 1902, 145, 62, 65, 248, 240, 2 }, + { 3369, 197, 47, 4, 128, 192, 0 }, + { 1902, 167, 94, 6, 200, 216, 2 } + } + }, + { /* FM region 67 */ + { 37, 0, 127 }, 17, 125, 190, 0, + { + { 0, 114, 109, 67, 244, 224, 0 }, + { 1902, 166, 93, 97, 200, 240, 0 }, + { 2786, 165, 95, 52, 160, 200, 0 }, + { 2400, 173, 78, 54, 240, 212, 2 } + } + }, + { /* FM region 68 */ + { 34, 0, 127 }, 16, 140, 205, 0, + { + { 0, 211, 55, 66, 244, 208, 0 }, + { 1902, 193, 93, 65, 248, 240, 0 }, + { 0, 204, 47, 4, 244, 216, 0 }, + { 3600, 183, 95, 6, 160, 232, 0 } + } + }, + { /* FM region 69 */ + { 34, 0, 127 }, 16, 126, 222, 0, + { + { 0, 243, 36, 66, 172, 200, 0 }, + { 1200, 193, 110, 67, 248, 244, 0 }, + { 0, 215, 33, 2, 232, 212, 0 }, + { 3369, 178, 63, 6, 184, 240, 0 } + } + }, + { /* FM region 70 */ + { 34, 0, 127 }, 16, 140, 221, 0, + { + { 1200, 213, 61, 66, 136, 200, 0 }, + { 1902, 193, 93, 68, 248, 240, 0 }, + { 0, 197, 47, 2, 228, 216, 0 }, + { 3369, 183, 95, 2, 160, 236, 0 } + } + }, + { /* FM region 71 */ + { 34, 0, 127 }, 16, 124, 201, 0, + { + { 1200, 195, 55, 68, 240, 208, 0 }, + { 0, 209, 76, 65, 248, 236, 0 }, + { 1902, 147, 47, 19, 208, 212, 0 }, + { 0, 183, 79, 22, 156, 228, 0 } + } + }, + { /* FM region 72 */ + { 37, 0, 127 }, 32, 110, 234, 0, + { + { 500, 237, 60, 68, 0, 192, 1 }, + { 1, 161, 93, 65, 248, 240, 2 }, + { 3365, 154, 47, 16, 48, 180, 6 }, + { 1200, 165, 92, 52, 160, 212, 2 } + } + }, + { /* FM region 73 */ + { 37, 0, 127 }, 32, 142, 200, 0, + { + { 0, 193, 60, 68, 248, 200, 0 }, + { 1, 129, 61, 65, 248, 240, 2 }, + { 3365, 154, 47, 16, 68, 184, 6 }, + { 1200, 169, 92, 52, 160, 204, 2 } + } + }, + { /* FM region 74 */ + { 35, 0, 127 }, 32, 135, 36, 0, + { + { 1199, 165, 79, 66, 152, 192, 2 }, + { -3, 145, 110, 64, 248, 240, 2 }, + { 0, 199, 79, 66, 44, 236, 2 }, + { 2986, 136, 110, 67, 100, 196, 2 } + } + }, + { /* FM region 75 */ + { 37, 0, 127 }, 32, 190, 71, 0, + { + { 868, 202, 140, 16, 24, 188, 2 }, + { 0, 176, 77, 65, 248, 240, 2 }, + { 3750, 169, 127, 16, 36, 228, 6 }, + { 2400, 195, 60, 17, 232, 172, 2 } + } + }, + { /* FM region 76 */ + { 37, 0, 127 }, 224, 16, 123, 0, + { + { 275, 202, 14, 2, 44, 196, 2 }, + { 0, 165, 89, 65, 56, 244, 2 }, + { 0, 255, 12, 2, 64, 216, 6 }, + { 963, 169, 14, 4, 40, 196, 2 } + } + }, + { /* FM region 77 */ + { 50, 0, 127 }, 192, 128, 100, 0, + { + { 1500, 202, 79, 68, 76, 204, 2 }, + { -2, 97, 26, 64, 248, 232, 2 }, + { 1588, 202, 223, 69, 4, 220, 0 }, + { 3, 188, 121, 67, 48, 252, 2 } + } + }, + { /* FM region 78 */ + { 34, 0, 127 }, 112, 140, 205, 0, + { + { 0, 68, 47, 66, 60, 176, 2 }, + { -2, 113, 94, 64, 248, 236, 0 }, + { 5000, 121, 47, 64, 32, 168, 7 }, + { 3, 136, 94, 64, 0, 236, 0 } + } + }, + { /* FM region 79 */ + { 35, 0, 127 }, 32, 135, 33, 0, + { + { 1199, 197, 79, 66, 152, 184, 2 }, + { 0, 161, 110, 64, 248, 240, 2 }, + { 0, 199, 79, 66, 44, 236, 2 }, + { 2400, 255, 110, 65, 36, 208, 6 } + } + }, + { /* FM region 80 */ + { 34, 0, 127 }, 0, 192, 170, 0, + { + { 1199, 192, 77, 33, 200, 212, 0 }, + { 0, 209, 107, 33, 232, 240, 0 }, + { 1201, 80, 77, 33, 200, 212, 0 }, + { 0, 241, 107, 33, 232, 240, 0 } + } + }, + { /* FM region 81 */ + { 34, 0, 127 }, 0, 192, 221, 0, + { + { -1, 192, 45, 33, 200, 212, 0 }, + { -1, 209, 107, 33, 232, 244, 0 }, + { 1, 80, 45, 33, 200, 212, 0 }, + { 1, 241, 107, 33, 232, 244, 0 } + } + }, + { /* FM region 82 */ + { 37, 0, 127 }, 0, 112, 255, 0, + { + { 4750, 221, 45, 34, 48, 172, 4 }, + { -10000, 161, 107, 33, 200, 244, 3 }, + { 2204, 137, 45, 37, 64, 184, 0 }, + { -2, 211, 107, 33, 160, 208, 0 } + } + }, + { /* FM region 83 */ + { 37, 0, 127 }, 16, 127, 238, 0, + { + { 2, 248, 45, 32, 204, 208, 0 }, + { -9500, 241, 107, 33, 200, 240, 3 }, + { 3369, 186, 45, 38, 24, 208, 0 }, + { -2, 211, 107, 32, 220, 212, 0 } + } + }, + { /* FM region 84 */ + { 37, 0, 127 }, 0, 128, 221, 0, + { + { -1, 192, 191, 99, 220, 216, 0 }, + { 1200, 243, 92, 97, 0, 244, 0 }, + { 3984, 200, 11, 96, 168, 192, 0 }, + { 1, 194, 127, 98, 108, 200, 0 } + } + }, + { /* FM region 85 */ + { 34, 0, 127 }, 128, 128, 111, 0, + { + { 1, 194, 25, 35, 120, 204, 2 }, + { -9750, 193, 107, 36, 224, 244, 3 }, + { 3906, 255, 28, 50, 12, 188, 3 }, + { -1, 216, 107, 80, 204, 240, 2 } + } + }, + { /* FM region 86 */ + { 34, 0, 127 }, 32, 134, 222, 0, + { + { 0, 195, 52, 33, 200, 208, 0 }, + { 0, 177, 90, 33, 232, 240, 2 }, + { 702, 195, 52, 33, 200, 208, 2 }, + { 702, 177, 90, 34, 232, 240, 2 } + } + }, + { /* FM region 87 */ + { 34, 0, 127 }, 32, 134, 205, 0, + { + { 0, 198, 75, 36, 120, 220, 2 }, + { 0, 225, 78, 52, 40, 244, 2 }, + { 0, 246, 47, 32, 220, 208, 2 }, + { 1902, 241, 124, 32, 240, 236, 2 } + } + }, + { /* FM region 88 */ + { 35, 0, 127 }, 32, 120, 14, 0, + { + { 3600, 244, 67, 34, 88, 208, 0 }, + { 3, 194, 84, 33, 84, 240, 2 }, + { -3, 194, 84, 33, 172, 236, 2 }, + { 902, 254, 114, 34, 0, 224, 3 } + } + }, + { /* FM region 89 */ + { 34, 0, 127 }, 64, 169, 170, 0, + { + { -3, 83, 69, 34, 184, 212, 0 }, + { -7500, 50, 69, 33, 176, 244, 3 }, + { 3, 81, 69, 34, 212, 212, 2 }, + { -8500, 66, 69, 33, 176, 244, 3 } + } + }, + { /* FM region 90 */ + { 34, 0, 127 }, 64, 120, 221, 0, + { + { -2, 82, 69, 34, 244, 216, 0 }, + { 0, 145, 102, 33, 228, 240, 0 }, + { 2, 81, 69, 34, 244, 208, 2 }, + { 0, 145, 102, 33, 224, 240, 2 } + } + }, + { /* FM region 91 */ + { 35, 0, 127 }, 32, 138, 14, 0, + { + { 2400, 148, 67, 34, 176, 200, 0 }, + { 3, 194, 85, 33, 220, 236, 2 }, + { -3, 194, 69, 33, 220, 236, 2 }, + { 1905, 254, 114, 34, 48, 224, 2 } + } + }, + { /* FM region 92 */ + { 34, 0, 127 }, 82, 67, 71, 0, + { + { 2982, 228, 22, 146, 88, 192, 3 }, + { 3, 102, 84, 146, 196, 240, 2 }, + { 3358, 50, 149, 116, 144, 208, 2 }, + { -3, 85, 84, 146, 120, 240, 0 } + } + }, + { /* FM region 93 */ + { 37, 0, 127 }, 48, 126, 219, 0, + { + { -3, 49, 19, 33, 120, 200, 0 }, + { 0, 81, 70, 33, 220, 240, 0 }, + { 3804, 242, 18, 50, 200, 200, 0 }, + { 1203, 82, 19, 82, 200, 176, 0 } + } + }, + { /* FM region 94 */ + { 35, 0, 127 }, 32, 138, 13, 0, + { + { 2786, 116, 67, 34, 204, 184, 0 }, + { 1902, 114, 69, 33, 192, 232, 2 }, + { -3, 178, 69, 33, 188, 232, 2 }, + { 3804, 254, 82, 34, 164, 228, 2 } + } + }, + { /* FM region 95 */ + { 34, 0, 127 }, 48, 135, 238, 0, + { + { -2, 34, 85, 34, 184, 224, 0 }, + { 1, 113, 70, 33, 228, 236, 0 }, + { 2, 19, 85, 34, 156, 224, 2 }, + { -1, 129, 70, 33, 224, 236, 2 } + } + }, + { /* FM region 96 */ + { 50, 0, 127 }, 240, 112, 221, 0, + { + { 3369, 213, 69, 32, 0, 204, 0 }, + { 0, 193, 70, 33, 112, 232, 2 }, + { 0, 145, 69, 34, 244, 208, 2 }, + { -9000, 145, 70, 33, 224, 236, 3 } + } + }, + { /* FM region 97 */ + { 34, 0, 127 }, 96, 122, 168, 0, + { + { -1, 99, 51, 33, 200, 208, 0 }, + { -8500, 81, 83, 33, 232, 240, 3 }, + { 702, 99, 52, 33, 200, 208, 2 }, + { -9500, 65, 83, 34, 224, 240, 3 } + } + }, + { /* FM region 98 */ + { 34, 0, 127 }, 0, 67, 0, 0, + { + { 1500, 217, 55, 151, 20, 224, 2 }, + { 3, 231, 70, 146, 88, 220, 2 }, + { 2369, 115, 148, 151, 32, 196, 2 }, + { -3, 118, 36, 146, 64, 244, 2 } + } + }, + { /* FM region 99 */ + { 34, 0, 127 }, 64, 169, 204, 0, + { + { -3, 228, 69, 34, 148, 220, 0 }, + { -7448, 243, 69, 33, 200, 240, 3 }, + { 3, 81, 68, 34, 212, 212, 2 }, + { -8526, 65, 68, 33, 196, 240, 3 } + } + }, + { /* FM region 100 */ + { 34, 0, 127 }, 64, 119, 187, 0, + { + { 2786, 228, 22, 146, 176, 192, 0 }, + { 3, 102, 68, 146, 196, 236, 2 }, + { 3369, 178, 149, 116, 176, 208, 2 }, + { -3, 231, 68, 146, 120, 240, 0 } + } + }, + { /* FM region 101 */ + { 34, 0, 127 }, 240, 144, 239, 0, + { + { -2, 49, 69, 34, 236, 208, 2 }, + { -9000, 113, 102, 33, 228, 236, 3 }, + { 2400, 149, 69, 34, 12, 216, 1 }, + { 0, 145, 102, 33, 224, 236, 2 } + } + }, + { /* FM region 102 */ + { 50, 0, 127 }, 241, 176, 6, 0, + { + { 1200, 247, 49, 64, 252, 204, 0 }, + { 3804, 246, 101, 32, 0, 232, 2 }, + { 1902, 247, 32, 32, 112, 188, 2 }, + { 0, 228, 84, 32, 0, 240, 2 } + } + }, + { /* FM region 103 */ + { 37, 0, 127 }, 64, 101, 221, 0, + { + { 1, 194, 68, 97, 196, 200, 2 }, + { -10001, 247, 100, 114, 176, 240, 3 }, + { 3370, 213, 33, 70, 52, 200, 2 }, + { -1, 178, 68, 49, 208, 212, 0 } + } + }, + { /* FM region 104 */ + { 34, 0, 127 }, 0, 255, 203, 0, + { + { -3, 245, 82, 99, 200, 232, 2 }, + { 2787, 244, 84, 96, 0, 236, 2 }, + { 1198, 133, 81, 100, 196, 220, 2 }, + { 1902, 147, 67, 80, 0, 232, 2 } + } + }, + { /* FM region 105 */ + { 37, 0, 127 }, 0, 255, 140, 0, + { + { 500, 255, 137, 179, 0, 200, 3 }, + { 1902, 248, 90, 160, 0, 244, 2 }, + { 3804, 245, 57, 35, 164, 204, 2 }, + { 0, 245, 38, 51, 196, 208, 2 } + } + }, + { /* FM region 106 */ + { 37, 0, 127 }, 0, 255, 72, 0, + { + { 1000, 238, 57, 65, 0, 188, 3 }, + { 1902, 247, 103, 112, 0, 244, 2 }, + { 2786, 250, 36, 81, 68, 212, 2 }, + { 0, 249, 50, 49, 172, 204, 2 } + } + }, + { /* FM region 107 */ + { 37, 0, 127 }, 16, 119, 72, 0, + { + { 1500, 255, 89, 65, 0, 196, 3 }, + { 2790, 246, 39, 112, 0, 240, 0 }, + { 1905, 246, 36, 81, 168, 208, 0 }, + { 0, 249, 114, 49, 172, 212, 0 } + } + }, + { /* FM region 108 */ + { 37, 0, 127 }, 0, 255, 237, 0, + { + { 1902, 254, 89, 65, 0, 212, 2 }, + { 0, 248, 87, 112, 0, 240, 2 }, + { 3369, 231, 62, 81, 0, 208, 2 }, + { 3, 245, 118, 49, 96, 196, 2 } + } + }, + { /* FM region 109 */ + { 34, 0, 127 }, 16, 188, 205, 0, + { + { -2, 179, 47, 50, 244, 224, 2 }, + { 1900, 145, 94, 49, 248, 232, 2 }, + { 3, 210, 46, 2, 244, 208, 2 }, + { 2789, 133, 93, 4, 180, 244, 2 } + } + }, + { /* FM region 110 */ + { 37, 0, 127 }, 48, 135, 220, 0, + { + { 1901, 162, 25, 35, 144, 208, 0 }, + { 0, 113, 105, 65, 220, 240, 0 }, + { 3369, 233, 88, 51, 120, 212, 0 }, + { 0, 229, 24, 84, 200, 208, 0 } + } + }, + { /* FM region 111 */ + { 34, 0, 127 }, 112, 32, 190, 0, + { + { 0, 53, 79, 66, 152, 212, 2 }, + { 1200, 53, 75, 64, 136, 244, 2 }, + { 500, 149, 60, 66, 16, 208, 2 }, + { 1902, 200, 78, 64, 0, 248, 0 } + } + }, + { /* FM region 112 */ + { 37, 0, 127 }, 0, 144, 130, 0, + { + { 2514, 255, 68, 53, 0, 204, 2 }, + { 2400, 247, 133, 48, 0, 240, 2 }, + { 4151, 243, 67, 50, 0, 212, 2 }, + { 3369, 243, 66, 56, 0, 204, 2 } + } + }, + { /* FM region 113 */ + { 37, 0, 127 }, 0, 255, 0, 0, + { + { 514, 253, 79, 51, 0, 196, 3 }, + { 1905, 252, 89, 51, 0, 244, 2 }, + { 4349, 245, 35, 51, 0, 208, 2 }, + { 1205, 247, 34, 51, 0, 208, 2 } + } + }, + { /* FM region 114 */ + { 37, 0, 127 }, 0, 255, 0, 0, + { + { 514, 221, 69, 35, 0, 204, 3 }, + { 0, 250, 86, 115, 0, 252, 2 }, + { 1884, 244, 116, 51, 0, 200, 2 }, + { 1208, 210, 35, 51, 0, 208, 2 } + } + }, + { /* FM region 115 */ + { 37, 0, 127 }, 0, 255, 16, 0, + { + { 514, 222, 85, 163, 0, 192, 3 }, + { 0, 254, 108, 163, 0, 252, 2 }, + { 3800, 255, 143, 160, 0, 176, 2 }, + { 1200, 250, 105, 163, 0, 212, 2 } + } + }, + { /* FM region 116 */ + { 37, 0, 127 }, 0, 255, 16, 0, + { + { 1514, 249, 101, 163, 0, 204, 3 }, + { -1200, 249, 87, 160, 0, 252, 2 }, + { 0, 235, 143, 160, 0, 204, 2 }, + { 1200, 234, 73, 163, 0, 204, 2 } + } + }, + { /* FM region 117 */ + { 37, 0, 127 }, 0, 255, 16, 0, + { + { 500, 239, 101, 160, 0, 204, 3 }, + { -1195, 248, 104, 160, 0, 252, 2 }, + { 1898, 252, 72, 163, 0, 216, 2 }, + { 1239, 248, 87, 163, 0, 196, 2 } + } + }, + { /* FM region 118 */ + { 37, 0, 127 }, 0, 255, 255, 0, + { + { 500, 255, 98, 160, 0, 196, 3 }, + { -1, 249, 105, 160, 0, 252, 2 }, + { 1907, 250, 71, 160, 0, 252, 2 }, + { 1182, 249, 87, 161, 0, 192, 2 } + } + }, + { /* FM region 119 */ + { 37, 0, 127 }, 0, 0, 100, 0, + { + { 600, 32, 15, 0, 252, 224, 6 }, + { 0, 47, 111, 65, 0, 244, 2 }, + { 1826, 16, 47, 0, 252, 216, 2 }, + { 3551, 240, 47, 0, 252, 212, 2 } + } + }, + { /* FM region 120 */ + { 52, 0, 127 }, 240, 128, 235, 0, + { + { 1228, 161, 47, 17, 196, 200, 3 }, + { 3000, 123, 75, 17, 0, 240, 2 }, + { 7022, 72, 43, 17, 0, 216, 0 }, + { 4000, 150, 79, 17, 48, 196, 3 } + } + }, + { /* FM region 121 */ + { 37, 0, 127 }, 224, 16, 86, 0, + { + { 275, 251, 6, 0, 36, 200, 2 }, + { 0, 101, 104, 65, 56, 240, 2 }, + { 0, 240, 6, 0, 252, 208, 6 }, + { 1000, 195, 8, 0, 248, 200, 2 } + } + }, + { /* FM region 122 */ + { 34, 0, 127 }, 0, 0, 185, 0, + { + { 600, 35, 66, 17, 72, 224, 4 }, + { -13000, 81, 67, 17, 228, 244, 2 }, + { 702, 97, 38, 17, 212, 196, 6 }, + { -14000, 81, 65, 17, 224, 244, 3 } + } + }, + { /* FM region 123 */ + { 50, 0, 127 }, 240, 112, 237, 0, + { + { -6528, 153, 127, 16, 0, 252, 3 }, + { 1200, 105, 109, 16, 0, 216, 2 }, + { -6022, 179, 139, 17, 0, 248, 3 }, + { 2000, 104, 79, 17, 0, 240, 0 } + } + }, + { /* FM region 124 */ + { 50, 0, 127 }, 240, 240, 16, 0, + { + { 1914, 240, 64, 160, 240, 208, 2 }, + { 1200, 240, 73, 163, 240, 244, 0 }, + { 1900, 240, 64, 160, 240, 148, 2 }, + { 4151, 240, 73, 163, 240, 244, 0 } + } + }, + { /* FM region 125 */ + { 34, 0, 127 }, 240, 56, 235, 0, + { + { -5522, 97, 32, 17, 196, 240, 3 }, + { 0, 84, 75, 17, 180, 248, 3 }, + { 702, 65, 38, 17, 224, 212, 6 }, + { -4000, 161, 73, 17, 224, 252, 1 } + } + }, + { /* FM region 126 */ + { 53, 0, 127 }, 240, 248, 37, 0, + { + { 1050, 243, 0, 0, 252, 224, 7 }, + { 2000, 49, 68, 0, 224, 236, 3 }, + { 350, 240, 0, 0, 252, 216, 1 }, + { 700, 240, 0, 0, 252, 212, 3 } + } + }, + { /* FM region 127 */ + { 53, 0, 127 }, 240, 248, 37, 0, + { + { 1050, 245, 85, 0, 0, 244, 7 }, + { -5000, 247, 71, 0, 0, 252, 3 }, + { 350, 240, 0, 0, 0, 164, 0 }, + { 700, 32, 0, 0, 0, 252, 2 } + } + }}; /* end FM Regions */ + +/*---------------------------------------------------------------------------- + * Programs + *---------------------------------------------------------------------------- +*/ +const S_PROGRAM eas_programs[] = +{ + { 7864320, 0 } /* program 0 */ +}; /* end Programs */ + +/*---------------------------------------------------------------------------- + * Banks + *---------------------------------------------------------------------------- +*/ +const S_BANK eas_banks[] = +{ + { /* bank 0 */ + 30976, + { + 32768, 32769, 32770, 32771, 32772, 32773, 32774, 32775, + 32776, 32777, 32778, 32779, 32780, 32781, 32782, 32783, + 32784, 32785, 32786, 32787, 32788, 32789, 32790, 32791, + 32792, 32793, 32794, 32795, 32796, 32797, 32798, 32799, + 32800, 32801, 32802, 32803, 32804, 32805, 32806, 32807, + 32808, 32809, 32810, 32811, 32812, 32813, 32814, 32815, + 32816, 32817, 32818, 32819, 32820, 32821, 32822, 32823, + 32824, 32825, 32826, 32827, 32828, 32829, 32830, 32831, + 32832, 32833, 32834, 32835, 32836, 32837, 32838, 32839, + 32840, 32841, 32842, 32843, 32844, 32845, 32846, 32847, + 32848, 32849, 32850, 32851, 32852, 32853, 32854, 32855, + 32856, 32857, 32858, 32859, 32860, 32861, 32862, 32863, + 32864, 32865, 32866, 32867, 32868, 32869, 32870, 32871, + 32872, 32873, 32874, 32875, 32876, 32877, 32878, 32879, + 32880, 32881, 32882, 32883, 32884, 32885, 32886, 32887, + 32888, 32889, 32890, 32891, 32892, 32893, 32894, 32895 + } + } +}; /* end Banks */ + +/*---------------------------------------------------------------------------- + * Samples + *---------------------------------------------------------------------------- +*/ + +const EAS_SAMPLE eas_samples[] = +{ + 13, -24, 28, -32, 33, -37, 39, -61, 119, -76, 120, -70, 99, -122, 89, -113, + 91, -123, 122, -123, 77, 86, -116, 6, -118, 123, -23, 64, -93, 17, 24, -125, + 124, -125, 124, -24, -12, 56, 87, -54, 38, -91, 64, -2, -41, 126, -127, 20, + 8, -48, -62, 127, -128, 88, -43, -18, 86, -100, 44, -32, -26, 71, -13, 6, + 51, -33, -50, 106, -59, 33, 5, -20, 69, -56, 54, -48, -6, 38, -5, -38, + 35, -1, 12, -1, 4, 23, -56, 19, -7, 5, -4, 31, -38, 3, -12, -9, + -25, -7, 24, -32, 17, -21, -22, 24, -20, 6, -18, 0, -15, 5, -16, 15, + 3, 2, -10, 3, 27, -31, 37, -12, 32, -5, 2, -21, 27, -14, 20, -8, + 5, 15, -7, -11, 20, -37, 7, -23, 17, -22, 11, -14, 8, -44, 39, -52, + 26, 3, 14, -10, 51, -45, 29, -19, 19, -3, 41, -21, 46, -23, 10, 16, + -25, 3, 7, -30, 19, -9, -5, -1, 1, -19, 1, -24, -23, 51, -48, -10, + 17, -34, -38, 60, -71, 26, -43, 65, -59, 70, -26, 61, -51, 63, -51, 42, + -25, 58, -36, 31, 10, -14, -9, 8, -18, 8, 4, 8, 7, 31, -52, 39, + -53, 53, -56, 24, 11, 1, -20, -8, -32, -18, -10, -25, 4, 1, 37, -37, + 42, -42, 53, -57, 52, -18, 30, 11, 20, -52, 55, -61, 56, -50, 24, -26, + 38, -42, 36, -1, -43, 58, -46, 6, 18, -35, 31, -36, 28, -55, 55, -98, + 52, -41, 26, -24, 48, -31, 48, -26, 30, 19, -17, 23, -8, 13, 15, 19, + -7, -23, 41, -36, 20, -39, 65, -64, 66, -38, -9, 7, -14, -10, -3, 6, + 15, -19, -40, 53, -67, -11, -12, -25, 23, -11, -12, 46, -48, 39, -20, 20, + -14, 31, -54, 71, -25, 2, -8, -5, -9, 1, 7, 27, 17, -14, 43, -31, + 27, 11, -33, 20, -2, -33, 45, -38, 17, -9, -11, -17, -22, -19, 20, -25, + 4, 29, -35, 14, -17, 1, -7, 19, 2, 16, 32, -3, -17, 4, 0, -9, + 17, 5, -8, 52, -32, 40, -39, -5, -18, 14, -21, 31, 10, -17, 8, -34, + -7, 1, -44, 7, 10, -8, -6, -18, -25, -1, -19, 16, -29, 62, 6, 9, + 21, 0, -14, 4, 5, 20, 13, 27, -1, 18, -5, 21, -31, 11, 2, -9, + -4, 21, -27, 8, -21, -28, -19, 14, -12, 5, -20, 20, -36, 4, -18, -27, + -4, -4, 15, 4, 48, -7, -11, 20, -6, 7, 20, 1, 20, 0, 35, -35, + 28, -37, 7, -43, 21, -22, 23, -18, 12, -22, -13, -20, -11, 7, 23, -10, + 19, -18, 17, -41, 4, -16, -8, 21, 11, -4, 10, 30, -24, 32, -15, 15, + -13, 28, -5, 38, -10, 0, -22, -13, -12, 24, -18, 30, -7, 4, -16, 27, + -28, -3, -1, 18, -14, 31, -24, -3, -13, -19, -36, -2, -31, 9, -2, -12, + 17, 12, -50, 46, -49, 43, -15, 13, 22, 15, -25, 10, -8, -6, 14, -2, + 24, 15, 9, 17, -13, 5, 14, -15, 7, 20, 4, 4, 18, -16, 3, -47, + 31, -46, 19, -24, 5, -19, -1, -42, 14, -44, 18, -7, -1, 15, 9, -35, + 32, -44, 39, -46, 23, -16, 36, -25, 45, -34, 32, -8, 10, 5, 28, 0, + 12, 11, 3, 20, -23, 6, -8, 16, 7, 17, -19, 32, -44, 3, -8, -21, + -8, -5, 2, -29, 2, -3, -19, -14, 3, 7, -23, 10, 1, 3, 8, 13, + -44, 20, 21, -16, 23, 3, 5, 10, -11, 32, -11, 13, -7, 30, 4, 16, + -7, -6, -7, 14, -40, 4, -16, -26, 3, -1, 0, -6, 5, -50, 37, -27, + 18, -16, -14, 6, -1, -4, -15, 8, -12, 14, 9, -22, 42, -10, 23, -11, + 36, -15, 13, 30, 1, 47, -20, 33, -14, -12, 1, -20, -9, -9, -11, -13, + 7, -37, 25, -47, 14, -13, 4, -12, 9, -32, 18, -48, -1, -35, -1, -7, + 35, -20, 53, -4, 34, -7, 13, 19, 9, 30, 6, 45, -22, 23, -18, -6, + -1, 3, -30, 14, -15, 9, -39, 10, -33, -13, -24, 10, 14, 14, -10, 2, + -34, -4, -20, -21, -14, 40, -10, 17, -14, 28, -17, 37, -26, 69, -15, 38, + 2, 21, -25, 37, -61, 13, -9, 5, -17, 18, -41, 22, -57, -1, -9, -13, + 24, -10, 38, -5, 8, -16, -2, 1, 12, -25, -2, -13, 2, 2, -16, -19, + 32, -30, 22, 20, -4, 12, 11, -17, 19, -17, -3, 20, -33, 65, -27, 32, + -14, 8, -8, 13, -19, 9, -2, 7, 33, -40, 18, -18, -18, 6, -23, -11, + -11, -28, 4, -11, -15, -14, -8, -5, 34, -6, 19, 1, -3, 9, -1, 5, + 5, 14, -11, 40, -3, 18, -20, 16, -7, 2, -5, 9, -16, 9, -17, 0, + -17, 4, -17, -3, 3, 8, -14, -19, 12, -21, -7, 1, -2, -8, 16, 3, + -6, 35, -23, 33, -13, 11, 12, 3, -7, 26, -11, 19, -18, 23, -22, 39, + -49, 39, -50, 11, -38, 26, -29, 10, -6, -22, 15, -8, 15, -37, 36, -43, + 39, -43, 18, -26, 1, 11, 4, -2, 9, 7, 2, 7, 19, 1, 1, -4, + 16, -5, 16, -9, -3, 4, -4, -1, -17, 0, 11, 16, -27, 12, -15, 15, + -3, 0, 10, -3, -5, 12, -13, -7, -13, -31, -1, -3, -17, 15, -31, 25, + -10, 15, -1, 2, 4, 10, 7, 32, -13, 7, -22, 2, -10, 16, 1, -15, + 19, -24, 16, -18, -12, 18, -9, 9, 24, -8, 8, 11, 0, -31, 17, -55, + 21, -43, 40, -40, 29, -54, 44, -34, 22, 11, 16, 7, 19, 21, -6, 2, + -7, -16, 22, 0, -1, -4, 5, -8, 26, -42, 4, -6, -21, 35, -16, 8, + 0, -22, -13, 11, -31, 7, -28, 4, 17, -12, -18, -2, -23, 23, -1, 19, + 34, 7, 7, 35, -19, 11, -8, -17, 8, 4, 16, -16, -13, 9, -15, -5, + -1, -6, 7, 3, 11, 1, -7, -24, 21, -31, 36, -3, -10, 8, 2, -17, + 12, -24, 6, -3, 9, 15, 3, 13, -8, -13, -3, 6, -19, 14, -33, 16, + -17, -5, -31, 3, -29, 24, -7, -6, 35, -20, -5, 34, -20, 25, -3, 10, + 25, 8, 14, -13, 0, 1, 17, -33, 51, -38, 45, -32, 39, -3, -2, -24, + 3, -18, 14, -4, -44, 2, -25, -15, -2, -23, 3, -2, -2, 20, -14, 8, + -10, -4, 21, 11, -13, 32, -4, 8, 19, -16, -2, -2, -2, 14, -2, -1, + 27, -26, 20, 11, -13, 10, -3, -7, 12, -13, -3, -30, -16, 10, -26, -3, + -10, -2, -9, 15, -17, 1, -2, -7, 14, -8, 12, -3, -1, 2, 47, -26, + 22, -19, 16, 2, 13, -3, 21, -10, 22, -32, 43, -24, 16, 0, 5, -2, + 12, -44, -12, 1, -26, 1, -36, 5, 2, 9, -17, 20, -37, 14, -9, -5, + 6, -3, -13, 23, -19, 25, -33, 6, 17, 10, 19, 15, -4, 12, 5, -9, + 33, -20, 26, -9, 11, -2, 11, -21, -7, -13, -4, -8, -12, 0, -10, -9, + 8, -33, 9, -26, 8, 6, -8, 12, 7, -8, 0, 7, -16, 25, -8, 27, + 12, 0, 9, -9, 4, -17, 14, -16, 11, -8, 18, -2, 4, 2, -20, -18, + 22, -16, -5, 3, -24, 13, -10, -12, -10, 2, -16, 33, -15, 21, -15, -4, + -19, 29, -22, 18, 2, 20, 12, 18, -22, -7, -16, 7, -19, 14, 1, -17, + 33, -22, 38, -8, 3, -3, 21, -17, 51, -43, 15, -22, -23, -6, -12, -14, + 14, 9, 6, 4, -31, 3, -16, -14, 22, -22, 5, 13, -25, 17, -2, -18, + 7, 1, 5, 36, -16, 23, 4, -15, 29, -20, 10, 1, 24, 17, 16, -4, + -16, -37, -11, 1, -33, 27, -36, 17, -22, 2, -33, 16, -29, 32, -7, 24, + -12, 14, -12, 22, -16, 15, -20, 19, 9, 14, 12, -1, -24, 13, -6, -1, + 32, -19, 24, 12, -26, 4, -31, -38, 18, -16, -13, 3, -14, -1, 11, -15, + 15, 0, -2, 30, -6, 35, -23, 10, -35, 5, -14, 17, -21, 20, 4, 7, + 8, -5, -15, 20, -25, 26, 6, -3, 3, 5, -24, 26, -35, 4, 0, -6, + 13, -23, 8, -25, 1, -2, 9, 3, 17, 4, 0, 13, -15, 3, -21, -16, + 4, -5, -10, 11, -2, 7, 23, -22, 25, -19, 18, 25, -9, 14, -21, -7, + 11, -24, 22, -12, -7, 6, 9, -33, 11, -20, 2, -9, 2, 3, -13, 12, + -15, 23, -21, 16, -16, -2, 8, 13, -12, 18, -10, 16, -12, 20, -18, 18, + -1, 21, -21, 20, -30, -6, 10, -2, 13, -6, -15, 6, 2, -1, 1, -19, + 9, -15, -3, -11, 0, -5, 1, 5, 1, -4, -8, 1, -16, 23, 0, -23, + 2, 8, -6, 38, -4, 2, 13, -17, 31, -4, -8, 22, -14, 0, 12, -22, + 7, -7, 11, 4, -4, -12, -9, -22, 2, -17, -17, -11, 7, -17, 19, -24, + 9, -8, -6, 29, -4, 10, 4, 4, 23, -1, 9, -6, -12, 23, 16, -6, + 33, -29, 12, -7, -10, 17, -4, -18, 21, 0, -14, -2, -20, -21, 10, -28, + 5, -18, -4, 0, -11, 1, 5, -17, 3, 9, 20, 6, 1, -7, 2, -7, + 3, 9, -22, 29, 6, -1, 25, -10, 6, -1, 4, 12, 18, -13, 28, -11, + 6, -15, -14, -22, -7, 5, -14, 1, -16, -12, -5, 5, -9, 4, -1, -14, + 21, -10, -5, 0, -17, -7, 2, -10, 6, 11, 1, 37, -17, 6, 21, -24, + 41, 2, 23, 0, 10, -18, 16, -26, 14, -21, -19, 18, -9, -14, -1, -9, + -14, -3, -7, -10, 7, -7, 19, -11, 15, -25, -3, -6, 2, 8, -10, 4, + 12, -3, 11, -2, -2, 5, 31, -9, 39, -21, 14, -23, 18, -16, -1, -3, + -6, 0, 22, -9, -5, -17, -4, -12, 2, -3, -7, 10, -10, 7, -20, -19, + -10, 0, -14, 32, -15, -18, 13, -9, 2, 17, -14, 6, 36, -9, 28, 1, + 0, 17, -10, 5, 17, -8, 12, -2, 3, 2, -22, -6, -14, 6, 8, -11, + -14, 2, -23, 25, -35, 3, -18, 1, -14, 22, -1, -12, -7, -9, 13, -4, + 12, 4, -3, 18, 0, 1, 8, -14, 14, -2, 1, 17, -3, -14, 35, -17, + 19, -14, -6, 1, -9, 18, -17, -4, -13, -2, -14, 10, -10, -6, 0, 3, + 5, -12, -13, -3, -6, -6, 11, -13, -7, 13, -2, 6, 13, -7, 11, -5, + 23, 1, 29, -17, 23, -10, 18, -16, 12, -20, 10, 7, -9, -5, -21, -9, + 5, -13, -2, 0, -15, -11, 3, 0, -18, 5, -25, -2, 3, -2, -3, 4, + 8, 14, -7, 15, 4, 8, 19, 9, 11, 7, -3, 14, -11, 1, 15, -35, + 3, 3, -10, -16, 0, -15, 2, 3, -12, 27, -23, 32, -15, 10, -14, 3, + -27, 10, -15, 12, -24, 7, 2, 9, -2, -2, -1, 3, 1, 1, 8, -4, + 0, 6, -6, 1, 1, -1, 8, -11, 31, -27, 13, 4, -3, 5, -1, 0, + 2, 9, 0, 12, -31, 4, -27, 1, -25, 20, -21, -14, 12, -14, 0, -5, + -23, 18, -1, 15, 19, -5, 20, -8, 14, -7, 16, 3, 0, 8, 10, 0, + -8, -10, 3, -8, 9, -12, 4, 15, -6, 2, -12, -29, -3, -16, -11, 35, + -18, -1, -28, 7, -12, 0, 7, -5, 22, 10, 10, -4, 6, -13, 21, -23, + 20, 8, -13, 11, 15, -6, -6, -22, -1, 3, 14, 7, 11, -27, 12, -17, + -12, 8, -15, 3, -8, 12, -12, 5, -30, 12, -18, 9, -2, 3, 4, 15, + 1, 5, -9, 0, -8, 24, -2, 21, 5, -4, -4, 14, -15, 0, -1, 3, + 17, -5, 13, -19, -10, -4, -6, -4, -7, 18, -27, 8, 1, -12, -21, -13, + 1, -9, 11, 1, -3, -1, 22, -21, 9, 6, -3, 20, -2, 17, 7, -12, + 1, 4, 4, -9, 9, -20, 24, 7, -9, -3, -7, -6, 10, 7, 3, 9, + -2, -3, -4, 1, -19, -8, -16, 0, -12, 0, -25, 4, -22, 10, -9, 0, + -3, 15, -1, 8, 11, -15, 10, 13, 1, 22, -5, 15, 1, 24, 6, 0, + -6, 5, 5, 10, 8, -1, -11, -14, 3, -31, 2, -22, -4, -8, -15, -2, + -31, -12, 6, -7, 5, 2, 3, -4, 19, 3, 4, 7, 7, -8, 31, -6, + 26, 1, -2, 2, -3, -10, -4, -4, 9, 3, 12, -16, 16, -9, -1, 5, + 4, -7, 13, -17, 0, -11, -13, -22, 1, -9, 4, -7, 7, -10, 5, -1, + -6, -3, -21, 7, -10, 18, -3, 1, -7, -11, 11, -8, 12, 20, 3, 13, + 16, -1, 3, 13, -3, 23, 16, -3, 15, -14, 12, -6, -8, -28, 0, -33, + 4, -11, -12, -13, -21, -17, -16, -5, -12, 16, -7, 15, -6, -5, 3, -9, + 21, 17, 13, 14, 11, 21, -12, 31, -18, 7, 12, 8, 9, 7, 1, -3, + -7, -14, 17, -35, -10, -2, -18, -8, -10, -20, -22, 2, -10, -3, 1, -1, + 4, -5, 11, -20, 11, -6, 27, 7, 18, 8, -1, 2, 3, 11, -9, 5, + 5, -7, 29, -6, 20, -21, 23, -15, 19, -19, 2, -22, 11, -26, -7, -10, + -30, -1, -3, -6, 15, -22, 16, -7, -9, -2, -7, -5, 11, 17, -13, 2, + 8, -5, 6, 27, -6, 12, -6, 4, 15, 3, 14, -3, -12, 11, -2, 6, + 5, 4, -6, -12, 0, -32, 2, -22, 22, -12, -5, -7, -11, -7, 6, -1, + -3, -3, -16, 2, -1, 0, 0, -7, -2, 1, 12, -4, 5, 20, 1, 16, + -2, 14, -1, 19, 8, 29, -8, 7, -14, -2, 3, -13, 8, -40, 22, -18, + 2, -14, -8, -11, -8, 12, -21, -1, -10, -12, -6, -4, -14, 6, -19, 7, + 14, 1, 11, 11, -11, 25, 1, 14, -5, 31, 0, 22, 4, 1, 3, 6, + -3, 4, -2, -20, -7, -26, 1, -12, -7, -10, 2, -1, -5, -7, -8, -10, + 6, -7, -6, 10, -17, 6, 3, 15, -8, 15, -7, 12, 1, 9, -4, -2, + 10, 9, -1, 10, -4, 9, -8, 17, 0, -13, -7, -2, -11, 3, -2, -15, + -4, -11, -5, -9, 1, 8, -10, 8, -8, -6, -18, 21, -19, 26, -19, -1, + -11, 10, 4, 12, -10, 16, -10, 17, 8, 13, -1, 17, 1, 5, -1, 11, + -8, 9, 16, -17, 3, -26, -17, -14, 6, -17, 4, -20, 0, -1, -6, -4, + 2, -15, 13, -3, -1, 0, -2, -8, 11, 7, -3, -8, 5, 14, -1, 28, + -19, 13, -4, 8, 1, 11, 7, 6, -8, -2, -13, -10, -22, 6, 11, -1, + -1, -5, -13, 18, 3, -10, 9, -17, -8, 9, -9, 1, -17, -4, -16, 18, + -6, 15, -10, 17, 5, 0, -5, 0, -11, 12, 15, 4, 8, 5, -4, 0, + -2, 3, -17, -2, -1, 11, -6, -7, 2, -33, 23, -6, -1, -2, -2, -1, + -8, 3, -29, -2, -34, 16, -3, 16, 1, 10, -12, 23, 0, -3, 16, 12, + 19, 23, -1, 8, -26, 16, -32, 26, -13, 2, -11, 5, -1, -15, -9, -16, + 7, -6, 14, -15, 5, -10, -7, -9, -9, 6, -17, 13, 18, -5, -3, -4, + -4, -18, 28, -6, 13, 17, 24, -2, 9, -14, 1, -11, 7, 17, 1, -15, + 10, -23, -4, -12, 5, -20, 17, -10, 6, 0, -9, 4, -8, -15, 6, -16, + 7, 9, 3, 6, -12, -17, 0, 4, 13, 22, -4, 10, -8, 7, -12, 5, + 5, 1, 11, 2, 10, -3, -2, 3, -10, -5, -7, -4, -18, 17, -2, -14, + -16, -7, -10, -3, 6, -1, 14, -11, 15, -18, 2, -6, 0, -1, 0, 20, + -17, 1, 6, 2, 6, 12, -3, 7, 25, -5, 17, -14, 0, -6, 0, -2, + -5, -1, -10, 8, 2, -9, -19, -7, -17, 5, 3, -7, 4, -15, -5, 9, + -12, -1, -5, 3, -5, 26, -2, 3, -4, 5, 3, 7, 10, 5, 6, 6, + 26, -17, 0, -1, 3, -3, 10, -7, -7, -9, 11, -18, 0, -16, -6, -5, + 3, 7, -14, -14, 0, -21, 14, -8, -1, -12, 2, 1, 2, -3, -1, -3, + 18, 5, 5, 9, 12, 7, 18, 8, 5, -25, 16, -15, 16, -7, 9, -22, + 1, 14, -13, -5, 2, -6, -8, 13, -17, 6, -16, 1, -5, -14, -6, -6, + -15, -2, 9, -9, -18, 15, -19, 12, 7, 4, 8, 14, 15, 6, 10, -3, + 9, -7, 23, -17, 21, -20, 7, 0, -9, 8, -10, 1, 4, 2, 3, -9, + -9, -15, -6, -21, -16, -6, 0, -11, 19, -8, -9, 5, -6, 0, 5, 14, + 7, 1, 12, 8, 7, -5, 12, 8, -4, 19, 4, -7, 2, 3, -12, -8, + -1, 0, 5, 7, -5, -8, -22, -8, -21, -2, -9, 10, -20, 13, -6, 8, + -17, -9, -6, 2, 5, 8, 6, -3, 10, -9, -2, 15, -6, 20, 7, 11, + 10, -3, -4, -8, 25, -25, 18, -12, 17, -6, 20, -22, -1, -17, -10, 5, + -10, 9, -13, -9, -6, 10, -25, -5, -2, -5, 13, 2, -5, -8, -10, 11, + -27, 10, -4, 11, 0, 33, -4, 10, -14, 1, 12, -2, 27, -8, 6, 11, + 9, -12, -4, -10, -13, 12, 5, 1, -10, -14, -15, -8, -7, -9, 3, -5, + 10, 3, -11, -12, -13, -3, -3, 3, 2, 9, 17, -6, 25, -3, -3, -8, + 19, 3, 30, -10, 12, -22, 7, -5, -10, -3, 21, -8, 12, 6, -5, -13, + -13, -9, -9, -1, -23, 13, -17, 15, -22, -11, -18, 8, -14, 20, 1, 4, + -5, 3, 3, 5, 11, 1, 2, 27, 1, 10, -7, -8, -2, -2, 7, -1, + 17, -5, 24, -7, 5, -10, -20, -6, 5, -4, -5, -1, -18, -5, -14, -1, + -20, 1, 7, -7, 12, -4, -2, -4, 2, 8, 0, 7, 1, 6, -2, 18, + -5, -7, 4, 3, -2, 13, 4, 0, 2, -3, 2, -10, -6, 1, -6, 6, + -7, -3, -21, -2, -12, 5, -1, -9, 7, -3, 13, 5, 5, -8, 0, -8, + 19, -5, 13, 13, -7, 3, 0, -10, 0, -8, 20, -8, 13, -20, -5, -7, + 3, 5, -7, 2, -5, -4, -14, 11, -23, -13, 2, -1, 12, 13, 5, -6, + 23, -9, 9, -6, -9, 18, -13, 16, -3, -7, -17, 3, -13, 12, -9, 4, + 0, 0, 13, -18, -1, 3, -13, 20, -5, 1, -20, 15, -23, 18, -4, -8, + 5, -7, 16, 4, 6, -3, 7, -21, 19, -17, -7, 9, 5, 3, -5, -3, + -16, -9, 25, -9, 12, -5, 10, -5, 9, -4, -6, -3, 4, 10, -2, 11, + -12, -2, -14, 8, -23, -5, 0, -8, 9, -2, -11, -3, -9, 9, 2, 2, + 4, -5, 7, 11, -16, 0, -6, 7, 6, 25, 5, 6, -4, 3, 4, 3, + 2, -8, -3, 5, -1, -11, -4, -9, -3, -15, 10, -12, -5, 11, -4, -7, + 6, -29, -5, 6, 11, 3, 9, -18, 13, -14, 19, -1, -2, 4, 5, 12, + 1, 5, -8, 3, 1, 20, -6, 2, 3, -16, 10, -10, -18, -11, -7, -7, + 9, -4, -8, 9, -15, 13, -13, -3, -7, 3, 8, 11, -6, -16, 1, -8, + 20, 4, 15, -5, -3, 11, -5, 6, 0, -5, 10, 13, 0, -6, -11, 0, + 11, -11, 10, -7, -8, 1, 16, -9, 2, -22, -9, 0, 4, 5, -12, -22, + 2, -8, -8, 14, -16, 0, 13, 0, 9, -7, 2, -1, 7, 8, -3, -3, + 2, 15, 5, 10, -7, 12, -4, 22, -4, -3, -12, -2, -15, 8, -2, -22, + 7, -10, 5, 12, -20, -9, -11, -2, -12, 2, -9, 5, -3, 11, 7, -9, + 4, -4, 24, -7, 21, -15, -3, 2, 14, -1, 5, 18, -12, 13, 3, 5, + -10, -11, 0, -8, -2, -4, 2, -15, 9, -10, -16, -9, -7, 0, -1, 3, + -8, -10, 5, -8, 4, -3, 8, -2, 20, 1, 6, -4, -9, 4, 14, 7, + -1, 3, -5, 18, -7, 20, -6, -10, 8, 1, -2, 3, -4, -5, -3, -6, + 0, -16, -7, 12, 0, -17, 4, -31, -7, 1, 1, -4, 8, -11, 6, -1, + 11, -5, -7, -4, 2, 4, 15, -3, 21, -5, 20, 3, -12, 21, -1, 10, + 5, 6, -20, -1, -18, 2, 3, -4, -5, -1, 6, -2, -11, -17, -15, -13, + 0, 6, -18, 7, -18, 7, -7, 6, 7, -10, 18, 16, 2, -1, 3, -11, + 6, 14, 1, 15, -2, 29, -8, 17, -14, 2, -19, 12, 8, -6, -1, -23, + 6, -11, 7, -19, -18, 0, 1, -8, -8, -4, -20, 8, -8, 4, 10, -12, + 13, 0, 18, -10, -3, -4, 6, 4, 17, 7, -2, 18, -9, 14, -10, -4, + -11, 4, 3, 23, -17, -6, -2, -7, -7, 9, -10, 1, 2, -4, -14, -7, + -6, -8, -4, 7, 2, -3, 3, 0, 13, -10, -4, -9, -6, 18, 11, -4, + 16, -8, -4, 1, -1, 7, 3, 3, 3, 10, -15, -2, -9, 9, 0, 2, + 2, -9, 12, -7, 0, -23, -7, -19, 2, -1, 0, 4, -15, 7, 3, -3, + 0, 9, -12, 19, 4, 8, -13, -6, 5, -1, 14, 10, 9, 13, -3, 16, + -18, 13, -18, 7, -10, 13, -6, -11, -3, 7, -23, -6, -11, -21, 9, -1, + 4, -3, -16, 0, -12, 7, 14, -5, 15, 0, 6, -5, -3, -9, 9, 4, + 10, 4, -2, -7, 10, -1, 10, -6, -14, 15, -4, 13, -4, -4, -14, 5, + -2, 4, -9, 3, -14, 2, 3, -10, -1, -9, 0, 3, -6, 12, -16, 0, + 4, 10, -25, 6, -5, 2, 8, 3, -2, -4, 15, 4, 7, 2, -1, -6, + 10, 11, 2, -2, -14, 6, -3, 0, -3, -9, -10, 1, -1, -15, 9, -29, + 9, -10, 7, -3, -3, -10, -2, 14, 4, -6, 0, 1, 12, 4, 18, -15, + 19, 1, 15, 1, 1, 3, -10, 8, -1, 7, -30, 8, -19, -2, -5, -9, + -10, 0, -1, 6, -4, -12, 1, -18, 10, -1, -12, 2, 7, 12, 11, 0, + -4, -1, 6, 10, 17, -8, 1, -12, 5, -2, 1, -7, -1, 4, 3, -3, + -1, -18, 8, -9, 0, -2, 8, -12, 12, 7, -5, -2, -16, -7, 9, -5, + 11, -9, -4, 3, 1, -9, -1, -2, -6, 7, 12, 0, -8, 9, -10, 3, + 0, 2, -3, 11, 14, 4, 3, -12, 3, -3, 2, 12, -4, -2, -2, 9, + -21, -5, -28, -6, -10, 6, 7, -6, -3, -24, 7, -11, 10, 0, 8, 13, + 10, 6, -7, -2, -5, 7, -1, 9, 18, -2, 12, -4, 7, -26, 13, -6, + 19, 6, 6, -5, -16, -6, -8, -18, -2, 1, -11, 3, 4, -16, -8, -10, + -3, 2, -3, 5, 5, 0, 11, 0, -14, 0, 1, 14, 11, 13, 0, -2, + 5, -1, -4, -2, -4, 5, 21, 3, 14, -5, -22, 5, -11, -3, -6, -3, + -11, 0, -5, -13, -10, -18, 3, 9, -10, 2, 3, -11, 11, -11, 5, -19, + 23, -1, 20, 18, 4, -3, -6, 9, 4, -3, 8, 4, 6, 2, 5, -14, + -6, -3, 2, -6, -4, -3, -11, 0, -5, 0, -21, -2, -10, 11, 5, -4, + -5, -5, -8, 10, -10, 4, -1, 6, 12, 9, 2, 8, -20, 8, -2, 11, + -11, 1, -4, 5, 6, -6, 6, -14, 14, 4, -2, 12, -3, -10, 8, -5, + -15, -9, -1, 5, 8, -3, 0, -23, -9, -11, 4, -12, 3, -4, 4, 1, + 15, -12, 3, 13, 2, 5, 8, -8, 7, 11, -3, 17, -11, 5, 3, 19, + 13, 3, -11, -11, -2, -9, -7, -4, -24, -1, -17, -3, -17, 0, -15, 2, + -1, -5, -4, 3, 2, 2, 11, -4, 3, -6, 11, 8, 3, 6, 3, 7, + 7, 6, -6, 2, 0, 14, 14, 3, 8, -6, 4, -3, 6, -13, -2, -9, + -4, 5, -13, -5, -21, -1, -6, -1, -5, -14, 8, -7, 5, -7, -17, -11, + 7, 3, 20, 7, 1, -3, 4, 5, 14, -3, 5, 3, 10, 8, 6, -6, + -2, 6, 3, 7, -6, -3, -3, -6, -1, -27, -11, -17, 0, 11, 7, 1, + -7, -9, -13, 5, -11, 0, -10, 15, 2, 5, -2, -5, 1, 6, 6, -6, + -5, 6, 2, 5, 3, 10, -16, 11, 8, 18, 3, 13, -11, 7, 5, -7, + -6, -20, 15, -1, 10, -1, -13, -17, -11, -3, -13, -4, -14, -3, -2, -6, + 6, -28, 9, -8, 10, 0, 12, -2, 10, 9, 1, 3, -6, 5, 17, 24, + 18, 3, 4, -9, -4, 2, -8, -4, -2, -11, 1, -8, -12, -9, -10, 5, + 0, -7, -9, 7, -18, 6, -10, -12, -1, -1, 13, 1, 18, 2, -3, 4, + 3, 3, -3, 3, 10, 9, 7, 5, -8, -7, 0, 3, -7, 7, -2, -2, + 5, -10, 2, -5, -3, -1, 4, 1, -2, -10, 4, -9, -5, -12, -18, 3, + 6, -3, 3, -15, -1, -13, 6, -2, 8, 0, 8, 16, -2, 17, -4, 8, + 3, 23, -1, 11, -8, 10, -4, -5, -3, -13, -2, -1, -2, 2, -9, -13, + -13, -2, -11, -2, -20, -5, 0, 3, 2, -1, -10, 1, 8, 3, 9, 6, + 4, -3, 13, 3, 4, 11, 2, 11, 8, -2, -1, -2, -2, -2, -1, -21, + -1, -14, 8, 6, -8, -10, 2, -16, 4, -3, -1, -10, 7, -1, 4, -4, + -12, 3, -2, 13, 2, -3, -9, -2, 6, -7, 8, -8, -5, 12, 7, 8, + -3, 6, -1, 16, 0, 7, -8, 3, -7, -1, 0, -6, -4, -8, 6, -1, + 4, -19, 2, -3, -8, -3, -12, 4, -6, 2, -7, 1, -13, 2, 9, -1, + 17, -19, 3, -3, 23, 9, 6, 3, 6, 6, -5, 11, -11, 1, 0, -5, + 6, -6, -4, -5, -7, 3, -4, -14, -9, -7, -1, 5, -11, 4, -19, 14, + -4, 3, 4, 2, 0, 9, -2, -3, 2, -2, 10, 15, -3, 14, -6, -4, + 6, 1, -8, 11, -9, 4, 3, -9, 2, 2, -2, 2, -2, -9, -2, -2, + 1, -6, -6, -22, -16, -10, 12, 0, 5, -8, -2, -4, -2, 5, -1, 7, + 7, 9, 1, 7, 6, -1, 10, 11, 5, -3, 8, 1, -1, 8, -15, -6, + -10, 12, 0, 2, -5, -9, -12, -7, -4, -14, -4, 0, -1, 5, -7, -8, + -12, 0, 2, 16, -3, 11, -4, 16, 11, 2, -3, 2, 8, -1, 7, -13, + 4, -3, -1, 3, -10, -2, -11, 3, 2, 3, -7, -10, -5, -10, 12, -8, + 5, -7, 15, 1, -10, 7, -16, 1, 3, 4, -5, 7, -7, 4, -2, -1, + -8, 0, -2, 17, 10, -2, 6, -5, 3, 10, -7, 2, -3, 4, 5, 5, + -3, -8, -8, -1, 1, 7, -5, -11, -2, -10, -4, -15, -7, -10, -2, 2, + -4, -10, -8, 0, 2, 6, 3, 2, 3, 10, 14, 8, 7, 3, 5, -5, + 20, -6, -1, -2, 0, 1, -2, -2, -8, 3, -3, 10, -14, 3, -3, -2, + 0, -5, 0, -15, 4, -2, 0, 4, -7, 3, -8, 7, -14, -2, -6, 4, + 2, 3, -10, -2, 5, -3, 12, -2, -5, -9, 1, 4, 1, 11, -12, 15, + 5, 20, 10, -5, 1, 5, 3, -13, 6, -16, 5, 1, -5, -8, -3, -14, + -6, -2, -5, -8, -17, -9, 3, -6, -2, -3, -3, 1, 14, 2, 4, 5, + 3, 8, 7, 12, 0, 11, 4, 16, 2, -3, -9, -1, 1, -1, -3, -6, + -14, 4, -6, 2, -14, -9, -11, -1, 0, 0, -5, -6, -10, 5, -5, 2, + -3, 2, 2, 17, -2, -1, -3, 3, 11, 1, 10, 2, 7, 6, 5, -5, + -3, -3, -2, 7, 2, 1, -18, -5, -2, -3, -5, 0, -2, 0, 8, -9, + -10, -15, -7, -2, -1, 6, -8, 16, -10, 13, -4, 2, -4, 4, 7, 9, + 6, -5, -2, 8, -1, 11, -6, -1, 5, 8, 0, 9, -20, 0, -9, 4, + -3, 1, -4, -11, 2, -6, 0, -12, 0, 1, 5, -2, 1, -7, -4, 3, + -1, -10, 3, -3, 7, 4, 8, -9, -6, -10, 0, 0, 2, -4, 6, 9, + 10, 2, 0, -1, 2, 14, 3, 7, -7, 2, -2, -2, -6, -9, 2, -3, + 6, -3, -7, -9, -10, -2, 2, -1, -11, 2, 1, 7, -4, -7, -19, 3, + -1, 6, 6, 6, 6, 0, 6, 7, 3, -1, 3, 8, 3, 4, -10, -5, + -7, 5, -4, -14, 2, -8, 5, -2, 2, -16, -4, -11, 2, 4, -1, 2, + -1, 0, 5, 4, -12, 3, 9, 7, 13, -3, -7, 2, 6, -1, 7, -1, + -1, 5, -5, 7, -11, -9, -13, 2, 5, 2, -2, -7, 5, 4, -4, -2, + -15, -4, 3, 0, 0, -5, 2, -7, -1, 9, -2, -1, 5, 1, 1, -4, + -5, -4, 6, 8, 7, -5, 4, -7, 4, 0, 1, -6, -5, -2, 5, -1, + 0, 1, 1, 3, 9, -4, -2, -4, -9, -1, 4, -17, 1, -13, 11, -1, + 6, -9, -1, 5, 1, 8, -3, 4, -5, 1, 7, -5, 1, -3, 5, 3, + 4, -7, -11, -7, 1, 5, -13, 11, -11, 1, 3, 6, -9, 6, -5, -7, + 4, -13, 5, -7, 10, 5, 6, -15, -1, 6, 4, 18, -7, -7, -3, -4, + 2, -5, 3, -4, 9, -4, 3, 3, -3, -10, 0, -1, 2, 5, -3, 7, + 3, 2, -6, -11, -2, -1, 4, -5, 4, -5, 0, -5, 5, -5, -4, 2, + 4, 2, 5, -8, -13, -3, 0, -1, -2, 4, 6, 9, 1, 3, -7, -1, + 1, 12, 1, 1, -1, -5, -1, 2, -8, -9, -7, -2, 3, 10, -6, -7, + -12, -7, -4, -5, 6, 0, 10, 5, 7, -4, -2, -8, 10, 5, 9, 4, + -1, -1, -1, -1, -1, -2, -3, 3, 9, -2, 9, -14, -13, -8, -10, 1, + 1, 3, 3, 1, -3, -12, -5, -7, 1, 6, 6, -2, -7, -3, -3, 2, + 2, 4, -9, 14, 8, 11, -3, 5, -11, 1, -1, 5, 3, 8, 2, 8, + -2, -6, -13, -10, 0, 4, 3, 4, -3, -9, 1, -5, -5, -6, 1, -2, + 2, -10, -6, -15, 1, -5, 4, -1, 2, 2, 4, 10, 4, 2, -13, 0, + 4, 8, 17, 2, 5, 4, 2, -6, 5, -5, 0, 8, -2, -1, -5, -4, + -5, -1, -5, -4, -5, 0, 0, 1, -9, -15, -3, -12, 1, -1, -7, 10, + 2, 5, -1, 2, -6, 2, 2, 10, 10, -1, 2, -2, 4, 5, 0, -6, + 12, 5, 3, -1, -8, -8, -4, -4, 3, -11, 0, -1, -1, 0, -2, -14, + -6, -9, 2, 1, 7, -4, 3, -1, 0, -3, 1, 2, 7, 5, 4, 3, + -2, -3, 1, 6, -1, 6, -11, 7, 2, -6, 2, -4, 0, 2, 3, -7, + -9, 3, 0, 4, -6, 0, -21, 0, -5, -1, 0, -1, 1, -6, -1, -1, + 0, -7, 5, 7, -2, 8, -4, -1, 3, 9, -6, 10, -6, 7, 9, 10, + 9, -6, 5, -14, 6, -5, 1, 2, -3, 0, -9, -10, -14, -2, -3, 6, + -8, -15, 3, -9, 0, -3, 0, -6, -1, 3, 9, 10, 3, 3, -10, 6, + 1, 3, -1, 9, 12, 4, 4, -9, -7, -5, 8, 6, 1, 1, -4, -5, + -5, -1, -11, -3, -4, 1, -1, 1, -10, -7, -2, -3, -4, -3, -6, 11, + 5, 3, 2, -8, -5, -2, 3, 9, 13, 5, 4, 4, 0, -5, -1, -5, + 9, 2, 3, -9, -4, 3, -6, 2, 1, -9, 5, -2, 3, -2, -9, -8, + -15, -5, -3, 3, -13, 11, 6, -3, 1, -6, -6, -1, 6, 4, 6, 7, + 1, 5, 0, 8, -6, 7, 2, 6, 2, -5, 0, -3, -1, 3, -7, -1, + -3, 5, 7, 6, -18, -10, -11, -7, -3, 10, -4, 3, -4, -8, -5, -12, + -3, -4, 12, 10, 2, -4, 6, 3, 1, 2, 0, -3, 3, 7, 7, -5, + 2, -4, 1, 3, 11, 2, 3, 4, -2, -7, -5, -17, -11, 4, -3, 5, + -7, -7, -6, -1, -8, -5, -5, 1, 7, 1, 2, -1, -9, 7, 1, 7, + 3, 3, 6, 9, 6, 1, -6, -4, 2, 5, 7, 4, -2, 1, 3, -11, + -1, -16, -2, -6, 1, 3, -8, -15, -11, 4, -1, 9, -2, -5, 0, 6, + 0, -7, 0, -8, 4, 2, 6, 2, 0, 2, 6, 2, -2, 4, -2, 4, + 14, 2, 2, -6, -6, -3, 4, -4, -1, -4, 1, -3, -6, -1, -13, -1, + -2, 7, -8, -7, -10, 0, 4, 3, -8, -3, 1, 4, 6, 4, 6, -3, + 5, 3, 4, 0, 6, 1, 4, 7, -3, -10, 8, -1, 9, -1, 1, -11, + -7, -3, -3, -6, -8, -9, -6, 1, -3, -6, -6, -5, 0, 0, 2, -3, + 0, 6, 4, 3, 2, 7, 4, 11, 14, 5, -1, -5, 1, -2, 7, 3, + 0, 1, 2, -5, -7, -10, -12, -10, -5, -5, -6, -6, -9, 1, -8, -2, + -1, -9, 1, 8, 2, -5, -2, -5, 0, 5, 6, 6, 7, 8, 10, 2, + 0, -3, -1, 2, 13, 3, 0, -6, 0, 1, -3, 0, -12, -2, 4, -4, + 4, -8, -11, -1, -2, 1, -1, 2, -12, 3, -6, 1, -12, -7, -7, 3, + 0, 9, 0, 1, 6, 1, -1, 2, 1, 2, 8, 9, -3, -1, 0, 7, + 3, 8, -1, -4, -1, 1, 3, -9, -1, -17, -3, -2, -4, -4, -3, -4, + -6, -11, -15, -2, -5, 6, 10, 1, 3, -1, -3, 13, 7, 1, 6, 4, + 4, 9, 5, -3, -5, 9, 3, 5, -3, 1, -3, 3, 0, -7, -5, -7, + 0, -5, 0, -1, -15, -11, -4, -5, -10, 2, -7, 5, -4, 1, -9, 2, + 1, 8, 7, 10, 2, 2, 0, 4, 3, -2, 0, 4, 2, 6, 8, -2, + 4, 4, -2, 5, -3, -6, 3, -3, -5, -9, -8, -11, -5, -1, -1, -5, + -7, -5, -8, 0, -3, 5, -7, 11, 1, 0, 2, -3, -1, 3, 9, 6, + -3, 8, 1, 11, 2, 8, -3, -3, 6, 2, 1, 2, -7, -3, -2, -4, + -8, -3, -3, 5, -10, -10, -4, -12, -2, 3, -5, 3, -6, -8, -2, 5, + -3, 0, 1, 4, 8, 4, 5, 0, 4, 8, 1, 7, -3, 0, 3, 4, + 4, -5, -2, -7, -3, 0, 5, -5, -9, 3, -2, -1, -2, -5, -1, -4, + -3, -11, -4, -5, -6, 0, 5, 0, -5, 5, 3, 8, -1, 3, 3, 2, + 5, 7, -4, 3, 1, 3, 10, 2, -7, 1, 0, 6, -4, -3, -5, -7, + -2, -4, -3, -6, 0, -10, 4, -6, -4, -7, -2, 1, -4, -1, -3, -1, + 2, 6, 2, 4, -2, 2, 4, 2, 5, -3, 4, 2, 1, 0, 8, -3, + 2, 5, -5, 3, -5, -2, 5, -5, 3, -1, -4, -3, 4, -10, -5, -7, + -4, -4, 0, 0, -7, -1, -1, 2, 1, -2, -12, -4, -1, 0, 4, -5, + 2, 0, 3, 12, 11, 3, 11, -1, -3, 6, -6, 1, 1, 7, 6, -7, + -1, -7, -4, -4, -7, -8, -1, -6, -6, -2, -3, -5, 0, -4, 8, -7, + 1, 4, -3, 6, 1, -7, 3, 5, 6, 5, 13, 2, 2, -4, 4, -3, + 1, 4, -4, 2, -3, -10, -10, -7, -2, -2, -2, 0, -6, -2, 1, -3, + -4, -2, -5, -2, 7, 1, 6, -5, 6, -1, -1, 2, -3, 4, 11, 2, + -1, 2, -7, -5, 8, 0, 3, -3, -5, -1, -2, 3, 1, -4, 4, 7, + 0, 2, 3, -3, 0, 1, -5, -15, -5, -3, 1, 3, -3, -11, -4, -7, + 1, -2, -1, -1, 0, 1, 1, -5, -1, 3, -2, 7, 1, -4, -1, 0, + 4, 5, 3, 3, -1, 8, 11, 1, 4, 1, -5, 7, -6, -4, -2, -4, + -2, 3, -8, -3, -13, -6, 3, -3, -7, -4, -7, 3, 3, -3, 2, -1, + 1, -4, -2, -2, -5, 1, 11, 9, -2, 6, -3, 7, 7, 1, 1, -7, + 2, -3, 1, 4, -4, -4, 5, 1, 0, -3, -6, 2, -3, 0, -8, -12, + -6, -2, -3, 6, -1, -9, 0, -1, 1, 3, -2, -1, 0, 1, 6, 0, + -3, 5, 1, 6, 1, -1, 4, 1, 7, -3, -1, -1, -4, 4, 14, -1, + -1, 2, -4, -1, -6, -8, -8, -3, -2, 2, -9, -5, -7, -12, 5, 0, + -3, -4, -3, 5, 4, 3, -2, -6, 4, 7, 3, 5, 7, -3, 8, 0, + -5, -1, -1, 11, 10, 3, 4, -8, -3, -3, 1, -3, 0, -4, -3, 1, + -7, -8, -16, -7, -6, -2, 3, -7, -2, 1, -4, 0, -5, -5, 1, 5, + 10, 5, 0, 3, 0, 1, 13, 0, 5, 9, 6, 8, -1, -4, 0, -3, + 6, 4, -4, 0, -3, -15, -2, -12, -15, -3, -6, 2, 1, -3, -4, -9, + -9, -3, -3, -2, 3, 4, 9, 0, 2, 1, 2, 14, 5, 3, 8, 2, + 7, 4, -4, -4, -1, -9, 9, -5, -1, -7, -10, -2, -7, -4, 0, -5, + 2, 5, 1, 0, -5, -5, -1, -1, -3, 4, -8, 5, 3, -4, 4, -5, + -3, 9, 4, 8, 0, 0, 2, 0, -2, 0, -2, -7, 12, -1, 5, -4, + 2, -3, 0, 2, -2, -4, -2, 2, -5, 3, -7, -9, -4, -3, -2, -6, + -6, -2, -6, -1, -7, -8, 1, 3, 6, 10, 4, 5, 0, 5, 8, 1, + 3, 8, 5, 11, 12, -7, 4, 0, -3, 2, -1, -8, -7, -4, -2, -6, + -9, -6, -13, -4, -1, 0, -9, -5, -3, -4, -2, 3, 1, 1, 9, 4, + 2, 6, -1, 3, 6, 2, 0, -3, 3, 2, 6, 3, -1, -4, 4, 1, + 2, 2, -5, -8, -1, -3, -1, -9, -4, 1, -5, 5, -7, -4, 0, 3, + -10, 3, -3, -5, 1, 5, 4, 1, -5, 1, -5, 4, 1, -6, 0, 5, + 8, 8, 1, 6, 0, 3, 4, 2, -3, 1, -3, -3, 3, -10, -6, -8, + -2, -1, -3, -6, -6, -5, -6, -6, -5, 5, -3, 5, 6, -2, -1, -1, + -4, 6, -2, 6, 6, 2, 12, 8, -2, 3, -6, -2, 5, 4, -3, -2, + -5, -4, -7, -6, 1, -5, 2, 2, 0, 1, -7, 0, -4, -2, -1, -2, + -5, 7, -5, -2, -3, -2, -3, 4, 4, 9, 0, 1, 1, -5, -3, -4, + -4, 4, 3, 6, 1, -2, -2, -7, 4, 1, 1, -3, 3, -1, 2, 0, + -7, 0, 0, -1, -3, -2, -1, -5, -2, -3, -8, -5, -5, -1, 5, 5, + 2, 2, -3, 4, 3, 4, 6, 3, -1, 10, -4, -3, -2, -3, 0, -4, + 0, -2, -2, 0, 2, -5, -2, -5, -9, 8, -2, -1, -1, -3, -3, -2, + -6, 2, 1, 2, 9, 0, 1, 4, -5, 2, 4, -6, -1, 2, -1, 6, + 3, 0, -5, -3, -1, 0, 3, -3, 0, -6, -2, -3, -4, -2, 0, 3, + 2, 2, 0, -10, 1, -6, -5, -1, -2, 5, 3, 6, -2, -6, -1, -3, + 2, 4, 1, -1, 0, 1, 1, 3, -1, 5, -1, 7, 6, 1, -2, 0, + -6, -2, -2, -8, -2, -2, -3, -5, -5, -8, -3, -1, 5, -3, 1, 2, + 1, 2, -3, -2, -3, 2, 6, 2, 6, 0, 0, -2, 9, -1, 3, -2, + 3, 0, 0, 0, -6, -6, -1, -5, -7, 1, -3, -6, 2, -2, -1, -5, + -2, 1, 4, 2, 2, -3, -1, 6, -2, 2, 4, -3, 2, 2, 2, -3, + 1, 0, -4, 2, -1, -2, 3, 1, 1, -1, -5, -8, -2, -5, 0, 1, + -6, 3, -4, 2, 3, -6, 3, 0, 2, -2, -1, -4, -2, -4, 4, 0, + -3, 0, -6, -3, 10, -3, 3, 0, 4, 7, 3, 0, 5, 1, 5, 1, + -3, -2, 0, -6, 3, -1, -7, -5, -7, -1, -2, -2, -2, -3, -2, 2, + -2, -1, -3, -3, 2, -2, -6, -3, -3, 4, 3, 2, 0, -1, 5, 5, + 8, 2, 2, -2, 4, 0, 5, -5, -3, -1, -3, -3, -6, -4, -2, 3, + 0, -2, -2, -5, 5, -1, 3, -1, -1, -3, 0, 0, -5, -4, -3, -2, + 5, 0, -4, -4, 1, 2, 6, 0, -3, -1, 2, 3, 7, -3, 0, -4, + -2, 4, 3, 0, 1, 3, -3, 1, -7, -4, 0, 1, 1, -4, -4, -4, + -9, -1, -2, -3, -2, -3, -3, 4, 3, -1, -4, 2, 4, 4, 3, 2, + -1, 0, 9, -1, 4, 2, 7, -1, 6, -2, -2, -5, -1, -9, -2, -2, + -6, -1, -1, 1, -8, -6, -5, -1, -1, 1, -4, -5, 3, 1, 5, 3, + -3, 0, -2, 7, 0, 1, -2, 3, -1, 5, -1, -5, 7, -1, 3, 2, + -5, -6, -2, 4, 2, -1, -3, -1, -1, -1, -1, -2, -4, 1, -5, 3, + -1, -3, -5, 2, 6, -6, -1, -5, -4, 4, -1, -1, -2, -1, 2, 0, + 3, 1, 4, 2, 7, -1, 2, 0, -2, 1, 4, -5, -3, -7, -2, 0, + -1, -1, -3, 0, 0, -2, -6, 2, -4, 2, -4, 1, -7, -2, -1, 5, + 3, -2, -7, -4, 1, 6, 4, 5, 1, 4, 0, 5, 1, -1, 2, 0, + -3, -3, -5, -6, 3, -1, 5, -1, -2, 1, 1, 4, 2, -6, -3, -4, + -3, 2, -2, -8, -3, -6, -4, -2, -11, 0, 0, 1, 6, -3, -2, 1, + 2, 10, 8, 4, -2, -1, 2, 2, 1, -2, 3, 1, 5, 3, -1, 0, + -4, 4, -7, -2, -7, -8, -4, -3, -2, -7, -7, -3, -1, 5, -2, 0, + -7, 2, -1, 3, 1, 4, 6, 5, 8, 3, 2, -1, 3, -3, 0, 0, + -5, -1, 1, 1, -5, -3, -2, 6, 4, 5, -4, -8, -4, -3, -2, -5, + -4, -4, -4, 2, -3, -2, -4, -4, -4, 6, 1, 0, 1, 3, 3, 5, + 2, 1, 0, 6, 2, -1, 1, -3, -3, 2, -1, 0, 1, 3, 1, 4, + -4, -5, -10, -8, 1, -6, -3, -4, -6, -3, 0, 2, -3, -1, 2, 0, + 8, 1, 4, 4, 3, 6, 3, 1, 3, 5, 1, 2, -4, -7, -3, -3, + 3, 0, -7, -5, 0, -3, -1, -2, -4, 0, -5, 1, -6, -1, -5, -3, + 1, 4, -1, -3, 3, 3, 5, -1, -2, 2, -1, 2, 1, -1, -5, 5, + 1, 2, 2, -4, 0, -1, 3, 0, -2, -1, 2, 1, 5, 4, -3, -5, + 0, -2, -2, -6, -3, -3, -4, -1, -5, -4, -1, -2, 0, 2, -2, -6, + -3, 1, 1, 1, -1, 3, 4, 7, 2, 3, 4, -1, 7, 2, 3, 1, + -1, 1, -2, 0, -4, -5, -6, 0, -2, -7, -2, -5, -5, 1, -4, -5, + -5, 3, -1, 1, 2, -2, 0, 1, 4, 1, -4, 2, 2, 0, 9, 2, + 0, 4, 3, 1, 2, -4, -2, -4, 3, -4, -2, -6, 0, -1, 5, 2, + -4, 0, -4, -4, -1, -5, -4, -7, -3, 1, 0, -2, -1, -5, 1, 0, + -1, 0, 2, 4, 0, 3, -2, 1, 2, 6, 0, 1, 5, 0, 3, 3, + 2, -5, -2, 1, 5, 2, -2, -5, -9, 0, -6, -1, -6, -7, -5, -4, + 0, -2, -5, -3, 2, -2, 3, 2, 0, 9, 2, 0, 4, -3, 4, 5, + 8, 6, -2, -4, -1, 0, -2, -2, 1, -5, 2, -5, -1, -4, -3, -4, + 0, -2, -7, -3, -1, 0, -1, 0, -6, 3, -2, 5, 2, -1, -2, 1, + 0, 1, -1, -3, 2, 3, 1, 2, -4, -3, -1, 5, 5, 3, -4, 0, + 1, 2, 5, -5, 1, -5, 2, -2, 2, -4, -3, 0, -4, -3, -9, -7, + -4, 2, -2, 1, -6, -3, 0, 1, 5, 1, -5, 0, 0, 2, 1, 2, + 0, 6, 4, 6, 3, 2, 3, 1, -2, -2, -9, -4, -1, 4, 0, -1, + -5, -8, -5, -4, 0, -4, -1, -3, 0, 0, -4, -3, -1, 1, 2, 0, + -2, -3, 1, 3, 2, 3, 3, 0, 8, 2, 7, -1, 3, -2, 4, 0, + 0, 1, -4, 5, -1, -3, -3, -6, -4, 2, 1, -5, -4, -7, -4, -4, + -7, -2, -10, 1, 0, 1, -3, 4, -2, 5, 2, 1, -3, -1, 2, 8, + 4, 5, 0, 1, 4, 5, 2, 2, -2, 1, -4, 0, -3, -3, -1, 0, + 2, -4, -4, -5, -1, -7, 0, -4, -5, -1, -3, 2, -2, 0, 3, 0, + 2, 0, 1, -2, 2, 4, -1, 0, -3, -1, 1, 3, 2, -3, 2, 0, + 2, 2, -1, 2, -2, -3, 0, 0, -2, 2, -2, 4, -3, -6, -7, -6, + 2, -1, -4, -1, -7, -1, -3, 3, -1, 0, -2, 2, 2, -3, 3, -4, + 5, 7, 6, 3, 1, -1, 6, 2, 1, 0, -1, -1, 1, -3, 1, -3, + -5, -5, -3, -8, -3, -11, -1, -1, 0, -8, -2, -5, 3, 4, 0, 1, + -2, 2, 0, 6, 4, 1, 4, 1, 5, 0, 0, 1, 2, 5, 0, 1, + -10, 0, -5, 2, 0, -6, -6, -2, -2, 2, -3, 0, -4, 2, -4, 1, + -3, -4, 1, -2, 2, 1, -2, 0, 3, 2, -3, -1, -5, -3, 4, 2, + 3, -1, 4, 1, 5, -1, 2, -3, 2, -3, 0, -3, -2, 1, 1, 5, + 1, -2, -5, 1, -1, -4, -3, -7, 0, -5, -4, -4, 0, -4, 4, 0, + -1, 1, -8, 1, 0, 9, 1, 2, -2, 5, 5, 1, 6, -1, 6, 3, + 1, 1, -2, -2, -4, -3, -2, -3, -7, -4, -4, -1, -3, -8, -1, -8, + 4, -5, 0, -3, 1, 0, 4, -1, 0, 1, 3, 3, 4, -4, 6, -2, + 2, 5, 4, -3, 4, -3, 5, 0, -4, 0, 0, -1, 0, -4, -4, 3, + -1, -2, -4, -8, -9, -5, -4, 4, -4, 1, -4, 1, 1, -1, -1, -1, + 3, 2, 3, 0, 1, 2, 1, 5, 3, 1, 0, 5, 3, 3, 0, -5, + -4, -2, 5, 0, -2, -5, -2, -6, -2, -5, -8, -2, 1, -1, -3, -7, + -8, -6, 0, 4, 7, -2, 7, -1, 7, 3, 2, -5, 0, 2, 0, 1, + -3, 2, 2, 3, 3, -3, 0, -2, 3, -1, -1, -4, -6, -2, -3, 4, + -4, 0, -4, 6, -2, -6, -2, -7, 1, 2, -1, -3, -2, -2, 3, -1, + 0, -3, -1, 4, 7, 4, 0, 2, -1, 0, 6, -2, 1, 1, 5, 4, + 1, -3, -3, -2, 2, 2, 1, -6, -6, -3, -4, -2, -6, -5, -4, -5, + -2, -8, -8, -3, 0, 4, 0, 1, -1, 2, 5, 4, 2, 2, 3, 3, + 4, 10, 0, 2, 0, 3, 1, 1, 0, -3, 1, -3, 1, -7, 0, 1, + -2, 1, -6, -4, -10, -1, -4, -2, -2, -3, 2, -4, 1, -5, -4, -4, + 2, 1, 1, -4, -1, 3, 1, 6, 2, -2, -2, 3, 3, 2, 7, -5, + 5, 0, 8, 1, -1, 2, 3, -1, -6, 0, -10, 3, -1, -1, -5, -6, + -8, -2, 0, -3, -5, -8, -4, 2, -3, -1, -2, 0, -1, 7, -1, 3, + 2, 4, 7, 3, 4, -1, 5, 1, 9, 1, -2, -1, -1, 1, -3, -2, + -6, -7, 1, -3, -1, -9, -4, -6, 0, 2, -3, -2, -4, -3, 0, -4, + -1, -4, 0, 1, 6, -1, 1, -1, 3, 5, -1, 3, 4, 5, 7, 4, + -2, 0, -2, 0, 3, 1, -1, -8, -2, -1, -2, -5, -1, -2, -2, 2, + -5, -7, -9, -2, -3, -2, 1, -5, 4, -4, 5, -1, -1, -3, 2, 3, + 7, 3, -1, 3, 4, -1, 5, -4, 0, 4, 4, 3, 4, -9, 1, -5, + 2, -2, -2, -3, -7, -1, -2, -2, -5, -3, -1, 1, -2, -1, -4, -4, + 1, -1, -7, 0, -1, 2, 5, 4, -4, -5, -4, 0, 2, 1, -1, 3, + 5, 4, 0, 0, -1, 3, 8, 3, 3, -4, 0, 1, 0, -2, -6, -2, + -4, 3, -2, -3, -5, -6, -3, -1, -1, -7, 0, 0, 3, -5, -4, -11, + 0, 0, 3, 3, 1, 1, 1, 4, 6, 1, 1, 2, 9, 3, 3, -4, + -4, -3, 2, -1, -6, 1, -5, 2, 0, -1, -8, -5, -6, 1, 0, -2, + -1, -2, -1, 2, 0, -9, 0, 5, 4, 7, -3, -3, 3, 4, 2, 4, + 0, -1, 3, 1, 5, -5, -6, -7, 0, 3, 0, -2, -4, 3, 3, -3, + -4, -7, -2, 4, 1, -1, -4, -1, -6, -2, 3, -2, -3, 1, 4, 1, + -1, -4, -3, 3, 4, 5, -2, 2, -3, 4, 0, 3, -3, -3, 0, 3, + 1, -2, -1, -3, 2, 4, -2, -2, -3, -1, -1, 3, -11, -2, -8, 5, + -1, 3, -5, -2, 2, -1, 3, -3, 0, -1, -1, 5, -2, 0, -2, 3, + 2, 3, -2, -6, -3, 2, 4, -6, 5, -6, 1, 2, 3, -6, 2, -3, + -4, 3, -9, 2, -6, 3, 4, 2, -9, -1, 1, 2, 8, -3, -4, -1, + -2, 2, -2, 2, -3, 3, -1, 1, 2, -1, -6, 1, 2, 2, 1, -2, + 2, 3, 1, -3, -6, -3, 0, 1, -3, 0, -3, -1, -4, 2, -4, -3, + -1, 4, 0, 5, -6, -7, -1, 0, 0, -3, -1, 2, 4, 0, 3, -4, + -1, 1, 7, 4, 2, -1, -4, 0, 2, -4, -5, -5, -1, 1, 4, -5, + -4, -6, -3, -2, -3, 2, -2, 5, 2, 3, -4, -2, -5, 6, 3, 4, + 2, -3, 1, 0, 0, 1, -3, -1, 1, 7, 0, 6, -6, -7, -2, -7, + 0, -1, 0, 2, 1, -2, -7, -2, -5, 0, 2, 0, -3, -5, -1, -3, + 0, -1, 0, -6, 8, 4, 5, -1, 1, -4, 1, 1, 4, 2, 5, 3, + 6, 0, -2, -9, -4, -1, 0, 0, 1, -1, -4, -1, -5, -5, -5, 0, + 0, 1, -6, -5, -9, 0, -3, 0, -2, 0, 0, 3, 4, 2, 1, -7, + 1, 3, 4, 9, 1, 4, 4, 2, -4, 2, -2, 1, 5, -2, 0, -3, + -4, -3, -2, -4, -4, -4, 1, -1, 2, -6, -8, -3, -8, -1, -2, -4, + 5, 2, 3, -1, 0, -4, 2, -1, 5, 5, -1, 3, 0, 3, 3, 0, + -4, 9, 4, 2, -1, -6, -4, -2, -2, 2, -7, 0, 0, -2, -2, -2, + -10, -4, -7, 0, -2, 2, -2, 2, 1, 0, -3, 0, 1, 6, 3, 2, + 0, 0, -1, 2, 3, -1, 4, -5, 6, 2, -3, 0, -3, 0, 1, 0, + -5, -6, 1, 0, 1, -5, -2, -14, 0, -4, -1, -1, -1, 1, -3, 0, + -2, -1, -4, 4, 5, -1, 5, -1, 3, 3, 5, -3, 5, -3, 5, 5, + 6, 4, -6, 2, -9, 4, -4, 0, 1, -2, -1, -8, -6, -11, -2, -3, + 3, -6, -8, 3, -5, 1, -3, 1, -3, 1, 3, 5, 6, 2, 1, -6, + 4, -1, 1, 0, 7, 7, 2, 3, -6, -4, -4, 3, 3, 0, 1, -1, + -2, -4, 0, -8, -2, -3, 1, -2, 1, -5, -2, -1, -3, -3, -4, -3, + 7, 4, 1, -1, -6, -5, -3, 2, 5, 8, 3, 3, 2, 1, -4, -1, + -2, 6, 3, 2, -4, -1, 1, -5, -1, -1, -5, 2, -2, 1, -2, -7, + -5, -11, -4, -3, 3, -8, 8, 4, -2, -2, -4, -4, -1, 4, 3, 5, + 5, 2, 4, -1, 6, -3, 6, 2, 3, 0, -4, 0, -2, -2, 0, -5, + -2, -1, 4, 3, 1, -13, -8, -8, -5, -3, 7, -2, 3, -2, -5, -3, + -8, -2, -3, 8, 6, 1, -2, 5, 3, 1, 2, 0, -1, 2, 4, 3, + -5, 1, -3, 0, 1, 7, 1, 2, 3, -1, -4, -4, -10, -7, 3, 0, + 2, -5, -5, -4, -1, -7, -3, -3, 1, 3, 0, 0, -1, -6, 6, 1, + 4, 1, 2, 5, 6, 4, -1, -4, -3, 1, 2, 5, 2, -1, 1, 3, + -8, -1, -10, -2, -5, 0, -1, -6, -10, -7, 2, -2, 6, -1, -2, 1, + 4, -1, -5, -1, -5, 4, 1, 4, 2, 1, 3, 4, 0, -2, 1, -1, + 3, 8, 2, 1, -4, -3, -3, 3, -3, -1, -4, 0, -4, -6, -2, -8, + 1, -2, 5, -6, -5, -6, 0, 3, 1, -6, -3, 1, 2, 4, 2, 4, + -2, 3, 3, 3, 1, 5, 1, 2, 3, -2, -6, 6, -1, 6, -2, 1, + -7, -5, -2, -3, -6, -6, -6, -4, 0, -2, -4, -4, -3, 0, -1, 1, + -3, -1, 3, 1, 1, 0, 6, 4, 8, 10, 5, 0, -3, 1, -2, 5, + 2, 1, 1, 1, -4, -6, -8, -8, -8, -5, -4, -5, -4, -5, 0, -5, + -3, 0, -7, 0, 4, 1, -4, -1, -4, -2, 4, 4, 5, 6, 6, 7, + 0, 0, -1, 0, 2, 9, 2, 1, -3, 0, 1, -3, 1, -9, -1, 3, + -4, 3, -6, -7, -2, -1, -1, -1, 1, -9, 2, -5, 1, -8, -6, -6, + 1, -1, 6, 0, 2, 5, 2, 0, 2, 1, 2, 6, 5, -2, -1, 0, + 4, 1, 6, 0, -2, 1, 0, 3, -7, -1, -13, -4, -3, -3, -3, -2, + -3, -5, -9, -11, -2, -3, 4, 7, -1, 2, 0, -2, 8, 5, 1, 4, + 3, 2, 7, 3, -2, -4, 7, 2, 3, -2, 1, -1, 2, 0, -5, -4, + -4, 0, -4, 0, -1, -10, -9, -3, -5, -8, 1, -5, 3, -3, 0, -7, + 1, 0, 5, 4, 7, 1, 1, 0, 2, 2, -2, -1, 2, 1, 4, 6, + -1, 4, 3, -1, 4, -2, -3, 3, -1, -2, -6, -6, -7, -3, -1, 0, + -4, -6, -5, -6, 0, -3, 3, -5, 7, 0, -1, 1, -3, -1, 1, 6, + 3, -3, 7, 1, 10, 1, 6, -1, -2, 5, 2, 1, 1, -4, -2, 0, + -3, -7, -2, -4, 4, -8, -8, -4, -10, -2, 2, -4, 1, -5, -7, -1, + 3, -1, 1, 1, 4, 6, 2, 2, 0, 4, 7, 0, 5, -2, 0, 3, + 3, 3, -3, -1, -5, -2, 0, 3, -4, -6, 2, -1, 0, -2, -4, 0, + -4, -3, -9, -3, -4, -4, 0, 3, -1, -4, 3, 1, 5, -2, 1, 2, + 2, 4, 5, -3, 2, 1, 3, 7, 1, -5, 1, 0, 5, -3, -2, -3, + -4, 0, -3, -2, -5, 0, -8, 3, -6, -4, -6, -2, 2, -4, -2, -3, + -2, 1, 4, 2, 3, -2, 2, 4, 1, 4, -2, 3, 2, 1, 1, 7, + -1, 2, 4, -4, 2, -4, -2, 5, -4, 3, -1, -3, -2, 3, -8, -4, + -6, -3, -3, -1, 0, -6, -1, 0, 1, 1, -2, -10, -3, -1, 0, 2, + -5, 1, 1, 2, 10, 8, 2, 8, -1, -2, 4, -5, 2, 2, 7, 6, + -6, -1, -5, -4, -3, -6, -7, 0, -5, -5, -1, -2, -5, 0, -4, 6, + -6, 0, 3, -3, 4, 0, -6, 2, 5, 5, 4, 10, 0, 2, -3, 3, + -2, 0, 3, -3, 2, -3, -8, -8, -5, -1, -1, -1, 0, -5, -2, 0, + -3, -4, -1, -5, -2, 5, 0, 5, -4, 4, -1, -1, 1, -3, 3, 9, + 2, -1, 1, -6, -3, 7, 1, 3, -2, -4, 0, -1, 3, 1, -3, 4, + 6, 0, 1, 2, -3, 0, 0, -5, -13, -4, -2, 1, 2, -3, -10, -4, + -7, 1, -2, -2, -1, 0, 1, 1, -4, -1, 2, -2, 7, 1, -3, 0, + 0, 4, 5, 2, 2, -1, 6, 9, 1, 3, 1, -5, 5, -6, -5, -2, + -4, -2, 2, -7, -4, -11, -5, 3, -3, -6, -4, -6, 3, 3, -3, 2, + 0, 1, -3, -1, -2, -4, 1, 10, 8, -2, 4, -3, 6, 6, 1, 0, + -7, 2, -2, 1, 3, -4, -4, 4, 1, 0, -2, -5, 2, -2, 0, -7, + -11, -5, -2, -2, 5, -1, -8, -1, -1, 1, 2, -2, -1, 1, 1, 5, + 0, -3, 5, 1, 6, 1, -1, 3, 1, 6, -3, -1, -1, -3, 4, 12, + -1, -1, 2, -4, -1, -6, -8, -7, -3, -2, 1, -9, -5, -6, -10, 5, + 1, -2, -3, -2, 5, 4, 3, -1, -5, 4, 6, 3, 4, 6, -2, 7, + 0, -4, -1, -1, 9, 8, 2, 2, -8, -3, -3, 0, -2, 0, -4, -2, + 0, -6, -7, -14, -6, -5, -1, 3, -6, -2, 1, -3, 0, -4, -5, 1, + 5, 9, 4, 0, 3, 0, 1, 12, 0, 4, 8, 5, 7, -1, -4, 0, + -3, 5, 4, -4, 0, -3, -13, -2, -10, -14, -3, -5, 2, 1, -3, -4, + -8, -8, -3, -2, -2, 3, 4, 8, 0, 2, 1, 2, 12, 5, 3, 8, + 2, 6, 3, -4, -4, -2, -8, 8, -5, -2, -6, -10, -2, -6, -4, 0, + -4, 2, 5, 1, 0, -4, -4, -1, -1, -3, 4, -7, 4, 3, -3, 4, + -4, -3, 8, 4, 7, 0, 0, 2, -1, -2, -1, -2, -7, 11, -1, 5, + -4, 2, -2, 0, 2, -2, -4, -2, 1, -5, 3, -6, -9, -3, -3, -2, + -5, -5, -2, -6, -2, -7, -8, 1, 3, 5, 9, 4, 4, 0, 5, 8, + 1, 3, 7, 5, 10, 11, -7, 3, 0, -3, 1, -1, -7, -7, -3, -2, + -6, -9, -6, -12, -4, -1, 0, -8, -5, -3, -3, -2, 3, 1, 1, 9, + 4, 2, 5, -1, 2, 6, 2, 0, -3, 2, 2, 5, 2, -1, -4, 4, + 1, 1, 2, -5, -8, -1, -3, -1, -9, -4, 1, -4, 5, -6, -4, 0, + 3, -9, 3, -3, -5, 1, 4, 4, 1, -4, 1, -4, 4, 1, -6, 0, + 5, 7, 8, 1, 6, 0, 3, 4, 2, -3, 1, -3, -3, 3, -9, -6, + -7, -2, -1, -3, -5, -6, -5, -5, -6, -5, 4, -3, 5, 5, -2, -1, + -1, -3, 6, -2, 5, 6, 2, 11, 8, -1, 3, -6, -2, 5, 4, -3, + -3, -5, -3, -7, -5, 0, -5, 2, 1, 0, 1, -7, 0, -3, -2, -1, + -2, -5, 7, -4, -2, -3, -2, -3, 4, 4, 9, 0, 1, 1, -5, -3, + -4, -4, 4, 3, 6, 0, -2, -2, -6, 4, 1, 1, -3, 3, -1, 2, + 0, -7, 0, 0, -1, -3, -2, -1, -5, -2, -3, -8, -5, -5, -1, 5, + 5, 2, 2, -3, 4, 3, 3, 6, 3, -1, 10, -4, -3, -2, -3, 0, + -4, 0, -2, -2, 0, 1, -4, -2, -5, -9, 8, -2, -1, -1, -3, -3, + -2, -6, 2, 1, 2, 9, 0, 1, 3, -4, 2, 4, -6, -1, 2, -1, + 6, 3, 0, -5, -3, -1, 0, 3, -3, 0, -6, -2, -3, -4, -2, 0, + 3, 2, 2, 0, -10, 1, -6, -5, -1, -2, 5, 3, 6, -2, -6, -1, + -3, 2, 11, 11, -28, -10, 54, -53, 2, 43, -37, 0, 43, -48, 7, 11, + -18, 19, -33, 32, -1, -7, -6, 19, -21, 23, -38, 0, 54, -49, 0, 15, + 20, -28, -20, 53, -28, -48, 70, -6, -60, 51, 5, -32, 1, 31, -10, -33, + 24, 33, -68, 21, 50, -67, -1, 57, -28, -21, 26, 15, -48, 9, 33, -32, + -3, 23, -10, 5, -4, -10, 24, -42, 29, -13, 0, 26, -15, -26, 46, -17, + -38, 45, -26, 8, -1, 4, -5, -3, 15, -27, -2, 39, -37, -25, 74, -33, + -25, 16, 24, -26, -25, 46, 10, -74, 50, 33, -80, 37, 32, -51, 13, 26, + -21, -5, 0, 18, -33, -1, 49, -29, -29, 38, 7, -26, -20, 45, -21, -18, + 26, -6, -6, 17, -29, -5, 41, -38, 10, 19, -18, -7, 15, 2, -24, 1, + 21, -6, -28, 51, -30, -7, 10, 6, -22, -3, 37, -32, -24, 63, -16, -60, + 65, -10, -35, 15, 17, -15, -8, -1, 33, -37, -10, 55, -44, -5, 41, -35, + -9, 20, -5, -18, 13, 19, -27, 2, 34, -34, -7, 21, -27, 27, -25, 26, + 5, -30, 32, -45, 38, -3, -41, 24, 25, -31, 5, 9, 9, -37, 13, 31, + -36, 7, 20, -18, -25, 56, -50, 13, 17, -17, 19, -40, 46, -3, -82, 88, + -1, -73, 66, -10, -4, -18, 13, 5, -27, 14, 7, -7, -10, 37, -39, 11, + 14, -38, 35, -21, 5, 11, -27, 45, -37, -6, 34, -39, 23, 16, -51, 51, + -11, -28, 19, -6, 12, -29, 12, 26, -21, -25, 48, -35, -6, 24, -9, 0, + -31, 54, -19, -47, 73, -33, -43, 81, -59, 12, 15, -28, 22, -26, 33, -2, + -29, 14, 34, -63, 28, 16, -40, 31, -22, 18, 8, -22, 25, -31, 6, 26, + -54, 33, 19, -53, 56, -25, -9, 24, -39, 34, -18, -15, 35, -18, -16, 43, + -41, -3, 47, -54, 9, 33, -13, -24, -2, 41, -26, -35, 73, -49, 1, 32, + -34, 20, -28, 22, -5, -16, 23, 18, -62, 47, 5, -57, 51, -15, -5, 0, + 4, 12, -11, -15, 29, -28, 4, 26, -44, 43, -19, -14, 35, -37, 23, -15, + -11, 45, -54, 17, 42, -67, 18, 47, -58, 17, 25, -35, 14, -6, 11, -3, + -42, 73, -50, -12, 67, -68, 28, -6, -4, 16, -44, 47, 8, -64, 80, -39, + -31, 54, -43, 14, -2, 11, -14, 4, -3, 19, -34, 0, 61, -98, 69, 12, + -61, 48, -35, 28, -12, -38, 85, -86, 42, 25, -76, 77, -31, -37, 39, -2, + -12, 7, -10, 16, -1, -33, 60, -48, -16, 70, -69, 13, 38, -43, 15, 0, + 0, 22, -65, 75, -28, -60, 96, -58, -8, 32, -6, 1, -11, 4, 17, -46, + 17, 46, -86, 66, 9, -69, 67, -21, -30, 33, -32, 42, -34, 1, 50, -74, + 40, 5, -34, 21, 7, -23, 21, -14, 10, -1, -33, 58, -48, -3, 65, -77, + 14, 51, -65, 32, -10, 0, 24, -58, 71, -27, -54, 86, -56, -12, 45, -17, + -18, 21, -1, -5, -14, 12, 19, -75, 78, 1, -80, 84, -25, -33, 48, -50, + 45, -30, -15, 69, -86, 46, 22, -56, 14, 36, -35, 2, 16, -11, 4, -24, + 41, -27, -19, 53, -42, -4, 49, -67, 36, 2, -26, 37, -46, 58, -40, -26, + 82, -70, -7, 55, -30, -20, 36, -1, -32, 11, 7, 7, -41, 39, 18, -68, + 65, -11, -39, 40, -34, 30, -20, -12, 70, -98, 53, 27, -74, 40, 10, -31, + 11, 20, -19, 6, -6, 12, -19, -9, 46, -36, -31, 83, -65, 8, 32, -48, + 42, -45, 49, -23, -32, 68, -59, 5, 39, -31, -1, 23, -20, -8, 17, -7, + -15, -1, 16, 25, -63, 51, 14, -66, 47, -10, -15, 5, -1, 36, -72, 54, + 22, -86, 64, -3, -31, 13, 11, -8, -12, 14, 15, -34, 6, 29, -24, -25, + 62, -49, -9, 49, -56, 45, -31, 18, 4, -37, 57, -41, -11, 38, -38, 7, + 24, -20, 10, -13, 20, -17, -8, 18, -4, -30, 35, 14, -63, 56, -7, -52, + 50, -5, -4, -19, 17, 36, -83, 51, 14, -52, 30, 4, 0, -15, 14, 8, + -43, 32, 3, -20, 2, 19, -11, -20, 45, -42, 14, 3, -5, 9, -31, 43, + -20, -30, 51, -24, -19, 47, -42, 21, -17, 25, -24, -20, 52, -37, 1, 20, + -6, -21, 25, -2, -33, 30, -9, -15, 23, -13, 26, -49, 29, 22, -76, 71, + -12, -37, 27, 4, 7, -41, 30, 10, -45, 28, 13, -13, -21, 31, -1, -33, + 27, 6, -18, -10, 24, -6, -26, 33, -10, -37, 72, -60, 24, 1, -13, 15, + -36, 52, -44, 18, 14, -31, 23, 2, -16, -8, 10, 23, -47, 19, 17, -10, + -17, 10, 29, -69, 56, -5, -38, 47, -28, 14, -21, 6, 32, -55, 33, 12, + -39, 24, 5, -11, -25, 31, 12, -47, 35, 9, -25, 1, 7, 5, -36, 57, + -52, 18, 29, -45, 37, -45, 35, -13, -17, 41, -31, 7, 8, -18, 15, -19, + 19, -22, 2, 33, -37, 20, -4, 2, -25, 27, 0, -34, 37, -13, -6, 3, + 1, 17, -46, 28, 32, -78, 60, -7, -25, 18, -6, 12, -35, 31, 4, -38, + 37, -11, -8, -13, 37, -22, -17, 32, -27, 25, -34, 24, 9, -43, 41, -19, + -1, 29, -48, 29, -6, -8, 10, -11, 27, -35, 18, 9, -19, -7, 12, 4, + -27, 30, 2, -24, 13, 7, -18, -1, 16, 11, -68, 77, -15, -45, 43, -24, + 29, -38, 16, 21, -43, 27, -7, -10, 11, 1, -4, -13, 26, -17, -1, 1, + -1, 3, -19, 34, -24, -13, 49, -51, 22, 3, -23, 29, -33, 28, -7, -15, + 31, -35, 2, 29, -28, -11, 27, -4, -18, 19, 2, -31, 26, -16, 17, -28, + 34, -3, -49, 64, -39, 6, 1, -8, 25, -38, 32, 4, -53, 47, 0, -32, + 16, 14, -1, -37, 31, -4, -7, -8, 9, 7, -20, 36, -34, 4, 25, -39, + 25, -13, 4, 12, -36, 51, -38, 0, 34, -51, 27, 13, -34, 14, 12, -9, + -23, 41, -21, -1, -16, 28, 10, -62, 66, -23, -26, 26, -9, 13, -29, 13, + 31, -62, 49, 1, -49, 49, -18, -7, 2, 14, -10, -19, 20, 5, -8, -17, + 37, -27, -5, 23, -35, 17, 15, -30, 30, -20, 28, -32, -5, 48, -64, 29, + 13, -37, 35, -10, -1, -7, -3, 14, -16, -9, 26, -5, -35, 48, -21, -21, + 40, -26, -11, 21, 3, 0, -42, 47, 8, -71, 72, -21, -21, 25, -15, 7, + -16, 14, -1, -24, 18, 32, -48, 12, 30, -46, 12, 26, -45, 36, -20, 18, + -3, -34, 52, -40, -2, 25, -29, 32, -11, -18, 18, -3, 3, -24, 7, 36, + -40, -10, 50, -35, -19, 47, -30, -4, 22, -17, 8, -22, 29, 4, -72, 85, + -21, -48, 57, -19, -8, -10, 17, 5, -31, 16, 24, -47, 29, 12, -31, 14, + 2, -27, 43, -26, 5, 13, -33, 48, -46, -6, 58, -67, 13, 45, -50, 26, + -6, -6, -2, -9, 24, -20, -7, 40, -37, -5, 36, -29, -17, 38, -21, 2, + -5, 6, 14, -52, 59, -11, -59, 82, -38, -22, 32, -11, -6, -4, 11, 14, + -38, 30, 5, -44, 24, 25, -37, 0, 21, 1, -9, -24, 49, -36, -12, 47, + -49, 20, 34, -70, 43, 6, -31, 21, -20, 24, -13, -10, 37, -35, -8, 37, + -26, -22, 44, -20, -13, 20, -7, 8, -28, 36, -15, -42, 79, -41, -28, 46, + -17, -8, -5, 5, 29, -44, 17, 24, -43, 20, 13, -42, 16, 37, -43, 5, + 22, 4, -31, 6, 26, -40, 11, 31, -45, 24, 9, -27, 26, -29, 26, -13, + -16, 38, -40, 19, 21, -37, -9, 51, -32, -18, 34, -11, -7, -11, 22, 0, + -40, 49, -20, -23, 44, -22, -9, 3, -2, 19, -44, 42, 6, -52, 41, 6, + -43, 20, 28, -48, 31, 8, -23, 10, -7, 7, -19, 4, 31, -41, 15, 28, + -40, 16, -8, 16, -25, -4, 51, -55, 19, 0, 8, -29, 29, -16, -11, 37, + -39, 18, 4, -6, -5, -14, 35, -6, -52, 72, -37, -9, 13, 11, -17, -22, + 53, -32, -20, 42, -19, -18, 12, 19, -29, 12, 12, -24, 15, -6, 6, -12, + -15, 54, -44, -2, 41, -48, 32, -20, -4, 9, 1, 5, -35, 48, -11, -17, + -9, 24, 1, -37, 38, -9, -16, 16, -2, -11, -1, 13, 11, -55, 67, -31, + -19, 37, -26, -4, 12, 16, -34, 11, 21, -22, -10, 12, 0, 0, -21, 37, + -16, -11, 29, -37, 15, -3, 17, -37, 13, 38, -54, 30, -2, -19, 11, -11, + 20, -20, 15, 4, -22, 13, 2, -8, -13, 20, 4, -28, 33, -9, -34, 38, + -13, -6, -14, 46, -33, -9, 36, -34, 4, 8, -9, 11, -9, 5, 1, -17, + 23, -16, -3, 4, 18, -26, -11, 54, -53, 5, 18, -5, -11, 8, 11, -20, + 12, -10, 1, 2, 5, -4, -5, -1, 23, -35, 22, -1, -25, 19, 3, -7, + -11, 22, 1, -37, 45, -26, -12, 20, 2, -23, 17, 13, -23, -4, 18, 1, + -15, -15, 33, 4, -49, 46, -25, 3, 5, 2, -11, 7, 13, -33, 13, 10, + -24, 12, 6, -3, -4, 12, -9, -10, -3, 20, -19, -3, 19, -2, -21, 16, + 5, -33, 35, -17, -3, 2, 17, -12, -21, 27, -17, -6, 19, -8, -6, 14, + -12, 10, -16, 13, 0, -19, 11, 20, -23, -9, 38, -50, 22, 17, -24, -5, + 17, 7, -24, 0, 23, -18, -14, 27, -15, 5, 6, -9, 1, -2, 7, -24, + 16, 10, -12, -9, 26, -19, -14, 30, -18, -13, 19, -10, 10, -8, 6, 1, + -27, 35, -13, -20, 26, -5, -11, -10, 28, -9, -32, 36, -3, -25, 12, 28, + -51, 36, -6, -20, 18, -2, -3, -1, -11, 28, -31, -4, 48, -56, 16, 19, + -18, 6, -4, 1, -10, 11, 0, -4, -6, 25, -26, -9, 30, -26, -6, 23, + -13, 10, -7, -3, 19, -56, 64, -30, -31, 50, -4, -31, 15, 15, -27, 6, + 13, -6, -14, 20, -2, -27, 23, 7, -30, 10, 19, -10, -1, -13, 27, -31, + 3, 38, -56, 29, 20, -45, 24, 5, -17, 0, 5, 3, -9, 2, 24, -25, + -14, 31, -13, -22, 28, -6, -8, 1, 3, 13, -41, 51, -39, -20, 60, -30, + -28, 48, -14, -26, 25, -10, 7, -17, 16, 5, -25, 13, 10, -32, 11, 35, + -46, 17, 10, 5, -32, 10, 21, -44, 19, 30, -39, 15, 7, -18, 11, -11, + 10, -13, 1, 19, -14, -12, 30, -25, -18, 43, -23, -15, 30, -13, -6, -14, + 43, -42, -9, 55, -36, -17, 43, -21, -11, 12, -13, 16, -28, 23, 10, -38, + 27, 17, -47, 22, 20, -46, 30, -7, 6, -10, -6, 26, -34, 15, 22, -39, + 15, 21, -43, 26, -6, 1, -14, 12, 20, -26, -12, 41, -29, -29, 57, -40, + 2, 27, -22, 8, -10, 10, -10, -10, 30, -14, -29, 47, -17, -24, 25, -11, + 3, -17, 30, -3, -32, 28, 7, -44, 35, 12, -46, 39, -6, -10, -2, -3, + 23, -31, -4, 49, -48, 6, 39, -55, 32, -8, -9, 0, 8, 7, -15, -3, + 29, -26, -16, 43, -44, 13, 26, -30, 9, 6, -5, 4, -28, 30, 9, -56, + 64, -19, -33, 43, -25, -8, 14, 8, -14, -8, 18, 11, -44, 23, 17, -39, + 20, 19, -24, -1, 12, 7, -27, -2, 47, -51, 3, 47, -55, 28, 1, -23, + 17, 4, -12, 5, -9, 18, -9, -21, 30, -24, 6, 12, -11, -2, 14, -13, + -3, -10, 26, -10, -45, 74, -31, -31, 51, -26, -14, 19, -8, 2, -4, 3, + 23, -43, 20, 15, -31, 13, 20, -36, 18, 9, -17, -3, 0, 21, -32, 12, + 32, -50, 21, 12, -26, 16, -6, 5, 1, -16, 21, -5, -27, 28, -11, -11, + 19, -2, -20, 28, -17, -2, 4, -5, 9, -26, 43, -31, -11, 47, -42, 1, + 19, -16, 5, -8, 12, 9, -41, 41, -7, -32, 22, 25, -51, 23, 14, -18, + 7, -21, 31, -22, -2, 24, -24, 6, 18, -39, 25, -9, 3, 5, -17, 28, + -13, -17, 27, -21, -12, 25, -12, -12, 32, -19, -6, 11, -24, 29, -21, 11, + -2, -17, 36, -29, -9, 24, -16, -2, 7, -6, 17, -27, 27, -20, -11, 23, + -1, -31, 25, 15, -32, 12, -8, 21, -22, -8, 26, -16, -15, 47, -45, 8, + 12, -12, 14, -28, 33, -10, -15, 15, -11, 6, 2, -17, 5, 23, -20, -5, + 19, -21, 12, -8, -8, 31, -38, 31, -17, -14, 31, -27, -1, 19, -20, 19, + -10, 4, -2, -7, 2, 1, -6, 6, 12, -27, 12, 8, -10, -7, 8, -1, + -3, -15, 47, -53, 15, 25, -40, 24, -7, 12, -13, -11, 22, -7, -22, 14, + 7, -5, -11, 13, 5, -8, -9, 4, 7, -22, 22, -12, 16, -9, -16, 29, + -32, 8, 23, -36, 14, 7, -3, 5, -27, 24, -1, -20, 14, 7, -7, -4, + 9, -21, 6, 23, -27, 7, -1, 23, -30, -3, 31, -39, 26, -17, -3, 30, + -24, 9, -7, -13, 30, -24, 3, 2, 9, -6, -15, 24, -18, 9, -20, 16, + 2, -8, 11, -11, 6, -10, 6, 11, -38, 27, 20, -42, 28, -26, 35, -21, + -29, 51, -32, 8, -3, 15, -19, 3, 14, -33, 24, 4, -9, -9, 4, 23, + -29, 0, 21, -32, 39, -38, 20, 8, -34, 38, -27, 8, 12, -12, 3, -8, + 11, -11, 1, 3, -9, 18, -18, 10, 0, -7, 4, -13, 17, -13, 0, 33, + -56, 42, -11, -7, 7, -17, 36, -50, 24, 21, -25, -7, 14, 9, -27, 8, + 23, -28, 3, 8, 2, -12, -10, 39, -43, 24, -4, -5, 18, -38, 39, -26, + -8, 26, -24, 14, 10, -20, 5, -9, 15, -19, 13, -12, 5, 24, -39, 24, + -8, 8, -16, -14, 53, -49, 16, 5, -22, 26, -28, 18, -13, 7, 18, -31, + 6, 17, -12, -13, 3, 26, -35, 16, 18, -36, 21, -12, 28, -49, 27, 22, + -38, 13, -1, 17, -28, -5, 30, -22, 2, 25, -42, 32, -19, 18, -23, -1, + 21, -20, 22, -31, 25, 3, -25, 9, -6, 27, -29, -3, 32, -35, 19, -7, + -8, 11, -12, 28, -35, 1, 39, -33, -6, 2, 30, -35, -1, 41, -42, 18, + -9, 6, -8, -2, 26, -46, 24, 24, -41, 11, 11, -2, -12, -9, 48, -59, + 31, -10, 6, -12, -5, 34, -43, 33, -12, -7, 11, -11, 1, 7, -12, 17, + -23, 32, -24, -5, 19, -26, 27, -28, 24, -15, -5, 31, -41, 11, 11, -4, + -19, 10, 37, -53, 2, 43, -35, 2, -3, 20, -20, 3, 32, -53, 30, 5, + -24, 10, -7, 41, -53, 10, 33, -31, -8, 11, 12, -30, 28, 4, -37, 28, + 8, -30, 12, -17, 42, -38, 5, 24, -33, 35, -41, 23, -1, -4, 5, -20, + 32, -18, -10, 25, -22, -4, 14, 6, -24, -5, 62, -80, 28, 19, -20, 4, + -14, 41, -49, 14, 34, -45, 3, 13, 17, -37, -4, 66, -61, -5, 35, -15, + -5, -2, 14, -24, 21, 5, -41, 41, -22, 18, -24, 5, 44, -66, 34, -3, + -17, 24, -26, 20, -13, 14, -1, -31, 39, -19, -20, 31, -14, 0, -12, 46, + -61, 29, 19, -44, 36, -26, 30, -31, -7, 49, -41, -15, 54, -42, -1, 12, + 24, -48, 8, 44, -57, 17, 13, 7, -34, 13, 33, -55, 28, 4, -14, 4, + -9, 32, -42, 15, 28, -58, 40, -12, 0, 7, -8, 8, -24, 29, -9, -29, + 38, -23, 9, -8, 13, -7, -14, 24, -37, 32, -7, 3, -17, 1, 39, -46, + -20, 78, -68, 15, 17, -6, -4, -15, 37, -47, 15, 20, -17, -12, 28, 9, + -52, 25, 31, -54, 24, 4, -1, -11, -5, 51, -74, 36, 9, -27, 17, -6, + 8, -12, 3, 6, -16, 14, 0, -15, 10, 3, 7, -31, 34, -22, -2, 17, + -20, 9, 10, -7, -13, -5, 45, -52, 8, 30, -33, 15, -11, 28, -32, -5, + 44, -42, -4, 42, -25, -29, 29, 14, -36, 12, 19, -20, 8, -14, 33, -42, + 16, 23, -48, 32, 2, -14, 2, -1, 14, -21, -9, 42, -47, 24, 0, -10, + 0, 15, -19, -1, 21, -31, 13, 15, -23, 10, -14, 20, -7, -27, 50, -32, + -5, 18, -10, -1, -8, 25, -36, 12, 34, -45, 6, 27, -20, -16, 12, 19, + -22, 0, 12, 0, -13, -8, 31, -41, 17, 16, -29, 17, 11, -19, -4, -2, + 36, -55, 30, 13, -35, 25, -7, -8, 10, -4, -8, 13, -7, 0, 4, -16, + 8, 13, -35, 40, -25, -6, 44, -51, 17, 15, -18, -3, 1, 14, -18, -1, + 24, -23, -9, 20, -6, -9, 1, 24, -30, 6, 6, 10, -29, 8, 31, -48, + 21, 27, -43, 13, 4, -4, -5, -2, 19, -18, 12, -15, 4, 16, -25, 9, + 1, 2, 0, -13, 12, 3, -16, -3, 18, -10, -6, 25, -41, 21, 11, -30, + 20, -3, 0, 1, -14, 27, -19, -21, 38, -28, 9, -3, 14, -22, 13, -4, + -2, -6, 12, 2, -26, 30, -1, -38, 31, 7, -32, 25, -16, 14, -4, -9, + 15, -19, 6, 4, -11, 2, 11, -8, -4, 10, -7, -4, 6, -10, 2, 11, + -9, 0, -5, 15, -16, 0, 9, -2, -7, 0, 11, -11, -12, 35, -44, 20, + 13, -19, 2, 13, -11, -14, 12, 10, -22, -2, 27, -24, -2, 15, 5, -29, + 22, -10, 6, -2, -3, 16, -31, 20, 11, -39, 29, 9, -34, 25, -10, 5, + -2, -15, 14, 0, -5, -6, 19, -18, 13, -22, 5, 24, -30, -1, 35, -23, + -12, 12, 12, -26, 5, 22, -32, 16, 16, -27, 2, 10, -4, -12, 2, 23, + -19, -1, 1, 11, -17, 4, 8, -18, 12, 12, -24, 1, 24, -20, -15, 29, + -5, -31, 42, -23, -8, 20, -18, 19, -33, 24, 8, -22, 0, 32, -38, 9, + 21, -25, 2, 23, -30, 7, 16, -20, 12, -10, 8, -14, 12, 16, -41, 24, + 14, -30, 6, 2, 19, -22, -6, 25, -8, -24, 23, -1, -29, 32, 9, -53, + 50, 4, -42, 12, 12, 3, -24, 15, 14, -25, 5, 4, 7, -25, 26, -5, + -23, 28, 0, -32, 23, -1, -21, 14, 10, -7, -13, 21, -25, 16, -8, 1, + -1, -1, 13, -22, 12, 12, -28, 3, 13, 1, -15, -3, 38, -41, -5, 45, + -37, -9, 30, -4, -35, 42, -10, -25, 19, -4, 3, -18, 12, 22, -43, 25, + 14, -37, 21, 4, -19, 5, 17, -12, -17, 26, -4, -22, 11, 7, 6, -31, + 35, -15, -14, 22, -14, 0, 0, 14, -16, -12, 31, -17, -19, 25, -10, 0, + 2, 12, -23, 8, 16, -44, 37, 0, -19, -2, 21, -5, -25, 22, 12, -38, + 3, 37, -11, -38, 36, 11, -54, 40, -9, -11, 14, -11, 11, -19, 17, 17, + -47, 16, 25, -17, -23, 34, -3, -29, 25, -17, 5, 14, -17, 3, -4, 21, + -23, -11, 35, -31, 7, 13, -17, 13, -6, 6, -22, 13, 5, -8, -8, 16, + 8, -34, 18, 21, -49, 32, 12, -45, 32, 0, 1, -32, 27, 2, -20, 10, + 6, 3, -26, 18, 19, -50, 31, 13, -40, 20, 12, -7, -19, 21, -9, -12, + 24, -21, 6, 7, -6, -2, -9, 23, -19, -8, 15, -7, 18, -26, 13, 5, + -21, 21, -19, 4, 25, -26, -14, 32, -2, -33, 21, 8, -29, 38, -35, 17, + 8, -19, 15, -29, 24, 15, -40, 10, 28, -21, -26, 34, 7, -42, 35, -3, + -14, -1, 18, -6, -30, 29, -1, -11, 8, -8, 16, -22, -2, 25, -27, 14, + 0, -9, 1, 9, 1, -25, 22, -16, 12, 8, -33, 32, 2, -35, 19, 4, + 0, -17, 15, 1, -6, 9, -15, 16, -30, 25, 8, -46, 40, 11, -39, 8, + 11, 2, -21, 10, 11, -17, 15, -6, -4, -10, 18, -6, -23, 29, -2, -7, + -13, 9, 24, -48, 23, 17, -30, 27, -22, 9, 4, -16, 8, 4, -9, -2, + 19, -12, -12, 21, -22, 15, -8, -2, 20, -39, 32, -5, -16, 11, 5, -15, + -8, 30, -5, -36, 34, -5, -13, 1, 3, 22, -37, 14, 6, -8, 0, -6, + 11, -17, 23, -6, -18, 19, -7, -4, -14, 11, 17, -32, 24, -6, -2, 9, + -26, 30, -24, 2, 18, -19, 7, 4, -6, -3, -1, 3, 1, 0, -21, 39, + -20, -33, 51, -27, -6, 24, -18, 8, -10, 12, -3, -23, 25, -11, 5, -19, + 25, 2, -34, 29, -5, -9, -7, 18, -12, -18, 30, -4, -26, 20, -9, 22, + -32, 7, 26, -28, 6, -9, 19, -20, 5, 2, -9, 26, -15, -13, 18, -19, + 15, -3, -26, 34, 2, -33, 6, 36, -36, -12, 36, -32, 29, -24, 10, 13, + -39, 30, -6, -17, 12, 9, -9, -17, 28, -6, -27, 21, 4, -15, 6, 13, + -13, -16, 30, -21, 1, -4, 4, 28, -60, 46, -3, -21, 3, 5, -8, 17, + -17, 3, 11, -6, -9, 11, -8, -17, 44, -36, 0, 20, -9, -4, -13, 29, + -24, 5, -3, 6, 14, -36, 26, -3, -23, 30, -3, -30, 25, 3, -12, -22, + 42, -13, -27, 19, 9, -3, -20, 16, -7, -3, 7, -5, 6, -13, 22, -21, + -15, 39, -17, -21, 30, -23, 19, -6, -20, 31, -24, 0, 8, 12, -31, 20, + 8, -27, 20, -14, 20, -22, -2, 17, 0, -18, 11, 0, 7, -28, 22, -2, + -19, 31, -17, -8, -2, 28, -24, -16, 34, -4, -28, 9, 26, -12, -30, 29, + -7, -6, 10, -1, -10, 5, -3, 6, -23, 29, -18, 10, -16, 7, 28, -48, + 21, 4, -12, 9, 4, -12, 5, -1, -7, 2, 0, -3, 11, -15, -3, 26, + -19, -4, 3, 1, 10, -37, 49, -26, -9, 6, 18, -23, 0, 17, -3, -27, + 25, 3, -22, 10, 6, -3, -19, 32, -23, 9, -3, -3, 11, -31, 27, 12, + -42, 23, 13, -12, -18, 30, -10, -19, 13, -4, 0, 17, -25, 12, -2, -2, + 4, -8, 9, -12, 8, -17, 24, -2, -19, 14, -16, 18, -6, -12, 22, -12, + -17, 20, 0, -4, -13, 19, -5, -18, 30, -19, 8, -17, 19, -9, -6, 8, + 1, 1, -36, 48, -9, -40, 46, 1, -50, 44, -5, -14, -3, 10, 4, -17, + 11, -1, 11, -25, 9, 10, -24, 19, 2, -9, -4, 4, 10, -26, 20, -8, + 6, -3, -12, 17, 7, -31, 18, -14, 17, -7, 0, 2, -8, 9, -15, 19, + -16, 8, 2, -22, 21, 15, -33, 4, 24, -20, -13, 36, -18, -24, 33, -16, + -8, 20, -19, 22, -32, 21, 0, -5, -7, 18, -17, -11, 26, -5, -25, 25, + 3, -17, -3, 15, 7, -35, 22, -3, 2, -2, -6, 7, -3, -4, 4, -13, + 25, -17, 1, -4, 7, -12, 13, -2, -11, 12, 2, -25, 24, 0, -25, 17, + -4, 6, -9, 14, -11, -8, 5, 0, 10, -25, 23, 1, -28, 27, 5, -26, + 0, 23, -11, -20, 21, 10, -30, 12, 9, -5, -16, 25, -12, -19, 26, -3, + -12, 1, 9, -1, -15, 11, 3, -12, 6, -5, 11, -7, -8, 6, 3, -11, + 4, 5, 0, -11, 7, -1, 6, -17, 1, 26, -35, 14, 6, -6, -8, 15, + -7, -9, 13, -2, -20, 19, 6, -11, -14, 24, 7, -36, 19, 11, -24, 1, + 23, -18, -4, 18, -10, -19, 29, -10, -9, -1, 6, 10, -23, 10, 19, -32, + 11, 11, -4, -13, 5, 12, -17, 3, 13, -20, 11, 0, -8, 5, 14, -32, + 19, 1, -22, 28, -16, -8, 13, 3, 0, -11, -10, 38, -40, 3, 22, -9, + -16, 19, -4, -13, 13, 9, -29, 9, 16, -9, -20, 25, -2, -22, 11, 6, + 4, -22, 12, 16, -35, 15, 26, -42, 13, 12, -5, -20, 24, -4, -18, 20, + -7, -11, 9, 5, -7, 1, -2, -2, 10, -18, 9, 11, -17, -2, 7, -5, + 28, -48, 12, 31, -36, 12, 8, -2, -14, 8, 2, -5, -1, 11, -17, -4, + 21, -1, -27, 19, 3, -13, 0, 8, 15, -39, 19, 17, -43, 34, 4, -32, + 16, 8, -10, -8, 21, -10, -12, 6, 9, -4, -10, 3, 9, -13, 8, 2, + -7, 1, 1, 2, -18, 22, -10, 2, 5, -19, 19, -4, -11, 11, -5, 2, + -13, 7, 15, -24, 9, 11, -20, -2, 21, 1, -38, 21, 9, -2, -22, 23, + 6, -41, 34, -2, -19, 27, -10, -23, 20, -3, 13, -34, 20, 10, -15, -3, + 14, -1, -19, 3, 4, 5, 8, -14, 9, -18, 18, -1, -22, 24, -8, -8, + 10, -10, 14, -12, -4, 6, -14, 30, -38, 28, -5, -23, 19, 4, -10, -9, + 22, -7, -22, 17, 8, -5, -19, 25, -9, -23, 31, -6, -26, 31, -20, 18, + -29, 22, 20, -54, 33, -4, 1, -3, 4, -8, 0, -5, 13, -6, -6, 9, + -1, -24, 36, -9, -26, 30, -24, 11, 8, -23, 22, -16, 5, -11, 20, -2, + -26, 23, -9, -3, 0, 9, -10, -6, 13, -3, -17, 25, -12, -2, -8, 16, + 4, -35, 39, -14, -9, -2, 23, -6, -37, 40, -12, -11, 4, 8, 1, -13, + 1, 17, -26, 12, 10, -27, 17, 4, -6, -18, 42, -32, 2, 4, -16, 36, + -31, 0, 10, 0, -1, -12, 15, 0, -28, 22, -3, -1, 6, -6, -9, -3, + 25, -18, -8, 7, 6, 5, -39, 48, -16, -23, 22, -2, -8, 1, 18, -25, + -9, 25, 1, -28, 16, 9, 0, -34, 37, -4, -27, 27, -18, -1, 6, 4, + -5, -8, 16, -9, 10, -21, 6, 12, -14, -4, 6, 9, 3, -31, 33, -14, + -12, 23, -28, 25, -10, 2, -11, 1, 11, 6, -30, 3, 40, -21, -34, 46, + -12, -22, 11, 6, -2, -10, 14, -10, -21, 49, -29, -16, 17, 9, -15, -13, + 32, -19, 0, 0, 8, 0, -14, 8, -4, -16, 30, -17, 2, -1, 0, 9, + -15, 6, -4, 11, -15, -6, 28, -28, 17, -18, 7, 11, -19, 12, 3, -24, + 21, 3, -29, 15, 26, -25, -27, 51, -18, -19, 7, 20, -21, -11, 36, -32, + -3, 35, -27, -4, 6, 8, 2, -31, 18, 18, -29, 1, 25, -16, -8, 19, + -30, 13, 16, -20, 8, -12, 19, -3, -21, 15, 0, -6, -3, 4, 6, 1, + -20, 2, 20, -5, -27, 31, -7, -21, 19, 6, -19, -10, 40, -28, -17, 40, + -15, -22, 12, 13, -23, 6, 14, -12, -7, 10, 11, -11, -30, 45, -9, -44, + 48, -5, -14, -5, 20, -22, 9, 3, -10, 0, 4, 4, -7, -9, 24, -23, + 3, 8, -15, 15, -2, -19, 21, -8, -6, -1, 14, -7, -12, 18, -10, -3, + 3, 21, -37, 2, 29, -23, -7, 22, -10, -2, -7, 20, -10, -20, 15, 5, + -25, 17, 23, -29, -16, 50, -35, -9, 19, 4, -22, 2, 24, -19, -10, 25, + -9, -22, 23, 3, -15, -6, 10, -4, 13, -29, 17, 13, -26, -2, 25, -23, + 14, -16, 12, -2, -2, 4, -11, 1, 11, 0, -22, 14, 18, -28, -6, 11, + 22, -29, -10, 42, -30, -12, 26, -12, -15, 19, 15, -41, 10, 33, -16, -32, + 20, 29, -47, 10, 36, -35, -1, 20, -19, 1, 9, 5, -14, -16, 15, 29, + -38, -6, 35, -16, -20, 18, 6, -9, -7, 1, 4, 6, -4, 0, -9, 2, + 8, 2, -14, -4, 24, -12, -32, 41, -1, -26, 1, 23, -22, 4, 11, -10, + -6, 8, 16, -28, -12, 52, -28, -40, 53, 2, -29, 2, 17, -10, -5, -2, + 8, -1, -13, 25, -10, -33, 51, -16, -32, 12, 29, -27, -11, 25, 7, -27, + 4, 12, 0, -15, 5, -2, 4, -11, 11, 21, -51, 15, 37, -46, 7, 24, + -9, -20, 2, 27, -11, -17, 4, 22, -40, 26, 16, -36, 2, 35, -32, -2, + 12, 14, -23, -17, 26, 10, -26, 3, 20, -20, -9, 28, -16, -9, 19, -4, + -21, 15, 12, -17, -15, 24, -7, -6, 5, -2, 10, -21, 4, 12, -9, -11, + 30, -12, -32, 38, 3, -33, 11, 11, 0, -24, 4, 44, -37, -18, 36, -8, + -25, 21, 5, -24, 10, -1, 18, -22, -2, 30, -38, -8, 41, -24, -3, 4, + 8, -6, -11, 20, -11, -20, 22, -2, 2, -8, 8, -12, 8, -17, 11, 18, + -34, 19, -4, 5, -3, -9, 5, -6, 6, -4, -6, 17, -5, -11, 2, 12, + -8, -16, 15, 3, -21, 13, 8, -7, -8, 12, -5, -5, -17, 33, -1, -44, + 35, 15, -42, 18, 15, -21, 4, -4, 10, -5, -14, 27, -21, -7, 19, 1, + -3, -8, -6, 9, -1, -23, 29, -13, -1, -2, 4, 8, -6, -20, 26, -22, + 5, 21, -25, 9, 3, -11, 16, -12, -4, 20, -20, -8, 25, -13, -5, 6, + -11, 13, 6, -30, 13, 24, -31, -11, 27, 9, -43, 28, 2, -3, -5, -4, + 13, -16, -1, 10, -8, -4, 11, 8, -23, 14, 0, -4, -10, 1, 14, -14, + 3, 2, -3, 20, -35, 26, -6, -25, 38, -32, 12, -10, 16, -10, 14, -24, + 9, 33, -83, 72, -13, -27, 28, -26, 25, -13, 8, -25, 18, 15, -29, 17, + -3, 9, -25, 2, 19, -20, 18, -20, 13, 4, -18, 32, -32, -10, 35, -18, + -12, 16, 10, -15, -5, 4, 13, -21, 1, 0, 14, -18, 9, 12, -26, 27, + -27, 9, 1, -4, -1, 1, 14, -33, 52, -49, -1, 46, -50, 21, -5, 12, + -9, -7, 6, 1, -2, -10, 14, -2, -10, 13, -19, 23, -26, 18, -2, -22, + 34, -30, 8, 20, -38, 14, 18, -18, -5, 9, 3, -6, -13, 24, -1, -28, + 12, 11, -14, -1, 21, -37, 31, -16, 5, 6, -26, 32, -23, 4, 2, 9, + 2, -40, 40, -7, -10, 2, 0, 9, -16, -1, 16, -3, -10, -3, 19, -22, + 6, 7, -9, -4, -10, 39, -38, 5, 27, -28, 0, 13, -8, 1, -3, 5, + -3, -9, 13, -8, -4, 13, -14, -6, 22, -14, -13, 31, -30, 22, -15, -15, + 55, -56, 6, 26, -23, 8, 1, 4, -17, 8, 6, -9, 9, -11, 15, -18, + 5, 14, -18, 9, -22, 26, -2, -23, 25, -11, 1, -16, 15, 12, -28, -4, + 35, -31, -3, 28, -8, -12, -8, 26, -21, -1, 3, -2, 12, -18, 18, -3, + -6, -9, 14, -23, 9, 36, -57, 29, 21, -50, 29, -2, -13, 7, 0, -5, + 6, -1, -4, 10, -25, 23, -3, -19, 28, -20, 11, -17, -5, 37, -39, 19, + -7, 1, 7, -17, 12, 14, -36, 6, 23, -23, 9, 12, -19, 4, 2, 2, + 6, -27, 14, 17, -39, 14, 34, -22, -31, 34, 6, -36, 28, -1, -28, 24, + 1, -18, 24, -20, 9, -2, -15, 21, -4, -23, 23, -10, -4, 15, -12, 3, + -6, 2, 10, -28, 28, -6, -15, 14, -14, 10, 1, -18, 14, 5, -19, 15, + 2, -18, 22, -17, -7, 29, -43, 45, -15, -40, 62, -27, -23, 23, 10, -20, + -20, 41, -7, -20, 9, 10, -22, 8, 5, 9, -21, 0, 22, -11, -18, 27, + -4, -34, 30, 3, -9, -2, 1, 4, -13, 6, 16, -25, 11, -11, 8, 1, + -11, 14, -4, -6, 4, 1, -2, -7, 1, -3, 11, -31, 57, -36, -10, 37, + -44, 22, -2, -10, 4, -1, 7, -2, -7, 7, 14, -33, 5, 24, -29, 7, + 10, -1, -13, 0, 26, -23, -16, 43, -32, -14, 23, 11, -23, -5, 13, 13, + -44, 44, -7, -18, 7, -7, 12, -12, -1, -1, 7, 0, -6, 26, -37, 17, + -6, 4, -19, 18, 13, -37, 24, 4, -7, 0, -13, 15, 3, -28, 22, 14, + -41, 27, 5, -28, 38, -30, 9, -6, -1, 18, -28, 8, 26, -36, 4, 21, + -3, -30, 28, -6, 1, -26, 45, -28, -15, 34, -15, -12, 6, 8, 1, -9, + -16, 26, 1, -50, 65, -34, -12, 25, -9, 4, -14, 21, -17, -2, -6, 10, + 17, -29, -6, 40, -23, -20, 27, 0, -40, 44, -27, 16, -6, 2, 3, -20, + 15, 15, -32, -1, 28, -9, -29, 38, -22, 14, -21, 16, -5, -6, 17, -35, + 20, 13, -19, 0, 2, 2, 16, -32, 0, 47, -61, 16, 31, -37, 21, -8, + 6, -7, 3, -6, 8, -9, -12, 29, -13, -20, 33, -16, 0, -21, 46, -39, + 2, 17, -3, -11, -6, 18, 2, -35, 29, 17, -37, 0, 42, -42, 9, -3, + 16, -19, -2, 24, -17, -2, 0, -1, 6, -12, 19, -12, -16, 27, -2, -27, + 16, 17, -42, 38, -22, 8, 2, -12, -1, 15, -18, 13, -6, -11, 7, 21, + -36, 26, -23, 38, -48, 15, 26, -20, -18, 24, -1, -4, -20, 34, -16, -17, + 18, 11, -30, 15, 7, -10, -10, 12, 15, -31, -1, 28, -6, -32, 30, 4, + -24, 1, 28, -28, 7, -11, 33, -39, 23, -15, 19, -12, -12, 11, 4, -25, + 33, -22, 14, -4, -3, -6, 10, -21, 31, -40, 19, 13, -10, -1, 14, -18, + -3, 10, -4, -5, -2, 10, -6, -14, 21, 14, -40, 15, 6, 3, -31, 28, + 12, -42, 11, 43, -44, 2, 27, -17, -18, 22, -16, 33, -59, 37, 15, -35, + 11, 20, -22, 1, -7, 22, -22, 7, -1, 9, -16, -4, 20, 3, -38, 31, + 9, -31, -3, 39, -34, 8, 4, -19, 41, -41, 11, 21, -40, 19, 18, -47, + 45, -14, -5, -13, 26, -4, -28, 19, 15, -45, 38, -4, -9, -4, 17, -29, + 28, -27, 34, -25, -20, 39, 5, -52, 49, -15, -13, 5, -3, 14, -2, -20, + 17, -3, -12, 18, -7, -9, 1, 10, 7, -31, 19, 13, -29, 12, -22, 52, + -30, -28, 40, 7, -60, 56, -19, -5, -5, 22, -26, 13, 1, 5, -28, 30, + -12, 3, -17, 25, -26, 16, -16, 20, -5, -14, 26, -19, -33, 67, -47, 2, + 20, -19, 21, -22, 12, 12, -25, 0, 17, -26, 24, -4, -15, 6, 9, -8, + 13, -28, 24, -15, 13, -27, 26, 3, -11, -31, 61, -31, -19, 24, 5, -33, + 22, -3, 14, -35, 22, 10, -28, 8, 23, -24, -2, 1, 18, -18, -8, 26, + -15, -12, 26, -31, 15, 10, -24, 18, -19, 35, -32, -1, 15, 7, -40, 36, + -14, -4, 16, -12, -22, 51, -54, 41, -31, 14, 4, -17, 5, 13, -24, 29, + -31, 12, 25, -34, -2, 30, -36, 21, -16, 22, -4, -36, 42, -11, -6, -12, + 31, -16, -29, 34, 6, -29, -4, 37, -23, -25, 51, -34, 9, -11, 23, -25, + 14, -8, 5, -20, 32, -22, 6, 14, -16, -3, 24, -49, 51, -46, 31, -4, + -21, 26, -13, 0, 7, -9, -2, -1, 8, -21, 22, -21, 29, -29, 10, 22, + -41, 37, -24, -7, 15, 3, -25, 26, 1, -15, 5, 2, 14, -33, -3, 54, + -69, 27, 13, 5, -37, 27, 4, -6, -19, 19, -3, -9, 2, 10, -11, 15, + -30, 38, -35, 20, 0, -29, 37, -16, 1, -14, 21, -12, -7, 22, -33, 30, + -19, 4, -7, -1, 31, -57, 46, -15, -8, 20, -21, -1, 18, -21, 17, -12, + 6, 7, -20, 2, 32, -57, 46, -7, -25, 12, 25, -32, -3, 18, 1, -12, + -15, 31, 4, -56, 52, -11, -6, -20, 23, 19, -50, 37, -7, -9, -1, 14, + -22, 10, 14, -36, 37, -18, -8, 25, -31, 20, -16, 21, -26, 10, 7, -15, + 9, 3, -14, 19, -25, 24, -15, -4, -4, 27, -37, 21, 7, -12, 1, -5, + 4, 5, -12, -4, 10, -12, 17, -10, -16, 52, -56, 5, 29, -12, -5, -28, + 56, -30, -19, 34, -3, -30, 20, 4, -21, 12, 9, -17, 21, -35, 43, -19, + -20, 21, -4, -13, 12, -10, 9, 0, -6, -4, 10, -19, 25, -23, 6, -3, + 10, -5, -15, 31, -12, -14, -4, 22, -15, -5, 1, 17, -17, -8, 28, -15, + -8, 6, -10, 2, 7, 8, -31, 25, 3, -20, -2, 26, -10, -22, 12, 20, + -25, 6, -11, 33, -36, -2, 43, -36, -8, 20, -9, -7, 2, 4, 5, -7, + -5, 24, -28, 11, 6, -24, 20, -7, -2, 6, -9, -1, 20, -35, 13, 27, + -31, -7, 31, -13, -12, -6, 27, -14, -24, 33, -6, -10, 15, -14, 6, -13, + 9, 0, -8, -1, 19, -20, 6, 10, -9, -15, 23, -20, -4, 31, -24, 2, + -13, 23, 1, -25, 14, 12, -16, -18, 25, 4, -25, 15, -3, 2, 6, -16, + 21, -12, -19, 19, 1, -18, 21, 1, -30, 25, 3, -15, -5, 6, 18, -34, + 4, 32, -13, -18, 1, 28, -21, -30, 44, -1, -41, 28, 16, -32, 9, 14, + -17, 6, -11, 5, 21, -43, 38, -11, -24, 39, -15, -18, 18, -3, -15, 0, + 20, -15, 2, -1, -6, 32, -43, 13, 19, -26, -3, 17, 10, -29, 19, 1, + -19, 22, -13, 7, -16, 10, 8, -17, -1, 12, 1, -18, 1, 40, -49, 6, + 34, -35, -8, 30, -2, -23, 4, 15, 12, -39, 2, 55, -57, -8, 47, -27, + -7, 18, -7, 2, -11, 0, 19, -21, 4, 2, 10, -32, 34, -16, -12, 20, + -12, 2, -4, 20, -12, -22, 22, -14, 9, -12, 6, 21, -24, -7, 27, -13, + -22, 13, 16, -38, 37, -2, -21, 19, -14, 2, -6, 6, 7, -16, -11, 44, + -22, -35, 52, -10, -41, 24, 16, -13, -19, 14, 21, -20, -29, 55, -20, -21, + 5, 28, -30, -3, 22, -6, -10, 5, 11, -11, -7, 15, -11, -4, -10, 18, + 1, -23, 24, 3, -24, 10, 5, 0, -32, 35, -7, -12, 1, 11, 18, -53, + 36, 7, -26, 0, 24, -27, 0, 26, -24, 6, 6, -13, 16, -21, 13, 1, + -25, 20, 26, -61, 40, 21, -41, -6, 28, 1, -24, -7, 38, -14, -25, 20, + 5, -16, -1, 6, 13, -20, -7, 39, -33, -8, 25, -14, 5, -20, 26, 2, + -28, 14, 14, -18, -23, 64, -60, 11, 24, -9, -13, -2, 17, -5, -25, 16, + 22, -13, -44, 61, -14, -38, 35, -7, -18, 28, -16, -10, 25, -9, -20, 8, + 6, 8, -23, 11, 19, -27, -1, 15, 0, -25, 18, 8, 2, -34, 38, 1, + -41, 23, -7, 13, -6, -19, 45, -20, -27, 24, 14, -61, 53, -13, -13, 21, + -21, 36, -25, -33, 58, -33, -26, 35, 19, -50, 7, 50, -35, -20, 28, 5, + -29, -1, 28, -20, 3, -10, 20, -8, -16, 35, -22, -13, 17, -10, -3, 15, + -25, 24, -7, 0, -8, -3, 29, -32, -7, 30, -16, 9, -29, 24, 10, -27, + -9, 49, -40, 4, 14, -28, 37, -29, -18, 68, -67, 12, 45, -48, 3, 31, + -21, -16, 9, 20, -3, -40, 38, 17, -65, 41, 8, -15, -9, -2, 46, -51, + -7, 64, -51, -31, 57, -21, 5, -10, -7, 35, -36, 0, 20, -20, 14, -16, + 10, 9, -1, -26, 26, -18, -3, 5, 14, -8, -17, 32, -25, 1, 17, -29, + 17, 17, -47, 50, -19, -12, 9, -1, -11, 17, -29, 44, -25, -36, 63, -32, + -18, 29, -7, 9, -38, 32, 14, -50, 21, 37, -57, 13, 37, -17, -16, -9, + 28, -6, -60, 76, -13, -34, 29, 1, -5, 9, -41, 35, -2, -48, 52, -5, + -3, -17, 14, 5, -12, -13, 24, -20, 7, -4, 10, 2, -13, 10, -2, -18, + 20, 2, -33, 37, -18, -9, 25, -21, 14, -15, 9, -2, -14, 15, 10, -44, + 37, 7, -36, 15, 18, -9, -21, 2, 45, -53, 3, 47, -48, 3, 25, -17, + 14, -24, -2, 53, -72, 22, 38, -32, -13, 22, -15, 30, -36, 6, 27, -30, + -4, 21, -3, -20, 8, 13, -3, -29, 43, -10, -41, 33, -14, 20, -22, 9, + 13, -14, -10, 25, -30, 14, 6, -29, 29, 2, -23, 4, 14, -15, -3, 13, + 11, -29, 21, -1, -25, 13, 5, 1, -9, -18, 58, -31, -44, 56, 7, -69, + 46, -10, 11, -3, -27, 41, 1, -58, 46, 7, -33, 14, -14, 30, -22, -24, + 77, -66, 6, 6, 27, -36, -2, 21, 10, -62, 57, 11, -46, 23, 7, -8, + -18, 24, -21, 17, -35, 40, -4, -31, 36, -13, -10, 0, -2, 2, 0, 2, + -14, 18, 22, -53, 11, 43, -45, -13, 39, -7, -12, -6, 22, -8, -27, 19, + 15, -35, 13, 21, -30, 26, -35, 40, -17, -11, -5, 33, -25, -4, -9, 32, + -10, -44, 65, -23, -18, 0, 28, -31, 17, -23, 45, -50, 11, 52, -68, 13, + 23, -10, -32, 41, -13, 4, -13, 5, 9, -11, 4, -8, 6, 12, -25, 4, + 24, -20, -15, 11, 30, -42, 5, 30, -7, -40, 27, 17, -27, -5, 14, 16, + -26, -9, 39, -23, -11, 17, -16, 30, -52, 43, -9, -4, -28, 31, 4, -15, + -15, 34, 6, -69, 65, -3, -40, 6, 42, -40, 8, 11, 18, -29, -28, 62, + -40, -17, 31, 2, -22, 20, -13, 16, -18, 0, -6, 12, -4, -10, 17, 0, + -6, -25, 44, -25, -6, 0, 24, -13, -33, 43, 1, -46, 36, 3, 0, -34, + 38, -11, -14, 5, -11, 30, -19, 3, -12, 45, -56, -3, 41, -20, -21, 17, + 22, -18, -15, 14, 37, -92, 53, 25, -48, -2, 57, -44, -4, 3, 35, -31, + -32, 59, -24, -17, 9, 28, -39, 22, -10, 9, -7, 0, 7, -29, 33, -16, + -17, 37, -24, -17, 43, -14, -28, 18, 18, -33, 5, 4, 21, -34, 13, 4, + -6, 7, -15, 14, -8, 11, -17, -1, 15, 0, -42, 58, -18, -35, 37, 14, + -47, 9, 27, -14, -33, 20, 58, -79, 11, 49, -18, -55, 58, -6, -29, 6, + 12, 16, -55, 61, -29, -20, 37, -15, -1, 9, -26, 22, 3, -25, 0, 31, + -18, -1, -12, 40, -11, -64, 62, -11, -23, 3, 32, -11, -18, 19, 5, -36, + 15, 11, -21, 6, 18, -16, 5, 16, -35, 14, -2, 19, -53, 45, 31, -81, + 31, 46, -51, -14, 44, -13, -23, -11, 67, -62, -3, 50, -23, -26, 24, 16, + -34, -2, 3, 27, -33, 1, 38, -35, 13, 0, -24, 50, -59, 11, 31, -20, + -6, 10, 20, -28, -15, 38, -2, -60, 43, 32, -68, 24, 47, -54, 9, 3, + 23, -46, 11, 36, -56, 34, -2, -20, 12, 24, -36, 9, 7, 18, -45, 11, + 45, -50, -10, 42, 4, -63, 62, -10, -22, -9, 26, 8, -52, 41, 14, -54, + 41, -9, -8, 12, -26, 33, -25, 6, 3, -14, 20, -28, -2, 50, -23, -51, + 64, 11, -86, 57, 17, -39, -5, 19, 41, -79, 33, 43, -64, 2, 40, -21, + -7, -6, 38, -37, -8, 43, -39, 5, 16, 3, -49, 67, -38, -20, 39, -20, + 10, -24, 43, -15, -47, 57, -13, -53, 59, -16, 8, -27, 35, -4, -36, 35, + -29, 13, -5, 5, -13, 32, -5, -48, 57, -29, -15, 30, -26, 23, -34, 33, + 25, -79, 54, 25, -70, 16, 33, -1, -60, 37, 52, -76, 7, 54, -22, -61, + 76, -23, -30, 30, -15, 14, -21, 24, -4, -20, 23, 0, -49, 63, -31, -12, + 28, -15, 9, -17, 26, -25, -1, 4, 15, -31, 22, 8, -23, 18, -8, -7, + 6, -1, 7, -12, -1, 32, -62, 42, 14, -59, 41, 13, -31, -5, 40, -14, + -49, 36, 38, -64, 1, 68, -54, -29, 61, -16, -29, 8, 37, -22, -33, 42, + 18, -75, 47, 6, -25, 26, -33, 42, -32, 1, 4, 3, -2, 5, -20, 27, + 4, -43, 33, 2, -27, 6, 26, -25, 8, 2, 19, -46, 26, 15, -56, 44, + 12, -34, -4, 43, -34, -1, 2, 27, -40, -3, 52, -64, 26, 21, -30, -3, + 30, 1, -37, 13, 27, -28, -31, 49, 4, -63, 61, 2, -23, -10, 22, 7, + -53, 17, 43, -51, 21, 15, -26, 37, -31, -4, 9, 0, -28, 28, 4, -10, + -5, 21, 2, -40, 32, 9, -50, 20, 43, -63, 32, -6, 13, -24, -4, 62, + -87, 46, 12, -27, -14, 25, 13, -44, 25, 24, -29, -8, 13, 18, -56, 46, + 6, -51, 55, -19, -10, -4, 17, 3, -52, 60, -3, -49, 41, -14, 0, -4, + -3, 17, -9, -9, 1, 18, -11, -17, 3, 17, -5, -23, 15, 42, -83, 51, + -1, -17, 6, -16, 57, -83, 48, 16, -46, 10, 24, -8, -32, 32, 15, -49, + 26, 19, -24, -22, 40, 20, -80, 64, -11, -24, 14, -11, 17, -18, 18, -5, + -21, 45, -36, -11, 24, -16, 5, -10, 32, -13, -17, 24, -15, -4, -8, 9, + 0, -16, 33, -36, 36, -7, -39, 46, -35, 33, -61, 51, 10, -63, 50, 11, + -34, -5, 39, -8, -46, 41, 6, -45, 22, 14, -4, -41, 74, -33, -44, 57, + -19, -20, -12, 42, -4, -37, 30, 18, -31, 0, -1, 10, -16, 3, 8, 1, + 9, -31, 21, -2, -11, -1, 3, 24, -40, 15, 31, -52, 20, -1, 13, -32, + 31, 6, -44, 41, -17, -18, 21, 18, -32, -10, 41, -2, -60, 42, 9, -25, + -9, 38, -10, -29, 40, -27, -7, 14, 8, -20, -2, 26, -11, -35, 42, -2, + -36, 28, -1, 3, -33, 39, -7, -24, 9, 4, 4, -10, 7, -2, 0, 15, + -52, 45, 4, -38, 14, 29, -20, -23, 39, -1, -38, 13, 23, -26, -1, 12, + 2, -30, 41, -10, -30, 36, -3, -22, -6, 35, -20, -32, 27, 22, -41, 19, + 23, -18, -18, 22, -5, -34, 39, -19, 5, -3, 29, -26, -21, 47, -38, -23, + 38, -4, -15, 6, 19, -12, -4, 6, -14, 17, -14, -11, 22, 3, -20, -13, + 38, -2, -52, 43, 16, -30, -19, 37, 1, -51, 47, 2, -23, -1, 22, -10, + -24, 17, 21, -62, 51, 11, -38, 19, 8, -3, -50, 61, -18, -15, 4, 16, + -9, -15, 29, -32, -2, 37, -43, 9, 35, -36, 13, -16, 28, -28, -5, 41, + -35, -3, 12, 15, -29, 2, 19, -20, 19, -21, 7, 18, -20, 1, -24, 47, + -17, -45, 54, 10, -43, 0, 37, -3, -63, 58, 4, -55, 43, -2, -6, -31, + 50, -35, -10, 37, -12, -17, 1, 29, -34, -5, 31, -19, -10, 29, -26, 32, + -44, 25, -5, -27, 43, -45, 33, 12, -29, -6, 38, -18, -34, 23, 18, -21, + -12, 17, 27, -52, 18, 32, -49, 42, -19, -24, 40, -26, -7, 0, 32, -12, + -44, 69, -18, -46, 21, 26, -41, -5, 49, -24, -8, 22, 0, -23, -17, 32, + -6, -42, 64, -40, 17, 0, 3, -11, -28, 63, -61, 13, 26, -12, -7, 4, + -5, 8, -2, -5, -14, 18, 13, -38, 6, 36, -7, -71, 86, -10, -56, 45, + -11, -2, -18, 9, 26, -38, 24, 1, -24, 41, -35, -10, 24, -1, -24, 10, + 25, -15, -20, 10, 36, -44, -32, 96, -69, -8, 44, -32, 12, -20, 33, -33, + 11, 24, -24, -15, 40, -23, -27, 20, 18, -19, -4, 28, -23, 9, -9, 4, + -19, 32, -27, -15, 59, -37, -17, 28, 2, -20, -12, 28, 20, -68, 46, 2, + -24, 3, 6, 16, -28, 17, 8, -21, 1, 6, -21, 15, 34, -68, 43, 41, + -81, 31, 10, -5, -28, 1, 51, -37, -21, 64, -40, -23, 44, -25, -12, 15, + 7, -21, 14, 0, 6, -29, 29, 7, -39, 30, -10, 0, -4, -5, 13, 8, + -24, 23, -28, 38, -27, -34, 50, -5, -33, 10, 55, -47, -22, 43, -3, -45, + 11, 38, -37, 15, 16, -25, 24, -22, -4, 0, 4, 14, -41, 33, 35, -67, + 13, 52, -57, 0, 25, -4, -7, -11, 18, 5, -37, 32, 2, -39, 54, -24, + -18, 13, 16, -27, -2, 7, 31, -52, 29, 17, -41, 38, -23, -15, 28, -4, + -28, 40, -13, -20, 8, 13, 0, -40, 37, 20, -53, 14, 39, -34, -21, 27, + 14, -28, 12, 14, -23, 7, 3, -28, 24, 6, -23, 10, 9, 20, -39, -12, + 61, -39, -44, 74, -24, -25, 21, 13, -31, 10, 11, -3, -21, 19, 7, -43, + 46, -26, -2, 22, -16, 0, 13, -16, 10, -9, -20, 33, -30, 29, -2, -29, + 44, -8, -62, 54, 13, -50, 8, 34, 7, -43, 9, 41, -34, -39, 54, -6, + -28, 9, 20, -16, -6, 25, -30, -6, 45, -51, 4, 36, -21, -22, 28, 4, + -25, 18, 6, -5, -33, 37, -9, -19, 14, 8, -5, -4, 5, -1, -13, 0, + 16, -46, 49, -5, -25, 30, -8, -16, 15, -17, -4, 24, -26, 14, -8, 16, + 3, -40, 16, 47, -78, 21, 65, -53, -20, 24, 26, -55, 6, 55, -47, -6, + 35, -4, -28, 14, 1, -19, 15, -9, 20, -22, 19, -6, -31, 32, 7, -36, + 14, 20, -18, -7, 9, 9, -27, 22, -15, 8, 9, -15, 2, -2, 9, -19, + 11, 5, 11, -38, 38, -4, -35, 23, 17, -48, 34, 15, -51, 41, -2, -11, + -30, 35, 20, -65, 33, 34, -37, -23, 48, -2, -48, 21, 19, -12, -34, 42, + 8, -49, 33, 10, -27, 25, -15, -6, 9, -11, 7, -14, 22, -7, -11, 18, + 4, -18, -12, 30, -40, 14, 16, -11, -2, 30, -36, 4, 20, -19, -25, 21, + 17, -39, 38, -11, 13, -32, 19, 13, -49, 41, -2, -25, 8, 24, -23, -16, + 41, -9, -44, 34, 28, -48, -15, 59, -22, -54, 64, -6, -10, -20, 29, 4, + -56, 42, 7, -31, 20, 0, -5, 9, -3, -27, 33, -15, -18, 25, 5, -21, + 10, -6, -4, 1, 5, 14, -42, 47, -10, -14, -15, 30, -6, -53, 64, -4, + -33, 13, 27, -34, -16, 37, -4, -42, 38, 11, -35, 11, 17, -10, -33, 55, + -35, -6, 14, 20, -35, -11, 63, -52, -17, 55, -22, -23, 19, -2, 0, -5, + -10, 21, -5, -14, 12, 1, -10, 6, -15, 11, 13, -37, 43, -14, -17, 11, + 10, -13, -28, 43, -15, -25, 35, 11, -45, 20, 25, -34, -21, 51, -16, -42, + 35, 18, -23, -32, 75, -47, -18, 34, -1, -28, 1, 34, -40, 16, 23, -26, + 4, 18, -22, -4, -7, 18, -8, -25, 41, 0, -24, 13, 9, -30, 14, -4, + -14, 30, -18, 5, 9, -12, -3, -8, 25, -22, -18, 50, -18, -43, 48, 0, + -39, 11, 27, -14, -26, 42, -10, -33, 4, 61, -72, 7, 58, -40, -22, 28, + 24, -62, 19, 31, -22, -23, 41, -13, -16, 5, 11, -13, -4, 23, -21, 4, + 7, -8, -20, 33, -19, -10, 26, -7, -13, 2, 18, -21, -10, 28, -20, -15, + 54, -36, -26, 56, -30, -32, 42, -5, -21, 1, 40, -26, -19, 29, 7, -59, + 34, 24, -43, 20, 3, 12, -36, 23, 23, -48, -1, 61, -49, -25, 62, -27, + -23, 19, 13, -17, 4, 0, 9, -29, 19, -5, -7, 13, -9, 17, -7, 0, + -14, 11, -5, -17, 2, 35, -29, -10, 45, -27, -21, 31, -9, -17, 12, 5, + -10, -12, 26, 0, -37, 34, 6, -36, 18, 8, -2, -42, 39, 16, -47, 25, + 37, -57, 1, 51, -59, 13, 19, -10, -10, 11, 11, -8, -32, 42, -19, -36, + 59, -26, 1, -7, 17, -14, -2, -1, -2, 5, -5, 4, 0, 15, -25, -3, + 30, -28, -15, 36, -13, -5, -13, 26, 2, -45, 41, 2, -38, 21, 20, -29, + -11, 46, -27, -35, 46, 3, -38, 20, 25, -48, 19, 18, -26, 5, 3, 10, + -17, -13, 46, -29, -27, 52, -40, 18, -6, 9, -14, -8, 21, -11, -11, 16, + 14, -42, 33, 5, -31, 14, 0, -14, 19, -9, 11, -5, 2, 2, -39, 58, + -35, -26, 47, -1, -40, 19, 32, -36, -14, 37, -2, -40, 18, 32, -47, -6, + 49, -34, -7, 36, -16, -15, 2, 22, -36, -5, 53, -56, 27, 6, 2, -13, + -8, 28, -40, 4, 22, -2, -33, 46, -14, -36, 51, -10, -47, 40, -2, -18, + 3, 11, 13, -50, 57, -33, -5, 30, -31, -4, 19, -3, -17, 20, -2, -8, + -16, 34, -6, -45, 30, 35, -73, 21, 55, -52, 3, 11, 19, -42, -2, 55, + -57, 13, 23, -11, -16, 12, 16, -45, 25, 9, -22, -2, 37, -23, -29, 49, + -24, -27, 46, -23, -8, 22, -14, 6, -26, 45, -42, -9, 41, -15, -12, 11, + 13, -25, -1, 10, 9, -42, 37, -2, -20, 17, 14, -41, 25, 17, -52, 45, + -14, 1, -23, 21, 30, -74, 44, 35, -53, -4, 42, -18, -36, 30, 9, -26, + 17, 15, -18, -12, 37, -32, -25, 48, -27, -6, 20, -8, 12, -32, 38, -22, + -17, 36, -18, -13, 15, 7, -22, 14, -3, 5, -21, 33, -18, -18, 17, 12, + -31, 10, 34, -51, 33, -12, 15, -23, 1, 19, -50, 51, -7, -41, 47, 11, + -56, 20, 30, -23, -34, 37, 17, -29, -14, 54, -25, -45, 50, -16, -17, 11, + 14, -2, -30, 44, -16, -32, 39, -18, -16, 26, -5, -22, 25, -7, 1, -18, + 27, -8, -21, 23, 0, -30, 16, 27, -54, 46, -1, -24, -9, 28, 8, -62, + 48, 6, -31, 13, 17, -25, 17, -16, -1, 9, 2, 0, -15, 12, 19, -42, + -2, 57, -56, -2, 47, -11, -40, 21, 38, -56, -22, 71, -26, -41, 52, 3, + -29, 14, -1, -7, -20, 29, -3, -34, 41, -1, -35, 26, 12, -38, 25, -6, + -4, 7, -9, 6, -14, 31, -24, -7, 24, 3, -47, 33, 9, -28, -7, 23, + 18, -44, 22, 29, -48, 1, 46, -52, 14, 21, -21, -9, 26, 3, -41, 20, + 34, -52, -14, 75, -39, -40, 53, 0, -35, 6, 29, -15, -36, 44, 0, -39, + 36, -15, -11, 25, -9, -8, 6, 0, 1, -30, 29, -1, -17, 12, 20, -34, + 17, 4, -35, 29, -4, -10, -8, 35, 0, -45, 34, 18, -77, 45, 22, -29, + -9, 24, 14, -50, 29, 15, -34, -1, 47, -52, 3, 58, -54, -12, 40, -7, + -28, 10, 33, -22, -50, 79, -24, -38, 25, 10, -5, -30, 27, 16, -42, 15, + 14, -19, 11, 6, -33, 35, 2, -46, 49, -20, -7, 13, -4, 0, -12, 14, + 3, -50, 58, -8, -44, 40, 17, -22, -41, 60, -13, -48, 25, 50, -62, -3, + 71, -55, -12, 23, 3, -20, -1, 13, 20, -50, 48, -27, -23, 57, -43, -5, + 8, 30, -34, -16, 51, -18, -42, 35, 19, -40, 23, 0, -35, 39, -23, 0, + 21, -24, 16, -6, 2, 14, -53, 43, 1, -46, 51, -2, -19, 3, 25, -32, + -11, 24, -1, -34, 25, 42, -74, 29, 42, -41, -34, 56, -3, -32, -26, 84, + -35, -72, 101, -39, -13, 5, 24, -31, -2, 21, -25, 2, 22, 0, -37, 43, + 2, -41, 23, -6, -9, 9, -7, 24, -19, -8, 24, -33, 31, -11, -37, 57, + -25, -22, 35, -2, -29, 2, 26, -1, -39, 20, 51, -72, 14, 45, -45, -17, + 49, -30, -12, 24, 25, -48, -23, 107, -96, -10, 61, -7, -47, 22, 34, -35, + -13, 21, 17, -55, 40, 12, -43, 23, 6, -21, 19, -10, -4, 10, 3, -2, + -35, 38, -7, -29, 31, 1, -15, 15, -11, 5, -8, -3, 10, -30, 40, 10, + -62, 43, 30, -80, 22, 59, -63, -6, 42, 4, -35, -2, 67, -87, 21, 44, + -44, -6, 34, -6, -39, 26, 28, -26, -47, 87, -25, -74, 69, 15, -63, 22, + 19, 3, -13, -14, 36, -30, 1, 5, -9, 9, 3, -14, 29, -9, -25, 14, + 6, -6, -38, 54, -12, -38, 46, 14, -70, 48, 19, -68, 37, 25, -27, -25, + 29, 39, -81, 27, 50, -53, -12, 44, -4, -46, 23, 27, -32, -24, 67, -34, + -36, 65, -33, -31, 52, -22, -23, 21, 8, 18, -61, 46, 14, -59, 26, 31, + -49, 24, 11, -27, 30, -29, 8, -7, 20, -20, -4, 11, 0, -1, 0, -1, + 0, -1, 1, -2, 2, -1, -4, -2, 1, 19, -2, -20, 3, -10, -11, 12, + 3, -10, -3, 25, -4, 1, 6, 4, -12, 10, 2, -4, -28, -11, 9, 2, + 1, 18, -9, -20, 12, 11, 10, 1, -5, 5, -15, 4, 7, -27, -3, 4, + -8, 38, -31, -15, 7, 13, -34, 37, -6, -19, -6, 20, 41, -31, -20, 28, + -13, 30, -4, 0, -23, -1, 0, -13, 21, 3, -32, 19, 30, -52, 18, -24, + -27, 31, -14, 4, 1, -16, 14, 12, -20, 32, 14, -41, 37, -6, -5, 1, + 27, -34, 42, 9, 2, -34, 20, -25, 11, 15, -10, -14, -19, -24, 5, -12, + 3, -17, 2, 46, -13, -15, 31, -23, -16, 21, 25, -6, -36, 10, 1, 26, + -18, -12, 1, 21, -8, 17, -16, -29, -39, 17, -5, -1, -4, -6, -18, 33, + -21, 24, -17, 31, 0, 4, 0, 6, -26, 18, 24, 46, 5, 19, -10, 11, + 25, -13, 10, 50, -50, -52, 21, -23, -29, -8, 34, -35, -39, 15, -16, -43, + -5, -29, 29, -1, -8, -30, 18, 5, -14, 52, 12, -4, -28, 19, 25, 25, + 16, -44, 53, -20, 49, -23, 25, -32, 1, -63, 50, 37, -52, -13, 13, 4, + -18, 22, -56, 7, 23, -46, -7, 39, -69, -15, 26, 28, 21, 9, -64, 55, + 23, -34, 46, -26, -9, 36, -31, 4, 5, 37, -58, 28, 49, -25, 20, -1, + -12, -25, -6, 12, 9, -23, -34, 0, -2, 14, 3, -4, -13, 25, 23, -11, + 1, -34, 6, 9, 30, -36, -19, 11, -16, 14, 76, -97, 33, 25, -50, 8, + 25, -35, 20, -20, 4, -27, 63, -73, 25, 35, -22, 7, -33, 13, 2, 6, + -3, 5, 1, 17, 1, -36, 40, -4, 10, -28, -9, 14, -16, 5, 20, -32, + -45, 59, -10, 26, -29, -10, -13, -32, 44, -74, 81, -51, -12, 66, -11, -33, + 17, 38, 12, 57, -39, 5, 39, 9, -4, 4, 0, 25, -50, 24, -19, -1, + -30, -21, 24, -46, -20, -35, 19, -10, 1, -45, -7, 29, -8, -70, 51, -4, + -51, 42, 20, 21, 21, -24, 7, 69, 1, 17, 10, 9, 8, 16, -8, 66, + -32, -13, -24, 30, 50, -86, -15, 34, -23, -56, -26, 7, 22, -45, 23, -41, + 50, -84, -19, 50, 0, 2, -20, -31, 49, -12, -8, 12, 63, -20, -23, 57, + -37, 85, -57, -29, 83, -11, -15, -29, 25, -44, 33, -51, 74, -56, 63, -99, + 72, 15, -40, -41, -29, 68, -66, 46, 12, 21, -65, 5, 62, -24, -24, -15, + 7, -25, 7, -4, -16, 47, 13, -38, 3, 55, -31, -40, 31, -1, -35, 22, + 4, 34, -6, -1, -12, 6, 75, -51, 12, 57, -19, -24, -5, 12, -10, 26, + -13, 10, -44, 25, -13, -26, 39, -42, -25, -65, 36, -55, -41, -12, 2, 8, + 22, 22, -24, -27, 51, -38, 36, 1, -14, -8, 88, 2, 15, 28, 6, 46, + 8, 32, -22, 37, -29, 10, 3, -36, 9, -9, 2, 6, -15, -79, 32, -15, + -26, -4, -29, -28, 7, 16, -29, -27, 3, 8, 2, 9, 5, 1, -13, 38, + 16, 26, -16, 0, 19, -14, 20, -29, -3, 43, 17, -14, 39, -34, -15, 24, + 36, -27, -1, 7, -55, 24, 50, -43, 21, 5, -5, -122, 78, -43, -33, 12, + -12, 9, -45, -3, -1, -22, 37, -3, 17, -35, -11, 32, 5, 62, 0, -4, + 20, 18, -33, 93, 2, -77, 45, 33, -29, -35, 45, -55, 48, -12, 15, -54, + 16, -3, -50, 1, -21, -39, 16, -1, -33, -38, 19, -45, 9, 34, 26, -15, + 21, 60, -32, 7, -2, 24, 21, 28, -19, -12, 7, 60, 23, -23, 7, -44, + -54, 54, -17, -42, 38, -24, -23, 18, 9, -31, 4, 24, -26, -27, 33, -53, + 15, 26, -38, 11, 13, -39, 24, 32, 19, 14, 16, -27, -24, 14, 14, 9, + 6, -48, -8, -8, 60, -39, 1, -32, 51, -34, 0, 33, -16, -33, -10, 60, + -40, -1, 3, 31, 50, -16, -32, -40, 45, -34, -8, 54, -80, 0, 19, 21, + -21, 87, -70, -19, 23, 25, -56, 40, -33, 19, -44, -8, 7, -12, 18, -20, + 22, -10, 18, 5, -7, 26, 33, -65, 49, -9, -9, 27, 22, 22, -37, 18, + -19, -1, 61, -23, -39, 4, 4, -32, -3, 27, -39, -3, 38, -19, -12, -8, + -37, 3, -10, -14, -37, 0, 4, 24, 1, 33, -35, 29, -2, 24, 24, -21, + 23, -3, -31, 47, 12, -26, 35, -19, -17, 22, 20, -27, 1, -16, -18, 17, + -2, -19, -22, 25, -2, -11, -3, -60, -2, 30, 64, -76, -7, -29, 45, 1, + 46, -23, -43, 2, 43, 68, -38, -8, 45, -7, -8, 15, -47, -27, 71, -12, + -3, -17, -54, -29, 75, -51, 8, -27, 12, -18, 60, -29, -42, 22, 51, -32, + -27, 28, -11, 48, -34, 30, 26, -19, 20, 14, -16, 2, 7, -36, 70, -14, + -21, -39, 82, -50, -49, 33, -28, 9, -17, -15, -51, 5, 7, -17, 58, -29, + -33, 2, 29, 14, -46, 3, 28, 2, 28, -22, 7, -3, 28, 2, 40, -71, + 2, 23, 24, 19, 11, -62, 56, 1, -24, -7, -10, -26, 30, -49, 18, -40, + 52, -51, 46, -3, -28, -26, 40, 11, -5, 8, -46, 25, -10, 34, -25, 44, + -17, -7, 12, 12, -28, -19, 30, -26, 6, -38, 13, 45, -43, 24, 24, -49, + -13, 19, 3, 27, -5, -8, 5, -6, -4, 39, 7, 1, -38, 22, 20, -20, + 19, -24, -50, 47, -11, -25, 32, -59, 17, 12, 35, -50, -14, -7, 15, 33, + -15, 11, -45, 10, 14, 50, -68, -4, 11, -35, 20, 88, -72, 40, 16, -9, + 3, 55, -44, 25, -24, 6, 14, -66, 9, 7, -10, 9, -7, 1, -42, -24, + -26, 74, -5, -23, -44, 12, 11, 12, 57, -60, -19, 7, -2, 40, 3, -26, + -14, 44, 29, 7, -23, 21, -32, 42, 13, -30, -16, 36, -9, 3, -21, 17, + -67, 30, -4, 23, -19, 8, -32, 5, 31, -4, -26, 18, -24, 6, 39, -7, + -24, -2, -5, 6, -3, 11, -10, -6, 16, -15, -15, 5, -19, -17, 38, -27, + 35, -48, 7, -20, 4, 12, 1, -33, 28, -24, -2, 28, -10, -11, 23, -2, + 5, 21, -5, 8, 0, 21, 12, -24, 36, -40, 36, 29, -2, -19, 1, 3, + -8, 9, -11, -13, -31, 26, -5, 23, -26, -30, 1, 30, -19, -2, -15, 3, + 5, 5, -3, 3, -43, 38, 16, -30, 18, 12, -1, -4, 20, -47, 11, 1, + 21, -15, 1, 0, -43, -5, 37, -28, 11, -51, 21, 2, 20, -24, 22, -46, + 34, -1, 7, 27, -12, -24, 28, 39, -4, 10, -19, 8, 6, 37, -26, 2, + -12, -32, 36, 17, -11, -14, -26, -1, 17, 17, -53, -10, -11, 23, -16, -26, + 10, -33, 1, 61, -5, -21, -14, -28, 50, 13, -41, 17, -12, 38, -19, 24, + 36, -75, 16, 1, 58, -15, -19, -33, 56, -40, 39, -18, 1, 0, -34, 11, + 32, -6, -52, 32, 2, 39, -31, -23, 0, -11, 10, -26, 55, -6, -51, 0, + 36, -33, -14, -9, 30, -11, -5, 14, -17, 6, -34, 28, 16, -3, -21, 7, + 25, 13, -30, 14, 12, 33, 3, -16, 9, -12, -17, 15, 2, 23, 14, -46, + 1, 13, -4, -19, 6, 30, -53, -13, 1, -17, 13, -38, 11, 20, 1, -24, + 19, -10, 7, -28, 48, 25, -59, -33, 51, 12, -4, -3, 13, -23, 64, 0, + -5, -24, -6, 21, -27, 28, -19, -29, 51, -24, -9, -12, 3, -3, 35, 6, + -33, -37, -5, 45, -47, 30, -16, -9, -10, 51, -31, 32, 10, -22, -10, 8, + -13, -28, 8, 15, -25, 39, -36, 2, 50, -30, 36, -40, -14, 35, -9, -3, + 12, -25, 36, -7, -20, -6, 48, -5, 31, -4, -18, -48, 67, -47, 26, -30, + 6, 9, -14, -29, 3, 23, -12, -27, 29, -22, -36, -9, 51, -30, -18, -16, + 47, -4, -25, 18, 16, 13, -11, 15, 10, 2, -36, 42, 3, -9, -21, 52, + -19, 18, -34, -3, -11, 23, 19, -13, -17, -19, 16, -1, 0, -32, -1, -4, + 25, 9, -37, -3, -9, 45, -15, -29, 36, 4, -29, -9, 35, 16, -36, -21, + 25, -12, 10, -21, 25, 5, -17, -8, 12, 35, -56, 4, -15, 47, -32, -5, + 18, 3, 11, 2, 7, 1, 1, -24, 23, 6, 7, -46, -37, 73, 12, -2, + -20, 34, -45, 32, -23, 15, -40, -34, 12, 4, 13, -39, 3, 23, 17, -24, + -15, 16, 19, -30, -9, 12, 53, -64, 1, 23, 40, -11, 8, 33, -36, 42, + -68, 71, -16, -10, -41, 22, 16, -19, -18, 26, -2, 1, 4, -21, -3, -16, + -4, 16, -31, 1, -26, -5, -8, 43, -69, 28, 14, 10, -16, 21, -18, -2, + -14, 0, 32, 23, -28, -21, 68, 0, -40, 24, 32, 1, -10, 8, -20, 32, + -37, 16, -3, 24, -10, -5, -30, 35, -39, 12, 6, -26, -2, -58, 65, -66, + 13, -10, -6, -15, 28, -27, -39, 51, -28, 16, -10, 60, -51, 30, 51, -24, + 11, -9, -7, 14, 39, -33, 4, -14, 25, -13, -8, 35, -40, -1, 27, -9, + 11, -9, -13, 5, 19, -37, -12, 23, 1, -2, -31, 37, -7, -41, 35, 16, + -6, -28, -8, 9, -23, 22, -8, 27, -17, -27, -10, 10, 12, -6, 11, -51, + 21, -19, -29, 23, -10, -4, 32, 3, 25, 7, -25, 23, 35, -21, -2, -3, + 23, -4, 14, 6, -8, -5, -6, 10, 10, 5, -38, -7, 16, -38, -2, 12, + 8, -54, 5, 18, -12, -18, 23, 17, -52, 50, -78, 11, 4, 5, 19, 7, + 27, -24, 5, 3, 35, -20, 34, -15, -10, 4, 21, 16, -14, 12, -8, -2, + 42, -30, -22, 28, -9, -34, -11, 23, -36, 0, 15, -10, 14, -37, -7, -19, + 30, -18, 15, -17, -14, -14, 51, -20, -8, 13, -12, 7, 35, 9, -12, -13, + 48, 1, -2, -32, 13, -5, 1, 15, 40, -66, 18, 1, 49, -45, -38, -8, + 14, -16, -2, 24, -13, -62, 15, 54, -28, -18, -3, 10, 13, -21, -18, -9, + 44, -13, 8, 37, 6, -18, 4, 27, -18, 21, 3, -8, 13, 27, -19, 14, + 2, -27, -11, -8, 17, -38, -26, 29, -31, 5, -7, -5, -9, -4, -11, 9, + -3, -5, -18, 16, 3, 0, -8, -2, -6, -1, 58, -11, 12, 2, 31, -21, + 13, 27, -17, -23, 54, 18, -33, -7, -7, 3, -2, -25, 15, -1, -25, -41, + -13, 46, -71, -15, 40, 10, -14, 0, -10, 18, 0, -31, 25, -8, -10, -13, + 24, 30, -9, 6, 4, 26, -3, 5, 31, -25, 0, -7, 16, 20, -1, -12, + -22, 11, -10, -3, -26, 12, 3, 2, -17, -31, 4, -26, 15, 13, 6, -22, + -5, 5, 8, 11, -23, 17, 17, -33, 0, 12, 21, -20, -3, 20, 21, -7, + -20, 38, 20, -27, -16, 3, 7, -8, -3, 0, 22, -38, -37, 26, 23, -26, + -8, -5, 0, -12, -2, 30, -8, -4, -2, -13, 15, -24, -4, 29, 10, 32, + -7, -57, 48, -13, 41, -13, 16, -20, -20, 33, -13, 26, -17, -18, 20, 10, + -44, 18, 2, -18, 3, -13, -5, -25, -16, 7, 30, -32, 8, -34, 19, -5, + 23, -28, 12, -4, -14, 30, 1, -2, 15, -20, -16, 44, -2, 34, -31, 36, + -25, 15, -3, 13, -10, -36, 39, -5, 0, -16, 1, 27, -28, 24, -26, -8, + -12, -16, 25, -2, -12, -28, 16, -17, 7, -24, 31, -15, -8, 31, -22, -7, + 0, 14, 16, -17, 8, -15, 24, -3, 17, -14, 6, -4, -22, 22, 9, 1, + 3, -21, 18, -8, 11, 0, 10, -3, -12, 3, 15, -15, 1, 2, -13, 3, + -23, -3, 15, -11, -5, 9, -30, -6, -10, 27, -2, -9, -12, 10, 4, 0, + -16, 16, -10, -27, 51, -5, -4, -1, -4, 5, 38, -18, -11, 17, 1, -2, + 8, 0, -7, 6, -6, -4, 9, -12, -11, 11, 1, -14, 1, -31, 13, 3, + -28, 12, 24, -30, 7, -6, 5, -4, -6, 8, 1, 14, -19, -1, 32, -22, + -9, 34, 6, -9, -9, -5, 15, 6, -25, 14, 6, -41, 0, 10, 2, 12, + -18, 6, 5, -1, -16, 4, 26, -33, 5, 4, -4, -9, 5, -2, 14, -10, + -11, 16, -6, 11, -5, -15, 14, 18, -19, 21, -24, 13, 6, -13, 21, -12, + -11, -2, 10, -6, -7, -13, 12, -13, 1, 10, -7, 2, -2, -21, 24, 5, + 2, 5, -24, 17, -17, -15, 9, 20, -12, -9, -15, 14, -1, -2, 14, -13, + 5, -32, 21, 10, 7, -11, 24, -1, -23, 24, -25, 31, 7, -16, -2, -4, + 9, -19, 17, 4, -27, 22, 21, -28, -6, 32, -48, 6, -4, 20, -6, -41, + 11, 31, -16, -14, 2, -8, -13, -13, 35, -15, 15, -20, 1, 26, 7, -13, + 18, 5, -19, 11, -7, 20, 22, -35, -11, 20, -24, 21, -20, 34, -15, -17, + -8, -2, 16, -9, -12, 2, 20, -31, 24, -21, 2, 12, -27, 28, -10, -5, + 24, 7, -29, 4, 6, -24, 33, -4, -8, -16, 1, 32, -28, 13, 7, 2, + -10, -38, 30, 2, -18, -2, 17, 13, -6, -46, -1, 61, -48, 18, 10, 2, + -17, -13, 8, 27, -8, 0, 11, -5, 20, -39, 4, 19, -8, -13, -15, 29, + -36, 29, -16, 14, -25, 17, -14, -15, 18, 5, 3, -5, -2, -19, 31, -12, + 14, -23, 31, -24, -4, 0, 4, 2, 11, -15, 22, -27, -4, 9, -8, 22, + -2, 7, -33, -12, -3, 30, -3, -10, 12, -19, 2, -9, 16, -4, -15, 5, + 32, -13, -13, 22, -11, 1, 3, 18, -12, 3, -17, 16, 15, -36, -2, 10, + -12, 9, -29, 14, 12, -23, 5, 39, -20, -39, 13, 14, -13, 2, -16, 43, + -25, -1, -12, 19, 11, -27, 0, 28, 3, -3, -15, -1, 10, -31, 43, -6, + 5, -10, 4, -18, 24, -6, -14, -8, -5, 4, 1, -5, -20, 21, 5, -19, + 22, -8, -13, -3, 20, -10, 20, -12, -7, 11, -11, -15, 6, 3, 24, -9, + -4, -3, -4, -20, 44, -12, -15, 4, -3, -6, 2, 9, 3, -17, -7, 9, + -2, 2, -22, 18, -8, -2, -10, 4, 6, -1, -4, 9, -1, 6, -9, 8, + 2, 4, 4, -6, 17, -32, 11, -1, 21, -7, -29, 12, 2, -35, 28, 12, + -15, 15, -43, 37, -30, -4, 2, 27, 8, -22, -1, -13, 20, -28, 36, -6, + -12, -4, -8, 14, 2, -12, 5, 12, -3, -11, 3, -1, 2, 18, 12, -11, + 4, -31, 13, 10, -10, 12, 7, -35, 10, -17, -3, 12, -5, 2, 0, -23, + 7, 5, -4, 23, -30, 2, 4, -3, 18, -16, 17, 16, -12, -3, -14, 17, + -1, -5, 9, 19, -23, 11, -8, -19, 34, -7, -13, 1, 3, 19, -23, -15, + 19, -17, 5, -24, 16, 4, -5, -7, 7, -2, -20, 4, 15, 21, -29, -7, + 16, -3, -17, 9, 3, 15, -15, -5, 12, -14, 8, 21, -15, 12, -18, -1, + 17, -19, 2, 16, 16, -11, -30, 22, -12, -12, -1, 21, -28, 29, -30, -6, + 19, -14, -5, 0, 10, 18, -8, -15, -1, 7, -15, 28, -3, -3, -9, -8, + 0, 6, 18, -32, 7, -3, -11, 6, 30, -42, 32, -13, -8, 5, 8, 8, + -15, 3, 4, -22, 27, -6, 6, -11, 1, -6, 13, -5, 2, -12, 29, -30, + 10, -15, 18, -19, 8, 21, 1, -28, 15, -20, 25, -25, -1, 11, -2, 1, + -22, -3, 15, 1, -22, 18, 16, -24, 1, 19, 6, 9, -7, -22, 8, -6, + 2, 14, -9, -4, -13, 10, -12, 13, 0, -11, -12, -2, -6, 20, -9, 4, + 5, -14, 3, 9, -2, 13, -5, 0, 14, -17, -1, -3, 8, -6, 7, 29, + -19, -13, 3, 27, -17, -8, 11, -2, -14, -9, 7, -3, -9, -14, 24, -12, + -35, -13, 40, -10, 1, -7, 1, 2, -1, 1, 16, 3, -13, -11, 30, 2, + -9, 0, -9, 2, 15, -9, 8, 3, -19, 12, 5, -21, 5, -6, 16, -4, + 7, -4, -2, 9, -35, 27, -6, 0, -12, 15, -29, 8, 2, -7, 4, 1, + -15, 28, -15, -13, 18, 4, -1, 1, -4, -7, -16, 21, -11, 25, -19, 2, + -10, 20, -32, 11, 6, 6, -15, 22, 8, -25, -13, 5, 20, 13, 7, -23, + -6, 7, -4, 4, 0, -7, 3, -10, -4, 9, 1, 3, -8, 2, 16, -22, + -7, -3, 12, -4, -4, 8, -10, 6, -13, -5, 3, 3, 6, 4, 4, -9, + -27, 1, 16, 17, -15, 0, -12, 15, -2, -6, 10, 3, -16, -16, 22, 13, + -12, 4, -4, 7, 11, -12, -14, 15, -1, 3, -12, 7, -7, 12, -14, 9, + -9, 2, 2, 9, -12, -17, 12, -17, 14, -2, -18, 2, 16, -5, 1, 8, + -5, -12, 0, -3, 21, -2, -17, 10, 10, -4, -16, 6, 15, -1, -25, -11, + 18, 0, -11, 8, 15, -16, -18, -4, 39, 3, -30, -6, 22, 2, -22, 2, + 21, -9, -9, 12, -3, 19, -24, -12, 20, -8, 4, 3, -3, 15, -20, -3, + 14, -7, -4, -14, 9, -8, 0, 7, -6, -8, -4, -3, 4, 13, -18, 0, + 9, -2, 5, -4, 10, 3, -9, -6, 9, -3, 1, 4, -3, 4, -11, 2, + -3, 5, 11, -13, -1, 4, -7, 1, -11, 1, 17, -17, 2, 13, 1, -21, + -2, 7, -5, -4, -5, 16, -5, -7, 4, 8, 8, -14, 4, 8, -7, -1, + 5, 2, -11, -9, 9, 6, -10, -2, 6, -7, -2, -1, 15, -17, -4, 5, + -2, 2, -3, -5, 11, -3, 1, 16, -12, -3, -7, 6, 5, -4, 5, 0, + -3, -15, 5, 3, -8, 9, 3, -8, 1, -6, -4, 0, -7, 21, -18, 9, + -8, 11, -2, -10, 10, 1, 14, -19, -11, -7, 18, -7, 4, 6, 2, -15, + 2, 4, 5, -3, 0, 0, 12, -2, -15, -4, 18, -7, -9, 18, -7, -6, + -9, 4, 7, -21, 11, -18, 14, -5, -4, 8, 5, 4, -3, -4, -11, 11, + -15, 19, 2, -18, 8, -4, -13, 18, 3, -14, -3, 9, -11, 2, 10, -9, + -5, -1, -15, 13, 16, -9, -4, 29, -15, -14, 6, 9, -1, -15, 12, 12, + -6, -6, 13, -10, 18, -14, 7, -12, 5, -9, -12, 16, -6, -16, 7, -1, + -22, 8, 2, -1, 9, 4, -31, -9, 12, 14, -9, -5, 17, -25, 7, 0, + 13, 4, -1, -17, 10, 13, -7, -11, 17, 2, -23, 27, 5, -10, -3, 13, + 5, -5, -5, -4, 0, -3, -5, 3, 4, -9, -7, 5, 4, -13, -10, 1, + 7, -4, -2, -3, -5, 15, -9, 0, 1, 12, -17, -6, 32, -15, -16, -11, + 20, 0, 2, -11, -5, 25, -21, 3, 10, 15, -24, -4, 8, -5, 0, 15, + -1, -7, 1, -18, 21, -7, 3, -12, 0, 12, -10, 6, -3, -2, 2, -1, + 9, 1, -9, 7, -9, -4, 9, -16, -4, 8, -10, 4, -3, -2, 13, -9, + 4, -16, 4, -3, -5, 14, 7, -8, 2, 9, 0, -2, -12, 7, -3, 2, + -4, -15, 11, -8, -11, -4, 23, -5, -1, 4, -9, 7, -4, 7, 8, -13, + -6, -4, 16, 10, -11, 8, -1, -1, 2, -5, 0, -3, -6, 2, 3, -6, + 13, -19, -9, 19, -11, 6, -12, 12, -10, -3, -11, -10, 14, 2, -19, 14, + 4, -6, 4, 11, -7, 3, -3, -8, 24, -18, 6, -8, 15, -14, -7, 19, + 0, -11, -3, 2, 2, 0, 2, 6, -7, -22, 16, 0, 11, -12, 7, -12, + 10, -16, 4, 8, -11, -11, 4, 16, -19, 13, 1, -19, 12, 19, -15, -4, + 9, -8, -13, 5, 14, -12, 5, -21, 7, 4, 11, -19, -1, 15, -16, -3, + -12, 14, 1, 1, 15, -6, -13, 7, 0, 6, 4, -11, -3, 10, 14, -20, + 7, 3, 1, 5, 17, -17, -5, 3, -4, 6, -1, 3, -18, 10, -10, 0, + 0, 14, -18, -19, 17, -23, -5, -1, 4, -4, -2, 1, -13, 26, -15, 2, + -10, 3, 13, 0, -6, 3, -4, 3, 0, -2, 9, 2, 9, -14, 23, -4, + -10, 15, 7, -16, 0, 9, 3, 0, 14, -12, 0, 4, -10, 1, -11, -13, + -6, 15, -14, -7, 2, -20, 4, -7, 9, -3, 2, -14, -1, 1, -1, 9, + -18, 10, -1, 1, -3, 22, 1, -1, 5, -4, 10, 2, 5, 0, 3, -2, + -1, 5, -2, -3, -5, 10, 2, -16, 2, 3, -1, -1, -11, 7, 6, 0, + -10, 10, -7, -2, -15, 15, 4, -25, 0, 4, 4, -12, 0, 5, -7, -6, + 6, 6, -8, 1, -1, -7, 17, -9, 2, 8, 4, -6, -6, 19, -5, -11, + 12, -12, 3, 3, -5, 9, 11, -26, 0, 0, 7, 5, -8, 11, -5, -6, + -16, 7, 12, -10, 0, -6, 7, -8, 3, -4, 11, -9, -16, 13, 18, -18, + 2, -5, 7, 5, 0, -1, 4, -9, -13, 18, 5, -4, -14, 1, 7, -5, + 4, -9, 15, 3, -10, -4, 5, 3, -11, -17, 18, 4, -9, -3, 3, -5, + -11, -3, 0, 7, -1, -8, -2, 6, -7, 7, -3, 6, 3, -12, 15, -5, + 23, -12, 8, -12, -4, 10, 1, 4, -3, 0, 0, 8, 0, 1, 11, -27, + -9, 9, -4, -3, 12, -19, -2, -8, -6, 1, -1, 2, -12, 5, -11, 3, + -1, -1, -10, 18, 0, 3, 2, 4, -5, 11, -3, 9, -2, -5, 7, -6, + 8, 10, 2, -1, -8, 1, -16, 2, 9, 1, -4, 0, -15, -5, 6, -14, + -9, 14, -22, 3, 7, -1, -2, -2, 0, 1, -2, 1, 9, 0, 7, -1, + 6, 4, 0, -6, -2, 2, 4, -9, 11, 1, -25, 9, -6, 5, 0, -7, + -8, 3, 5, 1, -2, 3, -9, -5, 7, 14, -12, 3, -10, 10, 3, -16, + -3, 26, -8, -9, -2, 15, 0, -21, 8, 11, -17, 3, 8, -8, 10, -19, + -3, 8, -4, 6, -10, 3, 4, -6, -4, 6, 0, 4, -19, 9, 3, -7, + 17, -7, 2, 3, -27, 12, 5, -14, 5, -6, -6, 6, 11, -11, 6, -12, + -2, 9, 8, 1, -18, 18, -9, 0, 13, -8, -10, 24, -11, 4, 13, -4, + -18, -3, 2, 9, -7, -1, 4, -6, 0, -11, 5, -1, -1, -8, -10, -6, + 6, -15, 20, 6, -25, 11, -5, -7, 12, 4, 0, -6, 6, 2, -1, 5, + 1, -11, 9, 20, -11, 14, -6, -15, 11, -11, 7, 1, -5, 2, -8, -2, + 12, -5, -16, 8, -4, -10, 2, 2, -6, -8, 5, 0, 3, 4, -17, 13, + 4, -9, 1, 5, 4, 8, -7, -3, 3, -2, 4, 14, -9, -6, -7, -3, + 11, -17, 0, 9, -10, 0, 1, 0, -9, -7, 8, 7, -3, 15, -22, 2, + 7, 0, 2, 4, -2, -6, -3, -1, 9, 2, -2, 1, -4, -1, -6, 2, + 4, -8, 3, -2, 1, 0, -9, 14, -6, -5, 3, -1, -6, 5, -5, -6, + 5, -5, -1, 12, -10, -6, -3, 9, -7, -8, 14, -5, -11, 9, -1, 5, + -5, 3, 1, 0, 1, 3, -7, 7, -1, 1, 4, 5, -16, 7, 6, -6, + -2, 11, -8, -9, 3, -9, -2, 15, -11, -11, 6, -1, -7, -4, 4, 2, + -9, 1, 1, -2, 0, 6, -3, -3, 6, -7, 6, 11, -11, -9, 0, 15, + -8, 14, -2, -13, 1, 4, 0, 7, -2, -10, -1, 8, -6, -4, 5, 1, + -6, 1, -8, 0, -4, 7, 4, -3, -8, -4, -3, 8, 3, -8, -3, 16, + -7, -1, 0, -1, -4, -2, 2, 6, -1, -2, -4, 5, 5, -4, -2, -8, + -6, 10, 4, -5, -2, -2, -2, 0, -4, 0, 2, 0, -12, 6, 2, 0, + 3, 2, -11, 2, 1, -2, 10, 1, -6, 9, -8, -3, 5, -1, 5, -2, + 0, -5, -7, 8, 5, -4, -9, -1, 1, -2, -7, 4, -12, -4, 5, 0, + -4, 5, -13, 8, 2, 4, 1, -10, -6, -3, 17, 4, 1, -7, 6, 2, + 1, -3, -1, 0, 7, -8, -2, 6, 2, -8, 0, 21, -16, -5, -1, -2, + 4, 0, -18, 11, -10, -4, 11, -4, -1, -2, 2, -3, 2, -2, -8, -1, + 1, -3, 8, 2, 0, 1, 5, -7, 2, -4, -1, 4, 5, 0, 1, -6, + -11, -6, 7, 8, 5, -7, -12, 7, 2, -6, -3, 7, -4, -3, -1, 2, + 9, 0, -7, 9, 5, -15, -3, -7, 2, 3, -2, 0, -3, 6, -13, -2, + 0, -5, 3, 9, -5, 9, -12, -9, 12, 4, 1, 5, 3, -4, -2, 3, + 11, -16, 2, 0, 10, -9, -4, 8, -4, -7, 2, 2, -6, 3, -22, 8, + 11, -7, -6, -2, -5, -5, -8, 3, 7, 12, -8, -1, 4, 8, -14, 4, + 13, -6, -8, 2, 17, -1, -3, 12, -10, -2, -7, 0, -6, 16, -17, -4, + 10, -9, -2, 1, 0, -1, -7, 7, -10, -3, 3, -1, -7, 11, -11, 3, + 3, 8, -6, -2, 1, 0, -15, 15, 5, 0, 7, -5, 4, -3, -2, 2, + -4, 10, -9, -9, 15, -6, -12, 14, 3, -7, 0, -9, -1, -5, 3, -4, + 3, 4, -14, -2, -1, 8, -3, 13, -5, -18, 12, -1, -7, 0, 5, -2, + -6, 14, 3, -9, 3, 1, -10, 0, 7, 3, -7, 4, 2, -14, 4, 4, + -6, 14, -4, -12, 6, 2, -10, 1, 5, -6, -10, 3, 8, -11, 9, -1, + -3, 2, -6, -8, 4, 2, -10, 6, 11, -7, 0, 2, 1, -10, 8, 6, + -5, 2, -2, 3, -4, 1, 4, -11, 6, 4, -8, 4, 4, -13, -4, 2, + 6, -3, 2, -4, -11, 11, 2, -13, 9, 3, -21, -2, 17, -4, -1, 6, + -11, -2, 1, -4, 4, 5, 0, 0, 1, 13, -8, 0, -3, 2, -6, 1, + 7, -4, 2, 2, -5, -5, 8, -14, -4, 8, -10, -1, 3, -4, -6, 6, + 5, -12, -6, 5, 1, -4, 2, -4, -1, 8, -8, 1, 8, -4, 6, -1, + 17, -8, -7, -1, 4, -1, 14, -5, 0, -6, -1, 0, -1, 2, -10, -7, + 0, 6, -6, 4, -12, -1, 7, -5, -2, 0, 3, 0, -9, 10, -8, -1, + -5, 11, -15, 6, 6, -1, 1, 1, -4, 4, -7, 12, -11, 10, 2, -15, + 5, 11, 5, -7, -7, 0, 0, -5, 11, 0, -5, -10, -12, 15, 1, -2, + -4, 2, 6, -9, -8, -3, -1, -5, 5, -4, 1, 5, -13, -1, 10, 0, + 0, -2, 1, 9, 0, 3, -7, 14, -2, 0, -2, 3, -12, 9, 4, 0, + -4, -7, 0, -6, -5, 5, -3, -5, -5, 4, 7, -13, -7, -6, 3, 1, + 0, 6, -3, -5, -4, 7, 1, 3, 1, -3, 5, 3, 3, 2, -1, 2, + 4, -9, 8, 2, -5, 6, -12, 7, -5, -8, -6, 9, -14, 4, -7, 4, + -6, 1, -2, -11, 4, -4, 2, 7, -4, 4, 5, -2, -4, -5, 6, 2, + 0, 5, 9, 3, -4, -7, 1, 6, 3, -2, -7, 1, 1, -6, 0, 8, + -12, -11, 7, -12, 0, 2, -5, 4, -1, -9, -2, 7, -8, 1, 1, 5, + 1, -4, 5, -8, 4, 2, -5, 7, 6, -6, -3, -8, 13, -2, -3, 2, + 0, 0, -5, 6, 5, -6, -3, -3, 2, 8, -12, 4, 7, -12, -10, 13, + -3, -2, 1, -5, 1, 1, -2, 5, -5, -6, -12, 4, 0, 4, 3, 3, + -10, -8, -3, 10, -5, 7, -8, 3, -1, 6, 0, 3, 6, 4, -6, 2, + 5, 5, -6, -4, -2, 4, -2, -9, -4, 7, -1, -12, 10, -5, -9, -11, + 1, 4, -8, 1, 7, -3, 4, -7, -1, 8, -5, -6, 9, -1, 0, 8, + 3, 7, -9, 6, -1, 9, -7, 2, 3, -4, -5, 6, -6, 8, -10, -12, + 4, 3, 1, -1, -9, -1, -4, -5, -3, 6, 7, -11, -4, 6, 0, -3, + 3, 4, -5, -4, 1, -3, 3, -2, 0, 1, -1, 3, -9, 7, 3, -7, + -2, 5, 5, -9, 7, 0, -8, 8, 1, -5, 6, -4, -6, 2, 6, -3, + 0, 0, -3, -9, -6, -2, 9, 2, -2, -11, 7, 9, -9, -7, 8, 0, + -7, 1, 4, -5, -3, -3, 5, 5, -3, -13, 7, 5, -6, 5, -2, 7, + -9, -8, 6, 2, -5, 3, 7, -4, -6, -7, 1, 7, 6, -5, -5, 6, + -10, 10, 1, -4, 4, -4, -2, 1, 9, -10, 0, 4, -8, -1, -5, -1, + 3, -2, 6, 1, -5, -5, -5, 2, -3, 3, 3, -1, 0, -4, 0, 9, + -1, -6, -6, 4, -1, 2, 5, 0, -2, -2, -4, 2, 4, -1, -4, 4, + 0, -3, -9, -2, 6, 0, -7, -1, 3, -2, -1, 2, 2, -7, -2, 0, + 2, 4, -6, 3, -3, 6, 0, 0, -2, -6, 1, 11, -2, -1, -8, 3, + -7, 1, -2, 6, -9, 6, 0, -1, 1, -6, -7, 5, -1, 2, -2, -1, + -1, 0, -3, 1, 2, -1, -3, -5, 3, 7, -9, 5, 3, -5, -5, 5, + -1, 0, 4, 4, -11, 8, -3, -10, 9, -7, -1, 1, -2, 1, -3, 6, + -3, -5, 2, 4, -7, 5, 2, -2, -3, 1, -2, -4, 2, 0, -4, 8, + 2, -12, 0, 6, -10, -2, 8, -6, -3, 6, -4, 2, 9, -4, -7, 2, + 5, -1, 1, 4, 0, -5, 2, -7, 2, 4, 1, -5, -1, 7, -5, -5, + 12, -7, -12, 6, -4, -3, 3, 4, -3, -5, -1, -3, -10, 9, -8, -2, + 6, -3, -4, 6, -1, 0, 3, 2, 1, -3, -5, 2, 0, 4, -3, -3, + 1, 4, -8, 0, 7, 4, -9, 0, 3, 1, 1, -5, -4, 3, -1, -4, + 4, 3, -8, -2, -2, -3, -1, 0, -3, -2, 3, -2, 1, 0, -1, 0, + -6, 8, -5, 5, -5, 5, -3, 5, -7, 1, -3, -1, -1, 2, 8, -2, + -5, 1, -3, -1, -4, -4, 9, -1, 1, -3, -2, 1, -14, 8, 3, -14, + 4, 1, 2, 2, 0, -5, 3, -1, 2, -2, 8, -8, -3, -3, 7, -1, + -3, -1, -3, 1, 5, -7, 7, -12, -1, 1, 4, 3, -7, 5, 6, -2, + 2, -6, -3, 0, -5, 2, 1, -1, 2, -7, 1, 8, -5, -4, -3, 2, + -2, -5, 3, 2, -3, -6, -1, 1, -4, 4, 5, 2, -14, -1, 3, -4, + 3, 10, 2, 2, -4, -1, 4, 3, -6, 2, 1, -2, -9, 7, -2, 1, + -4, -5, 1, -7, -1, 1, 2, 2, -1, -6, 5, -1, -12, -4, 11, -2, + -3, 6, -4, 2, 0, 0, -2, 0, 3, 2, 4, 2, -3, -6, 9, -10, + -4, 2, 4, -1, -5, -1, 2, 1, 2, -7, -2, -4, -4, -2, 7, 5, + -6, 0, 1, -1, -4, 2, -6, 3, 9, -11, -2, 8, 0, -5, 6, -1, + 3, -5, 6, 1, -10, -4, -3, 4, 10, -8, -2, 1, 4, -8, 4, 3, + -8, -5, 2, 4, -5, 6, -2, 2, 2, -3, -10, 0, -6, 2, 4, 12, + -4, -10, 6, 2, -5, 2, -3, 6, -4, 0, -6, -4, 7, 0, -4, 12, + 0, -14, 3, 2, 1, 1, 2, -7, -1, 3, -1, -4, 10, -9, -11, 6, + 4, -9, -5, -1, 5, 0, 6, -5, -5, -4, 3, -7, 9, 0, -1, 0, + 4, -3, -2, -1, -4, 0, 10, 3, -5, 4, -4, -6, 8, 0, -7, -3, + 17, -9, -8, -1, 3, -3, -3, 0, -4, -3, -5, -4, 8, 8, -9, -5, + 4, 0, -7, 6, 7, 3, -6, 3, -3, 1, -4, -4, 4, 10, 1, -5, + -2, 0, -9, 4, 1, 1, -4, -2, 6, -3, -5, 0, -6, 3, 0, -2, + 4, 1, 0, -4, 3, -1, -10, -2, -2, 2, 9, -11, 8, 3, -2, -1, + -1, -3, -1, -8, 4, 6, 2, -7, 2, -1, 3, -6, 0, 1, -1, 2, + 2, 3, -1, -13, 2, 9, 3, -5, -3, 2, -3, 5, -4, -2, 0, -4, + -1, 1, -4, 0, -4, 0, -2, -2, -5, 1, 4, -1, 1, -4, 1, 2, + 0, -2, 2, 1, 1, 0, 7, 0, -3, -4, -2, 5, 0, -3, -2, 3, + 2, -9, -1, -1, -1, -4, 1, 5, -6, 1, -4, 8, -12, 1, -5, 3, + 3, -1, -6, 9, -3, -2, 0, 4, 0, -3, 4, 10, -5, -4, -2, 0, + 2, -3, -2, -2, 0, 0, -3, 0, 3, -8, 0, -5, 1, 0, 5, 1, + 4, -14, -2, 1, 3, 1, 0, -1, 6, -2, 2, -5, 4, 1, -2, -3, + 1, 3, 5, -5, 3, -1, -8, 0, -3, 5, -7, 2, -4, 2, -4, 2, + -3, -2, -7, 4, 2, -2, -4, 5, -5, -3, 0, -4, 3, 5, -6, 5, + 8, -5, 0, 2, 1, -6, 0, 5, 1, -2, 6, -10, 7, -9, 3, -5, + 4, -1, -1, -4, 5, -6, 5, -1, -9, -1, 2, 4, -2, 0, 5, -9, + 1, 0, -2, 1, -1, -3, -1, 9, -1, -9, -2, 2, 1, 2, -2, 3, + -7, 3, -1, 3, -1, -5, -5, 9, 1, -1, -3, 2, -7, 1, 3, -4, + -2, 5, 3, -2, 0, -5, -1, -1, -3, 1, -2, 0, -1, -2, 7, -3, + -12, -1, -2, 0, 5, 4, -4, -2, 6, -3, -5, 8, -5, -4, 2, 6, + 1, -1, -1, -4, 4, 3, -6, -4, 6, -1, -4, 2, 2, -10, -4, 3, + 0, -3, 5, -4, -5, -1, 2, -5, -1, 2, -2, 1, 6, -2, -4, 5, + -2, 1, 4, 0, -2, 0, 3, 0, -2, -4, -6, 6, 3, -2, -1, -1, + 1, -1, 0, 0, -14, -1, 3, 0, 0, 4, -6, -2, 0, -2, -3, -3, + 3, -4, 7, 4, -4, -3, -2, 3, 1, 0, 1, 2, 5, -2, -6, -1, + 1, 1, -4, 3, 0, -2, -3, 2, -8, 1, -2, -5, 0, 2, -2, 6, + 2, -1, -7, 4, -5, 2, -4, -6, 5, 5, 2, -1, -3, -4, -7, 0, + 6, -3, 0, -4, 8, 1, -6, -1, 2, 0, -2, -1, 7, -5, -4, 0, + 7, 0, -5, -4, 3, -2, 3, -3, 1, 3, -1, -6, 2, 3, -7, 3, + 0, -3, -3, -2, -4, 2, -2, -1, -3, 2, -4, 0, 4, 2, -6, 1, + -1, 1, 1, 4, 1, 2, -4, 0, 0, 5, 0, -5, -5, 7, 0, -4, + -4, 2, -6, -4, 5, -1, -1, -4, -3, 3, -1, -6, 1, 4, -1, -3, + -3, 3, 4, -1, 3, 2, 0, -3, -3, 5, 2, -3, -1, 1, -1, -2, + -1, 2, 1, -5, -1, 1, -3, -3, -4, 0, 2, -3, -2, 0, 4, -1, + -2, 0, 3, -6, 0, 3, 5, -1, -2, 3, 0, -3, 0, -3, 8, -4, + -6, 4, 2, -5, 0, -1, 2, -5, -7, -2, 1, 2, 1, 0, -2, -1, + -2, 0, 4, 0, -5, 2, 7, 5, -5, 3, -3, 0, 1, 0, -2, 5, + -10, 0, 1, 3, -12, 1, -2, -1, 1, -2, -4, 3, -6, -2, 3, 0, + -6, 0, 2, 4, 2, -3, 6, 2, -7, 2, 1, -4, 9, 3, -1, 0, + -2, -7, 0, 5, 3, -6, 4, -8, -3, -3, -1, -3, 3, -3, -5, 3, + -3, 3, -1, 2, -7, -2, -1, -4, 2, 2, 4, 3, 0, 0, -1, -2, + 1, 4, -2, 2, -1, 2, -2, -1, -8, 2, 2, -3, -1, 2, -2, -5, + 0, -1, -4, -1, 5, 1, 3, -2, -1, 0, 2, 6, -4, -1, -6, -2, + 2, 4, 1, -2, -5, -4, 0, 3, -4, 1, 4, -1, -9, -1, 1, -1, + -2, -2, 2, 1, -5, 6, -1, 5, -4, -3, -2, 8, -2, 1, 5, 2, + -8, 0, 2, 0, 3, -3, -4, 3, -7, -6, 4, 1, -6, 0, 2, -2, + -4, -2, 2, 4, -5, -2, 3, 0, -5, 1, 7, 6, -4, -7, 4, 3, + -6, -3, 12, -3, -3, -5, -2, 2, -2, -7, -2, 10, -4, -5, 2, 0, + -3, -5, 3, -1, 3, -2, -3, 3, 6, -8, 2, 5, -3, -3, -5, 13, + -3, -1, 1, 1, -4, -3, 0, 3, -3, -2, -1, 1, 2, -7, -6, 3, + -7, -3, 3, 1, 2, 1, -7, 3, -3, -1, -5, 6, 3, -1, -6, 6, + 3, -2, -3, -1, 1, -3, 3, -5, 4, 0, -6, -3, 5, -1, -5, 8, + -2, -1, 0, -4, 5, -4, -5, -1, 1, 4, -1, 1, 5, -5, 3, -2, + -2, -5, -2, 2, 4, -2, 2, 1, -16, 5, 1, -1, -2, -2, 1, -4, + 0, -8, 2, 4, -5, 0, 6, -2, 0, 0, 0, -1, 2, -5, 6, -1, + -1, 2, -1, 4, -5, 1, 0, -4, -2, -3, 2, 2, 4, -3, 1, -9, + -1, 2, 0, 1, -1, -1, -4, 3, -7, 6, -4, 2, -4, 7, -3, -1, + 3, -7, 0, 10, -1, -8, 2, 2, -5, -5, 4, -2, -2, -7, -5, 4, + 2, 3, -11, 10, -6, -5, -4, 0, 9, -1, 0, 4, -6, -1, 3, -1, + 6, -6, -1, -1, 9, -5, -3, 7, -1, -1, 4, 2, -7, 3, -2, 0, + -2, 2, -9, 0, 4, -6, 0, 2, 3, -14, 4, -3, -12, 3, -1, 3, + -4, 4, -8, 6, 5, -3, -2, -4, 8, 0, -3, -1, 1, -4, 4, -3, + 7, 0, 1, -5, 1, 6, -10, 1, 8, -5, -8, 6, 4, -2, 5, 2, + -9, 4, -1, -1, 0, -4, -5, 3, 4, -11, 3, -7, -4, 1, 2, 0, + -3, -2, -7, 4, -9, 4, -6, -1, 2, -2, -1, 3, 9, -6, 2, -1, + 3, 4, 2, 3, -1, 0, -1, 1, 4, 0, -3, 3, 6, -7, -4, 4, + -3, 0, -5, -2, 2, 4, -1, -1, 0, -9, -4, -6, 14, -11, -5, -1, + 5, -6, -3, 3, -2, -6, 3, 5, -1, -4, 5, -7, 7, 4, -7, 6, + 4, -2, -4, 5, 8, -12, 3, -1, -5, 3, -3, 2, 10, -7, -12, 3, + -2, 5, -4, 4, 3, -6, -4, -6, 10, -4, 2, -3, 2, 0, -2, 0, + 2, 2, -12, -2, 13, -2, -6, 0, -5, 10, 1, -1, -2, 0, -12, 3, + 11, 0, -5, -9, 7, -4, 2, -3, 0, 9, -2, -6, 0, 3, -2, -13, + 1, 12, -7, -3, 0, -1, -4, -4, -5, 1, 5, -4, -7, 2, 0, -3, + 5, -2, 10, -12, 5, 1, 10, 8, -6, 4, -12, 7, -1, 5, 0, -1, + -2, 7, 4, -4, 5, -4, -20, 6, 1, -6, 5, 0, -14, 3, -12, 3, + -8, 6, -10, 2, -4, -3, 1, 4, -7, 4, 8, 2, 1, 2, 2, 3, + 3, 0, 7, -7, 3, -1, -1, 11, 3, 1, -6, 0, -8, -10, 8, 6, + -4, -1, -5, -11, 3, -1, -14, 6, -4, -13, 10, 0, 1, -5, 0, 0, + 1, -3, 7, 4, 3, 3, -1, 6, 1, -1, -6, 2, 2, -3, -4, 15, + -17, -4, 1, -3, 4, -4, -6, -2, 4, 4, -4, 3, -4, -7, -2, 13, + -1, -4, -2, -3, 9, -7, -12, 13, 10, -12, -3, 4, 13, -14, -6, 12, + -4, -10, 11, -5, 4, -1, -17, 9, -1, 4, -3, -5, 6, 0, -7, 3, + 2, 4, -9, -9, 13, -8, 7, 6, -8, 11, -15, -11, 16, -10, -2, 1, + -8, -1, 11, -1, -4, 2, -13, 9, 3, 11, -16, 4, 7, -9, 9, 4, + -16, 11, 9, -10, 13, 4, -10, -12, 2, 4, 4, -10, 7, -6, 0, -8, + -3, 3, -1, -4, -9, -9, 3, -5, -3, 24, -19, -5, 7, -11, 4, 9, + 1, -3, -1, 7, -4, 4, 4, -4, -7, 22, 0, -1, 10, -19, 3, 1, + -6, 9, -7, 3, -5, -5, 5, 9, -17, -2, 4, -9, -4, 5, -3, -7, + -3, 6, -4, 10, -12, -3, 13, -6, -5, 5, 3, 8, 0, -7, 0, 2, + -3, 12, 3, -10, -4, -8, 8, -1, -16, 13, -5, -5, 0, 3, -6, -8, + -2, 13, -5, 12, -4, -17, 11, 0, 2, 2, 3, -6, -3, -3, 4, 7, + -3, 1, -2, -2, -3, -4, 7, -3, -4, 4, -5, 6, -11, 5, 7, -10, + 0, 2, -6, -1, 5, -3, 3, -5, 5, -8, 4, 10, -8, 3, -4, 7, + -5, 3, -3, -2, 4, 2, -4, -7, 2, -3, -5, 6, -2, 5, -4, 6, + -10, -5, 5, 0, -8, 6, -6, -1, -3, 5, 2, 0, -4, 10, -12, -5, + -21, -1, -4, 5, 3, 2, 18, -14, 8, 5, 1, -4, -5, -2, -9, 0, + -12, 20, -4, 7, 1, 6, 7, -1, -5, 13, -1, -7, 6, -2, -5, 2, + 1, 4, 6, -7, 6, -9, -3, 6, -3, 8, -10, 8, -6, 0, -20, 1, + -5, 5, -4, -8, -12, -13, 8, -2, 17, 3, -5, -20, -1, -7, 3, 22, + 22, 12, -11, -13, -15, -9, 21, -3, 25, 43, -4, -3, -6, -21, -30, -37, + -9, 8, -5, 8, 53, 50, 1, -5, -13, -15, -41, -23, 6, -34, -47, -17, + -2, 2, -13, 22, 29, 32, 44, 51, 55, 10, 15, 7, 0, -31, -48, -38, + -48, -43, -13, 7, 4, -46, -23, -6, 6, 4, 12, 50, 26, 4, 24, 40, + 33, 20, 17, 17, -7, -30, 10, -2, -17, 5, -36, -7, -38, -30, -13, 1, + 9, -1, -6, -29, -15, -11, 7, 3, 6, 16, 27, -22, -8, 5, 24, 27, + 0, 4, -5, -5, -2, 15, 12, 12, 2, 13, 0, -19, -26, 4, -19, -24, + -33, -21, -28, 0, 6, 18, 20, 15, 40, 2, -8, 17, 21, 47, -2, -12, + 11, -9, 22, -19, 3, -27, -29, -10, -38, -36, -42, 33, 12, -29, 10, -15, + 0, -1, -22, 24, 27, 8, 15, 7, 16, -13, 9, 33, 8, -4, 33, 70, + 21, -26, -18, -15, -22, -76, -2, 15, -35, -4, 8, 5, -3, -45, 6, 24, + -20, 6, -15, 8, -1, 2, 7, -4, 39, 4, 22, 34, -25, 26, -1, -31, + -4, 10, 2, 22, -25, -19, -2, -2, -44, -29, -17, 10, -6, 29, -8, 12, + 18, -9, -6, -36, 4, -14, -8, 10, -12, 28, 9, 16, 17, -29, 26, 0, + 1, 11, -13, 11, 1, 7, -7, -3, -5, 22, -10, 10, -29, 22, -29, -30, + 29, -30, 3, -43, 21, 5, -18, 6, -5, 23, 18, -31, 35, 28, -19, 9, + 13, 10, -3, -10, 37, -69, 7, 11, -16, 8, -76, 11, 58, -57, 18, -7, + -11, 26, -40, 100, -53, -1, 14, 3, -26, -35, 21, 20, -30, 10, -26, 37, + 25, -97, 118, -72, 37, 11, -15, 52, -22, 6, 85, -32, 24, -63, 48, -60, + -19, 3, -28, -19, 7, -28, 15, -22, 7, 20, -7, 16, -13, 8, 25, -27, + 2, 7, -18, 15, -30, 23, -3, 28, -31, 34, 22, -23, -6, -6, 28, -68, + -10, -3, -22, 12, -43, 70, -52, 32, 8, -4, 55, -14, 19, 21, 45, -13, + -33, -9, 20, -22, -14, 9, -21, -2, 6, -56, 17, -26, 23, -13, -8, -1, + 3, 31, 16, 20, -12, -10, 50, -27, -17, -13, -26, 29, -23, -7, 58, -40, + -20, 16, 16, -13, -65, 63, 18, -25, 23, -3, 6, 11, -11, -24, -19, 8, + 32, -44, 47, -50, 26, 6, 43, -58, 15, -21, 46, -81, 60, -28, 65, -37, + 42, 42, -55, -6, -23, -9, -52, -25, -5, 7, -67, 26, 59, -62, 31, 63, + -23, 52, -16, 27, 14, -13, 19, -41, -8, 37, -7, 9, -33, 16, 7, 36, + -40, -26, -26, 49, -3, 3, -50, 33, 23, -10, -13, -14, -19, -13, 1, 2, + -41, -19, 32, -3, -29, 9, 58, 1, 9, 15, 19, -19, 59, 2, 6, -6, + -24, 52, -67, 3, 5, -37, 3, 31, -42, 45, -1, -31, -6, 19, 11, -17, + -5, -2, -22, 3, -35, 35, -39, 8, 17, 6, 7, -32, 2, -1, 40, -32, + -2, 26, -5, 2, -5, -12, 18, 21, -15, 29, -28, 13, -23, 36, 28, -75, + 55, -53, 50, -45, 9, -3, 42, -10, -33, 8, -9, -17, 8, 13, -13, 34, + -48, 39, -5, -26, 24, 19, -34, 29, -41, 22, -42, -11, -15, 37, 0, -31, + 15, 4, 11, 18, -28, 23, -3, -52, 33, -1, -8, 19, -39, 44, -3, -16, + 31, 7, -17, 38, -44, 62, -21, 0, -7, -13, 25, 12, -50, -13, 2, 9, + -47, 43, -29, -12, -3, -3, -37, -22, 0, -6, 60, -69, 27, 9, 12, 13, + -7, 46, 43, -2, 3, -5, -5, 17, 13, -37, 35, -39, -38, 33, -44, -10, + 11, -9, 50, -68, 26, -22, 10, -20, 34, -13, -17, 21, -34, -1, 42, -23, + -7, 9, 3, 1, -1, -9, 36, -15, 5, -21, 40, -47, 25, -11, 20, 24, + -19, 16, -13, 6, -25, -2, 19, -17, 7, -36, 28, -8, -28, -11, 9, 25, + -55, 7, 39, -36, -3, 8, 28, 25, -33, 29, 1, -28, -1, -7, 40, -50, + 22, 15, 21, -2, -1, 18, 8, 46, -52, -1, 14, -39, -10, 18, -10, -27, + -15, -9, 2, -7, -47, 23, 17, -40, 12, 37, -24, 22, 9, 5, 27, -14, + -17, -17, 23, 16, -18, 19, 32, -19, -10, 13, 12, -33, 31, -4, 12, -17, + 22, -3, -8, -33, 16, -45, -17, -13, -24, 23, 19, -22, 52, -63, 23, 26, + 8, -11, 30, 40, -35, 28, -5, 11, -10, -16, 18, -35, -21, -6, 9, 0, + -33, 9, -15, -24, 15, -23, -19, 30, 13, -20, 37, 24, -48, 47, 21, -31, + 51, -22, 40, -24, 47, -55, 31, -21, -57, 15, -7, -28, 5, 25, -12, -42, + 46, -43, -21, 6, 4, 14, -15, 11, 51, -27, 6, 21, -27, 42, 17, -35, + 3, 3, -15, 11, 17, -26, 0, 6, 11, 18, -37, 4, 28, -14, -14, -30, + 43, -50, -17, 55, -50, 16, -32, 51, -35, -13, -4, 54, -22, 23, -48, 51, + 2, 10, -16, 7, -10, 15, -48, 25, -5, -4, 6, 21, -17, -2, 30, -23, + 16, -3, -12, -11, 21, -57, 3, 10, -3, 0, -19, 36, -42, 50, 0, -30, + 55, -15, 12, -10, 28, -47, 29, -16, 6, -37, -1, -6, 3, -45, 35, -30, + 8, -4, -12, 32, 42, -23, 3, 5, 30, -38, 15, 16, -36, 60, -1, -53, + 28, -25, -10, 45, -20, 2, -22, 24, -6, -19, -31, 18, 6, -56, -15, -3, + -5, 1, 12, 5, -7, 70, -9, -7, 49, -31, 48, 36, -15, 5, -23, 35, + -51, 4, -32, -40, 7, -20, -15, -7, 17, -32, -2, 17, 1, -8, 46, -4, + 12, 15, 41, -50, 29, -21, -13, 10, -20, 12, 2, -24, 12, -1, 6, 8, + -29, 19, -27, 51, -67, 83, -44, -22, 21, -2, -14, 13, -52, 72, -37, 19, + -25, 43, -37, -22, 19, -12, -36, 14, 17, -3, 27, -39, 58, -23, 1, 14, + 52, -25, 15, -1, 1, -23, -11, -9, 4, 14, -83, 23, 4, -38, -21, 2, + -1, 17, 2, 48, -30, 24, 29, 9, 19, -44, 46, 22, 5, -32, 39, 0, + -28, -27, 16, -32, -31, 7, -17, -13, -9, -6, 14, -33, -18, 35, -39, 52, + -40, 31, 12, 14, -24, 52, -35, 11, 1, 26, 10, -18, 20, 7, -7, -5, + 7, 5, -15, -10, -7, 8, -10, -26, 21, -16, -14, 13, -27, 27, -44, 6, + 18, 6, -12, -4, -11, 12, -1, 7, 6, 3, 20, -5, 11, 15, 9, -10, + 37, -37, -3, 11, -23, 9, -35, 19, -32, 4, 14, -28, 41, -42, 43, -5, + 11, -20, -16, 20, -10, 6, 6, -4, 1, -6, 7, 20, -42, 25, -29, 34, + -31, -10, 14, -4, -9, -4, 13, 7, -7, -2, -19, 25, -10, 0, 16, -1, + -9, -6, 53, -52, 10, -7, 5, -10, 1, 4, 9, -24, 10, -21, 61, -40, + 3, 3, 12, -38, 31, -3, -7, 8, -13, 8, -15, 4, -33, 44, -29, 5, + 5, 37, -52, 16, -13, 25, 7, -34, 17, -7, 14, -11, 24, -32, 22, -23, + 42, 5, -30, 21, 19, -21, 2, -11, 14, -18, -16, -34, 41, -30, 7, 2, + -23, 20, -37, 26, -17, 18, -37, 64, 0, 14, -19, 5, 12, -8, -13, 22, + -9, -26, 24, 17, -8, 3, -5, -14, -14, 17, -30, 14, 26, -67, 38, -9, + -20, 11, 11, -22, 11, 15, 1, 11, -22, 0, 1, 38, -43, 2, 15, -31, + 2, -5, 29, -18, -27, 21, -8, 15, -20, 46, -24, 20, 16, -7, 24, -63, + 40, -8, 9, -8, 14, -10, -11, -28, 4, 10, 8, -26, 13, 11, -35, -1, + 40, -36, -5, -3, 38, -7, -23, 3, 4, 17, 3, -15, 11, 24, -67, 26, + 2, 21, -54, 30, 14, -34, 12, 25, -16, 12, -13, -7, 47, -24, -23, 7, + 18, -4, -19, 31, -18, -14, -11, 21, -15, 5, -31, 40, -53, 21, -4, 30, + -32, -3, 14, -5, 30, -17, 3, 13, 8, -4, -5, -11, -12, 8, -7, 16, + 10, -21, 35, -59, 13, 10, -3, -7, 1, 2, -16, -4, 27, -43, 35, -16, + -14, 36, 0, -51, 13, 31, -19, 14, 21, -19, 14, -3, -27, 29, -10, 34, + -46, 30, -12, -17, 11, -34, 23, -23, 10, -3, 4, -8, -14, 25, -16, 35, + -12, 22, -7, 3, 9, 0, 11, -5, -10, -16, 9, -21, 7, -36, -4, -13, + 4, -6, -7, -2, -1, 0, 14, 16, -15, 7, 27, -28, 43, -32, 17, 7, + -25, 33, -7, 6, -10, 11, -20, 1, 5, 28, -11, -26, 20, -17, 29, -40, + 1, -6, 13, -23, 23, -23, -28, 18, 5, -22, 16, -19, 41, -9, -16, -11, + 45, -17, 6, -51, 34, 36, -44, 29, -33, 22, -13, 3, 5, -26, 2, 11, + 23, -17, 0, -7, 12, 3, -27, 18, 13, -2, -30, 22, -6, 7, 1, -4, + 5, -1, 12, -14, 1, -15, -5, 12, 6, 3, -13, 15, -14, 14, -1, -12, + 3, 3, -4, -18, 7, 2, -7, -5, 9, -15, 7, 17, -27, 45, -52, 60, + -15, -12, -9, -11, -14, 27, -18, -9, 21, -10, 10, 3, -23, -4, 8, -23, + 19, -31, 12, 18, 12, -7, 1, 15, 3, 27, -38, -7, 42, -9, 1, -7, + -22, 5, -10, 0, -28, 5, 12, -6, 0, -12, -15, 18, 19, -14, -27, 47, + -6, -1, -21, 32, -31, 52, -41, 3, -39, 34, -29, 16, 8, -6, 33, 16, + -23, -10, 16, 9, 2, -33, 40, 0, -21, -2, -18, 1, 13, -32, 24, -11, + -14, 24, -20, 0, -19, 11, 23, 1, -30, 4, 38, -23, 11, 0, 9, 18, + -36, 10, -21, -1, -5, -1, 23, -24, 9, 27, -13, 4, -39, 60, -17, -11, + -12, 25, -9, -36, 26, -7, -3, 28, -27, 26, -12, -20, 8, 13, -40, 7, + -23, 38, -33, 14, 8, -1, -23, 36, -19, 15, 13, -36, 4, 17, -32, 31, + -23, 20, 0, 23, -3, 5, -17, -11, 12, -24, 21, -29, 34, -26, -1, 4, + -14, 21, 9, -1, -1, 21, -33, 29, 1, -28, 28, -20, 22, -24, -13, -13, + -6, 10, -22, 33, -49, 17, -24, 1, 22, -11, 43, -27, 28, 28, -33, 36, + 5, -5, 2, 22, -28, 16, -24, -16, 4, -69, 66, -47, -12, 19, -17, -1, + 24, -32, 46, -36, -3, 50, -26, 24, -22, 9, 39, -53, 0, 32, -1, -21, + 29, -26, -4, 29, -45, 12, -10, 11, -12, 20, -23, -11, 20, 10, -1, -24, + 33, -16, 12, 2, 4, 14, -17, -17, 20, -42, 6, -18, 0, -4, -10, 11, + 2, -10, 4, 7, 2, 27, -35, 11, 12, 4, -11, 19, -19, 40, -6, -16, + 44, 2, -10, 32, -37, 1, -23, -8, 23, -59, 11, -5, -9, -9, -1, -8, + 5, -18, 26, -14, 27, -10, 9, 30, 23, -31, 30, -1, -1, -14, -13, 35, + -76, 42, -79, 43, -29, 1, 2, -5, -6, 5, 30, 15, -20, 23, 25, -37, + 39, -5, -20, 24, -7, 2, 20, -38, 20, -31, -12, -2, -12, 13, -31, 10, + -9, 0, -11, 27, -16, 10, -2, 44, -46, 18, 33, -16, -12, 3, 11, 15, + -26, 8, -22, 19, -3, -11, 5, -48, 31, 16, -15, -5, -2, 17, 6, -9, + -8, 9, 25, -7, 0, 7, -8, -5, 10, -11, -26, 26, -15, 17, -31, -11, + 15, -1, -16, 1, 10, 4, -7, 18, -6, 2, 11, -2, 11, -26, -4, 25, + -27, -19, 7, 29, -29, 13, -10, 3, -27, 31, -55, 38, -13, 17, -9, 32, + -27, 17, 18, -3, -10, 17, -45, 58, -12, -18, 25, 4, -40, 35, -61, 10, + -3, 2, -15, -14, 33, -20, -2, -4, -19, 31, -29, 25, 8, -11, -3, 32, + 1, -26, 12, 25, -42, 5, 27, 1, 2, 17, -25, -2, 6, 9, -17, 9, + -11, 9, 9, -21, 11, 15, -55, 34, -24, -6, -1, -9, 17, -13, 1, -11, + 31, -24, -15, 38, -21, 27, -30, 30, -35, 28, 15, -30, 56, -40, -17, 39, + -9, -7, 4, -18, 7, 13, -25, 3, -9, -13, -13, 27, -35, 13, 0, 6, + -3, 26, -20, 27, -23, 25, -25, 38, -2, -3, 8, -11, 0, 0, 0, -28, + 28, -27, -6, 23, -33, -8, -1, -29, 0, 2, 26, -40, 15, 2, 23, 28, + -32, 17, 26, -17, 10, 1, -14, 17, 1, 14, -9, -10, -15, 12, -3, -19, + 2, 20, -19, -19, -14, 4, -2, -8, 13, -16, 22, -9, 28, 7, -9, -22, + 49, -28, 3, -5, 9, -2, 5, -26, 39, -12, -29, 19, -11, 7, -33, 27, + -32, 15, -9, -9, 16, -7, -3, 27, -4, -18, 19, 23, -20, 3, 2, 11, + -21, 14, 4, -13, 8, -15, 9, 4, -37, 9, -11, 22, -20, -12, 17, 12, + -20, -2, 13, 18, -19, -1, 19, -28, 12, 2, 12, 2, -37, 12, 21, -19, + -23, 17, 21, -35, 9, 26, -20, -15, 12, 14, 23, -20, 17, 9, -16, -4, + 5, 3, -8, -24, 13, -5, 5, -7, -11, 31, -24, -34, 28, -8, -26, 16, + -7, 2, -2, 9, -21, 42, -54, 34, 42, -22, 16, -1, 14, -15, -12, 21, + -16, -3, -18, 55, -46, 11, 6, -19, 18, -36, -9, 12, -21, 23, -41, 37, + -12, -10, 1, 13, -5, -7, 42, 2, 1, -2, 4, -3, 15, -53, 27, -3, + -26, -14, 32, -30, -5, 11, 12, -3, -4, -24, 35, -37, 12, 4, 5, -17, + 32, 0, -18, 41, -41, 43, -2, 22, -36, 7, -5, 11, -25, 7, -29, 9, + 2, -4, -11, 5, -2, 15, -31, -11, 24, 3, -15, 26, 11, -10, 18, 5, + -8, -2, -43, 43, 2, -43, -20, 25, 4, -3, 39, -11, -6, -3, -1, -12, + 22, -21, 6, 22, -7, -17, -5, 18, -4, -14, 3, 18, -11, -18, -3, -2, + 2, -5, 1, 10, -28, 17, 8, -8, -12, 23, -13, 10, 0, -12, 14, 11, + -11, 34, -21, 3, 1, -9, -17, 1, 9, -28, 5, -34, 21, -8, 8, 8, + -13, 18, 2, -15, 5, -3, 11, -2, 11, -2, 15, -10, 14, 5, -1, 18, + -6, 1, -26, 13, -25, 2, 6, -39, -14, 0, -5, 13, -22, -14, 34, -22, + -1, 16, -13, 11, 32, -10, 31, -5, 18, -21, 34, -47, 32, -9, 10, 8, + -31, 5, 4, -9, 5, -52, 16, -14, 4, 20, -11, -13, 13, -10, -12, 11, + 16, -20, 13, -12, 14, 10, 1, -15, 32, -24, 18, 0, 5, -26, 6, 16, + -23, -10, 12, -40, 17, -14, -13, 38, -5, 5, -19, -3, 17, 14, -8, 8, + -15, 21, -6, 10, -12, -16, 27, 6, -35, 16, -26, 45, -25, -1, -9, 29, + -25, 8, -31, 9, 25, -10, 4, 11, -22, -5, 1, -12, 6, -10, -11, 17, + -31, 5, 21, -6, 33, -55, 47, 6, -6, 2, 11, 14, -11, 10, -14, -26, + 8, -18, 4, 11, 6, -4, -2, -20, -2, -26, 38, 4, -24, -6, 7, 22, + -15, 30, 0, 13, 3, -11, 4, -10, -28, 38, -14, -9, -5, -45, 40, -21, + -28, 31, 0, -9, 18, -45, 20, 12, -20, 39, -25, 14, 1, 17, -4, 29, + -12, 26, -8, -21, -19, 10, 3, -31, 34, -16, -12, 5, -14, -4, -13, 13, + -7, 13, -15, -23, 40, -27, 15, 4, -11, 23, -20, -2, 7, 8, 3, 2, + -4, 1, 7, -22, 42, -37, 24, 1, -9, 16, -31, 9, 6, -3, -25, 40, + -41, 0, 2, -7, 18, 0, -10, 21, -5, -17, 29, -37, 27, 3, -22, 10, + 11, -5, 13, -17, 15, -19, -23, 17, -10, -35, 20, 4, -4, 3, -10, 7, + 15, -14, 10, -3, 10, -25, 13, 1, 20, -13, 13, 19, -38, 18, -4, 19, + -10, 9, -27, 19, -35, -8, -10, 39, -14, 2, 14, 36, -16, -8, -8, -7, + -2, -11, 4, 1, -42, 51, -17, 10, -15, -33, 29, -25, -7, 6, 2, 11, + 3, -20, 37, -28, 6, 34, -22, 5, 28, -4, 17, 5, -47, 28, 1, -3, + -21, 8, -6, -7, 10, -15, 6, -30, 6, -19, 1, -4, 30, -22, 29, -13, + -4, -2, 11, -1, -15, 38, -4, -9, 25, -29, -17, 10, -2, -3, 7, -15, + 24, -26, 21, 2, 6, -20, 10, -26, 41, -33, 19, -11, 6, -3, -9, 5, + 3, -21, 8, -5, -7, 10, 13, -10, -3, -4, -10, 26, -1, 1, 5, 11, + -3, 2, 23, -35, 21, -43, 17, -4, 2, -24, 14, -22, -3, 3, -5, -2, + 12, -13, 16, -5, 7, 17, 4, -44, 26, 17, -4, 36, -58, 43, -20, 8, + 3, -23, -18, -17, 16, 4, 3, -33, 15, -4, -10, 19, -20, 23, 13, -6, + -4, 25, -12, 21, -9, -4, 6, -1, 23, -7, -15, 3, -15, 3, -13, -23, + -3, -32, 4, 6, -18, 0, 11, -14, 42, -37, 26, -20, 50, -18, 18, 11, + 4, 18, -5, 8, -22, 30, 5, -20, 16, -20, -28, 2, 4, -10, -10, -10, + -27, 38, -38, 14, -17, -20, 34, -11, -5, -5, 10, 5, 25, -20, -2, 28, + -8, 26, -39, 68, -50, 53, -35, -5, 3, -23, 24, 8, -21, -28, 19, 6, + -18, -13, -7, 26, -7, 0, -4, 7, -7, -15, 29, -10, -12, 13, 9, -4, + -34, 39, -49, 38, -31, 29, -26, 2, -18, 45, 3, -16, -2, 29, 4, -27, + 2, 17, 6, -12, -3, 12, -12, -14, -22, 11, -13, 6, -2, 30, -39, 12, + 5, 10, -18, 3, -5, 24, -39, 15, 49, -42, 19, 9, -25, 5, -60, 31, + -19, -8, 9, 28, 28, -34, 21, -4, 25, 24, -18, 17, -35, 1, 7, -28, + 32, -29, 6, 7, 4, -23, 21, -17, -14, 16, -29, 21, -43, -24, 2, 58, + -33, 60, -20, 24, -29, 18, -24, 29, -14, -6, 10, -19, 15, 38, -38, 35, + -15, -11, 20, 9, -57, -4, 0, -8, 15, -8, -20, -6, 9, 21, 8, -21, + 12, 1, 6, -29, 24, 17, 6, -33, 26, 20, -12, 14, -17, 3, -2, -19, + -6, 13, -55, -5, 5, 8, 21, -12, 11, -13, 15, -34, 45, -47, 43, -6, + 5, 34, -32, 28, -15, 12, -38, 30, -16, 1, -4, -2, 6, 4, -26, 2, + 21, -42, 5, 19, -20, 44, -70, 38, -5, -4, -8, 20, -16, 22, -25, 46, + -21, 1, -31, 48, -32, 7, -23, 62, -48, 38, -2, -30, 41, -57, 41, -41, + 9, -5, 16, 9, 1, -50, 80, -48, 5, -20, 11, -9, -19, -8, 1, 20, + -24, 4, 36, -42, 42, -32, 39, 6, -12, 1, 12, 3, -17, 2, -13, 57, + -70, 26, 6, 0, -23, 8, 4, -17, -10, -41, 34, -10, -46, 51, 23, -10, + -4, -10, 16, -9, 4, 32, -14, 6, -7, 23, -18, -9, 5, -14, 4, 15, + -29, 10, 15, -14, 19, -28, 40, -30, -20, 17, 3, 5, 37, -32, 12, 0, + -18, 1, -7, -23, 4, -51, 69, -22, -43, 30, -39, 54, -64, 29, 21, -2, + 2, -22, 29, 2, 14, 5, 8, -7, 7, 34, 2, -25, 10, -7, -5, 24, + -64, -1, -18, -7, 23, -24, 26, -23, -35, -17, 51, -60, 53, -2, 14, 17, + 6, 5, 11, -9, 15, 21, -1, 21, -49, 45, -34, -16, 12, 0, -34, 2, + -67, 50, -48, 23, -20, -12, 20, -22, 32, -15, 15, -23, 65, -9, 33, 26, + -3, 4, 14, 8, -17, -17, -47, 57, -63, 13, 8, -30, -8, -31, -12, 28, + -45, 9, -3, 19, -31, 31, -2, 41, -46, 38, 38, -23, 21, -13, 9, 35, + -2, 5, 13, -36, -2, -10, 15, -16, -48, 22, 29, -49, -21, 15, -10, -15, + -23, 26, 40, -39, 26, -10, 13, 21, -46, 35, -20, 8, -1, 30, 17, -64, + 22, 2, 22, -30, 6, 19, -18, -34, 38, -4, 13, 0, -11, 50, -51, 21, + -10, 13, -42, -9, 45, 4, -82, 12, 37, -11, -12, -8, 21, 6, -33, 32, + -14, 6, 13, -44, 37, -22, 20, 2, 12, -15, 26, 30, -17, -11, -30, 18, + -4, -5, 11, -2, -22, -15, 25, -16, 11, -15, 21, -8, -17, -9, 27, 11, + -43, 2, 4, 31, -59, -5, 44, -16, 26, -13, 3, 1, -1, -40, 70, -44, + 43, -15, 2, 22, -36, 13, 41, -43, -12, 4, 12, -34, -22, 9, 22, -23, + -22, 27, -24, 22, -18, 45, 12, -32, 7, 17, -24, -15, 4, 20, 6, -40, + 29, 48, -64, 28, -3, -6, 43, -22, -34, 36, -41, 13, -2, -59, 72, -53, + 39, -30, -3, 16, 29, -40, 5, 30, -21, 15, -35, 9, 14, 2, 4, -16, + 4, 8, 14, 1, 30, -32, 5, -14, 28, -26, -1, -12, -16, -4, -22, -5, + 28, -8, -24, 7, 42, -22, -3, -9, 16, 38, -42, 25, 8, 10, -9, 38, + -28, 31, -8, -34, 22, -70, 21, 15, -36, -10, -15, -1, 49, -37, -17, 51, + -24, 11, 30, -27, 33, -39, -12, 36, -4, -49, 38, 12, 10, -17, -11, 59, + -26, -59, 33, 28, -37, 17, -39, 40, -16, -29, 28, 14, -19, -14, 18, 23, + -17, -16, 15, -11, 9, -16, 45, -25, -27, -1, 40, -36, 1, 19, -1, -14, + -3, 1, 29, -9, -58, 54, -12, -19, 16, 13, 29, -74, 48, -20, 22, -66, + 3, 23, 2, -31, 11, 41, -41, 2, 25, 4, 8, -3, 8, 23, -10, -6, + 27, -1, -67, 31, -29, 29, -29, 0, 17, -20, -18, -10, 29, -45, 43, -35, + 61, 4, -49, 31, -10, 53, -60, 19, 11, 15, -22, -3, -20, 26, 3, -60, + 59, -41, -26, 17, 22, 12, -6, -12, 30, -14, -8, -7, 16, 54, -34, -18, + 26, -15, -11, 7, -44, 39, -52, 48, -53, 18, -38, 3, 13, -11, 37, -12, + 11, 9, 14, -7, 40, -19, -6, 6, -15, 29, -34, 1, 18, -18, -9, -24, + -30, 17, -50, 31, 4, 8, 17, -7, -5, 0, 17, 25, 16, 15, 43, -54, + 39, -10, 2, -40, -23, 26, 3, -61, -2, 15, -6, -56, 46, -2, 16, -80, + 43, 52, -9, -30, 41, 17, 2, -33, -7, 52, -7, -29, 31, 0, -23, 10, + -24, 44, -82, 18, 45, -14, -40, -40, 40, 12, -66, 0, 74, -35, -5, 17, + 67, -59, 32, -4, 29, -1, -48, 39, 1, 8, -63, 43, -12, -37, -5, -12, + 25, 2, -21, 7, 24, -34, -11, 19, 28, 6, -34, 44, 13, -35, -19, 28, + -50, -13, 56, 7, -32, -12, 19, 6, -1, -6, 6, 0, 17, -26, 41, -20, + -5, -6, 43, -58, 10, -12, -14, 74, -84, 74, -28, -15, -27, 19, -15, -3, + 17, 24, 10, -60, 64, 0, -9, -39, 1, 25, -12, -25, 22, 8, -21, -40, + 73, -32, -18, -11, 6, 57, -52, 36, -19, 37, -40, 9, 2, 14, -15, 27, + -33, 35, 7, -37, 24, 10, -66, 17, 1, -10, 13, -38, 15, -9, 43, -30, + 19, -15, 17, -8, 7, 8, -38, 66, -55, 10, 9, -37, 37, -32, -11, 47, + -14, 11, 37, -41, -33, 12, 3, 34, -59, 35, 14, -4, -7, -2, -21, 48, + -52, 49, -8, -44, 0, 11, -6, -2, 11, -35, 64, -38, -35, 64, 7, -32, + 15, 15, 19, -39, 18, -31, 25, 6, -28, 25, 17, -34, -26, 21, -18, 15, + -15, -31, 24, -4, -26, 41, -2, -18, -24, 75, -21, 1, -6, -2, 16, 12, + -24, 15, 8, -14, 7, 7, -4, -37, 45, -67, 39, -41, 9, 19, 13, -60, + 44, -22, 23, 2, -35, 14, 35, -25, 7, 21, -39, 15, 1, 39, -43, 26, + -18, -14, 36, -10, -16, -15, 29, -34, 16, -1, -13, 24, 0, -43, 55, -18, + -31, 22, -15, -15, 43, -33, 50, -10, -43, 22, -27, 60, -30, 14, 0, 10, + -3, 10, -20, 11, -34, -7, 70, -59, -26, 25, -23, 7, -29, 8, 11, -13, + -8, 3, 13, -13, 35, -8, 34, -33, 9, 30, -5, 33, -37, -10, 56, -38, + -5, 14, -50, -24, 39, -11, -11, -27, -22, 46, -13, -6, -1, -6, 37, -56, + 48, -11, 24, -14, 32, -13, -1, 5, 8, 37, -86, 36, -1, -6, -12, 13, + -40, 3, 9, 15, -13, -23, 3, -15, 61, -50, -12, 29, -14, -2, 25, -31, + 52, -41, 31, 31, -27, -10, 9, 22, -15, 3, -11, 22, -25, 8, -40, 0, + -5, 2, -9, 40, -62, 5, 16, -6, -7, -21, 31, 29, -28, -3, 47, -31, + 51, -34, 59, -32, -8, 44, -7, -2, -20, 3, 64, -51, -58, -3, 0, -39, + 26, -22, 14, -39, 8, 20, -30, -2, 7, 8, 37, 15, -9, 43, -5, 2, + 11, -5, 10, 2, -37, 56, -59, -11, 8, -14, -30, -29, -3, 29, -1, -33, + 42, -44, 53, -58, 85, -28, -5, -2, 41, 5, 15, -49, 30, 26, -46, 17, + 9, -55, 0, 38, -46, 32, -32, 10, 15, -60, 8, 23, -1, 7, -35, 71, + -11, -39, 39, -22, -8, -3, 10, 36, 13, -73, 53, -15, 7, -7, -15, 25, + -7, -24, 21, 9, -51, -11, 27, -15, 11, -6, 26, -26, 27, 16, -33, 47, + -29, -18, 53, -53, -2, 38, -29, 12, -37, 18, 10, -10, -20, -8, 12, 15, + -43, 32, 3, -44, 35, 29, -38, 17, -16, 13, 45, -37, 21, 18, -7, -38, + 32, -21, -6, -4, 20, -14, -9, -16, 14, 1, -19, -13, 22, -4, -39, 58, + -34, 3, 17, -10, 50, -3, -47, 36, 29, -27, -13, 39, -20, -8, 12, -40, + -20, 1, 0, -24, 23, -40, 38, 4, -1, -19, 16, 10, -4, 28, -25, 44, + -17, 19, -21, 50, -10, -16, -13, 7, -28, 11, -9, -17, 13, -52, 22, -3, + -21, -49, 75, -42, 34, -3, 18, 1, 10, -20, 13, 13, 22, -11, -35, 46, + -29, 44, -39, -31, 37, -22, -27, 42, -57, 40, -34, 4, 12, 9, -29, 13, + 6, -10, 4, 21, 7, -17, 3, 25, -18, 44, -26, -1, 20, -38, 19, 24, + -35, -18, -6, -14, 23, -32, -15, 24, -6, -50, 62, -39, -3, 0, -23, 87, + -44, 37, -9, -4, 67, -73, 46, 45, -32, -14, 8, -4, -22, -5, -22, -20, + 36, -34, 6, 26, -35, -18, 15, 0, -12, 0, 12, -10, 28, -15, 24, 13, + -21, 19, 15, -17, 20, -7, 0, -21, 7, -16, 5, -12, -1, -11, 7, 32, + -68, 69, -55, 24, 2, -3, 21, -47, 28, 20, -15, -29, -2, 23, 4, -18, + 15, -22, 36, -38, 17, -23, 14, -18, 17, 31, -37, 30, 8, -1, -3, -5, + -12, 22, -18, -28, 33, 0, -9, -16, 20, 9, -26, -20, 21, 2, -4, 14, + -24, 16, -11, 12, -1, -39, 7, 51, -2, 1, -12, -30, 63, -43, -19, -2, + -6, 20, 10, -18, -2, 23, 15, -3, -34, 1, 9, 10, -22, -29, 28, 28, + -32, -2, 23, -26, 2, 11, 25, -35, -14, 15, 23, -48, 12, 7, 22, -52, + 25, 17, 16, -47, 29, 13, -19, 12, -67, 65, -6, -30, 32, 7, -12, 14, + -19, 27, -52, -2, 15, 40, -69, -5, 33, 15, 6, -51, 36, 21, -2, -24, + 15, -3, -9, -4, 30, -34, -2, -19, 27, -23, 3, -12, 2, 18, -15, -6, + -3, 22, -30, 55, -21, 26, -35, 44, -27, 25, -21, 4, 14, -20, -1, 10, + -42, 12, 7, -12, 5, -37, 13, 1, 3, -33, 24, 15, 0, -4, 10, -14, + -6, 35, -6, -4, -8, 13, 26, -7, -32, 36, -9, 5, -15, 14, -15, -36, + 8, 2, -15, -22, -7, 28, -4, -25, 17, 39, -16, 4, 20, 8, 4, -2, + 4, 31, -46, -12, 15, 0, -9, -36, 18, -10, -12, 7, -17, 3, -13, -4, + 37, -27, 6, -16, 76, -41, 13, -14, 25, 28, -21, -10, 31, -4, -39, 21, + -9, -35, 12, 3, -16, 7, -54, 51, -34, 44, -45, 30, -7, -30, 49, -21, + -1, 27, 12, -8, 9, 8, 5, -27, 42, -30, 32, -28, -27, 19, -18, -36, + 10, -25, 19, -9, -14, -5, 13, 31, -21, 22, -28, 15, 13, 10, -12, 6, + 32, 1, 24, -47, 36, -4, -23, 0, -16, 6, -41, 1, 17, -33, -9, 5, + 34, -5, -15, -1, 30, 13, -30, 20, 7, -12, -16, 11, 20, -4, -19, 21, + 26, -25, -17, -5, 23, -32, -3, -12, 18, -5, -28, 8, 15, -14, -10, 31, + 11, -43, 12, 35, -5, 3, -33, 48, -1, -11, -6, 28, -23, -13, 13, 9, + -7, -22, 2, -25, 32, -38, 17, -16, 10, -54, 69, -62, 61, -30, 4, 24, + 3, -12, 4, 27, -22, 22, 0, 4, -15, 4, -46, 20, -16, 29, -30, 14, + -25, 30, -18, 16, -12, -7, 21, -10, 16, -23, 15, 9, -12, 12, 13, -21, + 19, -28, -2, 5, -15, 0, 3, -17, 6, -6, 18, -11, 6, 13, -1, 15, + -23, 14, 5, -17, -14, 5, 24, -23, 15, -26, 9, -10, 15, -29, 2, -12, + 23, 8, 10, -37, 26, 7, -5, -25, 3, 16, 14, -10, -5, -16, 22, -7, + -8, 18, -58, 86, -15, -5, 4, -30, 40, -7, -21, -12, 9, -10, 16, -48, + 40, -29, -6, -5, -22, 21, 3, -20, 39, -36, 29, -5, 2, 3, 15, 2, + 6, 21, -11, 28, -13, 2, -33, 24, 1, -28, 12, -33, 12, 11, 0, -41, + 11, -5, -9, 26, -34, 15, 2, 18, -7, -25, 5, 11, -4, -7, 35, -6, + 23, 12, -42, 33, -32, 26, -41, 25, -23, 15, -13, 11, -5, -4, 0, -8, + -4, 1, 10, 6, -8, -7, 18, 8, -11, -19, 9, 17, -2, -13, 8, -21, + 31, -16, -24, 3, -12, 10, 23, -8, 12, 8, 23, -7, -22, -8, 5, -5, + -14, -33, 4, 7, -11, -11, 15, -22, 38, -2, -11, 24, -16, 38, 14, -6, + 7, -14, 18, -13, 2, -8, -14, 13, -19, -13, 2, 2, -23, -9, 11, 1, + -12, 16, 1, 2, 18, 1, -20, 9, -5, -14, 16, -11, 2, 8, -2, -9, + 0, 11, 13, -22, 18, -16, 35, -39, 45, -22, -18, 12, 1, -19, 21, -48, + 42, -20, 9, -23, 20, -11, -27, 21, -13, -14, -11, 29, -13, 25, -25, 36, + -13, 8, 17, 34, -14, 11, 4, -4, -15, -9, -12, 1, 19, -69, 7, 10, + -34, -20, 1, -5, 13, 6, 34, -17, 5, 40, -1, 21, -38, 35, 22, 11, + -28, 28, 11, -25, -26, 12, -20, -38, 10, -16, -11, -11, -6, 13, -22, -31, + 43, -42, 49, -33, 20, 17, 13, -22, 44, -21, -4, 14, 9, 33, 10, 0, + -1, 0, 0, -2, 11, 23, 22, 24, 25, 20, 21, 15, 40, -1, -24, -42, + -5, -19, -11, -8, 4, -46, -31, -14, -33, -40, -44, -48, -89, -63, -47, -33, + -27, -10, -6, 22, 25, 26, 28, 37, 11, 15, 51, 44, 54, 66, 66, 71, + 111, 84, 70, 63, 47, 39, 22, 47, -28, -79, -111, -90, -91, -112, -81, -87, + -49, -46, -5, -24, 26, 24, 47, 29, 23, 30, 30, 13, -1, 4, -14, 17, + 35, 62, 31, 53, 59, 72, 64, 27, 26, 9, 9, -61, -44, -88, -74, -81, + -83, -124, -96, -37, -78, -48, -56, -68, -60, 7, 44, 39, 54, 77, 102, 110, + 108, 89, 101, 100, 105, 64, 22, -1, 44, 40, -19, -29, -35, -16, -27, -40, + -77, -82, -113, -104, -93, -57, -72, -56, -3, 1, 7, -1, 49, 39, 30, 31, + 23, 10, 31, 11, 7, -19, -2, -2, 28, 62, 92, 75, 33, 34, -20, -47, + -61, -85, -105, -93, -119, -112, -54, -70, -67, -32, -1, 4, 4, 20, 29, 62, + 70, 54, 62, 78, 115, 92, 85, 78, 52, 21, 19, 27, 2, -8, 13, 0, + 5, 3, 9, 18, 0, -59, -61, -45, -57, -65, -76, -89, -102, -48, -24, 17, + 6, 26, 33, 35, 26, 41, 63, 20, 12, 29, 34, 8, 7, 31, 21, 31, + 39, 33, -5, -8, -55, -57, -98, -94, -88, -64, -82, -74, -39, -14, 3, 16, + 22, 8, 2, 17, 5, 36, 76, 74, 71, 57, 73, 62, 47, 30, 32, 19, + 4, 7, -14, -18, -2, 17, -5, 13, 22, 31, 10, 8, -13, -47, -80, -85, + -86, -71, -73, -60, -35, -10, 9, 19, 49, 53, 47, 60, 73, 43, 33, 20, + 13, -1, -7, -7, 7, 9, -2, 5, -14, -40, -69, -61, -66, -67, -84, -58, + -58, -33, 2, -7, -5, 12, 32, 18, 25, 19, 24, 65, 59, 62, 64, 63, + 55, 60, 52, 31, 19, -12, -26, -4, -7, -10, -3, 6, -22, -14, 12, 19, + 4, -26, -38, -40, -56, -61, -66, -59, -65, -51, -20, 29, 40, 51, 52, 62, + 61, 53, 26, 20, 6, 8, 6, 9, -14, -14, -15, -2, -11, -23, -36, -38, + -60, -77, -69, -60, -51, -56, -44, -27, 10, -2, 14, 10, 22, 16, 41, 60, + 39, 35, 60, 62, 43, 45, 63, 52, 17, 12, 15, -1, -2, 0, -38, -48, + -32, -22, -7, 3, 13, 10, -2, -1, -8, -12, -25, -48, -46, -52, -49, -36, + -17, 9, 17, 26, 48, 57, 55, 69, 60, 32, 6, 4, -6, -20, -24, -9, + -21, -25, -14, -18, -38, -38, -32, -51, -52, -60, -34, -6, -6, -16, -11, -2, + -1, 17, 19, 3, 11, 25, 31, 41, 39, 33, 33, 41, 34, 34, 23, 21, + 15, 6, -13, -24, -28, -20, -8, -12, -19, -12, -5, 9, 14, 2, -12, -25, + -28, -21, -28, -23, -22, -18, -26, -5, 24, 45, 46, 47, 39, 33, 36, 42, + 29, 7, -5, -10, -21, -29, -39, -39, -31, -24, -29, -39, -51, -43, -27, -22, + -18, -25, -26, -20, 9, 19, 18, 4, -2, 19, 30, 38, 25, 24, 28, 33, + 41, 38, 34, 32, 38, 24, 8, 4, -8, -11, -15, -25, -31, -25, -20, -22, + -15, -11, -9, -12, -17, -20, -20, -15, -6, -11, -8, 0, 11, 29, 19, 17, + 17, 18, 28, 31, 25, 18, 23, 18, 10, 1, -7, -18, -26, -24, -30, -41, + -38, -44, -32, -31, -31, -35, -25, -12, -2, -8, -11, -13, -13, -2, 8, 15, + 19, 29, 35, 37, 39, 43, 42, 40, 35, 27, 25, 18, 15, 9, 4, -4, + -15, -28, -28, -26, -28, -18, -15, -25, -23, -12, -11, -14, -10, -2, -4, -1, + 8, 15, 19, 22, 25, 16, 16, 17, 5, 7, 13, 18, 13, 9, 6, 6, + 4, -4, -21, -31, -28, -37, -39, -34, -38, -38, -32, -17, -6, -4, -14, -19, + -9, 3, -2, 3, 4, 7, 8, 13, 23, 35, 38, 43, 42, 31, 25, 23, + 17, 8, 3, 4, -7, -7, -10, -13, -20, -19, -28, -33, -30, -23, -18, -13, + -17, -12, 3, 14, 23, 31, 27, 23, 21, 22, 19, 12, 4, 2, 2, -2, + 0, 4, 11, 11, 6, 4, -2, -5, -14, -17, -30, -38, -44, -42, -28, -21, + -23, -21, -15, -15, -4, 8, 11, 4, -7, -15, -7, 5, 10, 21, 26, 28, + 27, 34, 37, 36, 28, 19, 10, 11, 8, -2, -18, -17, -19, -19, -22, -24, + -21, -24, -18, -17, -13, -19, -13, -1, 12, 19, 22, 21, 19, 19, 30, 34, + 24, 13, 7, 2, 1, 1, 2, -1, -2, -6, 0, 0, -2, -15, -21, -17, + -21, -28, -32, -31, -31, -32, -27, -24, -17, -4, 1, -3, -1, 1, 4, 7, + 8, 15, 16, 15, 15, 20, 32, 36, 38, 32, 19, 12, 3, 2, -2, -4, + -11, -19, -17, -15, -11, -16, -20, -27, -30, -28, -22, -13, -6, -2, 2, 12, + 23, 29, 45, 44, 36, 32, 21, 16, 14, 10, 1, -9, -8, -2, -1, -7, + -13, -13, -12, -9, -11, -18, -24, -26, -28, -30, -24, -21, -21, -21, -11, -11, + -10, 0, -2, 0, 4, 12, 13, 14, 12, 17, 22, 28, 30, 28, 20, 16, + 13, 8, 2, -2, -6, -15, -14, -18, -15, -15, -16, -18, -18, -16, -19, -18, + -17, -10, 0, -1, 4, 13, 22, 37, 39, 36, 27, 27, 32, 26, 15, 6, + -1, -4, -5, -7, -11, -11, -9, -15, -15, -14, -18, -21, -19, -17, -21, -19, + -15, -15, -10, -15, -14, -12, -11, -6, -2, 1, -2, 1, 5, 14, 22, 33, + 35, 23, 18, 16, 13, 11, 6, 1, -9, -18, -11, -6, -7, -8, -9, -11, + -11, -12, -13, -17, -21, -24, -24, -15, -4, 7, 12, 17, 25, 30, 28, 31, + 32, 31, 27, 22, 15, 12, 3, -2, -8, -6, -3, -9, -13, -22, -24, -20, + -18, -22, -24, -18, -14, -13, -10, -11, -9, -3, -2, -3, -5, -10, -10, -5, + -1, 4, 11, 15, 19, 22, 27, 23, 20, 16, 14, 5, -3, -11, -15, -16, + -12, -12, -11, -5, 1, -3, -10, -13, -15, -11, -10, -10, -11, -8, -3, 2, + 7, 9, 15, 25, 30, 33, 31, 25, 21, 20, 16, 13, 7, -2, -8, -5, + -4, -11, -20, -21, -22, -21, -17, -20, -21, -22, -19, -19, -11, -4, -2, -2, + -2, 2, 5, 2, 0, 0, -3, 1, 8, 16, 13, 14, 17, 15, 13, 8, + 5, -1, -6, -10, -13, -14, -14, -13, -10, -7, -8, -8, -6, -6, -3, -1, + -1, -9, -12, -7, 3, 13, 17, 14, 13, 17, 22, 23, 24, 18, 15, 18, + 18, 18, 15, 8, 0, -5, -8, -11, -15, -17, -21, -26, -26, -24, -26, -24, + -13, -9, -6, -3, -2, 3, 4, 6, 7, 5, 2, 4, 2, -2, -4, -3, + 5, 13, 17, 10, 3, -1, -2, -4, -5, -11, -14, -13, -11, -8, -8, -8, + -6, -3, 0, -1, -5, -5, 0, 4, 3, 1, 2, 0, 0, 6, 13, 20, + 17, 17, 18, 21, 18, 14, 13, 11, 11, 7, 9, 3, -5, -12, -14, -18, + -21, -23, -26, -26, -13, -3, -6, -13, -14, -5, 5, 8, 3, 0, 1, 3, + 6, 4, -1, -1, 1, 3, 7, 5, 3, 0, 1, -1, 3, 0, -3, -11, + -11, -9, -10, -9, -8, -5, -7, -7, -10, -9, -6, -1, 4, 6, 4, 2, + 5, 10, 13, 9, 12, 13, 14, 15, 16, 13, 12, 10, 13, 14, 13, 8, + 2, -1, -4, -6, -9, -15, -20, -21, -19, -14, -16, -22, -21, -13, -5, -3, + -3, -1, 3, 5, 10, 9, 9, 6, 8, 7, 7, 7, 3, -4, -6, -4, + -1, -4, -8, -10, -11, -8, -4, -6, -10, -7, -8, -11, -11, -8, -5, -4, + 0, 3, 3, 8, 10, 10, 12, 12, 11, 10, 13, 12, 10, 6, 8, 9, + 9, 11, 13, 11, 9, 10, 7, 2, -3, -8, -9, -14, -16, -16, -19, -18, + -14, -13, -11, -11, -10, -5, -1, 3, 5, 2, 2, 9, 14, 11, 9, 10, + 7, 2, 0, 2, -2, -9, -13, -15, -18, -17, -15, -13, -10, -5, -5, -7, + -7, -4, -1, 0, -2, -4, -2, 1, 4, 9, 10, 10, 11, 11, 13, 14, + 10, 11, 9, 9, 4, 6, 5, 4, 5, 7, 8, 10, 9, 4, -4, -8, + -9, -10, -11, -12, -14, -15, -17, -15, -9, -4, -1, -6, -5, 2, 8, 8, + 6, 5, 3, 4, 5, 9, 10, 10, 5, -1, -5, -10, -12, -14, -16, -18, + -17, -11, -10, -11, -8, -5, -2, -2, 0, 3, 4, 5, 3, 2, 3, 5, + 9, 12, 12, 11, 10, 12, 14, 12, 8, 5, 0, -1, 1, 3, 0, 1, + 3, 5, 6, 5, 0, -5, -11, -10, -13, -12, -13, -15, -14, -8, -4, -3, + -3, -4, 0, 4, 5, 3, 6, 4, 4, 7, 10, 9, 9, 8, 5, 5, + 2, -4, -10, -15, -17, -20, -22, -22, -19, -14, -11, -10, -8, -6, 0, 3, + 5, 3, 4, 8, 11, 11, 12, 13, 12, 12, 15, 15, 16, 16, 13, 11, + 6, 3, -2, -5, -5, -3, -2, -1, 2, 0, -3, -4, -5, -7, -10, -12, + -11, -12, -11, -8, -4, -2, 0, 1, 2, 2, 2, 4, 3, 3, 4, 5, + 9, 10, 6, 2, 1, 2, 0, -3, -7, -13, -18, -19, -18, -16, -18, -20, + -19, -14, -8, -4, -1, 3, 3, 5, 7, 9, 9, 10, 12, 13, 13, 13, + 13, 16, 15, 13, 9, 6, 3, 2, 1, 0, -3, -5, -6, -4, -2, -2, + -4, -4, -5, -5, -3, -3, -4, -6, -6, -7, -4, 0, 2, 3, 2, 2, + 1, 2, 2, 1, 4, 5, 4, 1, 0, 2, 2, 0, -2, -6, -8, -6, + -7, -9, -11, -15, -18, -19, -18, -18, -17, -13, -9, -2, 2, 3, 5, 10, + 12, 13, 14, 14, 15, 17, 17, 16, 16, 15, 13, 11, 7, 2, -6, -10, + -8, -6, -8, -8, -7, -6, -6, -3, -4, -6, -5, -3, -2, -2, 0, 1, + 0, 2, 2, 3, 2, 3, 2, 3, 3, 5, 2, 0, 4, 6, 5, -1, + -4, -2, -1, -2, -6, -8, -9, -10, -12, -10, -14, -17, -22, -22, -21, -19, + -15, -8, -3, 1, 7, 12, 12, 15, 19, 22, 21, 18, 16, 16, 16, 13, + 12, 6, 3, 3, 2, -3, -6, -7, -12, -12, -11, -8, -9, -8, -7, -3, + 0, 0, 0, 0, -2, -2, 0, 1, 2, 2, 4, 6, 6, 7, 5, 4, + 3, 4, 5, 3, 0, -2, -2, -4, -6, -10, -8, -8, -10, -11, -12, -12, + -12, -13, -16, -16, -16, -14, -11, -8, -4, -2, 1, 6, 12, 17, 19, 20, + 20, 21, 21, 19, 13, 10, 9, 5, 0, -3, -4, -4, -5, -6, -6, -4, + -7, -10, -12, -12, -12, -10, -7, -4, -2, 4, 6, 8, 7, 7, 7, 7, + 8, 8, 7, 5, 6, 6, 4, 1, -1, -1, 0, -3, -7, -10, -10, -8, + -11, -14, -14, -12, -11, -9, -6, -8, -8, -8, -11, -13, -12, -9, -8, -5, + 0, 4, 8, 11, 14, 18, 18, 20, 23, 23, 20, 14, 9, 4, 0, -3, + -6, -8, -8, -8, -8, -9, -10, -11, -10, -9, -8, -8, -7, -6, -3, 0, + 3, 6, 12, 16, 16, 14, 10, 8, 9, 7, 4, 1, 0, 0, -2, -1, + 0, 0, -3, -7, -10, -13, -13, -12, -13, -15, -14, -13, -9, -6, -5, -5, + -7, -8, -9, -7, -6, -5, -7, -5, 1, 8, 13, 17, 19, 20, 21, 22, + 22, 18, 12, 9, 5, -1, -5, -9, -11, -13, -12, -12, -11, -10, -8, -7, + -7, -6, -7, -6, -3, 0, 1, 3, 7, 10, 11, 12, 15, 15, 14, 9, + 6, 3, 1, 0, -2, -2, -2, -3, -6, -8, -10, -11, -13, -15, -15, -15, + -13, -12, -12, -7, -5, -5, -5, -4, -3, -3, -4, -4, -1, -1, 1, 4, + 7, 10, 12, 14, 17, 20, 22, 19, 14, 8, 5, 2, -2, -5, -10, -14, + -13, -11, -10, -10, -10, -10, -8, -6, -3, -3, -3, -1, -1, 2, 6, 10, + 13, 14, 15, 15, 15, 13, 11, 8, 5, 1, -1, -3, -3, -6, -10, -12, + -12, -12, -12, -13, -15, -18, -19, -15, -11, -6, -4, -3, -4, -4, -2, 1, + 4, 2, -1, -2, 1, 4, 6, 8, 7, 7, 11, 14, 15, 15, 15, 13, + 10, 6, 1, -3, -6, -9, -13, -15, -15, -13, -11, -9, -9, -9, -7, -3, + 0, 2, 2, 4, 7, 11, 15, 16, 14, 11, 12, 13, 15, 13, 9, 4, + 1, -1, -4, -6, -8, -11, -15, -17, -17, -17, -17, -15, -13, -13, -12, -10, + -7, -6, -4, 1, 2, 2, 3, 4, 5, 4, 4, 3, 5, 6, 6, 8, + 7, 7, 9, 11, 10, 9, 8, 5, 2, 0, -2, -6, -10, -13, -13, -14, + -14, -13, -11, -9, -4, -1, -1, -1, 2, 6, 8, 10, 11, 12, 14, 14, + 14, 13, 11, 10, 7, 4, 2, 3, 1, -3, -6, -10, -14, -17, -18, -18, + -19, -19, -17, -15, -13, -9, -5, -1, 1, 0, 1, 3, 5, 6, 6, 6, + 7, 8, 9, 8, 4, 1, 0, 2, 4, 5, 6, 5, 4, 4, 4, 3, + 1, -3, -7, -9, -11, -12, -12, -12, -11, -10, -7, -4, -2, 1, 4, 5, + 8, 11, 13, 14, 14, 11, 11, 11, 10, 10, 9, 6, 5, 3, 1, -2, + -5, -10, -14, -16, -17, -18, -19, -20, -19, -17, -14, -10, -5, -1, 1, 3, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 8, 7, 6, 4, 2, 0, -1, + 0, 0, 1, 2, 1, 1, 2, 1, -2, -5, -8, -9, -10, -11, -12, -12, + -10, -7, -4, -1, 2, 8, 11, 13, 15, 15, 13, 12, 11, 10, 9, 8, + 6, 5, 4, 4, 3, 0, -3, -6, -10, -14, -18, -21, -22, -21, -18, -16, + -13, -10, -6, -3, 0, 3, 5, 5, 5, 6, 7, 8, 8, 8, 7, 8, + 7, 6, 5, 4, 1, 0, -2, -4, -4, -5, -4, -4, -3, -2, -1, -2, + -3, -4, -7, -8, -9, -9, -9, -8, -5, -2, 2, 4, 8, 11, 14, 15, + 15, 14, 12, 10, 7, 5, 4, 4, 2, 1, 1, 2, -1, -3, -7, -10, + -15, -18, -18, -18, -18, -17, -15, -11, -7, -3, 1, 3, 4, 5, 6, 7, + 7, 8, 8, 9, 10, 10, 9, 6, 4, 2, 0, -3, -4, -6, -7, -7, + -6, -5, -3, -2, -2, -2, -2, -3, -4, -5, -6, -6, -6, -6, -5, -4, + -1, 4, 7, 9, 11, 12, 12, 11, 10, 9, 8, 7, 5, 3, 3, 2, + 1, 0, -1, -4, -7, -8, -10, -13, -14, -15, -15, -15, -14, -11, -9, -6, + -3, 0, 2, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 6, 5, 3, + 1, -3, -6, -8, -8, -7, -7, -7, -6, -4, -2, 0, -1, -2, -3, -3, + -3, -3, -4, -3, -3, -1, 1, 3, 4, 6, 7, 8, 9, 10, 10, 9, + 7, 6, 6, 4, 3, 2, 1, -1, -2, -4, -6, -9, -11, -12, -12, -12, + -11, -11, -10, -9, -8, -7, -5, -4, -1, 1, 3, 5, 7, 9, 10, 11, + 10, 9, 8, 7, 6, 2, -1, -3, -4, -6, -7, -7, -7, -7, -6, -5, + -5, -4, -3, -3, -4, -4, -4, -3, -2, 0, 0, 1, 1, 2, 4, 6, + 6, 7, 7, 8, 7, 7, 7, 7, 7, 6, 5, 2, 0, -2, -4, -5, + -7, -8, -8, -8, -9, -10, -10, -9, -8, -7, -7, -7, -5, -3, -2, 0, + 1, 2, 4, 6, 9, 10, 11, 12, 10, 8, 6, 3, 1, -2, -4, -6, + -7, -7, -7, -7, -8, -7, -7, -6, -6, -5, -4, -3, -3, -2, -1, 1, + 2, 2, 3, 4, 5, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 4, + 3, 2, 1, -1, -3, -4, -6, -8, -9, -9, -8, -8, -6, -5, -5, -5, + -6, -6, -6, -5, -4, -2, 0, 2, 4, 6, 7, 8, 9, 9, 9, 9, + 6, 4, 1, -1, -3, -5, -6, -7, -7, -7, -6, -6, -6, -6, -6, -5, + -4, -3, -3, -2, -1, 1, 3, 4, 5, 5, 5, 5, 5, 5, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 2, 1, -1, -3, -4, -5, -6, -7, -7, + -7, -7, -7, -6, -5, -4, -4, -3, -3, -3, -3, -2, -1, 0, 1, 3, + 5, 7, 8, 8, 8, 7, 6, 4, 2, 0, -2, -3, -4, -5, -6, -7, + -7, -7, -7, -6, -6, -5, -5, -5, -3, -2, 0, 1, 2, 3, 4, 5, + 6, 6, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 2, 1, 1, -1, + -2, -3, -4, -5, -6, -6, -7, -6, -5, -4, -3, -3, -3, -3, -3, -2, + -1, -1, 0, 1, 1, 1, 2, 3, 5, 6, 6, 6, 5, 4, 2, 1, + 0, -2, -4, -5, -5, -6, -6, -6, -7, -7, -7, -6, -5, -4, -3, -2, + -1, 0, 2, 3, 3, 4, 4, 5, 5, 5, 4, 4, 4, 4, 3, 3, + 2, 1, 1, 0, 0, -1, -1, -2, -3, -4, -5, -5, -5, -5, -5, -4, + -4, -3, -3, -2, -1, -1, -1, -1, 0, 0, 0, 1, 2, 3, 3, 4, + 4, 4, 4, 4, 3, 1, 0, 0, -2, -3, -4, -5, -5, -6, -6, -6, + -5, -4, -4, -4, -3, -2, -2, -1, 0, 2, 3, 3, 4, 4, 4, 4, + 3, 3, 3, 3, 2, 2, 1, 1, 1, 0, -1, -1, -2, -3, -3, -3, + -3, -3, -3, -3, -3, -3, -3, -2, -2, -2, -1, -1, -1, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 0, 0, -1, -1, + -2, -3, -3, -3, -4, -4, -4, -4, -3, -3, -2, -1, -1, -1, 0, 1, + 1, 1, 2, 2, 2, 3, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, -8, -33, -24, -25, -25, -26, -27, -32, -28, -36, -31, -36, -22, -34, + 11, -74, -14, 94, 41, 28, 33, 30, 40, 34, 23, 41, 40, 60, 56, 59, + 60, 44, 39, 54, 45, 52, 17, 44, 62, 34, 33, 19, 18, 43, 35, 22, + 36, -15, -10, 32, -7, -12, -6, -8, -50, -47, -44, -4, -25, -48, -76, -58, + -75, -96, -85, -118, -114, -63, -106, -103, -83, -110, -99, -84, -76, -58, -63, -61, + -51, -53, -36, -32, -41, -27, -11, 11, 8, 27, 19, 30, 35, 28, 57, 53, + 38, 71, 51, 68, 110, 78, 89, 109, 97, 82, 94, 115, 114, 79, 70, 79, + 94, 85, 76, 84, 95, 83, 82, 55, 54, 54, 41, 41, 27, 20, 6, -11, + -21, -16, -14, -33, -33, -52, -54, -59, -62, -71, -79, -88, -88, -78, -78, -72, + -71, -94, -99, -93, -90, -78, -87, -105, -103, -79, -62, -71, -78, -63, -61, -66, + -49, -23, -10, -11, -24, -20, -4, -22, 9, 8, 27, 43, 34, 38, 51, 83, + 65, 58, 74, 75, 70, 73, 71, 65, 100, 89, 94, 65, 84, 49, 49, 61, + 54, 43, 51, 58, 53, 35, 40, 36, 38, 34, 23, 14, -12, -10, -1, -1, + -11, -12, -19, -33, -66, -52, -42, -37, -55, -42, -28, -32, -29, -35, -41, -28, + -25, -46, -85, -64, -62, -55, -49, -68, -55, -53, -52, -47, -43, -26, -32, -41, + -34, -35, -40, -26, -8, -1, -6, -11, 5, -2, 8, 3, 8, 6, 4, 20, + 29, 43, 24, 33, 20, 30, 24, 39, 38, 40, 29, 37, 36, 39, 61, 58, + 41, 51, 59, 51, 55, 58, 48, 32, 45, 40, 27, 30, 41, 44, 26, 19, + 23, -3, 7, 0, -3, 2, 3, -6, -5, -14, -6, -10, -27, -45, -47, -41, + -38, -50, -51, -46, -43, -45, -65, -65, -80, -95, -82, -74, -66, -69, -67, -33, + -31, -53, -48, -51, -43, -18, -24, -24, -33, -26, -10, 0, -17, -6, 17, 31, + 2, 23, 45, 46, 12, 75, 38, 63, 69, 31, 38, 80, 57, 48, 59, 81, + 74, 32, 52, 72, 24, 60, 44, 55, 40, 28, 48, 33, 24, 10, -2, 21, + 34, 13, 18, 7, -1, -12, -20, -18, -30, -9, -7, -30, -27, -26, -38, -20, + -54, -55, -64, -53, -36, -62, -37, -71, -47, -42, -71, -45, -55, -50, -54, -56, + -36, -37, -54, -36, -12, -38, -33, -26, -7, -22, -44, -10, 2, 3, 15, 8, + 18, 6, 12, 8, 15, 28, 22, 50, 35, 55, 42, 36, 49, 52, 64, 48, + 60, 49, 60, 62, 40, 47, 68, 52, 59, 61, 44, 53, 44, 35, 31, 31, + 47, 22, 6, 4, -7, 5, -4, -21, -13, -9, -10, -27, -46, -32, -44, -46, + -62, -44, -51, -67, -53, -59, -63, -74, -67, -61, -61, -65, -47, -58, -57, -45, + -41, -46, -41, -38, -22, -25, -34, -16, -10, -18, 0, 1, -6, 5, 17, 15, + 10, 23, 38, 28, 28, 54, 40, 19, 55, 55, 41, 46, 53, 40, 49, 51, + 52, 41, 56, 39, 53, 38, 33, 35, 18, 15, 38, 30, 23, 27, 13, 11, + 7, 16, -1, 0, 0, 13, -6, -10, -15, -10, -10, -24, -20, -16, -38, -36, + -21, -40, -32, -42, -38, -52, -53, -41, -48, -58, -50, -47, -37, -41, -45, -29, + -41, -6, -48, -24, -25, -15, -9, -10, -10, -10, -1, -17, 4, 3, 10, -4, + 9, 15, 25, 24, 19, 23, 34, 28, 33, 37, 38, 26, 36, 47, 35, 46, + 45, 28, 35, 32, 32, 24, 21, 26, 23, 19, 37, 20, 9, 29, -2, 26, + 24, 8, 4, 14, 21, 11, -9, -8, 4, -9, -31, -11, -15, -21, -24, -29, + -22, -33, -26, -29, -48, -32, -44, -28, -22, -35, -30, -38, -31, -46, -44, -36, + -27, -23, -29, -24, -11, -20, -28, -13, -34, -19, -1, 7, -3, -1, 6, -3, + 5, 4, 8, 17, 26, 19, 33, 27, 16, 35, 14, 36, 39, 22, 32, 31, + 19, 32, 23, 29, 21, 30, 29, 23, 31, 13, 24, 17, 11, 26, 18, 12, + 5, 23, 16, 9, 15, -10, 3, 18, -15, -4, -4, 6, -14, -15, -5, -34, + -11, -20, -18, -8, -17, -29, -30, -29, -19, -34, -35, -20, -36, -20, -16, -21, + -38, -16, -30, -24, -25, -19, -18, -15, -7, -5, -5, -10, -23, -3, -14, 0, + -1, -12, -9, 7, 7, 2, 12, 5, 7, 19, 10, 21, 21, 27, 30, 22, + 18, 34, 22, 11, 26, 24, 20, 21, 25, 29, 22, 27, 27, 20, 10, 20, + 16, 22, 15, 16, 16, 5, 19, 10, 3, 22, -5, -5, -7, -16, -4, -11, + -22, -7, -16, -11, -23, -16, -30, -24, -28, -20, -29, -24, -32, -22, -22, -30, + -17, -23, -28, -22, -20, -21, -21, -17, -30, -15, -14, -20, -9, 3, 6, 5, + -20, 10, 13, -2, 11, 8, -1, 7, 16, 5, 22, 23, 13, 22, 13, 22, + 25, 15, 16, 11, 15, 13, 7, 12, 19, 18, 20, 12, 23, 11, 6, 10, + 1, 11, 19, 5, 20, 0, 11, 11, 1, 14, 15, -3, -1, -7, 6, -6, + -9, -9, 4, -3, -10, -20, -14, -9, -14, -7, -10, -5, -4, -29, -14, -12, + -26, -21, -27, -18, -10, -19, -27, -18, -8, -25, -8, -13, -15, -14, -15, 5, + -13, -7, -11, -4, -12, 0, 15, 5, 4, 1, 11, 6, 4, 3, 6, 21, + 19, 8, 15, 13, 6, 14, 16, 18, 17, 20, 15, 11, 15, 24, 13, 11, + 19, 7, 17, 14, 6, 17, 7, 7, 6, 6, 5, 11, 0, 6, 0, -6, + 5, 1, -11, -6, -1, -8, -9, -15, -7, -4, -16, -17, -13, -13, -17, -14, + -12, -12, -28, -13, -19, -25, -31, -24, -17, -17, -16, -7, -15, -12, -8, -15, + -8, -16, -10, -4, -1, -2, 3, 5, 2, -2, 5, 3, 6, 10, 8, 11, + 14, 14, 13, 15, 22, 16, 14, 18, 13, 17, 19, 16, 10, 17, 8, 17, + 14, 3, 14, 7, 10, 10, 7, 6, 6, -1, 6, 1, 0, 12, -6, 6, + 12, -4, -5, -4, -2, -2, -1, -2, -8, -11, -9, -11, -11, -18, -6, -5, + -16, -9, -14, -10, -13, -10, -11, -15, -14, -14, -12, -17, -17, -17, -7, -11, + -14, -15, -12, -6, -15, -5, -13, -9, 0, 12, -2, -2, 6, 2, -7, 4, + 10, 2, 9, 8, 7, 4, 5, 11, 15, 11, 10, 18, 9, 13, 13, 13, + 21, 11, 18, 19, 13, 14, 16, 6, 8, 1, 19, 11, 10, 11, 1, 3, + -1, -1, 5, -11, 5, -1, -5, -3, -13, -10, -6, -7, -5, -15, -10, -11, + -18, -8, -16, -20, -18, -9, -12, -17, -21, -21, -13, -21, -8, -10, -10, -5, + -16, -7, 2, -6, -6, -9, -7, -2, -9, -5, 6, -7, 1, 3, -1, 2, + 1, 2, 9, 8, 5, 15, 12, 1, 11, 9, 8, 10, 15, 14, 5, 13, + 17, 14, 15, 10, 7, 16, 5, 5, 5, 8, 9, 10, 10, 7, 0, 4, + 6, 9, -10, -4, 5, 2, -1, 0, -3, -4, -5, -10, -5, -8, -9, -10, + -3, -13, -6, -9, -20, -15, -11, -18, -14, -10, -12, -20, -14, -14, -7, -12, + -21, -14, -9, -8, -11, -5, -2, -7, -4, 4, -2, -3, -1, 0, -1, 8, + 6, 9, 7, 10, 6, 3, 4, 7, 10, 11, 6, 9, 17, 11, 9, 7, + -2, 16, 13, 12, 18, 5, 16, 9, 4, 9, 6, 8, 9, 4, 4, 3, + -2, -3, 2, -6, -3, 1, -7, -6, -3, -6, -14, -8, -9, -4, -13, -9, + -8, -16, -10, -12, -13, -11, -7, -8, -12, -9, -8, -7, -11, -4, -8, -7, + -8, -3, -13, -10, -3, 6, -5, -5, 0, -5, -3, 6, -2, -2, 4, -2, + 6, 2, -2, 5, 5, -2, 5, 15, 13, 4, 6, 6, 14, 9, 4, 8, + 7, 3, 11, 12, 2, 10, 7, 10, 8, 4, 6, 2, 0, 3, 2, 4, + 2, -6, -2, 2, -4, 3, -5, -6, -5, -5, -5, -4, -8, -7, -4, -4, + -7, -8, -7, -13, -10, -10, -11, -9, -8, -8, -7, -11, -7, -3, -9, -6, + -7, -3, -4, -5, 3, -3, -1, -2, -4, 1, 4, 0, 3, 0, 5, 2, + 0, 5, 4, 1, 3, 1, 0, 1, 7, 3, 0, 4, 3, 6, 5, 0, + 9, 5, 7, 6, 3, 6, 2, 3, 5, -4, 9, 0, 4, 10, 0, 5, + 1, -2, 4, -3, -3, -2, 0, 2, -7, 3, -10, -1, -6, -9, -2, -4, + -10, -3, -7, -6, -4, -10, -6, -6, -11, -6, 0, -6, -8, -4, -1, -9, + -10, 0, -6, -7, -2, -7, 1, -5, -5, -1, 1, -6, 2, 0, -3, -1, + 7, -4, 0, 7, 0, 8, 2, 3, 4, 4, 2, 5, -1, 6, 7, 5, + 6, 4, 2, 4, 6, 8, 6, 3, 1, 8, 9, 2, -1, 4, 3, 4, + 3, -3, 7, 4, 3, -2, 2, -4, -6, -2, -5, -2, -3, 0, -5, -6, + -13, -5, -6, -11, -9, -10, -5, -4, -9, -9, -7, -7, -8, -8, -6, -5, + -7, -5, -1, -3, -4, -2, -2, 2, -3, 1, 2, -3, 1, 2, 1, 0, + 1, 5, 0, 2, 5, 2, 0, 4, 1, 7, 3, 2, 6, 0, 5, 7, + 5, 5, 1, 3, 3, 5, 10, 3, 4, 8, 2, 7, 3, -2, 3, 0, + -1, -1, 1, 0, 1, -3, -2, -5, -4, -3, -1, -7, -8, -4, -4, -10, + -2, -8, -8, -8, -8, -9, -6, -8, -9, -4, -2, -7, -5, -2, -7, -6, + -9, -2, 0, -4, 4, -6, -3, -4, -1, 2, 1, 2, 9, 0, 3, 0, + 6, 4, 0, 5, 6, 2, 7, 7, 5, 7, 6, 8, 6, 6, 5, 5, + 1, 6, 5, -1, 3, 4, -1, 4, 1, 4, 3, -5, 0, 4, 1, 4, + -2, -3, -4, 0, -4, -8, -2, -5, -4, -8, -6, -5, -3, -3, -7, -9, + -6, -10, -10, -6, -6, -5, -4, -7, -6, -4, -10, -3, -10, 0, -2, -2, + -6, -1, 3, -3, -3, 1, 2, 1, 4, 3, 4, 3, 4, 1, 2, 6, + 5, 5, 5, 7, 9, 1, 5, 4, 4, 7, 2, 9, 2, 4, 8, 2, + 5, 6, 3, -2, -2, -1, -2, -1, 1, -2, -4, 1, -6, -2, -5, -3, + -5, -5, -6, -4, -3, -4, -10, -4, -3, -8, -4, 0, -3, -5, -6, -6, + -3, -1, -7, -3, 1, -1, -4, -2, 1, -2, 0, -1, -2, 0, 0, 5, + -2, 0, 3, 3, 1, 5, 2, 4, 1, 4, 1, 2, 3, 3, 3, 4, + 3, 3, 5, 1, 4, 2, 3, 1, 2, 0, 2, 1, -2, -2, -1, 0, + -2, -1, -1, -3, -5, -2, 0, -5, -1, 0, -5, -2, -2, -2, -3, -3, + -1, -4, -1, -2, -4, -2, -1, -2, -1, 0, -3, -1, -1, 0, 1, -1, + -1, 3, -4, -2, -2, 4, -2, -1, -1, -1, 0, 0, -1, -1, -1, -1, + 2, 0, -1, 2, -1, 0, -1, 2, 0, 3, 5, -2, 1, 2, 0, 5, + 0, -3, 4, -3, 1, 2, 0, 4, -1, -2, 1, 0, 0, 0, -1, 1, + -2, 0, 1, 1, 0, -5, 1, -2, -1, 0, -2, -3, -1, -3, 0, -2, + -3, -4, 1, -2, -3, -2, -2, -1, -1, -2, -1, -4, -5, 2, -4, 0, + 1, -1, 2, -2, -1, 0, 0, 1, -3, 3, 2, 0, -2, 2, 1, 2, + -2, 5, 3, -2, -2, -1, 1, 0, 0, 1, 3, 2, 0, 0, -1, -2, + 1, 1, 2, 1, 1, -1, 0, -1, -1, -1, -3, 1, 1, 2, -2, -1, + 0, 0, -2, 0, -1, -1, 2, -2, 1, -1, 0, 0, -1, -1, -2, 0, + -1, 1, -1, -1, 2, -2, 0, -1, -1, 2, -1, 0, -3, -1, 0, 0, + 0, -3, -3, -2, 0, 0, -1, -1, 0, -4, 2, 0, -2, 0, 1, -3, + -1, 2, 1, 0, -1, 0, 0, -1, 0, 2, -1, -1, 0, 0, -2, 1, + 1, 0, 1, 0, 2, -3, -2, 2, -1, -1, 2, -2, 1, 1, 0, 0, + 1, 1, 0, -4, 3, -1, 2, 0, 2, -1, -2, 0, 1, 1, -1, -1, + -1, -1, -1, -2, -2, -2, -2, -2, -1, -1, 1, 0, -5, 0, -1, -1, + -1, 1, -1, 1, -1, 1, 0, -2, 0, -2, 1, -1, 1, 0, -1, -2, + 0, -1, 0, 0, 2, 0, 0, 0, 1, 0, 0, 2, 0, -1, 0, 0, + 0, 2, -1, 1, 1, -1, -1, 0, 0, 1, 1, 0, 0, 0, 0, -1, + 0, 0, -2, 0, 0, -1, 1, -2, -1, -1, -1, -2, -1, -2, 1, -1, + 0, -2, -2, 1, -2, -1, 1, 0, 1, 1, -1, -1, 0, -1, 0, 0, + 0, -2, 0, -1, 0, 0, -1, -2, -2, -2, 1, -1, 0, 0, -1, 1, + 1, -2, -1, -2, -1, 1, -1, -1, -2, -2, 0, 0, 1, -1, -1, -1, + -1, -2, 2, 0, 0, 1, 1, 1, -2, 0, -1, 0, -1, -1, 2, 0, + -1, -1, -1, 1, -1, 2, 0, -1, 1, 1, 0, 1, 0, -1, -1, -1, + -1, -3, 0, 0, -1, 1, 0, 0, -2, -2, -2, 0, -1, 0, 0, -1, + 0, -1, -2, -1, -2, 0, -2, 0, 0, -1, -2, 1, -2, 0, -1, -2, + 2, 0, -1, 2, -1, 1, -1, 0, 0, -1, 0, 0, 0, -1, 0, 1, + 0, 0, 1, 0, -1, -1, 0, -2, -1, 0, 0, 1, 0, 0, 0, 0, + -1, -1, 1, -1, -2, -1, 0, 0, -2, 0, -1, 0, 0, 0, 1, 0, + 0, -1, 1, 0, -1, 0, 1, -1, 0, -1, -2, 0, -1, 0, -1, -1, + -1, 0, -1, 0, 0, 0, -1, -1, 0, -2, 0, 0, 0, -2, -2, 0, + -2, -1, -1, -1, -2, 0, -1, -1, -1, 0, 0, -1, -1, 0, 1, -1, + -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, + -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0, + -1, 0, -1, -1, 0, -2, -1, 0, -1, -1, -1, -1, 0, -1, 0, 0, + 0, 0, -1, 1, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, 0, + 0, -1, -1, 0, -1, -1, 0, 0, -1, 0, -2, 0, -1, -1, -1, 0, + -1, -1, 0, -1, 0, 0, 0, -2, -1, 0, -1, -1, 0, 1, -1, -1, + 0, 0, 0, 0, -1, -1, -1, -1, 0, 1, 0, 0, 0, 0, 0, -1, + 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, -1, -1, 0, + 0, -1, -1, 0, -1, 0, 0, 0, -1, 0, -1, -1, 0, -2, -1, -1, + -1, 0, -1, 0, -1, -1, 0, 0, -1, 0, -1, 0, -1, -1, -1, 0, + -1, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, -1, 0, 0, 0, -1, + 0, -1, 0, 1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, + 0, -1, -1, 0, 0, 0, -1, 0, 1, -1, -1, -1, 0, 0, -1, -1, + -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, + -1, 0, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, + 0, -1, 0, 0, -1, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, -1, + -1, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, + 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, + -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, + -1, -1, 0, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0, -1, -1, -1, + -1, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, + 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, + 0, -1, 0, -1, 0, 0, -1, -1, -1, 0, -1, -1, 0, -1, -1, 0, + 0, -1, -1, -1, -1, 0, -1, -1, 0, 0, -1, 0, 0, 0, -1, -1, + 0, -1, -1, -1, 0, 0, -1, -1, -1, -1, -1, 0, -1, 0, 0, -1, + -1, 0, 0, -1, 0, 0, -1, -1, -1, 0, -1, 0, 0, -1, -1, 0, + 0, -1, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, -1, 0, -1, 0, + -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, 11, -3, 47, -12, -15, -34, 3, 12, 38, 5, -24, -26, -9, -12, + 63, -18, 12, -17, -50, 34, -6, 40, -2, -8, -37, -6, 9, 12, 32, -4, + -33, 2, -33, 35, 20, 6, -11, -33, -11, 12, 23, 30, -21, -13, -28, -6, + 33, 14, 7, -18, -22, -11, 18, 23, 5, -4, -22, -30, 29, -11, 40, -12, + -15, -5, -11, 16, 13, -9, 5, -19, 3, 4, 2, 19, -28, 24, -41, 40, + -9, -8, 4, -29, 28, -1, 22, -16, -32, 16, -22, 45, 19, -45, 17, -54, + 25, 28, 33, -19, -30, -21, -25, 83, -20, 15, -3, -74, 12, 33, 4, 53, + -26, -57, -9, 0, 36, 33, 8, -67, -2, -17, 27, 55, -17, -11, -31, -23, + 24, 22, 6, 19, -55, 27, -48, 55, -8, 14, 7, -61, 26, -25, 34, 32, + -26, 11, -50, 5, 14, -1, 67, -75, 47, -79, 29, 15, 8, 42, -49, 2, + -34, -3, 51, -23, 52, -33, -32, -7, -14, 52, 6, 29, -73, 5, -9, -2, + 64, -39, -6, 25, -60, 30, 5, 16, -13, 40, -61, 7, 20, -50, 75, -36, + 10, -12, -4, -17, 23, 16, -18, 31, -38, -21, 33, -37, 56, -11, -5, -1, + -43, 43, -56, 93, -67, 40, -17, -46, 60, -56, 62, -24, 14, -18, -23, 9, + -16, 44, 19, -53, 58, -124, 81, -18, 32, 26, -43, -23, -28, 42, 1, 60, + -27, -61, 14, -37, 42, 64, -32, -2, -43, -31, 25, 59, -7, -1, -19, -73, + 51, 23, 18, 7, -24, -65, 29, 18, -2, 57, -47, -27, 4, -2, 16, 41, + -25, -47, 36, -51, 49, 24, -37, 13, -15, -11, 12, 26, -58, 52, -20, -16, + 31, -24, -20, 52, -16, -9, 32, -69, 5, 48, -34, 52, -12, -59, 20, -10, + 30, 16, 21, -75, 1, 8, -33, 126, -57, 9, -37, -49, 32, 24, 62, -59, + 19, -85, -2, 91, -23, 65, -49, -75, 19, -16, 68, 9, 16, -77, -3, 3, + -13, 111, -69, 17, -30, -59, 56, 1, 19, 23, -26, -21, -24, 25, -31, 97, + -59, 4, -16, -34, 40, 17, 16, -24, -6, -40, 26, 17, 3, 4, -23, -3, + -1, 23, -8, 6, -29, -2, 21, -13, 22, -11, -31, 40, -35, 48, -27, 7, + -39, 4, 28, -12, 55, -68, 9, -9, 2, 51, -21, -20, -18, -15, 33, 20, + 15, -57, 41, -78, 72, -2, -7, 13, -60, 11, 13, 49, -19, 10, -55, -23, + 59, -6, 22, 2, -79, 40, -11, 46, -11, 11, -66, 13, 24, -24, 80, -65, + 5, -22, 1, 19, 23, -8, -27, -11, 2, 0, 64, -61, 21, -52, 34, 23, + 7, -1, -51, 21, -41, 86, -45, 49, -62, -6, 0, 11, 51, -33, 16, -62, + -1, 23, 8, 62, -45, -35, 7, -39, 88, -54, 70, -86, 33, -27, -1, 61, + -60, 58, -62, 10, 15, -28, 65, -48, 11, -2, -44, 78, -64, 75, -78, 26, + -29, 22, 40, -30, 16, -53, -12, 56, -15, 48, -51, -22, -10, 9, 52, -20, + 40, -92, 16, -3, 26, 43, -19, -35, -31, 15, 13, 49, -11, -34, -24, -1, + 9, 50, -12, -25, -17, -10, 15, 44, -20, 0, -28, -22, 32, 5, 27, -33, + 15, -67, 61, -19, 19, 18, -46, -1, -1, 7, 18, 14, -27, -21, 18, -27, + 42, 22, -56, 38, -56, 21, 17, 2, 5, -3, -11, -38, 48, -27, 32, 8, + -50, 1, 10, -3, 38, -10, -16, -36, 34, -45, 74, -12, -30, 16, -52, 22, + 24, 17, -1, -13, -41, -10, 50, -5, 41, -32, -62, 25, -5, 48, 24, -26, + -61, 4, -2, 44, 62, -59, -23, -38, -4, 61, 34, 0, -57, -18, -41, 63, + 36, 6, -1, -69, -11, 10, 19, 60, -31, 3, -64, 18, -19, 61, 10, -17, + 10, -73, 13, 30, -7, 64, -39, -27, -34, 8, 20, 46, 24, -87, 29, -70, + 51, 51, -12, 6, -44, -30, 10, 52, -7, 2, -6, -72, 63, -9, 17, 15, + -37, -24, 14, 24, -11, 43, -55, -29, 42, -19, 47, 1, -49, -13, 13, 6, + 38, 4, -59, -2, 7, 5, 61, -31, -42, 11, -32, 54, 14, -11, -23, -10, + -20, 40, 19, -18, 0, -19, -28, 52, -14, -5, 29, -70, 53, -17, 19, -18, + 15, -30, -2, 37, -41, 38, 7, -61, 67, -67, 35, 11, -12, 11, -34, 38, + -61, 89, -59, 10, 28, -60, 52, -19, -22, 34, -30, 42, -42, 45, -68, 35, + 19, -45, 80, -81, 26, -16, 4, 30, 0, -13, -19, -14, 23, -22, 75, -77, + 47, -45, -5, 48, -36, 48, -50, 18, -35, 25, 5, 4, 14, -16, -33, 40, + -49, 71, -38, 17, -30, -6, 12, 4, 31, -27, -6, -12, -11, 27, 15, -13, + 12, -54, 32, -19, 53, -17, -1, -16, -39, 39, -5, 30, -3, -29, -13, -2, + 23, 16, 4, -18, -41, 26, -11, 35, 18, -48, 13, -33, 28, 1, 38, -45, + 5, -13, -18, 49, 1, -21, 16, -44, 14, 16, 7, -6, -5, -10, -18, 52, + -33, 25, -11, -36, 31, -15, 14, 11, -22, 9, -27, 41, -42, 56, -50, 15, + 10, -28, 30, -18, 3, 7, -7, 7, -16, 13, -27, 29, 5, -25, 42, -71, + 44, -18, 21, 8, -7, -21, -15, 21, -9, 36, -2, -43, 17, -26, 14, 45, + -33, 19, -40, 1, -3, 37, -5, -5, -2, -46, 38, 0, 7, 18, -33, -12, + 11, -11, 33, 2, -16, -15, -3, 1, 18, 26, -32, -4, -14, -17, 54, -1, + -1, -17, -35, 10, 12, 40, -12, -10, -30, -31, 51, -12, 65, -35, -34, -12, + -32, 60, 22, 19, -33, -39, -20, 2, 75, 2, 9, -42, -72, 35, 13, 65, + 5, -28, -60, -15, 23, 40, 44, -33, -34, -34, -5, 48, 33, 2, -21, -47, + -15, 25, 33, 12, 7, -55, -12, 7, 19, 28, 9, -34, -28, 5, 7, 32, + 15, -41, 8, -32, 10, 36, -4, 14, -40, 16, -45, 56, -15, 17, 0, -33, + 2, 0, 7, 23, -12, -1, -26, 3, 6, 10, 24, -32, 21, -50, 33, -9, + 15, 11, -24, 1, -12, 12, 4, 13, -10, -11, -2, -5, 7, 17, -23, 25, + -27, 12, -6, 0, 8, -16, 18, -24, 31, -27, 9, -3, -2, 18, -4, -7, + -11, -12, 10, 12, 15, -17, 7, -34, 18, 8, 4, 9, -18, -14, -3, 15, + 9, 7, 0, -37, 21, -13, 16, 18, -32, 12, -23, 21, 3, 12, -14, -14, + 3, -5, 24, 4, -21, 9, -32, 26, 14, -1, 12, -40, 0, -6, 24, 11, + 3, -11, -34, 17, -8, 28, 18, -36, 9, -38, 13, 26, 11, 7, -20, -13, + -34, 49, -24, 41, -8, -36, 4, -8, 3, 47, -11, -5, -24, -15, -9, 44, + 8, -5, 8, -61, 17, 14, 14, 23, -15, -43, 1, -1, 28, 27, 1, -40, + -6, -20, 18, 45, -22, 4, -20, -34, 39, 12, 3, 9, -31, -23, 15, 17, + -7, 36, -36, -19, 30, -30, 36, 1, -16, -8, 5, -14, 20, 10, -13, 0, + 6, -30, 37, -22, 3, 14, -27, 24, -15, 14, -15, 19, -22, 4, 17, -31, + 29, -14, -10, 27, -26, 22, -14, 8, -17, 9, -2, -11, 33, -27, 14, 0, + -29, 31, -21, 21, -7, -2, -14, -4, 20, -15, 37, -27, -9, 7, -24, 24, + 8, -9, 12, -23, 7, -14, 30, -22, 25, -16, -20, 24, -27, 23, 8, -9, + 6, -11, -18, 12, -3, 22, -14, 28, -61, 41, -32, 21, 29, -26, 8, -31, + 2, 5, 28, 3, -9, -14, -21, -3, 48, -33, 49, -62, 9, -1, 6, 33, + -24, 11, -44, 24, -2, 6, 25, -40, 8, 1, -16, 49, -41, 27, -41, 18, + 0, 3, 31, -50, 36, -42, 22, 15, -18, 24, -34, 5, 12, -21, 52, -56, + 52, -58, 29, -8, -8, 39, -51, 48, -47, 24, 4, -16, 22, -28, 6, 7, + -22, 48, -55, 51, -44, 31, -10, -5, 8, -36, 41, -31, 35, -9, -16, 10, + -17, 6, 21, -13, 10, -26, 5, -17, 39, -3, 3, 1, -43, 12, 1, 17, + 15, -7, -24, -9, 5, 15, 17, 8, -38, 2, -25, 25, 15, 12, -13, -16, + -11, 3, 19, 9, -9, -9, -15, 1, 19, -1, 14, -20, -1, -12, 15, -7, + 11, -10, -2, -3, 10, -9, 18, -17, 2, -4, -3, 4, 3, -2, -5, 9, + -9, 4, 5, -13, 5, 5, -21, 22, -16, 11, -4, 13, -22, 5, 3, -23, + 35, -14, -6, 13, -24, 4, 17, -6, 6, -7, -6, -27, 43, -28, 25, 9, + -45, 28, -23, 8, 25, -14, 0, -15, -4, -3, 27, 3, -15, 18, -59, 34, + 3, -3, 38, -39, -11, 4, -9, 27, 9, -2, -38, 21, -31, 19, 47, -53, + 43, -47, -11, 29, -2, 19, -7, -9, -36, 19, 12, -8, 53, -58, 1, 2, + -33, 67, -23, 25, -44, 5, -25, 28, 32, -29, 32, -60, 0, 25, -7, 39, + -14, -29, -12, 2, 11, 20, 23, -54, 18, -25, 1, 45, -10, -10, -4, -29, + 7, 28, 7, -11, 9, -46, 16, 11, 8, 8, -7, -25, -3, 16, -3, 32, + -25, -7, -20, 12, 0, 30, -14, -4, -15, -6, 6, 24, -9, 3, -16, -24, + 23, -3, 27, -20, 15, -56, 42, -17, 21, 13, -27, -8, -2, 5, 8, 21, + -21, -12, 4, -14, 15, 24, -39, 31, -38, 19, -2, 16, -16, 3, -6, -21, + 30, -14, 16, 4, -30, 11, -7, 7, 12, -5, -10, -9, 9, -17, 37, -15, + -5, 6, -26, 12, 13, -8, 7, -2, -18, 1, 17, -13, 15, 4, -37, 25, + -18, 8, 13, 1, -23, 21, -25, 10, 7, -1, -6, 10, -15, -7, 21, -26, + 29, -12, -3, -3, 0, -16, 29, -18, 21, -15, 1, -23, 22, -4, 3, 21, + -43, 22, -19, 4, 21, -8, 4, -11, -7, -5, 7, 19, -20, 31, -47, 11, + 2, -9, 44, -28, 8, -31, 5, -1, 20, 24, -38, 14, -32, -4, 47, -30, + 38, -41, -1, -12, 12, 27, -16, 29, -57, 12, -1, 3, 38, -29, 3, -25, + -1, 28, -10, 36, -52, 20, -33, 27, 14, -11, 18, -42, 13, 3, 3, 20, + -21, 0, -20, 15, 4, 0, 23, -49, 28, -24, 18, 16, -15, -2, -26, 22, + -10, 33, -7, -26, 11, -25, 19, 21, -14, 8, -33, 6, -2, 30, 2, -12, + -6, -37, 34, -4, 22, 1, -33, -3, -4, 15, 20, 3, -20, -16, 2, -14, + 38, -3, -7, 2, -24, -4, 22, -4, 11, -2, -15, -19, 21, -15, 24, 8, + -21, 1, -12, -3, 9, 21, -22, 17, -26, -2, 6, 14, -8, 19, -24, -10, + 8, -10, 17, 9, -7, -12, 8, -27, 29, -3, 4, -4, -3, -26, 25, -9, + 13, 9, -19, -7, 2, -4, 10, 19, -29, 13, -16, -3, 18, 4, -12, 10, + -24, 1, 6, 10, -9, 19, -26, -3, 16, -15, 20, -4, -16, 1, 3, -4, + 9, 6, -19, 7, 3, -18, 26, -13, -7, 12, -13, 2, 9, -5, -7, 15, + -18, 6, 8, -18, 13, -2, -12, 15, -12, 9, -6, -2, -16, 25, -14, 18, + 1, -29, 11, -4, 14, 2, 3, -26, 6, -3, 1, 19, -3, -15, 12, -29, + 17, -2, 12, -2, -4, -3, -28, 34, -21, 31, -7, -17, -3, -13, 20, 1, + 14, -14, -22, 11, -13, 33, -2, -11, -4, -30, 33, -12, 30, -17, -17, -4, + -4, 25, 2, 3, -20, -22, 20, -13, 42, -15, -11, -9, -16, 23, 8, 16, + -28, -3, -11, 4, 27, -8, 5, -17, -9, 8, -2, 25, -27, 17, -32, 19, + -4, 16, -8, -16, 6, -20, 32, 0, -14, 8, -34, 18, 12, 3, 13, -36, + 11, -34, 49, -14, 22, -12, -38, 17, -21, 42, 5, -10, -12, -34, 8, 18, + 18, 26, -50, 9, -50, 42, 16, 10, 10, -51, 2, -21, 38, 16, 7, -17, + -29, -12, 13, 19, 25, -16, -7, -40, 14, 5, 23, 6, -11, -23, -3, 11, + 2, 25, -26, 0, -12, 5, 4, 9, 2, -18, 10, -15, 5, 20, -26, 23, + -28, 6, 8, 1, 12, -26, 10, -19, 20, 7, -14, 17, -37, 18, 1, -1, + 23, -28, 9, -25, 20, 1, 6, 6, -23, 9, -15, 12, 10, -11, 5, -5, + -12, 15, -8, 4, 4, -4, -6, 8, -11, 3, 6, -6, 0, 6, -12, 1, + 14, -26, 27, -17, -3, 15, -18, 15, -10, 1, -6, 4, 9, -17, 28, -42, + 18, 3, -17, 45, -38, 9, -12, -7, 19, 8, 7, -31, 8, -18, 6, 53, + -51, 34, -41, -13, 32, -4, 17, -10, -6, -28, 25, 0, -2, 23, -32, -7, + 21, -28, 36, -7, -14, 7, -10, -4, 13, -3, -7, 7, -5, -6, 14, -10, + -10, 22, -29, 22, 0, -23, 24, -25, 15, 3, 3, -4, -9, 5, -23, 33, + -10, -6, 22, -48, 31, -8, 7, 10, -15, -5, -14, 20, -7, 16, 3, -32, + 20, -21, 13, 18, -20, 9, -25, 13, -3, 21, -4, -10, -4, -18, 18, 6, + 2, 6, -32, 8, -4, 18, 10, -3, -21, -12, 3, 3, 28, -3, -18, -4, + -14, 10, 19, 5, -9, -10, -21, 8, 21, 2, 11, -23, -12, -8, 14, 12, + -1, 5, -31, 14, -9, 15, 7, -14, 5, -19, 11, -3, 5, 1, -11, 12, + -13, 14, -6, -10, 5, -9, 16, -4, 3, -15, -5, 9, 2, 14, -11, -9, + -7, -7, 22, -2, 12, -14, -15, -2, 2, 19, 0, 6, -28, -3, 0, 5, + 27, -10, -8, -15, -9, 12, 10, 20, -25, 5, -23, 0, 27, -10, 21, -27, + -3, -14, 17, 8, 1, 6, -28, 2, 7, -2, 21, -14, -6, -9, 3, 6, + 2, 16, -33, 19, -17, 7, 10, -6, -3, -4, 0, 0, 11, -1, -13, 5, + -9, -1, 25, -27, 19, -20, 3, 9, 1, 2, -11, 5, -19, 26, -4, -6, + 13, -28, 10, 13, -11, 17, -19, -1, -10, 22, -4, -1, 13, -43, 29, -8, + 3, 18, -25, 5, -13, 16, -5, 12, 0, -29, 25, -23, 14, 17, -29, 23, + -23, 8, 2, 0, 4, -8, 11, -25, 22, -8, -6, 28, -35, 19, -6, -17, + 25, -15, 9, -5, 1, -12, 10, 5, -14, 22, -24, 0, 18, -23, 23, -9, + -10, 8, -1, -1, 4, -4, -13, 8, 6, -7, 22, -27, -8, 10, -6, 23, + 1, -17, -10, -9, 15, 14, 15, -17, -24, -1, -11, 41, 4, -4, -12, -35, + 12, 13, 19, 12, -22, -25, -6, 8, 22, 17, -3, -36, 7, -21, 21, 32, + -22, 8, -23, -17, 17, 15, 1, 10, -19, -20, 2, 10, 3, 23, -13, -21, + 7, -19, 26, 12, -10, 4, -35, 4, 7, 12, 19, -17, -3, -24, 14, 7, + 7, 15, -43, 12, -13, 8, 37, -29, 13, -34, 11, 2, 11, 14, -34, 22, + -31, 20, 14, -14, 18, -29, 5, -4, 3, 13, -11, 13, -23, 9, -3, -5, + 22, -22, 12, -10, -11, 15, -2, 6, 4, -10, -15, 11, -5, 10, 8, -14, + -12, 12, -10, 16, 17, -37, 16, -18, -3, 31, -11, -1, -9, -8, 0, 22, + 6, -21, 9, -32, 14, 26, -19, 27, -40, 6, -4, 13, 14, -14, 3, -34, + 21, 1, 10, 15, -32, 5, -10, 5, 19, -10, 3, -21, 10, -7, 14, 9, + -23, 18, -25, 9, 7, -5, 4, -1, -8, -2, 15, -17, 16, -5, -17, 16, + -13, 9, 3, 2, -17, 13, -10, -2, 29, -33, 17, -15, -10, 23, -6, 12, + -14, -3, -9, 2, 26, -23, 28, -45, 14, -1, 1, 33, -35, 17, -34, 15, + 10, 3, 12, -31, 7, -15, 18, 19, -19, 12, -39, 16, 5, 8, 17, -37, + 16, -35, 39, -3, 8, -5, -31, 9, -4, 26, 0, -3, -18, -15, 19, -2, + 25, -12, -21, 1, -16, 26, 4, 6, -20, -1, -14, 11, 21, -20, 22, -32, + 0, 14, -9, 19, -10, -2, -13, 14, -9, 4, 17, -36, 30, -20, -2, 22, + -21, 13, -11, 7, -12, 15, -6, -15, 25, -29, 20, 3, -18, 17, -17, 7, + -3, 11, -9, -4, 13, -33, 34, -10, -5, 22, -34, 11, -4, 8, -1, 11, + -14, -16, 24, -27, 31, 3, -29, 19, -23, 2, 26, -11, 1, -3, -14, -4, + 27, -14, 3, 9, -38, 26, -1, -7, 20, -15, -12, 14, -8, 4, 7, -11, + -10, 12, -3, 0, 16, -28, 7, 1, -2, 14, -7, -10, -5, 4, 5, 9, + 3, -22, 4, -5, 0, 27, -18, 1, -9, -10, 13, 10, 1, -9, -1, -21, + 15, 11, -8, 15, -21, -8, 12, -4, 13, 0, -12, -5, 2, -1, 9, 2, + -8, 0, -4, 1, 4, -1, -1, -1, -1, -2, -15, 21, -17, 23, -30, 1, + 34, -34, 6, 5, -15, 19, 1, -25, 6, 20, -2, -28, 15, 10, -15, 0, + -7, 10, 7, -5, -9, -6, 19, -3, -21, 3, 20, -4, -20, 1, 16, -3, + -8, -2, 5, 1, -8, -6, 3, 9, 2, -13, -4, 15, -7, -9, 0, 3, + 6, -7, -7, 5, 8, -8, -4, 0, 1, 1, -6, -4, 7, 2, -2, -7, + 0, 4, -3, -4, 0, 2, 0, -2, -4, 1, 4, -2, -4, -3, 1, 3, + -5, -4, 4, 3, -6, -5, 4, -1, -2, -3, 0, 3, -3, -1, -4, 3, + 3, -5, -3, 1, 1, -2, -3, 1, 2, -2, -4, 0, 0, 0, -1, -3, + 1, 1, -3, -2, 1, 0, -2, -2, 0, 0, -2, -1, 0, -1, 1, -2, + -2, 1, 0, -2, 0, -1, 0, -1, -1, -1, 0, 0, -1, -3, 1, 1, + -2, -2, 0, 1, -1, -2, -1, 0, 0, 0, -2, -1, 1, 0, -3, 0, + 2, -1, -2, 0, 0, 0, -2, 0, -1, 0, -1, -1, 1, 0, -1, 0, + -1, 1, 0, -13, 5, 7, -11, 24, -50, 41, 4, -29, 14, -11, 8, 11, + -15, -12, 15, 18, -21, -14, 22, -2, -11, -3, -3, 18, -3, -5, -14, 9, + 22, -24, -16, 23, 12, -23, -8, 9, 10, -4, -8, -3, 11, -4, -14, 0, + 8, 8, -5, -14, 8, 10, -12, -4, -2, 10, 0, -11, -3, 11, 0, -7, + -2, -1, 7, -6, -8, 3, 6, 0, -3, -8, 7, 2, -7, -2, 2, 1, + -2, -4, -1, 3, 3, -4, -5, 1, 3, -3, -6, 2, 5, -1, -7, -1, + 3, -1, -4, -3, 5, 0, -3, -2, -1, 4, -1, -5, -1, 3, -1, -4, + -1, 3, 1, -4, -2, 1, 0, -2, -3, 0, 2, -1, -4, 1, 1, -1, + -2, -2, 1, -1, -3, 0, 0, 0, -1, -2, 0, 0, -2, -1, 0, -1, + 0, -2, -1, 0, -1, 0, -1, -2, 2, -1, -2, -1, 0, 1, -2, 0, + -1, -1, 0, -1, -2, 0, 1, -1, -3, 0, 1, -1, -3, 0, 1, -2, + -1, 0, 0, -1, -1, 0, -1, -1, -1, -1, 0, 0, -1, -1, 0, 0, + -2, 0, 0, 0, 0, -2, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, + 0, 0, -1, 0, 0, -1, 0, -1, 1, 0, 0, 0, 1, -1, -1, 0, + 0, 0, 1, -2, 4, -3, 3, -40, 71, -73, 67, -27, -68, 127, -80, 3, + 5, 1, 17, -14, 1, -30, 53, -3, -42, 15, 19, -9, -17, -1, 13, 16, + -17, 4, -32, 43, 15, -68, 18, 54, -38, -7, -1, 11, 7, -3, -18, 5, + 25, -27, -9, 9, 19, -6, -12, -8, 20, -1, -15, -1, 1, 17, -10, -16, + 12, 12, -13, 0, -6, 10, 2, -16, -1, 14, -4, 4, -11, -2, 12, -6, + -8, 4, 4, -2, -4, 1, -2, 4, 3, -7, -5, 8, 0, -10, 1, 4, + 2, -4, -6, 4, 1, -1, -7, 1, 8, -9, 2, -5, 3, 3, -4, -3, + 0, 3, -3, -5, 4, 3, -3, -4, 0, 2, 0, -3, -4, 5, 0, -5, + -1, 2, 0, -3, 0, -1, 2, -2, -4, 3, 0, -1, -2, -1, 2, -2, + -2, 1, -1, 0, -1, -3, 1, 1, -2, 1, -3, 1, 1, -3, -1, 1, + 0, -1, -2, 1, -1, -1, 1, -2, 1, -1, -1, -1, -1, 0, 1, -3, + 0, 0, 1, -4, 0, 1, -2, 0, -2, 0, 0, 0, -2, 1, -1, 0, + -2, 0, 2, -2, -1, 0, -1, 2, -2, -1, 1, -2, 0, -1, 1, -1, + -1, -1, 1, -2, 1, -1, -1, 2, -3, 0, 0, -1, 1, -1, 0, 1, + 0, -2, 0, -1, 1, -2, 0, 0, -1, 1, 0, -2, 0, 1, -2, 1, + 0, 0, -1, 0, 1, -1, -1, -1, 1, 1, -1, 0, 0, 0, -1, 1, + 0, -1, 1, 0, 0, 1, 0, -1, 1, 0, 3, -40, 58, -39, 12, 42, + -117, 108, 1, -66, 22, 17, 0, -9, 10, -39, 42, 4, -23, -12, 28, 3, + -34, 9, 17, 3, -9, 10, -29, 13, 53, -79, 3, 64, -26, -24, 16, -9, + 14, 2, -8, -15, 31, -9, -30, 11, 29, -15, -7, 0, 3, 6, -4, -9, + -6, 22, 1, -24, 9, 11, -8, 0, -2, 2, 8, -12, -6, 10, 2, 2, + -9, -4, 11, -2, -10, 3, 2, 3, -5, -1, 1, -1, 6, -4, -8, 9, + 2, -8, -3, 6, 3, -4, -3, -1, 6, -2, -8, 0, 9, -4, -3, -2, + 2, 4, -4, -1, -1, 4, -2, -6, 4, 2, -1, -4, 0, 1, 2, -3, + -5, 3, 3, -3, -4, 3, 0, -1, 0, -2, 2, 0, -3, 0, 3, 0, + -3, -1, 2, 0, -3, 1, 0, -1, 2, -2, -2, 2, -1, 0, -1, -1, + 1, -1, -2, 0, 0, 1, -3, 1, 0, -1, 1, -2, -1, 2, -2, -1, + 0, -1, 2, -3, -1, 1, 1, -2, -2, 2, 1, -2, -1, 0, 0, 1, + -3, 1, 0, 0, 0, -2, 3, 0, -2, 0, 0, 1, 0, -1, 1, -2, + 0, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 1, 0, -1, 1, -2, + 0, 1, 1, 0, 1, -2, 1, 0, 1, 0, 0, 3, -1, 0, 1, 0, + 0, 3, -29, 35, -12, -16, 56, -88, 39, 62, -79, 5, 29, 1, -13, 12, + -29, 26, 17, -28, -3, 12, 5, -11, -19, 28, 1, -5, 9, -21, -7, 60, + -56, -20, 57, -10, -27, 21, -21, 16, 12, -12, -21, 24, 6, -29, 4, 19, + 2, -7, -5, -3, 7, 6, -11, -9, 11, 13, -18, -4, 13, 1, -3, -6, + -1, 10, -8, -6, 5, 3, 5, -3, -11, 4, 9, -11, 0, 4, 3, -4, + -1, 0, 0, 7, 0, -14, 7, 5, -7, -4, 4, 5, -1, -4, -4, 4, + 1, -4, -4, 7, -1, -1, -3, 0, 5, -1, -4, -1, 2, 0, -3, 1, + 1, 2, -2, -4, 1, 2, 0, -5, 2, 3, -2, -2, 1, 1, -2, 2, + -3, 0, 0, -1, -1, 0, 1, 0, -3, 0, 0, -1, 1, -1, -2, 1, + -1, 0, -2, 2, 1, -2, -1, 1, 0, -1, -1, 0, 1, -1, 0, -2, + 1, 1, -1, 0, -1, -1, 0, 0, -1, -1, 0, -1, -1, 2, -2, -1, + 1, 0, 0, -1, -1, 1, 0, -1, 1, -1, 0, 1, -3, 1, 1, -1, + -1, 0, 1, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, 0, 2, -2, + 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, -1, -1, -7, -9, + 35, -52, 59, -33, -32, 64, -15, -41, 19, 22, -20, 9, -11, -3, 33, -27, + 2, 7, -9, 19, -37, 24, 7, -11, 11, -1, -30, 37, 8, -57, 36, 19, + -33, 14, 0, -17, 26, 1, -20, -5, 26, -18, -13, 14, 7, -6, 4, -9, + -4, 11, 3, -14, -7, 20, 0, -18, 10, 1, 4, -5, -7, 6, 0, -3, + -2, -2, 8, 5, -11, -6, 10, -1, -10, 6, -2, -1, 1, -3, 0, 3, + 5, -9, -5, 9, -3, -4, 1, 1, 3, -1, -4, -1, 2, -2, -5, 5, + -3, 0, 1, -5, 4, 2, -3, -3, 0, 0, -2, 1, 0, -2, 3, -2, + -5, 2, 2, -2, -4, 3, 0, -2, 1, -2, -2, 5, -2, -6, 1, 2, + -1, -1, 0, 1, -1, -2, -1, -1, 2, 0, -4, 0, 1, 0, -3, 0, + 2, 0, -3, 0, 0, 1, -1, -1, 1, 0, -1, -2, 1, 0, 0, -1, + 0, -2, 1, 0, -1, 1, -1, 0, -2, 1, 1, -2, -1, 2, -2, 1, + -3, 1, 1, -1, 0, 0, -1, 1, 0, -2, 2, -1, -1, 0, 0, 1, + 0, 1, 0, -2, 1, 0, 0, -1, 1, 0, 0, 0, 0, -3, -20, 45, + -56, 40, -5, -34, 27, 24, -42, -1, 29, -14, -4, 2, -7, 24, -20, -1, + 18, -25, 25, -29, 9, 21, -26, 14, 4, -20, 7, 27, -42, 5, 31, -24, + -2, 19, -30, 21, 8, -11, -17, 20, 1, -22, 11, 7, -7, 6, -5, -7, + 3, 11, -6, -18, 11, 16, -20, 1, 5, 2, -3, -3, 0, -3, 4, -1, + -7, 2, 10, -9, -8, 7, 2, -9, 5, -1, -5, 2, 1, -3, -2, 9, + -5, -8, 4, 1, -5, 0, 1, 2, -1, 0, -5, 4, -1, -5, 4, -3, + 1, 1, -5, 3, 0, 0, -3, 0, -1, -2, 1, 2, -5, 2, 1, -5, + -2, 3, -1, -5, 2, 1, -4, 2, -1, -4, 2, 3, -7, -1, 2, 0, + -2, 1, 0, -2, -1, 0, -3, 1, 2, -3, -2, 3, 0, -3, -1, 1, + 0, -1, -2, -1, 1, 0, 0, -1, 0, 0, -2, 0, 0, 1, -2, 2, + -3, 1, 0, 0, -2, 1, 0, -1, 0, 0, -1, -1, 2, -3, 0, 0, + -1, 0, 0, -1, 1, 0, -4, -13, 32, -41, 31, -10, -10, 4, 22, -25, + -8, 21, -3, -14, 5, 1, 12, -23, 8, 18, -31, 25, -26, 10, 17, -23, + 8, 5, -9, 0, 16, -25, 2, 23, -22, -2, 22, -30, 15, 7, -6, -13, + 12, 1, -17, 9, 5, -6, 4, -3, -7, 5, 7, -6, -13, 7, 10, -11, + 0, 0, 4, -3, -3, 2, -7, 4, 2, -5, 0, 6, -3, -8, 4, 2, + -8, 7, 0, -8, -1, 6, 0, -8, 6, 0, -5, 1, 0, -5, 3, 2, + -3, -2, 4, -5, -1, -1, -2, 3, -4, 1, -1, -3, 3, -1, -2, -2, + 1, -2, -2, 1, 1, -4, 1, 2, -5, -3, 5, -3, -4, 4, -1, -4, + 2, -1, -4, 3, 1, -5, -2, 2, 0, -2, 2, -1, -4, 3, -1, -3, + 0, 1, -2, -2, 1, -1, -1, -1, 0, 0, -1, -1, -1, 0, -1, 1, + -1, -1, 0, -2, 1, 0, -1, -1, 0, -1, -1, -1, 2, -2, -1, 1, + -1, -2, 1, -1, -1, 1, -2, 1, -7, -3, 15, -23, 20, -16, 9, -12, + 16, -12, -8, 11, 5, -18, 6, 8, 0, -18, 16, 4, -19, 16, -17, 10, + 5, -8, -2, 9, -5, -4, 10, -17, 5, 13, -18, 2, 12, -17, 10, 0, + -2, -8, 7, -4, -7, 6, 1, -3, 1, 3, -9, -2, 10, -7, -8, 4, + 6, -6, 1, 0, 0, -2, 1, -1, -8, 6, 1, -5, 2, 4, -2, -4, + 1, 1, -7, 5, -1, -4, -2, 4, 0, -4, 4, -3, -4, 1, 0, -3, + 0, 2, -1, -2, 2, -2, -1, -3, 0, 3, -4, 3, -3, 0, 2, 0, + -3, -1, 1, -3, -1, 2, 0, -1, 0, 0, -3, 0, 1, -4, -1, 2, + 0, -2, 0, 1, -3, 1, 1, -3, -2, 2, -1, -1, 2, -1, -2, 1, + 0, -1, -1, 0, 2, 33, 42, 58, 71, 79, 85, 88, 91, 94, 79, 95, + 82, 106, 86, 105, 47, 16, -6, 13, 44, 31, -15, -38, -36, 20, 70, 41, + 48, 58, 24, -57, -127, -119, -102, -126, -128, -111, -78, -82, -88, -87, -60, -66, + -98, -104, -99, -97, -99, -104, -101, -88, -87, -91, -61, -27, -34, -54, -55, -45, + -24, -10, -5, -4, 5, 34, 63, 101, 94, 78, 52, 51, 52, 74, 81, 77, + 59, 46, 17, 7, 39, 53, 47, 42, 66, 83, 73, 52, 28, 22, 11, 8, + 11, 0, -15, -23, -15, -14, -6, 16, 46, 62, 71, 76, 90, 102, 103, 103, + 101, 100, 90, 75, 63, 67, 49, 37, 28, 12, 5, 6, 15, 15, 8, -7, + -12, -4, -10, -28, -24, -17, -25, -50, -64, -81, -103, -116, -116, -113, -95, -72, + -54, -41, -47, -65, -65, -50, -33, -24, -7, 11, 8, -4, -13, -28, -51, -75, + -90, -91, -90, -90, -87, -88, -83, -84, -82, -81, -81, -76, -65, -71, -85, -84, + -79, -83, -81, -77, -72, -70, -65, -66, -66, -65, -66, -68, -61, -56, -51, -36, + -13, -3, -5, -8, -12, -12, 3, 16, 21, 31, 50, 69, 77, 82, 90, 102, + 110, 114, 116, 117, 118, 119, 116, 112, 109, 105, 98, 99, 103, 102, 91, 73, + 64, 63, 61, 57, 51, 40, 24, 35, 57, 75, 84, 79, 65, 37, 4, -26, + -45, -57, -54, -46, -45, -54, -67, -67, -48, -16, 15, 35, 44, 45, 44, 45, + 46, 38, 23, 2, -15, -34, -52, -60, -70, -77, -80, -79, -74, -77, -84, -86, + -80, -72, -68, -72, -80, -87, -92, -96, -101, -104, -104, -101, -93, -90, -89, -86, + -85, -84, -83, -82, -81, -79, -77, -76, -73, -71, -66, -62, -55, -39, -31, -27, + -25, -31, -37, -46, -51, -53, -54, -48, -45, -38, -20, 3, 24, 35, 39, 32, + 16, 5, 3, 0, -6, -13, -13, -11, -2, 14, 28, 40, 50, 53, 50, 55, + 64, 74, 90, 105, 108, 112, 106, 104, 109, 112, 123, 127, 127, 127, 127, 127, + 127, 118, 113, 107, 110, 114, 111, 104, 101, 101, 102, 103, 99, 99, 89, 73, + 53, 35, 20, 0, -22, -43, -63, -77, -82, -76, -65, -48, -36, -29, -24, -25, + -29, -37, -40, -49, -59, -67, -73, -76, -78, -79, -75, -73, -74, -75, -68, -52, + -44, -30, -19, -9, -6, -9, -13, -24, -33, -35, -31, -30, -35, -40, -44, -45, + -51, -53, -54, -50, -50, -47, -42, -50, -55, -54, -56, -56, -54, -54, -49, -48, + -41, -32, -28, -18, -13, -5, 6, 18, 33, 49, 60, 71, 78, 88, 95, 97, + 93, 88, 91, 93, 97, 98, 97, 94, 91, 85, 81, 72, 70, 66, 61, 60, + 64, 66, 74, 83, 92, 102, 108, 109, 107, 102, 97, 95, 91, 87, 80, 74, + 67, 62, 61, 58, 61, 61, 57, 53, 43, 35, 27, 25, 24, 20, 20, 22, + 27, 34, 36, 32, 21, 8, -3, -10, -16, -18, -16, -16, -19, -15, -11, -11, + -12, -20, -34, -45, -59, -72, -80, -89, -94, -95, -102, -111, -114, -111, -111, -108, + -106, -104, -101, -98, -93, -90, -86, -86, -83, -82, -81, -79, -76, -73, -70, -72, + -78, -81, -79, -79, -72, -60, -43, -31, -25, -27, -34, -37, -40, -42, -41, -39, + -36, -34, -25, -12, -4, 5, 12, 16, 17, 15, 13, 6, -4, -7, -8, -6, + -1, 4, 7, 9, 12, 16, 19, 19, 22, 28, 29, 28, 29, 30, 34, 40, + 49, 57, 71, 78, 85, 92, 96, 95, 89, 85, 86, 93, 99, 104, 102, 100, + 94, 85, 77, 73, 69, 66, 63, 60, 60, 59, 57, 52, 47, 41, 31, 18, + 6, -3, -7, -11, -12, -14, -18, -22, -23, -22, -24, -30, -37, -41, -44, -50, + -56, -64, -67, -65, -62, -58, -58, -58, -59, -61, -62, -66, -72, -78, -79, -77, + -73, -68, -64, -61, -56, -53, -54, -52, -52, -57, -63, -69, -70, -68, -65, -62, + -59, -57, -56, -58, -60, -61, -63, -64, -62, -61, -60, -58, -54, -49, -45, -42, + -39, -36, -32, -28, -22, -13, -7, -3, 2, 13, 28, 41, 52, 64, 71, 73, + 73, 70, 64, 61, 60, 64, 66, 65, 66, 64, 61, 60, 62, 65, 64, 66, + 67, 67, 68, 66, 64, 66, 68, 73, 76, 74, 72, 66, 58, 52, 46, 42, + 38, 38, 41, 47, 52, 52, 48, 45, 42, 40, 38, 34, 29, 27, 26, 28, + 29, 28, 29, 30, 31, 28, 24, 21, 19, 17, 14, 10, 6, 3, -4, -9, + -15, -19, -26, -33, -40, -49, -55, -60, -65, -70, -73, -72, -72, -71, -70, -71, + -75, -78, -81, -83, -86, -86, -85, -84, -82, -80, -77, -72, -69, -66, -63, -61, + -61, -61, -61, -61, -60, -58, -53, -48, -42, -36, -30, -28, -30, -32, -33, -32, + -31, -28, -22, -18, -10, -5, 0, 3, 6, 11, 16, 19, 22, 24, 26, 27, + 29, 34, 40, 46, 48, 48, 48, 45, 40, 36, 33, 31, 33, 35, 40, 48, + 55, 62, 68, 73, 76, 78, 78, 77, 79, 82, 85, 87, 87, 87, 86, 86, + 86, 83, 78, 71, 63, 55, 48, 44, 39, 36, 36, 36, 35, 32, 28, 24, + 18, 13, 9, 6, 4, 1, -2, -5, -11, -17, -20, -21, -20, -21, -24, -28, + -32, -34, -33, -33, -35, -37, -40, -43, -47, -52, -58, -63, -69, -74, -77, -80, + -81, -82, -81, -80, -77, -74, -69, -62, -54, -48, -48, -51, -54, -57, -57, -57, + -56, -55, -55, -56, -57, -56, -55, -54, -54, -54, -54, -52, -49, -45, -41, -38, + -34, -31, -29, -27, -24, -20, -17, -11, -7, -3, 0, 5, 10, 16, 22, 27, + 31, 34, 38, 42, 44, 45, 48, 50, 52, 57, 61, 64, 64, 65, 65, 63, + 60, 57, 55, 55, 58, 61, 63, 65, 67, 69, 71, 74, 77, 79, 79, 77, + 74, 71, 68, 66, 63, 60, 57, 55, 51, 46, 40, 36, 30, 25, 20, 17, + 16, 17, 16, 14, 12, 10, 7, 3, -1, -5, -11, -15, -17, -18, -18, -19, + -21, -25, -29, -32, -33, -33, -36, -39, -43, -46, -50, -53, -56, -58, -59, -60, + -61, -62, -63, -65, -66, -67, -68, -70, -72, -72, -70, -67, -63, -61, -60, -60, + -58, -56, -54, -53, -52, -52, -52, -51, -50, -49, -47, -45, -43, -40, -37, -35, + -34, -32, -29, -25, -21, -18, -14, -9, -4, 0, 4, 7, 11, 15, 18, 21, + 25, 28, 33, 37, 41, 44, 46, 47, 47, 46, 46, 45, 43, 42, 42, 43, + 46, 48, 49, 50, 52, 55, 59, 62, 65, 66, 67, 68, 69, 69, 70, 72, + 74, 74, 73, 72, 71, 69, 65, 61, 57, 53, 50, 46, 43, 38, 35, 32, + 28, 23, 19, 17, 17, 15, 13, 11, 9, 5, 1, -3, -6, -9, -12, -14, + -17, -19, -23, -27, -31, -35, -38, -40, -43, -46, -48, -52, -55, -57, -61, -64, + -66, -67, -68, -69, -70, -70, -70, -69, -69, -70, -71, -70, -66, -62, -59, -55, + -52, -50, -46, -43, -41, -38, -36, -35, -35, -34, -33, -33, -33, -33, -31, -30, + -28, -26, -25, -24, -21, -20, -20, -19, -19, -18, -17, -16, -15, -13, -11, -8, + -3, 2, 9, 15, 21, 27, 33, 38, 41, 45, 48, 51, 53, 55, 56, 56, + 56, 56, 56, 56, 56, 55, 57, 58, 60, 61, 62, 62, 64, 66, 68, 69, + 71, 72, 73, 74, 72, 70, 67, 63, 60, 57, 54, 50, 46, 41, 36, 31, + 27, 23, 19, 16, 14, 12, 11, 9, 8, 5, 2, -1, -4, -8, -10, -15, + -18, -19, -20, -22, -22, -23, -23, -24, -26, -29, -31, -33, -35, -36, -37, -38, + -41, -44, -46, -48, -50, -52, -54, -56, -59, -61, -63, -63, -64, -65, -64, -63, + -62, -61, -60, -59, -58, -57, -58, -57, -57, -55, -53, -50, -49, -47, -46, -43, + -40, -37, -33, -31, -28, -26, -23, -20, -16, -14, -12, -9, -5, -2, 1, 5, + 9, 13, 17, 21, 24, 26, 29, 32, 35, 37, 37, 38, 39, 41, 43, 44, + 45, 46, 48, 50, 51, 53, 52, 52, 50, 48, 47, 46, 46, 46, 46, 47, + 48, 49, 51, 54, 56, 58, 60, 61, 62, 62, 62, 61, 59, 57, 55, 54, + 53, 52, 51, 49, 46, 41, 36, 31, 27, 22, 18, 14, 11, 9, 6, 3, + 0, -2, -5, -8, -11, -16, -20, -25, -28, -31, -34, -37, -39, -41, -41, -42, + -42, -42, -43, -45, -46, -47, -49, -50, -52, -54, -56, -57, -58, -60, -61, -63, + -64, -64, -64, -63, -63, -61, -59, -58, -57, -55, -54, -53, -52, -52, -51, -50, + -49, -47, -46, -45, -44, -42, -40, -38, -35, -32, -30, -28, -25, -22, -19, -17, + -15, -12, -9, -5, -1, 3, 7, 11, 15, 19, 23, 25, 27, 30, 34, 36, + 37, 38, 39, 40, 42, 44, 45, 46, 47, 49, 50, 52, 53, 52, 51, 49, + 47, 47, 46, 46, 46, 47, 47, 48, 50, 52, 55, 57, 59, 61, 62, 62, + 62, 61, 60, 58, 56, 54, 54, 53, 51, 50, 47, 44, 39, 34, 29, 25, + 20, 16, 13, 10, 7, 4, 2, -1, -3, -6, -9, -14, -18, -22, -26, -30, + -33, -35, -38, -40, -41, -41, -42, -42, -43, -44, -46, -47, -48, -49, -51, -53, + -55, -56, -57, -59, -60, -62, -63, -64, -64, -63, -63, -62, -60, -59, -57, -56, + -55, -53, -52, -52, -51, -51, -50, -48, -46, -45, -44, -43, -41, -39, -36, -34, + -31, -29, -26, -24, -21, -16, 1, -2, -1, -9, -9, -6, 5, 6, -1, -10, + 8, 24, 11, -2, -14, -9, -15, -13, 5, 14, 12, -6, -1, -12, 1, -9, + 12, 12, 10, 5, -19, -11, -13, -2, 8, 5, 1, -2, -3, 9, -6, 6, + 5, 6, -3, -17, -7, 3, 2, -1, 0, 7, -7, 5, 4, 6, -18, -24, + 6, 20, -1, -4, -1, 10, 3, -10, 8, 7, -11, -17, -15, 5, 18, 4, + 1, 8, -16, -4, 0, 11, 9, -10, -15, 0, -22, -12, 19, 34, 16, -9, + -16, -7, -12, -10, 13, 23, -1, -10, -2, -3, -11, 13, 7, -6, -9, 3, + 11, -10, -18, 12, 22, 7, -27, -29, -4, 20, 20, 10, 8, -16, -26, -6, + 22, 21, 7, 15, 8, -50, -50, -7, 35, 22, -13, 32, 41, -33, -46, -10, + 23, -7, -25, 23, 21, -38, -36, 14, 44, 2, 2, 34, -14, -51, -29, 11, + 19, 7, 22, 13, -23, -21, -8, -9, 1, 14, 26, 26, -8, -34, -33, 4, + 1, -6, -2, 16, -7, -23, 12, 27, 5, 6, 6, 0, -8, 0, -1, -17, + -13, -12, 3, 9, 4, 11, 23, 36, 0, -43, -16, 4, -21, -26, 27, 16, + -25, 3, 65, 4, -34, 24, -10, -38, -14, 13, 4, -15, 36, 44, -42, -51, + 20, -5, -6, 68, 20, -18, -39, -11, 9, 17, 6, -33, -20, -13, 48, 30, + 22, -4, -9, -53, -20, 32, 32, -16, 17, -11, -36, -8, -5, 39, 28, 33, + 21, -64, -48, 3, -22, 15, 62, -26, 0, 3, 5, 73, -14, -48, -20, -59, + 4, 70, 60, -7, -2, -88, -22, -17, 39, 17, 33, -3, 15, 28, -47, -80, + -37, 5, 7, 104, 16, -99, -92, -36, 109, 78, 26, -15, -92, -21, 62, 48, + -51, -81, -25, 55, 63, 35, 21, -115, -54, 101, 73, -41, -110, -66, 50, 107, + 45, -8, -109, -38, 12, 102, 3, 17, -45, -2, -36, 39, 46, -12, -28, -27, + -17, 17, -18, 82, -5, -3, -25, -5, -14, 15, 9, -3, -17, -6, 2, 7, + -36, -13, 6, 21, -23, -20, 16, -18, 3, -2, 26, 0, 13, -23, -2, -19, + -28, -18, 15, 12, 22, -4, 23, -17, -22, -9, -18, -4, 11, 13, 0, 34, + -16, -20, 26, 23, 15, -4, -25, 7, 8, -9, 8, 44, 1, -40, 17, -32, + 9, -30, -52, 52, 3, 2, -21, 83, 58, -14, -46, -61, -12, -67, -20, 64, + 72, 57, -10, 5, 1, -77, 31, -47, -39, 12, 22, 57, 28, 0, 9, -76, + 15, -74, 33, -12, 39, 114, -35, -36, -38, -23, 27, -21, 14, 56, 47, 6, + -72, -61, -4, 18, -4, 19, 13, 45, 71, 48, -1, -125, -52, -56, -20, -18, + -12, 51, 78, 68, -46, 32, -40, -29, -28, -81, -25, 75, 42, 58, -38, 1, + -29, -34, 31, -36, -14, 10, 64, 37, 2, -31, -72, -17, -33, 30, -52, -54, + 25, 43, 70, 81, -9, -73, 4, -65, 15, -28, 25, 0, 28, 19, 51, -26, + 6, 0, -37, -15, -22, -20, -16, -5, 50, 56, 67, 25, 16, -35, -29, -14, + -39, 19, -24, -52, -13, -32, -10, 39, 33, 59, 6, 37, 55, 11, -9, -35, + -15, -57, -56, -36, -34, 19, 19, 6, 20, 17, -11, 5, 26, 19, 16, 7, + -20, -26, -55, -62, -36, -18, 19, 37, 47, 25, -6, -14, 1, -4, -13, 12, + 23, 34, 38, 41, 33, 31, -10, -56, -52, -49, -31, -40, -21, -12, 0, 5, + 12, 22, 22, 21, 31, 12, 2, -8, -4, -18, -7, 3, 1, -1, 11, 12, + 18, 17, 9, -2, -12, -13, -11, -1, 8, 3, 3, 2, 5, -5, -16, -15, + -13, -8, -12, -9, -2, -1, 2, 7, 10, 7, 11, 14, 7, -1, -4, 5, + -3, -2, 0, -6, -10, -1, -5, 3, 9, 0, -8, -9, -6, -6, 0, 6, + 3, 6, 7, 10, 0, -8, -3, -5, -1, -8, -7, -4, -3, -3, 0, -1, + -6, 2, 7, 7, 5, 4, 10, 5, 8, -1, -11, -15, -11, -15, -10, -1, + -8, -12, -5, 1, 3, 6, 8, 11, 18, 22, 26, 10, -10, -1, -15, -3, + -21, -16, -14, -12, -7, -8, -18, -20, -11, 9, 20, 27, 26, 11, 1, 21, + 6, 3, -9, -15, -9, -20, 3, 5, 21, 14, 6, 11, -21, -22, -6, -21, + -23, -18, 11, 6, 5, 21, 9, 23, 16, -3, -30, -7, -27, -4, 5, 18, + 22, 16, 2, 7, -1, -2, -10, -14, -10, -17, -10, -15, -16, 3, 12, 30, + 18, -1, -6, -15, -3, 5, 11, -18, -2, 8, 21, 11, -13, -4, -30, -7, + 0, 12, 25, -3, 17, 14, -20, -6, -27, -41, -11, -12, 23, -8, 13, 24, + 18, 27, -11, -8, -12, -2, 17, 23, 13, -20, -21, -2, -21, -34, -46, -23, + 28, 48, 9, -10, 8, 29, 27, 5, -29, -12, 13, -5, -2, -35, 1, 3, + 24, 13, 17, -18, -30, -21, 14, -1, 6, -8, 48, 45, -7, -34, -49, -32, + -6, -26, 20, 29, 76, 30, -21, -66, -36, -15, 40, -5, 29, 3, 10, -39, + -25, -2, 24, 19, 19, -4, -8, 3, -22, -23, -18, 13, 17, -3, -25, 23, + 66, 26, -18, -27, -34, -30, -30, 36, 25, 28, -22, -17, -7, -22, 21, 18, + 42, 8, -25, -28, -31, -10, 15, 18, 0, -1, -5, 16, -12, 13, 13, 12, + -8, -37, -9, 13, -5, 8, -3, 13, -8, 4, 24, -16, -43, -18, 26, 26, + -11, -9, 19, 9, -15, 9, 15, -12, -31, -27, 8, 29, 5, 7, 17, -33, + -14, 14, 23, -1, -18, -18, -4, -35, -17, 47, 71, -16, -20, -11, -16, -25, + 6, 37, 14, -18, 1, -8, -14, 10, 14, 2, -20, 0, 20, -10, -25, 14, + 32, 7, -39, -38, -3, 34, 25, 13, 3, -24, -34, 5, 38, 18, 7, 29, + -30, -74, -41, 36, 40, -12, 26, 55, -17, -59, -26, 28, -2, -31, 24, 25, + -44, -39, 21, 44, -1, 10, 33, -34, -50, -12, 18, 13, 20, 17, -6, -31, + -10, -6, -1, 7, 12, 14, 6, -16, -24, 6, 9, -16, -16, 6, 2, -10, + 13, 12, -10, 0, 11, 11, 10, -3, -22, -22, -12, -7, 19, 17, -2, -12, + 6, 16, 7, -11, -1, -20, -22, -8, 26, 16, -3, 12, 1, -33, 2, 30, + -23, -5, 28, -17, -19, 21, 9, -28, -14, 25, -1, 4, 24, 0, -26, -9, + 7, 2, -2, 20, -10, -11, 5, -3, -4, 8, -9, 14, 18, 25, -22, -15, + -22, -3, -12, 27, 30, 15, -11, -26, -4, 15, -7, -14, 23, -23, -4, 34, + -2, -38, 14, -11, -24, 16, 34, 11, -13, 3, -3, -19, -34, 0, -3, 24, + 43, 1, -12, -38, -25, -11, 23, 35, 12, -28, -25, -16, 7, 22, 1, -10, + 8, 8, -3, 6, -24, -20, -13, 9, 31, 12, -16, 7, -29, 5, 8, -28, + 3, 4, 12, 26, -9, -15, -5, -20, 9, 21, 0, 1, -9, 0, 8, -3, + -7, -9, -3, 22, 8, 3, -11, -9, -11, 3, 15, 9, -10, 1, -3, -3, + -2, -5, 9, 0, 12, 7, -15, -7, 0, -8, 5, 9, -5, 7, -7, 10, + 4, -11, -2, -8, -4, 9, 9, 0, -2, -11, -3, -4, 3, 4, 3, -2, + 3, 3, -8, -9, -2, 0, 3, 5, -1, -10, -7, 2, 8, 3, 0, -5, + -5, 2, 4, -2, -5, -3, 2, 3, 0, 2, -5, -3, 3, 2, -2, -4, + -2, 1, 2, 1, 0, -1, 1, -2, -5, 0, 0, 2, 0, -3, -2, 0, + 1, 0, -2, -2, -2, 0, 3, 3, -2, -5, -1, -1, -1, -4, 3, 9, + 1, -1, -2, -11, -7, 1, 9, 11, 8, -4, -11, -12, -9, -4, 18, 15, + 14, 1, -22, -29, -14, 3, 30, 29, 14, -2, -35, -43, -11, 13, 36, 42, + 15, -16, -49, -44, -10, 28, 47, 38, 11, -25, -66, -39, 4, 36, 58, 33, + -3, -44, -65, -29, 19, 52, 54, 23, -13, -59, -65, -15, 32, 69, 49, 8, + -30, -74, -51, 3, 43, 71, 40, -5, -48, -77, -31, 16, 57, 67, 24, -15, + -67, -72, -12, 36, 66, 59, 5, -31, -80, -51, 3, 49, 75, 37, -2, -59, + -81, -28, 20, 67, 66, 22, -23, -76, -65, -10, 41, 78, 48, 4, -36, -85, + -47, 6, 59, 80, 31, -8, -69, -82, -22, 29, 73, 63, 17, -31, -81, -63, + -1, 47, 79, 47, 3, -56, -90, -40, 19, 75, 73, 28, -25, -86, -74, -10, + 48, 85, 56, 6, -51, -93, -48, 11, 67, 86, 33, -11, -78, -87, -29, 36, + 89, 66, 13, -38, -91, -60, 2, 50, 83, 48, 0, -56, -90, -41, 16, 71, + 78, 30, -17, -80, -75, -20, 31, 82, 62, 15, -32, -85, -66, -7, 48, 84, + 50, 4, -53, -87, -44, 8, 62, 78, 35, -8, -65, -83, -30, 23, 70, 71, + 24, -20, -76, -75, -12, 32, 73, 62, 15, -30, -85, -62, -2, 41, 76, 51, + 9, -39, -86, -52, 1, 45, 79, 46, 8, -49, -89, -46, 3, 54, 80, 43, + 7, -55, -83, -50, 0, 53, 76, 54, 11, -52, -83, -55, 0, 40, 67, 58, + 22, -32, -79, -67, -11, 28, 63, 52, 37, -9, -70, -63, -28, 10, 42, 49, + 53, 8, -46, -64, -41, 1, 22, 38, 51, 39, -16, -63, -46, -23, 5, 33, + 38, 48, 14, -42, -57, -29, -5, 22, 37, 40, 28, -23, -53, -39, -10, 14, + 30, 40, 31, -1, -48, -40, -18, 11, 19, 31, 26, 14, -20, -50, -25, -5, + 11, 31, 30, 14, 0, -35, -39, -4, -1, 19, 27, 17, 9, -10, -39, -21, + -8, 9, 24, 26, 13, -5, -19, -30, -12, -1, 17, 25, 16, 3, -19, -26, + -13, -6, 17, 22, 20, 5, -16, -32, -19, -1, 23, 27, 23, 4, -30, -33, + -23, -1, 35, 35, 24, -2, -41, -45, -21, 9, 45, 41, 22, -12, -50, -46, + -18, 28, 55, 45, 10, -27, -78, -42, 0, 53, 66, 32, -1, -61, -74, -28, + 27, 64, 64, 24, -28, -80, -66, -15, 53, 84, 48, 5, -59, -94, -41, 17, + 75, 80, 26, -21, -91, -79, -12, 48, 87, 55, 10, -58, -96, -46, 9, 80, + 81, 30, -23, -84, -80, -15, 49, 90, 49, 9, -57, -95, -45, 17, 76, 79, + 26, -20, -91, -75, -18, 52, 90, 52, 6, -59, -92, -41, 15, 68, 80, 31, + -21, -87, -76, -13, 45, 87, 49, 11, -60, -94, -35, 14, 80, 68, 22, -23, + -89, -66, -7, 47, 93, 44, -8, -61, -95, -31, 24, 86, 75, 10, -35, -96, + -66, -1, 61, 100, 44, -12, -77, -105, -33, 32, 97, 92, 16, -44, -111, -90, + -5, 65, 121, 65, -3, -80, -123, -59, 17, 98, 111, 46, -25, -112, -109, -33, + 42, 112, 90, 30, -55, -115, -84, -17, 66, 105, 71, 13, -73, -113, -61, 0, + 77, 96, 56, 4, -80, -108, -50, 8, 78, 93, 47, 3, -88, -98, -40, 7, + 65, 76, 53, 18, -71, -90, -44, 0, 39, 57, 43, 34, -19, -69, -54, -19, + 18, 32, 31, 34, 7, -40, -36, -21, -1, 12, 12, 25, 27, -9, -32, -14, + -14, 2, 0, 1, 20, 19, -2, -13, -11, -18, -12, -2, 18, 24, 12, -2, + -14, -19, -19, -12, 18, 24, 22, -2, -15, -32, -20, 3, 22, 26, 17, -13, + -31, -27, -13, 17, 33, 32, 5, -29, -47, -29, 2, 33, 42, 32, -6, -53, + -52, -24, 22, 51, 41, 27, -32, -74, -45, 0, 45, 59, 33, -1, -62, -66, + -31, 26, 73, 49, 17, -42, -80, -42, -8, 63, 72, 28, -10, -75, -72, -23, + 32, 88, 47, 13, -56, -93, -38, 10, 76, 69, 26, -20, -96, -66, -10, 48, + 90, 47, 0, -69, -103, -29, 25, 87, 73, 18, -35, -104, -68, -2, 61, 93, + 47, -5, -83, -98, -31, 30, 92, 68, 17, -39, -97, -63, -5, 64, 88, 35, + -9, -74, -86, -22, 31, 85, 54, 13, -44, -93, -46, 9, 65, 75, 23, -17, + -75, -78, -15, 39, 84, 54, 3, -52, -96, -46, 12, 71, 90, 29, -18, -89, + -87, -26, 36, 86, 72, 26, -37, -106, -77, -12, 45, 99, 68, 22, -46, -108, + -73, -10, 43, 87, 69, 19, -27, -92, -79, -12, 27, 63, 57, 26, 4, -53, + -75, -35, 12, 33, 37, 31, 26, -9, -53, -39, -16, 6, 20, 23, 22, 13, + -8, -22, -23, -18, -3, 9, 25, 19, 4, -8, -20, -17, -10, 6, 16, 17, + 13, -8, -34, -21, -6, 17, 33, 23, 6, -32, -51, -23, 11, 36, 46, 31, + -11, -46, -65, -31, 15, 59, 55, 28, -20, -73, -64, -26, 42, 78, 51, 14, + -53, -85, -48, -4, 70, 80, 38, -16, -80, -76, -32, 39, 90, 58, 19, -59, + -99, -50, 14, 71, 75, 36, -21, -94, -70, -23, 51, 88, 53, 9, -68, -97, + -40, 16, 83, 73, 29, -33, -100, -61, -13, 58, 87, 41, 0, -74, -81, -35, + 24, 87, 55, 20, -41, -88, -58, 0, 69, 73, 34, -5, -86, -75, -20, 38, + 79, 49, 13, -48, -90, -39, 2, 71, 68, 31, -16, -84, -67, -15, 38, 79, + 42, 12, -50, -85, -37, 2, 62, 71, 34, -5, -83, -75, -24, 27, 82, 51, + 27, -30, -88, -54, -15, 44, 73, 50, 16, -49, -81, -47, -6, 38, 58, 50, + 27, -31, -69, -52, -13, 15, 36, 45, 33, -5, -41, -44, -23, 2, 14, 27, + 33, 10, -25, -20, -18, -6, 1, -1, 17, 22, 3, -13, -10, -17, -13, -6, + 13, 24, 15, 1, -11, -19, -19, -16, 12, 24, 24, 3, -12, -29, -26, -1, + 18, 27, 19, -4, -31, -28, -19, 11, 30, 35, 12, -21, -46, -35, -6, 28, + 42, 36, 5, -46, -57, -31, 10, 50, 43, 33, -16, -71, -55, -9, 35, 62, + 38, 10, -51, -71, -40, 11, 69, 58, 24, -26, -81, -50, -18, 48, 79, 37, + 1, -62, -81, -32, 16, 84, 59, 20, -37, -96, -50, -2, 63, 78, 33, -4, + -85, -80, -20, 33, 88, 59, 10, -50, -107, -47, 14, 75, 85, 27, -19, -95, + -83, -15, 47, 94, 60, 8, -66, -105, -46, 15, 83, 81, 26, -23, -91, -76, + -18, 48, 92, 47, 1, -59, -94, -36, 18, 78, 66, 19, -27, -91, -60, -3, + 53, 80, 35, -8, -62, -86, -28, 27, 79, 66, 13, -38, -94, -62, 1, 56, + 95, 42, -6, -75, -96, -39, 22, 80, 80, 36, -20, -97, -92, -24, 30, 93, + 79, 32, -27, -102, -87, -22, 31, 81, 79, 29, -14, -81, -91, -25, 19, 56, + 63, 31, 11, -39, -77, -47, 3, 31, 37, 33, 27, 3, -48, -46, -20, 0, + 18, 22, 23, 16, -3, -20, -19, -15, -4, 2, 8, 5, 0, 0, 0, 1, + -1, -1, 3, -4, -2, 1, -1, -2, 2, 3, -6, 1, 2, -6, 2, 2, + -4, -1, 2, -5, 1, 4, -4, 0, -1, 0, -1, -2, 2, 2, -6, 0, + 4, -3, -3, 4, -2, -3, -2, 0, 1, 1, -2, -2, 3, -8, 27, -42, + 11, 21, -35, 34, -25, 12, 9, -24, 14, 13, -38, 53, -42, -3, 46, -73, + 55, -16, -9, 28, -49, 38, -12, -21, 49, -51, 20, 32, -73, 64, -28, -7, + 32, -50, 42, -11, -30, 49, -21, -31, 46, -25, -7, 20, -22, 18, -16, -10, + 21, -23, 5, 28, -35, 8, 0, 8, -26, 19, 6, -11, -20, 64, -46, -18, + 51, -73, 119, -117, 46, 36, -80, 67, -46, 22, 0, -24, 56, -59, 14, 26, + -40, 24, -9, 20, -20, -15, 43, -26, -11, 9, 14, -3, -31, 6, 54, -62, + 3, 67, -78, 20, 21, -25, 31, -41, 18, 27, -53, 32, 15, -48, 37, -11, + 4, -12, -3, 31, -24, -21, 42, -10, -45, 55, -32, 34, -43, -14, 86, -78, + 8, 39, -35, -2, 13, 2, 5, -11, -4, 7, 5, -31, 37, -4, -28, 28, + -9, -11, 10, -1, 4, -18, 17, -9, -13, 24, -18, 20, -18, -30, 59, -25, + -29, 48, -15, -29, 23, 4, -3, -18, 14, 6, -8, -19, 19, 8, -13, 0, + 13, -18, 4, 1, 0, 0, 10, -14, -12, 39, -46, 23, 9, -22, 23, -20, + -22, 63, -42, -28, 77, -66, 12, 38, -56, 31, 27, -77, 66, -11, -39, 59, + -33, -41, 92, -54, -50, 96, -36, -46, 46, -17, 31, -43, -28, 98, -57, -50, + 84, -22, -44, 39, -8, 17, -28, -13, 63, -67, 16, 10, 3, -15, -4, 36, + -34, -1, 26, -27, -2, 13, 7, -22, 0, 27, -11, -19, 6, 26, -42, 14, + 18, -7, -14, -10, 37, -14, -24, 25, -4, -5, -10, 3, 35, -39, -7, 31, + -8, -23, 15, 4, -1, -25, 28, 7, -35, 34, -16, -1, 9, -35, 45, -22, + -17, 48, -52, 24, 22, -65, 48, 7, -45, 47, -19, -33, 71, -70, 46, -7, + -52, 68, -25, -35, 48, -13, -17, 14, 2, -12, 8, -10, 1, 22, -32, 4, + 34, -26, -18, 29, -7, -19, 15, -7, 15, -8, -29, 50, -22, -35, 53, -19, + -37, 47, -9, -40, 41, 1, -27, 7, 3, 0, 0, -7, 13, -7, -21, 26, + 14, -44, 11, 40, -51, 10, 26, -28, 16, -13, -3, 31, -42, 11, 34, -52, + 11, 34, -43, 10, 29, -19, -21, 27, -10, -5, 10, -14, 11, 3, -35, 43, + 3, -52, 37, 22, -66, 49, -12, -19, 50, -58, 16, 42, -70, 50, -2, -42, + 60, -69, 43, 11, -57, 54, -8, -31, 23, -8, -7, 24, -32, 11, 21, -51, + 60, -44, -6, 68, -87, 33, 45, -79, 50, -7, -13, 21, -40, 31, 12, -41, + 18, 24, -39, 15, 7, -17, 25, -20, -12, 43, -47, 17, 6, -16, 10, 4, + -11, -1, 14, -10, -7, 6, 9, -23, 9, 3, 13, -30, 16, 16, -33, 17, + 4, -17, 23, -29, 3, 54, -86, 50, 11, -41, 30, -23, 15, 18, -60, 56, + 7, -65, 49, -4, -12, 1, -6, 19, -4, -33, 35, -10, -12, 13, -2, -2, + -2, 2, -10, 16, -8, -11, 19, -6, -19, 24, -14, 9, 3, -24, 24, -6, + -13, 19, -11, -6, 6, -9, 16, -8, -10, 14, -10, -1, -5, 16, -8, -25, + 37, -11, -27, 37, -14, -13, 19, -17, 14, -5, -15, 26, -27, 10, 11, -23, + 22, -5, -19, 25, -7, -28, 44, -35, 0, 25, -31, 31, -10, -26, 46, -41, + 2, 33, -40, 24, 8, -43, 44, -12, -25, 37, -25, -6, 29, -27, 5, 24, + -40, 24, -1, -25, 23, -1, -6, -2, -1, 14, -24, 8, 13, -11, 0, -13, + 16, 15, -56, 43, 12, -35, 14, -9, 18, -10, -19, 28, -3, -27, 23, -2, + -14, 27, -35, 10, 35, -68, 44, 7, -43, 46, -21, -25, 56, -35, -21, 51, + -33, -8, 28, -27, 19, -2, -26, 36, -26, 3, 13, -12, 6, -10, 8, -14, + 15, -12, 0, 13, -9, -16, 32, -27, 3, 23, -49, 49, -17, -31, 63, -64, + 25, 36, -76, 61, -11, -47, 75, -54, -9, 69, -81, 32, 29, -63, 46, -7, + -26, 39, -31, 6, 18, -26, 13, -5, 5, -5, -2, 5, -12, 17, -17, -2, + 22, -25, 1, 20, -19, 3, 6, -6, 3, -9, 10, -6, -3, 7, -7, -3, + 12, -5, -5, -11, 24, -7, -23, 24, 0, -14, 0, 12, -10, -2, 5, 0, + 1, -10, 10, -2, -17, 26, -11, -16, 28, -22, 6, 4, -17, 30, -27, -7, + 46, -54, 15, 29, -42, 25, -4, -15, 26, -29, 11, 15, -28, 19, -7, 1, + 8, -20, 14, 1, -15, 11, -2, -2, 0, -10, 15, -5, -12, 15, -1, -15, + 12, 4, -15, 9, -1, -9, 9, -5, -6, 13, -12, 1, 6, -6, -3, 6, + -4, 0, -6, 11, -9, -2, 13, -12, -2, -1, 8, -11, 4, 2, -6, 4, + -4, 4, 0, -13, 15, 0, -21, 23, -5, -15, 15, -2, -9, 6, -2, -4, + 2, 3, -1, -7, 7, -2, -9, 6, 2, -9, 4, 5, -12, 10, -9, 4, + 5, -16, 12, -2, -13, 20, -13, -4, 17, -23, 14, 2, -20, 22, -13, -3, + 15, -22, 12, 4, -18, 17, -7, -7, 13, -14, 6, 4, -10, 9, -5, -6, + 7, 0, -7, 8, -4, -1, 0, -6, 4, 7, -14, 2, 13, -16, 3, 10, + -15, 7, -1, -10, 14, -10, -2, 11, -9, -4, 7, -6, 3, -3, -5, 9, + -6, -3, 5, 1, -7, 3, -2, 0, -2, 0, 4, -3, -2, 4, -6, 4, + -2, -2, 0, 1, 0, -7, 7, -2, -7, 9, -7, -4, 11, -15, 11, -2, + -9, 9, -4, -3, 2, 3, -7, 5, 0, -5, 6, -7, 1, 7, -10, -2, + 13, -9, -4, 8, -4, -2, -1, 1, 1, -7, 4, 5, -8, 0, 6, -6, + 0, 3, -4, 0, 1, -2, 2, -4, -4, 8, -7, -1, 6, -9, 8, -3, + -6, 12, -12, 1, 10, -11, 1, 5, -6, 3, -2, -3, 7, -10, 2, 7, + -12, 5, 2, -5, 3, -5, 0, 6, -10, 3, 4, -8, 2, 2, -3, 3, + -8, 8, 2, -14, 10, 3, -12, 8, 2, -11, 8, -2, -6, 9, -7, -4, + 10, -9, -1, 7, -7, 1, 3, -8, 8, -2, -8, 10, -3, -5, 5, -6, + 3, 1, -8, 10, -5, -5, 7, -4, -2, 2, -3, 1, -1, -3, 4, -3, + 0, 0, 0, 0, -4, 3, -2, -3, 3, -5, 3, 0, -7, 5, 1, -8, + 5, 1, -6, 6, -5, 0, 3, -7, 3, 2, -6, 3, 2, -6, 3, 1, + -3, -2, 5, -4, -1, 3, -4, 0, 0, -3, 5, -5, -3, 7, -5, -3, + 6, -4, 0, -1, -3, 3, -2, -1, 2, -1, -2, 1, -2, 1, -1, -7, + 8, -1, 5, -7, 13, -22, 8, -7, 8, -110, -28, 24, 54, 36, 2, 60, + -45, 57, 42, -43, 20, 41, -66, 24, -11, 18, -18, -38, -63, -36, 30, -11, + 33, 25, 30, 18, 11, -18, -5, 5, -46, 40, 1, -13, -18, -20, -31, 20, + 10, 29, -7, -18, 40, -29, -17, 42, -19, 6, -4, 6, -8, 10, -26, -5, + 3, 1, -17, 6, 0, 19, -1, 8, 0, -6, -10, -1, -12, -1, 1, -3, + 8, -7, 4, 11, 4, 14, -13, 16, -19, -4, -13, -13, -14, 6, 4, -1, + 4, 11, -1, 11, -1, 1, -4, -1, -15, 6, -9, 1, -1, 0, 3, 1, + -8, 3, -1, -1, 2, -2, 2, -2, 1, -5, -7, 3, -3, 6, -3, 4, + -1, 0, -4, 2, -7, 3, -6, -1, -1, 4, 0, 3, -2, 2, -5, 5, + -8, -3, -3, 2, -5, 7, -1, 4, -2, 4, -10, 6, -6, -1, -4, 5, + -13, 7, -6, 5, -8, 17, -20, 14, -6, 9, -40, 71, -127, 9, -73, 127, + 76, -28, 74, -32, 8, -62, -49, -38, 40, -68, 22, -12, 68, 10, 39, -10, + 0, 35, -23, 0, -59, -15, -7, -3, -23, 1, -20, 37, 27, 2, 30, -2, + 17, 2, -5, -7, -27, -29, 16, -3, -11, 1, -16, -5, -8, -10, 7, 32, + 9, 5, -4, 16, 5, -8, -17, -16, 5, -13, 8, 11, 15, -10, -9, 0, + -1, 2, 7, -3, -23, 9, 2, 3, 1, -13, -1, -6, 11, -6, 8, 1, + 12, -12, 9, -14, 8, -1, 0, -3, -13, 4, -7, -4, 8, 5, -5, -7, + 4, -2, -3, 2, 3, -6, 8, -3, 1, -3, -2, 2, -6, 2, -4, -3, + -4, 3, 1, 0, 0, 1, -1, -1, 2, -2, 0, -4, -2, 1, 2, 0, + -3, 1, -3, 0, -1, -3, -6, 2, -2, 3, -4, 10, -8, 9, -5, 12, + -19, 46, 37, -128, 60, -90, 102, -65, 40, -57, 39, -6, 23, -8, 19, 24, + 15, -17, -47, -27, -36, -16, 21, 3, 23, 14, 50, -8, 19, 25, 7, -9, + -28, -63, -37, 0, -42, 54, -17, 68, -3, 30, -12, -4, 11, -15, 9, -25, + -15, -2, -27, -25, 38, -8, -13, 33, 24, 12, -38, 39, -12, -3, -17, -44, + 38, 2, 27, 3, -5, -4, -13, -30, -56, -4, 11, 1, 9, 17, 46, 25, + -14, 6, -3, -7, -21, 2, 16, -5, -22, 2, -2, 6, -12, -25, -15, 10, + 9, 8, 11, 43, 8, -5, -22, -16, 14, -31, 16, 7, -7, -26, -20, -2, + 9, 11, 26, 7, 6, -20, -13, 0, 4, 17, -17, -18, 10, 2, -10, 27, + -8, 24, -23, -14, 1, 0, 13, -19, 14, 10, -16, 16, -4, -20, 20, -33, + 2, 2, 24, 21, -3, -26, -24, -18, -18, 10, 10, 24, 18, 2, 9, -24, + 16, -14, -8, 9, -5, -14, 8, -5, 30, -11, 11, -13, -15, -12, 7, 4, + -13, -13, 13, -13, 12, 23, 9, 0, 14, -10, -9, -35, -2, -21, 12, -1, + 17, 19, 11, -4, 0, -18, -24, 11, -10, 1, 11, 12, -13, -16, 10, -23, + 21, 9, -9, 3, 12, -6, 3, -5, 12, 0, -2, 0, -19, -9, 5, -11, + -7, 10, 1, -3, 9, 18, -6, 0, -1, 1, -13, 2, 1, -3, -8, 17, + -4, -9, 18, -15, 8, -1, -11, -5, -14, 11, -5, -7, 12, 16, -7, 7, + -3, -11, -5, -6, 1, 4, -3, -3, 15, 5, 0, 3, 6, -16, 4, -14, + -6, -9, -4, 2, 11, 11, 7, -2, 4, -12, -7, -14, -6, -7, 9, 4, + 7, -2, 6, 5, 6, -4, -3, -4, 7, -7, -11, -9, 0, -3, 7, -2, + -2, 3, 13, -4, -6, -15, 9, -7, -1, 4, 6, 5, 8, -6, -8, 0, + -11, -4, 6, -8, 4, 3, 5, 13, -4, -9, -3, 4, -3, -3, 4, -1, + -12, 6, -14, 2, 3, 15, 2, 6, -7, -8, 3, 1, -2, 3, -3, -12, + -6, -14, 7, -2, 13, 6, 10, 6, 0, -2, -10, -12, -8, -6, -7, -6, + 6, 4, -2, 5, 2, 0, -1, 3, -11, 4, 0, 20, -8, -2, 0, -1, + -3, 7, -3, -4, -2, -6, -10, -10, -8, 1, 2, 5, 8, 2, 5, 8, + 3, 4, 3, -2, -15, 0, -1, -7, -2, -5, -10, 10, -1, 5, 3, 5, + -1, -2, -8, -5, -9, 1, -8, 6, 5, 4, 1, 1, 2, 3, -2, 4, + -7, 1, -7, -9, -2, 0, 2, 3, 6, -8, 8, 3, 0, -2, -9, -3, + -2, 0, 3, -1, -2, -3, 7, -3, 10, -8, 1, -12, 3, -7, 2, -3, + 7, 4, 4, 0, 0, -6, -1, -5, -3, -4, -7, 0, 5, 7, 0, 2, + -3, 10, -1, 3, -7, -5, -4, -9, -3, -7, 5, -4, 9, 2, 1, 4, + 5, 0, -5, 1, -8, 4, -9, 5, -5, 0, 3, -2, -1, 1, 1, -7, + 7, 0, 3, -5, 0, -3, -1, -1, -5, -1, 1, -1, 1, -1, 0, 2, + 0, 2, -7, -7, 4, -1, 0, 3, 4, -1, -3, -4, -6, 3, -2, 4, + -1, 5, -2, -1, -5, -2, -4, 1, 3, 2, 2, 0, -3, 1, 1, -3, + -3, -1, 1, -3, -2, -1, -2, -3, -1, 0, 4, 3, 5, 2, 1, -4, + -9, -3, -7, 1, -2, 7, -2, 3, 3, 3, 1, 0, -1, -6, -7, -6, + -4, -1, 1, 0, 5, 2, -2, 2, -3, -1, 3, -1, 1, -4, -4, -5, + 0, -7, 2, -4, 3, 4, 1, 2, -1, -1, -2, -2, 0, -1, 1, -1, + -1, -3, 1, 1, 3, -3, -1, 1, 1, -2, -3, -8, -5, 0, -1, 5, + 2, 3, 1, -2, -1, -1, -3, 1, 1, -2, -3, -3, -1, 0, -1, 1, + 2, 2, 5, 0, -1, -2, -1, -2, 0, -4, 0, -5, -1, -1, 0, 1, + 5, 4, -2, -1, -2, 0, -6, -1, 0, 1, -1, -2, 1, 0, 0, 3, + 1, -2, 1, -2, -4, -1, 0, -1, -1, -4, -2, -4, 2, -1, 1, 0, + 3, 2, 0, 4, -1, 4, -6, 2, -4, -3, -5, -4, -3, 0, 2, 0, + 1, 4, 2, 2, -2, -2, -5, -6, -5, -3, -2, 1, -1, 0, 0, 2, + 2, 2, 0, 4, -2, 3, 2, -1, -2, -3, -3, -3, -5, -5, -5, -1, + -1, 0, 2, 2, 4, 1, 2, 1, 2, -1, -1, -3, -4, -5, -3, -2, + -2, -1, 1, 4, 2, 2, 2, 1, -1, -2, -6, -2, -3, 2, -1, 1, + -2, 0, 2, 1, 2, -2, 1, 0, -2, -2, -3, 0, -2, -1, -1, 0, + -2, -2, 1, 0, 2, -1, 1, -1, 0, -1, -1, -7, 8, -1, 5, -7, + 13, -22, 8, -7, 8, -110, -28, 24, 54, 36, 2, 60, -45, 57, 42, -43, + 20, 41, -66, 24, -11, 18, -18, -38, -63, -36, 30, -11, 33, 25, 30, 18, + 11, -18, -5, 5, -46, 40, 1, -13, -18, -20, -31, 20, 10, 29, -7, -18, + 40, -29, -17, 42, -19, 6, -4, 6, -8, 10, -26, -5, 3, 1, -17, 6, + 0, 19, -1, 8, 0, -6, -10, -1, -12, -1, 1, -3, 8, -7, 4, 11, + 4, 14, -13, 16, -19, -4, -13, -13, -14, 6, 4, -1, 4, 11, -1, 11, + -1, 1, -4, -1, -15, 6, -9, 1, -1, 0, 3, 1, -8, 3, -1, -1, + 2, -2, 2, -2, 1, -5, -7, 3, -3, 6, -3, 4, -1, 0, -4, 2, + -7, 3, -6, -1, -1, 4, 0, 3, -2, 2, -5, 5, -8, -3, -3, 2, + -5, 7, -1, 4, -2, 4, -10, 6, -6, -1, -4, 5, -13, 7, -6, 5, + -8, 17, -20, 14, -6, 9, -40, 71, -127, 9, -73, 127, 76, -28, 74, -32, + 8, -62, -49, -38, 40, -68, 22, -12, 68, 10, 39, -10, 0, 35, -23, 0, + -59, -15, -7, -3, -23, 1, -20, 37, 27, 2, 30, -2, 17, 2, -5, -7, + -27, -29, 16, -3, -11, 1, -16, -5, -8, -10, 7, 32, 9, 5, -4, 16, + 5, -8, -17, -16, 5, -13, 8, 11, 15, -10, -9, 0, -1, 2, 7, -3, + -23, 9, 2, 3, 1, -13, -1, -6, 11, -6, 8, 1, 12, -12, 9, -14, + 8, -1, 0, -3, -13, 4, -7, -4, 8, 5, -5, -7, 4, -2, -3, 2, + 3, -6, 8, -3, 1, -3, -2, 2, -6, 2, -4, -3, -4, 3, 1, 0, + 0, 1, -1, -1, 2, -2, 0, -4, -2, 1, 2, 0, -3, 1, -3, 0, + -1, -3, -6, 2, -2, 3, -4, 10, -8, 9, -5, 12, -19, 46, 37, -128, + 60, -90, 102, -65, 40, -57, 39, -6, 23, -8, 19, 24, 15, -17, -47, -27, + -36, -16, 21, 3, 23, 14, 50, -8, 19, 25, 7, -9, -28, -63, -37, 0, + -42, 54, -17, 68, -3, 30, -12, -4, 11, -15, 9, -25, -15, -2, -27, -25, + 38, -8, -13, 33, 24, 12, -38, 39, -12, -3, -17, -44, 38, 2, 27, 3, + -5, -4, -13, -30, -56, -4, 11, 1, 9, 17, 46, 25, -14, 6, -3, -7, + -21, 2, 16, -5, -22, 2, -2, 6, -12, -25, -15, 10, 9, 8, 11, 43, + 8, -5, -22, -16, 14, -31, 16, 7, -7, -26, -20, -2, 9, 11, 26, 7, + 6, -20, -13, 0, 4, 17, -17, -18, 10, 2, -10, 27, -8, 24, -23, -14, + 1, 0, 13, -19, 14, 10, -16, 16, -4, -20, 20, -33, 2, 2, 24, 21, + -3, -26, -24, -18, -18, 10, 10, 24, 18, 2, 9, -24, 16, -14, -8, 9, + -5, -14, 8, -5, 30, -11, 11, -13, -15, -12, 7, 4, -13, -13, 13, -13, + 12, 23, 9, 0, 14, -10, -9, -35, -2, -21, 12, -1, 17, 19, 11, -4, + 0, -18, -24, 11, -10, 1, 11, 12, -13, -16, 10, -23, 21, 9, -9, 3, + 12, -6, 3, -5, 12, 0, -2, 0, -19, -9, 5, -11, -7, 10, 1, -3, + 9, 18, -6, 0, -1, 1, -13, 2, 1, -3, -8, 17, -4, -9, 18, -15, + 8, -1, -11, -5, -14, 11, -5, -7, 12, 16, -7, 7, -3, -11, -5, -6, + 1, 4, -3, -3, 15, 5, 0, 3, 6, -16, 4, -14, -6, -9, -4, 2, + 11, 11, 7, -2, 4, -12, -7, -14, -6, -7, 9, 4, 7, -2, 6, 5, + 6, -4, -3, -4, 7, -7, -11, -9, 0, -3, 7, -2, -2, 3, 13, -4, + -6, -15, 9, -7, -1, 4, 6, 5, 8, -6, -8, 0, -11, -4, 6, -8, + 4, 3, 5, 13, -4, -9, -3, 4, -3, -3, 4, -1, -12, 6, -14, 2, + 3, 15, 2, 6, -7, -8, 3, 1, -2, 3, -3, -12, -6, -14, 7, -2, + 13, 6, 10, 6, 0, -2, -10, -12, -8, -6, -7, -6, 6, 4, -2, 5, + 2, 0, -1, 3, -11, 4, 0, 20, -8, -2, 0, -1, -3, 7, -3, -4, + -2, -6, -10, -10, -8, 1, 2, 5, 8, 2, 5, 8, 3, 4, 3, -2, + -15, 0, -1, -7, -2, -5, -10, 10, -1, 5, 3, 5, -1, -2, -8, -5, + -9, 1, -8, 6, 5, 4, 1, 1, 2, 3, -2, 4, -7, 1, -7, -9, + -2, 0, 2, 3, 6, -8, 8, 3, 0, -2, -9, -3, -2, 0, 3, -1, + -2, -3, 7, -3, 10, -8, 1, -12, 3, -7, 2, -3, 7, 4, 4, 0, + 0, -6, -1, -5, -3, -4, -7, 0, 5, 7, 0, 2, -3, 10, -1, 3, + -7, -5, -4, -9, -3, -7, 5, -4, 9, 2, 1, 4, 5, 0, -5, 1, + -8, 4, -9, 5, -5, 0, 3, -2, -1, 1, 1, -7, 7, 0, 3, -5, + 0, -3, -1, -1, -5, -1, 1, -1, 1, -1, 0, 2, 0, 2, -7, -7, + 4, -1, 0, 3, 4, -1, -3, -4, -6, 3, -2, 4, -1, 5, -2, -1, + -5, -2, -4, 1, 3, 2, 2, 0, -3, 1, 1, -3, -3, -1, 1, -3, + -2, -1, -2, -3, -1, 0, 4, 3, 5, 2, 1, -4, -9, -3, -7, 1, + -2, 7, -2, 3, 3, 3, 1, 0, -1, -6, -7, -6, -4, -1, 1, 0, + 5, 2, -2, 2, -3, -1, 3, -1, 1, -4, -4, -5, 0, -7, 2, -4, + 3, 4, 1, 2, -1, -1, -2, -2, 0, -1, 1, -1, -1, -3, 1, 1, + 3, -3, -1, 1, 1, -2, -3, -8, -5, 0, -1, 5, 2, 3, 1, -2, + -1, -1, -3, 1, 1, -2, -3, -3, -1, 0, -1, 1, 2, 2, 5, 0, + -1, -2, -1, -2, 0, -4, 0, -5, -1, -1, 0, 1, 5, 4, -2, -1, + -2, 0, -6, -1, 0, 1, -1, -2, 1, 0, 0, 3, 1, -2, 1, -2, + -4, -1, 0, -1, -1, -4, -2, -4, 2, -1, 1, 0, 3, 2, 0, 4, + -1, 4, -6, 2, -4, -3, -5, -4, -3, 0, 2, 0, 1, 4, 2, 2, + -2, -2, -5, -6, -5, -3, -2, 1, -1, 0, 0, 2, 2, 2, 0, 4, + -2, 3, 2, -1, -2, -3, -3, -3, -5, -5, -5, -1, -1, 0, 2, 2, + 4, 1, 2, 1, 2, -1, -1, -3, -4, -5, -3, -2, -2, -1, 1, 4, + 2, 2, 2, 1, -1, -2, -6, -2, -3, 2, -1, 1, -2, 0, 2, 1, + 2, -2, 1, 0, -2, -2, -3, 0, -2, -1, -1, 0, -2, -2, 1, 0, + 2, -1, 1, -1, 0, -1, -1, 1, -7, 5, -22, -32, -35, -32, -43, -35, + -55, -42, -66, -48, -80, -57, -17, -128, -59, -76, 0, -26, 1, -33, 21, 3, + 16, 15, 26, 43, 28, 66, 6, 97, 40, 103, 67, 101, 102, 98, 94, 21, + 98, 90, 57, 78, 89, 81, 61, -6, 54, 4, 62, 19, 27, 34, 12, 16, + 14, -17, 19, -5, -2, -13, -38, -24, -3, -33, -14, -11, -16, 0, -13, 7, + -26, -13, -16, 6, -57, -23, -28, -13, -9, -34, -32, -20, -87, -62, -28, -38, + -75, -37, -27, -41, -71, -48, -30, -44, -83, -67, -52, -48, -45, -46, -45, -63, + -47, -40, -32, -45, -24, -32, -43, -21, -17, 0, 21, 26, 43, 51, 62, 47, + 41, 55, 57, 68, 34, 53, 63, 62, 71, 60, 61, 56, 53, 56, 54, 38, + 50, 58, 50, 40, 28, 54, 39, 41, 38, 22, 32, 20, -3, 19, -1, -7, + -6, -16, -16, -14, -27, -29, -46, -66, -61, -51, -54, -61, -41, -50, -47, -52, + -55, -45, -44, -28, -58, -56, -31, -37, -36, -32, -18, -16, -34, -29, -9, -21, + -20, -30, -22, -17, -19, -8, -12, -14, -6, -14, -6, -11, -2, 4, -6, 9, + 8, 17, 23, 13, 31, 13, 24, 30, 28, 29, 30, 43, 34, 37, 52, 42, + 44, 50, 67, 59, 49, 54, 48, 43, 51, 45, 42, 62, 47, 39, 37, 36, + 24, 28, 13, 3, 9, -11, -3, -9, -14, -18, -34, -27, -29, -39, -42, -38, + -46, -37, -46, -43, -41, -35, -38, -31, -38, -34, -39, -39, -34, -48, -44, -47, + -49, -54, -52, -44, -53, -37, -47, -38, -31, -38, -27, -19, -19, -15, -16, 0, + 0, 2, 7, 13, 29, 22, 32, 32, 39, 47, 41, 40, 55, 48, 41, 44, + 57, 43, 36, 47, 43, 42, 37, 32, 32, 27, 33, 36, 30, 23, 25, 25, + 22, 18, 22, 20, 16, 8, 6, 12, 7, 0, 1, 3, -5, -14, -9, -7, + -8, -19, -15, -16, -23, -21, -21, -32, -31, -29, -26, -27, -29, -33, -26, -29, + -30, -39, -28, -41, -43, -35, -34, -32, -29, -28, -28, -25, -27, -24, -27, -27, + -27, -22, -23, -17, -9, -10, -14, -10, -8, -4, -2, -1, -3, 5, 4, 10, + 11, 7, 13, 11, 14, 27, 22, 22, 22, 27, 36, 34, 36, 37, 45, 44, + 47, 48, 51, 49, 52, 51, 52, 48, 50, 47, 48, 42, 40, 29, 33, 24, + 22, 12, 5, 0, -3, -5, -9, -21, -21, -25, -19, -28, -28, -30, -33, -39, + -42, -42, -46, -46, -45, -42, -43, -47, -47, -36, -32, -30, -34, -31, -22, -29, + -29, -30, -26, -28, -30, -21, -26, -27, -21, -19, -16, -11, -12, -8, -2, 1, + -4, 1, 0, 1, 9, 8, 7, 12, 10, 13, 20, 17, 18, 21, 26, 29, + 30, 30, 29, 34, 33, 34, 33, 30, 32, 33, 28, 33, 29, 35, 32, 31, + 30, 31, 30, 25, 27, 24, 21, 21, 20, 16, 17, 12, 6, 4, -3, 1, + -6, -7, -11, -13, -11, -10, -8, -13, -12, -9, -17, -14, -19, -24, -22, -24, + -30, -32, -30, -33, -37, -39, -40, -42, -39, -41, -39, -40, -41, -35, -35, -35, + -37, -36, -33, -30, -25, -25, -19, -16, -16, -10, -6, -7, -4, -2, 1, 3, + 6, 10, 9, 15, 17, 18, 17, 13, 19, 18, 17, 19, 20, 24, 24, 27, + 27, 29, 30, 26, 28, 28, 27, 28, 26, 25, 24, 25, 20, 19, 17, 18, + 15, 12, 13, 10, 6, 8, 6, 3, 4, 3, 0, -3, 0, -1, -2, -5, + -4, -5, -4, -5, -6, -8, -9, -9, -12, -11, -16, -16, -15, -15, -13, -17, + -16, -17, -17, -21, -20, -25, -24, -24, -24, -26, -30, -30, -27, -30, -26, -26, + -27, -27, -25, -24, -19, -20, -17, -13, -12, -8, -8, -8, -6, -5, -2, -1, + 0, 3, 8, 10, 12, 16, 18, 24, 25, 25, 28, 30, 28, 32, 33, 31, + 32, 31, 35, 33, 31, 31, 27, 28, 26, 23, 23, 20, 22, 18, 16, 13, + 11, 9, 5, 4, -2, -2, -3, -8, -9, -11, -12, -13, -15, -15, -15, -15, + -15, -14, -12, -12, -13, -13, -8, -11, -10, -12, -10, -12, -12, -8, -8, -9, + -9, -9, -8, -9, -10, -11, -11, -10, -13, -14, -13, -16, -16, -17, -17, -18, + -19, -18, -17, -16, -16, -15, -15, -13, -12, -10, -12, -10, -9, -8, -6, -6, + -3, 0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 15, 15, 14, 13, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, + 3, 2, 1, 0, -1, -1, -2, -3, -4, -5, -5, -6, -7, -7, -8, -9, + -9, -10, -11, -11, -12, -12, -13, -13, -13, -13, -14, -14, -14, -15, -15, -15, + -15, -15, -15, -16, -16, -16, -15, -15, -15, -14, -13, -13, -12, -11, -10, -9, + -8, -7, -6, -5, -4, -2, -1, 0, 1, 2, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 16, 16, 15, 15, 14, 14, 13, 12, 11, 10, + 9, 7, 6, 5, 3, 1, 0, -2, -4, -5, -7, -9, -10, -11, -13, -14, + -15, -15, -16, -17, -17, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -17, -17, -16, -16, -15, -14, -14, -13, -12, -11, -10, -9, -8, -7, -6, + -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, + 11, 11, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 14, 14, 14, 13, 12, 12, 11, 10, 9, 8, 8, 7, + 6, 5, 4, 3, 2, 1, 0, 0, -1, 10, -20, 30, 25, 21, 14, 4, + 15, -48, -33, 11, -70, 54, -5, -21, -8, -3, 73, -52, 65, -55, 80, -28, + -67, -3, -13, 21, -49, -2, 11, 36, 59, -60, 34, -28, 21, -25, -45, 54, + 5, 0, -19, -12, 20, 54, -51, -23, 22, 36, -59, -20, 8, 28, -9, -54, + 127, -44, 69, -128, 5, 69, -8, -98, 45, 69, 20, -97, 23, -7, 121, -81, + -2, -21, 51, -67, -14, -24, 127, -60, 45, -116, 127, -29, -93, -23, 107, -5, + -21, -62, 37, 41, 29, -74, -63, 103, 24, -59, -44, 62, 43, -28, -46, 7, + 72, 19, -70, -47, 42, 53, -68, -13, 37, 59, -38, -60, 39, 66, 27, -128, + 36, 77, 15, -74, -15, 75, 38, -49, -11, -39, 16, -8, -30, 35, 41, -1, + -2, 17, -68, 99, -97, 60, -49, 32, -44, -29, 82, -26, 39, -35, 10, 38, + -20, -21, -92, 83, -24, 13, 31, -33, 22, 45, -31, -24, 9, -24, -32, 42, + -17, 34, 7, -27, 6, 61, -9, -34, -5, -8, -17, -6, -34, 17, 43, -9, + 35, -34, 16, 27, -24, -17, -17, 5, -17, 42, -31, 22, 17, -26, -22, 32, + 41, -27, -25, -10, -5, 16, -2, 13, -1, 48, -33, -27, 6, 16, 13, -37, + -11, 18, 25, -42, -11, 46, -7, -15, 9, 15, 4, -3, -36, -24, 31, -8, + 14, 12, 27, -19, -17, -14, -7, 42, -5, -15, 5, 1, -15, 14, 43, -19, + 1, -25, -35, 16, 16, 29, -12, 8, -14, 1, 21, -8, -12, -22, -4, 24, + 26, -16, -22, 37, 3, -41, 7, 4, 3, 30, 4, -27, 11, -6, -26, 33, + 23, -23, -14, -20, -7, -4, 36, 0, 18, 10, -27, 1, 1, 16, -1, -4, + -44, -5, 17, 9, 13, -4, -3, 31, 24, -14, -26, 9, -27, -28, 19, 22, + 32, -11, -15, 5, 15, -23, -21, 16, 14, 18, -11, -26, 13, 10, -12, -12, + 11, 14, -6, -13, -3, 6, -6, 3, 12, 32, 14, -22, -45, -10, 37, 11, + -50, -11, 50, 22, -13, -4, -4, 15, -16, -33, 7, 34, -9, -14, -1, 21, + 15, -14, -12, -6, 7, 8, 2, 0, -5, 6, 15, 4, -9, 13, 3, -51, + -18, 27, 10, 5, -11, 6, -1, 5, 22, 2, -14, -39, -12, 19, 17, 4, + 11, 5, -25, 2, 23, 8, 2, -3, -39, -22, 4, 18, 6, 14, 25, 20, + -17, -20, 17, 7, -43, -38, -18, 17, 24, -6, 30, 44, 6, -36, -20, 7, + 24, 1, -69, -25, 47, 15, -4, 35, 19, -18, -22, -12, 20, 39, -36, -49, + 9, 28, -16, 9, 34, 36, -22, -69, -16, 39, 7, -28, -3, 33, -18, -7, + 18, 53, 24, -37, -61, -10, 38, 2, -24, -11, 12, 17, 0, 28, 50, -5, + -59, -57, 22, 14, -15, -5, 22, 9, -20, 19, 33, 31, -33, -62, -13, -2, + 45, -9, -4, -3, 19, 8, -8, 40, 8, -16, -44, -19, 16, 3, 23, -32, + 22, 5, -9, 5, 26, 21, -27, -18, -45, 3, 15, 0, 7, 7, 7, 13, + 18, -10, 3, -5, -30, -30, -3, 9, 31, 17, -10, 19, 28, -33, -20, 31, + 14, -67, -27, 13, 20, 29, 1, -2, 24, -3, -26, -12, 32, -7, -31, -17, + 5, 22, 11, -6, 6, 7, 2, 7, 5, -12, -22, -17, -24, 22, 47, 1, + 2, 10, 5, -29, -5, 13, 1, -30, -28, -5, 23, 25, 6, 5, 1, 7, + 0, 5, 3, -33, -37, -6, 19, 20, 26, -1, -15, 21, 9, -14, -13, 0, + -11, -24, -9, 9, 23, 1, 1, 32, 11, -25, -18, 5, -5, -6, -9, -10, + 2, 18, 4, 12, 6, -2, -8, 2, 2, -7, 2, -22, -5, 17, 25, 15, + -5, -1, -24, -8, -10, -5, 12, 7, -4, -10, 4, 8, 22, 11, -1, -12, + -31, -17, 6, 12, 11, 5, -3, -1, 22, 0, -4, 3, -18, -17, -3, 16, + 9, 2, -5, 0, 4, -9, 18, 17, -22, -19, -8, -6, 21, 11, -6, -16, + 33, 13, -15, -3, -15, 1, -3, -10, -7, 8, 17, -11, 9, 19, 0, 5, + 0, -18, -13, 2, -20, 10, 29, -11, -13, 5, 11, 16, 4, -25, -21, 13, + -5, 1, 3, -1, 6, 13, -7, -1, 17, -6, -6, -9, -6, -3, -1, 1, + 18, 11, -22, 2, 18, -2, -15, 1, 5, -12, -10, -7, 9, 26, 10, -11, + 5, 0, -7, -3, -11, -9, -3, 2, -10, 19, 28, -3, -3, -4, 9, -14, + -5, -7, 8, -3, -27, 5, 37, 11, -2, 3, -27, -15, 12, -2, 14, 2, + -8, -16, 22, 11, -1, 10, -17, -8, -5, -23, 2, 29, 8, -21, 8, 12, + 6, 8, -17, 3, -2, -12, -27, 16, 25, -5, -7, 2, 19, 1, -15, 7, + 2, -5, -34, 2, 18, 17, -10, 2, 18, -1, -12, -10, 5, 1, -16, -9, + 12, 21, 4, -10, 2, 12, 1, -19, -11, 20, 5, -14, -21, 5, 17, -5, + 3, 17, 4, -25, -5, 5, 4, 0, -5, 2, 2, -1, 1, 13, 0, -11, + -8, 3, 2, -1, -3, -3, 11, 8, -6, 2, 7, 4, -5, -23, -2, 14, + -1, -15, -2, 15, 10, 1, -4, 16, 1, -24, -12, 8, 8, -20, -2, 14, + 13, 10, 2, 2, -9, -6, -9, -3, 5, 7, -3, -9, 0, 2, 8, 3, + -1, 2, -4, 0, -2, 0, -2, 3, 5, -4, -28, 22, -43, 36, -13, -127, + -43, 2, -18, 126, 78, -127, -48, 68, -74, -67, 33, 62, 83, 42, -32, -46, + -70, -26, 115, 21, -66, 72, 52, -27, 44, 50, 50, 61, 28, -12, 3, -59, + 49, 3, -19, 39, 94, 16, 31, 6, 29, 3, -100, -1, -4, -60, 19, 7, + -29, -28, -38, -3, -47, -20, -21, -1, 5, -55, -12, -55, -39, 26, 47, -22, + -9, -41, -21, -19, -37, 0, 45, -56, 24, 75, -50, -9, 31, 28, 26, 13, + -3, -15, -27, 1, 1, -31, -10, 38, -1, 7, 43, 19, 21, 41, 33, 9, + -17, -3, -42, -76, -30, -8, -9, -1, 21, 22, 38, 32, 22, 0, -18, -32, + -58, -12, 5, -48, -13, 64, 29, -2, 2, 19, 43, 25, -19, -39, -69, -92, + -15, 23, 30, 30, 51, 37, 35, 37, 30, -27, -63, 5, -30, -56, -16, 26, + 52, 20, 14, 59, 27, -9, 22, -4, -20, -37, -17, -34, -34, -1, 35, 26, + 31, 5, -16, 4, 33, 22, 8, 5, -28, -41, -20, -10, -6, -2, -16, 12, + 31, -23, 7, -2, -39, -28, -13, 8, 5, 16, -4, -6, -18, -24, -27, -50, + -6, 5, 12, 0, -2, -14, -23, 5, -28, -10, 2, 28, 15, 2, 22, 27, + 41, 31, 2, 12, 31, 5, 12, -6, 15, 40, 34, 18, 26, 26, 12, 34, + 23, 34, 30, 22, 10, -26, -22, 1, 0, -1, 12, -4, -21, -5, -5, -20, + -31, -25, -24, -42, -44, -41, -41, -37, -29, -28, -29, -40, -17, -21, -38, -42, + -38, -40, -36, -13, -14, -8, -15, -7, -6, 5, 12, -1, -17, -1, 9, 2, + 16, 30, 27, 37, 36, 38, 36, 36, 19, 45, 45, 33, 26, 33, 28, 36, + 31, 17, 12, 22, 11, 11, 17, 5, -13, 6, 10, 2, -6, 2, 9, 15, + -6, -8, -23, -44, -3, -11, -35, -25, -35, -23, -21, 0, -11, -21, -17, 11, + -6, -11, -17, -33, -16, -16, -4, -7, -7, -9, -4, 1, 1, -3, 6, 7, + 4, -17, -11, -6, -4, 1, 3, 6, 4, 5, -4, 17, 7, 3, 9, -20, + 0, -7, -3, -5, 4, 9, 16, 2, 3, 8, 15, 15, 1, -3, 8, -1, + 5, 14, 7, 4, 8, -8, 2, -3, 5, 11, 5, 3, -4, 10, 17, 13, + -11, -5, 1, -3, 0, -6, -12, 2, -3, 13, -5, -25, -15, -7, 4, 1, + -8, -4, -12, -16, 3, 9, -6, 3, -21, -4, 4, -14, 1, -1, -2, 3, + -8, -5, 0, 7, -2, -3, -1, 3, -9, 5, -4, -17, -1, 9, 3, 7, + 1, -4, -3, 5, 2, -7, -9, 12, -6, -14, -16, 2, -1, 16, 2, 2, + 7, -6, -26, 3, -2, -4, -2, 10, 3, -7, 3, 8, 9, 5, 4, 1, + -5, -5, 11, 8, 7, 11, 12, -1, -5, -16, 13, 7, 2, 11, 4, -4, + 9, -8, -8, 14, 11, -8, 0, -1, -5, -2, -1, -10, -5, -9, -9, -16, + -12, -8, -16, 5, -10, -4, -11, -3, 1, 0, -3, -5, -13, -9, -2, -8, + 5, -9, -7, -2, 2, -11, -7, 13, 8, -3, 2, 7, -2, -1, 5, 0, + 11, 6, 13, 15, 1, -4, 9, 5, 3, 8, -3, -4, 16, 4, 11, 9, + 0, 8, 1, -6, -5, -18, 3, 7, -18, -4, 0, -3, -3, -6, -4, -5, + -5, -10, -2, -9, -5, -2, -4, -11, -2, 1, -5, -2, 11, -6, -9, 1, + 4, -6, -1, -5, 1, 2, 9, 5, 0, 4, 4, -2, 7, 0, -10, 5, + 2, -3, 0, -6, 7, -4, -3, 6, -1, -6, -1, -1, 2, -2, -6, -3, + 0, 8, -6, 4, -1, -5, -3, 3, 1, -5, -6, -2, -3, 5, 6, 0, + 7, -3, 3, -1, 0, -2, 9, 1, 1, -3, 4, 5, -5, 2, -2, 2, + -11, -2, -4, 11, 4, 5, 0, -5, -12, -6, -5, -5, 3, -2, -2, 2, + 2, 1, 0, -1, -8, -5, -5, -3, 2, -1, 3, -1, 3, 0, -1, 0, + -1, 1, 1, -4, -4, 2, -2, 1, -6, 1, 2, 4, 2, 2, -5, -1, + 6, -3, -1, -4, 11, 3, -9, -2, -6, -3, 2, 4, 2, 1, 2, 4, + 3, -6, -4, -3, -2, 0, 2, -2, 5, 2, -1, 3, -9, -3, -3, -4, + -4, -1, 0, -2, 7, 3, 1, 1, -2, -4, -2, -3, -2, -4, 2, 4, + -1, 2, 3, 0, 3, -1, 0, -2, -2, -3, 1, -1, -4, 5, -1, 5, + 0, -3, -2, -1, -4, 3, -1, -3, -2, -2, -1, 0, 0, 1, -1, 0, + -2, -2, 0, -3, -1, 0, 0, 1, 1, -2, -1, 1, -3, 1, 2, 0, + -1, 0, -1, 1, 5, -2, 1, -3, -3, -1, -3, 0, 1, 3, 2, -1, + -1, -2, -2, -1, 1, 30, -9, -44, 13, 26, -53, -41, 2, 76, 47, 40, + -52, -53, -5, 12, -33, 15, 62, 53, -27, -98, -26, -42, 52, 75, 43, -32, + -3, -83, -13, -36, 35, 39, 56, 25, -9, -122, -22, -3, 79, -6, 6, 25, + -20, -12, -40, -19, 15, 74, 37, -14, -33, 6, 25, 7, -10, -4, 42, 4, + -33, -87, -55, 29, 39, 21, -34, -27, 1, 26, 5, -22, -13, 10, 56, 0, + -26, -40, 30, 42, 23, -7, -23, 28, 21, 9, -37, -25, 11, 25, 8, -48, + -19, -15, 41, -2, -30, -28, 4, 30, -12, -23, -28, 17, 38, 3, -12, -8, + 17, 26, 9, -32, 0, 12, 49, -3, -29, -17, 2, 41, -17, -24, -17, 9, + 30, -23, -22, -21, 19, 17, -12, -35, -18, 12, 29, 2, -27, 7, 14, 42, + -11, -24, -3, 15, 40, -23, -24, -17, 21, 22, -10, -23, -10, 23, 13, -4, + -37, 0, 15, 19, -12, -40, -2, 13, 30, -16, -22, -3, 22, 22, -13, -16, + -7, 34, 9, -5, -34, -5, 29, 10, -3, -39, 3, 17, 14, -13, -25, 5, + 21, 12, -18, -22, -8, 31, 8, -5, -27, -9, 30, 1, -3, -30, 6, 27, + 4, -14, -31, 8, 25, 10, -14, -21, -3, 24, 4, -11, -17, -1, 30, -1, + -12, -26, 3, 32, 3, -13, -26, 5, 23, 3, -14, -17, 6, 22, 1, -17, + -16, 4, 25, 4, -18, -19, 4, 23, 5, -17, -14, 5, 21, 1, -20, -11, + 7, 23, 2, -19, -17, 8, 19, 6, -18, -15, 10, 14, 6, -26, -5, 11, + 15, 4, -27, -5, 4, 22, 1, -17, -12, 6, 15, 1, -16, -13, 20, 8, + 4, -28, -7, 17, 9, 10, -31, 3, 1, 13, 0, -18, 0, 6, 17, -10, + -14, -15, 21, 10, 3, -19, -14, 22, -4, 11, -27, 8, 9, 7, -2, -26, + 8, 2, 23, -13, -7, -13, 12, 11, -11, -2, -15, 27, -8, 2, -22, 0, + 18, 0, 6, -27, 10, -4, 19, -13, -7, 1, 2, 19, -26, 7, -17, 28, + -2, -8, -6, -11, 23, -9, 10, -24, 12, -2, 10, -8, -14, 13, -5, 25, + -33, 7, -11, 17, 8, -19, 9, -18, 26, -17, 6, -12, 8, 8, -5, 0, + -23, 20, -10, 25, -24, 2, 0, -2, 17, -30, 22, -16, 25, -15, -7, -2, + -4, 21, -15, 13, -25, 19, -11, 9, -8, -7, 19, -15, 20, -34, 17, -9, + 15, 0, -15, 11, -17, 24, -24, 16, -15, 15, 0, -11, 6, -21, 30, -18, + 18, -22, 6, 3, -6, 10, -20, 23, -17, 20, -23, 7, -3, 2, 16, -24, + 18, -26, 27, -15, 5, -2, -5, 19, -21, 12, -22, 22, -9, 9, -11, -5, + 11, -13, 21, -27, 22, -17, 13, -5, -13, 14, -14, 28, -24, 9, -16, 12, + 3, -7, 5, -14, 22, -20, 14, -21, 14, 3, -2, 6, -26, 20, -17, 23, + -17, 3, 0, -2, 11, -23, 14, -14, 26, -14, 0, -10, -3, 18, -14, 15, + -24, 19, -9, 4, -8, -9, 18, -6, 15, -29, 11, -10, 16, -1, -11, 9, + -13, 23, -23, 8, -13, 12, 10, -11, 0, -20, 22, -7, 12, -19, 4, 4, + 1, 4, -23, 18, -10, 22, -17, -7, 0, -1, 23, -20, 6, -18, 18, 0, + -3, -8, -5, 20, -8, 6, -27, 14, 2, 11, -5, -20, 13, -10, 24, -22, + 3, -5, 11, 8, -20, 1, -12, 28, -7, 0, -19, 2, 15, -5, 6, -25, + 20, -4, 13, -19, -10, 10, 5, 17, -27, 1, -10, 22, -2, -10, -2, -7, + 26, -18, 4, -24, 18, 10, 1, -8, -23, 16, 2, 15, -22, -1, 3, 10, + 5, -27, 9, -8, 35, -19, -3, -18, 7, 19, -7, -3, -16, 14, 6, -5, + -9, -12, 23, -5, 11, -33, 19, -10, 23, -22, 3, -5, 14, -2, -8, -8, + 7, 7, 2, -14, 0, -2, 17, -14, 3, -17, 20, -5, 7, -19, 3, 3, + 10, -5, -9, -4, 6, 6, -2, -10, 1, 2, 12, -13, 0, -11, 18, -3, + 3, -16, 2, 4, 7, -5, -6, 0, 6, 1, -6, -6, 4, 6, 5, -11, + -2, -4, 12, -6, 1, -9, 9, 0, 1, -11, 0, 6, 5, -2, -11, 1, + 2, 7, -5, -7, 3, 1, 8, -13, 0, -6, 15, -3, -2, -11, 1, 9, + 1, -2, -12, 6, 2, 5, -9, -5, 3, 6, 5, -12, -3, -3, 12, 0, + -5, -7, 0, 8, -2, -2, -9, 7, 3, 5, -11, -4, 0, 9, 2, -7, + -6, 0, 7, 1, -6, -3, 1, 8, -4, -5, -7, 7, 4, 4, -11, -1, + -2, 10, -5, -1, -7, 8, 1, 1, -12, 1, 4, 7, -4, -8, -4, 8, + 0, 3, -16, 11, -7, 1, 0, 0, -1, -1, -4, 1, -1, -3, -13, -8, + -14, -3, -2, -2, 1, 8, 5, 7, -21, -13, -2, -6, -8, -22, -6, 5, + 11, 34, 41, 33, 13, 28, 33, 48, 35, 21, -3, -26, -18, -10, 3, 7, + 22, 21, 63, 40, 41, 43, 4, -8, -43, -63, -77, -77, -59, -18, 3, 2, + -21, -46, -74, -90, -108, -101, -94, -89, -84, -85, -77, -59, -50, -33, -7, 18, + 37, 47, 64, 101, 127, 125, 127, 126, 126, 126, 122, 100, 87, 62, 37, 28, + 27, 25, 27, 34, 25, -4, -45, -85, -123, -128, -126, -128, -127, -123, -92, -73, + -55, -45, -37, -33, -32, -33, -43, -53, -55, -43, -20, 3, 20, 34, 42, 49, + 55, 63, 74, 84, 93, 101, 107, 112, 117, 109, 92, 63, 33, 8, -13, -25, + -29, -30, -27, -27, -32, -46, -63, -82, -98, -109, -116, -121, -118, -104, -80, -49, + -12, 21, 45, 58, 64, 66, 66, 61, 51, 44, 37, 32, 32, 33, 33, 28, + 23, 15, 8, 3, 2, 9, 16, 20, 24, 23, 14, -1, -20, -37, -48, -53, + -52, -47, -38, -26, -13, -5, -1, -4, -10, -22, -34, -43, -48, -46, -34, -16, + 5, 25, 45, 65, 78, 84, 83, 71, 55, 39, 24, 9, -3, -12, -23, -34, + -45, -57, -65, -71, -71, -63, -49, -34, -21, -11, -2, 2, 8, 11, 12, 14, + 14, 20, 28, 38, 50, 58, 63, 61, 56, 46, 33, 17, -1, -19, -34, -45, + -48, -44, -32, -19, -5, 5, 7, 4, -2, -7, -11, -15, -18, -21, -23, -26, + -28, -30, -31, -29, -26, -20, -12, -1, 11, 21, 32, 42, 51, 55, 55, 52, + 46, 41, 37, 32, 30, 28, 27, 24, 19, 12, -1, -21, -45, -67, -89, -103, + -107, -101, -90, -70, -51, -33, -18, -2, 11, 23, 33, 39, 44, 49, 52, 57, + 59, 59, 56, 52, 48, 41, 35, 28, 20, 15, 11, 4, 0, -5, -11, -18, + -25, -34, -42, -47, -48, -46, -40, -33, -27, -24, -21, -24, -32, -42, -51, -56, + -58, -56, -47, -35, -18, 2, 24, 48, 70, 88, 99, 104, 102, 97, 89, 79, + 69, 59, 49, 37, 27, 14, 0, -14, -29, -44, -58, -71, -81, -87, -88, -88, + -85, -81, -77, -72, -63, -51, -37, -21, -5, 12, 29, 43, 53, 59, 61, 57, + 48, 36, 24, 13, 8, 8, 15, 25, 38, 48, 54, 54, 50, 43, 33, 22, + 11, 3, -6, -15, -25, -35, -46, -54, -61, -65, -68, -69, -69, -68, -64, -59, + -52, -43, -32, -20, -7, 6, 19, 31, 42, 51, 58, 62, 64, 62, 58, 52, + 44, 35, 26, 17, 9, 1, -5, -10, -15, -18, -19, -20, -19, -18, -16, -15, + -14, -14, -15, -16, -17, -18, -19, -19, -19, -19, -18, -16, -14, -11, -9, -6, + -3, 0, 3, 6, 10, 14, 18, 22, 27, 32, 35, 37, 37, 35, 30, 23, + 14, 4, -6, -15, -24, -31, -36, -39, -40, -39, -37, -32, -26, -19, -10, -1, + 8, 17, 24, 29, 32, 33, 32, 29, 25, 20, 15, 11, 7, 3, -1, -5, + -9, -14, -19, -24, -28, -31, -32, -31, -27, -23, -16, -10, -3, 2, 7, 10, + 12, 13, 13, 13, 12, 10, 8, 7, 5, 5, 5, 5, 6, 8, 10, 13, + 17, 20, 23, 25, 26, 25, 21, 16, 9, 1, -7, -16, -24, -31, -37, -42, + -47, -49, -51, -52, -51, -48, -43, -37, -30, -20, -7, 6, 19, 0, -4, 10, + 10, 11, -15, 4, -1, 3, -11, 11, 2, -12, 3, 18, -10, -62, 89, -16, + -95, 118, -128, 122, -128, 112, -100, 109, -121, 120, -104, 58, 10, -88, 127, -102, + 6, 98, -126, 35, 89, -111, -7, 112, -53, -94, 92, 64, -106, -53, 109, 52, + -100, -75, 86, 95, -45, -119, -12, 111, 74, -58, -118, -27, 97, 100, -4, -107, + -95, 17, 109, 92, -4, -99, -109, -26, 78, 115, 66, -27, -104, -109, -41, 55, + 112, 98, 32, -53, -109, -105, -44, 41, 102, 109, 67, -4, -74, -112, -102, -47, + 27, 88, 112, 93, 45, -19, -78, -110, -105, -65, -4, 59, 101, 110, 87, 43, + -13, -67, -103, -111, -89, -44, 13, 65, 100, 109, 93, 59, 14, -36, -78, -104, + -108, -90, -53, -6, 43, 83, 104, 106, 88, 57, 17, -27, -66, -95, -108, -102, + -80, -44, -2, 41, 77, 99, 106, 98, 77, 46, 10, -29, -64, -91, -105, -105, + -91, -64, -29, 10, 48, 78, 98, 105, 100, 84, 59, 30, -3, -36, -65, -88, + -101, -105, -99, -83, -60, -32, -1, 30, 58, 80, 96, 103, 102, 94, 80, 62, + 40, 16, -10, -35, -58, -78, -92, -101, -104, -100, -91, -77, -58, -36, -13, 12, + 36, 57, 75, 89, 98, 102, 102, 97, 88, 76, 61, 44, 25, 5, -15, -35, + -54, -70, -84, -94, -101, -104, -103, -98, -89, -77, -63, -46, -27, -8, 12, 31, + 49, 65, 79, 90, 97, 102, 104, 102, 97, 90, 81, 70, 57, 42, 27, 10, + -7, -24, -40, -56, -70, -81, -91, -99, -103, -105, -105, -101, -95, -87, -76, -63, + -49, -34, -18, -1, 16, 32, 48, 62, 74, 85, 93, 100, 104, 105, 105, 102, + 97, 90, 82, 72, 61, 48, 35, 21, 6, -9, -24, -38, -52, -65, -76, -86, + -94, -101, -105, -108, -108, -106, -102, -96, -87, -78, -66, -54, -40, -26, -11, 4, + 19, 34, 48, 61, 73, 83, 92, 99, 104, 107, 108, 108, 105, 101, 96, 89, + 80, 70, 60, 48, 36, 22, 9, -5, -19, -33, -46, -58, -69, -80, -89, -96, + -102, -107, -109, -110, -110, -107, -102, -97, -89, -80, -70, -59, -47, -33, -20, -6, + 7, 19, 30, 41, 50, 58, 65, 71, 75, 78, 79, 80, 79, 77, 74, 70, + 65, 60, 54, 48, 42, 36, 29, 22, 16, 10, 4, -2, -7, -12, -16, -19, + -22, -24, -26, -27, -27, -27, -26, -25, -23, -22, -19, -17, -14, -12, -10, 0, + -5, -2, -5, 2, -29, 22, 0, -27, 67, -59, 45, -13, -37, 28, 65, -4, + 6, 60, 5, 58, 44, 60, 27, 43, 96, 71, 81, 48, 96, 70, 23, 90, + 66, 80, 88, 40, 20, 61, 64, 12, 36, 24, 4, 7, 5, -27, -38, -26, + -33, -49, -50, -70, -69, -93, -92, -94, -104, -104, -101, -110, -107, -111, -111, -126, + -87, -119, -100, -94, -112, -93, -93, -80, -81, -76, -58, -56, -70, -30, -21, -42, + -13, -3, 2, 8, 20, 28, 41, 45, 59, 62, 69, 84, 85, 90, 103, 109, + 111, 118, 121, 121, 123, 121, 122, 121, 122, 121, 122, 121, 121, 120, 121, 120, + 121, 120, 121, 120, 120, 119, 120, 119, 120, 118, 105, 106, 110, 83, 89, 92, + 75, 67, 61, 57, 47, 40, 33, 24, 17, 10, 3, -2, -10, -20, -31, -31, + -37, -49, -50, -63, -66, -69, -74, -79, -91, -89, -92, -95, -102, -106, -104, -107, + -113, -113, -110, -113, -116, -114, -115, -114, -115, -114, -113, -114, -113, -114, -113, -112, + -113, -109, -105, -111, -106, -107, -103, -100, -103, -99, -97, -98, -99, -92, -92, -93, + -92, -92, -90, -88, -90, -88, -86, -89, -85, -85, -87, -85, -85, -82, -83, -82, + -80, -78, -79, -76, -74, -73, -73, -69, -68, -66, -64, -65, -62, -58, -56, -56, + -52, -50, -47, -43, -42, -39, -35, -33, -31, -27, -23, -21, -16, -16, -8, -7, + -3, 1, 0, 10, 15, 15, 19, 26, 29, 30, 38, 41, 42, 47, 54, 54, + 57, 63, 68, 69, 72, 77, 78, 80, 85, 84, 86, 87, 86, 87, 86, 85, + 86, 85, 84, 85, 84, 83, 84, 83, 82, 82, 83, 82, 81, 82, 81, 80, + 81, 80, 79, 80, 79, 79, 78, 79, 78, 78, 77, 74, 70, 66, 64, 61, + 55, 52, 49, 45, 40, 35, 32, 29, 24, 19, 15, 12, 8, 4, 0, -4, + -8, -11, -15, -17, -20, -25, -26, -29, -32, -34, -37, -39, -41, -43, -45, -46, + -48, -49, -50, -50, -52, -52, -53, -52, -53, -54, -53, -53, -52, -52, -51, -50, + -50, -49, -48, -48, -46, -45, -44, -42, -41, -40, -39, -37, -35, -34, -32, -30, + -28, -27, -24, -23, -22, -20, -19, -17, -15, -14, -13, -12, -10, -9, -8, -8, + -6, -6, -5, -4, -4, -3, -3, -2, -2, -1, -2, -1, -2, -1, -1, 0, + -1, 0, 1, 6, -11, 19, -25, 24, -15, 11, -6, 1, 9, -6, -3, 11, + -18, 28, -23, 8, 6, -2, -1, 0, -5, 18, -23, 24, -28, 27, -12, -1, + -2, 6, 4, -14, 19, -29, 42, -40, 22, -6, -3, 14, -16, 4, 8, -9, + 13, -22, 17, 5, -24, 37, -34, 20, -4, -11, 19, -20, 21, -16, 1, 17, + -17, 5, -9, 25, -31, 31, -40, 32, -11, -7, 4, -4, 13, -23, 29, -40, + 51, -49, 20, 3, -20, 38, -47, 34, -21, 14, -9, 4, -13, 20, -29, 37, + -57, 59, -48, 23, -5, -7, 5, -6, -5, 13, -17, 9, -4, -12, 22, -19, + -8, 10, -5, -7, 8, -18, 19, -13, 5, -12, 6, -10, 18, -40, 66, -91, + 82, -56, 17, 19, -51, 56, -45, 30, -19, 5, -6, 7, -9, -4, -2, -5, + 13, -19, 1, 20, -28, 13, -6, 0, -17, 33, -48, 38, -16, -20, 53, -75, + 75, -61, 30, -12, -9, 2, 5, -9, -7, 15, -17, 9, 4, -46, 70, -85, + 86, -67, 29, 18, -60, 76, -70, 29, -8, -1, 1, 14, -58, 93, -118, 127, + -125, 85, -36, -2, 17, -39, 46, -61, 70, -99, 122, -120, 56, 15, -85, 116, + -101, 30, 43, -108, 127, -122, 72, -38, -3, 20, -31, 29, -37, 42, -50, 63, + -72, 40, -7, -46, 66, -82, 53, -25, 1, 1, -1, -3, 3, -24, 24, -34, + 27, -24, 36, -49, 37, -38, 35, -42, 13, -4, -14, 14, -29, 42, -58, 58, + -60, 41, -39, 27, -35, 27, -32, 25, -37, 43, -50, 32, -20, -4, 4, -14, + 16, -43, 66, -93, 79, -58, 27, -11, -21, 34, -40, 24, -7, -25, 31, -29, + 19, -18, -2, 1, -6, 4, -31, 47, -63, 62, -64, 32, 2, -29, 23, -21, + 19, -41, 59, -76, 62, -52, 26, -11, -1, -10, 6, -10, -7, 17, -42, 34, + -12, -34, 73, -106, 92, -61, 26, -24, 8, -7, -2, 3, -24, 31, -44, 27, + -9, -22, 38, -43, 15, -4, -3, -2, -12, 5, 1, -7, 7, -25, 17, -17, + 4, -15, 27, -40, 34, -18, 6, -13, 12, -3, -9, -6, 8, -18, 18, -36, + 54, -55, 30, -25, 26, -41, 38, -49, 48, -38, 8, 16, -40, 47, -52, 34, + -12, -4, 2, -13, 0, 1, 6, -11, 19, -25, 24, -15, 11, -6, 1, 9, + -6, -3, 11, -18, 28, -23, 8, 6, -2, -1, 0, -5, 18, -23, 24, -28, + 27, -12, -1, -2, 6, 4, -14, 19, -29, 42, -40, 22, -6, -3, 14, -16, + 4, 8, -9, 13, -22, 17, 5, -24, 37, -34, 20, -4, -11, 19, -20, 21, + -16, 1, 17, -17, 5, -9, 25, -31, 31, -40, 32, -11, -7, 4, -4, 13, + -23, 29, -40, 51, -49, 20, 3, -20, 38, -47, 34, -21, 14, -9, 4, -13, + 20, -29, 37, -57, 59, -48, 23, -5, -7, 5, -6, -5, 13, -17, 9, -4, + -12, 22, -19, -8, 10, -5, -7, 8, -18, 19, -13, 5, -12, 6, -10, 18, + -40, 66, -91, 82, -56, 17, 19, -51, 56, -45, 30, -19, 5, -6, 7, -9, + -4, -2, -5, 13, -19, 1, 20, -28, 13, -6, 0, -17, 33, -48, 38, -16, + -20, 53, -75, 75, -61, 30, -12, -9, 2, 5, -9, -7, 15, -17, 9, 4, + -46, 70, -85, 86, -67, 29, 18, -60, 76, -70, 29, -8, -1, 1, 14, -58, + 93, -118, 127, -125, 85, -36, -2, 17, -39, 46, -61, 70, -99, 122, -120, 56, + 15, -85, 116, -101, 30, 43, -108, 127, -122, 72, -38, -3, 20, -31, 29, -37, + 42, -50, 63, -72, 40, -7, -46, 66, -82, 53, -25, 1, 1, -1, -3, 3, + -24, 24, -34, 27, -24, 36, -49, 37, -38, 35, -42, 13, -4, -14, 14, -29, + 42, -58, 58, -60, 41, -39, 27, -35, 27, -32, 25, -37, 43, -50, 32, -20, + -4, 4, -14, 16, -43, 66, -93, 79, -58, 27, -11, -21, 34, -40, 24, -7, + -25, 31, -29, 19, -18, -2, 1, -6, 4, -31, 47, -63, 62, -64, 32, 2, + -29, 23, -21, 19, -41, 59, -76, 62, -52, 26, -11, -1, -10, 6, -10, -7, + 17, -42, 34, -12, -34, 73, -106, 92, -61, 26, -24, 8, -7, -2, 3, -24, + 31, -44, 27, -9, -22, 38, -43, 15, -4, -3, -2, -12, 5, 1, -7, 7, + -25, 17, -17, 4, -15, 27, -40, 34, -18, 6, -13, 12, -3, -9, -6, 8, + -18, 18, -36, 54, -55, 30, -25, 26, -41, 38, -49, 48, -38, 8, 16, -40, + 47, -52, 34, -12, -4, 2, -13, -1, -9, -21, -32, -43, -55, -58, -40, -8, + 15, 29, 38, 44, 59, 63, 51, 20, -20, -47, -61, -58, -48, -42, -43, -35, + -15, 15, 41, 55, 61, 62, 70, 67, 45, 11, -31, -62, -80, -78, -71, -62, + -54, -39, -15, 18, 50, 68, 79, 83, 92, 88, 57, 16, -31, -71, -94, -95, + -90, -83, -71, -55, -28, 7, 49, 77, 93, 100, 109, 107, 78, 36, -20, -71, + -99, -104, -100, -92, -83, -69, -43, -5, 42, 79, 100, 108, 114, 112, 90, 51, + -9, -65, -100, -110, -105, -95, -87, -76, -52, -11, 35, 75, 100, 107, 111, 106, + 90, 52, -4, -60, -97, -109, -99, -87, -80, -65, -35, 5, 43, 75, 91, 95, + 93, 87, 71, 31, -19, -64, -93, -99, -88, -76, -66, -44, -9, 28, 59, 79, + 84, 80, 71, 59, 35, -5, -45, -76, -96, -95, -77, -59, -39, -9, 28, 61, + 86, 98, 93, 74, 52, 28, -6, -43, -72, -94, -108, -99, -77, -52, -20, 19, + 56, 84, 106, 115, 106, 79, 45, 3, -40, -74, -93, -108, -112, -100, -79, -46, + -1, 45, 78, 100, 113, 118, 108, 81, 39, -19, -67, -93, -103, -108, -104, -94, + -74, -32, 19, 61, 88, 102, 108, 109, 100, 73, 21, -44, -87, -102, -104, -97, + -90, -78, -49, 0, 46, 78, 90, 92, 89, 87, 77, 43, -15, -72, -101, -104, + -93, -79, -69, -47, -3, 47, 84, 96, 89, 74, 65, 58, 37, -7, -61, -99, + -110, -101, -82, -62, -38, 2, 49, 92, 112, 106, 82, 59, 41, 18, -19, -61, + -95, -111, -110, -98, -74, -39, 6, 54, 99, 122, 123, 104, 79, 50, 12, -32, + -72, -100, -111, -110, -106, -90, -54, -4, 49, 99, 123, 126, 113, 95, 69, 24, + -27, -72, -102, -114, -109, -104, -94, -64, -16, 36, 87, 116, 121, 111, 97, 76, + 36, -15, -61, -94, -110, -108, -98, -86, -60, -19, 29, 77, 104, 109, 99, 86, + 67, 35, -7, -47, -82, -98, -101, -92, -77, -48, -14, 25, 67, 92, 95, 83, + 66, 45, 18, -9, -37, -62, -77, -81, -78, -54, -16, 0, 0, 0, 12, -10, + 16, -14, -18, 17, -31, -2, 3, -19, -8, 17, 28, 37, 31, -1, -25, -16, + -47, -13, -43, -22, 6, 34, 41, 49, 41, 27, 6, -33, -62, -54, -59, -32, + -13, 29, 53, 73, 60, 54, 16, -19, -58, -77, -89, -42, -46, 17, 55, 78, + 86, 81, 33, -3, -35, -84, -110, -75, -70, 0, 39, 78, 92, 105, 70, 13, + -15, -82, -107, -103, -84, -41, 20, 81, 85, 127, 86, 39, -4, -63, -103, -99, + -107, -69, 2, 68, 82, 127, 84, 58, 28, -44, -88, -104, -108, -83, -13, 29, + 69, 116, 87, 77, 40, -16, -65, -89, -104, -89, -40, -1, 47, 96, 90, 85, + 52, 9, -38, -62, -96, -95, -62, -22, 21, 73, 78, 86, 65, 35, -15, -41, + -80, -92, -69, -48, 1, 43, 65, 80, 73, 49, 8, -23, -59, -75, -74, -60, + -22, 17, 49, 69, 65, 60, 25, -1, -36, -59, -70, -61, -40, -9, 30, 52, + 57, 63, 37, 17, -12, -41, -61, -57, -50, -30, 9, 30, 49, 60, 47, 28, + 6, -20, -49, -51, -53, -42, -11, 13, 34, 53, 50, 34, 18, -3, -35, -39, + -52, -49, -23, 0, 18, 41, 47, 36, 31, 10, -21, -28, -43, -49, -31, -13, + 2, 28, 39, 35, 38, 19, -7, -18, -33, -42, -36, -26, -12, 19, 30, 34, + 36, 22, 6, -5, -25, -38, -36, -29, -17, 8, 19, 26, 35, 28, 12, 3, + -17, -30, -29, -29, -22, -3, 9, 19, 33, 26, 14, 8, -9, -18, -22, -28, + -25, -9, 3, 15, 22, 20, 18, 12, 1, -11, -22, -24, -21, -13, -3, 8, + 11, 20, 21, 12, 5, -6, -19, -16, -17, -17, -7, 3, 8, 20, 17, 7, + 7, -2, -11, -13, -16, -17, -5, 2, 5, 12, 13, 8, 6, 3, -9, -11, + -9, -14, -5, 1, -3, 6, 11, 6, 7, 2, -6, -4, -4, -10, -6, -3, + -4, 5, 8, 2, 5, 4, -2, 0, -3, -9, -4, -3, -3, 2, 3, 0, + 6, 4, 0, -1, -2, -2, 0, -4, 8, -1, 9, 14, 53, 57, 33, -4, + -20, -14, -31, -71, -112, -43, 30, -22, -102, -74, 38, 90, 35, -22, 20, 99, + 96, 22, -42, -5, 48, 16, -74, -97, -51, 10, -21, -80, -68, 24, 77, 43, + -9, 20, 90, 99, 32, -28, -8, 41, 18, -63, -97, -55, -2, -18, -74, -67, + 11, 69, 44, -1, 17, 83, 98, 40, -20, -8, 35, 20, -55, -95, -60, -8, + -19, -69, -68, 3, 61, 45, 1, 15, 78, 99, 46, -14, -8, 33, 22, -48, + -93, -62, -13, -19, -67, -70, -5, 56, 44, 3, 13, 73, 99, 51, -10, -7, + 32, 25, -42, -91, -66, -15, -18, -65, -73, -11, 51, 44, 3, 9, 69, 100, + 55, -6, -8, 32, 30, -36, -89, -68, -17, -17, -64, -77, -18, 47, 45, 3, + 5, 64, 100, 60, -2, -8, 32, 34, -30, -87, -70, -19, -14, -63, -80, -25, + 43, 45, 3, 1, 59, 100, 66, 1, -9, 31, 39, -23, -84, -74, -20, -12, + -59, -84, -32, 38, 46, 3, -3, 53, 101, 71, 6, -10, 31, 43, -14, -81, + -76, -24, -9, -57, -86, -41, 33, 46, 5, -9, 47, 99, 77, 9, -11, 28, + 49, -6, -76, -79, -25, -9, -50, -91, -46, 9, -41, 2, 6, -33, 33, -4, + -1, 34, -93, 60, -49, 68, -21, 41, -38, -38, 27, -87, 127, -34, 38, -3, + -34, -2, -85, 79, -24, 4, 75, -23, 11, -70, 1, -6, -6, 63, -48, 76, + -71, 2, -7, -15, 46, -32, 48, -25, -5, 10, -31, 18, -23, 5, 6, 17, + 11, 3, 24, -46, -21, -1, -5, 31, 1, 36, -23, -11, -4, -29, 14, -5, + 29, 9, -2, -2, -20, -2, -15, 13, 7, 4, 15, -11, 4, -13, -1, 1, + -13, 15, -6, 9, 9, -2, -4, -11, -2, -11, 7, 12, 9, 5, -6, -6, + -16, -2, 3, 6, 13, 1, 7, -14, -3, -11, -1, 8, 0, 18, -3, -3, + -6, -13, 0, 4, 2, 9, 2, 2, -6, -4, -1, -8, 2, 4, 2, 7, + -4, 2, 1, -7, -3, -2, 0, 2, 8, -2, 2, -1, -7, -3, -1, 3, + 4, 3, 3, -3, -4, -4, 0, 2, 1, 5, -1, -2, 1, -4, -1, 1, + 0, 2, 8, -22, 25, 30, 6, -19, -62, -19, 10, 83, 57, -67, -88, -52, + 63, 127, 42, -63, -121, -70, 82, 111, 46, -43, -114, -35, 45, 73, 39, -19, + -54, -41, 9, 49, 24, -16, -14, -9, -6, 10, 8, -22, 25, 30, 6, -19, + -62, -19, 10, 83, 57, -67, -88, -52, 63, 127, 42, -63, -121, -70, 82, 111, + 46, -43, -114, -35, 45, 73, 39, -19, -54, -41, 9, 49, 24, -16, -14, -9, + -6, 10, 94, 127, 124, 127, 127, 114, 73, 35, -11, -52, -98, -118, -125, -128, + -128, -128, -128, -128, -128, -128, -124, -86, -47, 0, 40, 87, 106, 116, 119, 125, + 37, -7, 122, 72, -57, -71, -88, -28, 48, 127, 36, -30, -53, -126, -16, 71, + 92, 51, -1, -83, -128, 14, 43, 83, 86, -14, -106, -87, -7, 28, 1, 122, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; + +const EAS_U32 eas_sampleLengths[] = +{ + 9922, 9338, 6793, 5242, 3057, 2818, 2806, 1835, + 1603, 1262, 1227, 1168, 1132, 1132, 994, 907, + 817, 801, 583, 418, 402, 387, 387, 357, + 347, 212, 167, 40, 40, 32, 30 +}; + +const EAS_U32 eas_sampleOffsets[] = +{ + 0x00000000, 0x000026c2, 0x00004b3c, 0x000065c5, 0x00007a3f, 0x00008630, 0x00009132, 0x00009c28, + 0x0000a353, 0x0000a996, 0x0000ae84, 0x0000b34f, 0x0000b7df, 0x0000bc4b, 0x0000c0b7, 0x0000c499, + 0x0000c824, 0x0000cb55, 0x0000ce76, 0x0000d0bd, 0x0000d25f, 0x0000d3f1, 0x0000d574, 0x0000d6f7, + 0x0000d85c, 0x0000d9b7, 0x0000da8b, 0x0000db32, 0x0000db5a, 0x0000db82, 0x0000dba2 +}; + +/*---------------------------------------------------------------------------- + * S_EAS (hybrid) + *---------------------------------------------------------------------------- +*/ +const S_EAS easSoundLib = +{ + 0x01534145, + 0x00105622, + eas_banks, + eas_programs, + eas_regions, + eas_articulations, + eas_sampleLengths, + eas_sampleOffsets, + eas_samples, + eas_fmRegions, + 1, + 1, + 61, + 53, + 31, + 128 +}; /* end S_EAS */ + +/*---------------------------------------------------------------------------- + * Statistics + * + * Number of banks: 1 + * Number of programs: 1 + * Number of regions: 61 + * Number of articulations: 53 + * Number of samples: 31 + * Size of sample pool: 56276 + *---------------------------------------------------------------------------- +*/ +/* end C:\Sonic\Trunk\EASLib\WTLibrary\hybrid_22khz_mcu.c */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/Android.mk b/code/embeddedaudiosynthesis/arm-wt-22k/Android.mk new file mode 100755 index 0000000..71fbcf8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/Android.mk @@ -0,0 +1,104 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES = \ + lib_src/eas_chorus.c \ + lib_src/eas_chorusdata.c \ + lib_src/eas_data.c \ + lib_src/eas_dlssynth.c \ + lib_src/eas_flog.c \ + lib_src/eas_ima_tables.c \ + lib_src/eas_imaadpcm.c \ + lib_src/eas_imelody.c \ + lib_src/eas_imelodydata.c \ + lib_src/eas_math.c \ + lib_src/eas_mdls.c \ + lib_src/eas_midi.c \ + lib_src/eas_mididata.c \ + lib_src/eas_mixbuf.c \ + lib_src/eas_mixer.c \ + lib_src/eas_ota.c \ + lib_src/eas_otadata.c \ + lib_src/eas_pan.c \ + lib_src/eas_pcm.c \ + lib_src/eas_pcmdata.c \ + lib_src/eas_public.c \ + lib_src/eas_reverb.c \ + lib_src/eas_reverbdata.c \ + lib_src/eas_rtttl.c \ + lib_src/eas_rtttldata.c \ + lib_src/eas_smf.c \ + lib_src/eas_smfdata.c \ + lib_src/eas_voicemgt.c \ + lib_src/eas_wtengine.c \ + lib_src/eas_wtsynth.c \ + lib_src/eas_xmf.c \ + lib_src/eas_xmfdata.c \ + lib_src/wt_22khz.c \ + lib_src/jet.c \ + host_src/eas_config.c \ + host_src/eas_hostmm.c \ + host_src/eas_main.c \ + host_src/eas_report.c \ + host_src/eas_wave.c + +# not using these modules +# lib_src/eas_wavefile.c \ +# lib_src/eas_wavefiledata.c \ + +LOCAL_CFLAGS+= -O2 -D UNIFIED_DEBUG_MESSAGES -D EAS_WT_SYNTH \ + -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER \ + -D _XMF_PARSER -D NUM_OUTPUT_CHANNELS=2 \ + -D _SAMPLE_RATE_22050 -D MAX_SYNTH_VOICES=64 \ + -D _8_BIT_SAMPLES -D _FILTER_ENABLED \ + -D DLS_SYNTHESIZER \ + -D _REVERB_ENABLED + +# not using these options +# -D _WAVE_PARSER +# -D _IMA_DECODER (needed for IMA-ADPCM wave files) +# -D _CHORUS_ENABLED + +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH)/host_src \ + $(LOCAL_PATH)/lib_src + +LOCAL_ARM_MODE := arm + +LOCAL_MODULE := libsonivox + +LOCAL_COPY_HEADERS_TO := libsonivox +LOCAL_COPY_HEADERS := \ + host_src/eas.h \ + host_src/eas_types.h \ + host_src/eas_reverb.h \ + host_src/jet.h + +ifeq ($(TARGET_ARCH),arm) +LOCAL_SRC_FILES+= \ + lib_src/ARM-E_filter_gnu.s \ + lib_src/ARM-E_interpolate_loop_gnu.s \ + lib_src/ARM-E_interpolate_noloop_gnu.s \ + lib_src/ARM-E_mastergain_gnu.s \ + lib_src/ARM-E_voice_gain_gnu.s + +asm_flags := \ + -I $(LOCAL_PATH)/lib_src \ + --defsym SAMPLE_RATE_22050=1 \ + --defsym STEREO_OUTPUT=1 \ + --defsym FILTER_ENABLED=1 \ + --defsym SAMPLES_8_BIT=1 + +LOCAL_CFLAGS+= -D NATIVE_EAS_KERNEL \ + $(foreach f,$(asm_flags),-Wa,"$(f)") + +LOCAL_COPY_HEADERS += lib_src/ARM_synth_constants_gnu.inc +endif + +LOCAL_SHARED_LIBRARIES := \ + libutils libcutils + +LOCAL_LDLIBS := -lpthread + +include $(BUILD_SHARED_LIBRARY) + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/bin/arm-wt-22k b/code/embeddedaudiosynthesis/arm-wt-22k/bin/arm-wt-22k new file mode 100755 index 0000000..2e54640 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/bin/arm-wt-22k differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/arm-wt-22k.mak b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/arm-wt-22k.mak new file mode 100755 index 0000000..222d174 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/arm-wt-22k.mak @@ -0,0 +1,25 @@ +# +# Auto-generated sample makefile +# +# This makefile is intended for use with GNU make. +# Set the paths to the tools (CC, AR, LD, etc.) +# + +vpath %.c host_src + +CC = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AS = C:\Program Files\GNUARM\bin\arm-elf-as.exe +LD = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AR = C:\Program Files\GNUARM\bin\arm-elf-ar.exe + +%.o: %.c + $(CC) -c -O2 -o $@ -I host_src -D UNIFIED_DEBUG_MESSAGES -D EAS_WT_SYNTH -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _XMF_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED -D MMAPI_SUPPORT -D JET_INTERFACE $< + +%.o: %.s + $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa -I lib_src --defsym CHECK_STACK=0 --defsym REVERB=0 --defsym CHORUS=0 --defsym STEREO_OUTPUT=1 --defsym SAMPLE_RATE_22050=1 --defsym SAMPLES_8_BIT=1 --defsym FILTER_ENABLED=1 $< + +OBJS = eas_main.o eas_report.o eas_wave.o eas_hostmm.o eas_config.o + +arm-wt-22k: $(OBJS) + $(LD) -o $@ $(OBJS) libarm-wt-22k.a -lm + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas.h new file mode 100755 index 0000000..c64af49 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas.h @@ -0,0 +1,1062 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas.h + * + * Contents and purpose: + * The public interface header for the EAS synthesizer. + * + * This header only contains declarations that are specific + * to this implementation. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2005, 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 852 $ + * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_H +#define _EAS_H + +#include "eas_types.h" + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +/* library version macro */ +#define MAKE_LIB_VERSION(a,b,c,d) (((((((EAS_U32) a <<8) | (EAS_U32) b) << 8) | (EAS_U32) c) << 8) | (EAS_U32) d) +#define LIB_VERSION MAKE_LIB_VERSION(3, 6, 10, 14) + +typedef struct +{ + EAS_U32 libVersion; + EAS_BOOL checkedVersion; + EAS_I32 maxVoices; + EAS_I32 numChannels; + EAS_I32 sampleRate; + EAS_I32 mixBufferSize; + EAS_BOOL filterEnabled; + EAS_U32 buildTimeStamp; + EAS_CHAR *buildGUID; +} S_EAS_LIB_CONFIG; + +/* enumerated effects module numbers for configuration */ +typedef enum +{ + EAS_MODULE_ENHANCER = 0, + EAS_MODULE_COMPRESSOR, + EAS_MODULE_REVERB, + EAS_MODULE_CHORUS, + EAS_MODULE_WIDENER, + EAS_MODULE_GRAPHIC_EQ, + EAS_MODULE_WOW, + EAS_MODULE_MAXIMIZER, + EAS_MODULE_TONECONTROLEQ, + NUM_EFFECTS_MODULES +} E_FX_MODULES; + +/* enumerated optional module numbers for configuration */ +typedef enum +{ + EAS_MODULE_MMAPI_TONE_CONTROL = 0, + EAS_MODULE_METRICS +} E_OPT_MODULES; +#define NUM_OPTIONAL_MODULES 2 + +/* enumerated audio decoders for configuration */ +typedef enum +{ + EAS_DECODER_PCM = 0, + EAS_DECODER_SMAF_ADPCM, + EAS_DECODER_IMA_ADPCM, + EAS_DECODER_7BIT_SMAF_ADPCM, + EAS_DECODER_NOT_SUPPORTED +} E_DECODER_MODULES; +#define NUM_DECODER_MODULES 4 + +/* defines for EAS_PEOpenStream flags parameter */ +#define PCM_FLAGS_STEREO 0x00000100 /* stream is stereo */ +#define PCM_FLAGS_8_BIT 0x00000001 /* 8-bit format */ +#define PCM_FLAGS_UNSIGNED 0x00000010 /* unsigned format */ +#define PCM_FLAGS_STREAMING 0x80000000 /* streaming mode */ + +/* maximum volume setting */ +#define EAS_MAX_VOLUME 100 + +/*---------------------------------------------------------------------------- + * EAS_Init() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the synthesizer library + * + * Inputs: + * polyphony - number of voices to play (dynamic memory model only) + * ppLibData - pointer to data handle variable for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData); + +/*---------------------------------------------------------------------------- + * EAS_Config() + *---------------------------------------------------------------------------- + * Purpose: + * Returns a pointer to a structure containing the configuration options + * in this library build. + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void); + +/*---------------------------------------------------------------------------- + * EAS_Shutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the library. Deallocates any memory associated with the + * synthesizer (dynamic memory model only) + * + * Inputs: + * pEASData - handle to data for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_Render() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the Midi data and render PCM audio data. + * + * Inputs: + * pEASData - buffer for internal EAS data + * pOut - output buffer pointer + * nNumRequested - requested num samples to generate + * pnNumGenerated - actual number of samples generated + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated); + +/*---------------------------------------------------------------------------- + * EAS_SetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Set the selected stream to repeat. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * repeatCount - repeat count (0 = no repeat, -1 = repeat forever) + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 repeatCount); + +/*---------------------------------------------------------------------------- + * EAS_GetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the current repeat count for the selected stream. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * pRrepeatCount - pointer to variable to hold repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pRepeatCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPlaybackRate() + *---------------------------------------------------------------------------- + * Purpose: + * Set the playback rate. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U32 rate); +#define MAX_PLAYBACK_RATE (EAS_U32)(1L << 29) +#define MIN_PLAYBACK_RATE (EAS_U32)(1L << 27) + +/*---------------------------------------------------------------------------- + * EAS_SetTransposition) + *---------------------------------------------------------------------------- + * Purpose: + * Sets the key tranposition for the synthesizer. Transposes all + * melodic instruments by the specified amount. Range is limited + * to +/-12 semitones. + * + * Inputs: + * pEASData - handle to data for this instance + * streamHandle - handle to stream + * transposition - +/-12 semitones + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 transposition); +#define MAX_TRANSPOSE 12 + +/*---------------------------------------------------------------------------- + * EAS_SetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the synthesizer. Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_GetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the stream. Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_GetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * EAS_SetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the priority of the stream. Determines which stream's voices + * are stolen when there are insufficient voices for all notes. + * Value must be in the range of 1-255, lower values are higher + * priority. The default priority is 50. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 priority); + +/*---------------------------------------------------------------------------- + * EAS_GetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current priority setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPriority - pointer to variable to receive priority + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPriority); + +/*---------------------------------------------------------------------------- + * EAS_SetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for the mixer. The default volume setting is + * 90 (-10 dB). The volume range is 0 to 100 in 1dB increments. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 volume); + +/*---------------------------------------------------------------------------- + * EAS_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the master volume for the mixer in 1dB increments. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_SetMaxLoad() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the maximum workload the parsers will do in a single call to + * EAS_Render. The units are currently arbitrary, but should correlate + * well to the actual CPU cycles consumed. The primary effect is to + * reduce the occasional peaks in CPU cycles consumed when parsing + * dense parts of a MIDI score. Setting maxWorkLoad to zero disables + * the workload limiting function. + * + * Inputs: + * pEASData - handle to data for this instance + * maxLoad - the desired maximum workload + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad); + +/*---------------------------------------------------------------------------- + * EAS_SetMaxPCMStreams() + *---------------------------------------------------------------------------- + * Sets the maximum number of PCM streams allowed in parsers that + * use PCM streaming. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * maxNumStreams - maximum number of PCM streams + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams); + +/*---------------------------------------------------------------------------- + * EAS_OpenFile() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * locator - pointer to filename or other locating information + * pStreamHandle - pointer to stream handle variable + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle); + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * EAS_MMAPIToneControl() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a ToneControl file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * locator - pointer to filename or other locating information + * pStreamHandle - pointer to stream handle variable + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle); + +/*---------------------------------------------------------------------------- + * EAS_GetWaveFmtChunk + *---------------------------------------------------------------------------- + * Helper function to retrieve WAVE file fmt chunk for MMAPI + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * streamHandle - stream handle + * pFmtChunk - pointer to pointer to FMT chunk data + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_VOID_PTR *ppFmtChunk); +#endif + +/*---------------------------------------------------------------------------- + * EAS_GetFileType + *---------------------------------------------------------------------------- + * Returns the file type (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * streamHandle - stream handle + * pFileType - pointer to variable to receive file type + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetFileType (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pFileType); + +/*---------------------------------------------------------------------------- + * EAS_ParseMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * playLength - pointer to variable to store the play length (in msecs) + * + * Outputs: + * + * + * Side Effects: + * - resets the parser to the start of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPlayLength); + +/*---------------------------------------------------------------------------- + * EAS_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the synthesizer to play the file or stream. Parses the first + * frame of data from the file and arms the synthesizer. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the state of an audio file or stream. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_RegisterMetaDataCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers a metadata callback function for parsed metadata. To + * de-register the callback, call this function again with parameter + * cbFunc set to NULL. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * cbFunc - pointer to host callback function + * metaDataBuffer - pointer to metadata buffer + * metaDataBufSize - maximum size of the metadata buffer + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( + EAS_DATA_HANDLE pEASData, + EAS_HANDLE streamHandle, + EAS_METADATA_CBFUNC cbFunc, + char *metaDataBuffer, + EAS_I32 metaDataBufSize, + EAS_VOID_PTR pUserData); + +/*---------------------------------------------------------------------------- + * EAS_GetNoteCount () + *---------------------------------------------------------------------------- + * Returns the total number of notes played in this stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * pNoteCount - pointer to variable to receive note count + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount); + +/*---------------------------------------------------------------------------- + * EAS_CloseFile() + *---------------------------------------------------------------------------- + * Purpose: + * Closes an audio file or stream. Playback should have either paused or + * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_OpenMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pStreamHandle - pointer to variable to hold file or stream handle + * streamHandle - open stream or NULL for new synthesizer instance + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *pStreamHandle, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_WriteMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Send data to the MIDI stream device + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - stream handle + * pBuffer - pointer to buffer + * count - number of bytes to write + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream(EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 *pBuffer, EAS_I32 count); + +/*---------------------------------------------------------------------------- + * EAS_CloseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Closes a raw MIDI stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_Locate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate into the file associated with the handle. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file handle + * milliseconds - playback offset from start of file in milliseconds + * + * Outputs: + * + * + * Side Effects: + * the actual offset will be quantized to the closest update period, typically + * a resolution of 5.9ms. Notes that are started prior to this time will not + * sound. Any notes currently playing will be shut off. + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 milliseconds, EAS_BOOL offset); + +/*---------------------------------------------------------------------------- + * EAS_GetRenderTime() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * Gets the render time clock in msecs. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime); + +/*---------------------------------------------------------------------------- + * EAS_GetLocation() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file handle + * + * Outputs: + * The offset in milliseconds from the start of the current sequence, quantized + * to the nearest update period. Actual resolution is typically 5.9 ms. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pTime); + +/*---------------------------------------------------------------------------- + * EAS_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the playback of the data associated with this handle. The audio + * is gracefully ramped down to prevent clicks and pops. It may take several + * buffers of audio before the audio is muted. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resumes the playback of the data associated with this handle. The audio + * is gracefully ramped up to prevent clicks and pops. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); + +/*---------------------------------------------------------------------------- + * EAS_GetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * module - enumerated module number + * param - enumerated parameter number + * pValue - pointer to variable to receive parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue); + +/*---------------------------------------------------------------------------- + * EAS_SetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * value - new parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value); + +#ifdef _METRICS_ENABLED +/*---------------------------------------------------------------------------- + * EAS_MetricsReport() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the EAS_Report interface. + * + * Inputs: + * pEASData - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_MetricsReset() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the EAS_Report interface. + * + * Inputs: + * pEASData - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetSoundLibrary() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * streamHandle - file or stream handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_SNDLIB_HANDLE pSndLib); + +/*---------------------------------------------------------------------------- + * EAS_SetHeaderSearchFlag() + *---------------------------------------------------------------------------- + * By default, when EAS_OpenFile is called, the parsers check the + * first few bytes of the file looking for a specific header. Some + * mobile devices may add a header to the start of a file, which + * will prevent the parser from recognizing the file. If the + * searchFlag is set to EAS_TRUE, the parser will search the entire + * file looking for the header. This may enable EAS to recognize + * some files that it would ordinarily reject. The negative is that + * it make take slightly longer to process the EAS_OpenFile request. + * + * Inputs: + * pEASData - instance data handle + * searchFlag - search flag (EAS_TRUE or EAS_FALSE) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag); + +/*---------------------------------------------------------------------------- + * EAS_SetPlayMode() + *---------------------------------------------------------------------------- + * Some file formats support special play modes, such as iMode partial + * play mode. This call can be used to change the play mode. The + * default play mode (usually straight playback) is always zero. + * + * Inputs: + * pEASData - instance data handle + * handle - file or stream handle + * playMode - play mode (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode); + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * EAS_LoadDLSCollection() + *---------------------------------------------------------------------------- + * Purpose: + * Downloads a DLS collection + * + * Inputs: + * pEASData - instance data handle + * streamHandle - file or stream handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_FILE_LOCATOR locator); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetFrameBuffer() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the frame buffer pointer passed to the IPC communications functions + * + * Inputs: + * pEASData - instance data handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers callback functions for audio events. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * cbProgChgFunc - pointer to host callback function for program change + * cbEventFunc - pointer to host callback functio for note events + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, + EAS_HANDLE streamHandle, + EAS_VOID_PTR pInstData, + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, + EAS_EXT_EVENT_FUNC cbEventFunc); + +/*---------------------------------------------------------------------------- + * EAS_GetMIDIControllers() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of MIDI controllers on the requested channel. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - file or stream handle + * pControl - pointer to structure to receive data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl); +#endif + +/*---------------------------------------------------------------------------- + * EAS_SearchFile + *---------------------------------------------------------------------------- + * Search file for specific sequence starting at current file + * position. Returns offset to start of sequence. + * + * Inputs: + * pEASData - pointer to EAS persistent data object + * fileHandle - file handle + * searchString - pointer to search sequence + * len - length of search sequence + * pOffset - pointer to variable to store offset to sequence + * + * Returns EAS_EOF if end-of-file is reached + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SearchFile (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* #ifndef _EAS_H */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_build.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_build.h new file mode 100755 index 0000000..a65f8a6 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_build.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------- + * + * File: + * host_src\eas_build.h + * + * Contents and purpose: + * This file contains the build configuration for this + * build. The buildGUIDStr is a GUID created during + * the build process and is guaranteed to be unique + * for each build. + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file was autogenerated by buildid.exe + *---------------------------------------------------------------------------- +*/ + +#ifndef _GUID_1feda229b9a845e996f473c0a80e7220_ +#define _GUID_1feda229b9a845e996f473c0a80e7220_ + +#define _BUILD_VERSION_ "1feda229-b9a8-45e9-96f4-73c0a80e7220" +#define _BUILD_TIME_ 0x4743badd + +#endif /* _GUID_1feda229b9a845e996f473c0a80e7220_ */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_chorus.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_chorus.h new file mode 100755 index 0000000..d84a53b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_chorus.h @@ -0,0 +1,53 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorus.h + * + * Contents and purpose: + * Contains parameter enumerations for the Chorus effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 309 $ + * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_CHORUS_H +#define EAS_CHORUS_H + +/* enumerated parameter settings for Chorus effect */ +typedef enum +{ + EAS_PARAM_CHORUS_BYPASS, + EAS_PARAM_CHORUS_PRESET, + EAS_PARAM_CHORUS_RATE, + EAS_PARAM_CHORUS_DEPTH, + EAS_PARAM_CHORUS_LEVEL +} E_CHORUS_PARAMS; + +typedef enum +{ + EAS_PARAM_CHORUS_PRESET1, + EAS_PARAM_CHORUS_PRESET2, + EAS_PARAM_CHORUS_PRESET3, + EAS_PARAM_CHORUS_PRESET4 +} E_CHORUS_PRESETS; + + +#endif diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_config.c b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_config.c new file mode 100755 index 0000000..0b92357 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_config.c @@ -0,0 +1,619 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_config.c + * + * Contents and purpose: + * This file contains the Configuration Module interface (CM). The CM + * is a module compiled external to the library that sets the configuration + * for this build. It allows the library to find optional components and + * links to static memory allocations (when used in a static configuration). + * + * DO NOT MODIFY THIS FILE! + * + * NOTE: This module is not intended to be modified by the customer. It + * needs to be included in the build process with the correct configuration + * defines (see the library documentation for information on how to configure + * the library). + * + * Copyright Sonic Network Inc. 2004-2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 796 $ + * $Date: 2007-08-01 00:15:25 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas.h" +#include "eas_config.h" + + +#ifdef _MFI_PARSER +/*---------------------------------------------------------------------------- + * Vendor/Device ID for MFi Extensions + * + * Define the preprocessor symbols to establish the vendor ID and + * device ID for the MFi PCM/ADPCM extensions. + *---------------------------------------------------------------------------- +*/ +const EAS_U8 eas_MFIVendorIDMSB = (MFI_VENDOR_ID >> 8) & 0xff; +const EAS_U8 eas_MFIVendorIDLSB = MFI_VENDOR_ID & 0xff; +const EAS_U8 eas_MFIDeviceID = MFI_DEVICE_ID; +#endif + +/*---------------------------------------------------------------------------- + * + * parserModules + * + * This structure is used by the EAS library to locate file parsing + * modules. + *---------------------------------------------------------------------------- +*/ + +/* define the external file parsers */ +extern EAS_VOID_PTR EAS_SMF_Parser; + +#ifdef _XMF_PARSER +extern EAS_VOID_PTR EAS_XMF_Parser; +#endif + +#ifdef _SMAF_PARSER +extern EAS_VOID_PTR EAS_SMAF_Parser; +#endif + +#ifdef _WAVE_PARSER +extern EAS_VOID_PTR EAS_Wave_Parser; +#endif + +#ifdef _OTA_PARSER +extern EAS_VOID_PTR EAS_OTA_Parser; +#endif + +#ifdef _IMELODY_PARSER +extern EAS_VOID_PTR EAS_iMelody_Parser; +#endif + +#ifdef _RTTTL_PARSER +extern EAS_VOID_PTR EAS_RTTTL_Parser; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) +extern EAS_VOID_PTR EAS_CMF_Parser; +#endif + +/* initalize pointers to parser interfaces */ +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const parserModules[] = +{ + &EAS_SMF_Parser, + +#ifdef _XMF_PARSER + &EAS_XMF_Parser, +#endif + +#ifdef _WAVE_PARSER + &EAS_Wave_Parser, +#endif + +#ifdef _SMAF_PARSER + &EAS_SMAF_Parser, +#endif + +#ifdef _OTA_PARSER + &EAS_OTA_Parser, +#endif + +#ifdef _IMELODY_PARSER + &EAS_iMelody_Parser, +#endif + +#ifdef _RTTTL_PARSER + &EAS_RTTTL_Parser, +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) + &EAS_CMF_Parser +#endif +}; +#define NUM_PARSER_MODULES (sizeof(parserModules) / sizeof(EAS_VOID_PTR)) + +/*---------------------------------------------------------------------------- + * Data Modules + *---------------------------------------------------------------------------- +*/ + +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_SMFData; +extern EAS_VOID_PTR eas_Data; +extern EAS_VOID_PTR eas_MixBuffer; +extern EAS_VOID_PTR eas_Synth; +extern EAS_VOID_PTR eas_MIDI; +extern EAS_VOID_PTR eas_PCMData; +extern EAS_VOID_PTR eas_MIDIData; + +#ifdef _XMF_PARSER +extern EAS_VOID_PTR eas_XMFData; +#endif + +#ifdef _SMAF_PARSER +extern EAS_VOID_PTR eas_SMAFData; +#endif + +#ifdef _OTA_PARSER +extern EAS_VOID_PTR eas_OTAData; +#endif + +#ifdef _IMELODY_PARSER +extern EAS_VOID_PTR eas_iMelodyData; +#endif + +#ifdef _RTTTL_PARSER +extern EAS_VOID_PTR eas_RTTTLData; +#endif + +#ifdef _WAVE_PARSER +extern EAS_VOID_PTR eas_WaveData; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) +extern EAS_VOID_PTR eas_CMFData; +#endif +#endif + +/*---------------------------------------------------------------------------- + * + * Effects Modules + * + * These declarations are used by the EAS library to locate + * effects modules. + *---------------------------------------------------------------------------- +*/ + +#ifdef _ENHANCER_ENABLED +extern EAS_VOID_PTR EAS_Enhancer; +#define EAS_ENHANCER_INTERFACE &EAS_Enhancer +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_EnhancerData; +#define EAS_ENHANCER_DATA &eas_EnhancerData +#else +#define EAS_ENHANCER_DATA NULL +#endif +#else +#define EAS_ENHANCER_INTERFACE NULL +#define EAS_ENHANCER_DATA NULL +#endif + +#ifdef _COMPRESSOR_ENABLED +extern EAS_VOID_PTR EAS_Compressor; +#define EAS_COMPRESSOR_INTERFACE &EAS_Compressor +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_CompressorData; +#define EAS_COMPRESSOR_DATA &eas_CompressorData +#else +#define EAS_COMPRESSOR_DATA NULL +#endif +#else +#define EAS_COMPRESSOR_INTERFACE NULL +#define EAS_COMPRESSOR_DATA NULL +#endif + +#ifdef _MAXIMIZER_ENABLED +extern EAS_VOID_PTR EAS_Maximizer; +#define EAS_MAXIMIZER_INTERFACE &EAS_Maximizer +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_MaximizerData; +#define EAS_MAXIMIZER_DATA &eas_MaximizerData +#else +#define EAS_MAXIMIZER_DATA NULL +#endif +#else +#define EAS_MAXIMIZER_INTERFACE NULL +#define EAS_MAXIMIZER_DATA NULL +#endif + + +#ifdef _REVERB_ENABLED +extern EAS_VOID_PTR EAS_Reverb; +#define EAS_REVERB_INTERFACE &EAS_Reverb +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ReverbData; +#define EAS_REVERB_DATA &eas_ReverbData +#else +#define EAS_REVERB_DATA NULL +#endif +#else +#define EAS_REVERB_INTERFACE NULL +#define EAS_REVERB_DATA NULL +#endif + +#ifdef _CHORUS_ENABLED +extern EAS_VOID_PTR EAS_Chorus; +#define EAS_CHORUS_INTERFACE &EAS_Chorus +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ChorusData; +#define EAS_CHORUS_DATA &eas_ChorusData +#else +#define EAS_CHORUS_DATA NULL +#endif +#else +#define EAS_CHORUS_INTERFACE NULL +#define EAS_CHORUS_DATA NULL +#endif + +#ifdef _WIDENER_ENABLED +extern EAS_VOID_PTR EAS_Widener; +#define EAS_WIDENER_INTERFACE &EAS_Widener +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_WidenerData; +#define EAS_WIDENER_DATA &eas_WidenerData +#else +#define EAS_WIDENER_DATA NULL +#endif +#else +#define EAS_WIDENER_INTERFACE NULL +#define EAS_WIDENER_DATA NULL +#endif + +#ifdef _GRAPHIC_EQ_ENABLED +extern EAS_VOID_PTR EAS_GraphicEQ; +#define EAS_GRAPHIC_EQ_INTERFACE &EAS_GraphicEQ +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_GraphicEQData; +#define EAS_GRAPHIC_EQ_DATA &eas_GraphicEQData +#else +#define EAS_GRAPHIC_EQ_DATA NULL +#endif +#else +#define EAS_GRAPHIC_EQ_INTERFACE NULL +#define EAS_GRAPHIC_EQ_DATA NULL +#endif + +#ifdef _WOW_ENABLED +extern EAS_VOID_PTR EAS_Wow; +#define EAS_WOW_INTERFACE &EAS_Wow +#ifdef _STATIC_MEMORY +#error "WOW module requires dynamic memory model" +#else +#define EAS_WOW_DATA NULL +#endif +#else +#define EAS_WOW_INTERFACE NULL +#define EAS_WOW_DATA NULL +#endif + +#ifdef _TONECONTROLEQ_ENABLED +extern EAS_VOID_PTR EAS_ToneControlEQ; +#define EAS_TONECONTROLEQ_INTERFACE &EAS_ToneControlEQ +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_ToneControlEQData; +#define EAS_TONECONTROLEQ_DATA &eas_ToneControlEQData +#else +#define EAS_TONECONTROLEQ_DATA NULL +#endif +#else +#define EAS_TONECONTROLEQ_INTERFACE NULL +#define EAS_TONECONTROLEQ_DATA NULL +#endif + +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const effectsModules[] = +{ + EAS_ENHANCER_INTERFACE, + EAS_COMPRESSOR_INTERFACE, + EAS_REVERB_INTERFACE, + EAS_CHORUS_INTERFACE, + EAS_WIDENER_INTERFACE, + EAS_GRAPHIC_EQ_INTERFACE, + EAS_WOW_INTERFACE, + EAS_MAXIMIZER_INTERFACE, + EAS_TONECONTROLEQ_INTERFACE +}; + +EAS_VOID_PTR const effectsData[] = +{ + EAS_ENHANCER_DATA, + EAS_COMPRESSOR_DATA, + EAS_REVERB_DATA, + EAS_CHORUS_DATA, + EAS_WIDENER_DATA, + EAS_GRAPHIC_EQ_DATA, + EAS_WOW_DATA, + EAS_MAXIMIZER_DATA, + EAS_TONECONTROLEQ_DATA +}; + +/*---------------------------------------------------------------------------- + * + * Optional Modules + * + * These declarations are used by the EAS library to locate + * effects modules. + *---------------------------------------------------------------------------- +*/ + +#ifdef _METRICS_ENABLED +extern EAS_VOID_PTR EAS_Metrics; +#define EAS_METRICS_INTERFACE &EAS_Metrics +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_MetricsData; +#define EAS_METRICS_DATA &eas_MetricsData +#else +#define EAS_METRICS_DATA NULL +#endif +#else +#define EAS_METRICS_INTERFACE NULL +#define EAS_METRICS_DATA NULL +#endif + +#ifdef MMAPI_SUPPORT +extern EAS_VOID_PTR EAS_TC_Parser; +#define EAS_TONE_CONTROL_PARSER &EAS_TC_Parser +#ifdef _STATIC_MEMORY +extern EAS_VOID_PTR eas_TCData; +#define EAS_TONE_CONTROL_DATA &eas_TCData +#else +#define EAS_TONE_CONTROL_DATA NULL +#endif +#else +#define EAS_TONE_CONTROL_PARSER NULL +#define EAS_TONE_CONTROL_DATA NULL +#endif + +/*lint -e{605} not pretty, but it works */ +EAS_VOID_PTR const optionalModules[] = +{ + EAS_TONE_CONTROL_PARSER, + EAS_METRICS_INTERFACE +}; + +EAS_VOID_PTR const optionalData[] = +{ + EAS_TONE_CONTROL_DATA, + EAS_METRICS_DATA +}; + +/*---------------------------------------------------------------------------- + * EAS_CMStaticMemoryModel() + *---------------------------------------------------------------------------- + * Purpose: + * This function returns true if EAS has been configured for + * a static memory model. There are some limitations in the + * static memory model, see the documentation for more + * information. + * + * Outputs: + * returns EAS_TRUE if a module is found + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_CMStaticMemoryModel (void) +{ +#ifdef _STATIC_MEMORY + return EAS_TRUE; +#else + return EAS_FALSE; +#endif +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - module number + * + * Outputs: + * returns a pointer to the module function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module) +{ + + if (module >= (EAS_INT) NUM_PARSER_MODULES) + return NULL; + return parserModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, dataModule) used only when _STATIC_MEMORY is defined */ +EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule) +{ + +#ifdef _STATIC_MEMORY + switch (dataModule) + { + + /* main instance data for synthesizer */ + case EAS_CM_EAS_DATA: + return &eas_Data; + + /* mix buffer for mix engine */ + case EAS_CM_MIX_BUFFER: + /*lint -e{545} lint doesn't like this because it sees the underlying type */ + return &eas_MixBuffer; + + /* instance data for synth */ + case EAS_CM_SYNTH_DATA: + return &eas_Synth; + + /* instance data for MIDI parser */ + case EAS_CM_MIDI_DATA: + return &eas_MIDI; + + /* instance data for SMF parser */ + case EAS_CM_SMF_DATA: + return &eas_SMFData; + +#ifdef _XMF_PARSER + /* instance data for XMF parser */ + case EAS_CM_XMF_DATA: + return &eas_XMFData; +#endif + +#ifdef _SMAF_PARSER + /* instance data for SMAF parser */ + case EAS_CM_SMAF_DATA: + return &eas_SMAFData; +#endif + + /* instance data for the PCM engine */ + case EAS_CM_PCM_DATA: + /*lint -e{545} lint doesn't like this because it sees the underlying type */ + return &eas_PCMData; + + case EAS_CM_MIDI_STREAM_DATA: + return &eas_MIDIData; + +#ifdef _OTA_PARSER + /* instance data for OTA parser */ + case EAS_CM_OTA_DATA: + return &eas_OTAData; +#endif + +#ifdef _IMELODY_PARSER + /* instance data for iMelody parser */ + case EAS_CM_IMELODY_DATA: + return &eas_iMelodyData; +#endif + +#ifdef _RTTTL_PARSER + /* instance data for RTTTL parser */ + case EAS_CM_RTTTL_DATA: + return &eas_RTTTLData; +#endif + +#ifdef _WAVE_PARSER + /* instance data for WAVE parser */ + case EAS_CM_WAVE_DATA: + return &eas_WaveData; +#endif + +#if defined (_CMX_PARSER) || defined(_MFI_PARSER) + /* instance data for CMF parser */ + case EAS_CM_CMF_DATA: + return &eas_CMFData; +#endif + + default: + return NULL; + } + +#else + return NULL; +#endif +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional effects modules. + * + * Inputs: + * module - enumerated module number + * pModule - pointer to module interface + * + * Outputs: + * Returns pointer to function table or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module) +{ + + if (module >= NUM_EFFECTS_MODULES) + return NULL; + return effectsModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * pData - pointer to handle variable + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule) +{ + + if (dataModule >= NUM_EFFECTS_MODULES) + return NULL; + return effectsData[dataModule]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - enumerated module number + * + * Outputs: + * returns pointer to function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module) +{ + + /* sanity check */ + if (module >= NUM_OPTIONAL_MODULES) + return EAS_FALSE; + return optionalModules[module]; +} + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule) +{ + + if (dataModule >= NUM_OPTIONAL_MODULES) + return NULL; + return optionalData[dataModule]; +} + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_config.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_config.h new file mode 100755 index 0000000..49c2ef2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_config.h @@ -0,0 +1,191 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_config.h + * + * Contents and purpose: + * This header declares the Configuration Module interface (CM). The CM + * is a module compiled external to the library that sets the configuration + * for this build. It allows the library to find optional components and + * links to static memory allocations (when used in a static configuration). + * + * NOTE: This module is not intended to be modified by the customer. It + * needs to be included in the build process with the correct configuration + * defines (see the library documentation for information on how to configure + * the library). + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// sentinel +#ifndef _EAS_CONFIG_H +#define _EAS_CONFIG_H + +#include "eas_types.h" + +/* list of enumerators for optional modules */ +typedef enum { + EAS_CM_FILE_PARSERS = 1 +} E_CM_ENUM_MODULES; + +/* list of enumerators for module and memory pointers */ +typedef enum { + EAS_CM_EAS_DATA = 1, + EAS_CM_MIX_BUFFER, + EAS_CM_SYNTH_DATA, + EAS_CM_MIDI_DATA, + EAS_CM_SMF_DATA, + EAS_CM_XMF_DATA, + EAS_CM_SMAF_DATA, + EAS_CM_PCM_DATA, + EAS_CM_MIDI_STREAM_DATA, + EAS_CM_METRICS_DATA, + EAS_CM_OTA_DATA, + EAS_CM_IMELODY_DATA, + EAS_CM_RTTTL_DATA, + EAS_CM_WAVE_DATA, + EAS_CM_CMF_DATA +} E_CM_DATA_MODULES; + +typedef struct +{ + int maxSMFStreams; + void *pSMFData; + void *pSMFStream; +} S_EAS_SMF_PTRS; + +typedef struct +{ + int maxSMAFStreams; + void *pSMAFData; + void *pSMAFStream; +} S_EAS_SMAF_PTRS; + +/*---------------------------------------------------------------------------- + * EAS_CMStaticMemoryModel() + *---------------------------------------------------------------------------- + * Purpose: + * This function returns true if EAS has been configured for + * a static memory model. There are some limitations in the + * static memory model, see the documentation for more + * information. + * + * Outputs: + * returns EAS_TRUE if a module is found + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_CMStaticMemoryModel (void); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - module number + * + * Outputs: + * returns a pointer to the module function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional effects modules. + * + * Inputs: + * module - enumerated module number + * pModule - pointer to module interface + * + * Outputs: + * Returns pointer to function table or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumFXData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * pData - pointer to handle variable + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptModules() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to optional modules. + * + * Inputs: + * module - enumerated module number + * + * Outputs: + * returns pointer to function table or NULL if no module + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module); + +/*---------------------------------------------------------------------------- + * EAS_CMEnumOptData() + *---------------------------------------------------------------------------- + * Purpose: + * This function is used to find pointers to static memory allocations. + * + * Inputs: + * dataModule - enumerated module number + * + * Outputs: + * Returns handle to data or NULL if not found + *---------------------------------------------------------------------------- +*/ +EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule); + +#endif /* end _EAS_CONFIG_H */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_debugmsgs.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_debugmsgs.h new file mode 100755 index 0000000..25913bd --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_debugmsgs.h @@ -0,0 +1,87 @@ +/* Auto-generated from source file: eas_chorusdata.c */ +/* Auto-generated from source file: eas_xmfdata.c */ +/* Auto-generated from source file: eas_mdls.c */ +{ 0x19299ed4, 0x00000022, "eas_mdls.c[2561]: #Instruments: %u\n" }, +{ 0x19299ed4, 0x00000023, "eas_mdls.c[2562]: #Regions: %u\n" }, +{ 0x19299ed4, 0x00000024, "eas_mdls.c[2563]: #Articulations: %u\n" }, +{ 0x19299ed4, 0x00000025, "eas_mdls.c[2564]: #Waves: %u\n" }, +{ 0x19299ed4, 0x00000026, "eas_mdls.c[2569]: Locale: %lu:%lu:%lu\n" }, +{ 0x19299ed4, 0x00000027, "eas_mdls.c[2576]: \tRegion: %u\n" }, +{ 0x19299ed4, 0x00000028, "eas_mdls.c[2578]: \t\tm_nGain: %d\n" }, +{ 0x19299ed4, 0x00000029, "eas_mdls.c[2579]: \t\trangeLow:rangeHigh %u:%u\n" }, +{ 0x19299ed4, 0x0000002a, "eas_mdls.c[2580]: \t\tm_nKeyGroupAndFlags: %04x\n" }, +{ 0x19299ed4, 0x0000002b, "eas_mdls.c[2581]: \t\tm_nLoopStart: %u\n" }, +{ 0x19299ed4, 0x0000002c, "eas_mdls.c[2582]: \t\tm_nLoopEnd: %u\n" }, +{ 0x19299ed4, 0x0000002d, "eas_mdls.c[2583]: \t\tm_nNetTuningInCents: %d\n" }, +{ 0x19299ed4, 0x0000002e, "eas_mdls.c[2584]: \t\tArt Index: %u\n" }, +{ 0x19299ed4, 0x0000002f, "eas_mdls.c[2585]: \t\tWave Index: %u\n" }, +{ 0x19299ed4, 0x00000030, "eas_mdls.c[2597]: Articulation: %u\n" }, +{ 0x19299ed4, 0x00000031, "eas_mdls.c[2599]: \t\tm_nEG2toFilterDepth: %d\n" }, +{ 0x19299ed4, 0x00000032, "eas_mdls.c[2600]: \t\tm_nEG2toPitchDepth: %d\n" }, +{ 0x19299ed4, 0x00000033, "eas_mdls.c[2601]: \t\tm_nFilterCutoffFrequency: %d\n" }, +{ 0x19299ed4, 0x00000034, "eas_mdls.c[2602]: \t\tm_nFilterResonance: %u\n" }, +{ 0x19299ed4, 0x00000035, "eas_mdls.c[2603]: \t\tm_nLFOAmplitudeDepth: %d\n" }, +{ 0x19299ed4, 0x00000036, "eas_mdls.c[2604]: \t\tm_nLFODelayTime: %d\n" }, +{ 0x19299ed4, 0x00000037, "eas_mdls.c[2605]: \t\tm_nLFOFrequency: %d\n" }, +{ 0x19299ed4, 0x00000038, "eas_mdls.c[2606]: \t\tm_nLFOPitchDepth: %d\n" }, +{ 0x19299ed4, 0x00000039, "eas_mdls.c[2607]: \t\tm_nPan: %d\n" }, +{ 0x19299ed4, 0x0000003a, "eas_mdls.c[2610]: \t\tm_nAttack: %d\n" }, +{ 0x19299ed4, 0x0000003b, "eas_mdls.c[2611]: \t\tm_nDecay: %d\n" }, +{ 0x19299ed4, 0x0000003c, "eas_mdls.c[2612]: \t\tm_nSustain: %d\n" }, +{ 0x19299ed4, 0x0000003d, "eas_mdls.c[2613]: \t\tm_nRelease: %d\n" }, +{ 0x19299ed4, 0x0000003e, "eas_mdls.c[2616]: \t\tm_nAttack: %d\n" }, +{ 0x19299ed4, 0x0000003f, "eas_mdls.c[2617]: \t\tm_nDecay: %d\n" }, +{ 0x19299ed4, 0x00000040, "eas_mdls.c[2618]: \t\tm_nSustain: %d\n" }, +{ 0x19299ed4, 0x00000041, "eas_mdls.c[2619]: \t\tm_nRelease: %d\n" }, +{ 0x19299ed4, 0x00000042, "eas_mdls.c[2626]: Wave Index: %d\n" }, +{ 0x19299ed4, 0x00000043, "eas_mdls.c[2627]: \tSize %u\n" }, +{ 0x19299ed4, 0x00000044, "eas_mdls.c[2628]: \tPointer %08lx\n" }, +/* Auto-generated from source file: eas_mididata.c */ +/* Auto-generated from source file: eas_pan.c */ +/* Auto-generated from source file: eas_wavefiledata.c */ +/* Auto-generated from source file: eas_reverbdata.c */ +/* Auto-generated from source file: eas_imelodydata.c */ +/* Auto-generated from source file: eas_ota.c */ +/* Auto-generated from source file: eas_mixbuf.c */ +/* Auto-generated from source file: eas_tcdata.c */ +/* Auto-generated from source file: jet.c */ +/* Auto-generated from source file: eas_rtttl.c */ +/* Auto-generated from source file: eas_reverb.c */ +/* Auto-generated from source file: eas_pcmdata.c */ +/* Auto-generated from source file: eas_chorus.c */ +/* Auto-generated from source file: eas_math.c */ +/* Auto-generated from source file: eas_xmf.c */ +/* Auto-generated from source file: eas_smfdata.c */ +/* Auto-generated from source file: eas_imelody.c */ +/* Auto-generated from source file: eas_dlssynth.c */ +/* Auto-generated from source file: eas_public.c */ +/* Auto-generated from source file: eas_rtttldata.c */ +/* Auto-generated from source file: eas_voicemgt.c */ +/* Auto-generated from source file: eas_tonecontrol.c */ +/* Auto-generated from source file: eas_wtengine.c */ +/* Auto-generated from source file: eas_imaadpcm.c */ +{ 0x2380b977, 0x00000006, "eas_imaadpcm.c[305]: IMADecoderLocate: Time=%d, samples=%d\n" }, +{ 0x2380b977, 0x00000007, "eas_imaadpcm.c[328]: IMADecoderLocate: Looped sample, numBlocks=%d, samplesPerLoop=%d, samplesInLastBlock=%d, samples=%d\n" }, +{ 0x2380b977, 0x00000008, "eas_imaadpcm.c[335]: IMADecoderLocate: Byte location in audio = %d\n" }, +{ 0x2380b977, 0x00000009, "eas_imaadpcm.c[345]: IMADecoderLocate: bytesLeft = %d\n" }, +/* Auto-generated from source file: eas_flog.c */ +/* Auto-generated from source file: eas_midi.c */ +/* Auto-generated from source file: eas_otadata.c */ +/* Auto-generated from source file: eas_ima_tables.c */ +/* Auto-generated from source file: eas_data.c */ +/* Auto-generated from source file: eas_pcm.c */ +/* Auto-generated from source file: eas_mixer.c */ +/* Auto-generated from source file: eas_wavefile.c */ +/* Auto-generated from source file: eas_wtsynth.c */ +/* Auto-generated from source file: eas_smf.c */ +/* Auto-generated from source file: eas_wave.c */ +/* Auto-generated from source file: eas_hostmm.c */ +{ 0x1a54b6e8, 0x00000001, "eas_hostmm.c[586]: Vibrate state: %d\n" }, +{ 0x1a54b6e8, 0x00000002, "eas_hostmm.c[601]: LED state: %d\n" }, +{ 0x1a54b6e8, 0x00000003, "eas_hostmm.c[616]: Backlight state: %d\n" }, +{ 0x1a54b6e8, 0x00000004, "eas_hostmm.c[162]: HWMemCpy: bad amount: %d\n" }, +{ 0x1a54b6e8, 0x00000005, "eas_hostmm.c[179]: HWMemSet: bad amount: %d\n" }, +{ 0x1a54b6e8, 0x00000006, "eas_hostmm.c[196]: HWMemCmp: bad amount: %d\n" }, +/* Auto-generated from source file: eas_config.c */ +/* Auto-generated from source file: eas_main.c */ +{ 0xe624f4d9, 0x00000005, "eas_main.c[106]: Play length: %d.%03d (secs)\n" }, diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_host.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_host.h new file mode 100755 index 0000000..349241e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_host.h @@ -0,0 +1,87 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_host.h + * + * Contents and purpose: + * This header defines the host wrapper functions for stdio, stdlib, etc. + * The host application must provide an abstraction layer for these functions + * to support certain features, such as SMAF and SMF-1 conversion. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// sentinel +#ifndef _EAS_HOST_H +#define _EAS_HOST_H + +#include "eas_types.h" + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +/* initialization and shutdown routines */ +extern EAS_RESULT EAS_HWInit(EAS_HW_DATA_HANDLE *hwInstData); +extern EAS_RESULT EAS_HWShutdown(EAS_HW_DATA_HANDLE hwInstData); + +/* threading */ + extern void* EAS_HWRegisterSignalHandler(void); +extern EAS_RESULT EAS_HWUnRegisterSignalHandler(void *cookie); + +/* memory functions */ +extern void *EAS_HWMemSet(void *s, int c, EAS_I32 n); +extern void *EAS_HWMemCpy(void *s1, const void *s2, EAS_I32 n); +extern EAS_I32 EAS_HWMemCmp(const void *s1, const void *s2, EAS_I32 n); + +/* memory allocation */ +extern void *EAS_HWMalloc(EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size); +extern void EAS_HWFree(EAS_HW_DATA_HANDLE hwInstData, void *p); + +/* file I/O */ +extern EAS_RESULT EAS_HWOpenFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode); +extern EAS_RESULT EAS_HWReadFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead); +extern EAS_RESULT EAS_HWGetByte(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p); +extern EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst); +extern EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst); +extern EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition); +extern EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position); +extern EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position); +extern EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength); +extern EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pFile); +extern EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file); + +/* vibrate, LED, and backlight functions */ +extern EAS_RESULT EAS_HWVibrate(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); +extern EAS_RESULT EAS_HWLED(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); +extern EAS_RESULT EAS_HWBackLight(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + + +/* host yield function */ +extern EAS_BOOL EAS_HWYield(EAS_HW_DATA_HANDLE hwInstData); +#endif /* end _EAS_HOST_H */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_hostmm.c b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_hostmm.c new file mode 100755 index 0000000..ea4fcf7 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_hostmm.c @@ -0,0 +1,688 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_hostmm.c + * + * Contents and purpose: + * This file contains the host wrapper functions for stdio, stdlib, etc. + * This is a sample version that reads from a filedescriptor. + * The file locator (EAS_FILE_LOCATOR) handle passed to + * HWOpenFile is the same one that is passed to EAS_OpenFile. + * + * Modify this file to suit the needs of your particular system. + * + * EAS_MAX_FILE_HANDLES sets the maximum number of MIDI streams within + * a MIDI type 1 file that can be played. + * + * EAS_HW_FILE is a structure to support the file I/O functions. It + * comprises the file descriptor, the file read pointer, and + * the dup flag, which when set, indicates that the file handle has + * been duplicated, and offset and length within the file. + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define LOG_TAG "Sonivox" +#endif + +#include "eas_host.h" + +/* Only for debugging LED, vibrate, and backlight functions */ +#include "eas_report.h" + +/* this module requires dynamic memory support */ +#ifdef _STATIC_MEMORY +#error "eas_hostmm.c requires the dynamic memory model!\n" +#endif + +#ifndef EAS_MAX_FILE_HANDLES +// 100 max file handles == 3 * (nb tracks(32) + 1 for the segment) + 1 for jet file +// 3 == 1(playing segment) + 1(prepared segment) +// + 1(after end of playing segment, before files closed) +#define EAS_MAX_FILE_HANDLES 100 +#endif + +/* + * this structure and the related function are here + * to support the ability to create duplicate handles + * and buffering it in memory. If your system uses + * in-memory resources, you can eliminate the calls + * to malloc and free, the dup flag, and simply track + * the file size and read position. + */ +typedef struct eas_hw_file_tag +{ + EAS_I32 fileSize; + EAS_I32 filePos; + EAS_BOOL dup; + int fd; + EAS_I32 offset; +} EAS_HW_FILE; + +typedef struct eas_hw_inst_data_tag +{ + EAS_HW_FILE files[EAS_MAX_FILE_HANDLES]; +} EAS_HW_INST_DATA; + +pthread_key_t EAS_sigbuskey; + +/*---------------------------------------------------------------------------- + * EAS_HWInit + * + * Initialize host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData) +{ + EAS_HW_FILE *file; + int i; + + /* need to track file opens for duplicate handles */ + *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA)); + if (!(*pHWInstData)) + return EAS_ERROR_MALLOC_FAILED; + + EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA)); + + file = (*pHWInstData)->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + file->fd = -1; + file++; + } + + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_HWShutdown + * + * Shut down host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData) +{ + + free(hwInstData); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMalloc + * + * Allocates dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size) +{ + /* Since this whole library loves signed sizes, let's not let + * negative or 0 values through */ + if (size <= 0) + return NULL; + return malloc((size_t) size); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFree + * + * Frees dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p) +{ + free(p); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCpy + * + * Copy memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount) +{ + if (amount < 0) { + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000004 , amount); + exit(255); + } + return memcpy(dest, src, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemSet + * + * Set memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount) +{ + if (amount < 0) { + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000005 , amount); + exit(255); + } + return memset(dest, val, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCmp + * + * Compare memory wrapper + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount) +{ + if (amount < 0) { + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000006 , amount); + exit(255); + } + return (EAS_I32) memcmp(s1, s2, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWOpenFile + * + * Open a file for read or write + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) +{ + EAS_HW_FILE *file; + int fd; + int i; + + /* set return value to NULL */ + *pFile = NULL; + + /* only support read mode at this time */ + if (mode != EAS_FILE_READ) + return EAS_ERROR_INVALID_FILE_MODE; + + /* find an empty entry in the file table */ + file = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (file->fd < 0) + { + if (locator->path) { + /* open the file */ + if ((fd = open(locator->path, O_RDONLY)) < 0) { + return EAS_ERROR_FILE_OPEN_FAILED; + } + } else { + /* else file is already open */ + fd = dup(locator->fd); + } + + /* determine the file size */ + if (locator->length == 0) { + if (lseek(fd, 0, SEEK_END) < 0) { + close(fd); + return EAS_ERROR_FILE_LENGTH; + } + if ((file->fileSize = (EAS_I32)lseek(fd, 0, SEEK_CUR)) == -1L) { + close(fd); + return EAS_ERROR_FILE_LENGTH; + } + } + + // file size was passed in + else { + file->fileSize = (EAS_I32) locator->length; + } + + file->fd = fd; + file->offset = (EAS_I32)locator->offset; + + /* initialize some values */ + file->filePos = 0; + file->dup = EAS_FALSE; + + *pFile = file; + return EAS_SUCCESS; + } + file++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + + +/*---------------------------------------------------------------------------- + * + * EAS_HWReadFile + * + * Read data from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) +{ + EAS_I32 count; + + /* make sure we have a valid handle */ + if (file->fd < 0) + return EAS_ERROR_INVALID_HANDLE; + + if (n < 0) + return EAS_EOF; + + /* calculate the bytes to read */ + count = file->fileSize - file->filePos; + if (n < count) + count = n; + if (count < 0) + return EAS_EOF; + + /* copy the data to the requested location, and advance the pointer */ + if (count) { + lseek(file->fd, file->filePos + file->offset, SEEK_SET); + count = read(file->fd, pBuffer, count); + } + file->filePos += count; + *pBytesRead = count; + + /* were n bytes read? */ + if (count!= n) + return EAS_EOF; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetByte + * + * Read a byte from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) +{ + EAS_I32 numread; + return EAS_HWReadFile(hwInstData, file, p, 1, &numread); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetWord + * + * Read a 16 bit word from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2; + + /* read 2 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2; + else + *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetDWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2,c3,c4; + + /* read 4 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4; + else + *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFilePos + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) +{ + + /* make sure we have a valid handle */ + if (file->fd < 0) + return EAS_ERROR_INVALID_HANDLE; + + *pPosition = file->filePos; + return EAS_SUCCESS; +} /* end EAS_HWFilePos */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeek + * + * Seek to a specific location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* make sure we have a valid handle */ + if (file->fd < 0) + return EAS_ERROR_INVALID_HANDLE; + + /* validate new position */ + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeekOfs + * + * Seek forward or back relative to the current position + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* make sure we have a valid handle */ + if (file->fd < 0) + return EAS_ERROR_INVALID_HANDLE; + + /* determine the file position */ + position += file->filePos; + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileLength + * + * Return the file length + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) +{ + + /* make sure we have a valid handle */ + if (file->fd < 0) + return EAS_ERROR_INVALID_HANDLE; + + *pLength = file->fileSize; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWDupHandle + * + * Duplicate a file handle + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile) +{ + EAS_HW_FILE *dupFile; + int i; + + /* make sure we have a valid handle */ + if (file->fd < 0) + return EAS_ERROR_INVALID_HANDLE; + + /* find an empty entry in the file table */ + dupFile = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (dupFile->fd < 0) + { + /* copy info from the handle to be duplicated */ + dupFile->filePos = file->filePos; + dupFile->fileSize = file->fileSize; + dupFile->fd = file->fd; + dupFile->offset = file->offset; + + /* set the duplicate handle flag */ + dupFile->dup = file->dup = EAS_TRUE; + + *pDupFile = dupFile; + return EAS_SUCCESS; + } + dupFile++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWClose + * + * Wrapper for fclose function + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) +{ + EAS_HW_FILE *file2,*dupFile; + int i; + + + /* make sure we have a valid handle */ + if (file1->fd < 0) + return EAS_ERROR_INVALID_HANDLE; + + /* check for duplicate handle */ + if (file1->dup) + { + dupFile = NULL; + file2 = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* check for duplicate */ + if ((file1 != file2) && (file2->fd == file1->fd)) + { + /* is there more than one duplicate? */ + if (dupFile != NULL) + { + /* clear this entry and return */ + file1->fd = -1; + return EAS_SUCCESS; + } + + /* this is the first duplicate found */ + else + dupFile = file2; + } + file2++; + } + + /* there is only one duplicate, clear the dup flag */ + if (dupFile) + dupFile->dup = EAS_FALSE; + else + /* if we get here, there's a serious problem */ + return EAS_ERROR_HANDLE_INTEGRITY; + + /* clear this entry and return */ + file1->fd = -1; + return EAS_SUCCESS; + } + + /* no duplicates - close the file */ + close(file1->fd); + /* clear this entry and return */ + file1->fd = -1; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWVibrate + * + * Turn on/off vibrate function + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000001 , state); + return EAS_SUCCESS; +} /* end EAS_HWVibrate */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWLED + * + * Turn on/off LED + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000002 , state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWBackLight + * + * Turn on/off backlight + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000003 , state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWYield + * + * This function is called periodically by the EAS library to give the + * host an opportunity to allow other tasks to run. There are two ways to + * use this call: + * + * If you have a multi-tasking OS, you can call the yield function in the + * OS to allow other tasks to run. In this case, return EAS_FALSE to tell + * the EAS library to continue processing when control returns from this + * function. + * + * If tasks run in a single thread by sequential function calls (sometimes + * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to + * return to the caller. Be sure to check the number of bytes rendered + * before passing the audio buffer to the codec - it may not be filled. + * The next call to EAS_Render will continue processing until the buffer + * has been filled. + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData) +{ + /* put your code here */ + return EAS_FALSE; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_main.c b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_main.c new file mode 100755 index 0000000..5cbf064 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_main.c @@ -0,0 +1,464 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_main.c + * + * Contents and purpose: + * The entry point and high-level functions for the EAS Synthesizer test + * harness. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 775 $ + * $Date: 2007-07-20 10:11:11 -0700 (Fri, 20 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#include +#endif + +#include "eas.h" +#include "eas_wave.h" +#include "eas_report.h" + +/* determines how many EAS buffers to fill a host buffer */ +#define NUM_BUFFERS 8 + +/* default file to play if no filename is specified on the command line */ +static const char defaultTestFile[] = "test.mid"; + +EAS_I32 polyphony; + +/* prototypes for helper functions */ +static void StrCopy(char *dest, const char *src, EAS_I32 size); +static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size); +static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize); +static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig); + +/* main is defined after playfile to avoid the need for two passes through lint */ + +/*---------------------------------------------------------------------------- + * PlayFile() + *---------------------------------------------------------------------------- + * Purpose: + * This function plays the file requested by filename + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize) +{ + EAS_HANDLE handle; + EAS_RESULT result, reportResult; + EAS_I32 count; + EAS_STATE state; + EAS_I32 playTime; + char waveFilename[256]; + WAVE_FILE *wFile; + EAS_INT i; + EAS_PCM *p; + EAS_FILE file; + + /* determine the name of the output file */ + wFile = NULL; + if (outputFile == NULL) + { + StrCopy(waveFilename, filename, sizeof(waveFilename)); + if (!ChangeFileExt(waveFilename, "wav", sizeof(waveFilename))) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error in output filename %s\n", waveFilename); */ } + return EAS_FAILURE; + } + outputFile = waveFilename; + } + + /* call EAS library to open file */ + file.path = filename; + file.fd = 0; + if ((reportResult = EAS_OpenFile(easData, &file, &handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_OpenFile returned %ld\n", reportResult); */ } + return reportResult; + } + + /* prepare to play the file */ + if ((result = EAS_Prepare(easData, handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Prepare returned %ld\n", result); */ } + reportResult = result; + } + + /* get play length */ + if ((result = EAS_ParseMetaData(easData, handle, &playTime)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_ParseMetaData returned %ld\n", result); */ } + return result; + } + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0xe624f4d9, 0x00000005 , playTime / 1000, playTime % 1000); + + if (reportResult == EAS_SUCCESS) + { + /* create the output file */ + wFile = WaveFileCreate(outputFile, pLibConfig->numChannels, pLibConfig->sampleRate, sizeof(EAS_PCM) * 8); + if (!wFile) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to create output file %s\n", waveFilename); */ } + reportResult = EAS_FAILURE; + } + } + + /* rendering loop */ + while (reportResult == EAS_SUCCESS) + { + + /* we may render several buffers here to fill one host buffer */ + for (i = 0, p = buffer; i < NUM_BUFFERS; i++, p+= pLibConfig->mixBufferSize * pLibConfig->numChannels) + { + + /* get the current time */ + if ((result = EAS_GetLocation(easData, handle, &playTime)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_GetLocation returned %d\n",result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + break; + } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Parser time: %d.%03d\n", playTime / 1000, playTime % 1000); */ } + + /* render a buffer of audio */ + if ((result = EAS_Render(easData, p, pLibConfig->mixBufferSize, &count)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Render returned %d\n",result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + + if (result == EAS_SUCCESS) + { + /* write it to the wave file */ + if (WaveFileWrite(wFile, buffer, bufferSize) != bufferSize) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "WaveFileWrite failed\n"); */ } + reportResult = EAS_FAILURE; + } + } + + if (reportResult == EAS_SUCCESS) + { + /* check stream state */ + if ((result = EAS_State(easData, handle, &state)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_State returned %d\n", result); */ } + reportResult = result; + } + + /* is playback complete */ + if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) + break; + } + } + + /* close the output file */ + if (wFile) + { + if (!WaveFileClose(wFile)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error closing wave file %s\n", waveFilename); */ } + if (reportResult == EAS_SUCCESS) + result = EAS_FAILURE; + } + } + + /* close the input file */ + if ((result = EAS_CloseFile(easData,handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Close returned %ld\n", result); */ } + if (reportResult == EAS_SUCCESS) + result = EAS_FAILURE; + } + + return reportResult; +} /* end PlayFile */ + +/*---------------------------------------------------------------------------- + * main() + *---------------------------------------------------------------------------- + * Purpose: The entry point for the EAS sample application + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +int main( int argc, char **argv ) +{ + EAS_DATA_HANDLE easData; + const S_EAS_LIB_CONFIG *pLibConfig; + void *buffer; + EAS_RESULT result, playResult; + EAS_I32 bufferSize; + int i; + int temp; + FILE *debugFile; + char *outputFile = NULL; + + /* set the error reporting level */ + EAS_SetDebugLevel(_EAS_SEVERITY_INFO); + debugFile = NULL; + + /* process command-line arguments */ + for (i = 1; i < argc; i++) + { + /* check for switch */ + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'd': + temp = argv[i][2]; + if ((temp >= '0') || (temp <= '9')) + EAS_SetDebugLevel(temp); + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid debug level %d\n", temp); */ } + break; + case 'f': + if ((debugFile = fopen(&argv[i][2],"w")) == NULL) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unable to create debug file %s\n", &argv[i][2]); */ } + else + EAS_SetDebugFile(debugFile, EAS_TRUE); + break; + case 'o': + outputFile = &argv[i][2]; + break; + case 'p': + polyphony = atoi(&argv[i][2]); + if (polyphony < 1) + polyphony = 1; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Polyphony set to %d\n", polyphony); */ } + break; + default: + break; + } + continue; + } + } + + /* assume success */ + playResult = EAS_SUCCESS; + + /* get the library configuration */ + pLibConfig = EAS_Config(); + if (!EASLibraryCheck(pLibConfig)) + return -1; + if (polyphony > pLibConfig->maxVoices) + polyphony = pLibConfig->maxVoices; + + /* calculate buffer size */ + bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS; + + /* allocate output buffer memory */ + buffer = malloc((EAS_U32)bufferSize); + if (!buffer) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Error allocating memory for audio buffer\n"); */ } + return EAS_FAILURE; + } + + /* initialize the EAS library */ + polyphony = pLibConfig->maxVoices; + if ((result = EAS_Init(&easData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Init returned %ld - aborting!\n", result); */ } + free(buffer); + return result; + } + + /* + * Some debugging environments don't allow for passed parameters. + * In this case, just play the default MIDI file "test.mid" + */ + if (argc < 2) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", defaultTestFile); */ } + if ((playResult = PlayFile(easData, defaultTestFile, NULL, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, defaultTestFile); */ } + } + } + /* iterate through the list of files to be played */ + else + { + for (i = 1; i < argc; i++) + { + /* check for switch */ + if (argv[i][0] != '-') + { + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", argv[i]); */ } + if ((playResult = PlayFile(easData, argv[i], outputFile, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, argv[i]); */ } + break; + } + } + } + } + + /* shutdown the EAS library */ + if ((result = EAS_Shutdown(easData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Shutdown returned %ld\n", result); */ } + } + + /* free the output buffer */ + free(buffer); + + /* close the debug file */ + if (debugFile) + fclose(debugFile); + + /* play errors take precedence over shutdown errors */ + if (playResult != EAS_SUCCESS) + return playResult; + return result; +} /* end main */ + +/*---------------------------------------------------------------------------- + * StrCopy() + *---------------------------------------------------------------------------- + * Purpose: + * Safe string copy + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void StrCopy(char *dest, const char *src, EAS_I32 size) +{ + int len; + + strncpy(dest, src, (size_t) size-1); + len = (int) strlen(src); + if (len < size) + dest[len] = 0; +} /* end StrCopy */ + +/*---------------------------------------------------------------------------- + * ChangeFileExt() + *---------------------------------------------------------------------------- + * Purpose: + * Changes the file extension of a filename + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size) +{ + char *p; + + /* find the extension, if any */ + p = strrchr(str,'.'); + if (!p) + { + if ((EAS_I32)(strlen(str) + 5) > size) + return EAS_FALSE; + strcat(str,"."); + strcat(str,ext); + return EAS_TRUE; + } + + /* make sure there's room for the extension */ + p++; + *p = 0; + if ((EAS_I32)(strlen(str) + 4) > size) + return EAS_FALSE; + strcat(str,ext); + return EAS_TRUE; +} /* end ChangeFileExt */ + +/*---------------------------------------------------------------------------- + * EASLibraryCheck() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the library version and checks it against the header + * file used to build this code. + * + * Inputs: + * pLibConfig - library configuration retrieved from the library + * + * Outputs: + * returns EAS_TRUE if matched + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig) +{ + + /* display the library version */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "EAS Library Version %d.%d.%d.%d\n", + pLibConfig->libVersion >> 24, + (pLibConfig->libVersion >> 16) & 0x0f, + (pLibConfig->libVersion >> 8) & 0x0f, + pLibConfig->libVersion & 0x0f); */ } + + /* display some info about the library build */ + if (pLibConfig->checkedVersion) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tChecked library\n"); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMaximum polyphony: %d\n", pLibConfig->maxVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tNumber of channels: %d\n", pLibConfig->numChannels); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tSample rate: %d\n", pLibConfig->sampleRate); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMix buffer size: %d\n", pLibConfig->mixBufferSize); */ } + if (pLibConfig->filterEnabled) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tFilter enabled\n"); */ } +#ifndef _WIN32_WCE + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build Timestamp: %s", ctime((time_t*)&pLibConfig->buildTimeStamp)); */ } +#endif + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build ID: %s\n", pLibConfig->buildGUID); */ } + + /* check it against the header file used to build this code */ + /*lint -e{778} constant expression used for display purposes may evaluate to zero */ + if (LIB_VERSION != pLibConfig->libVersion) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Library version does not match header files. EAS Header Version %d.%d.%d.%d\n", + LIB_VERSION >> 24, + (LIB_VERSION >> 16) & 0x0f, + (LIB_VERSION >> 8) & 0x0f, + LIB_VERSION & 0x0f); */ } + return EAS_FALSE; + } + return EAS_TRUE; +} /* end EASLibraryCheck */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_report.c b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_report.c new file mode 100755 index 0000000..92f3840 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_report.c @@ -0,0 +1,264 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_report.c + * + * Contents and purpose: + * This file contains the debug message handling routines for the EAS library. + * These routines should be modified as needed for your system. + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 659 $ + * $Date: 2007-04-24 13:36:35 -0700 (Tue, 24 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#endif + +#include "eas_report.h" + +static int severityLevel = 9999; + +/* debug file */ +static FILE *debugFile = NULL; +int flush = 0; + +#ifndef _NO_DEBUG_PREPROCESSOR + +/* structure should have an #include for each error message header file */ +S_DEBUG_MESSAGES debugMessages[] = +{ +//#ifndef UNIFIED_DEBUG_MESSAGES +//#include "eas_config_msgs.h" +// +// +//#include "eas_host_msgs.h" +//#include "eas_hostmm_msgs.h" +//#include "eas_math_msgs.h" +//#include "eas_midi_msgs.h" +//#include "eas_mixer_msgs.h" +//#include "eas_pcm_msgs.h" +//#include "eas_public_msgs.h" +//#include "eas_smf_msgs.h" +//#include "eas_wave_msgs.h" +//#include "eas_voicemgt_msgs.h" +// +//#ifdef _FM_SYNTH +//#include "eas_fmsynth_msgs.h" +//#include "eas_fmengine_msgs.h" +//#endif +// +//#ifdef _WT_SYNTH +//#include "eas_wtsynth_msgs.h" +//#include "eas_wtengine_msgs.h" +//#endif +// +//#ifdef _ARM_TEST_MAIN +//#include "arm_main_msgs.h" +//#endif +// +//#ifdef _EAS_MAIN +//#include "eas_main_msgs.h" +//#endif +// +//#ifdef _EAS_MAIN_IPC +//#include "eas_main_ipc_msgs.h" +//#endif +// +//#ifdef _METRICS_ENABLED +//#include "eas_perf_msgs.h" +//#endif +// +//#ifdef _COMPRESSOR_ENABLED +//#include "eas_compressor_msgs.h" +//#endif +// +//#ifdef _ENHANCER_ENABLED +//#include "eas_enhancer_msgs.h" +//#endif +// +//#ifdef _WOW_ENABLED +//#include "eas_wow_msgs.h" +//#endif +// +//#ifdef _SMAF_PARSER +//#include "eas_smaf_msgs.h" +//#endif +// +//#ifdef _OTA_PARSER +//#include "eas_ota_msgs.h" +//#endif +// +//#ifdef _IMELODY_PARSER +//#include "eas_imelody_msgs.h" +//#endif +// +//#ifdef _WAVE_PARSER +//#include "eas_wavefile_msgs.h" +//#endif +// +//#if defined(_CMX_PARSER) || defined(_MFI_PARSER) +//#include "eas_cmf_msgs.h" +//#endif +// +//#if defined(_CMX_PARSER) || defined(_MFI_PARSER) || defined(_WAVE_PARSER) +//#include "eas_imaadpcm_msgs.h" +//#endif + +//#else +#include "eas_debugmsgs.h" +//#endif + +/* denotes end of error messages */ +{ 0,0,0 } +}; + +/*---------------------------------------------------------------------------- + * EAS_ReportEx() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...) +{ + va_list vargs; + int i; + + /* check severity level */ + if (severity > severityLevel) + return; + + /* find the error message and output to stdout */ + /*lint -e{661} we check for NULL pointer - no fence post error here */ + for (i = 0; debugMessages[i].m_pDebugMsg; i++) + { + if ((debugMessages[i].m_nHashCode == hashCode) && + (debugMessages[i].m_nSerialNum == serialNum)) + { + /*lint -e{826} */ + va_start(vargs, serialNum); + if (debugFile) + { + vfprintf(debugFile, debugMessages[i].m_pDebugMsg, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(debugMessages[i].m_pDebugMsg, vargs); + } + va_end(vargs); + return; + } + } + printf("Unrecognized error: Severity=%d; HashCode=%lu; SerialNum=%d\n", severity, hashCode, serialNum); +} /* end EAS_ReportEx */ + +#else +/*---------------------------------------------------------------------------- + * EAS_Report() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_Report (int severity, const char *fmt, ...) +{ + va_list vargs; + + /* check severity level */ + if (severity > severityLevel) + return; + + /*lint -e{826} */ + va_start(vargs, fmt); + if (debugFile) + { + vfprintf(debugFile, fmt, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(fmt, vargs); + } + va_end(vargs); +} /* end EAS_Report */ + +/*---------------------------------------------------------------------------- + * EAS_ReportX() + * + * This is the error message handler. The default handler outputs error + * messages to stdout. Modify this as needed for your system. + *---------------------------------------------------------------------------- +*/ +void EAS_ReportX (int severity, const char *fmt, ...) +{ + va_list vargs; + + /* check severity level */ + if (severity > severityLevel) + return; + + /*lint -e{826} */ + va_start(vargs, fmt); + if (debugFile) + { + vfprintf(debugFile, fmt, vargs); + if (flush) + fflush(debugFile); + } + else + { + vprintf(fmt, vargs); + } + va_end(vargs); +} /* end EAS_ReportX */ +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetDebugLevel() + * + * Sets the level for debug message output + *---------------------------------------------------------------------------- +*/ + +void EAS_SetDebugLevel (int severity) +{ + severityLevel = severity; +} /* end EAS_SetDebugLevel */ + +/*---------------------------------------------------------------------------- + * EAS_SetDebugFile() + * + * Redirect debugger output to the specified file. + *---------------------------------------------------------------------------- +*/ +void EAS_SetDebugFile (void *file, int flushAfterWrite) +{ + debugFile = (FILE*) file; + flush = flushAfterWrite; +} /* end EAS_SetDebugFile */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_report.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_report.h new file mode 100755 index 0000000..b603b12 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_report.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_report.h + * + * Contents and purpose: + * This file contains the debug message handling routines for the EAS library. + * These routines should be modified as needed for your system. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +/* sentinel */ +#ifndef _EAS_REPORT_H +#define _EAS_REPORT_H + +#define _EAS_SEVERITY_NOFILTER 0 +#define _EAS_SEVERITY_FATAL 1 +#define _EAS_SEVERITY_ERROR 2 +#define _EAS_SEVERITY_WARNING 3 +#define _EAS_SEVERITY_INFO 4 +#define _EAS_SEVERITY_DETAIL 5 + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _NO_DEBUG_PREPROCESSOR + +/* structure for included debug message header files */ +typedef struct +{ + unsigned long m_nHashCode; + int m_nSerialNum; + char *m_pDebugMsg; +} S_DEBUG_MESSAGES; + +/* debug message handling prototypes */ +extern void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...); + +#else + +/* these prototypes are used if the debug preprocessor is not used */ +extern void EAS_Report (int severity, const char* fmt, ...); +extern void EAS_ReportX (int severity, const char* fmt, ...); + +#endif + +extern void EAS_SetDebugLevel (int severity); +extern void EAS_SetDebugFile (void *file, int flushAfterWrite); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_reverb.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_reverb.h new file mode 100755 index 0000000..559abed --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_reverb.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverb.h + * + * Contents and purpose: + * Contains parameter enumerations for the Reverb effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 300 $ + * $Date: 2006-09-11 17:37:20 -0700 (Mon, 11 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_REVERB_H +#define _EAS_REVERB_H + + +/* enumerated parameter settings for Reverb effect */ +typedef enum +{ + EAS_PARAM_REVERB_BYPASS, + EAS_PARAM_REVERB_PRESET, + EAS_PARAM_REVERB_WET, + EAS_PARAM_REVERB_DRY +} E_REVERB_PARAMS; + + +typedef enum +{ + EAS_PARAM_REVERB_LARGE_HALL, + EAS_PARAM_REVERB_HALL, + EAS_PARAM_REVERB_CHAMBER, + EAS_PARAM_REVERB_ROOM, +} E_REVERB_PRESETS; + + +#endif /* _REVERB_H */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_types.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_types.h new file mode 100755 index 0000000..d66a2b7 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_types.h @@ -0,0 +1,273 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_types.h + * + * Contents and purpose: + * The public interface header for the EAS synthesizer. + * + * This header only contains declarations that are specific + * to this implementation. + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 726 $ + * $Date: 2007-06-14 23:10:46 -0700 (Thu, 14 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_TYPES_H +#define _EAS_TYPES_H + +/* EAS_RESULT return codes */ +typedef long EAS_RESULT; +#define EAS_SUCCESS 0 +#define EAS_FAILURE -1 +#define EAS_ERROR_INVALID_MODULE -2 +#define EAS_ERROR_MALLOC_FAILED -3 +#define EAS_ERROR_FILE_POS -4 +#define EAS_ERROR_INVALID_FILE_MODE -5 +#define EAS_ERROR_FILE_SEEK -6 +#define EAS_ERROR_FILE_LENGTH -7 +#define EAS_ERROR_NOT_IMPLEMENTED -8 +#define EAS_ERROR_CLOSE_FAILED -9 +#define EAS_ERROR_FILE_OPEN_FAILED -10 +#define EAS_ERROR_INVALID_HANDLE -11 +#define EAS_ERROR_NO_MIX_BUFFER -12 +#define EAS_ERROR_PARAMETER_RANGE -13 +#define EAS_ERROR_MAX_FILES_OPEN -14 +#define EAS_ERROR_UNRECOGNIZED_FORMAT -15 +#define EAS_BUFFER_SIZE_MISMATCH -16 +#define EAS_ERROR_FILE_FORMAT -17 +#define EAS_ERROR_SMF_NOT_INITIALIZED -18 +#define EAS_ERROR_LOCATE_BEYOND_END -19 +#define EAS_ERROR_INVALID_PCM_TYPE -20 +#define EAS_ERROR_MAX_PCM_STREAMS -21 +#define EAS_ERROR_NO_VOICE_ALLOCATED -22 +#define EAS_ERROR_INVALID_CHANNEL -23 +#define EAS_ERROR_ALREADY_STOPPED -24 +#define EAS_ERROR_FILE_READ_FAILED -25 +#define EAS_ERROR_HANDLE_INTEGRITY -26 +#define EAS_ERROR_MAX_STREAMS_OPEN -27 +#define EAS_ERROR_INVALID_PARAMETER -28 +#define EAS_ERROR_FEATURE_NOT_AVAILABLE -29 +#define EAS_ERROR_SOUND_LIBRARY -30 +#define EAS_ERROR_NOT_VALID_IN_THIS_STATE -31 +#define EAS_ERROR_NO_VIRTUAL_SYNTHESIZER -32 +#define EAS_ERROR_FILE_ALREADY_OPEN -33 +#define EAS_ERROR_FILE_ALREADY_CLOSED -34 +#define EAS_ERROR_INCOMPATIBLE_VERSION -35 +#define EAS_ERROR_QUEUE_IS_FULL -36 +#define EAS_ERROR_QUEUE_IS_EMPTY -37 +#define EAS_ERROR_FEATURE_ALREADY_ACTIVE -38 + +/* special return codes */ +#define EAS_EOF 3 +#define EAS_STREAM_BUFFERING 4 +#define EAS_BUFFER_FULL 5 + +/* EAS_STATE return codes */ +typedef long EAS_STATE; +typedef enum +{ + EAS_STATE_READY = 0, + EAS_STATE_PLAY, + EAS_STATE_STOPPING, + EAS_STATE_PAUSING, + EAS_STATE_STOPPED, + EAS_STATE_PAUSED, + EAS_STATE_OPEN, + EAS_STATE_ERROR, + EAS_STATE_EMPTY +} E_EAS_STATE; + +/* constants */ +#ifndef EAS_CONST +#define EAS_CONST const +#endif + +/* definition for public interface functions */ +#ifndef EAS_PUBLIC +#define EAS_PUBLIC +#endif + +/* boolean values */ +typedef unsigned EAS_BOOL; +typedef unsigned char EAS_BOOL8; + +#define EAS_FALSE 0 +#define EAS_TRUE 1 + +/* scalar variable definitions */ +typedef unsigned char EAS_U8; +typedef signed char EAS_I8; +typedef char EAS_CHAR; + +typedef unsigned short EAS_U16; +typedef short EAS_I16; + +typedef unsigned long EAS_U32; +typedef long EAS_I32; + +typedef unsigned EAS_UINT; +typedef int EAS_INT; +typedef long EAS_LONG; + +/* audio output type */ +typedef short EAS_PCM; + +/* file open modes */ +typedef EAS_I32 EAS_FILE_MODE; +#define EAS_FILE_READ 1 +#define EAS_FILE_WRITE 2 + +/* file locator e.g. filename or memory pointer */ +typedef struct s_eas_file_tag { + const char* path; + int fd; + long long offset; + long long length; +} EAS_FILE, *EAS_FILE_LOCATOR; + +/* handle to stream */ +typedef struct s_eas_stream_tag *EAS_HANDLE; + +/* handle to file */ +typedef struct eas_hw_file_tag *EAS_FILE_HANDLE; + +/* handle for synthesizer data */ +typedef struct s_eas_data_tag *EAS_DATA_HANDLE; + +/* handle to persistent data for host wrapper interface */ +typedef struct eas_hw_inst_data_tag *EAS_HW_DATA_HANDLE; + +/* handle to sound library */ +typedef struct s_eas_sndlib_tag *EAS_SNDLIB_HANDLE; +typedef struct s_eas_dls_tag *EAS_DLSLIB_HANDLE; + +/* pointer to frame buffer - used in split architecture only */ +typedef struct s_eas_frame_buffer_tag *EAS_FRAME_BUFFER_HANDLE; + +/* untyped pointer for instance data */ +typedef void *EAS_VOID_PTR; + +/* inline functions */ +#ifndef EAS_INLINE +#if defined (__XCC__) +#define EAS_INLINE __inline__ +#elif defined (__GNUC__) +#define EAS_INLINE inline static +#else +#define EAS_INLINE __inline +#endif +#endif + +/* define NULL value */ +#ifndef NULL +#define NULL 0 +#endif + +/* metadata types for metadata return codes */ +typedef enum +{ + EAS_METADATA_UNKNOWN = 0, + EAS_METADATA_TITLE, + EAS_METADATA_AUTHOR, + EAS_METADATA_COPYRIGHT, + EAS_METADATA_LYRIC, + EAS_METADATA_TEXT +} E_EAS_METADATA_TYPE; + +/* metadata callback function */ +typedef void (*EAS_METADATA_CBFUNC) (E_EAS_METADATA_TYPE metaDataType, char *metaDataBuf, EAS_VOID_PTR pUserData); + +/* file types for metadata return codes */ +typedef enum +{ + EAS_FILE_UNKNOWN = 0, + EAS_FILE_SMF0, + EAS_FILE_SMF1, + EAS_FILE_SMAF_UNKNOWN, + EAS_FILE_SMAF_MA2, + EAS_FILE_SMAF_MA3, + EAS_FILE_SMAF_MA5, + EAS_FILE_CMX, + EAS_FILE_MFI, + EAS_FILE_OTA, + EAS_FILE_IMELODY, + EAS_FILE_RTTTL, + EAS_FILE_XMF0, + EAS_FILE_XMF1, + EAS_FILE_WAVE_PCM, + EAS_FILE_WAVE_IMA_ADPCM, + EAS_FILE_MMAPI_TONE_CONTROL +} E_EAS_FILE_TYPE; + +/* enumeration for synthesizers */ +typedef enum +{ + EAS_MCU_SYNTH = 0, + EAS_DSP_SYNTH +} E_SYNTHESIZER; + +/* external audio callback program change */ +typedef struct s_ext_audio_prg_chg_tag +{ + EAS_U16 bank; + EAS_U8 program; + EAS_U8 channel; +} S_EXT_AUDIO_PRG_CHG; + +/* external audio callback event */ +typedef struct s_ext_audio_event_tag +{ + EAS_U8 channel; + EAS_U8 note; + EAS_U8 velocity; + EAS_BOOL8 noteOn; +} S_EXT_AUDIO_EVENT; + +typedef struct s_midi_controllers_tag +{ + EAS_U8 modWheel; /* CC1 */ + EAS_U8 volume; /* CC7 */ + EAS_U8 pan; /* CC10 */ + EAS_U8 expression; /* CC11 */ + EAS_U8 channelPressure; /* MIDI channel pressure */ + +#ifdef _REVERB + EAS_U8 reverbSend; /* CC91 */ +#endif + +#ifdef _CHORUS + EAS_U8 chorusSend; /* CC93 */ +#endif +} S_MIDI_CONTROLLERS; + +/* iMode play modes enumeration for EAS_SetPlayMode */ +typedef enum +{ + IMODE_PLAY_ALL = 0, + IMODE_PLAY_PARTIAL +} E_I_MODE_PLAY_MODE; + +typedef EAS_BOOL (*EAS_EXT_PRG_CHG_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_PRG_CHG *pPrgChg); +typedef EAS_BOOL (*EAS_EXT_EVENT_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_EVENT *pEvent); + +#endif /* #ifndef _EAS_TYPES_H */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_wave.c b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_wave.c new file mode 100755 index 0000000..4f6ffbd --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_wave.c @@ -0,0 +1,423 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wave.c + * + * Contents and purpose: + * This module contains .WAV file functions for the EAS synthesizer + * test harness. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 658 $ + * $Date: 2007-04-24 13:35:49 -0700 (Tue, 24 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* lint complaints about most C library headers, so we use our own during lint step */ +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#endif + +#include "eas_wave.h" + +/* .WAV file format tags */ +const EAS_U32 riffTag = 0x46464952; +const EAS_U32 waveTag = 0x45564157; +const EAS_U32 fmtTag = 0x20746d66; +const EAS_U32 dataTag = 0x61746164; + +#ifdef _BIG_ENDIAN +/*---------------------------------------------------------------------------- + * FlipDWord() + *---------------------------------------------------------------------------- + * Purpose: Endian flip a DWORD for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipDWord (EAS_U32 *pValue) +{ + EAS_U8 *p; + EAS_U32 temp; + + p = (EAS_U8*) pValue; + temp = (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; + *pValue = temp; +} + +/*---------------------------------------------------------------------------- + * FlipWord() + *---------------------------------------------------------------------------- + * Purpose: Endian flip a WORD for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipWord (EAS_U16 *pValue) +{ + EAS_U8 *p; + EAS_U16 temp; + + p = (EAS_U8*) pValue; + temp = (p[1] << 8) | p[0]; + *pValue = temp; +} + +/*---------------------------------------------------------------------------- + * FlipWaveHeader() + *---------------------------------------------------------------------------- + * Purpose: Endian flip the wave header for big-endian processors + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void FlipWaveHeader (WAVE_HEADER *p) +{ + + FlipDWord(&p->nRiffTag); + FlipDWord(&p->nRiffSize); + FlipDWord(&p->nWaveTag); + FlipDWord(&p->nFmtTag); + FlipDWord(&p->nFmtSize); + FlipDWord(&p->nDataTag); + FlipDWord(&p->nDataSize); + FlipWord(&p->fc.wFormatTag); + FlipWord(&p->fc.nChannels); + FlipDWord(&p->fc.nSamplesPerSec); + FlipDWord(&p->fc.nAvgBytesPerSec); + FlipWord(&p->fc.nBlockAlign); + FlipWord(&p->fc.wBitsPerSample); + +} +#endif + +/*---------------------------------------------------------------------------- + * WaveFileCreate() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for writing and writes the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample) +{ + WAVE_FILE *wFile; + + /* allocate memory */ + wFile = malloc(sizeof(WAVE_FILE)); + if (!wFile) + return NULL; + wFile->write = EAS_TRUE; + + /* create the file */ + wFile->file = fopen(filename,"wb"); + if (!wFile->file) + { + free(wFile); + return NULL; + } + + /* initialize PCM format .WAV file header */ + wFile->wh.nRiffTag = riffTag; + wFile->wh.nRiffSize = sizeof(WAVE_HEADER) - 8; + wFile->wh.nWaveTag = waveTag; + wFile->wh.nFmtTag = fmtTag; + wFile->wh.nFmtSize = sizeof(FMT_CHUNK); + + /* initalize 'fmt' chunk */ + wFile->wh.fc.wFormatTag = 1; + wFile->wh.fc.nChannels = (EAS_U16) nChannels; + wFile->wh.fc.nSamplesPerSec = (EAS_U32) nSamplesPerSec; + wFile->wh.fc.wBitsPerSample = (EAS_U16) wBitsPerSample; + wFile->wh.fc.nBlockAlign = (EAS_U16) (nChannels * (EAS_U16) (wBitsPerSample / 8)); + wFile->wh.fc.nAvgBytesPerSec = wFile->wh.fc.nBlockAlign * (EAS_U32) nSamplesPerSec; + + /* initialize 'data' chunk */ + wFile->wh.nDataTag = dataTag; + wFile->wh.nDataSize = 0; + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + + /* write the header */ + if (fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file) != 1) + { + fclose(wFile->file); + free(wFile); + return NULL; + } + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + + /* return the file handle */ + return wFile; +} /* end WaveFileCreate */ + +/*---------------------------------------------------------------------------- + * WaveFileWrite() + *---------------------------------------------------------------------------- + * Purpose: Writes data to the wave file + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n) +{ + EAS_I32 count; + + /* make sure we have an open file */ + if (wFile == NULL) + { + return 0; + } + +#ifdef _BIG_ENDIAN + { + EAS_I32 i; + EAS_U16 *p; + p = buffer; + i = n >> 1; + while (i--) + FlipWord(p++); + } +#endif + + /* write the data */ + count = (EAS_I32) fwrite(buffer, 1, (size_t) n, wFile->file); + + /* add the number of bytes written */ + wFile->wh.nRiffSize += (EAS_U32) count; + wFile->wh.nDataSize += (EAS_U32) count; + + /* return the count of bytes written */ + return count; +} /* end WriteWaveHeader */ + +/*---------------------------------------------------------------------------- + * WaveFileClose() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for writing and writes the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +EAS_BOOL WaveFileClose (WAVE_FILE *wFile) +{ + EAS_I32 count = 1; + + /* return to beginning of file and write the header */ + if (wFile->write) + { + if (fseek(wFile->file, 0L, SEEK_SET) == 0) + { + +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + count = (EAS_I32) fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file); +#ifdef _BIG_ENDIAN + FlipWaveHeader(&wFile->wh); +#endif + } + } + + /* close the file */ + if (fclose(wFile->file) != 0) + count = 0; + + /* free the memory */ + free(wFile); + + /* return the file handle */ + return (count == 1 ? EAS_TRUE : EAS_FALSE); +} /* end WaveFileClose */ + +#ifdef _WAVE_FILE_READ +#ifdef _BIG_ENDIAN +#error "WaveFileOpen not currently supported on big-endian processors" +#endif +/*---------------------------------------------------------------------------- + * WaveFileOpen() + *---------------------------------------------------------------------------- + * Purpose: Opens a wave file for reading and reads the header + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ + +WAVE_FILE *WaveFileOpen (const char *filename) +{ + WAVE_FILE *wFile; + struct + { + EAS_U32 tag; + EAS_U32 size; + } chunk; + EAS_U32 tag; + EAS_I32 startChunkPos; + EAS_INT state; + EAS_BOOL done; + + /* allocate memory */ + wFile = malloc(sizeof(WAVE_FILE)); + if (!wFile) + return NULL; + + /* open the file */ + wFile->write = EAS_FALSE; + wFile->file = fopen(filename,"rb"); + if (!wFile->file) + { + free(wFile); + return NULL; + } + + /* make lint happy */ + chunk.tag = chunk.size = 0; + startChunkPos = 0; + + /* read the RIFF tag and file size */ + state = 0; + done = EAS_FALSE; + while (!done) + { + + switch(state) + { + /* read the RIFF tag */ + case 0: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + if (chunk.tag != riffTag) + done = EAS_TRUE; + else + state++; + } + break; + + /* read the WAVE tag */ + case 1: + if (fread(&tag, sizeof(tag), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + if (tag != waveTag) + done = EAS_TRUE; + else + state++; + } + break; + + /* looking for fmt chunk */ + case 2: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + startChunkPos = ftell(wFile->file); + + /* not fmt tag, skip it */ + if (chunk.tag != fmtTag) + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + else + state++; + } + break; + + /* read fmt chunk */ + case 3: + if (fread(&wFile->wh.fc, sizeof(FMT_CHUNK), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + state++; + } + break; + + /* looking for data chunk */ + case 4: + if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) + done = EAS_TRUE; + else + { + startChunkPos = ftell(wFile->file); + + /* not data tag, skip it */ + if (chunk.tag != dataTag) + fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); + else + { + wFile->dataSize = chunk.size; + state++; + done = EAS_TRUE; + } + } + break; + + default: + done = EAS_TRUE; + break; + } + } + + /* if not final state, an error occurred */ + if (state != 5) + { + fclose(wFile->file); + free(wFile); + return NULL; + } + + /* return the file handle */ + return wFile; +} /* end WaveFileOpen */ +#endif + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_wave.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_wave.h new file mode 100755 index 0000000..968782f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/eas_wave.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wave.h + * + * Contents and purpose: + * Writes output to a .WAV file + * + * DO NOT MODIFY THIS FILE! + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" + +/* sentinel */ +#ifndef _EAS_WAVE_H +#define _EAS_WAVE_H + +/* .WAV file format chunk */ +typedef struct { + EAS_U16 wFormatTag; + EAS_U16 nChannels; + EAS_U32 nSamplesPerSec; + EAS_U32 nAvgBytesPerSec; + EAS_U16 nBlockAlign; + EAS_U16 wBitsPerSample; +} FMT_CHUNK; + +/* .WAV file header */ +typedef struct { + EAS_U32 nRiffTag; + EAS_U32 nRiffSize; + EAS_U32 nWaveTag; + EAS_U32 nFmtTag; + EAS_U32 nFmtSize; + FMT_CHUNK fc; + EAS_U32 nDataTag; + EAS_U32 nDataSize; +} WAVE_HEADER; + +typedef struct { + WAVE_HEADER wh; + FILE *file; + EAS_BOOL write; + EAS_U32 dataSize; +} WAVE_FILE; + +WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample); +EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n); +EAS_BOOL WaveFileClose (WAVE_FILE *wFile); +WAVE_FILE *WaveFileOpen (const char *filename); + +#endif /* end #ifndef _EAS_WAVE_H */ + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/host_src/jet.h b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/jet.h new file mode 100755 index 0000000..2e97a13 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/host_src/jet.h @@ -0,0 +1,199 @@ +/*---------------------------------------------------------------------------- + * + * File: + * jet.h + * + * Contents and purpose: + * Public interface for JET sound engine + * + * Copyright (c) 2006 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 554 $ + * $Date: 2007-02-02 11:06:10 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _JET_H +#define _JET_H + +#include "eas_types.h" +#include "eas.h" + +/* for C++ linkage */ +#ifdef __cplusplus +extern "C" { +#endif + +/* opaque handle types for JET interface */ +typedef struct s_jet_data_tag *JET_DATA_HANDLE; + +typedef struct s_jet_config_tag +{ + EAS_U8 appEventRangeLow; + EAS_U8 appEventRangeHigh; +} S_JET_CONFIG; + +typedef struct s_jet_status_tag +{ + EAS_INT currentUserID; + EAS_INT segmentRepeatCount; + EAS_INT numQueuedSegments; + EAS_BOOL paused; + EAS_I32 location; + EAS_U8 currentPlayingSegment; + EAS_U8 currentQueuedSegment; +} S_JET_STATUS; + +typedef struct s_jet_event_tag +{ + EAS_U8 segment; + EAS_U8 channel; + EAS_U8 track; + EAS_U8 controller; + EAS_U8 value; +} S_JET_EVENT; + +/*---------------------------------------------------------------------------- + * JET_Init() + *---------------------------------------------------------------------------- + * Initializes the JET library, allocates memory, etc. Call + * JET_Shutdown to de-allocate memory. Pass NULL for pConfig + * to use defaults. If passing config data, configSize should be + * sizeof(S_JET_CONFIG). This allows for future expansion of the + * config structure while maintaining compatibility. + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Init (EAS_DATA_HANDLE easHandle, const S_JET_CONFIG *pConfig, EAS_INT configSize); + +/*---------------------------------------------------------------------------- + * JET_Shutdown() + *---------------------------------------------------------------------------- + * Frees any memory used by the JET library + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Shutdown (EAS_DATA_HANDLE easHandle); + +/*---------------------------------------------------------------------------- + * JET_OpenFile() + *---------------------------------------------------------------------------- + * Opens a JET content file for playback + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_OpenFile (EAS_DATA_HANDLE easHandle, EAS_FILE_LOCATOR locator); + +/*---------------------------------------------------------------------------- + * JET_GetAppData() + *---------------------------------------------------------------------------- + * Returns location and size of application data in the JET file + *---------------------------------------------------------------------------- +*/ +EAS_RESULT JET_GetAppData (EAS_DATA_HANDLE easHandle, EAS_I32 *pAppDataOffset, EAS_I32 *pAppDataSize); + +/*---------------------------------------------------------------------------- + * JET_CloseFile() + *---------------------------------------------------------------------------- + * Closes a JET content file and releases associated resources + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_CloseFile (EAS_DATA_HANDLE easHandle); + +/*---------------------------------------------------------------------------- + * JET_Status() + *---------------------------------------------------------------------------- + * Returns current status + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Status (EAS_DATA_HANDLE easHandle, S_JET_STATUS *pStatus); + +/*---------------------------------------------------------------------------- + * JET_GetEvent() + *---------------------------------------------------------------------------- + * Checks for application events + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_BOOL JET_GetEvent (EAS_DATA_HANDLE easHandle, EAS_U32 *pEventRaw, S_JET_EVENT *pEvent); + +/*---------------------------------------------------------------------------- + * JET_ParseEvent() + *---------------------------------------------------------------------------- + * Returns current status + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC void JET_ParseEvent (EAS_U32 event, S_JET_EVENT *pEvent); + +/*---------------------------------------------------------------------------- + * JET_QueueSegment() + *---------------------------------------------------------------------------- + * Queue a segment for playback + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_QueueSegment (EAS_DATA_HANDLE easHandle, EAS_INT segmentNum, EAS_INT libNum, EAS_INT repeatCount, EAS_INT transpose, EAS_U32 muteFlags, EAS_U8 userID); + +/*---------------------------------------------------------------------------- + * JET_Play() + *---------------------------------------------------------------------------- + * Starts playback of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Play (EAS_DATA_HANDLE easHandle); + +/*---------------------------------------------------------------------------- + * JET_Pause() + *---------------------------------------------------------------------------- + * Pauses playback of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Pause (EAS_DATA_HANDLE easHandle); + +/*---------------------------------------------------------------------------- + * JET_SetMuteFlags() + *---------------------------------------------------------------------------- + * Change the state of the mute flags + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_SetMuteFlags (EAS_DATA_HANDLE easHandle, EAS_U32 muteFlags, EAS_BOOL sync); + +/*---------------------------------------------------------------------------- + * JET_SetMuteFlag() + *---------------------------------------------------------------------------- + * Change the state of a single mute flag + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_SetMuteFlag (EAS_DATA_HANDLE easHandle, EAS_INT trackNum, EAS_BOOL muteFlag, EAS_BOOL sync); + +/*---------------------------------------------------------------------------- + * JET_TriggerClip() + *---------------------------------------------------------------------------- + * Unmute a track and then mute it when it is complete + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_TriggerClip (EAS_DATA_HANDLE easHandle, EAS_INT clipID); + +/*---------------------------------------------------------------------------- + * JET_Clear_Queue() + *---------------------------------------------------------------------------- + * Clears all segments in the queue + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Clear_Queue (EAS_DATA_HANDLE easHandle); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/project.pbxproj b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/project.pbxproj new file mode 100755 index 0000000..29a353c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/project.pbxproj @@ -0,0 +1,361 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 44; + objects = { + +/* Begin PBXBuildFile section */ + 9A56ACEA0F72B84D00D115A7 /* libeaswt_vst_lib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A56ACD80F72B7D600D115A7 /* libeaswt_vst_lib.a */; }; + C5AB01090E3400DC0051F183 /* EASLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C5AB01070E3400DC0051F183 /* EASLib.h */; }; + C5AB010A0E3400DC0051F183 /* EASLib.c in Sources */ = {isa = PBXBuildFile; fileRef = C5AB01080E3400DC0051F183 /* EASLib.c */; }; + C5AB01240E3406090051F183 /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = C5AB01230E3406090051F183 /* eas_config.c */; }; + C5AB017A0E340DD60051F183 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5AB01790E340DD60051F183 /* AudioUnit.framework */; }; + C5AB018C0E340EAA0051F183 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5AB018B0E340EAA0051F183 /* AudioToolbox.framework */; }; + C5AB01910E340EC50051F183 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5AB01900E340EC50051F183 /* CoreAudio.framework */; }; + C5AB02F60E341AAC0051F183 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5AB02F50E341AAC0051F183 /* Carbon.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 9A56ACD70F72B7D600D115A7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9A56ACD30F72B7D600D115A7 /* easwt_vst_lib.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D2AAC046055464E500DB518D; + remoteInfo = easwt_vst_lib; + }; + 9A56ACFC0F72B8B200D115A7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9A56ACD30F72B7D600D115A7 /* easwt_vst_lib.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D2AAC045055464E500DB518D; + remoteInfo = easwt_vst_lib; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 9A56ACD30F72B7D600D115A7 /* easwt_vst_lib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = easwt_vst_lib.xcodeproj; sourceTree = ""; }; + C5AB01070E3400DC0051F183 /* EASLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EASLib.h; sourceTree = ""; }; + C5AB01080E3400DC0051F183 /* EASLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = EASLib.c; sourceTree = ""; }; + C5AB01230E3406090051F183 /* eas_config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_config.c; path = ../../host_src/eas_config.c; sourceTree = SOURCE_ROOT; }; + C5AB01790E340DD60051F183 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = ""; }; + C5AB018B0E340EAA0051F183 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; + C5AB01900E340EC50051F183 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; + C5AB02F50E341AAC0051F183 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + D2AAC0630554660B00DB518D /* libEASLIb.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libEASLIb.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D289988505E68E00004EDB86 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9A56ACEA0F72B84D00D115A7 /* libeaswt_vst_lib.a in Frameworks */, + C5AB017A0E340DD60051F183 /* AudioUnit.framework in Frameworks */, + C5AB018C0E340EAA0051F183 /* AudioToolbox.framework in Frameworks */, + C5AB01910E340EC50051F183 /* CoreAudio.framework in Frameworks */, + C5AB02F60E341AAC0051F183 /* Carbon.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* EASLIb */ = { + isa = PBXGroup; + children = ( + 9A56ACD30F72B7D600D115A7 /* easwt_vst_lib.xcodeproj */, + C5AB02F50E341AAC0051F183 /* Carbon.framework */, + C5AB01900E340EC50051F183 /* CoreAudio.framework */, + C5AB018B0E340EAA0051F183 /* AudioToolbox.framework */, + C5AB01790E340DD60051F183 /* AudioUnit.framework */, + 08FB7795FE84155DC02AAC07 /* Source */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = EASLIb; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + C5AB01230E3406090051F183 /* eas_config.c */, + C5AB01070E3400DC0051F183 /* EASLib.h */, + C5AB01080E3400DC0051F183 /* EASLib.c */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + D2AAC0630554660B00DB518D /* libEASLIb.dylib */, + ); + name = Products; + sourceTree = ""; + }; + 9A56ACD40F72B7D600D115A7 /* Products */ = { + isa = PBXGroup; + children = ( + 9A56ACD80F72B7D600D115A7 /* libeaswt_vst_lib.a */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D2AAC0600554660B00DB518D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C5AB01090E3400DC0051F183 /* EASLib.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D2AAC0620554660B00DB518D /* EASLIb */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "EASLIb" */; + buildPhases = ( + D2AAC0600554660B00DB518D /* Headers */, + D2AAC0610554660B00DB518D /* Sources */, + D289988505E68E00004EDB86 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 9A56ACFD0F72B8B200D115A7 /* PBXTargetDependency */, + ); + name = EASLIb; + productName = EASLIb; + productReference = D2AAC0630554660B00DB518D /* libEASLIb.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "EASLIb" */; + compatibilityVersion = "Xcode 3.0"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* EASLIb */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 9A56ACD40F72B7D600D115A7 /* Products */; + ProjectRef = 9A56ACD30F72B7D600D115A7 /* easwt_vst_lib.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + D2AAC0620554660B00DB518D /* EASLIb */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 9A56ACD80F72B7D600D115A7 /* libeaswt_vst_lib.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libeaswt_vst_lib.a; + remoteRef = 9A56ACD70F72B7D600D115A7 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXSourcesBuildPhase section */ + D2AAC0610554660B00DB518D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C5AB010A0E3400DC0051F183 /* EASLib.c in Sources */, + C5AB01240E3406090051F183 /* eas_config.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 9A56ACFD0F72B8B200D115A7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = easwt_vst_lib; + targetProxy = 9A56ACFC0F72B8B200D115A7 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 1DEB914B08733D8E0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + EXECUTABLE_PREFIX = lib; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "EAS_MAX_FILE_HANDLES=100", + "_DEBUG_CMF=1", + "JET_INTERFACE=1", + "MAX_SMF_STREAMS=32", + "NUM_OUTPUT_CHANNELS=2", + "_SAMPLE_RATE_44100=1", + "_8_BIT_SAMPLES=1", + "_FILTER_ENABLED=1", + "_NO_DEBUG_PREPROCESSOR=1", + "_CORE_CYCLES_PER_MEMORY_CYCLE=1", + "_IMA_DECODER=1", + "_XMF_PARSER=1", + "_DLS_PARSER=1", + "MAX_DLS_MEMORY=16777216", + "EAS_WT_SYNTH=1", + "MAX_SYNTH_VOICES=64", + "X_ENHANCER_ENABLED=1", + "_REVERB_ENABLED=1", + "_CHORUS_ENABLED=1", + "DLS_SYNTHESIZER=1", + "EXTERNAL_AUDIO=1", + "TEST_HARNESS=1", + "MMAPI_SUPPORT=1", + "X_MAXIMIZER_ENABLED=1", + "X_COMPRESSOR_ENABLED=1", + "X_STATS=1", + "X_DEBUG_DLS=1", + "X_OPTIMIZED_MONO=1", + "X_CHECKED_BUILD=1", + "_NO_ALIGN=1", + "_C_REFERENCE=1", + "XMAXIMIZER_USE_FLOATING_POINT=1", + "BUFFERED_FILE_ACCESS=1", + ); + HEADER_SEARCH_PATHS = ( + "${TARGET_BUILD_DIR}/**", + "../../Common/**", + "../../Parsers/**", + "../../Effects/**", + "../../WTSynth/**", + "../../FMSynth/**", + "../../SplitArch/**", + "../../Jet/**", + ); + INSTALL_PATH = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.4; + PRODUCT_NAME = EASLIb; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB914C08733D8E0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + EXECUTABLE_PREFIX = lib; + GCC_AUTO_VECTORIZATION = YES; + GCC_MODEL_TUNING = G5; + GCC_PREPROCESSOR_DEFINITIONS = ( + "BUFFERED_FILE_ACCESS=1", + "EAS_FILE_BUFFER_SIZE=1024", + "EAS_MAX_FILE_HANDLES=100", + "JET_INTERFACE=1", + "MAX_SMF_STREAMS=32", + "EAS_WT_SYNTH=1", + "NUM_OUTPUT_CHANNELS=2", + "_SAMPLE_RATE_44100=1", + "_8_BIT_SAMPLES=1", + "_FILTER_ENABLED=1", + "_NO_DEBUG_PREPROCESSOR=1", + "_CORE_CYCLES_PER_MEMORY_CYCLE=1", + "_IMA_DECODER=1", + "_XMF_PARSER=1", + "_DLS_PARSER=1", + "MAX_DLS_MEMORY=16777216", + "MAX_SYNTH_VOICES=64", + "X_ENHANCER_ENABLED=1", + "_REVERB_ENABLED=1", + "_CHORUS_ENABLED=1", + "DLS_SYNTHESIZER=1", + "EXTERNAL_AUDIO=1", + "TEST_HARNESS=1", + "MMAPI_SUPPORT=1", + "X_MAXIMIZER_ENABLED=1", + "X_COMPRESSOR_ENABLED=1", + "X_STATS=1", + "X_DEBUG_DLS=1", + "X_OPTIMIZED_MONO=1", + "X_CHECKED_BUILD=1", + "_NO_ALIGN=1", + "_C_REFERENCE=1", + "XMAXIMIZER_USE_FLOATING_POINT=1", + ); + GCC_UNROLL_LOOPS = YES; + HEADER_SEARCH_PATHS = ( + "${TARGET_BUILD_DIR}/**", + "../../Common/**", + "../../Parsers/**", + "../../Effects/**", + "../../WTSynth/**", + "../../FMSynth/**", + "../../SplitArch/**", + "../../Jet/**", + ); + INSTALL_PATH = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.4; + PRODUCT_NAME = EASLIb; + }; + name = Release; + }; + 1DEB914F08733D8E0010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; + }; + name = Debug; + }; + 1DEB915008733D8E0010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "EASLIb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB914B08733D8E0010E9CD /* Debug */, + 1DEB914C08733D8E0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "EASLIb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB914F08733D8E0010E9CD /* Debug */, + 1DEB915008733D8E0010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/EASLIb.xcscheme b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/EASLIb.xcscheme new file mode 100755 index 0000000..4770fdf --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/EASLIb.xcscheme @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 0000000..4f6c235 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + EASLIb.xcscheme + + orderHint + 13 + + + SuppressBuildableAutocreation + + D2AAC0620554660B00DB518D + + primary + + + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/EASLIb.xcscheme b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/EASLIb.xcscheme new file mode 100755 index 0000000..4770fdf --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/EASLIb.xcscheme @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/xcschememanagement.plist b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 0000000..b4f4c7c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLIb.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + EASLIb.xcscheme + + orderHint + 4 + + + SuppressBuildableAutocreation + + D2AAC0620554660B00DB518D + + primary + + + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.c b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.c new file mode 100755 index 0000000..ca19247 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.c @@ -0,0 +1,1809 @@ +/* + * EASLib.c + * EASLIb + * + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "eas.h" +#include "eas_report.h" +#include "eas_host.h" +#include +#include + +#ifdef JET_INTERFACE +#include "jet.h" +#endif + + +#define EAS_EXPORT __attribute__((visibility("default"))) + +// #define DEBUG_FILE_IO + +/* include debug interface */ +#include "eas_host_debug.h" + +#ifdef AUX_MIXER +#include "eas_auxmix.h" +#endif + +/* this module requires dynamic memory support */ +#ifdef _STATIC_MEMORY +#error "eas_hostmm.c requires the dynamic memory model!\n" +#endif + +#ifndef EAS_MAX_FILE_HANDLES +#define EAS_MAX_FILE_HANDLES 32 +#endif + +#ifndef EAS_FILE_BUFFER_SIZE +#define EAS_FILE_BUFFER_SIZE 32 +#endif + +/* + * this structure and the related function are here + * to support the ability to create duplicate handles + * and buffering it in memory. If your system uses + * in-memory resources, you can eliminate the calls + * to malloc and free, the dup flag, and simply track + * the file size and read position. + */ + #ifdef BUFFERED_FILE_ACCESS +typedef struct eas_hw_file_tag +{ + FILE *pFile; + EAS_I32 bytesInBuffer; + EAS_I32 readIndex; + EAS_I32 filePos; + EAS_I32 fileSize; + EAS_BOOL dup; + EAS_U8 buffer[EAS_FILE_BUFFER_SIZE]; +} EAS_HW_FILE; +#else +typedef struct eas_hw_file_tag +{ + EAS_I32 fileSize; + EAS_I32 filePos; + EAS_BOOL dup; + EAS_U8 *buffer; +} EAS_HW_FILE; +#endif + +typedef struct eas_hw_inst_data_tag +{ + EAS_HW_FILE files[EAS_MAX_FILE_HANDLES]; +} EAS_HW_INST_DATA; + +EAS_BOOL errorConditions[eNumErrorConditions]; +EAS_BOOL ledState; +EAS_BOOL vibState; +EAS_BOOL backlightState; + +#define MAX_DEBUG_MSG_LEN 1024 + +typedef void (*EAS_LOG_FUNC)(EAS_INT severity, char *msg); + +static EAS_LOG_FUNC logCallback = NULL; +static char messageBuffer[MAX_DEBUG_MSG_LEN]; + +/* error counts */ +static EAS_INT eas_fatalErrors; +static EAS_INT eas_errors; +static EAS_INT eas_warnings; +static int severityLevel = 9999; + + +#define MAX_BUFFERS 8 + +// The output unit +AudioUnit OutputUnit; +AudioStreamBasicDescription streamFormat; + +// sync stuf +pthread_mutex_t mtx; +pthread_cond_t cond; +bool bStopped = true; + +// buffer to hold the data +typedef struct +{ + UInt32 uOutBufferLength; + UInt32 uOutFrames; + int ix; + short* pData[8]; + unsigned int uLength; +} S_BUFFER_INFO; + +static S_BUFFER_INFO *pBuf = NULL; +const S_EAS_LIB_CONFIG *pConfig = NULL; + +/*---------------------------------------------------------------------------- + * ResetErrorCounters() + *---------------------------------------------------------------------------- +*/ +EAS_EXPORT void ResetErrorCounters() +{ + eas_fatalErrors = 0; + eas_errors = 0; + eas_warnings = 0; +} + +/*---------------------------------------------------------------------------- + * SetLogCallback() + *---------------------------------------------------------------------------- +*/ +EAS_EXPORT void SetLogCallback (EAS_LOG_FUNC callback) +{ + logCallback = callback; +} + +#ifndef _NO_DEBUG_PREPROCESSOR +static S_DEBUG_MESSAGES debugMessages[] = +{ +#ifdef UNIFIED_DEBUG_MESSAGES +#include "eas_debugmsgs.h" +#endif + { 0,0,0 } +}; + +/*---------------------------------------------------------------------------- + * EAS_ReportEx() + *---------------------------------------------------------------------------- +*/ +void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...) +{ + va_list vargs; + int i; + + switch (severity) + { + case _EAS_SEVERITY_FATAL: + eas_fatalErrors++; + break; + + case _EAS_SEVERITY_ERROR: + eas_errors++; + break; + + case _EAS_SEVERITY_WARNING: + eas_warnings++; + break; + + default: + break; + } + + /* check severity level */ + if (severity > severityLevel) + return; + + /* check for callback */ + if (logCallback == NULL) + return; + + /* find the error message and output to stdout */ + for (i = 0; debugMessages[i].m_pDebugMsg; i++) + { + if ((debugMessages[i].m_nHashCode == hashCode) && + (debugMessages[i].m_nSerialNum == serialNum)) + { + va_start(vargs, serialNum); +#ifdef WIN32 + vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs); +#else + vsprintf(messageBuffer, debugMessages[i].m_pDebugMsg, vargs); +#endif + logCallback(severity, messageBuffer); + va_end(vargs); + return; + } + } + printf("Unrecognized error: Severity=%d; HashCode=%lu; SerialNum=%d\n", severity, hashCode, serialNum); +} /* end EAS_ReportEx */ + +#else +/*---------------------------------------------------------------------------- + * EAS_Report() + *---------------------------------------------------------------------------- +*/ +void EAS_Report (int severity, const char *fmt, ...) +{ + va_list vargs; + + switch (severity) + { + case _EAS_SEVERITY_FATAL: + eas_fatalErrors++; + break; + + case _EAS_SEVERITY_ERROR: + eas_errors++; + break; + + case _EAS_SEVERITY_WARNING: + eas_warnings++; + break; + + default: + break; + } + + /* check severity level */ + if (severity > severityLevel) + return; + + /* check for callback */ + if (logCallback == NULL) + return; + + va_start(vargs, fmt); +#ifdef _WIN32 + vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs); +#else + vsprintf(messageBuffer, fmt, vargs); +#endif + logCallback(severity, messageBuffer); + va_end(vargs); +} /* end EAS_Report */ + +/*---------------------------------------------------------------------------- + * EAS_ReportX() + *---------------------------------------------------------------------------- +*/ +void EAS_ReportX (int severity, const char *fmt, ...) +{ + va_list vargs; + + switch (severity) + { + case _EAS_SEVERITY_FATAL: + eas_fatalErrors++; + break; + + case _EAS_SEVERITY_ERROR: + eas_errors++; + break; + + case _EAS_SEVERITY_WARNING: + eas_warnings++; + break; + + default: + break; + } + + /* check severity level */ + if (severity > severityLevel) + return; + + /* check for callback */ + if (logCallback == NULL) + return; + + va_start(vargs, fmt); +#ifdef _WIN32 + vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs); +#else + vsprintf(messageBuffer, fmt, vargs); +#endif + logCallback(severity, messageBuffer); + va_end(vargs); +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_DLLSetDebugLevel() + *---------------------------------------------------------------------------- +*/ +EAS_EXPORT void EAS_DLLSetDebugLevel (int severity) +{ + severityLevel = severity; +} + +/*---------------------------------------------------------------------------- + * EAS_ExSetDebugLevel() + *---------------------------------------------------------------------------- +*/ +void EAS_SetDebugLevel (int severity) +{ + severityLevel = severity; +} + +/*---------------------------------------------------------------------------- + * EAS_SelectLibrary() + *---------------------------------------------------------------------------- +*/ +EAS_EXPORT EAS_RESULT EAS_SelectLib (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_BOOL testLib) +{ + extern EAS_SNDLIB_HANDLE VMGetLibHandle(EAS_INT libNum); + return EAS_SetSoundLibrary(pEASData, streamHandle, VMGetLibHandle(testLib ? 1 : 0)); +} + +// Callback proc +static OSStatus RenderProc( void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) +{ + // Get the mutex + pthread_mutex_lock(&mtx); + + short* ptrOutL = (short *)ioData->mBuffers[0].mData; + short* ptrOutR = (short *)ioData->mBuffers[1].mData; + + memset(ptrOutL, 0, pBuf->uOutFrames); + memset(ptrOutR, 0, pBuf->uOutFrames); + + // check if there is any data in the buffer + if (pBuf->ix == 0 ) + { + // Release the mutex and signal the python thread + pthread_mutex_unlock(&mtx); + pthread_cond_signal(&cond); + return 0; + } + + // Get a ptr to the data + short* pData = pBuf->pData[--(pBuf->ix)]; + + // Now copy the data + int i; + for (i = 0; i < pBuf->uOutFrames; i+=2 ) + { + *ptrOutL++ = pData[i]; + *ptrOutR++ = pData[i+1]; + } + + // Release the mutex + pthread_mutex_unlock(&mtx); + pthread_cond_signal(&cond); + + return 0; +} + +EAS_RESULT addData(EAS_PCM *pAudioBuffer) +{ + // Copy the data we got from the synth + memcpy(pBuf->pData[(pBuf->ix)++], pAudioBuffer, 2048); + + // Start the output Audio Unit only the first time + if ( bStopped == true ) + { + bStopped = false; + OSStatus err = AudioOutputUnitStart (OutputUnit); + if (err) + { + printf ("AudioDeviceStart=%ld\n", err); + return EAS_FAILURE; + } + } + + return EAS_SUCCESS; +} + + +EAS_EXPORT EAS_RESULT EAS_RenderWaveOut(EAS_DATA_HANDLE easHandle, EAS_PCM *pAudioBuffer, EAS_I32 numRequested, EAS_I32 *pNumGenerated) +{ + // Get the mutex + pthread_mutex_lock(&mtx); + + // Check if our buffer is full + while(pBuf->ix == MAX_BUFFERS - 1) + pthread_cond_wait(&cond, &mtx); + + // Call the synth the render a buffer + EAS_RESULT result = EAS_Render(easHandle, pAudioBuffer, numRequested, pNumGenerated); + addData( pAudioBuffer ); + + // Release the mutex + pthread_mutex_unlock(&mtx); + + //Done + return result; +} + +#ifdef AUX_MIXER +EAS_EXPORT EAS_RESULT EAS_RenderAuxMixerWaveOut (EAS_DATA_HANDLE easHandle, EAS_PCM *pAudioBuffer, EAS_I32 *pNumGenerated) +{ + // Get the mutex + pthread_mutex_lock(&mtx); + + // Check if our buffer is full + while(pBuf->ix == MAX_BUFFERS - 1) + pthread_cond_wait(&cond, &mtx); + + EAS_RESULT result = EAS_RenderAuxMixer(easHandle, pAudioBuffer, pNumGenerated); + addData( pAudioBuffer ); + + // Release the mutex + pthread_mutex_unlock(&mtx); + + return result; +} +#endif + +EAS_EXPORT EAS_RESULT OpenWaveOutDevice(EAS_INT devNum, EAS_INT sampleRate, EAS_INT maxBufSize) +{ + // Open the default output unit + ComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + Component comp = FindNextComponent(NULL, &desc); + if (comp == NULL) + { + printf ("Could find the default output unit!!!\n"); + return EAS_FAILURE; + } + + OSStatus err = OpenAComponent(comp, &OutputUnit); + if (comp == NULL) + { + printf ("OpenAComponent=%ld\n", err); + return EAS_FAILURE; + } + + // Set up a callback function to generate output to the output unit + AURenderCallbackStruct auRenderCallback; + auRenderCallback.inputProc = RenderProc; + auRenderCallback.inputProcRefCon = NULL; + + err = AudioUnitSetProperty (OutputUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &auRenderCallback, + sizeof(auRenderCallback)); + if (err) + { + printf ("AudioUnitSetProperty-CB=%ld\n", err); + return EAS_FAILURE;; + } + + pConfig = EAS_Config(); + + // The synth engine already uses short* for the buffers so let CoreAudio do any conversions if needed + if (sampleRate != 0) + streamFormat.mSampleRate = sampleRate; + else + streamFormat.mSampleRate = pConfig->sampleRate; + + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger + | kAudioFormatFlagsNativeEndian + | kLinearPCMFormatFlagIsPacked + | kAudioFormatFlagIsNonInterleaved; + + streamFormat.mBytesPerPacket = 2; + streamFormat.mFramesPerPacket = 1; + streamFormat.mBytesPerFrame = 2; + streamFormat.mChannelsPerFrame = 2; + streamFormat.mBitsPerChannel = 16; + + err = AudioUnitSetProperty (OutputUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &streamFormat, + sizeof(AudioStreamBasicDescription)); + if (err) + { + printf ("AudioUnitSetProperty-SF= %4.4s, %ld\n", (char*)&err, err); + return EAS_FAILURE; + } + + // Initialize + err = AudioUnitInitialize(OutputUnit); + if (err) + { + printf ("AudioUnitInitialize = %ld\n", err); + return EAS_FAILURE; + } + + pBuf = (S_BUFFER_INFO *) malloc(sizeof(S_BUFFER_INFO)); + if( !pBuf ) + return EAS_FAILURE; + + pBuf->uOutBufferLength = pConfig->mixBufferSize * streamFormat.mBitsPerChannel / 2; + UInt32 uDataSize = sizeof(pBuf->uOutBufferLength); + + err = AudioUnitSetProperty(OutputUnit, kAudioDevicePropertyBufferSize, kAudioUnitScope_Output, 0, &pBuf->uOutBufferLength, uDataSize); + if (err) + { + printf ("AudioUnitSetProperty = %ld\n", err); + return EAS_FAILURE; + } + + err = AudioUnitGetProperty(OutputUnit, kAudioDevicePropertyBufferSize, kAudioUnitScope_Output, 0, &pBuf->uOutBufferLength, &uDataSize); + if (err) + { + printf ("AudioUnitGetProperty = %ld\n", err); + return EAS_FAILURE; + } + + pBuf->uLength = pBuf->uOutBufferLength; + int i; + for ( i = 0; i < MAX_BUFFERS; i++) + pBuf->pData[i] = malloc(pBuf->uLength); + + pBuf->uOutBufferLength /= pConfig->numChannels; + pBuf->uOutFrames = pBuf->uOutBufferLength / sizeof(short); + + pBuf->ix = 0; + + // Init the stop flag + bStopped = true; + + int result = pthread_mutex_init(&mtx, NULL); + if (result) + { + printf("pthread_mutex_init failed\n"); + return EAS_FAILURE; + } + + result = pthread_cond_init(&cond, NULL); + if (result) + { + printf("pthread_cond_init failed\n"); + return EAS_FAILURE; + } + + // Done + return EAS_SUCCESS; +} + + +EAS_EXPORT EAS_RESULT StartStream() +{ + OSStatus err = noErr; + pthread_mutex_lock(&mtx); + if ( bStopped == true ) + { + err = AudioOutputUnitStart (OutputUnit); + if (err) + { + printf ("AudioOutputUnitStart=%ld\n", err); + return EAS_FAILURE; + } + bStopped = false; + } + + return EAS_SUCCESS; +} + + +EAS_EXPORT EAS_RESULT CloseWaveOutDevice() +{ + OSStatus err; + + pthread_mutex_lock(&mtx); + if( false == bStopped ) + { + AudioOutputUnitStop (OutputUnit); + bStopped = true; + + err = AudioUnitUninitialize (OutputUnit); + if (err) + { + printf ("AudioUnitUninitialize=%ld\n", err); + return EAS_FAILURE; + } + + CloseComponent (OutputUnit); + int i = 0; + for(i; i < MAX_BUFFERS; i++) + free(pBuf->pData[i]); + + free(pBuf); + } + + pthread_mutex_unlock(&mtx); + return EAS_SUCCESS; +} + + +#if defined(_DEBUG) && !defined(MSC) +#include +/*---------------------------------------------------------------------------- + * EnableHeapDebug() + *---------------------------------------------------------------------------- +*/ +static void EnableHeapDebug (void) +{ + int temp; + temp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + temp |= _CRTDBG_ALLOC_MEM_DF; + temp |= _CRTDBG_CHECK_ALWAYS_DF; + temp |= _CRTDBG_LEAK_CHECK_DF; +// temp |= _CRTDBG_DELAY_FREE_MEM_DF; + _CrtSetDbgFlag(temp); +} + +/*---------------------------------------------------------------------------- + * HeapCheck() + *---------------------------------------------------------------------------- + * Check heap status + *---------------------------------------------------------------------------- +*/ +void HeapCheck (void) +{ + int heapStatus; + + /* Check heap status */ + heapStatus = _heapchk(); + if ((heapStatus == _HEAPOK) || (heapStatus == _HEAPEMPTY)) + return; + + EAS_ReportX(_EAS_SEVERITY_FATAL, "Heap corrupt\n" ); +} +#endif + + +/*---------------------------------------------------------------------------- + * EAS_HWInit + * + * Initialize host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData) +{ + +#if defined(_DEBUG) && !defined(MSC) + EnableHeapDebug(); +#endif + + #ifdef BUFFERED_FILE_ACCESS + EAS_ReportX(_EAS_SEVERITY_INFO, "EAS_HWInit: Buffered file access\n"); + #else + EAS_ReportX(_EAS_SEVERITY_INFO, "EAS_HWInit: Memory mapped file access\n"); + #endif + + /* simulate failure */ + if (errorConditions[eInitError]) + return EAS_FAILURE; + + /* need to track file opens for duplicate handles */ + *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA)); + if (!(*pHWInstData)) + return EAS_ERROR_MALLOC_FAILED; + + EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA)); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_HWShutdown + * + * Shut down host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData) +{ + + /* simulate failure */ + if (errorConditions[eShutdownError]) + return EAS_FAILURE; + + free(hwInstData); + +#if defined(_DEBUG) && !defined(MSC) + HeapCheck(); +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMalloc + * + * Allocates dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size) +{ + /* simulate failure */ + if (errorConditions[eMallocError]) + return NULL; + + return malloc((size_t) size); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFree + * + * Frees dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p) +{ + free(p); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCpy + * + * Copy memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount) +{ + return memcpy(dest, src, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemSet + * + * Set memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount) +{ + return memset(dest, val, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCmp + * + * Compare memory wrapper + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount) +{ + return (EAS_I32) memcmp(s1, s2, (size_t) amount); +} + +#ifdef BUFFERED_FILE_ACCESS +/*---------------------------------------------------------------------------- + * + * EAS_HWOpenFile + * + * Open a file for read or write + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) +{ + EAS_HW_FILE *file; + int i; + + /* set return value to NULL */ + *pFile = NULL; + + /* only support read mode at this time */ + if (mode != EAS_FILE_READ) + return EAS_ERROR_INVALID_FILE_MODE; + + /* find an empty entry in the file table */ + file = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (file->pFile == NULL) + { + EAS_RESULT result; + + /* open the file */ + file->pFile = fopen((const char*) locator, "rb"); + if (file->pFile == NULL) + return EAS_ERROR_FILE_OPEN_FAILED; + + /* get file length */ + if ((result = EAS_HWFileLength(hwInstData, file, &file->fileSize)) != EAS_SUCCESS) + { + EAS_HWCloseFile(hwInstData, file); + return result; + } + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWOpenFile: Open file %d\n", i); +#endif + + /* initialize some values */ + file->bytesInBuffer = 0; + file->readIndex = 0; + file->filePos = 0; + file->dup = EAS_FALSE; + + *pFile = file; + return EAS_SUCCESS; + } + file++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFillBuffer + * + * Fill buffer from file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFillBuffer (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file) +{ + /* reposition the file pointer */ + if (fseek(file->pFile, file->filePos, SEEK_SET) != 0) + return EAS_ERROR_FILE_SEEK; + + /* read some data from the file */ + file->bytesInBuffer = (EAS_I32) fread(file->buffer, 1, EAS_FILE_BUFFER_SIZE, file->pFile); + file->readIndex = 0; + if (file->bytesInBuffer == 0) + return EAS_EOF; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWReadFile + * + * Read data from a file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_U8 *p = pBuffer; + EAS_I32 bytesLeft = n; + + *pBytesRead = 0; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWReadFile: Reading %d bytes from position %d\n", n, file->filePos); +#endif + + /* try to fulfill request from buffer */ + for (;bytesLeft > 0;) + { + /* how many bytes can we get from buffer? */ + temp = file->bytesInBuffer - file->readIndex; + if (temp > bytesLeft) + temp = bytesLeft; + + /* copy data from buffer */ + EAS_HWMemCpy(p, &file->buffer[file->readIndex], temp); + *pBytesRead += temp; + file->readIndex += temp; + file->filePos += temp; + p += temp; + bytesLeft -= temp; + + /* don't refill buffer if request is bigger than buffer */ + if ((bytesLeft == 0) || (bytesLeft >= EAS_FILE_BUFFER_SIZE)) + break; + + /* refill buffer */ + if ((result = EAS_HWFillBuffer(hwInstData, file)) != EAS_SUCCESS) + return result; + } + + /* more to read? do unbuffered read directly to target memory */ + if (bytesLeft) + { + + /* position the file pointer */ + if (fseek(file->pFile, file->filePos, SEEK_SET) != 0) + return EAS_ERROR_FILE_SEEK; + + /* read data in the buffer */ + temp = (EAS_I32) fread(p, 1, (size_t) bytesLeft, file->pFile); + *pBytesRead += temp; + file->filePos += temp; + + /* reset buffer info */ + file->bytesInBuffer = 0; + file->readIndex = 0; + } + +#ifdef DEBUG_FILE_IO + { +#define BYTES_PER_LINE 16 + char str[BYTES_PER_LINE * 3 + 1]; + EAS_INT i; + for (i = 0; i < (n > BYTES_PER_LINE ? BYTES_PER_LINE : n) ; i ++) + sprintf(&str[i*3], "%02x ", ((EAS_U8*)pBuffer)[i]); + if (i) + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "%s\n", str); + } +#endif + + /* were n bytes read? */ + if (*pBytesRead != n) + return EAS_EOF; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetByte + * + * Read a byte from a file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) +{ + EAS_RESULT result; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* use local buffer - do we have any data? */ + if (file->readIndex >= file->bytesInBuffer) + { + if ((result = EAS_HWFillBuffer(hwInstData, file)) != EAS_SUCCESS) + return result; + + /* if nothing to read, return EOF */ + if (file->bytesInBuffer == 0) + return EAS_EOF; + } + + /* get a character from the buffer */ + *((EAS_U8*) p) = file->buffer[file->readIndex++]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetByte: Reading from position %d, byte = 0x%02x\n", file->filePos, *(EAS_U8*)p); +#endif + + file->filePos++; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetWord + * + * Read a 16-bit value from the file + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_I32 count; + EAS_U8 c[2]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetWord: Reading 2 bytes from position %d\n", file->filePos); +#endif + + /* read 2 bytes from the file */ + if ((result = EAS_HWReadFile(hwInstData, file, c, 2, &count)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U16*) p) = ((EAS_U16) c[0] << 8) | c[1]; + else + *((EAS_U16*) p) = ((EAS_U16) c[1] << 8) | c[0]; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetDWord + * + * Read a 16-bit value from the file + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_I32 count; + EAS_U8 c[4]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetDWord: Reading 4 bytes from position %d\n", file->filePos); +#endif + + /* read 4 bytes from the file */ + if ((result = EAS_HWReadFile(hwInstData, file, c, 4, &count)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U32*) p) = ((EAS_U32) c[0] << 24) | ((EAS_U32) c[1] << 16) | ((EAS_U32) c[2] << 8) | c[3]; + else + *((EAS_U32*) p) = ((EAS_U32) c[3] << 24) | ((EAS_U32) c[2] << 16) | ((EAS_U32) c[1] << 8) | c[0]; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFilePos + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) +{ + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pPosition = file->filePos; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeek + * + * Seek to a specific location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + EAS_I32 newIndex; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for seek past end */ + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWFileSeek: Seeking to new position %d\n", file->filePos); +#endif + + /* is new position in current buffer? */ + newIndex = position - file->filePos + file->readIndex; + if ((newIndex >= 0) && (newIndex < file->bytesInBuffer)) + { + file->readIndex = newIndex; + file->filePos = position; + return EAS_SUCCESS; + } + + /* save new position and reset buffer info so EAS_HWGetByte doesn't fail */ + file->filePos = position; + file->bytesInBuffer = 0; + file->readIndex = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeekOfs + * + * Seek forward or back relative to the current position + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + EAS_I32 temp; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWFileSeekOfs: Seeking to new position %d\n", file->filePos + position); +#endif + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for seek past end */ + temp = file->filePos + position; + if ((temp < 0) || (temp > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* is new position in current buffer? */ + temp = position + file->readIndex; + if ((temp >= 0) && (temp < file->bytesInBuffer)) + { + file->readIndex = temp; + file->filePos += position; + return EAS_SUCCESS; + } + + /* save new position and reset buffer info so EAS_HWGetByte doesn't fail */ + file->filePos += position; + file->bytesInBuffer = 0; + file->readIndex = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileLength + * + * Return the file length + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) +{ + long pos; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + if ((pos = ftell(file->pFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(file->pFile, 0L, SEEK_END) != 0) + return EAS_ERROR_FILE_LENGTH; + if ((*pLength = ftell(file->pFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(file->pFile, pos, SEEK_SET) != 0) + return EAS_ERROR_FILE_LENGTH; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWDupHandle + * + * Duplicate a file handle + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pDupFile) +{ + EAS_HW_FILE *dupfile; + int i; + + /* check handle integrity */ + *pDupFile = NULL; + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* find an empty entry in the file table */ + dupfile = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (dupfile->pFile == NULL) + { + + /* copy info from the handle to be duplicated */ + dupfile->filePos = file->filePos; + dupfile->pFile = file->pFile; + dupfile->fileSize = file->fileSize; + + /* set the duplicate handle flag */ + dupfile->dup = file->dup = EAS_TRUE; + + /* initialize some values */ + dupfile->bytesInBuffer = 0; + dupfile->readIndex = 0; + + *pDupFile = dupfile; + return EAS_SUCCESS; + } + dupfile++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWClose + * + * Wrapper for fclose function + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) +{ + EAS_HW_FILE *file2,*dupFile; + int i; + + /* check handle integrity */ + if (file1->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for duplicate handle */ + if (file1->dup) + { + dupFile = NULL; + file2 = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* check for duplicate */ + if ((file1 != file2) && (file2->pFile == file1->pFile)) + { + /* is there more than one duplicate? */ + if (dupFile != NULL) + { + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; + } + + /* this is the first duplicate found */ + dupFile = file2; + } + file2++; + } + + /* there is only one duplicate, clear the dup flag */ + if (dupFile) + dupFile->dup = EAS_FALSE; + else + /* if we get here, there's a serious problem */ + return EAS_ERROR_HANDLE_INTEGRITY; + + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; + } + + /* no duplicates - close the file */ + if (fclose(file1->pFile) != 0) + return EAS_ERROR_CLOSE_FAILED; + + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; +} +#else +/*---------------------------------------------------------------------------- + * + * EAS_HWOpenFile + * + * Open a file for read or write + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) +{ + EAS_HW_FILE *file; + FILE *ioFile; + int i, temp; + + /* set return value to NULL */ + *pFile = NULL; + + /* simulate failure */ + if (errorConditions[eOpenError]) + return EAS_FAILURE; + + /* only support read mode at this time */ + if (mode != EAS_FILE_READ) + return EAS_ERROR_INVALID_FILE_MODE; + + /* find an empty entry in the file table */ + file = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (file->buffer == NULL) + { + /* open the file */ + if ((ioFile = fopen(locator,"rb")) == NULL) + return EAS_ERROR_FILE_OPEN_FAILED; + + /* determine the file size */ + if (fseek(ioFile, 0L, SEEK_END) != 0) + return EAS_ERROR_FILE_LENGTH; + if ((file->fileSize = ftell(ioFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(ioFile, 0L, SEEK_SET) != 0) + return EAS_ERROR_FILE_LENGTH; + + /* allocate a buffer */ + file->buffer = EAS_HWMalloc(hwInstData, file->fileSize); + if (file->buffer == NULL) + { + fclose(ioFile); + return EAS_ERROR_MALLOC_FAILED; + } + + /* read the file into memory */ + temp = (int) fread(file->buffer, (size_t) file->fileSize, 1, ioFile); + + /* close the file - don't need it any more */ + fclose(ioFile); + + /* check for error reading file */ + if (temp != 1) + return EAS_ERROR_FILE_READ_FAILED; + + /* initialize some values */ + file->filePos = 0; + file->dup = EAS_FALSE; + + *pFile = file; + return EAS_SUCCESS; + } + file++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWReadFile + * + * Read data from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) +{ + EAS_I32 count; + + /* simulate failure */ + if (errorConditions[eReadError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* calculate the bytes to read */ + count = file->fileSize - file->filePos; + if (n < count) + count = n; + + /* copy the data to the requested location, and advance the pointer */ + if (count) + EAS_HWMemCpy(pBuffer, &file->buffer[file->filePos], count); + file->filePos += count; + *pBytesRead = count; + + /* were n bytes read? */ + if (count!= n) + return EAS_EOF; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetByte + * + * Read a byte from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{715} hwInstData available for customer use */ +EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) +{ + + /* simulate failure */ + if (errorConditions[eReadError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for end of file */ + if (file->filePos >= file->fileSize) + { + *((EAS_U8*) p) = 0; + return EAS_EOF; + } + + /* get a character from the buffer */ + *((EAS_U8*) p) = file->buffer[file->filePos++]; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2; + + /* read 2 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2; + else + *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetDWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2,c3,c4; + + /* read 4 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4; + else + *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFilePos + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) +{ + + /* simulate failure */ + if (errorConditions[ePosError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pPosition = file->filePos; + return EAS_SUCCESS; +} /* end EAS_HWFilePos */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeek + * + * Seek to a specific location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* simulate failure */ + if (errorConditions[eSeekError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* validate new position */ + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeekOfs + * + * Seek forward or back relative to the current position + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* simulate failure */ + if (errorConditions[eSeekError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* determine the file position */ + position += file->filePos; + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileLength + * + * Return the file length + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) +{ + + /* simulate failure */ + if (errorConditions[eLengthError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pLength = file->fileSize; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWDupHandle + * + * Duplicate a file handle + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile) +{ + EAS_HW_FILE *dupFile; + int i; + + /* simulate failure */ + if (errorConditions[eDupError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* find an empty entry in the file table */ + dupFile = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (dupFile->buffer == NULL) + { + + /* copy info from the handle to be duplicated */ + dupFile->filePos = file->filePos; + dupFile->fileSize = file->fileSize; + dupFile->buffer = file->buffer; + + /* set the duplicate handle flag */ + dupFile->dup = file->dup = EAS_TRUE; + + *pDupFile = dupFile; + return EAS_SUCCESS; + } + dupFile++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWClose + * + * Wrapper for fclose function + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) +{ + EAS_HW_FILE *file2,*dupFile; + int i; + + /* simulate failure */ + if (errorConditions[eCloseError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file1->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for duplicate handle */ + if (file1->dup) + { + dupFile = NULL; + file2 = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* check for duplicate */ + if ((file1 != file2) && (file2->buffer == file1->buffer)) + { + /* is there more than one duplicate? */ + if (dupFile != NULL) + { + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; + } + + /* this is the first duplicate found */ + else + dupFile = file2; + } + file2++; + } + + /* there is only one duplicate, clear the dup flag */ + if (dupFile) + dupFile->dup = EAS_FALSE; + else + /* if we get here, there's a serious problem */ + return EAS_ERROR_HANDLE_INTEGRITY; + + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; + } + + /* no duplicates -free the buffer */ + EAS_HWFree(hwInstData, file1->buffer); + + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * + * EAS_HWVibrate + * + * Turn on/off vibrate function + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + vibState = state; +// EAS_ReportX(_EAS_SEVERITY_NOFILTER, "Vibrate state: %d\n", state); + return EAS_SUCCESS; +} /* end EAS_HWVibrate */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWLED + * + * Turn on/off LED + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + ledState = state; +// EAS_ReportX(_EAS_SEVERITY_NOFILTER, "LED state: %d\n", state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWBackLight + * + * Turn on/off backlight + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + backlightState = state; +// EAS_ReportX(_EAS_SEVERITY_NOFILTER, "Backlight state: %d\n", state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWYield + * + * This function is called periodically by the EAS library to give the + * host an opportunity to allow other tasks to run. There are two ways to + * use this call: + * + * If you have a multi-tasking OS, you can call the yield function in the + * OS to allow other tasks to run. In this case, return EAS_FALSE to tell + * the EAS library to continue processing when control returns from this + * function. + * + * If tasks run in a single thread by sequential function calls (sometimes + * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to + * return to the caller. Be sure to check the number of bytes rendered + * before passing the audio buffer to the codec - it may not be filled. + * The next call to EAS_Render will continue processing until the buffer + * has been filled. + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData) +{ + /* put your code here */ + return EAS_FALSE; +} + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.h b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.h new file mode 100755 index 0000000..adaaa70 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLib.h @@ -0,0 +1,31 @@ +/* + * EASLib.h + * EASLIb + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "eas_types.h" + +extern EAS_RESULT EAS_LibInit (EAS_DATA_HANDLE *pHandle) +{ + return EAS_Init(pEASData); +} + +EAS_EXPORT EAS_LibShutdown (EAS_DATA_HANDLE handle) +{ + EAS_Shutdown(handle); +} diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLibVst.c b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLibVst.c new file mode 100755 index 0000000..5bfe774 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/EASLibVst.c @@ -0,0 +1,1504 @@ +/* + * EASLib.c + * EASLIb + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + */ + +#include +#include +#include +#include + +#include "eas.h" +#include "eas_report.h" +#include "eas_host.h" + +#ifdef JET_INTERFACE +#include "jet.h" +#endif + + +#define EAS_EXPORT __attribute__((visibility("default"))) + +// #define DEBUG_FILE_IO + +/* include debug interface */ +#include "eas_host_debug.h" + +#ifdef AUX_MIXER +#include "eas_auxmix.h" +#endif + +/* this module requires dynamic memory support */ +#ifdef _STATIC_MEMORY +#error "eas_hostmm.c requires the dynamic memory model!\n" +#endif + +#ifndef EAS_MAX_FILE_HANDLES +#define EAS_MAX_FILE_HANDLES 32 +#endif + +#ifndef EAS_FILE_BUFFER_SIZE +#define EAS_FILE_BUFFER_SIZE 32 +#endif + +/* + * this structure and the related function are here + * to support the ability to create duplicate handles + * and buffering it in memory. If your system uses + * in-memory resources, you can eliminate the calls + * to malloc and free, the dup flag, and simply track + * the file size and read position. + */ + #ifdef BUFFERED_FILE_ACCESS +typedef struct eas_hw_file_tag +{ + FILE *pFile; + EAS_I32 bytesInBuffer; + EAS_I32 readIndex; + EAS_I32 filePos; + EAS_I32 fileSize; + EAS_BOOL dup; + EAS_U8 buffer[EAS_FILE_BUFFER_SIZE]; +} EAS_HW_FILE; +#else +typedef struct eas_hw_file_tag +{ + EAS_I32 fileSize; + EAS_I32 filePos; + EAS_BOOL dup; + EAS_U8 *buffer; +} EAS_HW_FILE; +#endif + +typedef struct eas_hw_inst_data_tag +{ + EAS_HW_FILE files[EAS_MAX_FILE_HANDLES]; +} EAS_HW_INST_DATA; + +EAS_BOOL errorConditions[eNumErrorConditions]; +EAS_BOOL ledState; +EAS_BOOL vibState; +EAS_BOOL backlightState; + +#define MAX_DEBUG_MSG_LEN 1024 + +typedef void (*EAS_LOG_FUNC)(EAS_INT severity, char *msg); + +static EAS_LOG_FUNC logCallback = NULL; +static char messageBuffer[MAX_DEBUG_MSG_LEN]; + +/* error counts */ +static EAS_INT eas_fatalErrors; +static EAS_INT eas_errors; +static EAS_INT eas_warnings; +static int severityLevel = 9999; + +/* wave out device */ +#ifndef MAX_WAVE_OUT_BUFFERS +#define MAX_WAVE_OUT_BUFFERS 8 +#endif + +#ifndef EAS_BUFFERS_PER_WAVE_BUFFER +#define EAS_BUFFERS_PER_WAVE_BUFFER 8 +#endif + +/*---------------------------------------------------------------------------- + * ResetErrorCounters() + *---------------------------------------------------------------------------- +*/ +EAS_EXPORT void ResetErrorCounters() +{ + eas_fatalErrors = 0; + eas_errors = 0; + eas_warnings = 0; +} + +/*---------------------------------------------------------------------------- + * SetLogCallback() + *---------------------------------------------------------------------------- +*/ +EAS_EXPORT void SetLogCallback (EAS_LOG_FUNC callback) +{ + logCallback = callback; +} + +#ifndef _NO_DEBUG_PREPROCESSOR +static S_DEBUG_MESSAGES debugMessages[] = +{ +#ifdef UNIFIED_DEBUG_MESSAGES +#include "eas_debugmsgs.h" +#endif + { 0,0,0 } +}; + +/*---------------------------------------------------------------------------- + * EAS_ReportEx() + *---------------------------------------------------------------------------- +*/ +void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...) +{ + va_list vargs; + int i; + + switch (severity) + { + case _EAS_SEVERITY_FATAL: + eas_fatalErrors++; + break; + + case _EAS_SEVERITY_ERROR: + eas_errors++; + break; + + case _EAS_SEVERITY_WARNING: + eas_warnings++; + break; + + default: + break; + } + + /* check severity level */ + if (severity > severityLevel) + return; + + /* check for callback */ + if (logCallback == NULL) + return; + + /* find the error message and output to stdout */ + for (i = 0; debugMessages[i].m_pDebugMsg; i++) + { + if ((debugMessages[i].m_nHashCode == hashCode) && + (debugMessages[i].m_nSerialNum == serialNum)) + { + va_start(vargs, serialNum); +#ifdef WIN32 + vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs); +#else + vsprintf(messageBuffer, debugMessages[i].m_pDebugMsg, vargs); +#endif + logCallback(severity, messageBuffer); + va_end(vargs); + return; + } + } + printf("Unrecognized error: Severity=%d; HashCode=%lu; SerialNum=%d\n", severity, hashCode, serialNum); +} /* end EAS_ReportEx */ + +#else +/*---------------------------------------------------------------------------- + * EAS_Report() + *---------------------------------------------------------------------------- +*/ +void EAS_Report (int severity, const char *fmt, ...) +{ + va_list vargs; + + switch (severity) + { + case _EAS_SEVERITY_FATAL: + eas_fatalErrors++; + break; + + case _EAS_SEVERITY_ERROR: + eas_errors++; + break; + + case _EAS_SEVERITY_WARNING: + eas_warnings++; + break; + + default: + break; + } + + /* check severity level */ + if (severity > severityLevel) + return; + + /* check for callback */ + if (logCallback == NULL) + return; + + va_start(vargs, fmt); +#ifdef _WIN32 + vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs); +#else + vsprintf(messageBuffer, fmt, vargs); +#endif + logCallback(severity, messageBuffer); + va_end(vargs); +} /* end EAS_Report */ + +/*---------------------------------------------------------------------------- + * EAS_ReportX() + *---------------------------------------------------------------------------- +*/ +void EAS_ReportX (int severity, const char *fmt, ...) +{ + va_list vargs; + + switch (severity) + { + case _EAS_SEVERITY_FATAL: + eas_fatalErrors++; + break; + + case _EAS_SEVERITY_ERROR: + eas_errors++; + break; + + case _EAS_SEVERITY_WARNING: + eas_warnings++; + break; + + default: + break; + } + + /* check severity level */ + if (severity > severityLevel) + return; + + /* check for callback */ + if (logCallback == NULL) + return; + + va_start(vargs, fmt); +#ifdef _WIN32 + vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs); +#else + vsprintf(messageBuffer, fmt, vargs); +#endif + logCallback(severity, messageBuffer); + va_end(vargs); +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_DLLSetDebugLevel() + *---------------------------------------------------------------------------- +*/ +EAS_EXPORT void EAS_DLLSetDebugLevel (int severity) +{ + severityLevel = severity; +} + +/*---------------------------------------------------------------------------- + * EAS_ExSetDebugLevel() + *---------------------------------------------------------------------------- +*/ +void EAS_SetDebugLevel (int severity) +{ + severityLevel = severity; +} + +/*---------------------------------------------------------------------------- + * EAS_SelectLibrary() + *---------------------------------------------------------------------------- +*/ +EAS_EXPORT EAS_RESULT EAS_SelectLib (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_BOOL testLib) +{ + extern EAS_SNDLIB_HANDLE VMGetLibHandle(EAS_INT libNum); + return EAS_SetSoundLibrary(pEASData, streamHandle, VMGetLibHandle(testLib ? 1 : 0)); +} + + +#if defined(_DEBUG) && !defined(MSC) +#include +/*---------------------------------------------------------------------------- + * EnableHeapDebug() + *---------------------------------------------------------------------------- +*/ +static void EnableHeapDebug (void) +{ + int temp; + temp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + temp |= _CRTDBG_ALLOC_MEM_DF; + temp |= _CRTDBG_CHECK_ALWAYS_DF; + temp |= _CRTDBG_LEAK_CHECK_DF; +// temp |= _CRTDBG_DELAY_FREE_MEM_DF; + _CrtSetDbgFlag(temp); +} + +/*---------------------------------------------------------------------------- + * HeapCheck() + *---------------------------------------------------------------------------- + * Check heap status + *---------------------------------------------------------------------------- +*/ +void HeapCheck (void) +{ + int heapStatus; + + /* Check heap status */ + heapStatus = _heapchk(); + if ((heapStatus == _HEAPOK) || (heapStatus == _HEAPEMPTY)) + return; + + EAS_ReportX(_EAS_SEVERITY_FATAL, "Heap corrupt\n" ); +} +#endif + + +/*---------------------------------------------------------------------------- + * EAS_HWInit + * + * Initialize host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData) +{ + +#if defined(_DEBUG) && !defined(MSC) + EnableHeapDebug(); +#endif + + #ifdef BUFFERED_FILE_ACCESS + EAS_ReportX(_EAS_SEVERITY_INFO, "EAS_HWInit: Buffered file access\n"); + #else + EAS_ReportX(_EAS_SEVERITY_INFO, "EAS_HWInit: Memory mapped file access\n"); + #endif + + /* simulate failure */ + if (errorConditions[eInitError]) + return EAS_FAILURE; + + /* need to track file opens for duplicate handles */ + *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA)); + if (!(*pHWInstData)) + return EAS_ERROR_MALLOC_FAILED; + + EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA)); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_HWShutdown + * + * Shut down host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData) +{ + + /* simulate failure */ + if (errorConditions[eShutdownError]) + return EAS_FAILURE; + + free(hwInstData); + +#if defined(_DEBUG) && !defined(MSC) + HeapCheck(); +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMalloc + * + * Allocates dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size) +{ + /* simulate failure */ + if (errorConditions[eMallocError]) + return NULL; + + return malloc((size_t) size); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFree + * + * Frees dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p) +{ + free(p); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCpy + * + * Copy memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount) +{ + return memcpy(dest, src, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemSet + * + * Set memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount) +{ + return memset(dest, val, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCmp + * + * Compare memory wrapper + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount) +{ + return (EAS_I32) memcmp(s1, s2, (size_t) amount); +} + +#ifdef BUFFERED_FILE_ACCESS +/*---------------------------------------------------------------------------- + * + * EAS_HWOpenFile + * + * Open a file for read or write + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) +{ + EAS_HW_FILE *file; + int i; + + /* set return value to NULL */ + *pFile = NULL; + + /* only support read mode at this time */ + if (mode != EAS_FILE_READ) + return EAS_ERROR_INVALID_FILE_MODE; + + /* find an empty entry in the file table */ + file = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (file->pFile == NULL) + { + EAS_RESULT result; + + /* open the file */ + file->pFile = fopen((const char*) locator, "rb"); + if (file->pFile == NULL) + return EAS_ERROR_FILE_OPEN_FAILED; + + /* get file length */ + if ((result = EAS_HWFileLength(hwInstData, file, &file->fileSize)) != EAS_SUCCESS) + { + EAS_HWCloseFile(hwInstData, file); + return result; + } + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWOpenFile: Open file %d\n", i); +#endif + + /* initialize some values */ + file->bytesInBuffer = 0; + file->readIndex = 0; + file->filePos = 0; + file->dup = EAS_FALSE; + + *pFile = file; + return EAS_SUCCESS; + } + file++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFillBuffer + * + * Fill buffer from file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFillBuffer (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file) +{ + /* reposition the file pointer */ + if (fseek(file->pFile, file->filePos, SEEK_SET) != 0) + return EAS_ERROR_FILE_SEEK; + + /* read some data from the file */ + file->bytesInBuffer = (EAS_I32) fread(file->buffer, 1, EAS_FILE_BUFFER_SIZE, file->pFile); + file->readIndex = 0; + if (file->bytesInBuffer == 0) + return EAS_EOF; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWReadFile + * + * Read data from a file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_U8 *p = pBuffer; + EAS_I32 bytesLeft = n; + + *pBytesRead = 0; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWReadFile: Reading %d bytes from position %d\n", n, file->filePos); +#endif + + /* try to fulfill request from buffer */ + for (;bytesLeft > 0;) + { + /* how many bytes can we get from buffer? */ + temp = file->bytesInBuffer - file->readIndex; + if (temp > bytesLeft) + temp = bytesLeft; + + /* copy data from buffer */ + EAS_HWMemCpy(p, &file->buffer[file->readIndex], temp); + *pBytesRead += temp; + file->readIndex += temp; + file->filePos += temp; + p += temp; + bytesLeft -= temp; + + /* don't refill buffer if request is bigger than buffer */ + if ((bytesLeft == 0) || (bytesLeft >= EAS_FILE_BUFFER_SIZE)) + break; + + /* refill buffer */ + if ((result = EAS_HWFillBuffer(hwInstData, file)) != EAS_SUCCESS) + return result; + } + + /* more to read? do unbuffered read directly to target memory */ + if (bytesLeft) + { + + /* position the file pointer */ + if (fseek(file->pFile, file->filePos, SEEK_SET) != 0) + return EAS_ERROR_FILE_SEEK; + + /* read data in the buffer */ + temp = (EAS_I32) fread(p, 1, (size_t) bytesLeft, file->pFile); + *pBytesRead += temp; + file->filePos += temp; + + /* reset buffer info */ + file->bytesInBuffer = 0; + file->readIndex = 0; + } + +#ifdef DEBUG_FILE_IO + { +#define BYTES_PER_LINE 16 + char str[BYTES_PER_LINE * 3 + 1]; + EAS_INT i; + for (i = 0; i < (n > BYTES_PER_LINE ? BYTES_PER_LINE : n) ; i ++) + sprintf(&str[i*3], "%02x ", ((EAS_U8*)pBuffer)[i]); + if (i) + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "%s\n", str); + } +#endif + + /* were n bytes read? */ + if (*pBytesRead != n) + return EAS_EOF; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetByte + * + * Read a byte from a file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) +{ + EAS_RESULT result; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* use local buffer - do we have any data? */ + if (file->readIndex >= file->bytesInBuffer) + { + if ((result = EAS_HWFillBuffer(hwInstData, file)) != EAS_SUCCESS) + return result; + + /* if nothing to read, return EOF */ + if (file->bytesInBuffer == 0) + return EAS_EOF; + } + + /* get a character from the buffer */ + *((EAS_U8*) p) = file->buffer[file->readIndex++]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetByte: Reading from position %d, byte = 0x%02x\n", file->filePos, *(EAS_U8*)p); +#endif + + file->filePos++; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetWord + * + * Read a 16-bit value from the file + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_I32 count; + EAS_U8 c[2]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetWord: Reading 2 bytes from position %d\n", file->filePos); +#endif + + /* read 2 bytes from the file */ + if ((result = EAS_HWReadFile(hwInstData, file, c, 2, &count)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U16*) p) = ((EAS_U16) c[0] << 8) | c[1]; + else + *((EAS_U16*) p) = ((EAS_U16) c[1] << 8) | c[0]; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetDWord + * + * Read a 16-bit value from the file + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_I32 count; + EAS_U8 c[4]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetDWord: Reading 4 bytes from position %d\n", file->filePos); +#endif + + /* read 4 bytes from the file */ + if ((result = EAS_HWReadFile(hwInstData, file, c, 4, &count)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U32*) p) = ((EAS_U32) c[0] << 24) | ((EAS_U32) c[1] << 16) | ((EAS_U32) c[2] << 8) | c[3]; + else + *((EAS_U32*) p) = ((EAS_U32) c[3] << 24) | ((EAS_U32) c[2] << 16) | ((EAS_U32) c[1] << 8) | c[0]; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFilePos + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) +{ + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pPosition = file->filePos; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeek + * + * Seek to a specific location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + EAS_I32 newIndex; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for seek past end */ + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWFileSeek: Seeking to new position %d\n", file->filePos); +#endif + + /* is new position in current buffer? */ + newIndex = position - file->filePos + file->readIndex; + if ((newIndex >= 0) && (newIndex < file->bytesInBuffer)) + { + file->readIndex = newIndex; + file->filePos = position; + return EAS_SUCCESS; + } + + /* save new position and reset buffer info so EAS_HWGetByte doesn't fail */ + file->filePos = position; + file->bytesInBuffer = 0; + file->readIndex = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeekOfs + * + * Seek forward or back relative to the current position + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + EAS_I32 temp; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWFileSeekOfs: Seeking to new position %d\n", file->filePos + position); +#endif + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for seek past end */ + temp = file->filePos + position; + if ((temp < 0) || (temp > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* is new position in current buffer? */ + temp = position + file->readIndex; + if ((temp >= 0) && (temp < file->bytesInBuffer)) + { + file->readIndex = temp; + file->filePos += position; + return EAS_SUCCESS; + } + + /* save new position and reset buffer info so EAS_HWGetByte doesn't fail */ + file->filePos += position; + file->bytesInBuffer = 0; + file->readIndex = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileLength + * + * Return the file length + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) +{ + long pos; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + if ((pos = ftell(file->pFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(file->pFile, 0L, SEEK_END) != 0) + return EAS_ERROR_FILE_LENGTH; + if ((*pLength = ftell(file->pFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(file->pFile, pos, SEEK_SET) != 0) + return EAS_ERROR_FILE_LENGTH; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWDupHandle + * + * Duplicate a file handle + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pDupFile) +{ + EAS_HW_FILE *dupfile; + int i; + + /* check handle integrity */ + *pDupFile = NULL; + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* find an empty entry in the file table */ + dupfile = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (dupfile->pFile == NULL) + { + + /* copy info from the handle to be duplicated */ + dupfile->filePos = file->filePos; + dupfile->pFile = file->pFile; + dupfile->fileSize = file->fileSize; + + /* set the duplicate handle flag */ + dupfile->dup = file->dup = EAS_TRUE; + + /* initialize some values */ + dupfile->bytesInBuffer = 0; + dupfile->readIndex = 0; + + *pDupFile = dupfile; + return EAS_SUCCESS; + } + dupfile++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWClose + * + * Wrapper for fclose function + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) +{ + EAS_HW_FILE *file2,*dupFile; + int i; + + /* check handle integrity */ + if (file1->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for duplicate handle */ + if (file1->dup) + { + dupFile = NULL; + file2 = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* check for duplicate */ + if ((file1 != file2) && (file2->pFile == file1->pFile)) + { + /* is there more than one duplicate? */ + if (dupFile != NULL) + { + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; + } + + /* this is the first duplicate found */ + dupFile = file2; + } + file2++; + } + + /* there is only one duplicate, clear the dup flag */ + if (dupFile) + dupFile->dup = EAS_FALSE; + else + /* if we get here, there's a serious problem */ + return EAS_ERROR_HANDLE_INTEGRITY; + + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; + } + + /* no duplicates - close the file */ + if (fclose(file1->pFile) != 0) + return EAS_ERROR_CLOSE_FAILED; + + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; +} +#else +/*---------------------------------------------------------------------------- + * + * EAS_HWOpenFile + * + * Open a file for read or write + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) +{ + EAS_HW_FILE *file; + FILE *ioFile; + int i, temp; + + /* set return value to NULL */ + *pFile = NULL; + + /* simulate failure */ + if (errorConditions[eOpenError]) + return EAS_FAILURE; + + /* only support read mode at this time */ + if (mode != EAS_FILE_READ) + return EAS_ERROR_INVALID_FILE_MODE; + + /* find an empty entry in the file table */ + file = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (file->buffer == NULL) + { + /* open the file */ + if ((ioFile = fopen(locator,"rb")) == NULL) + return EAS_ERROR_FILE_OPEN_FAILED; + + /* determine the file size */ + if (fseek(ioFile, 0L, SEEK_END) != 0) + return EAS_ERROR_FILE_LENGTH; + if ((file->fileSize = ftell(ioFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(ioFile, 0L, SEEK_SET) != 0) + return EAS_ERROR_FILE_LENGTH; + + /* allocate a buffer */ + file->buffer = EAS_HWMalloc(hwInstData, file->fileSize); + if (file->buffer == NULL) + { + fclose(ioFile); + return EAS_ERROR_MALLOC_FAILED; + } + + /* read the file into memory */ + temp = (int) fread(file->buffer, (size_t) file->fileSize, 1, ioFile); + + /* close the file - don't need it any more */ + fclose(ioFile); + + /* check for error reading file */ + if (temp != 1) + return EAS_ERROR_FILE_READ_FAILED; + + /* initialize some values */ + file->filePos = 0; + file->dup = EAS_FALSE; + + *pFile = file; + return EAS_SUCCESS; + } + file++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWReadFile + * + * Read data from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) +{ + EAS_I32 count; + + /* simulate failure */ + if (errorConditions[eReadError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* calculate the bytes to read */ + count = file->fileSize - file->filePos; + if (n < count) + count = n; + + /* copy the data to the requested location, and advance the pointer */ + if (count) + EAS_HWMemCpy(pBuffer, &file->buffer[file->filePos], count); + file->filePos += count; + *pBytesRead = count; + + /* were n bytes read? */ + if (count!= n) + return EAS_EOF; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetByte + * + * Read a byte from a file + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{715} hwInstData available for customer use */ +EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) +{ + + /* simulate failure */ + if (errorConditions[eReadError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for end of file */ + if (file->filePos >= file->fileSize) + { + *((EAS_U8*) p) = 0; + return EAS_EOF; + } + + /* get a character from the buffer */ + *((EAS_U8*) p) = file->buffer[file->filePos++]; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2; + + /* read 2 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2; + else + *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetDWord + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_U8 c1, c2,c3,c4; + + /* read 4 bytes from the file */ + if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4; + else + *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFilePos + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) +{ + + /* simulate failure */ + if (errorConditions[ePosError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pPosition = file->filePos; + return EAS_SUCCESS; +} /* end EAS_HWFilePos */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeek + * + * Seek to a specific location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* simulate failure */ + if (errorConditions[eSeekError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* validate new position */ + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeekOfs + * + * Seek forward or back relative to the current position + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + + /* simulate failure */ + if (errorConditions[eSeekError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* determine the file position */ + position += file->filePos; + if ((position < 0) || (position > file->fileSize)) + return EAS_ERROR_FILE_SEEK; + + /* save new position */ + file->filePos = position; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileLength + * + * Return the file length + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) +{ + + /* simulate failure */ + if (errorConditions[eLengthError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pLength = file->fileSize; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWDupHandle + * + * Duplicate a file handle + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile) +{ + EAS_HW_FILE *dupFile; + int i; + + /* simulate failure */ + if (errorConditions[eDupError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* find an empty entry in the file table */ + dupFile = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (dupFile->buffer == NULL) + { + + /* copy info from the handle to be duplicated */ + dupFile->filePos = file->filePos; + dupFile->fileSize = file->fileSize; + dupFile->buffer = file->buffer; + + /* set the duplicate handle flag */ + dupFile->dup = file->dup = EAS_TRUE; + + *pDupFile = dupFile; + return EAS_SUCCESS; + } + dupFile++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWClose + * + * Wrapper for fclose function + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) +{ + EAS_HW_FILE *file2,*dupFile; + int i; + + /* simulate failure */ + if (errorConditions[eCloseError]) + return EAS_FAILURE; + + /* make sure we have a valid handle */ + if (file1->buffer == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for duplicate handle */ + if (file1->dup) + { + dupFile = NULL; + file2 = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* check for duplicate */ + if ((file1 != file2) && (file2->buffer == file1->buffer)) + { + /* is there more than one duplicate? */ + if (dupFile != NULL) + { + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; + } + + /* this is the first duplicate found */ + else + dupFile = file2; + } + file2++; + } + + /* there is only one duplicate, clear the dup flag */ + if (dupFile) + dupFile->dup = EAS_FALSE; + else + /* if we get here, there's a serious problem */ + return EAS_ERROR_HANDLE_INTEGRITY; + + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; + } + + /* no duplicates -free the buffer */ + EAS_HWFree(hwInstData, file1->buffer); + + /* clear this entry and return */ + file1->buffer = NULL; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * + * EAS_HWVibrate + * + * Turn on/off vibrate function + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + vibState = state; +// EAS_ReportX(_EAS_SEVERITY_NOFILTER, "Vibrate state: %d\n", state); + return EAS_SUCCESS; +} /* end EAS_HWVibrate */ + +/*---------------------------------------------------------------------------- + * + * EAS_HWLED + * + * Turn on/off LED + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + ledState = state; +// EAS_ReportX(_EAS_SEVERITY_NOFILTER, "LED state: %d\n", state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWBackLight + * + * Turn on/off backlight + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + backlightState = state; +// EAS_ReportX(_EAS_SEVERITY_NOFILTER, "Backlight state: %d\n", state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWYield + * + * This function is called periodically by the EAS library to give the + * host an opportunity to allow other tasks to run. There are two ways to + * use this call: + * + * If you have a multi-tasking OS, you can call the yield function in the + * OS to allow other tasks to run. In this case, return EAS_FALSE to tell + * the EAS library to continue processing when control returns from this + * function. + * + * If tasks run in a single thread by sequential function calls (sometimes + * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to + * return to the caller. Be sure to check the number of bytes rendered + * before passing the audio buffer to the codec - it may not be filled. + * The next call to EAS_Render will continue processing until the buffer + * has been filled. + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) available for customer use */ +EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData) +{ + /* put your code here */ + return EAS_FALSE; +} + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/README.txt b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/README.txt new file mode 100755 index 0000000..bcc6ef0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/README.txt @@ -0,0 +1,9 @@ +OS X JetCreator Library Build Instructions + +1/ Open easwt_vst_lib.xcodeproj and build + +2/ Open EASLIb.xcodeproj and build + +3/ Copy build/Release/libEASLIb.dylib to the JetCreator folder + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/eas_host_debug.h b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/eas_host_debug.h new file mode 100755 index 0000000..fb40923 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/eas_host_debug.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_host_debug.h + * + * Contents and purpose: + * This header defines the host wrapper functions for simulating + * error conditions. + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +// sentinel +#ifndef _EAS_HOST_DEBUG_H +#define _EAS_HOST_DEBUG_H + +#include "eas_types.h" + +typedef enum +{ + eInitError, + eShutdownError, + eMallocError, + eOpenError, + eReadError, + ePosError, + eSeekError, + eLengthError, + eDupError, + eCloseError, + eNumErrorConditions, +} E_ERROR_CONDITIONS; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/eastestv37.c b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/eastestv37.c new file mode 100755 index 0000000..f325c04 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/eastestv37.c @@ -0,0 +1,999 @@ +/*---------------------------------------------------------------------------- + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +#include "eas_sndlib.h" + +/*---------------------------------------------------------------------------- + * Articulations + *---------------------------------------------------------------------------- +*/ +const S_ARTICULATION testArticulations[] = +{ + { /* articulation 0 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 1 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 0, 19, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 2 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 34, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 3 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 86, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 4 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 172, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 5 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 345, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 6 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 517, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 7 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 689, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 8 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 861, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 9 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 1723, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 10 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 0, 191, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 11 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 0, 382, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 12 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 13 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 0, 1903, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 14 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 0, 3804, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 15 */ + { 1902, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 16 */ + { 380, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 17 */ + { 190, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 18 */ + { 38, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 19 */ + { 19, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 20 */ + { 10, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 21 */ + { 5, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 22 */ + { 32767, 17213, 0, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 23 */ + { 32767, 28809, 0, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 24 */ + { 32767, 30725, 0, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 25 */ + { 32767, 32349, 0, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 26 */ + { 32767, 32558, 0, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 27 */ + { 32767, 32663, 0, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 28 */ + { 32767, 32715, 0, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 29 */ + { 32767, 30725, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 30 */ + { 32767, 30725, 3566, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 31 */ + { 32767, 30725, 42, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 32 */ + { 32767, 30725, 5, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 33 */ + { 32767, 30725, 2, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 34 */ + { 32767, 0, 32767, 17213 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 35 */ + { 32767, 0, 32767, 28809 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 36 */ + { 32767, 0, 32767, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 37 */ + { 32767, 0, 32767, 32349 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 38 */ + { 32767, 0, 32767, 32558 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 39 */ + { 32767, 0, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 40 */ + { 32767, 0, 32767, 32715 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 41 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 190, 0, 0, 0, 1, 0, 0 + }, + { /* articulation 42 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 189, 0, 0, 0, 3, 0, 0 + }, + { /* articulation 43 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 190, 0, 0, 0, 4, 0, 0 + }, + { /* articulation 44 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 190, 0, 0, 0, 6, 0, 0 + }, + { /* articulation 45 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + -1200, 0, 190, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 46 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + -600, 0, 190, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 47 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + -100, 0, 190, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 48 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + -50, 0, 190, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 49 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 50, 0, 190, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 50 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 0, 190, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 51 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 600, 0, 190, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 52 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 1200, 0, 190, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 53 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, -1200, 0, 0, 0, 0, 0 + }, + { /* articulation 54 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, -600, 0, 0, 0, 0, 0 + }, + { /* articulation 55 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, -100, 0, 0, 0, 0, 0 + }, + { /* articulation 56 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, -50, 0, 0, 0, 0, 0 + }, + { /* articulation 57 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 50, 0, 0, 0, 0, 0 + }, + { /* articulation 58 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 100, 0, 0, 0, 0, 0 + }, + { /* articulation 59 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 600, 0, 0, 0, 0, 0 + }, + { /* articulation 60 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 1200, 0, 0, 0, 0, 0 + }, + { /* articulation 61 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 5535, 0, 0, 0 + }, + { /* articulation 62 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 7121, 0, 0, 0 + }, + { /* articulation 63 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 8321, 0, 0, 0 + }, + { /* articulation 64 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 9906, 0, 0, 0 + }, + { /* articulation 65 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 11106, 0, 0, 0 + }, + { /* articulation 66 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 9521, 0, 0, 0 + }, + { /* articulation 67 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 9521, 0, 8, 0 + }, + { /* articulation 68 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 9521, 0, 16, 0 + }, + { /* articulation 69 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 9521, 0, 24, 0 + }, + { /* articulation 70 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 9521, 0, 30, 0 + }, + { /* articulation 71 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 0, -6400, 9521, 0, 0, 0 + }, + { /* articulation 72 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 0, -3200, 9521, 0, 0, 0 + }, + { /* articulation 73 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 0, -1600, 9521, 0, 0, 0 + }, + { /* articulation 74 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 0, -800, 9521, 0, 0, 0 + }, + { /* articulation 75 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 0, 800, 7121, 0, 0, 0 + }, + { /* articulation 76 */ + { 190, 30725, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 0, 1600, 7121, 0, 0, 0 + }, + { /* articulation 77 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 0, 3200, 7121, 0, 0, 0 + }, + { /* articulation 78 */ + { 32767, 0, 32767, 0 }, + { 190, 190, 0, 0 }, + 0, 0, 951, 0, 6400, 7121, 0, 0, 0 + }, + { /* articulation 79 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 190, 0, 0, 11106, 0, 0, 0 + }, + { /* articulation 80 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 191, 0, 0, 11106, 0, 0, 0 + }, + { /* articulation 81 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 190, 0, 0, 7121, 0, 0, 0 + }, + { /* articulation 82 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -63 + }, + { /* articulation 83 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -50 + }, + { /* articulation 84 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 85 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -25 + }, + { /* articulation 86 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -12 + }, + { /* articulation 87 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 12 + }, + { /* articulation 88 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 89 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 37 + }, + { /* articulation 90 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 50 + }, + { /* articulation 91 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 92 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 9907, 0, 0, 0 + }, + { /* articulation 93 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 10574, 0, 0, 0 + }, + { /* articulation 94 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 11373, 0, 0, 0 + }, + { /* articulation 95 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 11376, 0, 0, 0 + }, + { /* articulation 96 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 100, 0, 949, 0, 0, 0, 0, 0, 0 + } +}; /*end Articulations */ + +/*---------------------------------------------------------------------------- + * Regions + *---------------------------------------------------------------------------- +*/ +const S_WT_REGION testRegions[] = +{ + { { 32769, 0, 127 }, -6000, 32767, 101, 301, 4, 0 }, /* region 0 */ + { { 1, 0, 60 }, -6000, 32767, 101, 301, 4, 2 }, /* region 1 */ + { { 1, 61, 61 }, -6000, 32767, 101, 301, 4, 3 }, /* region 2 */ + { { 1, 62, 62 }, -6000, 32767, 101, 301, 4, 4 }, /* region 3 */ + { { 1, 63, 63 }, -6000, 32767, 101, 301, 4, 5 }, /* region 4 */ + { { 1, 64, 64 }, -6000, 32767, 101, 301, 4, 6 }, /* region 5 */ + { { 1, 65, 65 }, -6000, 32767, 101, 301, 4, 7 }, /* region 6 */ + { { 1, 66, 66 }, -6000, 32767, 101, 301, 4, 8 }, /* region 7 */ + { { 32769, 67, 127 }, -6000, 32767, 101, 301, 4, 9 }, /* region 8 */ + { { 32769, 0, 127 }, -6005, 32767, 3, 171, 5, 0 }, /* region 9 */ + { { 32768, 0, 127 }, -6555, 32767, 0, 0, 2, 0 }, /* region 10 */ + { { 32770, 0, 127 }, -6000, 32767, 0, 0, 0, 0 }, /* region 11 */ + { { 1, 60, 60 }, -6000, 32767, 101, 301, 4, 0 }, /* region 12 */ + { { 1, 61, 61 }, -6100, 16422, 101, 151, 4, 0 }, /* region 13 */ + { { 1, 62, 62 }, -6200, 8231, 101, 151, 4, 0 }, /* region 14 */ + { { 1, 63, 63 }, -6300, 2067, 101, 151, 4, 0 }, /* region 15 */ + { { 1, 64, 64 }, -6400, 130, 101, 151, 4, 0 }, /* region 16 */ + { { 32769, 65, 65 }, -6500, 1, 101, 151, 4, 0 }, /* region 17 */ + { { 1, 60, 60 }, -6000, 32767, 101, 301, 4, 0 }, /* region 18 */ + { { 1, 61, 61 }, -6200, 32767, 101, 151, 4, 0 }, /* region 19 */ + { { 1, 62, 62 }, -6400, 32767, 101, 151, 4, 0 }, /* region 20 */ + { { 1, 63, 63 }, -6600, 32767, 101, 151, 4, 0 }, /* region 21 */ + { { 1, 64, 64 }, -6800, 32767, 101, 151, 4, 0 }, /* region 22 */ + { { 1, 65, 65 }, -7000, 32767, 101, 151, 4, 0 }, /* region 23 */ + { { 1, 66, 66 }, -7200, 32767, 101, 151, 4, 0 }, /* region 24 */ + { { 1, 67, 67 }, -7400, 32767, 101, 151, 4, 0 }, /* region 25 */ + { { 1, 68, 68 }, -7600, 32767, 101, 151, 4, 0 }, /* region 26 */ + { { 1, 69, 69 }, -7800, 32767, 101, 151, 4, 0 }, /* region 27 */ + { { 1, 70, 70 }, -8000, 32767, 101, 151, 4, 0 }, /* region 28 */ + { { 1, 71, 71 }, -8200, 32767, 101, 151, 4, 0 }, /* region 29 */ + { { 32769, 72, 72 }, -8400, 32767, 101, 151, 4, 0 }, /* region 30 */ + { { 1, 60, 60 }, -6000, 32767, 101, 301, 4, 0 }, /* region 31 */ + { { 1, 61, 61 }, -6099, 32767, 101, 151, 4, 0 }, /* region 32 */ + { { 1, 62, 62 }, -6190, 32767, 101, 151, 4, 0 }, /* region 33 */ + { { 1, 63, 63 }, -6250, 32767, 101, 151, 4, 0 }, /* region 34 */ + { { 1, 64, 64 }, -6300, 32767, 101, 151, 4, 0 }, /* region 35 */ + { { 1, 65, 65 }, -6500, 32767, 101, 151, 4, 0 }, /* region 36 */ + { { 1, 66, 66 }, -6601, 32767, 101, 151, 4, 0 }, /* region 37 */ + { { 1, 67, 67 }, -6710, 32767, 101, 151, 4, 0 }, /* region 38 */ + { { 1, 68, 68 }, -6850, 32767, 101, 151, 4, 0 }, /* region 39 */ + { { 32769, 69, 69 }, -7000, 32767, 101, 151, 4, 0 }, /* region 40 */ + { { 1, 0, 0 }, 0, 32767, 101, 151, 4, 1 }, /* region 41 */ + { { 1, 1, 1 }, -100, 32767, 101, 151, 4, 10 }, /* region 42 */ + { { 1, 2, 2 }, -200, 32767, 101, 151, 4, 11 }, /* region 43 */ + { { 1, 3, 3 }, -300, 32767, 101, 151, 4, 12 }, /* region 44 */ + { { 1, 4, 4 }, -400, 32767, 101, 151, 4, 13 }, /* region 45 */ + { { 1, 5, 5 }, -500, 32767, 101, 151, 4, 14 }, /* region 46 */ + { { 1, 6, 6 }, -600, 32767, 101, 151, 4, 0 }, /* region 47 */ + { { 1, 7, 7 }, -700, 32767, 101, 151, 4, 15 }, /* region 48 */ + { { 1, 8, 8 }, -800, 32767, 101, 151, 4, 16 }, /* region 49 */ + { { 1, 9, 9 }, -900, 32767, 101, 151, 4, 17 }, /* region 50 */ + { { 1, 10, 10 }, -1000, 32767, 101, 151, 4, 18 }, /* region 51 */ + { { 1, 11, 11 }, -1100, 32767, 101, 151, 4, 19 }, /* region 52 */ + { { 1, 12, 12 }, -1200, 32767, 101, 151, 4, 20 }, /* region 53 */ + { { 1, 13, 13 }, -1300, 32767, 101, 151, 4, 21 }, /* region 54 */ + { { 1, 14, 14 }, -1400, 32767, 101, 151, 4, 22 }, /* region 55 */ + { { 1, 15, 15 }, -1500, 32767, 101, 151, 4, 23 }, /* region 56 */ + { { 1, 16, 16 }, -1600, 32767, 101, 151, 4, 24 }, /* region 57 */ + { { 1, 17, 17 }, -1700, 32767, 101, 151, 4, 25 }, /* region 58 */ + { { 1, 18, 18 }, -1800, 32767, 101, 151, 4, 26 }, /* region 59 */ + { { 1, 19, 19 }, -1900, 32767, 101, 151, 4, 27 }, /* region 60 */ + { { 1, 20, 20 }, -2000, 32767, 101, 151, 4, 28 }, /* region 61 */ + { { 1, 21, 21 }, -2100, 32767, 101, 151, 4, 29 }, /* region 62 */ + { { 1, 22, 22 }, -2200, 32767, 101, 151, 4, 30 }, /* region 63 */ + { { 1, 23, 23 }, -2300, 32767, 101, 151, 4, 31 }, /* region 64 */ + { { 1, 24, 24 }, -2400, 32767, 101, 151, 4, 32 }, /* region 65 */ + { { 1, 25, 25 }, -2500, 32767, 101, 151, 4, 33 }, /* region 66 */ + { { 1, 26, 26 }, -2600, 32767, 101, 151, 4, 24 }, /* region 67 */ + { { 1, 27, 27 }, -2700, 32767, 101, 151, 4, 0 }, /* region 68 */ + { { 1, 28, 28 }, -2800, 32767, 101, 151, 4, 34 }, /* region 69 */ + { { 1, 29, 29 }, -2900, 32767, 101, 151, 4, 35 }, /* region 70 */ + { { 1, 30, 30 }, -3000, 32767, 101, 151, 4, 36 }, /* region 71 */ + { { 1, 31, 31 }, -3100, 32767, 101, 151, 4, 37 }, /* region 72 */ + { { 1, 32, 32 }, -3200, 32767, 101, 151, 4, 38 }, /* region 73 */ + { { 1, 33, 33 }, -3300, 32767, 101, 151, 4, 39 }, /* region 74 */ + { { 1, 34, 34 }, -3400, 32767, 101, 151, 4, 40 }, /* region 75 */ + { { 1, 35, 35 }, -3500, 32767, 101, 151, 4, 41 }, /* region 76 */ + { { 1, 36, 36 }, -3600, 32767, 101, 151, 4, 42 }, /* region 77 */ + { { 1, 37, 37 }, -3700, 32767, 101, 151, 4, 43 }, /* region 78 */ + { { 1, 38, 38 }, -3800, 32767, 101, 151, 4, 44 }, /* region 79 */ + { { 1, 39, 39 }, -3900, 32767, 101, 151, 4, 45 }, /* region 80 */ + { { 1, 40, 40 }, -4000, 32767, 101, 151, 4, 46 }, /* region 81 */ + { { 1, 41, 41 }, -4100, 32767, 101, 151, 4, 47 }, /* region 82 */ + { { 1, 42, 42 }, -4200, 32767, 101, 151, 4, 48 }, /* region 83 */ + { { 1, 43, 43 }, -4300, 32767, 101, 151, 4, 49 }, /* region 84 */ + { { 1, 44, 44 }, -4400, 32767, 101, 151, 4, 50 }, /* region 85 */ + { { 1, 45, 45 }, -4500, 32767, 101, 151, 4, 51 }, /* region 86 */ + { { 1, 46, 46 }, -4600, 32767, 101, 151, 4, 52 }, /* region 87 */ + { { 1, 47, 47 }, -4700, 32767, 101, 151, 4, 53 }, /* region 88 */ + { { 1, 48, 48 }, -4800, 32767, 101, 151, 4, 54 }, /* region 89 */ + { { 1, 49, 49 }, -4900, 32767, 101, 151, 4, 55 }, /* region 90 */ + { { 1, 50, 50 }, -5000, 32767, 101, 151, 4, 56 }, /* region 91 */ + { { 1, 51, 51 }, -5100, 32767, 101, 151, 4, 57 }, /* region 92 */ + { { 1, 52, 52 }, -5200, 32767, 101, 151, 4, 58 }, /* region 93 */ + { { 1, 53, 53 }, -5300, 32767, 101, 151, 4, 59 }, /* region 94 */ + { { 1, 54, 54 }, -5400, 32767, 101, 151, 4, 60 }, /* region 95 */ + { { 2, 55, 55 }, -5500, 32767, 0, 0, 0, 61 }, /* region 96 */ + { { 2, 56, 56 }, -5600, 32767, 0, 0, 0, 62 }, /* region 97 */ + { { 2, 57, 57 }, -5700, 32767, 0, 0, 0, 63 }, /* region 98 */ + { { 2, 58, 58 }, -5800, 32767, 0, 0, 0, 64 }, /* region 99 */ + { { 2, 59, 59 }, -5900, 32767, 0, 0, 0, 65 }, /* region 100 */ + { { 2, 60, 60 }, -6000, 32767, 0, 0, 0, 0 }, /* region 101 */ + { { 2, 61, 61 }, -6100, 32767, 0, 0, 0, 66 }, /* region 102 */ + { { 2, 62, 62 }, -6200, 32767, 0, 0, 0, 67 }, /* region 103 */ + { { 2, 63, 63 }, -6300, 32767, 0, 0, 0, 68 }, /* region 104 */ + { { 2, 64, 64 }, -6400, 32767, 0, 0, 0, 69 }, /* region 105 */ + { { 2, 65, 65 }, -6500, 32767, 0, 0, 0, 70 }, /* region 106 */ + { { 2, 66, 66 }, -6600, 32767, 0, 0, 0, 71 }, /* region 107 */ + { { 2, 67, 67 }, -6700, 32767, 0, 0, 0, 72 }, /* region 108 */ + { { 2, 68, 68 }, -6800, 32767, 0, 0, 0, 73 }, /* region 109 */ + { { 2, 69, 69 }, -6900, 32767, 0, 0, 0, 74 }, /* region 110 */ + { { 2, 70, 70 }, -7000, 32767, 0, 0, 0, 75 }, /* region 111 */ + { { 2, 71, 71 }, -7100, 32767, 0, 0, 0, 76 }, /* region 112 */ + { { 2, 72, 72 }, -7200, 32767, 0, 0, 0, 77 }, /* region 113 */ + { { 2, 73, 73 }, -7300, 32767, 0, 0, 0, 78 }, /* region 114 */ + { { 2, 74, 74 }, -7400, 32767, 0, 0, 0, 79 }, /* region 115 */ + { { 2, 75, 75 }, -7500, 32767, 0, 0, 0, 79 }, /* region 116 */ + { { 2, 76, 76 }, -7600, 32767, 0, 0, 0, 79 }, /* region 117 */ + { { 2, 77, 77 }, -7700, 32767, 0, 0, 0, 80 }, /* region 118 */ + { { 2, 78, 78 }, -7800, 32767, 0, 0, 0, 81 }, /* region 119 */ + { { 2, 79, 79 }, -7900, 32767, 0, 0, 0, 81 }, /* region 120 */ + { { 2, 80, 80 }, -8000, 32767, 0, 0, 0, 81 }, /* region 121 */ + { { 2, 81, 81 }, -8100, 32767, 0, 0, 0, 81 }, /* region 122 */ + { { 2, 82, 82 }, -8200, 32767, 0, 0, 0, 0 }, /* region 123 */ + { { 257, 83, 83 }, -8300, 32767, 101, 151, 4, 0 }, /* region 124 */ + { { 257, 84, 84 }, -8405, 32767, 0, 171, 5, 0 }, /* region 125 */ + { { 0, 85, 85 }, -9055, 32767, 0, 0, 2, 82 }, /* region 126 */ + { { 0, 86, 86 }, -9155, 32767, 0, 0, 2, 83 }, /* region 127 */ + { { 0, 87, 87 }, -9255, 32767, 0, 0, 2, 84 }, /* region 128 */ + { { 0, 88, 88 }, -9355, 32767, 0, 0, 2, 85 }, /* region 129 */ + { { 0, 89, 89 }, -9455, 32767, 0, 0, 2, 86 }, /* region 130 */ + { { 0, 90, 90 }, -9555, 32767, 0, 0, 2, 0 }, /* region 131 */ + { { 0, 91, 91 }, -9655, 32767, 0, 0, 2, 87 }, /* region 132 */ + { { 0, 92, 92 }, -9755, 32767, 0, 0, 2, 88 }, /* region 133 */ + { { 0, 93, 93 }, -9855, 32767, 0, 0, 2, 89 }, /* region 134 */ + { { 0, 94, 94 }, -9955, 32767, 0, 0, 2, 90 }, /* region 135 */ + { { 0, 95, 95 }, -10055, 32767, 0, 0, 2, 91 }, /* region 136 */ + { { 2, 96, 96 }, -9600, 32767, 0, 0, 0, 63 }, /* region 137 */ + { { 2, 97, 97 }, -9700, 32767, 0, 0, 0, 92 }, /* region 138 */ + { { 2, 98, 98 }, -9800, 32767, 0, 0, 0, 93 }, /* region 139 */ + { { 2, 99, 99 }, -9900, 32767, 0, 0, 0, 94 }, /* region 140 */ + { { 2, 100, 100 }, -10000, 32767, 0, 0, 0, 95 }, /* region 141 */ + { { 32770, 101, 101 }, -10100, 32767, 0, 0, 0, 0 }, /* region 142 */ + { { 1, 36, 60 }, -6000, 32767, 1481, 1565, 0, 0 }, /* region 143 */ + { { 1, 61, 61 }, -7300, 32767, 740, 782, 1, 0 }, /* region 144 */ + { { 32769, 62, 62 }, -8599, 32767, 370, 391, 3, 0 }, /* region 145 */ + { { 32769, 60, 60 }, -6000, 32767, 101, 301, 4, 1 }, /* region 146 */ + { { 32769, 60, 60 }, -6000, 32767, 101, 301, 4, 50 }, /* region 147 */ + { { 32769, 60, 60 }, -6000, 32767, 101, 301, 4, 11 }, /* region 148 */ + { { 32769, 60, 60 }, -6000, 32767, 101, 301, 4, 96 }, /* region 149 */ + { { 32769, 60, 60 }, -6000, 32767, 101, 301, 4, 13 }, /* region 150 */ + { { 32769, 60, 60 }, -6000, 32767, 101, 301, 4, 14 } /* region 151 */ +}; /* end Regions */ + +/*---------------------------------------------------------------------------- + * Programs + *---------------------------------------------------------------------------- +*/ +const S_PROGRAM testPrograms[] = +{ + { 0, 41 } /* program 0 */, + { 1, 10 } /* program 1 */, + { 2, 11 } /* program 2 */, + { 3, 12 } /* program 3 */, + { 4, 18 } /* program 4 */, + { 5, 31 } /* program 5 */, + { 6, 143 } /* program 6 */, + { 7, 146 } /* program 7 */, + { 8, 147 } /* program 8 */, + { 9, 148 } /* program 9 */, + { 10, 149 } /* program 10 */, + { 11, 150 } /* program 11 */, + { 12, 151 } /* program 12 */, + { 13, 0 } /* program 13 */, + { 14, 9 } /* program 14 */, + { 15, 1 } /* program 15 */ +}; /* end Programs */ + +/*---------------------------------------------------------------------------- + * Banks + *---------------------------------------------------------------------------- +*/ +#define testBanks NULL + +/*---------------------------------------------------------------------------- + * Samples + *---------------------------------------------------------------------------- +*/ + +const EAS_SAMPLE testSamples[] = +{ + -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, + 13, 13, 14, 13, 13, 13, 12, 12, 10, 9, 8, 6, 5, 3, 2, 0, + -1, -3, -5, -8, -10, -12, -14, -15, -16, -17, -17, -17, -17, -16, -14, -13, + -11, -10, -8, -6, -5, -4, -4, -3, -3, -2, -1, -1, -1, -1, -1, -1, + -1, -2, -3, -3, -3, -3, -3, -2, -2, -2, -1, -1, -1, -1, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 4, 6, 9, 11, 12, 13, 15, 16, 17, + 19, 20, 22, 23, 25, 28, 32, 34, 36, 36, 35, 31, 25, 18, 11, 3, + -5, -13, -20, -26, -31, -34, -35, -36, -36, -35, -34, -32, -29, -26, -23, -19, + -16, -12, -8, -5, -4, -4, -4, -6, -8, -9, -11, -11, -12, -13, -13, -13, + -12, -11, -10, -9, -7, -5, -4, -3, -2, -1, -1, 0, 0, 2, 4, 5, + 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 7, 9, 12, 14, 17, 20, + 24, 27, 30, 33, 36, 39, 41, 43, 46, 49, 51, 51, 50, 48, 43, 35, + 25, 14, 1, -12, -25, -37, -48, -56, -61, -63, -62, -60, -57, -53, -48, -42, + -35, -29, -23, -17, -12, -8, -5, -3, -3, -4, -5, -7, -9, -11, -12, -14, + -14, -14, -14, -13, -11, -9, -7, -5, -3, -1, 0, 1, 1, 1, 2, 3, + 4, 5, 6, 6, 7, 8, 9, 10, 11, 11, 11, 11, 10, 9, 9, 10, + 12, 14, 17, 20, 23, 26, 30, 34, 38, 40, 43, 46, 49, 52, 55, 57, + 58, 56, 50, 42, 30, 16, 1, -15, -29, -43, -54, -63, -68, -69, -68, -65, + -60, -55, -49, -42, -35, -29, -22, -16, -10, -6, -2, -1, 0, -1, -3, -6, + -9, -12, -16, -18, -20, -21, -21, -21, -19, -17, -14, -11, -8, -5, -2, 1, + 3, 5, 7, 9, 11, 12, 12, 12, 11, 10, 9, 8, 7, 7, 7, 7, + 8, 9, 10, 12, 15, 17, 19, 22, 24, 26, 28, 30, 32, 34, 36, 38, + 42, 44, 47, 49, 53, 56, 55, 52, 45, 35, 22, 8, -8, -23, -37, -50, + -60, -67, -71, -71, -69, -63, -56, -48, -40, -33, -27, -21, -16, -12, -8, -6, + -5, -5, -6, -8, -11, -14, -17, -19, -21, -22, -22, -22, -20, -18, -16, -13, + -9, -6, -2, 1, 5, 7, 8, 9, 10, 11, 11, 11, 10, 10, 9, 9, + 9, 8, 8, 9, 9, 10, 10, 12, 13, 14, 16, 18, 19, 21, 24, 26, + 29, 32, 35, 39, 42, 46, 49, 51, 53, 56, 59, 59, 55, 48, 37, 22, + 5, -12, -29, -45, -58, -68, -74, -77, -77, -75, -69, -62, -53, -44, -35, -28, + -21, -15, -11, -8, -5, -4, -4, -4, -6, -8, -10, -13, -15, -17, -19, -19, + -19, -18, -16, -13, -10, -8, -4, -1, 1, 4, 5, 7, 8, 10, 11, 12, + 13, 14, 14, 13, 12, 12, 11, 9, 8, 7, 6, 6, 7, 8, 10, 12, + 15, 18, 21, 25, 29, 34, 39, 45, 51, 57, 61, 67, 73, 77, 82, 84, + 81, 70, 52, 29, 3, -24, -49, -72, -90, -103, -110, -112, -109, -102, -91, -78, + -64, -49, -35, -23, -13, -5, 1, 5, 8, 9, 9, 7, 4, 0, -4, -9, + -12, -15, -18, -18, -18, -17, -14, -12, -9, -6, -3, 0, 3, 6, 8, 10, + 11, 12, 11, 11, 10, 8, 7, 5, 4, 2, 2, 1, 2, 3, 4, 6, + 8, 11, 13, 15, 18, 21, 26, 31, 36, 42, 48, 53, 60, 66, 72, 77, + 82, 87, 91, 91, 86, 73, 54, 28, -2, -32, -61, -86, -105, -119, -126, -126, + -121, -111, -98, -82, -65, -48, -33, -19, -7, 1, 8, 12, 14, 14, 12, 10, + 6, 1, -4, -9, -14, -18, -20, -21, -22, -21, -19, -17, -14, -11, -8, -4, + 0, 3, 7, 10, 12, 13, 14, 14, 13, 12, 11, 10, 9, 8, 7, 5, + 4, 3, 2, 2, 4, 6, 9, 12, 16, 20, 26, 31, 36, 42, 48, 53, + 58, 64, 69, 74, 79, 82, 84, 83, 80, 72, 59, 39, 14, -14, -43, -70, + -92, -109, -119, -123, -120, -113, -102, -88, -73, -56, -40, -25, -12, -2, 5, 10, + 12, 12, 11, 9, 5, 1, -3, -8, -12, -15, -18, -20, -21, -21, -20, -18, + -16, -13, -9, -6, -2, 1, 5, 8, 11, 13, 15, 16, 16, 16, 15, 14, + 12, 10, 7, 5, 4, 3, 3, 5, 6, 8, 9, 12, 15, 19, 23, 27, + 31, 35, 38, 42, 46, 50, 54, 59, 65, 71, 75, 77, 78, 76, 68, 54, + 34, 10, -16, -43, -68, -88, -103, -112, -114, -112, -105, -94, -80, -65, -50, -35, + -22, -10, -2, 5, 9, 11, 10, 9, 6, 2, -3, -7, -12, -15, -18, -20, + -21, -22, -21, -20, -17, -14, -11, -7, -3, 0, 4, 7, 9, 11, 13, 15, + 17, 17, 17, 16, 14, 12, 11, 10, 8, 7, 5, 5, 5, 6, 7, 8, + 10, 11, 14, 17, 20, 24, 28, 32, 37, 43, 49, 57, 63, 70, 77, 82, + 83, 80, 73, 60, 42, 18, -8, -34, -59, -80, -95, -105, -110, -109, -103, -94, + -81, -67, -53, -38, -24, -13, -3, 4, 9, 11, 11, 9, 6, 3, -2, -6, + -10, -14, -17, -19, -20, -20, -20, -19, -17, -15, -12, -8, -5, -1, 2, 6, + 9, 11, 13, 15, 15, 16, 16, 15, 14, 12, 11, 9, 8, 6, 6, 5, + 5, 5, 6, 7, 8, 10, 12, 15, 19, 23, 28, 32, 38, 44, 50, 58, + 66, 74, 82, 87, 90, 89, 83, 69, 48, 21, -9, -41, -69, -93, -111, -121, + -124, -121, -113, -100, -85, -68, -50, -33, -18, -5, 5, 12, 16, 17, 16, 13, + 9, 4, -1, -6, -11, -15, -18, -20, -21, -21, -21, -19, -17, -15, -12, -8, + -4, -1, 3, 6, 9, 12, 14, 15, 15, 14, 13, 12, 11, 10, 9, 9, + 8, 8, 6, 6, 5, 5, 6, 7, 8, 11, 15, 18, 23, 27, 31, 36, + 41, 46, 51, 58, 66, 74, 82, 88, 91, 90, 83, 68, 46, 16, -16, -48, + -77, -101, -118, -127, -128, -124, -114, -101, -84, -66, -47, -30, -14, -1, 9, 16, + 19, 20, 19, 15, 11, 5, -1, -6, -11, -16, -19, -21, -23, -23, -23, -21, + -19, -16, -12, -8, -4, 0, 4, 8, 11, 13, 14, 15, 15, 14, 13, 12, + 11, 10, 9, 8, 7, 7, 7, 7, 7, 8, 8, 9, 11, 12, 14, 16, + 19, 23, 27, 31, 35, 40, 45, 51, 58, 66, 74, 82, 88, 90, 88, 77, + 58, 32, 1, -31, -62, -87, -107, -119, -125, -123, -117, -105, -90, -73, -56, -38, + -22, -8, 2, 10, 15, 17, 17, 15, 11, 7, 2, -4, -9, -14, -17, -20, + -22, -23, -22, -21, -19, -17, -14, -10, -6, -2, 2, 5, 9, 12, 14, 15, + 17, 18, 18, 18, 17, 15, 12, 10, 8, 6, 4, 4, 4, 5, 6, 7, + 8, 10, 13, 16, 19, 22, 25, 28, 32, 35, 40, 45, 52, 59, 67, 75, + 81, 85, 86, 80, 66, 45, 18, -12, -42, -69, -91, -107, -116, -119, -115, -107, + -95, -80, -64, -47, -31, -17, -5, 4, 10, 13, 14, 14, 11, 7, 3, -2, + -7, -12, -15, -18, -20, -21, -21, -20, -18, -16, -14, -11, -7, -4, 0, 4, + 7, 10, 12, 14, 16, 16, 16, 16, 16, 15, 14, 12, 10, 9, 7, 6, + 5, 4, 4, 5, 6, 7, 8, 10, 12, 15, 19, 23, 27, 31, 36, 41, + 47, 55, 64, 73, 81, 87, 90, 86, 75, 56, 30, 1, -30, -58, -82, -100, + -112, -117, -115, -109, -98, -84, -69, -52, -37, -22, -10, 0, 8, 12, 14, 14, + 13, 10, 6, 2, -3, -8, -12, -16, -18, -20, -20, -20, -19, -17, -15, -12, + -9, -5, -1, 2, 6, 9, 12, 14, 16, 17, 17, 17, 16, 14, 13, 11, + 8, 6, 4, 3, 2, 2, 2, 3, 5, 6, 8, 10, 12, 15, 18, 22, + 26, 30, 35, 40, 47, 55, 63, 71, 80, 87, 90, 88, 78, 59, 34, 4, + -27, -57, -82, -101, -113, -118, -117, -110, -99, -85, -69, -53, -37, -22, -9, 2, + 9, 14, 17, 17, 15, 12, 8, 3, -2, -7, -12, -16, -19, -20, -21, -21, + -19, -18, -15, -12, -9, -6, -2, 2, 6, 9, 12, 14, 16, 17, 17, 16, + 14, 12, 10, 8, 6, 5, 4, 3, 3, 2, 3, 4, 6, 7, 9, 11, + 13, 16, 19, 22, 26, 30, 34, 39, 46, 53, 61, 70, 80, 88, 93, 91, + 80, 61, 34, 3, -30, -59, -84, -102, -114, -119, -117, -110, -99, -84, -68, -51, + -35, -20, -7, 3, 11, 15, 17, 18, 16, 13, 9, 4, -2, -7, -11, -15, + -18, -20, -21, -21, -20, -19, -16, -14, -11, -8, -4, 0, 3, 7, 10, 13, + 15, 16, 17, 16, 14, 12, 10, 9, 7, 6, 5, 4, 4, 4, 5, 6, + 7, 8, 9, 11, 13, 15, 18, 21, 24, 27, 31, 35, 41, 48, 55, 64, + 73, 82, 89, 91, 85, 71, 48, 19, -13, -44, -71, -93, -108, -117, -118, -114, + -105, -92, -77, -60, -43, -27, -13, -1, 8, 14, 17, 18, 17, 14, 8, 13, + -1, -1, 0, 2, 4, 6, 9, 11, 13, 14, 13, 12, 11, 8, 5, 2, + -1, -5, -10, -14, -16, -17, -16, -14, -11, -8, -5, -4, -3, -1, -1, -1, + -1, -3, -3, -3, -2, -1, -1, 0, 0, 0, 0, 2, 6, 11, 14, 16, + 19, 22, 25, 32, 36, 34, 25, 11, -5, -20, -31, -35, -36, -34, -29, -23, + -16, -8, -4, -4, -8, -11, -12, -13, -12, -10, -7, -4, -2, -1, 1, 4, + 7, 7, 6, 6, 6, 7, 12, 17, 24, 30, 36, 41, 46, 51, 50, 43, + 25, 2, -25, -48, -61, -62, -57, -48, -35, -23, -12, -5, -3, -5, -9, -12, + -14, -14, -12, -7, -3, 0, 1, 2, 4, 6, 7, 9, 11, 11, 10, 9, + 12, 17, 23, 30, 37, 43, 49, 55, 58, 50, 30, 1, -29, -54, -68, -68, + -60, -49, -35, -22, -10, -2, 0, -3, -9, -16, -20, -21, -19, -14, -8, -2, + 3, 7, 11, 12, 11, 9, 7, 7, 8, 10, 15, 19, 24, 28, 33, 36, + 42, 47, 53, 56, 45, 23, -8, -37, -60, -71, -69, -56, -40, -27, -16, -8, + -5, -6, -11, -17, -21, -22, -20, -16, -9, -2, 5, 8, 10, 11, 10, 9, + 8, 8, 9, 10, 13, 16, 19, 24, 29, 35, 42, 49, 53, 59, 55, 37, + 5, -29, -58, -74, -77, -69, -53, -35, -21, -11, -5, -4, -6, -10, -15, -19, + -19, -16, -10, -5, 1, 5, 8, 11, 13, 14, 12, 10, 8, 6, 7, 10, + 15, 21, 29, 39, 51, 62, 72, 82, 81, 52, 3, -50, -90, -110, -109, -91, + -64, -35, -13, 1, 8, 9, 4, -4, -12, -18, -18, -14, -9, -3, 3, 8, + 11, 11, 10, 7, 4, 2, 2, 4, 8, 13, 18, 26, 36, 48, 60, 72, + 82, 91, 86, 54, -2, -61, -105, -126, -121, -98, -65, -33, -7, 8, 14, 12, + 6, -4, -14, -20, -22, -19, -14, -8, 0, 7, 12, 14, 13, 11, 9, 7, + 4, 2, 4, 9, 16, 26, 36, 48, 58, 69, 79, 84, 80, 59, 14, -43, + -92, -119, -120, -102, -73, -40, -12, 5, 12, 11, 5, -3, -12, -18, -21, -20, + -16, -9, -2, 5, 11, 15, 16, 15, 12, 7, 4, 4, 6, 9, 15, 23, + 31, 38, 46, 54, 65, 75, 78, 68, 34, -16, -68, -103, -114, -105, -80, -50, + -22, -1, 9, 10, 6, -3, -12, -18, -21, -21, -17, -11, -3, 4, 9, 13, + 16, 17, 14, 11, 8, 5, 5, 7, 10, 14, 20, 28, 37, 49, 64, 77, + 83, 73, 42, -8, -59, -95, -110, -103, -81, -53, -24, -3, 9, 11, 6, -2, + -10, -17, -20, -20, -17, -12, -5, 2, 9, 13, 15, 16, 14, 11, 8, 6, + 5, 6, 8, 12, 19, 28, 38, 50, 66, 82, 90, 83, 48, -9, -69, -111, + -124, -113, -85, -50, -18, 5, 16, 16, 9, -1, -11, -18, -21, -21, -17, -12, + -5, 3, 9, 14, 15, 13, 11, 9, 8, 6, 5, 6, 8, 15, 23, 31, + 41, 52, 66, 82, 91, 83, 46, -16, -77, -118, -128, -114, -84, -47, -14, 9, + 19, 19, 10, -1, -11, -19, -23, -23, -19, -12, -4, 4, 11, 14, 15, 13, + 11, 9, 7, 7, 7, 8, 11, 14, 19, 27, 35, 45, 58, 74, 88, 88, + 58, 1, -62, -107, -125, -116, -90, -56, -22, 2, 15, 17, 11, 2, -9, -17, + -22, -22, -20, -14, -6, 2, 9, 14, 17, 18, 17, 12, 8, 4, 4, 6, + 8, 13, 19, 25, 32, 40, 52, 67, 81, 86, 66, 18, -42, -91, -116, -115, + -95, -64, -31, -5, 10, 14, 11, 3, -7, -15, -20, -21, -18, -14, -7, 0, + 7, 12, 16, 17, 16, 14, 10, 7, 5, 4, 6, 8, 12, 19, 27, 36, + 47, 64, 81, 90, 75, 30, -30, -82, -112, -115, -98, -69, -37, -10, 8, 14, + 13, 6, -3, -12, -18, -20, -19, -15, -9, -1, 6, 12, 16, 17, 16, 13, + 8, 4, 2, 2, 5, 8, 12, 18, 26, 35, 47, 63, 80, 90, 78, 34, + -27, -82, -113, -117, -99, -69, -37, -9, 9, 17, 15, 8, -2, -12, -19, -21, + -19, -15, -9, -2, 6, 12, 16, 17, 14, 10, 6, 4, 3, 3, 6, 9, + 13, 19, 26, 34, 46, 61, 80, 93, 80, 34, -30, -84, -114, -117, -99, -68, + -35, -7, 11, 17, 16, 9, -2, -11, -18, -21, -20, -16, -11, -4, 3, 10, + 15, 17, 14, 10, 7, 5, 4, 5, 7, 9, 13, 18, 24, 31, 41, 55, + 73, 89, 85, 48, -12, -71, -108, -118, -104, -77, -43, -13, 8, 16, 17, 16, + 0, -3, -4, -5, -4, 0, -4, -8, -20, -25, 51, 11, -55, 9, 39, 55, + -76, -19, 92, -23, -58, 2, -15, 57, 71, 34, -41, 20, 51, 22, 63, -21, + 63, 74, 32, 36, 99, -14, 27, 102, 66, 90, 79, 77, 58, 66, 65, 114, + 69, 26, 30, 92, 90, 53, 78, 97, 77, 66, 39, -4, 60, 57, 64, 68, + -16, 36, 49, 12, 19, 12, -12, 21, 11, -32, -19, -41, -44, -12, -36, -44, + -45, -51, -55, -70, -69, -73, -85, -102, -86, -99, -92, -105, -108, -103, -100, -107, + -112, -104, -113, -112, -104, -119, -124, -115, -87, -100, -128, -106, -83, -105, -108, -109, + -91, -95, -90, -83, -80, -79, -83, -68, -59, -53, -63, -69, -57, -28, -11, -38, + -43, -23, -10, -6, 3, 1, 6, 14, 21, 23, 34, 40, 42, 48, 57, 61, + 63, 65, 73, 82, 90, 82, 89, 98, 100, 110, 111, 109, 115, 120, 121, 121, + 123, 123, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 113, 104, 103, 113, 110, 94, 80, 88, 96, 89, 81, 70, + 68, 64, 59, 59, 54, 44, 44, 39, 31, 31, 21, 18, 16, 8, 6, 2, + -3, -6, -13, -19, -27, -31, -34, -30, -38, -47, -48, -51, -56, -64, -68, -67, + -68, -76, -73, -79, -85, -94, -89, -90, -94, -92, -99, -100, -107, -107, -104, -107, + -106, -112, -114, -113, -112, -111, -112, -116, -116, -115, -115, -115, -115, -115, -115, -115, + -114, -114, -114, -114, -114, -114, -114, -114, -113, -113, -113, -113, -113, -108, -106, -107, + -111, -110, -105, -108, -107, -102, -100, -103, -103, -100, -100, -97, -97, -100, -99, -97, + -94, -90, -94, -94, -93, -93, -92, -92, -90, -89, -89, -90, -91, -87, -87, -88, + -89, -88, -84, -85, -88, -87, -86, -85, -85, -84, -82, -83, -83, -82, -81, -80, + -79, -79, -79, -78, -75, -74, -75, -73, -74, -71, -69, -67, -69, -66, -64, -66, + -65, -64, -62, -58, -57, -57, -57, -56, -52, -51, -50, -48, -46, -43, -43, -42, + -39, -36, -35, -34, -32, -31, -29, -26, -23, -23, -21, -15, -18, -15, -11, -8, + -6, -7, 0, 2, 0, 2, 7, 15, 14, 15, 16, 19, 23, 27, 29, 30, + 31, 34, 41, 41, 42, 44, 45, 51, 55, 54, 56, 57, 60, 65, 67, 69, + 69, 71, 74, 77, 79, 78, 80, 82, 86, 86, 84, 86, 88, 87, 87, 87, + 87, 87, 86, 86, 86, 86, 86, 85, 85, 85, 85, 85, 84, 84, 84, 84, + 84, 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 81, 81, 81, 81, + 81, 80, 80, 80, 80, 80, 79, 79, 79, 79, 79, 78, 78, 78, 78, 76, + 75, 72, 69, 67, 65, 64, 63, 59, 55, 54, 52, 50, 48, 45, 42, 38, + 36, 34, 31, 30, 27, 24, 21, 18, 16, 14, 12, 9, 7, 4, 1, -2, + -4, -7, -10, -11, -13, -16, -17, -18, -21, -24, -26, -27, -28, -30, -32, -33, + -35, -36, -38, -39, -41, -42, -43, -45, -45, -46, -47, -48, -49, -50, -51, -50, + -51, -52, -53, -53, -53, -53, -53, -53, -53, -54, -54, -54, -54, -53, -53, -52, + -52, -52, -51, -51, -51, -50, -50, -50, -48, -49, -48, -47, -46, -45, -45, -44, + -43, -42, -41, -41, -40, -39, -38, -37, -36, -35, -34, -33, -31, -30, -29, -28, + -27, -26, -24, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -13, + -12, -11, -11, -10, -9, -9, -8, -8, -7, -6, -7, -6, -5, -5, -5, -4, + -4, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, + 0, 0, -1, 0, 4, 9, 13, 13, 11, 5, -1, -10, -16, -17, -11, -5, + -2, -1, -2, -3, -2, -1, 0, 0, 6, 14, 19, 26, 36, 25, -5, -30, + -36, -29, -16, -4, -7, -13, -12, -7, -2, 1, 6, 7, 6, 11, 24, 36, + 46, 50, 26, -25, -60, -57, -36, -12, -3, -9, -14, -12, -3, 1, 4, 7, + 11, 10, 12, 23, 37, 49, 58, 31, -29, -67, -61, -36, -10, 0, -9, -20, + -19, -8, 3, 11, 11, 7, 8, 15, 24, 32, 41, 53, 45, -7, -60, -68, + -41, -16, -5, -11, -21, -20, -10, 4, 10, 10, 8, 9, 13, 19, 29, 42, + 54, 55, 6, -57, -77, -54, -21, -6, -6, -15, -19, -11, 1, 8, 13, 12, + 8, 7, 15, 29, 50, 73, 80, 5, -90, -109, -65, -13, 8, 4, -13, -18, + -10, 3, 11, 10, 4, 2, 8, 18, 36, 60, 82, 86, 1, -105, -121, -66, + -8, 13, 6, -14, -22, -15, -1, 12, 13, 9, 4, 3, 16, 36, 58, 78, + 81, 15, -91, -121, -74, -13, 12, 5, -11, -21, -16, -2, 11, 16, 12, 4, + 6, 15, 31, 46, 64, 79, 36, -66, -115, -81, -23, 9, 6, -11, -21, -17, + -4, 9, 16, 15, 8, 5, 9, 20, 37, 63, 83, 43, -57, -110, -83, -25, + 8, 7, -10, -20, -17, -5, 9, 15, 14, 8, 5, 8, 18, 37, 65, 91, + 50, -67, -124, -86, -19, 16, 9, -10, -21, -18, -5, 9, 15, 11, 8, 5, + 8, 22, 40, 65, 92, 48, -74, -128, -85, -16, 19, 11, -11, -23, -19, -4, + 10, 15, 11, 8, 7, 11, 19, 35, 57, 88, 60, -58, -125, -92, -24, 15, + 12, -8, -22, -20, -7, 9, 17, 17, 8, 4, 8, 18, 31, 51, 81, 67, + -38, -116, -96, -33, 9, 11, -6, -20, -19, -8, 7, 16, 16, 11, 5, 5, + 12, 26, 47, 80, 76, -26, -111, -99, -39, 7, 13, -3, -18, -19, -9, 5, + 16, 16, 8, 2, 4, 12, 25, 46, 79, 79, -23, -112, -101, -39, 9, 15, + -2, -18, -20, -9, 5, 16, 14, 7, 3, 5, 13, 25, 44, 79, 81, -25, + -113, -100, -37, 10, 16, -1, -18, -20, -11, 3, 15, 15, 7, 4, 6, 13, + 23, 40, 72, 86, -7, -107, -106, -46, 7, 16, 0, 16, 31, 47, 61, 75, + 87, 98, 107, 115, 121, 125, 127, 127, 125, 121, 116, 108, 99, 88, 75, 62, + 47, 32, 16, 0, -16, -31, -47, -61, -75, -87, -98, -108, -116, -122, -126, -128, + -128, -126, -123, -117, -109, -100, -89, -77, -64, -49, -34, -18, -2, 14, 29, 45, + 59, 73, 86, 97, 106, 114, 121, 125, 127, 127, 126, 122, 116, 109, 100, 89, + 77, 63, 49, 34, 18, 2, -14, -30, -45, -60, -73, -86, -97, -107, -115, -121, + -126, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, -36, -20, -4, 12, + 28, 43, 58, 72, 84, 96, 106, 114, 120, 124, 127, 127, 126, 122, 117, 109, + 100, 90, 78, 64, 50, 35, 19, 3, -13, -29, -44, -59, -73, -85, -97, -107, + -115, -121, -125, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, -36, -20, + -4, 12, 28, 43, 58, 72, 84, 96, 106, 114, 120, 124, 127, 127, 126, 122, + 117, 109, 100, 90, 78, 64, 50, 35, 19, 3, -13, -29, -44, -59, -73, -85, + -97, -107, -115, -121, -125, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, + -36, -20, -4, 12, 28, 43, 58, 72, 84, 96, 106, 114, 120, 124, 127, 127, + 126, 122, 117, 109, 100, 90, 78, 64, 50, 35, 19, 3, -13, -29, -44, -59, + -73, -85, -97, -107, -115, -121, -125, -128, -128, -127, -123, -118, -110, -101, -91, -79, + -65, -51, -36, -20, -4, 12, 28, 43, 58, 72, 84, 96, 106, 114, 120, 124, + 127, 127, 126, 122, 117, 109, 100, 90, 78, 64, 50, 35, 19, 3, -13, -29, + -44, -59, -73, -85, -97, -107, -115, -121, -125, -128, -128, -127, -123, -118, -110, -101, + -91, -79, -65, -51, -36, -20, -4, 12, 0, -104, -55, -11, 24, 33, 30, 7, + -15, -31, -30, -25, -23, -20, -9, 10, 31, 59, 91, 111, 115, 92, 51, 7, + -33, -64, -81, -81, -71, -51, -22, 16, 52, 74, 82, 81, 68, 38, 0, -40, + -81, -112, -124, -102, -57, -11, 24, 33, 30, 7, -15, -31, -30, -25, -23, -20, + -9, 10, 31, 59, 91, 111, 115, 92, 51, 7, -33, -64, -81, -81, -71, -51, + -22, 16, 52, 74, 82, 81, 68, 38, 0, -40, -81, -112, -124, -102, -57, -11, + 24, 33, 30, 7, -15, -31, -30, -25, -23, -20, -9, 10, 31, 59, 91, 111, + 115, 92, 51, 7, -33, -64, -81, -81, -71, -51, -22, 16, 52, 74, 82, 81, + 68, 38, 0, -40, -81, -112, -124, -102, -57, -11, 24, 33, 30, 7, -15, -31, + -30, -25, -23, -20, -9, 10, 31, 59, 91, 111, 115, 92, 51, 7, -33, -64, + -81, -81, -71, -51, -22, 16, 52, 74, 82, 81, 68, 38, 0, -40, -81, -112, + -124, -102, -57, -11, 0 +}; + +const EAS_U32 testSampleLengths[] = +{ + 1568, 784, 642, 392, 302, 172 +}; + +const EAS_U32 testSampleOffsets[] = +{ + 0x00000000, 0x00000620, 0x00000930, 0x00000bb2, 0x00000d3a, 0x00000e68 +}; + +/*---------------------------------------------------------------------------- + * S_EAS + *---------------------------------------------------------------------------- +*/ +const S_EAS easTestLib = +{ + 0x01534145, + 0x00105622, + testBanks, + testPrograms, + testRegions, + testArticulations, + testSampleLengths, + testSampleOffsets, + testSamples, + 0, + 0, + 16, + 152, + 97, + 6, + 0 +}; /* end S_EAS */ + +/*---------------------------------------------------------------------------- + * Statistics + * + * Number of banks: 0 + * Number of programs: 16 + * Number of regions: 152 + * Number of articulations: 97 + * Number of samples: 6 + * Size of sample pool: 3861 + *---------------------------------------------------------------------------- +*/ +/* end ..\..\EASLib\WTLibrary\eastestv37.c */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/project.pbxproj b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/project.pbxproj new file mode 100755 index 0000000..bd0d6ef --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/project.pbxproj @@ -0,0 +1,645 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 44; + objects = { + +/* Begin PBXBuildFile section */ + 9A56AB8F0F7197AE00D115A7 /* wt_44khz.c in Sources */ = {isa = PBXBuildFile; fileRef = 9A56AB8E0F7197AE00D115A7 /* wt_44khz.c */; }; + 9A56ABD00F71998600D115A7 /* eas_fmengine.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A56ABCF0F71998600D115A7 /* eas_fmengine.h */; }; + 9A56ABDB0F719D4600D115A7 /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = 9A56ABD70F719D4600D115A7 /* eas_xmf.c */; }; + 9A56ABDC0F719D4600D115A7 /* eas_xmf.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A56ABD80F719D4600D115A7 /* eas_xmf.h */; }; + 9A56ABDD0F719D4600D115A7 /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = 9A56ABD90F719D4600D115A7 /* eas_xmfdata.c */; }; + 9A56ABDE0F719D4600D115A7 /* eas_xmfdata.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A56ABDA0F719D4600D115A7 /* eas_xmfdata.h */; }; + 9A56AC050F71BCFE00D115A7 /* eas_build.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A56AC040F71BCFE00D115A7 /* eas_build.h */; }; + C55B113D0E2D33B4006357C1 /* eas.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11290E2D33B4006357C1 /* eas.h */; }; + C55B113E0E2D33B4006357C1 /* eas_audioconst.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B112A0E2D33B4006357C1 /* eas_audioconst.h */; }; + C55B11400E2D33B4006357C1 /* eas_config.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B112C0E2D33B4006357C1 /* eas_config.h */; }; + C55B11410E2D33B4006357C1 /* eas_data.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B112D0E2D33B4006357C1 /* eas_data.h */; }; + C55B11420E2D33B4006357C1 /* eas_host.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B112E0E2D33B4006357C1 /* eas_host.h */; }; + C55B11430E2D33B4006357C1 /* eas_math.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B112F0E2D33B4006357C1 /* eas_math.h */; }; + C55B11440E2D33B4006357C1 /* eas_midi.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11300E2D33B4006357C1 /* eas_midi.h */; }; + C55B11450E2D33B4006357C1 /* eas_midictrl.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11310E2D33B4006357C1 /* eas_midictrl.h */; }; + C55B11460E2D33B4006357C1 /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11320E2D33B4006357C1 /* eas_mixer.c */; }; + C55B11470E2D33B4006357C1 /* eas_pan.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11330E2D33B4006357C1 /* eas_pan.h */; }; + C55B11480E2D33B4006357C1 /* eas_pcm.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11340E2D33B4006357C1 /* eas_pcm.h */; }; + C55B11490E2D33B4006357C1 /* eas_pcmdata.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11350E2D33B4006357C1 /* eas_pcmdata.h */; }; + C55B114B0E2D33B4006357C1 /* eas_report.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11370E2D33B4006357C1 /* eas_report.h */; }; + C55B114C0E2D33B4006357C1 /* eas_sndlib.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11380E2D33B4006357C1 /* eas_sndlib.h */; }; + C55B114D0E2D33B4006357C1 /* eas_synth.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11390E2D33B4006357C1 /* eas_synth.h */; }; + C55B114E0E2D33B4006357C1 /* eas_synth_protos.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B113A0E2D33B4006357C1 /* eas_synth_protos.h */; }; + C55B114F0E2D33B4006357C1 /* eas_types.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B113B0E2D33B4006357C1 /* eas_types.h */; }; + C55B11500E2D33B4006357C1 /* eas_vm_protos.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B113C0E2D33B4006357C1 /* eas_vm_protos.h */; }; + C55B115B0E2D3796006357C1 /* eas_effects.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11530E2D3796006357C1 /* eas_effects.h */; }; + C55B11640E2D37FC006357C1 /* eas_imelodydata.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11620E2D37FC006357C1 /* eas_imelodydata.h */; }; + C55B11760E2D38CE006357C1 /* eas_mdls.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B116B0E2D38CE006357C1 /* eas_mdls.h */; }; + C55B11770E2D38CE006357C1 /* eas_otadata.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B116C0E2D38CE006357C1 /* eas_otadata.h */; }; + C55B11780E2D38CE006357C1 /* eas_parser.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B116D0E2D38CE006357C1 /* eas_parser.h */; }; + C55B11790E2D38CE006357C1 /* eas_rtttldata.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B116E0E2D38CE006357C1 /* eas_rtttldata.h */; }; + C55B117B0E2D38CE006357C1 /* eas_smf.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11700E2D38CE006357C1 /* eas_smf.h */; }; + C55B117C0E2D38CE006357C1 /* eas_smfdata.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11710E2D38CE006357C1 /* eas_smfdata.h */; }; + C55B117D0E2D38CE006357C1 /* eas_tcdata.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11720E2D38CE006357C1 /* eas_tcdata.h */; }; + C55B117E0E2D38CE006357C1 /* eas_wavefile.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11730E2D38CE006357C1 /* eas_wavefile.h */; }; + C55B11830E2D38FB006357C1 /* jet.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11810E2D38FB006357C1 /* jet.h */; }; + C55B11840E2D38FB006357C1 /* jet_data.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11820E2D38FB006357C1 /* jet_data.h */; }; + C55B11860E2D395F006357C1 /* eas_wtengine.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11850E2D395F006357C1 /* eas_wtengine.h */; }; + C55B11900E2D39ED006357C1 /* eas_reverb.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B118E0E2D39ED006357C1 /* eas_reverb.h */; }; + C55B11910E2D39ED006357C1 /* eas_reverbdata.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B118F0E2D39ED006357C1 /* eas_reverbdata.h */; }; + C55B11940E2D39FE006357C1 /* eas_chorus.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11920E2D39FE006357C1 /* eas_chorus.h */; }; + C55B11950E2D39FE006357C1 /* eas_chorusdata.h in Headers */ = {isa = PBXBuildFile; fileRef = C55B11930E2D39FE006357C1 /* eas_chorusdata.h */; }; + C55B11AE0E2D3B1B006357C1 /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B119F0E2D3B1B006357C1 /* eas_data.c */; }; + C55B11AF0E2D3B1B006357C1 /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A00E2D3B1B006357C1 /* eas_flog.c */; }; + C55B11B10E2D3B1B006357C1 /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A20E2D3B1B006357C1 /* eas_ima_tables.c */; }; + C55B11B20E2D3B1B006357C1 /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A30E2D3B1B006357C1 /* eas_imaadpcm.c */; }; + C55B11B30E2D3B1B006357C1 /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A40E2D3B1B006357C1 /* eas_math.c */; }; + C55B11B40E2D3B1B006357C1 /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A50E2D3B1B006357C1 /* eas_midi.c */; }; + C55B11B50E2D3B1B006357C1 /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A60E2D3B1B006357C1 /* eas_mididata.c */; }; + C55B11B60E2D3B1B006357C1 /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A70E2D3B1B006357C1 /* eas_mixbuf.c */; }; + C55B11B70E2D3B1B006357C1 /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A80E2D3B1B006357C1 /* eas_pan.c */; }; + C55B11B80E2D3B1B006357C1 /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11A90E2D3B1B006357C1 /* eas_pcm.c */; }; + C55B11B90E2D3B1B006357C1 /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11AA0E2D3B1B006357C1 /* eas_pcmdata.c */; }; + C55B11BA0E2D3B1B006357C1 /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11AB0E2D3B1B006357C1 /* eas_public.c */; }; + C55B11BB0E2D3B1B006357C1 /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11AC0E2D3B1B006357C1 /* eas_voicemgt.c */; }; + C55B11BD0E2D3B55006357C1 /* jet.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11BC0E2D3B55006357C1 /* jet.c */; }; + C55B11C10E2D3BFD006357C1 /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11C00E2D3BFD006357C1 /* eas_chorus.c */; }; + C55B11E40E2D3C62006357C1 /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11D00E2D3C62006357C1 /* eas_imelody.c */; }; + C55B11E50E2D3C62006357C1 /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11D10E2D3C62006357C1 /* eas_imelodydata.c */; }; + C55B11E60E2D3C62006357C1 /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11D20E2D3C62006357C1 /* eas_mdls.c */; }; + C55B11E70E2D3C62006357C1 /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11D30E2D3C62006357C1 /* eas_ota.c */; }; + C55B11E80E2D3C62006357C1 /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11D40E2D3C62006357C1 /* eas_otadata.c */; }; + C55B11E90E2D3C62006357C1 /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11D50E2D3C62006357C1 /* eas_rtttl.c */; }; + C55B11EA0E2D3C62006357C1 /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11D60E2D3C62006357C1 /* eas_rtttldata.c */; }; + C55B11EE0E2D3C62006357C1 /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11DA0E2D3C62006357C1 /* eas_smf.c */; }; + C55B11EF0E2D3C62006357C1 /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11DB0E2D3C62006357C1 /* eas_smfdata.c */; }; + C55B11F00E2D3C62006357C1 /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11DC0E2D3C62006357C1 /* eas_tcdata.c */; }; + C55B11F10E2D3C62006357C1 /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11DD0E2D3C62006357C1 /* eas_tonecontrol.c */; }; + C55B11F20E2D3C62006357C1 /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11DE0E2D3C62006357C1 /* eas_wavefile.c */; }; + C55B11F30E2D3C62006357C1 /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11DF0E2D3C62006357C1 /* eas_wavefiledata.c */; }; + C55B11F70E2D3C7B006357C1 /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11F60E2D3C7B006357C1 /* eas_reverb.c */; }; + C55B11FA0E2D3CAC006357C1 /* eastestv37.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B11F80E2D3CAC006357C1 /* eastestv37.c */; }; + C55B12050E2D3D56006357C1 /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B12020E2D3D56006357C1 /* eas_dlssynth.c */; }; + C55B12060E2D3D56006357C1 /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B12030E2D3D56006357C1 /* eas_wtengine.c */; }; + C55B12070E2D3D56006357C1 /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = C55B12040E2D3D56006357C1 /* eas_wtsynth.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9A56AB8E0F7197AE00D115A7 /* wt_44khz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wt_44khz.c; sourceTree = ""; }; + 9A56ABCF0F71998600D115A7 /* eas_fmengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_fmengine.h; path = "../../../arm-fm-22k/lib_src/eas_fmengine.h"; sourceTree = SOURCE_ROOT; }; + 9A56ABD70F719D4600D115A7 /* eas_xmf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_xmf.c; path = ../../lib_src/eas_xmf.c; sourceTree = SOURCE_ROOT; }; + 9A56ABD80F719D4600D115A7 /* eas_xmf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_xmf.h; path = ../../lib_src/eas_xmf.h; sourceTree = SOURCE_ROOT; }; + 9A56ABD90F719D4600D115A7 /* eas_xmfdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_xmfdata.c; path = ../../lib_src/eas_xmfdata.c; sourceTree = SOURCE_ROOT; }; + 9A56ABDA0F719D4600D115A7 /* eas_xmfdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_xmfdata.h; path = ../../lib_src/eas_xmfdata.h; sourceTree = SOURCE_ROOT; }; + 9A56AC040F71BCFE00D115A7 /* eas_build.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_build.h; path = ../../host_src/eas_build.h; sourceTree = SOURCE_ROOT; }; + C55B11290E2D33B4006357C1 /* eas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas.h; path = ../../host_src/eas.h; sourceTree = SOURCE_ROOT; }; + C55B112A0E2D33B4006357C1 /* eas_audioconst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_audioconst.h; path = ../../lib_src/eas_audioconst.h; sourceTree = SOURCE_ROOT; }; + C55B112C0E2D33B4006357C1 /* eas_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_config.h; path = ../../host_src/eas_config.h; sourceTree = SOURCE_ROOT; }; + C55B112D0E2D33B4006357C1 /* eas_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_data.h; path = ../../lib_src/eas_data.h; sourceTree = SOURCE_ROOT; }; + C55B112E0E2D33B4006357C1 /* eas_host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_host.h; path = ../../host_src/eas_host.h; sourceTree = SOURCE_ROOT; }; + C55B112F0E2D33B4006357C1 /* eas_math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_math.h; path = ../../lib_src/eas_math.h; sourceTree = SOURCE_ROOT; }; + C55B11300E2D33B4006357C1 /* eas_midi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_midi.h; path = ../../lib_src/eas_midi.h; sourceTree = SOURCE_ROOT; }; + C55B11310E2D33B4006357C1 /* eas_midictrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_midictrl.h; path = ../../lib_src/eas_midictrl.h; sourceTree = SOURCE_ROOT; }; + C55B11320E2D33B4006357C1 /* eas_mixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_mixer.c; path = ../../lib_src/eas_mixer.c; sourceTree = SOURCE_ROOT; }; + C55B11330E2D33B4006357C1 /* eas_pan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_pan.h; path = ../../lib_src/eas_pan.h; sourceTree = SOURCE_ROOT; }; + C55B11340E2D33B4006357C1 /* eas_pcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_pcm.h; path = ../../lib_src/eas_pcm.h; sourceTree = SOURCE_ROOT; }; + C55B11350E2D33B4006357C1 /* eas_pcmdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_pcmdata.h; path = ../../lib_src/eas_pcmdata.h; sourceTree = SOURCE_ROOT; }; + C55B11370E2D33B4006357C1 /* eas_report.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_report.h; path = ../../host_src/eas_report.h; sourceTree = SOURCE_ROOT; }; + C55B11380E2D33B4006357C1 /* eas_sndlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_sndlib.h; path = ../../lib_src/eas_sndlib.h; sourceTree = SOURCE_ROOT; }; + C55B11390E2D33B4006357C1 /* eas_synth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_synth.h; path = ../../lib_src/eas_synth.h; sourceTree = SOURCE_ROOT; }; + C55B113A0E2D33B4006357C1 /* eas_synth_protos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_synth_protos.h; path = ../../lib_src/eas_synth_protos.h; sourceTree = SOURCE_ROOT; }; + C55B113B0E2D33B4006357C1 /* eas_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_types.h; path = ../../host_src/eas_types.h; sourceTree = SOURCE_ROOT; }; + C55B113C0E2D33B4006357C1 /* eas_vm_protos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_vm_protos.h; path = ../../lib_src/eas_vm_protos.h; sourceTree = SOURCE_ROOT; }; + C55B11530E2D3796006357C1 /* eas_effects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_effects.h; path = ../../lib_src/eas_effects.h; sourceTree = SOURCE_ROOT; }; + C55B11620E2D37FC006357C1 /* eas_imelodydata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_imelodydata.h; path = ../../lib_src/eas_imelodydata.h; sourceTree = SOURCE_ROOT; }; + C55B116B0E2D38CE006357C1 /* eas_mdls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_mdls.h; path = ../../lib_src/eas_mdls.h; sourceTree = SOURCE_ROOT; }; + C55B116C0E2D38CE006357C1 /* eas_otadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_otadata.h; path = ../../lib_src/eas_otadata.h; sourceTree = SOURCE_ROOT; }; + C55B116D0E2D38CE006357C1 /* eas_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_parser.h; path = ../../lib_src/eas_parser.h; sourceTree = SOURCE_ROOT; }; + C55B116E0E2D38CE006357C1 /* eas_rtttldata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_rtttldata.h; path = ../../lib_src/eas_rtttldata.h; sourceTree = SOURCE_ROOT; }; + C55B11700E2D38CE006357C1 /* eas_smf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_smf.h; path = ../../lib_src/eas_smf.h; sourceTree = SOURCE_ROOT; }; + C55B11710E2D38CE006357C1 /* eas_smfdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_smfdata.h; path = ../../lib_src/eas_smfdata.h; sourceTree = SOURCE_ROOT; }; + C55B11720E2D38CE006357C1 /* eas_tcdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_tcdata.h; path = ../../lib_src/eas_tcdata.h; sourceTree = SOURCE_ROOT; }; + C55B11730E2D38CE006357C1 /* eas_wavefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_wavefile.h; path = ../../lib_src/eas_wavefile.h; sourceTree = SOURCE_ROOT; }; + C55B11810E2D38FB006357C1 /* jet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jet.h; path = ../../host_src/jet.h; sourceTree = SOURCE_ROOT; }; + C55B11820E2D38FB006357C1 /* jet_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jet_data.h; path = ../../lib_src/jet_data.h; sourceTree = SOURCE_ROOT; }; + C55B11850E2D395F006357C1 /* eas_wtengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_wtengine.h; path = ../../lib_src/eas_wtengine.h; sourceTree = SOURCE_ROOT; }; + C55B118E0E2D39ED006357C1 /* eas_reverb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_reverb.h; path = ../../host_src/eas_reverb.h; sourceTree = SOURCE_ROOT; }; + C55B118F0E2D39ED006357C1 /* eas_reverbdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_reverbdata.h; path = ../../lib_src/eas_reverbdata.h; sourceTree = SOURCE_ROOT; }; + C55B11920E2D39FE006357C1 /* eas_chorus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_chorus.h; path = ../../host_src/eas_chorus.h; sourceTree = SOURCE_ROOT; }; + C55B11930E2D39FE006357C1 /* eas_chorusdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_chorusdata.h; path = ../../lib_src/eas_chorusdata.h; sourceTree = SOURCE_ROOT; }; + C55B119F0E2D3B1B006357C1 /* eas_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_data.c; path = ../../lib_src/eas_data.c; sourceTree = SOURCE_ROOT; }; + C55B11A00E2D3B1B006357C1 /* eas_flog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_flog.c; path = ../../lib_src/eas_flog.c; sourceTree = SOURCE_ROOT; }; + C55B11A20E2D3B1B006357C1 /* eas_ima_tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_ima_tables.c; path = ../../lib_src/eas_ima_tables.c; sourceTree = SOURCE_ROOT; }; + C55B11A30E2D3B1B006357C1 /* eas_imaadpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_imaadpcm.c; path = ../../lib_src/eas_imaadpcm.c; sourceTree = SOURCE_ROOT; }; + C55B11A40E2D3B1B006357C1 /* eas_math.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_math.c; path = ../../lib_src/eas_math.c; sourceTree = SOURCE_ROOT; }; + C55B11A50E2D3B1B006357C1 /* eas_midi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_midi.c; path = ../../lib_src/eas_midi.c; sourceTree = SOURCE_ROOT; }; + C55B11A60E2D3B1B006357C1 /* eas_mididata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_mididata.c; path = ../../lib_src/eas_mididata.c; sourceTree = SOURCE_ROOT; }; + C55B11A70E2D3B1B006357C1 /* eas_mixbuf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_mixbuf.c; path = ../../lib_src/eas_mixbuf.c; sourceTree = SOURCE_ROOT; }; + C55B11A80E2D3B1B006357C1 /* eas_pan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_pan.c; path = ../../lib_src/eas_pan.c; sourceTree = SOURCE_ROOT; }; + C55B11A90E2D3B1B006357C1 /* eas_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_pcm.c; path = ../../lib_src/eas_pcm.c; sourceTree = SOURCE_ROOT; }; + C55B11AA0E2D3B1B006357C1 /* eas_pcmdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_pcmdata.c; path = ../../lib_src/eas_pcmdata.c; sourceTree = SOURCE_ROOT; }; + C55B11AB0E2D3B1B006357C1 /* eas_public.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_public.c; path = ../../lib_src/eas_public.c; sourceTree = ""; }; + C55B11AC0E2D3B1B006357C1 /* eas_voicemgt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_voicemgt.c; path = ../../lib_src/eas_voicemgt.c; sourceTree = SOURCE_ROOT; }; + C55B11BC0E2D3B55006357C1 /* jet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = jet.c; path = ../../lib_src/jet.c; sourceTree = SOURCE_ROOT; }; + C55B11C00E2D3BFD006357C1 /* eas_chorus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_chorus.c; path = ../../lib_src/eas_chorus.c; sourceTree = SOURCE_ROOT; }; + C55B11D00E2D3C62006357C1 /* eas_imelody.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_imelody.c; path = ../../lib_src/eas_imelody.c; sourceTree = SOURCE_ROOT; }; + C55B11D10E2D3C62006357C1 /* eas_imelodydata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_imelodydata.c; path = ../../lib_src/eas_imelodydata.c; sourceTree = SOURCE_ROOT; }; + C55B11D20E2D3C62006357C1 /* eas_mdls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_mdls.c; path = ../../lib_src/eas_mdls.c; sourceTree = SOURCE_ROOT; }; + C55B11D30E2D3C62006357C1 /* eas_ota.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_ota.c; path = ../../lib_src/eas_ota.c; sourceTree = SOURCE_ROOT; }; + C55B11D40E2D3C62006357C1 /* eas_otadata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_otadata.c; path = ../../lib_src/eas_otadata.c; sourceTree = SOURCE_ROOT; }; + C55B11D50E2D3C62006357C1 /* eas_rtttl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_rtttl.c; path = ../../lib_src/eas_rtttl.c; sourceTree = SOURCE_ROOT; }; + C55B11D60E2D3C62006357C1 /* eas_rtttldata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_rtttldata.c; path = ../../lib_src/eas_rtttldata.c; sourceTree = SOURCE_ROOT; }; + C55B11DA0E2D3C62006357C1 /* eas_smf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_smf.c; path = ../../lib_src/eas_smf.c; sourceTree = SOURCE_ROOT; }; + C55B11DB0E2D3C62006357C1 /* eas_smfdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_smfdata.c; path = ../../lib_src/eas_smfdata.c; sourceTree = SOURCE_ROOT; }; + C55B11DC0E2D3C62006357C1 /* eas_tcdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_tcdata.c; path = ../../lib_src/eas_tcdata.c; sourceTree = SOURCE_ROOT; }; + C55B11DD0E2D3C62006357C1 /* eas_tonecontrol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_tonecontrol.c; path = ../../lib_src/eas_tonecontrol.c; sourceTree = SOURCE_ROOT; }; + C55B11DE0E2D3C62006357C1 /* eas_wavefile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wavefile.c; path = ../../lib_src/eas_wavefile.c; sourceTree = SOURCE_ROOT; }; + C55B11DF0E2D3C62006357C1 /* eas_wavefiledata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wavefiledata.c; path = ../../lib_src/eas_wavefiledata.c; sourceTree = SOURCE_ROOT; }; + C55B11F60E2D3C7B006357C1 /* eas_reverb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_reverb.c; path = ../../lib_src/eas_reverb.c; sourceTree = SOURCE_ROOT; }; + C55B11F80E2D3CAC006357C1 /* eastestv37.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eastestv37.c; sourceTree = ""; }; + C55B12020E2D3D56006357C1 /* eas_dlssynth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_dlssynth.c; path = ../../lib_src/eas_dlssynth.c; sourceTree = SOURCE_ROOT; }; + C55B12030E2D3D56006357C1 /* eas_wtengine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wtengine.c; path = ../../lib_src/eas_wtengine.c; sourceTree = SOURCE_ROOT; }; + C55B12040E2D3D56006357C1 /* eas_wtsynth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wtsynth.c; path = ../../lib_src/eas_wtsynth.c; sourceTree = SOURCE_ROOT; }; + D2AAC046055464E500DB518D /* libeaswt_vst_lib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libeaswt_vst_lib.a; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D289987405E68DCB004EDB86 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* easwt_vst_lib */ = { + isa = PBXGroup; + children = ( + C55B11280E2D31B6006357C1 /* Header Files */, + 08FB7795FE84155DC02AAC07 /* Source */, + C6A0FF2B0290797F04C91782 /* Documentation */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = easwt_vst_lib; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + C55B119F0E2D3B1B006357C1 /* eas_data.c */, + C55B11A00E2D3B1B006357C1 /* eas_flog.c */, + C55B11A20E2D3B1B006357C1 /* eas_ima_tables.c */, + C55B11A30E2D3B1B006357C1 /* eas_imaadpcm.c */, + C55B11A40E2D3B1B006357C1 /* eas_math.c */, + C55B11A50E2D3B1B006357C1 /* eas_midi.c */, + C55B11A60E2D3B1B006357C1 /* eas_mididata.c */, + C55B11A70E2D3B1B006357C1 /* eas_mixbuf.c */, + C55B11320E2D33B4006357C1 /* eas_mixer.c */, + C55B11A80E2D3B1B006357C1 /* eas_pan.c */, + C55B11A90E2D3B1B006357C1 /* eas_pcm.c */, + C55B11AA0E2D3B1B006357C1 /* eas_pcmdata.c */, + C55B11AB0E2D3B1B006357C1 /* eas_public.c */, + C55B11AC0E2D3B1B006357C1 /* eas_voicemgt.c */, + C55B11BC0E2D3B55006357C1 /* jet.c */, + C55B11960E2D3A56006357C1 /* Chorus */, + C55B119A0E2D3A7F006357C1 /* Parsers */, + C55B11970E2D3A5C006357C1 /* Reverb */, + C55B119B0E2D3A99006357C1 /* SoundLibs */, + C55B119D0E2D3AB6006357C1 /* Wavetable */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + D2AAC046055464E500DB518D /* libeaswt_vst_lib.a */, + ); + name = Products; + sourceTree = ""; + }; + C55B11280E2D31B6006357C1 /* Header Files */ = { + isa = PBXGroup; + children = ( + 9A56AC040F71BCFE00D115A7 /* eas_build.h */, + 9A56ABCF0F71998600D115A7 /* eas_fmengine.h */, + C55B11880E2D39B0006357C1 /* Reverb */, + C55B11870E2D39A9006357C1 /* Chorus */, + C55B11850E2D395F006357C1 /* eas_wtengine.h */, + C55B11810E2D38FB006357C1 /* jet.h */, + C55B11820E2D38FB006357C1 /* jet_data.h */, + C55B116B0E2D38CE006357C1 /* eas_mdls.h */, + C55B116C0E2D38CE006357C1 /* eas_otadata.h */, + C55B116D0E2D38CE006357C1 /* eas_parser.h */, + C55B116E0E2D38CE006357C1 /* eas_rtttldata.h */, + C55B11700E2D38CE006357C1 /* eas_smf.h */, + C55B11710E2D38CE006357C1 /* eas_smfdata.h */, + C55B11720E2D38CE006357C1 /* eas_tcdata.h */, + C55B11730E2D38CE006357C1 /* eas_wavefile.h */, + C55B11620E2D37FC006357C1 /* eas_imelodydata.h */, + C55B11530E2D3796006357C1 /* eas_effects.h */, + C55B11290E2D33B4006357C1 /* eas.h */, + C55B112A0E2D33B4006357C1 /* eas_audioconst.h */, + C55B112C0E2D33B4006357C1 /* eas_config.h */, + C55B112D0E2D33B4006357C1 /* eas_data.h */, + C55B112E0E2D33B4006357C1 /* eas_host.h */, + C55B112F0E2D33B4006357C1 /* eas_math.h */, + C55B11300E2D33B4006357C1 /* eas_midi.h */, + C55B11310E2D33B4006357C1 /* eas_midictrl.h */, + C55B11330E2D33B4006357C1 /* eas_pan.h */, + C55B11340E2D33B4006357C1 /* eas_pcm.h */, + C55B11350E2D33B4006357C1 /* eas_pcmdata.h */, + C55B11370E2D33B4006357C1 /* eas_report.h */, + C55B11380E2D33B4006357C1 /* eas_sndlib.h */, + C55B11390E2D33B4006357C1 /* eas_synth.h */, + C55B113A0E2D33B4006357C1 /* eas_synth_protos.h */, + C55B113B0E2D33B4006357C1 /* eas_types.h */, + C55B113C0E2D33B4006357C1 /* eas_vm_protos.h */, + ); + name = "Header Files"; + sourceTree = ""; + }; + C55B11870E2D39A9006357C1 /* Chorus */ = { + isa = PBXGroup; + children = ( + C55B11920E2D39FE006357C1 /* eas_chorus.h */, + C55B11930E2D39FE006357C1 /* eas_chorusdata.h */, + ); + name = Chorus; + sourceTree = ""; + }; + C55B11880E2D39B0006357C1 /* Reverb */ = { + isa = PBXGroup; + children = ( + C55B118E0E2D39ED006357C1 /* eas_reverb.h */, + C55B118F0E2D39ED006357C1 /* eas_reverbdata.h */, + ); + name = Reverb; + sourceTree = ""; + }; + C55B11960E2D3A56006357C1 /* Chorus */ = { + isa = PBXGroup; + children = ( + C55B11C00E2D3BFD006357C1 /* eas_chorus.c */, + ); + name = Chorus; + sourceTree = ""; + }; + C55B11970E2D3A5C006357C1 /* Reverb */ = { + isa = PBXGroup; + children = ( + C55B11F60E2D3C7B006357C1 /* eas_reverb.c */, + ); + name = Reverb; + sourceTree = ""; + }; + C55B119A0E2D3A7F006357C1 /* Parsers */ = { + isa = PBXGroup; + children = ( + 9A56ABD70F719D4600D115A7 /* eas_xmf.c */, + 9A56ABD80F719D4600D115A7 /* eas_xmf.h */, + 9A56ABD90F719D4600D115A7 /* eas_xmfdata.c */, + 9A56ABDA0F719D4600D115A7 /* eas_xmfdata.h */, + C55B11D00E2D3C62006357C1 /* eas_imelody.c */, + C55B11D10E2D3C62006357C1 /* eas_imelodydata.c */, + C55B11D20E2D3C62006357C1 /* eas_mdls.c */, + C55B11D30E2D3C62006357C1 /* eas_ota.c */, + C55B11D40E2D3C62006357C1 /* eas_otadata.c */, + C55B11D50E2D3C62006357C1 /* eas_rtttl.c */, + C55B11D60E2D3C62006357C1 /* eas_rtttldata.c */, + C55B11DA0E2D3C62006357C1 /* eas_smf.c */, + C55B11DB0E2D3C62006357C1 /* eas_smfdata.c */, + C55B11DC0E2D3C62006357C1 /* eas_tcdata.c */, + C55B11DD0E2D3C62006357C1 /* eas_tonecontrol.c */, + C55B11DE0E2D3C62006357C1 /* eas_wavefile.c */, + C55B11DF0E2D3C62006357C1 /* eas_wavefiledata.c */, + ); + name = Parsers; + sourceTree = ""; + }; + C55B119B0E2D3A99006357C1 /* SoundLibs */ = { + isa = PBXGroup; + children = ( + 9A56AB8E0F7197AE00D115A7 /* wt_44khz.c */, + C55B11F80E2D3CAC006357C1 /* eastestv37.c */, + ); + name = SoundLibs; + sourceTree = ""; + }; + C55B119D0E2D3AB6006357C1 /* Wavetable */ = { + isa = PBXGroup; + children = ( + C55B12020E2D3D56006357C1 /* eas_dlssynth.c */, + C55B12030E2D3D56006357C1 /* eas_wtengine.c */, + C55B12040E2D3D56006357C1 /* eas_wtsynth.c */, + ); + name = Wavetable; + sourceTree = ""; + }; + C6A0FF2B0290797F04C91782 /* Documentation */ = { + isa = PBXGroup; + children = ( + ); + name = Documentation; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + D2AAC043055464E500DB518D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C55B113D0E2D33B4006357C1 /* eas.h in Headers */, + C55B113E0E2D33B4006357C1 /* eas_audioconst.h in Headers */, + C55B11400E2D33B4006357C1 /* eas_config.h in Headers */, + C55B11410E2D33B4006357C1 /* eas_data.h in Headers */, + C55B11420E2D33B4006357C1 /* eas_host.h in Headers */, + C55B11430E2D33B4006357C1 /* eas_math.h in Headers */, + C55B11440E2D33B4006357C1 /* eas_midi.h in Headers */, + C55B11450E2D33B4006357C1 /* eas_midictrl.h in Headers */, + C55B11470E2D33B4006357C1 /* eas_pan.h in Headers */, + C55B11480E2D33B4006357C1 /* eas_pcm.h in Headers */, + C55B11490E2D33B4006357C1 /* eas_pcmdata.h in Headers */, + C55B114B0E2D33B4006357C1 /* eas_report.h in Headers */, + C55B114C0E2D33B4006357C1 /* eas_sndlib.h in Headers */, + C55B114D0E2D33B4006357C1 /* eas_synth.h in Headers */, + C55B114E0E2D33B4006357C1 /* eas_synth_protos.h in Headers */, + C55B114F0E2D33B4006357C1 /* eas_types.h in Headers */, + C55B11500E2D33B4006357C1 /* eas_vm_protos.h in Headers */, + C55B115B0E2D3796006357C1 /* eas_effects.h in Headers */, + C55B11640E2D37FC006357C1 /* eas_imelodydata.h in Headers */, + C55B11760E2D38CE006357C1 /* eas_mdls.h in Headers */, + C55B11770E2D38CE006357C1 /* eas_otadata.h in Headers */, + C55B11780E2D38CE006357C1 /* eas_parser.h in Headers */, + C55B11790E2D38CE006357C1 /* eas_rtttldata.h in Headers */, + C55B117B0E2D38CE006357C1 /* eas_smf.h in Headers */, + C55B117C0E2D38CE006357C1 /* eas_smfdata.h in Headers */, + C55B117D0E2D38CE006357C1 /* eas_tcdata.h in Headers */, + C55B117E0E2D38CE006357C1 /* eas_wavefile.h in Headers */, + C55B11830E2D38FB006357C1 /* jet.h in Headers */, + C55B11840E2D38FB006357C1 /* jet_data.h in Headers */, + C55B11860E2D395F006357C1 /* eas_wtengine.h in Headers */, + C55B11900E2D39ED006357C1 /* eas_reverb.h in Headers */, + C55B11910E2D39ED006357C1 /* eas_reverbdata.h in Headers */, + C55B11940E2D39FE006357C1 /* eas_chorus.h in Headers */, + C55B11950E2D39FE006357C1 /* eas_chorusdata.h in Headers */, + 9A56ABD00F71998600D115A7 /* eas_fmengine.h in Headers */, + 9A56ABDC0F719D4600D115A7 /* eas_xmf.h in Headers */, + 9A56ABDE0F719D4600D115A7 /* eas_xmfdata.h in Headers */, + 9A56AC050F71BCFE00D115A7 /* eas_build.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + D2AAC045055464E500DB518D /* easwt_vst_lib */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "easwt_vst_lib" */; + buildPhases = ( + D2AAC043055464E500DB518D /* Headers */, + D2AAC044055464E500DB518D /* Sources */, + D289987405E68DCB004EDB86 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = easwt_vst_lib; + productName = easwt_vst_lib; + productReference = D2AAC046055464E500DB518D /* libeaswt_vst_lib.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "easwt_vst_lib" */; + compatibilityVersion = "Xcode 3.0"; + hasScannedForEncodings = 1; + mainGroup = 08FB7794FE84155DC02AAC07 /* easwt_vst_lib */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D2AAC045055464E500DB518D /* easwt_vst_lib */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + D2AAC044055464E500DB518D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C55B11460E2D33B4006357C1 /* eas_mixer.c in Sources */, + C55B11AE0E2D3B1B006357C1 /* eas_data.c in Sources */, + C55B11AF0E2D3B1B006357C1 /* eas_flog.c in Sources */, + C55B11B10E2D3B1B006357C1 /* eas_ima_tables.c in Sources */, + C55B11B20E2D3B1B006357C1 /* eas_imaadpcm.c in Sources */, + C55B11B30E2D3B1B006357C1 /* eas_math.c in Sources */, + C55B11B40E2D3B1B006357C1 /* eas_midi.c in Sources */, + C55B11B50E2D3B1B006357C1 /* eas_mididata.c in Sources */, + C55B11B60E2D3B1B006357C1 /* eas_mixbuf.c in Sources */, + C55B11B70E2D3B1B006357C1 /* eas_pan.c in Sources */, + C55B11B80E2D3B1B006357C1 /* eas_pcm.c in Sources */, + C55B11B90E2D3B1B006357C1 /* eas_pcmdata.c in Sources */, + C55B11BA0E2D3B1B006357C1 /* eas_public.c in Sources */, + C55B11BB0E2D3B1B006357C1 /* eas_voicemgt.c in Sources */, + C55B11BD0E2D3B55006357C1 /* jet.c in Sources */, + C55B11C10E2D3BFD006357C1 /* eas_chorus.c in Sources */, + C55B11E40E2D3C62006357C1 /* eas_imelody.c in Sources */, + C55B11E50E2D3C62006357C1 /* eas_imelodydata.c in Sources */, + C55B11E60E2D3C62006357C1 /* eas_mdls.c in Sources */, + C55B11E70E2D3C62006357C1 /* eas_ota.c in Sources */, + C55B11E80E2D3C62006357C1 /* eas_otadata.c in Sources */, + C55B11E90E2D3C62006357C1 /* eas_rtttl.c in Sources */, + C55B11EA0E2D3C62006357C1 /* eas_rtttldata.c in Sources */, + C55B11EE0E2D3C62006357C1 /* eas_smf.c in Sources */, + C55B11EF0E2D3C62006357C1 /* eas_smfdata.c in Sources */, + C55B11F00E2D3C62006357C1 /* eas_tcdata.c in Sources */, + C55B11F10E2D3C62006357C1 /* eas_tonecontrol.c in Sources */, + C55B11F20E2D3C62006357C1 /* eas_wavefile.c in Sources */, + C55B11F30E2D3C62006357C1 /* eas_wavefiledata.c in Sources */, + C55B11F70E2D3C7B006357C1 /* eas_reverb.c in Sources */, + C55B11FA0E2D3CAC006357C1 /* eastestv37.c in Sources */, + C55B12050E2D3D56006357C1 /* eas_dlssynth.c in Sources */, + C55B12060E2D3D56006357C1 /* eas_wtengine.c in Sources */, + C55B12070E2D3D56006357C1 /* eas_wtsynth.c in Sources */, + 9A56AB8F0F7197AE00D115A7 /* wt_44khz.c in Sources */, + 9A56ABDB0F719D4600D115A7 /* eas_xmf.c in Sources */, + 9A56ABDD0F719D4600D115A7 /* eas_xmfdata.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB91EC08733DB70010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG_JET=1", + "_DEBUG_SMAF=1", + "_DEBUG_CMF=1", + "JET_INTERFACE=1", + "MAX_SMF_STREAMS=32", + "NUM_OUTPUT_CHANNELS=2", + "_SAMPLE_RATE_44100=1", + "_8_BIT_SAMPLES=1", + "_FILTER_ENABLED=1", + "_NO_DEBUG_PREPROCESSOR=1", + "_CORE_CYCLES_PER_MEMORY_CYCLE=1", + "_IMA_DECODER=1", + "_XMF_PARSER=1", + "_DLS_PARSER=1", + "MAX_DLS_MEMORY=16777216", + "EAS_WT_SYNTH=1", + "MAX_SYNTH_VOICES=64", + "X_ENHANCER_ENABLED=1", + "_REVERB_ENABLED=1", + "_CHORUS_ENABLED=1", + "DLS_SYNTHESIZER=1", + "EXTERNAL_AUDIO=1", + "TEST_HARNESS=1", + "MMAPI_SUPPORT=1", + "X_MAXIMIZER_ENABLED=1", + "X_COMPRESSOR_ENABLED=1", + "X_STATS=1", + "X_DEBUG_DLS=1", + "X_OPTIMIZED_MONO=1", + "X_CHECKED_BUILD=1", + "_NO_ALIGN=1", + "_C_REFERENCE=1", + "XMAXIMIZER_USE_FLOATING_POINT=1", + ); + HEADER_SEARCH_PATHS = ( + "${TARGET_BUILD_DIR}/**", + "../../Common/**", + "../../Parsers/**", + "../../Effects/**", + "../../WTSynth/**", + "../../FMSynth/**", + "../../SplitArch/**", + "../../Jet/**", + ); + INSTALL_PATH = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.4; + PRODUCT_NAME = easwt_vst_lib; + ZERO_LINK = YES; + }; + name = Debug; + }; + 1DEB91ED08733DB70010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_AUTO_VECTORIZATION = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "JET_INTERFACE=1", + "MAX_SMF_STREAMS=32", + "NUM_OUTPUT_CHANNELS=2", + "_SAMPLE_RATE_44100=1", + "_8_BIT_SAMPLES=1", + "_FILTER_ENABLED=1", + "_NO_DEBUG_PREPROCESSOR=1", + "_CORE_CYCLES_PER_MEMORY_CYCLE=1", + "_IMA_DECODER=1", + "_XMF_PARSER=1", + "_DLS_PARSER=1", + "MAX_DLS_MEMORY=16777216", + "EAS_WT_SYNTH=1", + "MAX_SYNTH_VOICES=64", + "X_ENHANCER_ENABLED=1", + "_REVERB_ENABLED=1", + "_CHORUS_ENABLED=1", + "DLS_SYNTHESIZER=1", + "EXTERNAL_AUDIO=1", + "TEST_HARNESS=1", + "MMAPI_SUPPORT=1", + "X_MAXIMIZER_ENABLED=1", + "X_COMPRESSOR_ENABLED=1", + "X_STATS=1", + "X_DEBUG_DLS=1", + "X_OPTIMIZED_MONO=1", + "X_CHECKED_BUILD=1", + "_NO_ALIGN=1", + "_C_REFERENCE=1", + "XMAXIMIZER_USE_FLOATING_POINT=1", + ); + GCC_UNROLL_LOOPS = YES; + HEADER_SEARCH_PATHS = ( + "${TARGET_BUILD_DIR}/**", + "../../Common/**", + "../../Parsers/**", + "../../Effects/**", + "../../WTSynth/**", + "../../FMSynth/**", + "../../SplitArch/**", + "../../Jet/**", + ); + INSTALL_PATH = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.4; + PRODUCT_NAME = easwt_vst_lib; + }; + name = Release; + }; + 1DEB91F008733DB70010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; + }; + name = Debug; + }; + 1DEB91F108733DB70010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "easwt_vst_lib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91EC08733DB70010E9CD /* Debug */, + 1DEB91ED08733DB70010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "easwt_vst_lib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91F008733DB70010E9CD /* Debug */, + 1DEB91F108733DB70010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/easwt_vst_lib.xcscheme b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/easwt_vst_lib.xcscheme new file mode 100755 index 0000000..dc2fe91 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/easwt_vst_lib.xcscheme @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 0000000..98709ed --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + easwt_vst_lib.xcscheme + + orderHint + 11 + + + SuppressBuildableAutocreation + + D2AAC045055464E500DB518D + + primary + + + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/easwt_vst_lib.xcscheme b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/easwt_vst_lib.xcscheme new file mode 100755 index 0000000..dc2fe91 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/easwt_vst_lib.xcscheme @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/xcschememanagement.plist b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100755 index 0000000..101eeec --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/easwt_vst_lib.xcodeproj/xcuserdata/ryan.gerleve.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + easwt_vst_lib.xcscheme + + orderHint + 3 + + + SuppressBuildableAutocreation + + D2AAC045055464E500DB518D + + primary + + + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/wt_44khz.c b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/wt_44khz.c new file mode 100755 index 0000000..53cd952 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/jetcreator_lib_src/darwin-x86/wt_44khz.c @@ -0,0 +1,14723 @@ +/*---------------------------------------------------------------------------- + * + * Filename: wt_44khz.c + * Purpose: Wavetable sound libary + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +#include "eas_sndlib.h" + +/*---------------------------------------------------------------------------- + * Articulations + *---------------------------------------------------------------------------- +*/ +const S_ARTICULATION eas_articulations[] = +{ + { /* articulation 0 */ + { 32767, 31730, 0, 31730 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 1 */ + { 32767, 29669, 0, 29669 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 2 */ + { 32767, 31605, 0, 31701 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 3 */ + { 32767, 29434, 0, 29434 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 4 */ + { 32767, 0, 32767, 32742 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 5 */ + { 32767, 26439, 0, 26439 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 6 */ + { 32767, 32322, 0, 32350 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 7 */ + { 32767, 32715, 32767, 32715 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 8 */ + { 32767, 0, 32767, 0 }, + { 32767, 951, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 9 */ + { 32767, 32558, 0, 32558 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 10 */ + { 32767, 0, 32767, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -1 + }, + { /* articulation 11 */ + { 32767, 32245, 0, 32245 }, + { 32767, 380, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -44 + }, + { /* articulation 12 */ + { 32767, 27897, 0, 27897 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 13 */ + { 32767, 32245, 0, 32245 }, + { 32767, 380, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -31 + }, + { /* articulation 14 */ + { 4755, 26439, 0, 26439 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 15 */ + { 32767, 32187, 0, 32187 }, + { 32767, 380, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -6 + }, + { /* articulation 16 */ + { 32767, 32444, 0, 32480 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 17 */ + { 32767, 32153, 0, 32153 }, + { 32767, 380, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 6 + }, + { /* articulation 18 */ + { 32767, 32072, 0, 32072 }, + { 32767, 476, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 31 + }, + { /* articulation 19 */ + { 32767, 32363, 0, 32363 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 20 */ + { 32767, 31901, 0, 31901 }, + { 32767, 476, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 21 */ + { 32767, 32528, 0, 32518 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 22 */ + { 9511, 32322, 0, 32337 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 23 */ + { 32767, 32376, 0, 32398 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 24 */ + { 32767, 0, 32767, 32715 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 12 + }, + { /* articulation 25 */ + { 32767, 32052, 0, 32052 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -25 + }, + { /* articulation 26 */ + { 32767, 0, 32767, 32715 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 27 */ + { 32767, 32289, 0, 32271 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -25 + }, + { /* articulation 28 */ + { 32767, 31730, 0, 31730 }, + { 32767, 48, 0, 0 }, + 0, 0, 476, 240, 0, 0, 0, 0, -56 + }, + { /* articulation 29 */ + { 32767, 32498, 0, 32492 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 30 */ + { 32767, 29434, 0, 29434 }, + { 32767, 1902, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 50 + }, + { /* articulation 31 */ + { 32767, 27897, 0, 27897 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -50 + }, + { /* articulation 32 */ + { 32767, 31056, 0, 31056 }, + { 32767, 1902, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -50 + }, + { /* articulation 33 */ + { 32767, 31479, 0, 31476 }, + { 32767, 1902, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -44 + }, + { /* articulation 34 */ + { 32767, 32663, 0, 32663 }, + { 32767, 127, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 35 */ + { 32767, 0, 32767, 32715 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -63 + }, + { /* articulation 36 */ + { 1902, 27897, 0, 27897 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -63 + }, + { /* articulation 37 */ + { 32767, 27897, 0, 27897 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -59 + }, + { /* articulation 38 */ + { 32767, 31730, 0, 31730 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 50 + }, + { /* articulation 39 */ + { 32767, 30725, 0, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 44 + }, + { /* articulation 40 */ + { 951, 31730, 0, 31730 }, + { 32767, 190, 0, 0 }, + 0, 0, 476, -100, 0, 0, 0, 0, 44 + }, + { /* articulation 41 */ + { 32767, 17213, 0, 17213 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 42 */ + { 32767, 31295, 0, 31295 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 43 */ + { 32767, 31479, 0, 31476 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 44 */ + { 9511, 25581, 0, 25581 }, + { 476, 32767, 32767, 0 }, + 0, 0, 476, 100, 0, 0, 0, 0, -25 + }, + { /* articulation 45 */ + { 1902, 23749, 0, 23749 }, + { 476, 32767, 32767, 0 }, + 0, 0, 476, 500, 0, 0, 0, 0, -25 + }, + { /* articulation 46 */ + { 32767, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -56 + }, + { /* articulation 47 */ + { 32767, 31730, 0, 31730 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, -56 + }, + { /* articulation 48 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 49 */ + { 32767, 31964, 0, 31964 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 50 */ + { 9511, 32363, 0, 32418 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 51 */ + { 32767, 31180, 0, 31180 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 52 */ + { 32767, 32251, 0, 32052 }, + { 32767, 147, 0, 0 }, + 0, 0, 476, 0, 10000, 7121, 0, 0, 0 + }, + { /* articulation 53 */ + { 32767, 0, 32767, 32072 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 778, 0, -2300, 11920, 0, 0, 0 + }, + { /* articulation 54 */ + { 587, 0, 32767, 32376 }, + { 32767, 63, 0, 0 }, + 0, 0, 778, 0, 2000, 10721, 0, 8, 15 + }, + { /* articulation 55 */ + { 587, 0, 32767, 32376 }, + { 476, 63, 0, 0 }, + 0, 0, 778, 0, 2000, 9023, 0, 5, 15 + }, + { /* articulation 56 */ + { 3804, 0, 32767, 31477 }, + { 32767, 34, 5898, 0 }, + 0, 0, 778, 0, 6000, 9080, 0, 0, -2 + }, + { /* articulation 57 */ + { 32767, 0, 32767, 31005 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 778, 0, 0, 0, 0, 0, 1 + }, + { /* articulation 58 */ + { 2570, 0, 32767, 31455 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 778, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 59 */ + { 32767, 32663, 0, 29434 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 60 */ + { 32767, 32558, 0, 29434 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 61 */ + { 32767, 32418, 0, 32418 }, + { 32767, 48, 0, 0 }, + 0, 69, 495, 0, 2400, 9521, 0, 0, 0 + }, + { /* articulation 62 */ + { 32767, 31476, 0, 31476 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 11738, 0, 16, 0 + }, + { /* articulation 63 */ + { 32767, 32558, 0, 31391 }, + { 32767, 317, 0, 0 }, + 0, 69, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 64 */ + { 32767, 32245, 0, 32115 }, + { 32767, 317, 0, 0 }, + 0, 69, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 65 */ + { 32767, 32593, 0, 28809 }, + { 32767, 48, 0, 0 }, + 0, 69, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 66 */ + { 32767, 32408, 0, 32363 }, + { 32767, 317, 0, 0 }, + 0, 69, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 67 */ + { 32767, 32350, 0, 32350 }, + { 32767, 317, 0, 0 }, + 0, 69, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 68 */ + { 4755, 32715, 18820, 27897 }, + { 951, 29, 13107, 0 }, + 0, 0, 495, 0, 6000, 5535, 0, 4, 0 + }, + { /* articulation 69 */ + { 32767, 32257, 0, 32245 }, + { 32767, 951, 0, 0 }, + 0, 103, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 70 */ + { 63, 32727, 3811, 32558 }, + { 48, 19, 32767, 0 }, + 0, 0, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 71 */ + { 2378, 32715, 3566, 30725 }, + { 1902, 32767, 32767, 0 }, + 0, 0, 495, 100, 0, 11919, 0, 0, 0 + }, + { /* articulation 72 */ + { 32767, 32349, 0, 32349 }, + { 32767, 168, 0, 0 }, + 0, 34, 495, 0, 7000, 9023, 0, 0, 0 + }, + { /* articulation 73 */ + { 32767, 32072, 0, 32072 }, + { 32767, 168, 0, 0 }, + 0, 3, 476, 0, 7000, 9023, 0, 0, 0 + }, + { /* articulation 74 */ + { 32767, 32698, 6208, 32349 }, + { 190, 48, 0, 0 }, + 0, 0, 495, 0, 3840, 8302, 0, 8, 0 + }, + { /* articulation 75 */ + { 32767, 32418, 0, 32468 }, + { 32767, 190, 0, 0 }, + 0, 0, 495, 0, 5000, 8321, 0, 0, 0 + }, + { /* articulation 76 */ + { 32767, 32349, 0, 32349 }, + { 32767, 190, 0, 0 }, + 0, 0, 476, 0, 5000, 7934, 0, 0, 0 + }, + { /* articulation 77 */ + { 32767, 32441, 0, 31709 }, + { 32767, 32, 0, 0 }, + 0, 34, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 78 */ + { 32767, 32505, 0, 27897 }, + { 32767, 951, 0, 0 }, + 0, 345, 495, 0, 1000, 11107, 0, 0, 0 + }, + { /* articulation 79 */ + { 32767, 32715, 6208, 32349 }, + { 48, 48, 0, 0 }, + 0, 69, 811, 0, 3560, 8834, 1, 8, 0 + }, + { /* articulation 80 */ + { 32767, 32564, 0, 29434 }, + { 32767, 95, 0, 0 }, + 0, 34, 495, 0, 6000, 9907, 0, 0, 0 + }, + { /* articulation 81 */ + { 32767, 32505, 0, 27897 }, + { 32767, 32, 0, 0 }, + 0, 34, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 82 */ + { 32767, 32245, 18820, 17213 }, + { 32767, 32767, 32767, 0 }, + 0, 34, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 83 */ + { 32767, 32742, 128, 32466 }, + { 32767, 63, 0, 0 }, + 0, 0, 495, 0, 0, 11920, 0, 8, 0 + }, + { /* articulation 84 */ + { 32767, 32418, 0, 32418 }, + { 32767, 33, 0, 0 }, + 3, 0, 286, 0, 5000, 5535, 0, 0, 0 + }, + { /* articulation 85 */ + { 1902, 32715, 18820, 27897 }, + { 32767, 1012, 0, 0 }, + 10, 69, 504, -30, 0, 0, 0, 0, 0 + }, + { /* articulation 86 */ + { 9511, 32715, 18820, 27897 }, + { 380, 48, 0, 0 }, + 0, 69, 495, 0, 4473, 7131, 0, 8, 0 + }, + { /* articulation 87 */ + { 951, 32698, 6208, 32468 }, + { 317, 19, 16384, 0 }, + 0, 0, 495, 0, 2987, 7877, 0, 12, 0 + }, + { /* articulation 88 */ + { 32767, 32680, 0, 32349 }, + { 32767, 48, 0, 0 }, + 0, 0, 581, 0, 4053, 7930, 2, 12, 0 + }, + { /* articulation 89 */ + { 190, 32726, 6208, 32349 }, + { 32767, 56, 0, 0 }, + 0, 0, 495, 0, 0, 8887, 0, 0, 0 + }, + { /* articulation 90 */ + { 9511, 32715, 18820, 27897 }, + { 634, 48, 0, 0 }, + 0, 69, 495, 0, 5113, 7981, 0, 4, 0 + }, + { /* articulation 91 */ + { 951, 32715, 6208, 31730 }, + { 951, 63, 0, 0 }, + 0, 69, 495, 0, 3500, 7877, 0, 5, 0 + }, + { /* articulation 92 */ + { 951, 32715, 6208, 31730 }, + { 634, 48, 0, 0 }, + 0, 69, 476, 0, 4773, 8355, 0, 5, 0 + }, + { /* articulation 93 */ + { 238, 32715, 10809, 32349 }, + { 32767, 32767, 32767, 0 }, + 0, 69, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 94 */ + { 1902, 32715, 18820, 31476 }, + { 32767, 32767, 32767, 0 }, + 0, 69, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 95 */ + { 3804, 32715, 18820, 23749 }, + { 1268, 130, 0, 0 }, + 0, 69, 495, 0, 1200, 11690, 0, 4, 0 + }, + { /* articulation 96 */ + { 19021, 32618, 15076, 31476 }, + { 32767, 32767, 32767, 0 }, + 0, 72, 1091, 0, 0, 11919, 1, 0, 0 + }, + { /* articulation 97 */ + { 32767, 0, 32767, 32715 }, + { 190, 32767, 32767, 0 }, + 0, 0, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 98 */ + { 32767, 32072, 0, 32072 }, + { 32767, 317, 0, 0 }, + 0, 0, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 99 */ + { 32767, 32663, 0, 27897 }, + { 634, 95, 13107, 0 }, + 0, 69, 495, 0, 3200, 8321, 0, 0, 0 + }, + { /* articulation 100 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 101 */ + { 32767, 32418, 0, 27897 }, + { 32767, 543, 0, 0 }, + 0, 69, 495, 0, 8187, 5535, 0, 5, 0 + }, + { /* articulation 102 */ + { 19021, 32663, 0, 31056 }, + { 32767, 95, 7667, 0 }, + 5, 0, 495, 0, 6053, 5535, 0, 5, 0 + }, + { /* articulation 103 */ + { 32767, 32715, 18820, 27897 }, + { 951, 48, 0, 0 }, + 0, 0, 495, 0, 2700, 9852, 0, 0, 0 + }, + { /* articulation 104 */ + { 32767, 32715, 18820, 30234 }, + { 951, 48, 0, 0 }, + 0, 0, 495, 0, 2700, 9852, 0, 0, 0 + }, + { /* articulation 105 */ + { 32767, 32715, 18820, 27897 }, + { 32767, 634, 0, 0 }, + 0, 103, 476, 0, 2500, 10490, 1, 8, 0 + }, + { /* articulation 106 */ + { 32767, 32715, 23493, 27897 }, + { 32767, 190, 0, 0 }, + 0, 69, 494, 0, 4000, 10223, 1, 4, 0 + }, + { /* articulation 107 */ + { 32767, 32715, 18820, 30234 }, + { 32767, 63, 7667, 0 }, + 0, 0, 495, 0, 1813, 9154, 0, 0, 0 + }, + { /* articulation 108 */ + { 19021, 32245, 0, 32245 }, + { 32767, 190, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 109 */ + { 32767, 31964, 0, 31605 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 11690, 0, 0, 0 + }, + { /* articulation 110 */ + { 32767, 31730, 0, 31730 }, + { 32767, 190, 0, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 111 */ + { 32767, 32558, 18820, 30234 }, + { 32767, 48, 0, 0 }, + 12, 69, 476, 0, 3000, 10223, 0, 0, 0 + }, + { /* articulation 112 */ + { 32767, 32558, 18820, 30234 }, + { 32767, 32, 0, 0 }, + 12, 69, 476, 0, 1900, 10031, 0, 0, 0 + }, + { /* articulation 113 */ + { 32767, 32715, 18820, 29434 }, + { 32767, 32, 0, 0 }, + 12, 69, 494, 0, 1000, 11107, 0, 0, 0 + }, + { /* articulation 114 */ + { 32767, 32715, 18820, 29434 }, + { 32767, 32, 0, 0 }, + 12, 69, 494, 0, 2000, 11107, 0, 0, 0 + }, + { /* articulation 115 */ + { 32767, 32636, 0, 29434 }, + { 32767, 95, 0, 0 }, + 0, 34, 495, 0, 4000, 8321, 0, 0, 0 + }, + { /* articulation 116 */ + { 32767, 32297, 19893, 17213 }, + { 32767, 238, 0, 0 }, + 0, 69, 726, 0, 0, 11919, 0, 0, 0 + }, + { /* articulation 117 */ + { 9511, 32418, 23493, 17213 }, + { 32767, 32767, 32767, 0 }, + 0, 69, 678, 0, 0, 11877, 1, 0, 0 + }, + { /* articulation 118 */ + { 32767, 32618, 0, 27897 }, + { 32767, 95, 0, 0 }, + 0, 69, 495, 0, 3500, 9023, 0, 0, 0 + }, + { /* articulation 119 */ + { 32767, 23749, 23493, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 34, 761, 0, 0, 10925, 1, 0, 0 + }, + { /* articulation 120 */ + { 32767, 32636, 0, 29434 }, + { 32767, 95, 0, 0 }, + 0, 103, 495, 0, 3200, 8721, 0, 4, 0 + }, + { /* articulation 121 */ + { 1902, 32715, 18820, 27897 }, + { 32767, 32767, 32767, 0 }, + 0, 69, 495, 0, 0, 0, 1, 0, 0 + }, + { /* articulation 122 */ + { 4755, 32715, 18820, 28809 }, + { 32767, 32767, 32767, 0 }, + 0, 69, 495, 0, 0, 11877, 0, 8, 0 + }, + { /* articulation 123 */ + { 32767, 32715, 18820, 27897 }, + { 32767, 16, 0, 0 }, + 0, 34, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 124 */ + { 32767, 32663, 0, 27897 }, + { 32767, 190, 0, 0 }, + 0, 69, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 125 */ + { 32767, 32715, 18820, 27897 }, + { 32767, 12, 0, 0 }, + 0, 34, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 126 */ + { 32767, 31730, 0, 31730 }, + { 32767, 380, 0, 0 }, + 0, 0, 495, 0, 3000, 10223, 0, 8, 0 + }, + { /* articulation 127 */ + { 63, 0, 32767, 32558 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 761, 0, 0, 11423, 4, 0, 0 + }, + { /* articulation 128 */ + { 476, 32595, 0, 32577 }, + { 32767, 10, 0, 0 }, + 0, 0, 495, 0, 0, 11423, 0, 0, 0 + }, + { /* articulation 129 */ + { 196, 0, 0, 31964 }, + { 95, 32767, 32767, 0 }, + 0, 0, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 130 */ + { 32767, 31730, 0, 31730 }, + { 32767, 380, 0, 0 }, + 0, 0, 495, 1200, 0, 0, 0, 0, 0 + }, + { /* articulation 131 */ + { 32767, 32245, 0, 32349 }, + { 32767, 190, 0, 0 }, + 0, 0, 495, 50, 0, 0, 0, 0, 0 + }, + { /* articulation 132 */ + { 32767, 32418, 0, 32418 }, + { 32767, 9511, 0, 0 }, + 0, 0, 495, 0, 4700, 7769, 0, 0, 0 + }, + { /* articulation 133 */ + { 32767, 31391, 0, 31391 }, + { 32767, 19021, 0, 0 }, + 0, 0, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 134 */ + { 32767, 32663, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 135 */ + { 32767, 32715, 18820, 23749 }, + { 32767, 95, 0, 0 }, + 10, 68, 476, 0, 2000, 10696, 0, 0, 0 + }, + { /* articulation 136 */ + { 32767, 32715, 10809, 23749 }, + { 32767, 95, 0, 0 }, + 12, 69, 491, 0, 0, 10910, 0, 0, 0 + }, + { /* articulation 137 */ + { 32767, 32715, 18820, 23749 }, + { 32767, 95, 0, 0 }, + 10, 69, 476, 0, 1200, 10218, 0, 0, 0 + }, + { /* articulation 138 */ + { 19021, 32715, 18820, 23749 }, + { 32767, 95, 0, 0 }, + 10, 69, 476, 0, 1100, 9525, 0, 0, 0 + }, + { /* articulation 139 */ + { 9511, 32663, 18820, 27897 }, + { 32767, 10, 0, 0 }, + 10, 69, 494, 0, 2000, 10962, 0, 0, 0 + }, + { /* articulation 140 */ + { 32767, 32558, 18820, 27897 }, + { 9511, 317, 0, 0 }, + 10, 63, 504, 0, 1200, 10090, 0, 0, 0 + }, + { /* articulation 141 */ + { 1268, 0, 32767, 30234 }, + { 951, 190, 0, 0 }, + 7, 69, 494, 0, 1620, 8933, 0, 0, 0 + }, + { /* articulation 142 */ + { 32767, 32558, 10809, 27897 }, + { 19021, 190, 0, 0 }, + 7, 69, 494, 0, 2200, 8994, 0, 0, 0 + }, + { /* articulation 143 */ + { 32767, 32715, 15076, 27897 }, + { 32767, 951, 0, 0 }, + 10, 69, 491, 0, 2500, 9525, 0, 0, 0 + }, + { /* articulation 144 */ + { 32767, 32715, 15076, 27897 }, + { 32767, 95, 0, 0 }, + 10, 69, 476, 0, 1500, 11423, 0, 0, 0 + }, + { /* articulation 145 */ + { 32767, 32715, 18820, 27897 }, + { 32767, 951, 0, 0 }, + 9, 69, 491, 0, 1500, 9521, 0, 0, 0 + }, + { /* articulation 146 */ + { 1902, 0, 32767, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 761, 0, 0, 9521, 0, 0, 0 + }, + { /* articulation 147 */ + { 32767, 32663, 0, 27897 }, + { 32767, 9511, 0, 0 }, + 0, 34, 495, 0, 5000, 10223, 0, 0, 0 + }, + { /* articulation 148 */ + { 32767, 32715, 18820, 27897 }, + { 32767, 32, 0, 0 }, + 10, 69, 476, 0, 1500, 9907, 0, 0, 0 + }, + { /* articulation 149 */ + { 32767, 32733, 11682, 27897 }, + { 32767, 951, 0, 0 }, + 0, 69, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 150 */ + { 32767, 32418, 0, 32418 }, + { 32767, 190, 0, 0 }, + 0, 34, 495, 0, 3440, 9260, 0, 0, 0 + }, + { /* articulation 151 */ + { 32767, 31476, 0, 31730 }, + { 32767, 951, 0, 0 }, + 0, 34, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 152 */ + { 32767, 32245, 0, 31730 }, + { 32767, 190, 0, 0 }, + 0, 34, 495, 0, 4000, 7823, 0, 0, 0 + }, + { /* articulation 153 */ + { 32767, 32663, 3566, 27897 }, + { 391, 32767, 32767, 0 }, + 100, 0, 761, 500, 0, 11877, 0, 0, 0 + }, + { /* articulation 154 */ + { 32767, 32715, 18820, 23749 }, + { 32767, 951, 0, 0 }, + 8, 69, 495, -22, 0, 0, 0, 0, 0 + }, + { /* articulation 155 */ + { 9511, 30830, 6784, 27897 }, + { 32767, 951, 0, 0 }, + 0, 69, 476, 0, 5000, 9521, 1, 0, 0 + }, + { /* articulation 156 */ + { 32767, 32663, 0, 32349 }, + { 951, 127, 16384, 0 }, + 0, 103, 495, 0, 3627, 10547, 0, 5, 0 + }, + { /* articulation 157 */ + { 1902, 0, 32767, 27897 }, + { 951, 951, 0, 0 }, + 0, 69, 495, 27, 0, 11919, 0, 0, 0 + }, + { /* articulation 158 */ + { 32767, 0, 32767, 32245 }, + { 38, 33, 10092, 0 }, + 5, 0, 495, 0, 8007, 5535, 0, 8, 0 + }, + { /* articulation 159 */ + { 32767, 32618, 0, 31056 }, + { 32767, 63, 0, 0 }, + 0, 103, 495, 0, 2500, 9032, 0, 0, 0 + }, + { /* articulation 160 */ + { 4755, 32715, 10809, 28809 }, + { 32767, 32767, 32767, 0 }, + 0, 69, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 161 */ + { 9511, 32663, 18820, 27897 }, + { 32767, 95, 0, 0 }, + 10, 69, 494, 0, 2600, 9513, 0, 0, 0 + }, + { /* articulation 162 */ + { 32767, 32435, 9568, 27897 }, + { 1174, 196, 0, 0 }, + 10, 103, 490, 0, 6500, 9023, 0, 0, 0 + }, + { /* articulation 163 */ + { 32767, 32663, 0, 29434 }, + { 32767, 32, 0, 0 }, + 0, 69, 495, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 164 */ + { 32767, 32418, 15076, 23749 }, + { 32767, 634, 0, 0 }, + 0, 0, 476, 0, 2000, 10223, 0, 0, 0 + }, + { /* articulation 165 */ + { 32767, 32663, 0, 27897 }, + { 32767, 190, 0, 0 }, + 0, 69, 495, 0, 3000, 9366, 0, 0, 0 + }, + { /* articulation 166 */ + { 32767, 32715, 18820, 27897 }, + { 951, 64, 10879, 0 }, + 0, 0, 495, 0, 6000, 7121, 0, 4, 0 + }, + { /* articulation 167 */ + { 32767, 32636, 0, 29434 }, + { 32767, 10, 0, 0 }, + 0, 103, 495, 0, 3500, 6236, 0, 5, 0 + }, + { /* articulation 168 */ + { 32767, 32636, 0, 29434 }, + { 32767, 95, 0, 0 }, + 0, 103, 495, 0, 2800, 7121, 0, 0, 0 + }, + { /* articulation 169 */ + { 32767, 32593, 0, 31056 }, + { 32767, 63, 0, 0 }, + 0, 103, 495, 0, 2100, 9626, 0, 0, 0 + }, + { /* articulation 170 */ + { 32767, 32558, 0, 31476 }, + { 32767, 63, 0, 0 }, + 0, 103, 495, 0, 3000, 9626, 0, 0, 0 + }, + { /* articulation 171 */ + { 32767, 32527, 0, 30506 }, + { 32767, 63, 0, 0 }, + 0, 103, 495, 0, 1000, 9032, 0, 0, 0 + }, + { /* articulation 172 */ + { 32767, 32418, 0, 30725 }, + { 32767, 63, 0, 0 }, + 0, 103, 495, 0, 1000, 9032, 0, 0, 0 + }, + { /* articulation 173 */ + { 1902, 32418, 15076, 23749 }, + { 32767, 634, 0, 0 }, + 0, 103, 496, 0, 0, 11107, 0, 8, 0 + }, + { /* articulation 174 */ + { 32767, 32558, 15076, 27897 }, + { 3804, 73, 0, 0 }, + 0, 0, 495, 0, 4500, 9521, 0, 8, 0 + }, + { /* articulation 175 */ + { 32767, 32715, 18820, 27897 }, + { 32767, 48, 0, 0 }, + 0, 0, 495, 0, 2000, 8321, 0, 8, 0 + }, + { /* articulation 176 */ + { 32767, 32742, 128, 31180 }, + { 32767, 865, 0, 0 }, + 0, 0, 495, 0, 6000, 7823, 0, 8, 0 + }, + { /* articulation 177 */ + { 9511, 32608, 0, 32322 }, + { 32767, 48, 0, 0 }, + 0, 0, 495, 0, 4500, 7121, 0, 8, 0 + }, + { /* articulation 178 */ + { 19021, 32664, 3646, 32436 }, + { 32767, 95, 0, 0 }, + 0, 0, 495, 0, 4000, 8321, 0, 8, 0 + }, + { /* articulation 179 */ + { 32767, 32685, 13644, 29434 }, + { 32767, 32, 0, 0 }, + 12, 69, 494, 0, 2000, 11107, 0, 0, 0 + }, + { /* articulation 180 */ + { 9511, 31605, 0, 27897 }, + { 32767, 951, 0, 0 }, + 0, 0, 495, 0, 5000, 8321, 1, 0, 0 + }, + { /* articulation 181 */ + { 130, 32617, 0, 32350 }, + { 32767, 317, 0, 0 }, + 0, 69, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 182 */ + { 32767, 32593, 0, 32251 }, + { 1174, 20, 0, 0 }, + 0, 69, 495, 0, 3600, 7121, 0, 4, 0 + }, + { /* articulation 183 */ + { 32767, 32427, 0, 32427 }, + { 32767, 317, 0, 0 }, + 0, 69, 476, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 184 */ + { 834, 32742, 19242, 31455 }, + { 32767, 148, 0, 0 }, + 0, 0, 778, 0, 3000, 9907, 0, 4, 0 + } +}; /*end Articulations */ + +/*---------------------------------------------------------------------------- + * Regions + *---------------------------------------------------------------------------- +*/ +const S_WT_REGION eas_regions[] = +{ + { { 0, 27, 27 }, -4068, 16422, 0, 0, 81, 0 }, /* region 0 */ + { { 0, 28, 28 }, -4768, 32767, 0, 0, 40, 0 }, /* region 1 */ + { { 0, 29, 29 }, -5753, 32767, 0, 0, 32, 1 }, /* region 2 */ + { { 0, 30, 30 }, -6053, 32767, 0, 0, 32, 2 }, /* region 3 */ + { { 0, 31, 31 }, -5068, 23197, 0, 0, 48, 3 }, /* region 4 */ + { { 1536, 32, 32 }, -4400, 20675, 0, 0, 137, 4 }, /* region 5 */ + { { 1537, 33, 33 }, -4903, 20675, 792, 879, 50, 5 }, /* region 6 */ + { { 1537, 34, 34 }, -5003, 16422, 792, 879, 50, 6 }, /* region 7 */ + { { 0, 35, 35 }, -6168, 32767, 0, 0, 83, 7 }, /* region 8 */ + { { 0, 36, 36 }, -6168, 32767, 0, 0, 83, 7 }, /* region 9 */ + { { 0, 37, 37 }, -5251, 18426, 0, 0, 53, 8 }, /* region 10 */ + { { 0, 38, 38 }, -5351, 23197, 0, 0, 16, 9 }, /* region 11 */ + { { 0, 39, 39 }, -4768, 32767, 0, 0, 40, 10 }, /* region 12 */ + { { 0, 40, 40 }, -5351, 23197, 0, 0, 16, 4 }, /* region 13 */ + { { 1, 41, 41 }, -7055, 26028, 798, 993, 45, 11 }, /* region 14 */ + { { 257, 42, 42 }, -5400, 26028, 4288, 7488, 7, 12 }, /* region 15 */ + { { 1, 43, 43 }, -6955, 26028, 798, 993, 45, 13 }, /* region 16 */ + { { 257, 44, 44 }, -5600, 26028, 4288, 7488, 7, 14 }, /* region 17 */ + { { 1, 45, 45 }, -6955, 26028, 798, 993, 45, 15 }, /* region 18 */ + { { 257, 46, 46 }, -5800, 26028, 4288, 7488, 7, 16 }, /* region 19 */ + { { 1, 47, 47 }, -6655, 26028, 798, 993, 45, 17 }, /* region 20 */ + { { 1, 48, 48 }, -6555, 26028, 798, 993, 45, 18 }, /* region 21 */ + { { 1, 49, 49 }, -6400, 16422, 1294, 5778, 8, 19 }, /* region 22 */ + { { 1, 50, 50 }, -6455, 26028, 798, 993, 45, 20 }, /* region 23 */ + { { 1, 51, 51 }, -6468, 16422, 6592, 9921, 6, 21 }, /* region 24 */ + { { 1, 52, 52 }, -6800, 32767, 1294, 5778, 8, 22 }, /* region 25 */ + { { 1, 53, 53 }, -6618, 14636, 6592, 9921, 6, 23 }, /* region 26 */ + { { 0, 54, 54 }, -6951, 26028, 0, 0, 39, 24 }, /* region 27 */ + { { 1, 55, 55 }, -6500, 32767, 1294, 5778, 8, 25 }, /* region 28 */ + { { 0, 56, 56 }, -8455, 32767, 0, 0, 90, 26 }, /* region 29 */ + { { 1, 57, 57 }, -6900, 32767, 1294, 5778, 8, 27 }, /* region 30 */ + { { 1, 58, 58 }, -8253, 23197, 0, 166, 113, 28 }, /* region 31 */ + { { 1, 59, 59 }, -7168, 16422, 6592, 9921, 6, 29 }, /* region 32 */ + { { 1, 60, 60 }, -7653, 23197, 432, 582, 63, 30 }, /* region 33 */ + { { 1, 61, 61 }, -8053, 16422, 432, 582, 63, 30 }, /* region 34 */ + { { 1, 62, 62 }, -8453, 20675, 432, 582, 63, 31 }, /* region 35 */ + { { 1, 63, 63 }, -8553, 23197, 432, 582, 63, 32 }, /* region 36 */ + { { 1, 64, 64 }, -9153, 23197, 432, 582, 63, 33 }, /* region 37 */ + { { 0, 65, 65 }, -8755, 32767, 0, 0, 14, 34 }, /* region 38 */ + { { 0, 66, 66 }, -9155, 20675, 0, 0, 14, 34 }, /* region 39 */ + { { 512, 67, 67 }, -8355, 18426, 0, 0, 90, 35 }, /* region 40 */ + { { 512, 68, 68 }, -8955, 18426, 0, 0, 90, 35 }, /* region 41 */ + { { 0, 69, 69 }, -8955, 32767, 0, 0, 86, 36 }, /* region 42 */ + { { 0, 70, 70 }, -8055, 21900, 0, 0, 86, 37 }, /* region 43 */ + { { 769, 71, 71 }, -7555, 23197, 0, 1226, 35, 38 }, /* region 44 */ + { { 769, 72, 72 }, -8155, 26028, 0, 1226, 35, 38 }, /* region 45 */ + { { 1024, 73, 73 }, -9155, 32767, 0, 0, 22, 39 }, /* region 46 */ + { { 1024, 74, 74 }, -9655, 32767, 0, 0, 22, 40 }, /* region 47 */ + { { 1, 75, 75 }, -9100, 23197, 0, 31, 139, 41 }, /* region 48 */ + { { 0, 76, 76 }, -11655, 23197, 0, 0, 134, 42 }, /* region 49 */ + { { 0, 77, 77 }, -11255, 23197, 0, 0, 134, 43 }, /* region 50 */ + { { 0, 78, 78 }, -10053, 16422, 0, 0, 89, 44 }, /* region 51 */ + { { 0, 79, 79 }, -11453, 16422, 0, 0, 89, 45 }, /* region 52 */ + { { 1281, 80, 80 }, -7500, 13045, 209, 230, 103, 46 }, /* region 53 */ + { { 1281, 81, 81 }, -7600, 16422, 209, 230, 103, 47 }, /* region 54 */ + { { 0, 82, 82 }, -9655, 20675, 0, 0, 87, 48 }, /* region 55 */ + { { 0, 83, 83 }, -10100, 32767, 0, 0, 13, 49 }, /* region 56 */ + { { 1, 84, 84 }, -9600, 23197, 0, 10294, 5, 50 }, /* region 57 */ + { { 0, 85, 85 }, -10855, 32767, 0, 0, 135, 4 }, /* region 58 */ + { { 0, 86, 86 }, -10268, 16422, 0, 0, 24, 51 }, /* region 59 */ + { { 32769, 87, 87 }, -10368, 32767, 1335, 1603, 24, 52 }, /* region 60 */ + { { 1, 12, 67 }, -7805, 23197, 437, 16584, 2, 48 }, /* region 61 */ + { { 1, 68, 73 }, -8396, 23197, 452, 16803, 0, 48 }, /* region 62 */ + { { 32769, 74, 108 }, -9667, 23197, 404, 16698, 1, 48 }, /* region 63 */ + { { 1, 12, 78 }, -7805, 16422, 437, 16584, 2, 48 }, /* region 64 */ + { { 1, 79, 91 }, -8396, 16422, 452, 16803, 0, 48 }, /* region 65 */ + { { 32769, 92, 108 }, -9667, 16422, 404, 16698, 1, 48 }, /* region 66 */ + { { 1, 12, 78 }, -7805, 16422, 437, 16584, 2, 48 }, /* region 67 */ + { { 1, 79, 91 }, -8396, 16422, 452, 16803, 0, 48 }, /* region 68 */ + { { 32769, 92, 108 }, -9667, 16422, 404, 16698, 1, 48 }, /* region 69 */ + { { 1, 12, 70 }, -7800, 23197, 437, 16584, 2, 48 }, /* region 70 */ + { { 1, 71, 88 }, -8391, 23197, 452, 16803, 0, 48 }, /* region 71 */ + { { 32769, 89, 108 }, -9662, 23197, 404, 16698, 1, 48 }, /* region 72 */ + { { 1, 12, 54 }, -7156, 13045, 639, 4368, 10, 48 }, /* region 73 */ + { { 32769, 55, 108 }, -7551, 18426, 702, 3112, 12, 48 }, /* region 74 */ + { { 1, 12, 66 }, -7811, 23197, 437, 16584, 2, 48 }, /* region 75 */ + { { 1, 67, 87 }, -8402, 23197, 452, 16803, 0, 48 }, /* region 76 */ + { { 32769, 88, 108 }, -9673, 16422, 404, 16698, 1, 48 }, /* region 77 */ + { { 1, 12, 43 }, -4255, 23197, 920, 1383, 30, 59 }, /* region 78 */ + { { 32769, 44, 96 }, -6260, 18426, 885, 1176, 37, 59 }, /* region 79 */ + { { 1, 12, 48 }, -4661, 18426, 1148, 1514, 26, 60 }, /* region 80 */ + { { 32769, 49, 96 }, -7453, 16422, 1347, 1420, 29, 60 }, /* region 81 */ + { { 1, 33, 56 }, -6800, 26028, 1064, 1170, 38, 61 }, /* region 82 */ + { { 1, 57, 72 }, -7200, 26028, 930, 1014, 44, 61 }, /* region 83 */ + { { 32769, 73, 108 }, -8800, 26028, 726, 826, 52, 61 }, /* region 84 */ + { { 1, 36, 96 }, -8800, 20675, 635, 735, 58, 62 }, /* region 85 */ + { { 32769, 97, 108 }, -11308, 13045, 0, 31, 139, 62 }, /* region 86 */ + { { 1, 36, 96 }, -8800, 14636, 635, 735, 58, 0 }, /* region 87 */ + { { 32769, 97, 108 }, -11308, 13045, 0, 31, 139, 0 }, /* region 88 */ + { { 1, 36, 83 }, -7206, 13045, 838, 922, 47, 63 }, /* region 89 */ + { { 1, 84, 93 }, -9606, 14636, 209, 230, 103, 63 }, /* region 90 */ + { { 32769, 94, 108 }, -11308, 13045, 0, 31, 139, 63 }, /* region 91 */ + { { 1, 36, 83 }, -7206, 13045, 838, 922, 47, 64 }, /* region 92 */ + { { 1, 84, 93 }, -9606, 13045, 209, 230, 103, 64 }, /* region 93 */ + { { 32769, 94, 108 }, -11308, 13045, 0, 31, 139, 64 }, /* region 94 */ + { { 1, 21, 56 }, -6795, 23197, 1064, 1170, 38, 65 }, /* region 95 */ + { { 1, 57, 72 }, -7195, 23197, 930, 1014, 44, 65 }, /* region 96 */ + { { 32769, 73, 108 }, -8798, 23197, 726, 826, 52, 65 }, /* region 97 */ + { { 1, 12, 83 }, -7206, 16422, 838, 922, 47, 66 }, /* region 98 */ + { { 1, 84, 93 }, -9606, 16422, 209, 230, 103, 66 }, /* region 99 */ + { { 32769, 94, 108 }, -11308, 16422, 0, 31, 139, 66 }, /* region 100 */ + { { 1, 24, 83 }, -7206, 16422, 838, 922, 47, 67 }, /* region 101 */ + { { 1, 84, 93 }, -9606, 16422, 209, 230, 103, 67 }, /* region 102 */ + { { 32769, 94, 108 }, -11308, 16422, 0, 31, 139, 67 }, /* region 103 */ + { { 1, 12, 83 }, -7220, 16422, 0, 83, 126, 68 }, /* region 104 */ + { { 1, 84, 90 }, -9682, 16422, 0, 20, 145, 68 }, /* region 105 */ + { { 32769, 91, 108 }, -10301, 16422, 6, 20, 147, 68 }, /* region 106 */ + { { 1, 21, 75 }, -8441, 16422, 419, 460, 76, 69 }, /* region 107 */ + { { 32769, 76, 108 }, -10890, 14636, 254, 264, 101, 69 }, /* region 108 */ + { { 32769, 36, 84 }, -8955, 16422, 0, 2775, 17, 70 }, /* region 109 */ + { { 32769, 12, 108 }, -7855, 23197, 30, 276, 100, 71 }, /* region 110 */ + { { 0, 12, 60 }, -9114, 26028, 0, 0, 15, 72 }, /* region 111 */ + { { 32768, 61, 96 }, -9114, 26028, 0, 0, 15, 73 }, /* region 112 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 74 }, /* region 113 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 74 }, /* region 114 */ + { { 1, 12, 35 }, -6555, 16422, 2869, 3778, 11, 75 }, /* region 115 */ + { { 1, 36, 48 }, -7755, 20675, 2869, 3778, 11, 75 }, /* region 116 */ + { { 32769, 49, 72 }, -7755, 20675, 2869, 3778, 11, 76 }, /* region 117 */ + { { 1, 16, 55 }, -7424, 20675, 1045, 1119, 41, 77 }, /* region 118 */ + { { 32769, 56, 96 }, -7918, 20675, 907, 963, 46, 77 }, /* region 119 */ + { { 1, 16, 53 }, -7194, 29204, 1140, 1479, 27, 78 }, /* region 120 */ + { { 1, 54, 70 }, -8371, 29204, 726, 812, 55, 78 }, /* region 121 */ + { { 32769, 71, 108 }, -8988, 29204, 718, 748, 56, 78 }, /* region 122 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 79 }, /* region 123 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 79 }, /* region 124 */ + { { 1, 16, 54 }, -6927, 20675, 5362, 5461, 9, 80 }, /* region 125 */ + { { 1, 55, 63 }, -7051, 26028, 1362, 1454, 28, 80 }, /* region 126 */ + { { 32769, 64, 108 }, -7944, 16422, 311, 366, 88, 80 }, /* region 127 */ + { { 1, 16, 48 }, -5998, 20675, 1132, 1301, 31, 81 }, /* region 128 */ + { { 32769, 49, 108 }, -7188, 20675, 1099, 1184, 36, 81 }, /* region 129 */ + { { 1, 21, 68 }, -9658, 20675, 87, 2170, 18, 82 }, /* region 130 */ + { { 1, 69, 82 }, -10160, 20675, 120, 2167, 19, 82 }, /* region 131 */ + { { 32769, 83, 108 }, -11360, 20675, 376, 2041, 20, 82 }, /* region 132 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 83 }, /* region 133 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 83 }, /* region 134 */ + { { 32769, 55, 108 }, -8568, 20675, 0, 477, 75, 84 }, /* region 135 */ + { { 32769, 36, 96 }, -8100, 14636, 101, 151, 116, 85 }, /* region 136 */ + { { 1, 24, 83 }, -7220, 13045, 0, 83, 126, 86 }, /* region 137 */ + { { 1, 84, 90 }, -9682, 13045, 0, 20, 145, 86 }, /* region 138 */ + { { 32769, 91, 108 }, -10301, 13045, 6, 20, 147, 86 }, /* region 139 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 87 }, /* region 140 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 87 }, /* region 141 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 88 }, /* region 142 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 88 }, /* region 143 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 89 }, /* region 144 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 89 }, /* region 145 */ + { { 1, 24, 83 }, -7220, 13045, 0, 83, 126, 90 }, /* region 146 */ + { { 1, 84, 90 }, -9682, 13045, 0, 20, 145, 90 }, /* region 147 */ + { { 32769, 91, 108 }, -10301, 13045, 6, 20, 147, 90 }, /* region 148 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 91 }, /* region 149 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 91 }, /* region 150 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 92 }, /* region 151 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 92 }, /* region 152 */ + { { 1, 12, 62 }, -8253, 16422, 23, 10953, 4, 93 }, /* region 153 */ + { { 32769, 63, 108 }, -8955, 20675, 11, 11753, 3, 93 }, /* region 154 */ + { { 1, 12, 62 }, -8253, 16422, 23, 10953, 4, 94 }, /* region 155 */ + { { 32769, 63, 108 }, -8955, 16422, 11, 11753, 3, 94 }, /* region 156 */ + { { 1, 24, 79 }, -7220, 13045, 0, 83, 126, 95 }, /* region 157 */ + { { 1, 80, 90 }, -9682, 13045, 0, 20, 145, 95 }, /* region 158 */ + { { 32769, 91, 108 }, -10301, 13045, 6, 20, 147, 95 }, /* region 159 */ + { { 1, 12, 65 }, -8253, 13045, 23, 10953, 4, 96 }, /* region 160 */ + { { 32769, 66, 108 }, -8955, 16422, 11, 11753, 3, 96 }, /* region 161 */ + { { 32768, 36, 84 }, -8700, 20675, 0, 0, 25, 97 }, /* region 162 */ + { { 32769, 36, 96 }, -10055, 20675, 1482, 1613, 23, 98 }, /* region 163 */ + { { 32769, 12, 96 }, -5566, 32767, 818, 1033, 42, 99 }, /* region 164 */ + { { 32769, 36, 84 }, -9768, 18426, 0, 293, 98, 100 }, /* region 165 */ + { { 32769, 12, 96 }, -7220, 26028, 0, 83, 125, 101 }, /* region 166 */ + { { 32769, 12, 96 }, -7220, 20675, 0, 83, 125, 102 }, /* region 167 */ + { { 1, 12, 83 }, -7220, 13045, 0, 83, 125, 104 }, /* region 168 */ + { { 1, 84, 90 }, -9682, 13045, 0, 20, 146, 104 }, /* region 169 */ + { { 32769, 91, 108 }, -10301, 13045, 6, 20, 148, 104 }, /* region 170 */ + { { 32769, 36, 108 }, -9770, 32767, 472, 491, 74, 105 }, /* region 171 */ + { { 32769, 36, 108 }, -9770, 20675, 472, 491, 74, 106 }, /* region 172 */ + { { 1, 12, 72 }, -7212, 7336, 2, 86, 124, 107 }, /* region 173 */ + { { 1, 73, 101 }, -9700, 8231, 2, 22, 143, 107 }, /* region 174 */ + { { 32769, 102, 108 }, -10883, 20675, 173, 183, 110, 107 }, /* region 175 */ + { { 1, 21, 96 }, -8968, 13045, 477, 507, 73, 108 }, /* region 176 */ + { { 32769, 97, 108 }, -10883, 13045, 173, 183, 110, 109 }, /* region 177 */ + { { 32769, 12, 108 }, -8971, 16422, 477, 507, 73, 110 }, /* region 178 */ + { { 1, 12, 53 }, -6171, 16422, 388, 541, 68, 111 }, /* region 179 */ + { { 32769, 54, 60 }, -7149, 11626, 473, 560, 65, 111 }, /* region 180 */ + { { 32769, 36, 72 }, -7149, 16422, 473, 560, 65, 112 }, /* region 181 */ + { { 1, 48, 58 }, -8253, 16422, 356, 402, 82, 113 }, /* region 182 */ + { { 1, 59, 65 }, -8774, 16422, 514, 548, 67, 113 }, /* region 183 */ + { { 1, 66, 78 }, -9374, 16422, 505, 529, 71, 113 }, /* region 184 */ + { { 32769, 79, 96 }, -10433, 16422, 178, 191, 109, 113 }, /* region 185 */ + { { 1, 55, 60 }, -8253, 16422, 356, 402, 82, 114 }, /* region 186 */ + { { 1, 61, 69 }, -8774, 16422, 514, 548, 67, 114 }, /* region 187 */ + { { 1, 70, 79 }, -9374, 16422, 505, 529, 71, 114 }, /* region 188 */ + { { 32769, 80, 108 }, -10433, 16422, 178, 191, 109, 114 }, /* region 189 */ + { { 1, 16, 82 }, -9229, 23197, 180, 206, 106, 115 }, /* region 190 */ + { { 32769, 83, 108 }, -8440, 18426, 3, 44, 131, 115 }, /* region 191 */ + { { 32769, 21, 108 }, -10069, 20675, 483, 515, 72, 116 }, /* region 192 */ + { { 1, 21, 89 }, -8405, 18426, 3, 45, 130, 117 }, /* region 193 */ + { { 32769, 90, 108 }, -10301, 10362, 6, 20, 148, 117 }, /* region 194 */ + { { 1, 21, 42 }, -5886, 20675, 0, 180, 111, 118 }, /* region 195 */ + { { 1, 43, 51 }, -6486, 23197, 0, 127, 120, 118 }, /* region 196 */ + { { 1, 52, 58 }, -7492, 26028, 0, 71, 127, 118 }, /* region 197 */ + { { 1, 59, 68 }, -8668, 23197, 0, 36, 136, 118 }, /* region 198 */ + { { 32769, 69, 108 }, -9774, 20675, 0, 19, 149, 118 }, /* region 199 */ + { { 1, 21, 89 }, -8399, 20675, 3, 45, 130, 119 }, /* region 200 */ + { { 32769, 90, 108 }, -10301, 14636, 6, 20, 148, 119 }, /* region 201 */ + { { 1, 21, 46 }, -6851, 26028, 236, 340, 92, 120 }, /* region 202 */ + { { 1, 47, 71 }, -7763, 20675, 824, 885, 49, 120 }, /* region 203 */ + { { 1, 72, 88 }, -9107, 18426, 719, 747, 57, 120 }, /* region 204 */ + { { 1, 89, 93 }, -10076, 16422, 83, 99, 122, 120 }, /* region 205 */ + { { 32769, 94, 108 }, -10889, 16422, 173, 183, 110, 120 }, /* region 206 */ + { { 1, 60, 71 }, -8405, 16422, 0, 42, 132, 121 }, /* region 207 */ + { { 1, 72, 78 }, -9103, 16422, 0, 28, 141, 121 }, /* region 208 */ + { { 32769, 79, 96 }, -9605, 16422, 0, 21, 144, 121 }, /* region 209 */ + { { 1, 48, 65 }, -7516, 11626, 0, 70, 128, 122 }, /* region 210 */ + { { 1, 66, 79 }, -8924, 14636, 0, 31, 138, 122 }, /* region 211 */ + { { 32769, 80, 96 }, -9230, 11626, 0, 26, 142, 122 }, /* region 212 */ + { { 1, 16, 44 }, -7068, 14636, 163, 254, 102, 123 }, /* region 213 */ + { { 1, 45, 51 }, -7618, 16422, 261, 393, 85, 123 }, /* region 214 */ + { { 1, 52, 58 }, -8533, 18426, 190, 229, 104, 123 }, /* region 215 */ + { { 1, 59, 66 }, -9300, 18426, 168, 193, 108, 123 }, /* region 216 */ + { { 1, 67, 70 }, -9776, 18426, 138, 157, 115, 123 }, /* region 217 */ + { { 1, 71, 80 }, -10303, 18426, 166, 180, 112, 123 }, /* region 218 */ + { { 32769, 81, 108 }, -11274, 18426, 135, 151, 117, 123 }, /* region 219 */ + { { 32769, 12, 96 }, -6204, 23197, 570, 719, 59, 124 }, /* region 220 */ + { { 1, 12, 48 }, -7068, 14636, 163, 254, 102, 125 }, /* region 221 */ + { { 1, 49, 54 }, -7618, 16422, 261, 393, 85, 125 }, /* region 222 */ + { { 1, 55, 63 }, -8533, 18426, 190, 229, 104, 125 }, /* region 223 */ + { { 1, 64, 70 }, -9300, 18426, 168, 193, 108, 125 }, /* region 224 */ + { { 1, 71, 75 }, -9776, 18426, 138, 157, 115, 125 }, /* region 225 */ + { { 1, 76, 82 }, -10303, 18426, 166, 180, 112, 125 }, /* region 226 */ + { { 32769, 83, 108 }, -11274, 18426, 135, 151, 117, 125 }, /* region 227 */ + { { 32770, 36, 84 }, -8400, 29204, 0, 0, 0, 126 }, /* region 228 */ + { { 32770, 36, 84 }, -8800, 8231, 0, 0, 0, 127 }, /* region 229 */ + { { 32770, 36, 84 }, -8400, 20675, 0, 0, 0, 128 }, /* region 230 */ + { { 32769, 36, 84 }, -7200, -24285, 1294, 5778, 8, 129 }, /* region 231 */ + { { 32769, 36, 84 }, -7755, 29204, 798, 993, 45, 130 }, /* region 232 */ + { { 32769, 36, 84 }, -8055, 20675, 798, 993, 45, 131 }, /* region 233 */ + { { 32769, 36, 84 }, -8955, 29204, 798, 993, 45, 132 }, /* region 234 */ + { { 32768, 36, 84 }, -9355, 32767, 0, 0, 133, 133 }, /* region 235 */ + { { 32768, 36, 84 }, -7755, 20675, 0, 0, 91, 134 }, /* region 236 */ + { { 1, 24, 62 }, -8200, 23197, 286, 333, 94, 135 }, /* region 237 */ + { { 1, 63, 66 }, -8564, 26028, 297, 335, 93, 135 }, /* region 238 */ + { { 1, 67, 72 }, -8922, 23197, 368, 399, 84, 135 }, /* region 239 */ + { { 32769, 73, 96 }, -9510, 23197, 116, 138, 119, 135 }, /* region 240 */ + { { 1, 24, 48 }, -6341, 23197, 309, 447, 77, 136 }, /* region 241 */ + { { 1, 49, 56 }, -7466, 26028, 211, 283, 99, 136 }, /* region 242 */ + { { 1, 57, 63 }, -8200, 26028, 286, 333, 94, 136 }, /* region 243 */ + { { 32769, 64, 84 }, -8922, 23197, 368, 399, 84, 136 }, /* region 244 */ + { { 1, 24, 56 }, -7466, 29204, 211, 283, 99, 137 }, /* region 245 */ + { { 1, 57, 63 }, -8200, 29204, 286, 333, 94, 137 }, /* region 246 */ + { { 1, 64, 69 }, -8922, 29204, 368, 399, 84, 137 }, /* region 247 */ + { { 32769, 70, 96 }, -9510, 29204, 116, 138, 119, 137 }, /* region 248 */ + { { 1, 24, 68 }, -8922, 18426, 368, 399, 84, 138 }, /* region 249 */ + { { 1, 69, 76 }, -9510, 26028, 116, 138, 119, 138 }, /* region 250 */ + { { 32769, 77, 108 }, -9958, 23197, 127, 144, 118, 138 }, /* region 251 */ + { { 1, 24, 82 }, -8813, 23197, 389, 422, 80, 139 }, /* region 252 */ + { { 32769, 83, 108 }, -9964, 26028, 146, 163, 114, 139 }, /* region 253 */ + { { 1, 12, 58 }, -8098, 29204, 386, 436, 78, 140 }, /* region 254 */ + { { 32769, 59, 96 }, -8571, 26028, 290, 328, 95, 140 }, /* region 255 */ + { { 1, 12, 58 }, -8098, 16422, 386, 436, 78, 141 }, /* region 256 */ + { { 32769, 59, 96 }, -8571, 18426, 290, 328, 95, 141 }, /* region 257 */ + { { 1, 12, 48 }, -8098, -28771, 386, 436, 78, 142 }, /* region 258 */ + { { 32769, 49, 84 }, -8571, 29204, 290, 328, 95, 142 }, /* region 259 */ + { { 1, 12, 60 }, -6653, 20675, 314, 430, 79, 143 }, /* region 260 */ + { { 32769, 61, 84 }, -7753, 18426, 263, 324, 96, 143 }, /* region 261 */ + { { 1, 24, 60 }, -7753, 16422, 263, 324, 96, 144 }, /* region 262 */ + { { 1, 61, 70 }, -8869, 20675, 279, 311, 97, 144 }, /* region 263 */ + { { 32769, 71, 96 }, -9298, 23197, 179, 204, 107, 144 }, /* region 264 */ + { { 1, 24, 84 }, -9683, 20675, 191, 211, 105, 145 }, /* region 265 */ + { { 32769, 85, 108 }, -10883, 20675, 92, 102, 121, 145 }, /* region 266 */ + { { 1, 21, 69 }, -7753, 13045, 263, 324, 96, 146 }, /* region 267 */ + { { 1, 70, 94 }, -8869, 20675, 279, 311, 97, 146 }, /* region 268 */ + { { 1, 95, 96 }, -9298, -24285, 179, 204, 107, 146 }, /* region 269 */ + { { 32769, 97, 108 }, -10883, -24285, 173, 183, 110, 146 }, /* region 270 */ + { { 1, 16, 55 }, -9300, 20675, 168, 193, 108, 147 }, /* region 271 */ + { { 1, 56, 74 }, -9776, 26028, 138, 157, 115, 147 }, /* region 272 */ + { { 32769, 75, 96 }, -11274, 26028, 135, 151, 117, 147 }, /* region 273 */ + { { 1, 24, 72 }, -9298, 26028, 179, 204, 107, 148 }, /* region 274 */ + { { 1, 73, 85 }, -9683, 20675, 191, 211, 105, 148 }, /* region 275 */ + { { 32769, 86, 108 }, -10883, 18426, 92, 102, 121, 148 }, /* region 276 */ + { { 32769, 36, 108 }, -8930, 18426, 1839, 1901, 21, 149 }, /* region 277 */ + { { 32769, 24, 108 }, -8473, 20675, 494, 534, 69, 150 }, /* region 278 */ + { { 32769, 12, 108 }, -8473, 20675, 494, 534, 69, 151 }, /* region 279 */ + { { 32769, 24, 108 }, -8473, 20675, 494, 534, 69, 152 }, /* region 280 */ + { { 1, 36, 60 }, -6100, 5193, 2, 22, 143, 153 }, /* region 281 */ + { { 32769, 61, 84 }, -7283, 20675, 173, 183, 110, 153 }, /* region 282 */ + { { 32769, 24, 96 }, -7753, 14636, 263, 324, 96, 154 }, /* region 283 */ + { { 32769, 36, 96 }, -8930, 26028, 1839, 1901, 21, 155 }, /* region 284 */ + { { 32769, 24, 108 }, -8473, 20675, 494, 534, 69, 156 }, /* region 285 */ + { { 1, 24, 58 }, -9051, 14636, 0, 29, 140, 157 }, /* region 286 */ + { { 32769, 59, 96 }, -9051, 14636, 0, 29, 140, 157 }, /* region 287 */ + { { 1, 12, 83 }, -7220, 13045, 0, 83, 125, 158 }, /* region 288 */ + { { 1, 84, 90 }, -9682, 13045, 0, 20, 146, 158 }, /* region 289 */ + { { 32769, 91, 108 }, -10301, 13045, 6, 20, 148, 158 }, /* region 290 */ + { { 1, 21, 42 }, -5863, 26028, 1047, 1229, 34, 159 }, /* region 291 */ + { { 1, 43, 48 }, -6656, 29204, 1138, 1253, 33, 159 }, /* region 292 */ + { { 1, 49, 53 }, -7045, 26028, 559, 651, 60, 159 }, /* region 293 */ + { { 1, 54, 60 }, -7932, 26028, 508, 563, 64, 159 }, /* region 294 */ + { { 1, 61, 65 }, -8280, 32767, 819, 864, 51, 159 }, /* region 295 */ + { { 1, 66, 70 }, -8066, 26942, 981, 1032, 43, 159 }, /* region 296 */ + { { 1, 71, 76 }, -9366, 26028, 790, 814, 54, 159 }, /* region 297 */ + { { 1, 77, 82 }, -9966, 26028, 592, 609, 61, 159 }, /* region 298 */ + { { 1, 83, 87 }, -10717, 23197, 543, 554, 66, 159 }, /* region 299 */ + { { 1, 88, 96 }, -11271, 18426, 601, 609, 62, 159 }, /* region 300 */ + { { 32769, 97, 108 }, -11766, 18426, 523, 529, 70, 159 }, /* region 301 */ + { { 1, 48, 69 }, -7513, 14636, 0, 70, 128, 160 }, /* region 302 */ + { { 1, 70, 79 }, -8924, 18426, 0, 31, 138, 160 }, /* region 303 */ + { { 32769, 80, 96 }, -9230, 14636, 0, 26, 142, 160 }, /* region 304 */ + { { 1, 36, 72 }, -8334, 29204, 0, 87, 123, 161 }, /* region 305 */ + { { 32769, 73, 96 }, -9160, 29204, 0, 54, 129, 161 }, /* region 306 */ + { { 32769, 36, 96 }, -8930, 26028, 1839, 1901, 21, 162 }, /* region 307 */ + { { 32769, 12, 96 }, -5572, 32767, 818, 1033, 42, 163 }, /* region 308 */ + { { 32769, 36, 108 }, -9770, 26028, 472, 491, 74, 164 }, /* region 309 */ + { { 32769, 12, 96 }, -6204, 29204, 570, 719, 59, 165 }, /* region 310 */ + { { 1, 12, 83 }, -7220, 13045, 0, 83, 125, 166 }, /* region 311 */ + { { 1, 84, 90 }, -9682, 13045, 0, 20, 146, 166 }, /* region 312 */ + { { 32769, 91, 108 }, -10301, 13045, 6, 20, 148, 166 }, /* region 313 */ + { { 1, 21, 46 }, -6851, 32767, 236, 340, 92, 167 }, /* region 314 */ + { { 1, 47, 75 }, -7763, 26028, 824, 885, 49, 167 }, /* region 315 */ + { { 1, 76, 84 }, -9107, 23197, 719, 747, 57, 167 }, /* region 316 */ + { { 1, 85, 93 }, -10076, 20675, 83, 99, 122, 167 }, /* region 317 */ + { { 32769, 94, 108 }, -10889, 20675, 173, 183, 110, 167 }, /* region 318 */ + { { 1, 21, 46 }, -6851, 26028, 236, 340, 92, 168 }, /* region 319 */ + { { 1, 47, 71 }, -7763, 20675, 824, 885, 49, 168 }, /* region 320 */ + { { 1, 72, 88 }, -9107, 18426, 719, 747, 57, 168 }, /* region 321 */ + { { 1, 89, 93 }, -10076, 16422, 83, 99, 122, 168 }, /* region 322 */ + { { 32769, 94, 108 }, -10889, 16422, 173, 183, 110, 168 }, /* region 323 */ + { { 1, 21, 45 }, -5863, 26028, 1047, 1229, 34, 169 }, /* region 324 */ + { { 1, 46, 51 }, -6656, 29204, 1138, 1253, 33, 169 }, /* region 325 */ + { { 1, 52, 54 }, -7045, 26028, 559, 651, 60, 169 }, /* region 326 */ + { { 1, 55, 63 }, -7932, 26028, 508, 563, 64, 169 }, /* region 327 */ + { { 1, 64, 68 }, -8280, 32767, 819, 864, 51, 169 }, /* region 328 */ + { { 1, 69, 73 }, -8066, 26942, 981, 1032, 43, 169 }, /* region 329 */ + { { 1, 74, 79 }, -9366, 26028, 790, 814, 54, 169 }, /* region 330 */ + { { 1, 80, 88 }, -9966, 23197, 592, 609, 61, 169 }, /* region 331 */ + { { 1, 89, 99 }, -11271, 18426, 601, 609, 62, 169 }, /* region 332 */ + { { 32769, 100, 108 }, -11766, 18426, 523, 529, 70, 169 }, /* region 333 */ + { { 1, 21, 45 }, -5863, 26028, 1047, 1229, 34, 170 }, /* region 334 */ + { { 1, 46, 51 }, -6656, 29204, 1138, 1253, 33, 170 }, /* region 335 */ + { { 1, 52, 54 }, -7045, 26028, 559, 651, 60, 170 }, /* region 336 */ + { { 1, 55, 63 }, -7932, 26028, 508, 563, 64, 170 }, /* region 337 */ + { { 1, 64, 68 }, -8280, 32767, 819, 864, 51, 170 }, /* region 338 */ + { { 1, 69, 73 }, -8066, 26942, 981, 1032, 43, 170 }, /* region 339 */ + { { 1, 74, 79 }, -9366, 26028, 790, 814, 54, 170 }, /* region 340 */ + { { 1, 80, 88 }, -9966, 23197, 592, 609, 61, 170 }, /* region 341 */ + { { 1, 89, 99 }, -11271, 18426, 601, 609, 62, 171 }, /* region 342 */ + { { 32769, 100, 108 }, -11766, 18426, 523, 529, 70, 172 }, /* region 343 */ + { { 32769, 36, 108 }, -9770, 20675, 472, 491, 74, 173 }, /* region 344 */ + { { 32769, 12, 108 }, -8930, 20675, 1839, 1901, 21, 174 }, /* region 345 */ + { { 1, 12, 44 }, -7068, 18426, 163, 254, 102, 175 }, /* region 346 */ + { { 1, 45, 51 }, -7618, 20675, 261, 393, 85, 175 }, /* region 347 */ + { { 1, 52, 58 }, -8533, 23197, 190, 229, 104, 175 }, /* region 348 */ + { { 1, 59, 66 }, -9300, 23197, 168, 193, 108, 175 }, /* region 349 */ + { { 1, 67, 70 }, -9776, 23197, 138, 157, 115, 175 }, /* region 350 */ + { { 1, 71, 80 }, -10303, 23197, 166, 180, 112, 175 }, /* region 351 */ + { { 32769, 81, 108 }, -11274, 23197, 135, 151, 117, 175 }, /* region 352 */ + { { 1, 12, 65 }, -8253, 16422, 23, 10953, 4, 176 }, /* region 353 */ + { { 32769, 66, 108 }, -8955, 20675, 11, 11753, 3, 176 }, /* region 354 */ + { { 1, 12, 48 }, -5998, 29204, 1132, 1301, 31, 177 }, /* region 355 */ + { { 32769, 49, 108 }, -7188, 29204, 1099, 1184, 36, 177 }, /* region 356 */ + { { 1, 12, 83 }, -8441, 20675, 419, 460, 76, 178 }, /* region 357 */ + { { 32769, 84, 108 }, -11323, 20675, 0, 31, 139, 178 }, /* region 358 */ + { { 1, 55, 60 }, -8253, 18426, 356, 402, 82, 179 }, /* region 359 */ + { { 1, 61, 69 }, -8774, 18426, 514, 548, 67, 179 }, /* region 360 */ + { { 1, 70, 79 }, -9374, 18426, 505, 529, 71, 179 }, /* region 361 */ + { { 32769, 80, 108 }, -10433, 23197, 178, 191, 109, 179 }, /* region 362 */ + { { 32769, 36, 96 }, -8930, -24285, 1839, 1901, 21, 180 }, /* region 363 */ + { { 1, 12, 83 }, -7206, 16422, 838, 922, 47, 181 }, /* region 364 */ + { { 1, 84, 93 }, -9606, 18426, 209, 230, 103, 181 }, /* region 365 */ + { { 32769, 94, 108 }, -11308, 16422, 0, 31, 139, 181 }, /* region 366 */ + { { 1, 12, 56 }, -6795, 23197, 1064, 1170, 38, 182 }, /* region 367 */ + { { 1, 57, 72 }, -7195, 23197, 930, 1014, 44, 182 }, /* region 368 */ + { { 32769, 73, 108 }, -8798, 23197, 726, 826, 52, 182 }, /* region 369 */ + { { 32769, 24, 108 }, -8800, 23197, 635, 735, 58, 62 }, /* region 370 */ + { { 1, 36, 83 }, -7206, 13045, 838, 922, 47, 183 }, /* region 371 */ + { { 1, 84, 93 }, -9606, 13045, 209, 230, 103, 183 }, /* region 372 */ + { { 32769, 94, 108 }, -11308, 13045, 0, 31, 139, 183 }, /* region 373 */ + { { 1, 12, 66 }, -7811, 23197, 437, 16584, 2, 184 }, /* region 374 */ + { { 1, 67, 87 }, -8402, 23197, 452, 16803, 0, 184 }, /* region 375 */ + { { 32769, 88, 108 }, -9673, 16422, 404, 16698, 1, 184 } /* region 376 */ +}; /* end Regions */ + +/*---------------------------------------------------------------------------- + * Programs + *---------------------------------------------------------------------------- +*/ +const S_PROGRAM eas_programs[] = +{ + { 7864320, 0 } /* program 0 */ +}; /* end Programs */ + +/*---------------------------------------------------------------------------- + * Banks + *---------------------------------------------------------------------------- +*/ +const S_BANK eas_banks[] = +{ + { /* bank 0 */ + 30976, + { + 291, 324, 314, 334, 202, 319, 95, 195, + 107, 92, 371, 89, 87, 85, 135, 82, + 200, 192, 130, 267, 193, 302, 207, 210, + 128, 125, 190, 120, 118, 213, 221, 271, + 80, 78, 308, 164, 220, 310, 166, 167, + 186, 182, 181, 179, 160, 178, 176, 115, + 155, 153, 151, 149, 75, 73, 374, 111, + 252, 254, 258, 305, 256, 157, 146, 137, + 249, 237, 245, 241, 274, 262, 260, 265, + 172, 171, 309, 277, 284, 307, 136, 344, + 173, 168, 345, 353, 346, 70, 110, 311, + 357, 144, 104, 67, 364, 367, 64, 288, + 142, 140, 98, 355, 133, 123, 61, 113, + 285, 280, 279, 278, 370, 286, 359, 283, + 101, 236, 163, 235, 234, 233, 232, 231, + 162, 363, 230, 281, 165, 229, 109, 228 + } + } +}; /* end Banks */ + +/*---------------------------------------------------------------------------- + * Samples + *---------------------------------------------------------------------------- +*/ + +const EAS_SAMPLE eas_samples[] = +{ + 0, 0, -3, -4, -6, -8, -10, -12, -12, -11, -8, -3, 3, 7, 10, 14, + 16, 16, 15, 12, 9, 4, -4, -12, -18, -21, -21, -19, -18, -15, -10, -3, + 10, 20, 34, 44, 51, 52, 48, 43, 38, 26, 8, -15, -37, -52, -61, -64, + -66, -64, -59, -47, -31, -13, 4, 18, 30, 37, 40, 36, 30, 24, 19, 11, + -2, -17, -24, -28, -28, -21, -18, -16, -10, -3, 12, 27, 39, 49, 53, 53, + 50, 43, 37, 25, 11, -11, -31, -46, -57, -63, -66, -63, -57, -46, -34, -19, + -3, 13, 27, 35, 39, 37, 32, 26, 20, 11, 0, -13, -20, -24, -25, -21, + -19, -14, -8, -2, 9, 23, 37, 47, 53, 52, 49, 42, 35, 25, 13, -6, + -28, -48, -60, -67, -67, -64, -60, -51, -39, -23, -7, 10, 23, 35, 39, 38, + 32, 26, 21, 15, 4, -9, -20, -22, -21, -19, -14, -11, -5, 1, 9, 19, + 31, 45, 51, 52, 47, 39, 35, 25, 15, -3, -23, -42, -58, -70, -71, -66, + -60, -51, -43, -30, -13, 6, 22, 32, 40, 40, 38, 33, 27, 19, 9, -5, + -17, -25, -26, -22, -16, -11, -8, -4, 7, 21, 35, 48, 53, 56, 50, 43, + 34, 22, 13, -2, -22, -44, -63, -75, -76, -69, -61, -51, -43, -29, -13, 6, + 23, 32, 41, 43, 41, 37, 26, 18, 7, -8, -19, -25, -25, -22, -15, -9, + -5, 0, 10, 24, 37, 44, 48, 52, 52, 46, 33, 20, 8, -5, -20, -38, + -59, -74, -79, -73, -67, -55, -43, -26, -11, 4, 18, 29, 41, 45, 45, 38, + 29, 21, 11, -3, -15, -25, -27, -22, -16, -11, -8, 0, 10, 25, 38, 44, + 47, 50, 53, 49, 37, 20, 7, -5, -17, -34, -58, -74, -82, -76, -67, -59, + -47, -29, -12, 3, 14, 25, 38, 50, 52, 46, 33, 23, 14, 3, -11, -25, + -28, -27, -21, -16, -13, -7, 8, 27, 41, 44, 45, 47, 54, 55, 44, 25, + 7, -7, -18, -32, -53, -71, -81, -81, -72, -67, -55, -37, -16, 3, 15, 23, + 34, 48, 57, 56, 44, 30, 19, 5, -12, -26, -33, -31, -25, -19, -16, -11, + 7, 25, 45, 49, 49, 52, 57, 59, 48, 32, 11, -5, -22, -39, -56, -73, + -82, -88, -84, -75, -60, -38, -16, 5, 21, 30, 39, 52, 59, 61, 53, 37, + 22, 7, -12, -28, -35, -36, -30, -22, -19, -16, -2, 21, 41, 52, 51, 52, + 57, 62, 54, 40, 18, -2, -18, -36, -54, -70, -80, -86, -87, -81, -69, -48, + -23, 0, 18, 28, 35, 45, 57, 64, 59, 46, 27, 9, -11, -24, -30, -32, + -29, -25, -20, -16, -5, 15, 36, 47, 50, 49, 53, 57, 54, 43, 24, 5, + -14, -32, -50, -65, -75, -82, -86, -86, -77, -58, -32, -8, 14, 25, 30, 41, + 56, 69, 69, 57, 36, 17, -4, -20, -29, -32, -27, -28, -27, -23, -13, 10, + 33, 46, 50, 48, 50, 54, 55, 48, 34, 16, -6, -29, -50, -68, -75, -78, + -82, -86, -84, -72, -47, -16, 11, 28, 34, 41, 51, 64, 70, 64, 49, 27, + 5, -17, -30, -33, -29, -29, -30, -30, -22, -2, 23, 41, 49, 51, 51, 54, + 56, 50, 42, 25, 4, -20, -44, -62, -70, -76, -83, -87, -89, -78, -56, -29, + 0, 19, 31, 38, 48, 63, 72, 71, 60, 40, 14, -12, -25, -29, -26, -27, + -33, -37, -30, -12, 11, 31, 41, 48, 51, 53, 55, 55, 51, 39, 17, -12, + -38, -58, -67, -74, -82, -92, -98, -89, -69, -41, -13, 10, 29, 41, 50, 64, + 72, 78, 74, 57, 29, 0, -18, -26, -28, -32, -38, -42, -38, -23, -3, 18, + 30, 42, 52, 58, 60, 61, 57, 48, 28, 2, -30, -51, -62, -70, -81, -94, + -101, -93, -75, -49, -23, -2, 18, 36, 50, 61, 69, 77, 78, 66, 42, 11, + -11, -22, -27, -32, -39, -46, -46, -36, -14, 8, 25, 41, 52, 59, 62, 63, + 62, 57, 38, 11, -20, -47, -61, -69, -78, -89, -98, -94, -80, -60, -37, -12, + 13, 33, 48, 62, 70, 78, 81, 72, 52, 23, 0, -14, -24, -33, -43, -49, + -49, -39, -23, -2, 15, 33, 47, 57, 63, 62, 62, 57, 40, 20, -7, -34, + -52, -65, -74, -83, -94, -92, -81, -63, -42, -22, 0, 21, 39, 54, 63, 73, + 79, 76, 61, 37, 12, -5, -19, -28, -37, -46, -51, -47, -32, -13, 7, 25, + 43, 54, 58, 60, 60, 61, 48, 27, 3, -25, -45, -60, -72, -81, -90, -92, + -84, -71, -52, -32, -9, 14, 33, 50, 61, 74, 80, 78, 67, 47, 24, 6, + -12, -26, -37, -50, -56, -52, -37, -19, -2, 16, 35, 52, 61, 63, 61, 59, + 51, 35, 12, -15, -38, -55, -66, -77, -83, -83, -80, -68, -55, -39, -19, 4, + 25, 41, 54, 66, 73, 75, 68, 52, 31, 11, -7, -22, -33, -46, -54, -51, + -39, -24, -5, 12, 32, 48, 56, 60, 61, 58, 50, 36, 17, -8, -30, -46, + -63, -74, -80, -80, -74, -69, -58, -43, -27, -5, 15, 31, 48, 60, 68, 72, + 68, 57, 39, 20, 2, -16, -30, -44, -51, -50, -41, -27, -10, 9, 28, 43, + 53, 57, 57, 54, 48, 37, 19, -3, -25, -41, -56, -69, -75, -73, -69, -63, + -59, -49, -32, -13, 9, 25, 37, 48, 58, 66, 65, 58, 42, 25, 8, -9, + -22, -36, -41, -43, -37, -26, -14, 4, 21, 37, 48, 52, 53, 47, 42, 34, + 21, 3, -18, -39, -51, -64, -67, -62, -60, -60, -58, -50, -36, -16, 3, 17, + 29, 41, 49, 58, 61, 60, 49, 29, 11, -7, -19, -28, -32, -33, -30, -25, + -14, 2, 19, 33, 41, 45, 42, 38, 36, 29, 20, 6, -14, -28, -43, -54, + -58, -55, -50, -51, -54, -51, -41, -22, -4, 11, 19, 30, 37, 47, 55, 56, + 51, 34, 16, 0, -15, -19, -23, -22, -22, -21, -14, 0, 15, 29, 39, 43, + 37, 31, 25, 21, 18, 6, -11, -28, -42, -50, -51, -48, -44, -41, -44, -43, + -41, -25, -8, 9, 16, 22, 26, 35, 43, 50, 48, 33, 16, -3, -13, -16, + -16, -15, -13, -11, -6, 5, 16, 28, 38, 41, 35, 24, 15, 12, 10, 4, + -11, -27, -39, -46, -46, -45, -40, -36, -36, -37, -38, -29, -13, 6, 16, 19, + 22, 27, 37, 43, 42, 32, 19, 2, -10, -13, -12, -7, -4, -2, 2, 10, + 18, 27, 36, 38, 32, 20, 9, 4, -2, -4, -11, -23, -34, -42, -42, -38, + -31, -28, -29, -32, -33, -30, -18, 0, 10, 12, 12, 17, 26, 35, 36, 31, + 19, 5, -6, -11, -9, -2, 7, 14, 13, 13, 16, 23, 31, 34, 29, 15, + -3, -8, -10, -10, -14, -20, -26, -30, -32, -30, -25, -18, -17, -24, -31, -32, + -26, -11, 2, 7, 8, 9, 17, 25, 29, 28, 21, 9, -2, -7, -5, 4, + 12, 21, 24, 23, 25, 26, 29, 31, 27, 15, -2, -15, -21, -23, -23, -23, + -28, -30, -31, -27, -19, -10, -9, -13, -21, -22, -20, -11, -4, -3, -5, -2, + 5, 13, 17, 17, 16, 10, 6, 0, 3, 11, 23, 32, 33, 30, 28, 27, + 24, 24, 19, 9, -6, -19, -29, -29, -26, -20, -19, -22, -24, -23, -16, -10, + -9, -14, -20, -24, -21, -16, -10, -6, -5, 1, 5, 11, 12, 13, 11, 8, + 6, 1, 4, 9, 23, 33, 39, 36, 32, 32, 28, 22, 17, 7, -7, -22, + -31, -33, -31, -24, -19, -18, -18, -16, -13, -7, -6, -8, -14, -21, -24, -20, + -15, -12, -9, -6, 0, 4, 6, 8, 8, 5, 5, 2, 7, 15, 27, 37, + 42, 45, 41, 39, 32, 22, 13, 3, -11, -26, -37, -41, -37, -29, -21, -18, + -15, -11, -6, -2, -2, -4, -7, -13, -16, -20, -21, -16, -14, -10, -6, -3, + -3, 0, 3, 2, 3, 3, 9, 18, 32, 41, 46, 49, 44, 43, 35, 24, + 12, 1, -14, -27, -39, -40, -36, -31, -22, -16, -13, -6, -3, -3, -4, -9, + -9, -13, -16, -20, -21, -16, -15, -11, -6, -4, -4, -5, -5, -3, -3, 0, + 10, 19, 33, 44, 51, 56, 52, 50, 40, 23, 11, -6, -19, -30, -40, -43, + -40, -35, -24, -16, -7, 2, 6, 5, 1, -6, -9, -9, -9, -12, -19, -21, + -21, -17, -9, -7, -9, -11, -15, -14, -9, -7, 7, 19, 36, 51, 57, 61, + 59, 56, 48, 33, 13, -8, -24, -35, -45, -51, -46, -38, -26, -14, -7, 3, + 11, 15, 12, 3, -5, -7, -6, -9, -15, -22, -25, -23, -17, -13, -12, -16, + -19, -21, -18, -12, 3, 21, 38, 50, 58, 67, 65, 64, 55, 41, 21, -4, + -25, -38, -46, -50, -49, -43, -33, -23, -11, 3, 14, 19, 16, 8, 0, -2, + -2, 0, -8, -19, -27, -30, -25, -22, -20, -20, -22, -25, -24, -16, 1, 22, + 43, 56, 62, 67, 68, 65, 60, 46, 24, -3, -25, -40, -45, -49, -50, -46, + -37, -23, -10, 1, 12, 20, 20, 14, 7, 2, 3, 3, -4, -15, -26, -31, + -30, -27, -26, -26, -29, -33, -33, -25, -8, 17, 41, 57, 65, 71, 73, 73, + 66, 53, 33, 5, -23, -41, -48, -50, -48, -48, -40, -30, -14, 1, 12, 21, + 24, 18, 13, 6, 5, 5, 0, -11, -25, -37, -39, -35, -31, -31, -33, -38, + -37, -29, -12, 15, 40, 59, 67, 71, 72, 73, 69, 59, 39, 14, -16, -38, + -50, -51, -50, -48, -45, -36, -21, -4, 12, 25, 30, 25, 18, 11, 11, 10, + 6, -8, -25, -39, -46, -42, -38, -37, -37, -40, -42, -34, -15, 13, 40, 57, + 66, 71, 72, 72, 69, 61, 45, 19, -10, -34, -46, -48, -47, -45, -45, -41, + -28, -12, 7, 23, 27, 25, 18, 15, 17, 17, 12, 1, -20, -37, -47, -50, + -46, -45, -44, -45, -46, -41, -21, 7, 37, 60, 69, 73, 72, 72, 72, 67, + 52, 25, -6, -33, -47, -50, -47, -47, -47, -45, -35, -16, 6, 23, 31, 30, + 24, 23, 24, 25, 18, 4, -15, -33, -50, -56, -57, -53, -48, -49, -49, -45, + -29, 2, 35, 58, 68, 71, 72, 74, 73, 68, 56, 34, 5, -26, -43, -48, + -45, -42, -46, -46, -41, -24, 0, 21, 33, 34, 31, 25, 27, 27, 19, 6, + -14, -36, -55, -64, -64, -60, -50, -47, -45, -44, -31, -4, 32, 58, 71, 72, + 68, 70, 70, 66, 57, 36, 11, -20, -43, -50, -48, -41, -37, -42, -40, -28, + -5, 21, 36, 38, 34, 26, 29, 28, 20, 8, -13, -33, -52, -68, -69, -65, + -55, -49, -47, -44, -31, -3, 30, 55, 67, 70, 68, 70, 70, 65, 57, 39, + 15, -13, -38, -49, -47, -40, -35, -39, -41, -30, -9, 17, 37, 44, 45, 38, + 32, 29, 22, 9, -10, -34, -54, -70, -75, -73, -64, -52, -45, -43, -31, -7, + 25, 53, 67, 72, 70, 72, 70, 62, 53, 38, 16, -10, -32, -49, -50, -43, + -35, -33, -36, -29, -10, 16, 35, 46, 46, 41, 35, 30, 23, 10, -10, -34, + -53, -69, -75, -74, -66, -53, -45, -42, -34, -13, 17, 46, 63, 68, 66, 63, + 65, 63, 54, 43, 24, 0, -20, -40, -43, -42, -36, -32, -32, -28, -16, 7, + 29, 47, 52, 47, 39, 31, 21, 10, -9, -30, -50, -66, -78, -77, -71, -59, + -49, -42, -34, -17, 9, 37, 56, 66, 66, 62, 62, 61, 56, 45, 30, 7, + -13, -31, -39, -40, -36, -33, -32, -28, -18, 1, 21, 41, 54, 52, 44, 36, + 26, 13, -8, -29, -48, -66, -76, -80, -74, -64, -55, -45, -34, -18, 5, 29, + 50, 65, 68, 66, 64, 60, 59, 47, 33, 15, -5, -23, -37, -43, -41, -37, + -35, -31, -21, -4, 16, 36, 52, 59, 54, 45, 33, 17, -5, -25, -45, -60, + -74, -83, -82, -71, -59, -49, -37, -23, -2, 22, 43, 59, 66, 65, 64, 60, + 58, 50, 39, 23, 2, -17, -32, -39, -40, -38, -35, -32, -23, -6, 14, 33, + 49, 59, 58, 49, 34, 16, -5, -25, -43, -60, -74, -83, -83, -76, -63, -53, + -40, -24, -5, 16, 36, 54, 65, 67, 65, 61, 57, 52, 43, 27, 9, -12, + -26, -37, -40, -39, -36, -32, -28, -13, 6, 27, 46, 58, 60, 52, 39, 23, + 5, -16, -36, -53, -66, -77, -84, -81, -72, -60, -45, -32, -15, 5, 25, 48, + 62, 69, 71, 69, 65, 58, 50, 34, 16, -6, -24, -36, -42, -45, -44, -39, + -33, -21, -2, 22, 43, 59, 64, 60, 47, 34, 17, -6, -28, -50, -66, -76, + -84, -86, -82, -72, -57, -40, -21, -2, 21, 42, 58, 66, 73, 76, 71, 64, + 53, 40, 26, 4, -17, -34, -45, -49, -48, -43, -38, -28, -10, 15, 40, 58, + 66, 64, 56, 42, 25, 4, -21, -44, -62, -73, -81, -87, -86, -78, -65, -47, + -31, -9, 15, 34, 52, 62, 72, 79, 80, 72, 61, 49, 34, 12, -12, -32, + -43, -49, -54, -55, -48, -36, -16, 10, 35, 56, 67, 71, 67, 54, 38, 15, + -10, -34, -57, -72, -85, -93, -97, -89, -76, -59, -40, -20, 8, 32, 50, 67, + 77, 87, 89, 81, 66, 52, 35, 16, -6, -30, -47, -58, -61, -57, -50, -37, + -19, 6, 29, 51, 65, 73, 73, 62, 44, 18, -6, -28, -49, -67, -81, -93, + -97, -94, -83, -65, -47, -28, -5, 19, 42, 61, 76, 87, 90, 88, 80, 66, + 48, 27, 3, -17, -40, -56, -65, -66, -58, -49, -30, -6, 17, 41, 59, 71, + 77, 70, 56, 36, 11, -13, -34, -53, -71, -89, -98, -100, -94, -79, -62, -44, + -21, 3, 27, 52, 74, 90, 98, 95, 86, 75, 59, 37, 12, -14, -35, -54, + -64, -67, -64, -51, -34, -10, 11, 32, 50, 65, 73, 71, 58, 37, 14, -10, + -29, -48, -64, -81, -93, -98, -94, -82, -63, -45, -26, -5, 16, 40, 65, 83, + 94, 94, 84, 75, 63, 46, 23, -3, -27, -47, -58, -64, -64, -56, -39, -17, + 3, 20, 38, 57, 71, 72, 61, 45, 24, 1, -19, -37, -56, -73, -91, -99, + -100, -92, -74, -53, -34, -16, 7, 31, 59, 82, 97, 101, 92, 78, 65, 48, + 29, 6, -21, -43, -55, -64, -66, -58, -40, -18, 3, 17, 32, 51, 69, 71, + 62, 45, 27, 6, -15, -34, -50, -64, -81, -93, -99, -96, -80, -59, -40, -23, + -4, 21, 50, 77, 94, 100, 93, 81, 67, 53, 36, 14, -12, -36, -53, -58, + -63, -56, -42, -22, -5, 10, 23, 42, 63, 70, 62, 47, 29, 13, -6, -27, + -43, -57, -72, -84, -98, -99, -87, -66, -44, -27, -11, 10, 38, 67, 91, 99, + 92, 82, 70, 57, 41, 21, -3, -27, -47, -58, -63, -58, -44, -23, -5, 7, + 17, 35, 55, 66, 61, 46, 29, 13, -4, -22, -39, -51, -65, -78, -90, -95, + -85, -69, -47, -30, -12, 9, 30, 57, 83, 96, 91, 81, 67, 57, 42, 26, + 6, -18, -39, -55, -62, -58, -43, -24, -8, 2, 14, 30, 47, 60, 60, 49, + 34, 17, 0, -16, -31, -43, -58, -71, -86, -93, -86, -72, -52, -32, -15, 3, + 22, 48, 76, 90, 89, 78, 69, 59, 46, 32, 14, -6, -27, -47, -57, -56, + -45, -29, -12, -5, 4, 18, 37, 54, 58, 51, 36, 21, 6, -8, -20, -33, + -52, -68, -84, -90, -85, -74, -58, -42, -22, 0, 20, 42, 67, 83, 87, 80, + 68, 58, 47, 34, 19, 0, -20, -40, -52, -53, -45, -27, -13, -4, 6, 17, + 33, 47, 53, 52, 38, 21, 3, -11, -24, -35, -50, -65, -80, -89, -85, -71, + -55, -39, -21, -2, 20, 39, 59, 74, 81, 75, 67, 57, 47, 38, 23, 4, + -17, -32, -43, -45, -39, -26, -14, -4, 4, 12, 26, 38, 47, 48, 35, 19, + 4, -10, -20, -29, -41, -56, -71, -78, -81, -71, -56, -43, -23, -6, 15, 35, + 49, 62, 72, 69, 63, 54, 45, 41, 28, 11, -11, -27, -37, -40, -35, -24, + -17, -7, 2, 9, 22, 35, 46, 49, 37, 21, 4, -9, -18, -27, -41, -55, + -71, -79, -79, -70, -53, -38, -23, -8, 9, 31, 46, 58, 63, 63, 59, 52, + 45, 40, 32, 14, -6, -24, -32, -31, -30, -23, -18, -12, 1, 9, 21, 31, + 41, 44, 33, 21, 5, -6, -20, -29, -43, -57, -69, -77, -73, -65, -52, -41, + -27, -8, 11, 32, 49, 57, 64, 61, 55, 47, 39, 36, 29, 13, -8, -25, + -36, -35, -26, -16, -9, -5, 1, 9, 22, 36, 45, 43, 33, 17, 1, -11, + -21, -32, -45, -57, -71, -78, -73, -61, -45, -33, -23, -8, 11, 31, 46, 53, + 57, 54, 48, 40, 34, 31, 27, 14, -4, -20, -29, -28, -22, -12, -4, 1, + 4, 8, 21, 34, 43, 43, 31, 17, 1, -11, -22, -31, -44, -59, -72, -78, + -70, -54, -40, -28, -19, -8, 10, 28, 45, 53, 57, 53, 43, 34, 28, 27, + 26, 18, 0, -18, -31, -29, -20, -11, -3, 2, 5, 10, 19, 31, 43, 44, + 34, 19, 2, -13, -23, -32, -43, -55, -68, -77, -73, -57, -41, -26, -15, -6, + 11, 28, 43, 52, 52, 49, 41, 33, 24, 22, 21, 14, 1, -14, -25, -24, + -18, -7, -2, 2, 7, 10, 20, 31, 40, 43, 33, 18, 3, -13, -24, -35, + -44, -55, -70, -78, -74, -59, -40, -26, -11, 1, 13, 29, 44, 53, 57, 54, + 45, 32, 24, 18, 13, 9, -4, -16, -26, -29, -22, -10, 1, 8, 13, 18, + 23, 35, 42, 45, 37, 21, 5, -14, -30, -41, -49, -57, -69, -77, -76, -61, + -39, -20, -5, 9, 20, 34, 47, 53, 55, 48, 39, 27, 14, 8, 3, 2, + -4, -15, -23, -24, -16, -3, 6, 11, 19, 24, 30, 34, 41, 43, 35, 18, + 1, -17, -31, -44, -52, -59, -68, -75, -73, -61, -38, -19, 1, 13, 23, 30, + 42, 52, 52, 47, 36, 23, 14, 7, 4, 0, -6, -11, -20, -24, -18, -5, + 7, 15, 18, 22, 28, 36, 43, 43, 38, 24, 4, -13, -30, -44, -55, -64, + -69, -77, -76, -65, -44, -19, 1, 15, 27, 35, 46, 53, 53, 46, 36, 23, + 11, 3, -5, -7, -9, -14, -20, -23, -19, -7, 11, 18, 21, 25, 30, 40, + 43, 43, 38, 24, 7, -14, -30, -41, -55, -65, -73, -77, -74, -66, -49, -24, + -2, 17, 29, 35, 44, 51, 54, 49, 35, 23, 11, 1, -6, -12, -15, -16, + -20, -24, -21, -10, 8, 21, 27, 33, 35, 42, 48, 47, 37, 23, 7, -12, + -28, -44, -60, -69, -75, -78, -74, -65, -49, -25, -2, 17, 30, 40, 48, 54, + 55, 48, 36, 20, 6, -4, -9, -14, -20, -22, -24, -21, -15, -6, 7, 21, + 32, 39, 43, 44, 49, 50, 38, 21, 4, -13, -28, -47, -62, -74, -77, -78, + -77, -65, -48, -26, -4, 15, 28, 40, 50, 56, 54, 46, 33, 20, 9, -2, + -10, -16, -21, -21, -23, -21, -15, -5, 9, 19, 30, 38, 42, 44, 46, 47, + 36, 22, 6, -10, -23, -39, -57, -74, -78, -79, -75, -65, -51, -33, -11, 9, + 25, 37, 46, 55, 56, 48, 34, 21, 10, 4, -4, -14, -20, -25, -24, -21, + -12, -3, 8, 17, 26, 36, 47, 50, 50, 47, 36, 25, 10, -5, -21, -40, + -57, -75, -82, -79, -75, -64, -51, -37, -16, 5, 25, 40, 48, 55, 55, 49, + 37, 25, 15, 6, -6, -18, -26, -29, -25, -20, -16, -7, 5, 17, 29, 39, + 49, 56, 56, 51, 39, 28, 15, 0, -17, -38, -58, -75, -86, -86, -80, -70, + -54, -37, -16, 7, 25, 42, 50, 55, 58, 52, 40, 25, 11, 2, -5, -14, + -21, -26, -26, -18, -12, -5, 4, 13, 25, 34, 45, 53, 55, 48, 39, 25, + 16, 3, -13, -31, -54, -70, -83, -85, -78, -68, -55, -38, -20, 1, 20, 36, + 46, 51, 55, 48, 39, 27, 17, 7, -5, -13, -20, -23, -23, -18, -10, -4, + 3, 10, 21, 29, 40, 48, 52, 50, 40, 28, 20, 10, -5, -24, -48, -67, + -82, -87, -81, -73, -56, -44, -25, -5, 15, 34, 46, 52, 55, 51, 39, 27, + 18, 7, -2, -13, -22, -25, -24, -16, -9, 1, 8, 13, 22, 30, 42, 48, + 50, 47, 38, 26, 15, 6, -8, -22, -41, -61, -77, -86, -81, -70, -54, -40, + -27, -8, 12, 31, 42, 49, 50, 48, 38, 26, 16, 7, -4, -11, -18, -22, + -21, -16, -9, 0, 9, 15, 21, 26, 35, 47, 50, 46, 36, 28, 18, 7, + -7, -22, -37, -53, -70, -81, -83, -72, -58, -43, -30, -14, 5, 22, 37, 44, + 46, 44, 37, 26, 17, 8, 2, -7, -12, -17, -16, -12, -6, 3, 8, 13, + 17, 22, 31, 42, 43, 43, 35, 29, 25, 14, 2, -17, -35, -51, -65, -77, + -80, -75, -63, -47, -34, -18, 4, 21, 32, 38, 41, 41, 36, 28, 17, 8, + 1, -9, -12, -16, -15, -9, -2, 8, 13, 15, 17, 23, 28, 39, 43, 38, + 30, 21, 17, 11, 4, -12, -28, -45, -60, -68, -71, -66, -58, -49, -38, -23, + -5, 15, 27, 34, 34, 32, 28, 23, 18, 13, 4, -2, -7, -9, -7, -4, + 5, 14, 16, 16, 14, 15, 24, 35, 39, 35, 23, 17, 15, 11, 8, -4, + -19, -37, -53, -62, -65, -62, -57, -53, -43, -31, -14, 5, 19, 27, 31, 28, + 26, 23, 20, 18, 11, 5, -2, -5, 0, 3, 8, 14, 16, 15, 11, 7, + 12, 23, 32, 32, 21, 12, 10, 13, 12, 6, -9, -27, -43, -50, -55, -53, + -51, -52, -44, -38, -23, -6, 7, 18, 22, 19, 16, 15, 16, 19, 17, 12, + 6, 3, 7, 10, 16, 20, 23, 20, 14, 8, 9, 17, 27, 26, 17, 6, + 3, 7, 10, 7, -5, -18, -32, -41, -46, -45, -45, -45, -44, -40, -30, -16, + -3, 8, 15, 12, 10, 11, 16, 19, 19, 16, 12, 10, 11, 15, 20, 25, + 26, 24, 18, 11, 6, 11, 17, 21, 15, 3, -6, -2, 4, 7, 2, -14, + -25, -32, -36, -38, -37, -37, -35, -33, -33, -25, -15, -4, 3, 4, 0, -3, + 2, 13, 21, 21, 20, 17, 19, 23, 27, 31, 33, 31, 24, 16, 4, 2, + 7, 13, 13, 3, -10, -9, 0, 8, 7, -3, -15, -22, -24, -30, -32, -37, + -39, -38, -37, -34, -28, -17, -8, -2, -4, -4, 4, 16, 26, 30, 26, 22, + 22, 25, 29, 31, 30, 29, 24, 17, 6, -2, 7, 10, 13, 4, -11, -15, + -10, 3, 8, 2, -10, -17, -17, -17, -23, -29, -35, -37, -34, -36, -35, -28, + -19, -10, -11, -14, -8, 8, 21, 26, 26, 21, 24, 31, 38, 40, 38, 37, + 33, 26, 15, 4, 1, 2, 1, -6, -19, -24, -18, -7, 2, 5, -4, -10, + -9, -6, -7, -16, -27, -33, -35, -38, -41, -38, -32, -22, -20, -18, -10, 4, + 20, 29, 31, 30, 28, 32, 38, 43, 42, 39, 34, 28, 14, 4, 1, 3, + 4, -5, -21, -30, -26, -14, 1, 3, -4, -8, -8, 0, 0, -8, -15, -26, + -29, -35, -40, -40, -36, -30, -28, -29, -22, -10, 9, 22, 28, 28, 27, 30, + 39, 46, 50, 50, 43, 33, 21, 9, 3, 3, 1, -10, -22, -35, -34, -22, + -8, 2, 0, -6, -7, 0, 5, -2, -9, -18, -28, -34, -41, -43, -39, -35, + -33, -33, -25, -12, 5, 19, 26, 29, 31, 31, 39, 46, 51, 52, 47, 38, + 27, 18, 10, 5, -3, -13, -22, -33, -36, -28, -16, -4, -2, -4, -6, 0, + 8, 7, 0, -12, -22, -33, -40, -42, -39, -37, -38, -39, -32, -17, 2, 15, + 24, 25, 28, 33, 39, 47, 51, 53, 51, 44, 35, 23, 15, 8, 1, -12, + -25, -37, -41, -33, -22, -11, -4, -5, -3, 3, 10, 13, 6, -5, -17, -28, + -38, -43, -44, -44, -44, -43, -36, -23, -7, 7, 20, 26, 29, 35, 43, 51, + 54, 58, 56, 52, 44, 29, 18, 9, -2, -12, -28, -39, -45, -38, -26, -16, + -7, -3, 1, 6, 12, 15, 12, 3, -11, -25, -37, -41, -43, -46, -47, -46, + -39, -28, -15, 0, 11, 21, 25, 31, 38, 46, 53, 60, 62, 59, 53, 42, + 32, 19, 6, -10, -27, -41, -47, -47, -39, -31, -21, -9, -2, 5, 11, 16, + 19, 13, 2, -15, -30, -35, -37, -43, -47, -49, -42, -32, -21, -11, 0, 8, + 19, 27, 38, 47, 51, 58, 63, 63, 59, 50, 41, 28, 10, -9, -26, -37, + -43, -44, -40, -33, -23, -11, 0, 6, 9, 14, 15, 13, 1, -15, -25, -32, + -34, -43, -49, -50, -43, -30, -20, -13, -9, 0, 10, 23, 36, 46, 52, 55, + 62, 65, 66, 61, 51, 36, 15, -7, -24, -34, -42, -45, -46, -42, -34, -20, + -5, 5, 11, 14, 16, 13, 2, -10, -18, -24, -31, -39, -49, -48, -42, -34, + -24, -18, -15, -8, 2, 13, 29, 42, 51, 57, 62, 65, 70, 69, 60, 45, + 20, -3, -24, -37, -43, -46, -49, -48, -39, -24, -6, 5, 12, 17, 20, 16, + 6, -9, -15, -21, -26, -38, -50, -56, -50, -37, -26, -23, -19, -14, -4, 11, + 27, 42, 54, 58, 63, 65, 68, 70, 63, 50, 26, 1, -21, -37, -43, -44, + -44, -44, -40, -28, -11, 5, 10, 16, 18, 14, 5, -12, -19, -22, -24, -33, + -47, -52, -52, -38, -25, -17, -17, -16, -10, 4, 22, 39, 53, 59, 62, 63, + 66, 68, 66, 55, 32, 9, -17, -34, -43, -42, -39, -38, -38, -31, -19, -3, + 10, 17, 19, 12, 3, -12, -21, -24, -24, -31, -40, -49, -52, -41, -30, -18, + -15, -17, -10, 0, 16, 33, 47, 59, 65, 64, 65, 67, 63, 56, 38, 13, + -12, -32, -41, -39, -35, -33, -32, -27, -17, -4, 8, 15, 16, 13, 4, -11, + -20, -25, -27, -32, -40, -48, -52, -46, -37, -25, -18, -16, -10, 1, 16, 33, + 49, 59, 66, 67, 65, 66, 62, 51, 38, 15, -9, -30, -38, -41, -33, -29, + -26, -23, -17, -5, 7, 16, 15, 14, 5, -9, -19, -27, -31, -34, -40, -47, + -52, -49, -40, -30, -22, -16, -8, 4, 19, 32, 46, 59, 67, 71, 69, 64, + 57, 49, 36, 17, -7, -27, -38, -40, -35, -28, -23, -19, -12, -5, 6, 12, + 16, 15, 10, -5, -19, -28, -32, -36, -39, -46, -53, -52, -45, -34, -25, -18, + -7, 6, 20, 33, 46, 60, 67, 74, 71, 65, 56, 46, 37, 18, -2, -20, + -33, -38, -38, -30, -22, -16, -12, -6, 2, 6, 15, 15, 11, 1, -11, -19, + -31, -37, -42, -46, -51, -54, -53, -46, -35, -26, -14, 3, 17, 33, 45, 57, + 67, 75, 77, 71, 62, 50, 36, 18, 0, -19, -31, -36, -37, -31, -23, -17, + -11, -6, 1, 6, 11, 15, 14, 8, -3, -16, -27, -37, -41, -47, -52, -58, + -60, -55, -46, -32, -16, 0, 17, 32, 46, 59, 70, 79, 80, 75, 65, 51, + 35, 20, 2, -15, -27, -38, -42, -36, -27, -17, -10, -4, 3, 7, 12, 18, + 19, 14, 5, -7, -22, -37, -46, -53, -57, -62, -67, -65, -58, -43, -22, 1, + 20, 35, 48, 60, 69, 79, 82, 79, 68, 53, 36, 21, 4, -11, -24, -36, + -40, -38, -31, -21, -14, -5, 1, 5, 11, 17, 22, 19, 14, -2, -17, -35, + -48, -55, -63, -67, -73, -72, -64, -49, -27, -4, 19, 36, 52, 64, 73, 81, + 85, 82, 72, 56, 36, 20, 3, -14, -24, -33, -36, -35, -32, -22, -13, -6, + 2, 7, 10, 15, 19, 19, 17, 6, -10, -29, -48, -58, -67, -71, -75, -78, + -72, -58, -35, -10, 16, 35, 52, 65, 74, 80, 86, 87, 79, 62, 39, 21, + 5, -11, -22, -33, -39, -39, -34, -25, -15, -7, 3, 8, 16, 17, 21, 22, + 19, 9, -6, -27, -47, -60, -71, -77, -80, -81, -73, -61, -39, -12, 16, 36, + 52, 63, 73, 80, 85, 87, 76, 59, 41, 23, 8, -7, -18, -29, -36, -38, + -33, -23, -13, -8, 1, 6, 14, 18, 19, 23, 23, 17, 1, -20, -43, -57, + -67, -78, -83, -89, -81, -67, -45, -19, 9, 35, 55, 67, 74, 80, 87, 91, + 83, 68, 44, 24, 6, -9, -21, -29, -36, -39, -39, -31, -20, -10, 1, 13, + 20, 26, 26, 27, 28, 22, 8, -16, -40, -60, -75, -86, -93, -95, -89, -75, + -52, -24, 7, 37, 57, 69, 77, 83, 90, 93, 85, 70, 48, 27, 8, -8, + -19, -26, -32, -35, -39, -37, -28, -17, -2, 9, 19, 21, 27, 31, 32, 29, + 12, -9, -32, -54, -71, -86, -94, -96, -90, -82, -62, -33, 2, 34, 56, 69, + 78, 87, 94, 94, 85, 69, 49, 29, 9, -10, -21, -27, -30, -33, -37, -36, + -29, -17, -5, 9, 19, 25, 27, 31, 33, 33, 21, -2, -25, -51, -71, -86, + -95, -95, -92, -85, -69, -42, -8, 27, 52, 67, 74, 83, 92, 95, 89, 75, + 56, 35, 16, -6, -17, -26, -28, -34, -41, -39, -37, -25, -9, 6, 20, 28, + 31, 37, 37, 34, 24, 3, -20, -46, -69, -85, -96, -99, -97, -89, -73, -47, + -11, 21, 45, 61, 73, 84, 92, 95, 89, 77, 61, 41, 20, -2, -13, -20, + -28, -36, -43, -46, -40, -30, -16, 0, 12, 24, 30, 38, 43, 41, 33, 13, + -14, -39, -63, -80, -93, -98, -100, -94, -76, -52, -19, 14, 38, 56, 70, 80, + 90, 94, 88, 75, 58, 40, 22, 6, -8, -19, -25, -33, -39, -41, -38, -31, + -19, -5, 7, 21, 31, 39, 45, 42, 32, 15, -8, -32, -55, -77, -93, -102, + -101, -94, -80, -57, -29, 5, 34, 54, 70, 78, 88, 96, 92, 80, 62, 41, + 24, 8, -9, -21, -32, -35, -38, -41, -39, -35, -22, -6, 6, 21, 31, 39, + 46, 44, 35, 18, -5, -27, -49, -70, -86, -97, -102, -96, -84, -58, -30, -2, + 26, 45, 62, 74, 82, 89, 89, 80, 66, 46, 28, 12, -3, -14, -26, -36, + -39, -42, -40, -36, -28, -15, 0, 17, 30, 37, 45, 48, 40, 23, 3, -20, + -43, -64, -81, -93, -98, -96, -85, -65, -38, -8, 20, 40, 55, 68, 80, 88, + 88, 82, 68, 54, 35, 18, 2, -12, -24, -35, -40, -45, -45, -41, -33, -20, + -4, 15, 31, 41, 49, 52, 48, 32, 13, -14, -38, -59, -77, -92, -101, -102, + -91, -70, -45, -15, 15, 38, 53, 65, 77, 89, 91, 85, 71, 52, 38, 21, + 5, -12, -26, -36, -42, -45, -45, -43, -34, -22, -7, 9, 26, 39, 50, 56, + 50, 34, 14, -7, -29, -50, -69, -84, -96, -98, -90, -72, -50, -24, 7, 32, + 48, 57, 68, 84, 91, 88, 74, 58, 44, 30, 11, -9, -26, -38, -41, -46, + -45, -44, -38, -23, -7, 9, 24, 36, 49, 55, 51, 35, 18, -3, -24, -45, + -64, -78, -89, -93, -90, -75, -54, -29, 0, 23, 42, 54, 67, 80, 90, 91, + 81, 65, 48, 31, 13, -5, -24, -41, -50, -53, -51, -46, -42, -28, -10, 8, + 23, 36, 50, 59, 56, 44, 26, 8, -13, -35, -56, -77, -89, -94, -92, -80, + -61, -39, -11, 14, 33, 50, 63, 77, 88, 89, 81, 67, 54, 38, 21, 1, + -23, -39, -50, -54, -53, -46, -42, -31, -17, 1, 17, 33, 46, 56, 56, 46, + 33, 16, -4, -24, -46, -67, -82, -92, -94, -87, -67, -45, -19, 4, 22, 43, + 62, 76, 87, 90, 87, 76, 59, 40, 20, 1, -22, -40, -55, -62, -58, -50, + -40, -29, -17, -3, 14, 33, 49, 59, 58, 49, 35, 21, 2, -17, -39, -59, + -76, -90, -93, -86, -70, -49, -29, -8, 12, 33, 57, 75, 84, 87, 84, 78, + 65, 47, 28, 6, -18, -39, -58, -65, -64, -57, -44, -33, -22, -10, 6, 26, + 44, 56, 56, 48, 40, 27, 11, -8, -30, -49, -65, -80, -86, -87, -72, -51, + -31, -13, 5, 24, 48, 70, 81, 86, 83, 79, 69, 51, 30, 8, -16, -37, + -55, -65, -67, -61, -48, -36, -21, -10, 5, 22, 40, 55, 58, 53, 43, 31, + 16, -2, -23, -45, -60, -74, -82, -86, -75, -56, -36, -16, 1, 21, 44, 65, + 81, 88, 85, 81, 72, 54, 33, 8, -18, -41, -58, -71, -74, -70, -56, -41, + -23, -6, 8, 23, 38, 53, 60, 59, 50, 37, 22, 1, -20, -41, -56, -69, + -79, -83, -78, -62, -42, -20, 2, 22, 41, 59, 77, 86, 87, 79, 67, 50, + 31, 10, -15, -36, -52, -63, -69, -69, -59, -41, -23, -9, 4, 15, 29, 44, + 55, 56, 53, 43, 27, 12, -8, -27, -44, -57, -68, -78, -77, -67, -48, -29, + -12, 12, 32, 52, 70, 79, 84, 82, 73, 59, 38, 15, -9, -33, -52, -63, + -71, -72, -66, -50, -30, -13, 2, 12, 27, 42, 50, 54, 54, 46, 34, 19, + -2, -19, -35, -47, -61, -71, -72, -66, -51, -36, -19, 5, 27, 46, 63, 74, + 79, 79, 70, 58, 41, 21, 3, -24, -44, -58, -66, -66, -65, -52, -36, -22, + -10, 4, 18, 34, 43, 49, 52, 48, 43, 31, 14, -4, -21, -35, -51, -61, + -66, -64, -56, -43, -29, -8, 16, 37, 54, 67, 72, 74, 70, 61, 46, 27, + 7, -19, -40, -56, -62, -62, -63, -55, -43, -26, -10, 3, 13, 26, 38, 44, + 47, 43, 39, 30, 19, 5, -12, -24, -40, -47, -51, -53, -51, -44, -32, -14, + 6, 24, 41, 54, 61, 63, 61, 56, 47, 32, 13, -9, -31, -46, -56, -53, + -54, -54, -48, -37, -18, -3, 8, 17, 27, 33, 38, 39, 39, 37, 30, 18, + 1, -16, -29, -35, -39, -42, -47, -47, -39, -22, -3, 14, 29, 42, 51, 57, + 56, 54, 45, 36, 20, -2, -23, -41, -50, -51, -52, -53, -51, -42, -27, -8, + 5, 12, 19, 28, 35, 40, 39, 40, 37, 28, 12, -7, -23, -28, -30, -37, + -43, -49, -45, -32, -15, 3, 19, 34, 45, 49, 49, 51, 47, 41, 26, 6, + -18, -34, -43, -45, -45, -48, -51, -49, -33, -15, -2, 8, 12, 19, 26, 33, + 38, 38, 38, 34, 25, 8, -11, -19, -20, -23, -32, -43, -48, -41, -24, -8, + 10, 21, 31, 38, 43, 47, 48, 45, 34, 16, -9, -31, -41, -42, -42, -46, + -52, -52, -40, -23, -6, 6, 11, 17, 24, 30, 35, 38, 39, 40, 29, 14, + -3, -14, -14, -15, -24, -36, -47, -45, -33, -15, 3, 14, 23, 29, 35, 39, + 44, 45, 38, 22, -3, -26, -38, -37, -37, -41, -50, -56, -45, -26, -8, 5, + 12, 16, 22, 27, 32, 39, 41, 41, 33, 17, 1, -9, -8, -8, -16, -30, + -41, -45, -35, -21, -5, 10, 18, 24, 28, 31, 38, 42, 39, 25, 2, -23, + -36, -36, -37, -39, -47, -53, -47, -31, -11, 3, 12, 16, 23, 27, 32, 37, + 40, 41, 33, 18, 2, -7, -8, -6, -10, -23, -36, -41, -35, -20, -6, 7, + 14, 17, 24, 29, 36, 42, 40, 28, 5, -20, -35, -38, -38, -39, -45, -51, + -46, -33, -15, 2, 13, 22, 27, 28, 27, 30, 37, 41, 35, 20, 5, -4, + -4, -2, -3, -13, -28, -35, -32, -23, -10, 3, 11, 14, 14, 20, 28, 37, + 40, 27, 7, -16, -31, -36, -37, -36, -41, -44, -45, -35, -18, 1, 12, 19, + 25, 26, 27, 31, 34, 39, 34, 20, 8, 0, 0, 1, 0, -9, -23, -33, + -34, -24, -10, 2, 8, 8, 10, 16, 27, 34, 35, 27, 10, -10, -27, -35, + -35, -34, -39, -46, -47, -38, -22, -3, 10, 19, 26, 31, 32, 32, 35, 41, + 39, 25, 9, -2, -3, -2, -2, -7, -19, -30, -33, -26, -14, -3, 6, 6, + 7, 12, 26, 37, 37, 26, 10, -8, -25, -35, -39, -39, -42, -47, -49, -42, + -27, -4, 12, 20, 29, 33, 36, 35, 35, 38, 37, 27, 10, -3, -6, -3, + -2, -7, -16, -24, -28, -24, -13, -4, 4, 5, 7, 9, 19, 30, 33, 28, + 12, -6, -24, -35, -40, -39, -42, -47, -47, -41, -26, -8, 10, 22, 31, 36, + 41, 39, 34, 33, 33, 29, 15, 2, -7, -8, -6, -6, -10, -18, -24, -24, + -15, -5, 6, 7, 7, 10, 17, 23, 23, 18, 9, -7, -23, -36, -42, -41, + -41, -45, -45, -39, -28, -11, 7, 21, 31, 36, 39, 39, 34, 31, 33, 29, + 19, 7, -5, -6, -6, -4, -6, -13, -17, -20, -16, -8, 1, 6, 7, 7, + 11, 16, 20, 18, 9, -7, -24, -37, -43, -42, -42, -42, -45, -41, -28, -11, + 7, 19, 28, 35, 40, 42, 38, 33, 29, 27, 21, 10, -2, -8, -8, -6, + -8, -11, -13, -16, -14, -8, 1, 5, 8, 9, 15, 19, 20, 18, 9, -4, + -18, -34, -42, -46, -47, -45, -47, -45, -36, -20, 0, 13, 26, 36, 45, 48, + 42, 35, 29, 28, 26, 20, 6, -6, -10, -10, -6, -7, -8, -10, -14, -10, + -7, 0, 6, 8, 13, 14, 16, 13, 7, -3, -13, -27, -37, -44, -49, -44, + -42, -40, -37, -25, -9, 9, 23, 31, 41, 44, 44, 37, 30, 27, 28, 27, + 15, 2, -7, -9, -6, -7, -9, -8, -13, -12, -8, -3, 4, 9, 13, 14, + 14, 11, 6, 0, -9, -23, -34, -43, -49, -46, -42, -40, -35, -29, -13, 3, + 19, 31, 41, 45, 43, 37, 31, 29, 30, 28, 19, 4, -5, -7, -7, -5, + -8, -7, -9, -11, -9, -4, 0, 6, 12, 14, 13, 9, 5, -3, -9, -19, + -28, -37, -48, -48, -45, -39, -34, -30, -18, -5, 12, 23, 34, 42, 44, 39, + 34, 32, 31, 33, 30, 18, 8, 1, -5, -6, -5, -5, -8, -13, -16, -14, + -7, 2, 7, 11, 10, 7, 4, -2, -7, -12, -22, -32, -45, -50, -45, -38, + -33, -30, -24, -13, 2, 20, 31, 39, 43, 42, 38, 36, 33, 33, 33, 24, + 14, 1, -8, -9, -7, -4, -5, -11, -16, -16, -11, -4, 2, 9, 8, 7, + 3, -3, -6, -9, -15, -24, -38, -47, -48, -42, -35, -32, -29, -21, -9, 11, + 27, 35, 42, 42, 42, 40, 40, 38, 36, 30, 19, 8, -4, -9, -8, -5, + -5, -12, -18, -20, -15, -5, -2, 3, 4, 5, 6, 1, -3, -8, -12, -19, + -31, -43, -47, -43, -36, -35, -36, -32, -19, 2, 19, 30, 38, 42, 46, 49, + 50, 47, 43, 39, 28, 16, 1, -10, -13, -11, -9, -14, -21, -25, -20, -10, + -4, 1, 3, 4, 7, 4, -3, -7, -7, -10, -23, -38, -47, -46, -41, -37, + -38, -37, -27, -11, 11, 24, 33, 38, 45, 50, 53, 52, 48, 43, 37, 25, + 10, -3, -11, -11, -11, -13, -20, -27, -29, -22, -14, -7, -2, 2, 6, 3, + -2, -3, 0, 0, -11, -28, -41, -45, -39, -35, -36, -39, -37, -24, -7, 11, + 22, 32, 41, 51, 55, 56, 54, 53, 50, 40, 23, 6, -5, -10, -11, -14, + -20, -28, -34, -33, -25, -16, -10, -5, 0, 0, 1, 2, 4, 5, -4, -16, + -29, -35, -37, -37, -35, -39, -39, -32, -19, 0, 13, 23, 36, 46, 54, 58, + 57, 59, 56, 47, 33, 16, 3, -5, -9, -11, -19, -29, -36, -39, -33, -26, + -18, -12, -7, -5, -2, 4, 11, 15, 10, -3, -18, -29, -32, -35, -36, -41, + -44, -40, -30, -18, 0, 13, 28, 41, 50, 59, 63, 66, 66, 60, 44, 26, + 11, 2, -6, -12, -19, -29, -38, -44, -41, -33, -25, -16, -9, -8, -6, 1, + 11, 18, 16, 8, -6, -17, -27, -32, -36, -39, -43, -44, -37, -30, -12, 8, + 26, 39, 46, 56, 64, 70, 72, 66, 51, 36, 18, 7, -4, -11, -18, -29, + -42, -50, -51, -45, -35, -23, -14, -10, -9, 0, 14, 27, 29, 20, 7, -5, + -15, -23, -30, -38, -45, -50, -49, -43, -30, -9, 13, 31, 41, 52, 65, 75, + 79, 77, 66, 50, 30, 13, 3, -6, -14, -26, -41, -53, -57, -54, -44, -32, + -23, -17, -13, -5, 10, 24, 31, 28, 20, 9, -5, -17, -26, -35, -40, -48, + -54, -53, -44, -23, 0, 21, 35, 46, 60, 73, 81, 83, 77, 60, 42, 25, + 11, 1, -11, -25, -42, -57, -64, -62, -54, -43, -33, -24, -17, -6, 9, 23, + 37, 37, 33, 19, 6, -9, -20, -30, -41, -49, -57, -59, -54, -38, -16, 10, + 31, 46, 58, 70, 78, 85, 84, 73, 54, 32, 16, 5, -5, -22, -41, -60, + -72, -71, -66, -54, -43, -30, -19, -6, 10, 25, 41, 47, 43, 32, 20, 7, + -10, -25, -40, -52, -61, -68, -65, -54, -34, -11, 16, 39, 57, 72, 80, 88, + 91, 83, 67, 46, 28, 13, 1, -18, -40, -62, -77, -77, -70, -63, -54, -43, + -30, -12, 7, 25, 40, 51, 51, 42, 31, 19, 3, -13, -32, -48, -60, -68, + -71, -63, -49, -28, -2, 23, 46, 66, 77, 86, 92, 89, 82, 62, 43, 22, + 7, -12, -39, -59, -74, -80, -78, -72, -63, -50, -35, -17, 5, 22, 35, 45, + 49, 49, 42, 31, 13, -7, -25, -38, -49, -59, -66, -65, -57, -42, -20, 8, + 34, 55, 69, 79, 84, 84, 84, 77, 64, 42, 18, -6, -29, -49, -69, -82, + -87, -87, -78, -66, -48, -27, -4, 17, 33, 47, 56, 60, 58, 49, 31, 8, + -18, -36, -47, -57, -67, -75, -74, -60, -36, -3, 25, 48, 65, 76, 83, 87, + 90, 88, 77, 52, 24, -4, -26, -42, -61, -77, -91, -94, -85, -70, -54, -34, + -11, 12, 30, 44, 56, 63, 66, 61, 43, 19, -8, -27, -39, -49, -62, -74, + -80, -71, -49, -20, 9, 34, 56, 70, 79, 86, 93, 96, 91, 70, 41, 11, + -18, -39, -58, -77, -91, -99, -95, -83, -65, -42, -17, 7, 27, 43, 57, 66, + 69, 67, 55, 32, 5, -21, -32, -42, -56, -73, -84, -79, -60, -33, -5, 21, + 44, 61, 72, 80, 92, 100, 99, 82, 54, 23, -10, -31, -51, -71, -87, -101, + -101, -92, -76, -49, -24, 1, 21, 37, 52, 66, 72, 72, 64, 44, 18, -7, + -23, -31, -45, -64, -79, -83, -71, -46, -18, 7, 27, 46, 62, 72, 85, 97, + 100, 92, 65, 35, 2, -22, -40, -60, -78, -92, -100, -96, -82, -59, -29, -6, + 15, 28, 44, 57, 65, 67, 65, 49, 27, 2, -17, -23, -35, -53, -70, -79, + -73, -52, -27, -4, 16, 35, 54, 65, 77, 88, 95, 93, 73, 44, 12, -17, + -38, -54, -74, -86, -97, -98, -89, -69, -37, -11, 9, 27, 42, 56, 65, 68, + 71, 59, 39, 13, -9, -20, -30, -45, -62, -74, -75, -60, -41, -18, 3, 23, + 43, 60, 74, 83, 91, 91, 78, 52, 22, -8, -30, -46, -66, -82, -90, -92, + -85, -70, -44, -17, 5, 22, 33, 45, 56, 60, 63, 56, 39, 21, 5, -9, + -20, -33, -49, -62, -70, -62, -47, -28, -9, 11, 29, 47, 60, 73, 83, 87, + 81, 62, 32, 4, -21, -39, -60, -78, -88, -90, -86, -73, -55, -28, -2, 18, + 30, 42, 50, 57, 58, 53, 44, 27, 15, 4, -10, -24, -40, -53, -59, -57, + -49, -38, -21, -3, 17, 34, 49, 62, 75, 81, 76, 63, 39, 15, -11, -31, + -50, -69, -79, -84, -82, -73, -57, -34, -7, 12, 26, 35, 42, 50, 56, 53, + 42, 31, 20, 13, 1, -16, -30, -43, -50, -51, -49, -42, -28, -11, 7, 23, + 38, 52, 65, 75, 73, 62, 43, 20, -2, -24, -43, -60, -69, -74, -74, -69, + -59, -42, -19, 2, 19, 27, 34, 41, 48, 50, 45, 39, 33, 25, 13, -3, + -18, -32, -42, -47, -49, -47, -40, -27, -8, 11, 28, 43, 57, 69, 73, 65, + 50, 31, 8, -16, -36, -53, -63, -70, -72, -70, -62, -46, -25, -6, 11, 23, + 30, 38, 45, 49, 50, 46, 42, 33, 22, 6, -13, -25, -37, -43, -48, -50, + -45, -35, -18, 2, 21, 39, 51, 61, 64, 63, 53, 38, 19, -6, -30, -49, + -59, -63, -65, -66, -64, -52, -31, -14, 2, 13, 25, 35, 42, 46, 46, 47, + 48, 44, 33, 15, -6, -21, -32, -37, -42, -48, -46, -39, -26, -8, 12, 31, + 45, 55, 58, 57, 51, 39, 22, 2, -21, -39, -49, -56, -59, -62, -59, -52, + -38, -22, -9, 5, 16, 25, 32, 40, 46, 51, 54, 52, 40, 24, 5, -11, + -20, -28, -35, -44, -48, -43, -33, -17, 0, 18, 32, 44, 48, 49, 48, 40, + 28, 11, -10, -26, -37, -45, -52, -58, -57, -51, -41, -29, -19, -10, 3, 15, + 27, 36, 40, 50, 59, 60, 51, 33, 15, 2, -11, -21, -34, -45, -49, -45, + -36, -25, -11, 8, 26, 38, 43, 42, 41, 39, 31, 16, -5, -24, -31, -37, + -43, -51, -54, -49, -40, -31, -24, -13, -3, 12, 22, 29, 33, 43, 55, 60, + 53, 37, 18, 5, -4, -12, -23, -35, -44, -42, -35, -26, -15, -2, 15, 26, + 33, 31, 31, 29, 28, 21, 6, -13, -27, -30, -37, -44, -48, -45, -39, -34, + -28, -18, -8, 4, 17, 23, 31, 40, 51, 58, 56, 42, 25, 12, 2, -7, + -16, -27, -36, -39, -37, -31, -21, -12, 3, 14, 21, 25, 23, 23, 25, 23, + 11, -4, -16, -21, -26, -34, -39, -40, -34, -31, -30, -23, -17, -3, 9, 16, + 23, 31, 42, 54, 57, 49, 29, 14, 7, 4, -3, -15, -26, -32, -32, -31, + -24, -16, -5, 5, 8, 10, 9, 10, 16, 19, 14, 4, -8, -14, -16, -21, + -29, -34, -33, -30, -29, -26, -20, -10, 2, 11, 20, 28, 40, 51, 55, 51, + 33, 17, 9, 6, 4, -9, -20, -28, -32, -29, -25, -20, -11, -2, 3, 4, + 1, 6, 12, 18, 16, 8, -5, -10, -14, -17, -20, -23, -25, -26, -28, -26, + -21, -12, -2, 6, 13, 20, 29, 40, 48, 48, 37, 23, 13, 8, 7, 3, + -6, -15, -22, -24, -24, -21, -16, -10, -6, -11, -15, -10, 1, 12, 15, 9, + 4, 3, 1, -5, -11, -18, -18, -22, -25, -29, -27, -19, -7, 4, 10, 14, + 21, 35, 46, 48, 40, 27, 16, 13, 11, 11, 5, -5, -14, -19, -21, -24, + -19, -14, -13, -17, -21, -21, -11, 1, 11, 12, 5, 3, 2, 5, 6, 0, + -6, -16, -20, -25, -26, -20, -12, -4, 1, 5, 11, 25, 38, 46, 41, 33, + 21, 17, 15, 15, 14, 8, -3, -14, -23, -27, -26, -21, -20, -22, -26, -25, + -20, -7, 5, 10, 10, 8, 5, 6, 6, 5, 1, -7, -14, -20, -23, -21, + -17, -11, -4, 2, 7, 17, 29, 38, 40, 37, 30, 23, 21, 20, 17, 14, + 5, -6, -19, -26, -29, -25, -24, -27, -28, -28, -26, -18, -4, 6, 9, 8, + 4, 5, 10, 12, 11, 3, -8, -15, -18, -18, -15, -11, -10, -5, 1, 8, + 16, 26, 35, 35, 31, 24, 22, 21, 22, 21, 16, 5, -12, -24, -30, -31, + -29, -31, -32, -31, -32, -22, -12, 0, 7, 11, 12, 10, 11, 15, 13, 10, + 2, -10, -13, -16, -17, -14, -14, -12, -6, 0, 10, 20, 26, 32, 30, 29, + 27, 26, 28, 26, 22, 13, -2, -16, -25, -30, -32, -33, -35, -35, -34, -28, + -19, -12, -5, 1, 5, 9, 11, 16, 17, 18, 11, 3, -4, -10, -12, -13, + -12, -13, -14, -10, -4, 8, 20, 27, 31, 31, 28, 29, 31, 30, 26, 17, + 5, -9, -23, -32, -37, -36, -34, -35, -34, -32, -24, -16, -7, 2, 4, 6, + 10, 16, 17, 15, 12, 8, 3, -5, -11, -11, -10, -11, -12, -11, -5, 3, + 13, 22, 30, 32, 27, 25, 25, 28, 27, 19, 7, -8, -22, -31, -34, -32, + -30, -28, -31, -31, -29, -21, -12, -4, 1, 1, 3, 10, 16, 18, 18, 14, + 12, 3, -5, -8, -7, -8, -10, -12, -12, -5, 6, 16, 26, 30, 29, 24, + 25, 26, 29, 23, 13, -2, -16, -26, -32, -33, -30, -30, -30, -30, -29, -25, + -18, -12, -5, -2, 2, 8, 14, 18, 16, 18, 14, 10, 4, 0, -5, -4, + -7, -9, -14, -10, -3, 9, 19, 26, 26, 23, 23, 26, 29, 28, 21, 7, + -10, -19, -25, -26, -27, -27, -29, -30, -32, -31, -27, -19, -13, -9, -7, 0, + 9, 18, 24, 26, 21, 13, 9, 8, 4, -2, -6, -9, -11, -11, -7, 4, + 16, 24, 26, 21, 19, 22, 26, 29, 23, 7, -10, -17, -19, -19, -23, -25, + -25, -25, -26, -26, -29, -26, -17, -14, -9, -7, 1, 12, 21, 26, 23, 18, + 13, 11, 11, 6, -4, -6, -10, -10, -9, -2, 9, 20, 25, 23, 18, 18, + 23, 26, 24, 10, -5, -13, -17, -14, -15, -17, -20, -24, -25, -29, -31, -32, + -28, -22, -16, -13, -8, 2, 14, 25, 27, 27, 22, 17, 15, 13, 10, 5, + -3, -6, -8, -6, 1, 11, 18, 20, 13, 11, 15, 19, 20, 14, 4, -4, + -12, -12, -12, -12, -14, -17, -23, -30, -35, -37, -31, -26, -20, -16, -12, -4, + 9, 22, 28, 26, 22, 17, 14, 15, 11, 8, 6, 2, 0, -2, 4, 11, + 16, 16, 12, 7, 8, 13, 13, 10, 1, -5, -8, -8, -8, -7, -7, -10, + -20, -26, -34, -36, -33, -31, -29, -25, -19, -12, 4, 18, 27, 28, 23, 22, + 18, 19, 17, 14, 9, 7, 4, 0, 2, 8, 14, 16, 12, 2, 0, 2, + 5, 6, 2, -4, -7, -6, -2, -2, -3, -5, -11, -19, -28, -37, -37, -37, + -34, -29, -24, -18, -8, 7, 20, 25, 25, 25, 22, 21, 21, 21, 19, 15, + 11, 6, 6, 6, 10, 11, 6, -2, -5, -5, -2, 0, 0, 0, -4, 0, + 2, 4, 2, -2, -8, -16, -25, -34, -39, -42, -39, -33, -26, -21, -16, -4, + 11, 22, 25, 27, 25, 23, 23, 24, 25, 22, 17, 13, 10, 9, 12, 10, + 4, -5, -12, -12, -11, -9, -8, -6, -5, 1, 4, 8, 10, 7, 4, -7, + -18, -26, -34, -39, -43, -42, -34, -28, -22, -13, 2, 14, 18, 21, 23, 27, + 30, 32, 31, 28, 23, 20, 20, 15, 14, 10, 2, -5, -13, -15, -16, -16, + -12, -12, -5, 1, 5, 8, 8, 10, 8, 0, -13, -23, -27, -33, -40, -44, + -41, -32, -24, -17, -6, 3, 9, 17, 22, 25, 29, 34, 39, 36, 32, 26, + 25, 23, 19, 11, 1, -9, -16, -18, -17, -19, -21, -17, -8, 0, 4, 7, + 8, 10, 11, 6, -4, -13, -21, -25, -35, -40, -41, -37, -26, -21, -13, -8, + -3, 6, 15, 23, 27, 35, 40, 41, 38, 33, 31, 29, 24, 16, 5, -5, + -16, -23, -23, -23, -18, -14, -6, 2, 3, 4, 7, 11, 13, 7, -5, -13, + -21, -25, -32, -40, -42, -37, -28, -21, -14, -13, -9, 1, 11, 22, 27, 33, + 39, 43, 42, 41, 33, 29, 25, 18, 7, -6, -17, -25, -24, -23, -21, -16, + -9, 2, 6, 5, 5, 10, 15, 12, 3, -8, -16, -22, -29, -39, -44, -42, + -34, -27, -22, -21, -17, -8, 4, 19, 29, 40, 48, 53, 51, 49, 43, 38, + 28, 19, 6, -9, -19, -27, -30, -30, -24, -16, -10, -3, 3, 6, 5, 6, + 9, 11, 7, 2, -7, -16, -25, -34, -37, -37, -33, -31, -28, -27, -24, -20, + -10, 8, 22, 35, 46, 52, 53, 54, 49, 46, 37, 23, 9, -7, -18, -24, + -30, -32, -28, -22, -12, -5, 1, 6, 4, 8, 9, 11, 9, 3, -3, -13, + -21, -32, -37, -38, -35, -34, -32, -32, -32, -27, -14, 5, 24, 38, 48, 55, + 56, 56, 54, 50, 40, 23, 4, -10, -18, -24, -26, -29, -29, -24, -17, -5, + 2, 9, 9, 6, 6, 7, 12, 11, 6, -7, -18, -30, -36, -36, -37, -35, + -38, -40, -41, -36, -24, -2, 20, 35, 47, 55, 60, 62, 62, 61, 47, 26, + 7, -12, -18, -22, -24, -28, -33, -31, -24, -12, -2, 7, 9, 5, 4, 5, + 11, 14, 13, 7, -8, -24, -37, -41, -38, -34, -37, -44, -50, -46, -33, -10, + 16, 36, 49, 57, 61, 64, 66, 65, 55, 34, 11, -14, -24, -26, -26, -24, + -30, -34, -33, -24, -7, 5, 12, 10, 5, 6, 9, 16, 22, 21, 10, -10, + -32, -45, -44, -38, -38, -47, -61, -60, -48, -21, 11, 34, 51, 60, 63, 66, + 70, 69, 63, 45, 18, -10, -27, -27, -23, -20, -28, -36, -37, -32, -17, -2, + 8, 9, 5, 6, 8, 15, 24, 30, 25, 5, -22, -41, -44, -40, -38, -50, + -64, -72, -62, -37, -3, 29, 52, 62, 66, 69, 73, 78, 72, 54, 26, -5, + -25, -32, -29, -24, -27, -34, -37, -36, -26, -11, 5, 15, 15, 11, 9, 15, + 26, 35, 33, 14, -14, -37, -49, -47, -45, -51, -63, -72, -66, -42, -10, 22, + 49, 64, 69, 69, 70, 75, 73, 59, 34, 4, -20, -30, -30, -25, -24, -29, + -36, -40, -35, -22, -2, 16, 20, 17, 14, 15, 27, 39, 41, 27, -4, -32, + -48, -54, -53, -59, -65, -73, -71, -55, -23, 16, 49, 67, 70, 68, 71, 77, + 78, 65, 40, 10, -17, -31, -34, -28, -24, -26, -31, -40, -40, -30, -10, 10, + 21, 18, 15, 16, 26, 40, 48, 40, 13, -20, -44, -55, -61, -63, -69, -76, + -76, -63, -35, 6, 41, 66, 75, 71, 71, 75, 77, 67, 44, 17, -10, -25, + -34, -35, -29, -27, -28, -35, -40, -35, -18, 1, 16, 21, 20, 19, 25, 38, + 47, 43, 23, -9, -34, -50, -59, -65, -72, -76, -74, -66, -43, -9, 27, 58, + 71, 69, 70, 71, 73, 67, 48, 25, 2, -18, -28, -33, -29, -25, -25, -31, + -39, -41, -28, -10, 8, 19, 20, 23, 27, 36, 45, 45, 31, 4, -22, -45, + -58, -67, -74, -75, -73, -66, -50, -21, 16, 49, 67, 73, 72, 72, 74, 69, + 53, 33, 9, -11, -25, -34, -35, -31, -27, -30, -38, -43, -33, -16, 6, 18, + 24, 27, 30, 38, 45, 46, 34, 10, -16, -40, -61, -70, -77, -76, -72, -66, + -52, -31, 2, 36, 60, 71, 72, 69, 71, 68, 57, 44, 20, 2, -17, -32, + -36, -33, -31, -31, -40, -46, -41, -29, -5, 16, 27, 34, 35, 41, 49, 51, + 41, 17, -11, -34, -56, -71, -79, -80, -76, -68, -57, -36, -10, 21, 48, 64, + 71, 71, 73, 69, 61, 48, 32, 11, -5, -21, -31, -34, -34, -37, -43, -48, + -45, -34, -14, 8, 25, 34, 41, 43, 49, 51, 43, 26, -2, -27, -49, -65, + -74, -77, -74, -70, -58, -42, -20, 9, 38, 56, 64, 67, 69, 71, 66, 53, + 37, 16, 1, -15, -30, -33, -39, -38, -41, -45, -42, -35, -15, 7, 25, 36, + 41, 45, 49, 49, 40, 23, 1, -20, -41, -59, -71, -75, -73, -65, -57, -45, + -28, -6, 22, 42, 56, 63, 67, 71, 70, 59, 44, 28, 12, -3, -19, -32, + -40, -41, -46, -47, -46, -37, -20, -2, 20, 34, 45, 48, 52, 53, 42, 26, + 4, -15, -35, -51, -65, -70, -70, -68, -61, -50, -34, -15, 9, 28, 45, 54, + 64, 71, 72, 67, 53, 40, 24, 8, -10, -27, -37, -41, -49, -53, -53, -42, + -25, -8, 14, 31, 43, 52, 56, 56, 46, 30, 11, -8, -26, -43, -59, -70, + -69, -68, -62, -55, -44, -25, -4, 17, 36, 48, 62, 69, 69, 67, 57, 47, + 33, 17, -2, -21, -33, -41, -47, -52, -53, -43, -25, -10, 9, 23, 36, 46, + 52, 54, 47, 31, 14, -4, -19, -32, -49, -57, -62, -60, -57, -58, -51, -39, + -19, 6, 23, 38, 51, 60, 68, 71, 67, 58, 44, 27, 7, -17, -32, -41, + -47, -52, -54, -46, -31, -12, 7, 22, 35, 45, 51, 53, 46, 33, 18, 2, + -12, -26, -42, -55, -61, -60, -56, -57, -55, -46, -29, -8, 10, 27, 42, 55, + 65, 70, 69, 61, 49, 34, 16, -5, -23, -36, -45, -51, -54, -50, -35, -17, + 3, 17, 29, 37, 44, 51, 47, 39, 21, 6, -8, -20, -31, -44, -52, -58, + -60, -58, -58, -51, -39, -22, -4, 14, 31, 48, 62, 70, 69, 65, 57, 45, + 28, 7, -15, -31, -44, -50, -53, -50, -39, -24, -6, 11, 24, 33, 43, 46, + 45, 35, 25, 14, 1, -13, -23, -35, -44, -53, -57, -59, -59, -57, -47, -33, + -15, 3, 21, 39, 56, 69, 72, 69, 60, 49, 36, 17, -5, -25, -42, -52, + -52, -48, -40, -26, -9, 9, 20, 29, 34, 39, 40, 34, 25, 16, 6, -6, + -16, -27, -34, -44, -50, -55, -58, -57, -52, -41, -27, -11, 11, 31, 51, 67, + 70, 68, 61, 53, 43, 30, 7, -14, -35, -49, -54, -50, -40, -26, -13, -2, + 9, 22, 30, 38, 41, 36, 28, 20, 12, 4, -5, -15, -26, -41, -52, -58, + -60, -60, -59, -55, -41, -25, -5, 19, 42, 62, 74, 75, 70, 63, 55, 43, + 22, -3, -24, -42, -51, -50, -45, -32, -22, -14, -2, 14, 28, 35, 34, 33, + 30, 25, 21, 11, 4, -6, -18, -32, -46, -56, -61, -61, -62, -60, -51, -39, + -16, 11, 37, 58, 70, 75, 72, 67, 58, 46, 31, 10, -17, -35, -48, -49, + -41, -28, -17, -14, -7, 4, 18, 28, 32, 29, 27, 21, 19, 16, 7, 2, + -11, -22, -35, -48, -57, -61, -60, -60, -56, -47, -30, -5, 23, 48, 63, 72, + 75, 71, 64, 53, 39, 20, -2, -22, -40, -48, -45, -34, -21, -17, -10, -4, + 10, 22, 27, 28, 29, 26, 26, 22, 14, 7, -3, -14, -30, -46, -59, -65, + -65, -65, -64, -56, -41, -17, 15, 42, 62, 73, 77, 75, 69, 57, 43, 25, + 6, -12, -31, -44, -46, -37, -24, -16, -11, -3, 6, 20, 24, 23, 24, 23, + 25, 23, 16, 9, 1, -10, -23, -41, -56, -63, -67, -67, -66, -59, -47, -25, + 3, 32, 54, 70, 75, 76, 70, 62, 47, 32, 15, -3, -21, -38, -44, -41, + -31, -21, -15, -11, -2, 8, 18, 24, 27, 28, 29, 29, 24, 17, 8, -2, + -17, -35, -54, -66, -73, -74, -71, -66, -55, -35, -6, 24, 50, 69, 77, 79, + 74, 63, 51, 38, 22, 2, -17, -35, -42, -39, -32, -24, -17, -11, -5, 6, + 13, 20, 28, 31, 33, 29, 23, 15, 10, 3, -12, -30, -51, -65, -73, -75, + -71, -67, -58, -41, -18, 11, 38, 60, 75, 77, 74, 64, 53, 42, 31, 15, + -7, -25, -38, -40, -37, -29, -24, -15, -11, -2, 9, 17, 28, 33, 36, 33, + 27, 18, 13, 4, -8, -26, -48, -65, -75, -76, -72, -68, -58, -43, -18, 11, + 37, 58, 72, 76, 73, 63, 51, 40, 28, 13, -6, -23, -35, -41, -40, -33, + -24, -16, -9, -2, 7, 18, 29, 38, 42, 38, 31, 21, 11, 3, -10, -26, + -47, -65, -75, -79, -75, -69, -58, -39, -19, 7, 33, 54, 71, 77, 75, 66, + 52, 39, 27, 15, -2, -22, -35, -41, -41, -36, -27, -17, -8, 1, 11, 22, + 33, 41, 47, 45, 35, 21, 11, 4, -7, -24, -46, -66, -77, -81, -79, -73, + -62, -44, -24, -2, 23, 47, 69, 79, 79, 70, 57, 45, 33, 20, 5, -18, + -36, -43, -41, -37, -32, -23, -14, -3, 8, 20, 34, 45, 53, 52, 41, 27, + 16, 7, -5, -24, -47, -69, -83, -86, -84, -74, -62, -44, -22, 1, 24, 47, + 66, 78, 76, 69, 57, 43, 31, 17, 5, -13, -33, -43, -46, -41, -31, -22, + -12, 0, 11, 24, 39, 49, 57, 58, 48, 30, 15, 4, -8, -26, -52, -74, + -86, -89, -83, -74, -60, -43, -21, 1, 22, 45, 65, 78, 79, 68, 54, 40, + 26, 17, 7, -9, -31, -45, -46, -40, -31, -21, -11, 0, 8, 21, 39, 51, + 60, 60, 52, 36, 19, 4, -9, -25, -49, -71, -87, -92, -89, -79, -63, -45, + -24, 0, 22, 43, 65, 75, 80, 70, 57, 44, 30, 16, 2, -14, -31, -46, + -52, -47, -35, -21, -9, 1, 12, 26, 44, 59, 68, 68, 59, 42, 22, 6, + -11, -29, -49, -72, -87, -96, -95, -86, -67, -46, -23, -4, 16, 38, 59, 76, + 82, 74, 61, 45, 31, 20, 3, -14, -30, -44, -51, -51, -41, -26, -11, 3, + 13, 25, 44, 61, 71, 72, 59, 45, 28, 9, -10, -33, -53, -70, -83, -93, + -96, -91, -74, -53, -27, -6, 15, 35, 53, 71, 80, 77, 66, 51, 34, 20, + 3, -15, -30, -45, -53, -55, -48, -32, -17, 1, 16, 29, 47, 62, 73, 77, + 67, 50, 30, 9, -10, -32, -55, -73, -86, -93, -94, -90, -76, -54, -27, -4, + 17, 32, 48, 64, 74, 78, 68, 55, 38, 17, 1, -15, -28, -39, -47, -52, + -49, -37, -21, -3, 16, 31, 46, 61, 70, 75, 70, 55, 36, 13, -9, -32, + -56, -72, -84, -89, -93, -91, -81, -61, -30, -5, 18, 32, 45, 58, 71, 76, + 70, 57, 40, 18, 1, -17, -28, -35, -45, -52, -50, -39, -25, -7, 15, 33, + 48, 60, 67, 73, 70, 60, 42, 19, -8, -34, -57, -69, -77, -83, -87, -92, + -85, -66, -39, -10, 12, 27, 39, 52, 62, 73, 72, 61, 46, 25, 4, -14, + -27, -34, -41, -46, -48, -43, -30, -11, 14, 38, 53, 63, 66, 69, 72, 65, + 48, 23, -4, -31, -56, -72, -81, -83, -87, -91, -87, -72, -46, -15, 11, 28, + 40, 50, 60, 71, 75, 69, 54, 32, 8, -13, -29, -39, -45, -48, -50, -48, + -40, -21, 9, 37, 57, 66, 71, 74, 75, 71, 55, 32, 2, -29, -55, -73, + -81, -84, -87, -89, -88, -75, -49, -19, 10, 29, 39, 48, 53, 62, 72, 68, + 58, 35, 9, -11, -27, -34, -39, -42, -44, -46, -41, -26, 5, 35, 56, 65, + 69, 72, 73, 72, 59, 37, 9, -22, -50, -71, -83, -83, -83, -86, -88, -81, + -55, -24, 5, 24, 37, 48, 54, 59, 64, 66, 59, 41, 17, -9, -27, -36, + -38, -39, -42, -45, -41, -28, -2, 28, 53, 65, 68, 71, 71, 70, 58, 40, + 16, -14, -46, -67, -79, -81, -80, -83, -87, -83, -64, -36, -4, 19, 35, 46, + 51, 58, 65, 69, 64, 49, 26, -2, -25, -38, -41, -39, -40, -43, -45, -33, + -8, 24, 52, 65, 72, 74, 72, 66, 55, 40, 20, -7, -38, -65, -80, -85, + -80, -82, -84, -82, -65, -38, -9, 13, 29, 41, 49, 57, 62, 64, 59, 48, + 29, 6, -19, -36, -39, -37, -35, -38, -39, -31, -11, 19, 47, 63, 70, 71, + 71, 65, 55, 38, 17, -4, -33, -58, -76, -83, -79, -79, -80, -82, -70, -46, + -19, 8, 25, 36, 43, 51, 59, 63, 62, 50, 34, 14, -9, -27, -35, -38, + -36, -38, -39, -30, -15, 10, 34, 52, 67, 73, 74, 68, 54, 37, 21, 2, + -21, -45, -68, -78, -81, -81, -80, -79, -70, -51, -28, -4, 17, 32, 40, 48, + 56, 59, 57, 46, 34, 18, 3, -20, -34, -39, -35, -31, -30, -26, -13, 8, + 31, 48, 61, 67, 69, 66, 53, 38, 16, -4, -23, -41, -58, -72, -78, -80, + -76, -74, -64, -50, -33, -8, 12, 28, 35, 41, 50, 57, 53, 44, 31, 20, + 10, -8, -24, -34, -34, -30, -25, -21, -13, 5, 22, 38, 52, 61, 66, 65, + 53, 36, 15, -4, -18, -33, -45, -61, -73, -79, -78, -72, -62, -49, -33, -13, + 3, 19, 29, 38, 48, 52, 49, 41, 29, 22, 14, 2, -11, -25, -27, -25, + -20, -15, -8, 4, 19, 30, 42, 53, 57, 61, 50, 32, 15, -7, -18, -27, + -37, -50, -65, -73, -72, -66, -57, -49, -37, -19, -3, 13, 23, 32, 41, 44, + 41, 35, 29, 26, 21, 10, -2, -13, -21, -18, -14, -8, -4, 3, 12, 21, + 29, 42, 51, 54, 49, 32, 14, -5, -15, -22, -28, -39, -55, -69, -68, -62, + -52, -44, -37, -25, -11, 4, 16, 24, 32, 37, 35, 28, 23, 23, 23, 18, + 8, -4, -12, -12, -8, -2, 5, 9, 14, 18, 23, 31, 41, 45, 43, 29, + 11, -8, -18, -23, -21, -29, -43, -60, -65, -58, -50, -39, -32, -26, -17, -6, + 8, 18, 25, 31, 29, 24, 17, 20, 24, 25, 19, 8, 0, -5, -3, 4, + 11, 13, 12, 14, 16, 22, 31, 38, 37, 27, 9, -11, -22, -24, -22, -25, + -36, -50, -57, -53, -46, -37, -30, -24, -17, -9, 1, 10, 16, 20, 19, 17, + 13, 14, 21, 24, 24, 19, 10, 8, 9, 13, 18, 20, 15, 12, 11, 14, + 21, 27, 30, 21, 8, -12, -23, -24, -22, -20, -29, -40, -49, -47, -41, -33, + -26, -23, -20, -16, -11, -2, 7, 12, 14, 14, 13, 14, 19, 26, 30, 26, + 20, 11, 11, 16, 21, 26, 22, 18, 15, 14, 15, 19, 20, 16, 4, -15, + -29, -32, -27, -21, -24, -34, -40, -41, -33, -28, -24, -21, -20, -15, -14, -10, + -5, 1, 7, 10, 10, 12, 18, 26, 36, 34, 27, 21, 17, 20, 23, 25, + 24, 19, 11, 10, 9, 12, 16, 14, 3, -16, -32, -34, -27, -19, -20, -27, + -34, -35, -31, -27, -22, -18, -18, -19, -19, -20, -15, -7, 2, 6, 8, 9, + 18, 26, 38, 41, 37, 28, 21, 23, 25, 27, 25, 20, 13, 7, 3, 5, + 9, 11, 4, -14, -31, -35, -29, -20, -18, -23, -26, -32, -29, -25, -23, -15, + -17, -18, -21, -25, -23, -15, -6, 0, 5, 6, 16, 25, 37, 45, 43, 36, + 27, 25, 28, 30, 29, 26, 16, 7, -2, -2, 2, 3, -2, -15, -31, -38, + -35, -23, -15, -15, -19, -23, -26, -23, -21, -15, -12, -18, -24, -27, -25, -19, + -9, -3, 2, 5, 12, 19, 32, 42, 45, 41, 31, 28, 31, 33, 37, 33, + 26, 14, 4, -2, -3, -3, -5, -18, -34, -43, -42, -31, -20, -18, -17, -19, + -18, -16, -13, -9, -8, -13, -22, -32, -32, -28, -19, -11, -6, -2, 7, 18, + 31, 42, 46, 46, 41, 36, 32, 35, 39, 39, 30, 17, 5, -3, -3, -3, + -7, -19, -32, -39, -41, -36, -26, -17, -12, -13, -18, -20, -14, -7, -6, -11, + -23, -32, -34, -28, -23, -15, -9, -2, 9, 17, 28, 37, 44, 48, 45, 38, + 32, 35, 41, 45, 37, 23, 10, 1, -3, -5, -8, -20, -35, -44, -44, -42, + -34, -24, -14, -10, -12, -14, -11, -6, -2, -5, -15, -25, -32, -29, -24, -19, + -15, -10, 1, 10, 20, 31, 40, 45, 48, 43, 39, 39, 45, 51, 43, 28, + 15, 2, -4, -8, -13, -20, -34, -42, -45, -45, -36, -26, -13, -8, -11, -13, + -8, -2, 1, -4, -13, -22, -30, -33, -28, -25, -18, -12, -5, 3, 13, 25, + 37, 46, 47, 45, 40, 41, 47, 53, 49, 35, 21, 10, 2, -6, -11, -22, + -32, -43, -50, -50, -47, -34, -17, -9, -9, -12, -9, 3, 7, 4, -8, -18, + -25, -31, -31, -27, -21, -16, -11, -8, 2, 17, 31, 45, 47, 44, 40, 43, + 54, 60, 58, 42, 26, 14, 4, -5, -14, -26, -37, -47, -54, -53, -49, -38, + -22, -13, -9, -7, -3, 6, 11, 6, -5, -14, -22, -28, -31, -30, -29, -24, + -18, -15, -2, 14, 29, 42, 45, 47, 45, 48, 56, 63, 59, 46, 29, 17, + 5, -4, -11, -23, -36, -49, -53, -52, -48, -40, -29, -21, -16, -11, -2, 5, + 6, 3, -5, -10, -13, -17, -21, -25, -26, -23, -19, -15, -8, 5, 20, 31, + 38, 42, 41, 46, 55, 62, 63, 50, 36, 24, 12, 5, -7, -20, -33, -46, + -51, -51, -48, -40, -33, -27, -20, -15, 0, 9, 7, 1, -6, -10, -11, -16, + -22, -25, -30, -28, -25, -21, -11, 2, 17, 28, 32, 41, 47, 55, 64, 66, + 64, 54, 41, 32, 19, 4, -9, -24, -37, -48, -54, -55, -51, -41, -33, -29, + -24, -15, 0, 13, 14, 8, 1, -5, -6, -10, -17, -24, -30, -32, -33, -32, + -22, -9, 9, 21, 25, 35, 45, 56, 67, 71, 71, 63, 49, 37, 25, 11, + -5, -19, -32, -45, -54, -59, -54, -43, -36, -31, -27, -18, -3, 11, 13, 9, + 2, -3, -6, -9, -13, -20, -25, -29, -33, -30, -23, -9, 2, 11, 19, 28, + 40, 51, 63, 68, 71, 66, 55, 44, 31, 16, 1, -15, -30, -41, -50, -57, + -56, -46, -37, -32, -30, -21, -7, 8, 17, 12, 5, 3, -2, -6, -11, -19, + -23, -27, -33, -34, -28, -19, -6, 3, 13, 24, 38, 51, 62, 70, 72, 68, + 60, 48, 38, 22, 6, -13, -27, -39, -46, -53, -52, -48, -42, -37, -36, -25, + -9, 4, 11, 9, 7, 8, 6, 2, -6, -13, -20, -24, -28, -31, -30, -27, + -19, -10, 4, 19, 33, 45, 57, 67, 74, 74, 70, 60, 47, 31, 10, -8, + -25, -36, -42, -51, -56, -56, -51, -40, -35, -28, -16, -4, 7, 7, 10, 12, + 13, 11, 3, -8, -18, -21, -25, -29, -33, -33, -30, -20, -8, 11, 27, 42, + 54, 64, 72, 77, 76, 69, 56, 34, 14, -5, -20, -32, -43, -50, -57, -59, + -57, -47, -39, -31, -17, -5, 6, 8, 9, 17, 19, 16, 5, -9, -13, -18, + -21, -26, -33, -37, -35, -28, -15, 1, 18, 34, 47, 58, 68, 76, 77, 76, + 65, 47, 25, 6, -12, -24, -37, -49, -57, -62, -64, -58, -50, -40, -24, -12, + 3, 9, 13, 22, 26, 26, 17, 4, -9, -21, -25, -30, -36, -41, -44, -41, + -27, -8, 12, 31, 44, 57, 68, 77, 81, 80, 72, 56, 34, 12, -6, -19, + -30, -41, -53, -65, -68, -65, -56, -44, -30, -17, -8, 2, 10, 23, 31, 32, + 25, 10, -4, -14, -20, -25, -31, -39, -45, -45, -35, -17, 2, 22, 37, 51, + 63, 72, 79, 78, 74, 62, 43, 20, 2, -12, -24, -34, -49, -61, -69, -70, + -63, -48, -35, -23, -11, 0, 9, 20, 31, 36, 32, 20, 7, -9, -18, -24, + -30, -38, -47, -50, -44, -29, -9, 10, 27, 45, 60, 71, 78, 80, 78, 68, + 54, 33, 13, -5, -18, -29, -44, -57, -68, -74, -66, -54, -41, -30, -18, -5, + 8, 19, 26, 33, 32, 24, 13, -4, -15, -22, -24, -29, -40, -44, -42, -29, + -14, 0, 15, 31, 48, 63, 69, 74, 74, 72, 64, 47, 27, 11, -4, -17, + -33, -50, -66, -78, -78, -68, -54, -38, -25, -11, 4, 18, 31, 38, 40, 34, + 21, 5, -12, -23, -28, -34, -43, -50, -51, -39, -22, -6, 10, 26, 46, 61, + 70, 75, 79, 76, 67, 52, 34, 18, 4, -11, -27, -45, -63, -76, -78, -70, + -57, -44, -29, -15, 0, 14, 26, 35, 39, 34, 23, 9, -7, -18, -23, -30, + -40, -49, -51, -41, -24, -9, 5, 19, 39, 55, 67, 74, 77, 79, 72, 56, + 39, 24, 12, -5, -23, -42, -60, -73, -78, -74, -62, -48, -33, -18, -6, 10, + 25, 34, 37, 34, 26, 16, -2, -15, -23, -28, -32, -42, -46, -44, -31, -16, + -4, 11, 28, 44, 56, 64, 69, 75, 73, 63, 50, 37, 22, 6, -10, -27, + -47, -68, -81, -80, -68, -52, -39, -25, -13, 2, 17, 29, 36, 37, 32, 23, + 4, -14, -24, -26, -26, -36, -44, -45, -36, -20, -7, 9, 25, 38, 49, 58, + 66, 75, 77, 67, 52, 39, 26, 14, -3, -21, -43, -65, -81, -84, -74, -56, + -40, -27, -15, -2, 15, 27, 37, 38, 35, 26, 8, -11, -23, -26, -27, -34, + -42, -45, -40, -27, -13, 4, 19, 33, 45, 54, 60, 67, 72, 67, 57, 44, + 32, 20, 5, -11, -32, -55, -72, -82, -76, -62, -46, -31, -21, -5, 6, 19, + 29, 34, 33, 26, 12, -6, -17, -22, -23, -28, -38, -42, -38, -27, -14, 1, + 14, 27, 40, 48, 53, 62, 68, 67, 58, 44, 32, 21, 9, -5, -22, -43, + -63, -76, -75, -62, -46, -30, -24, -13, 0, 10, 20, 28, 31, 27, 12, -5, + -16, -20, -19, -21, -29, -35, -35, -27, -16, -6, 9, 21, 33, 41, 47, 53, + 61, 63, 60, 51, 39, 27, 15, 3, -13, -33, -55, -72, -75, -67, -52, -37, + -26, -18, -7, 4, 15, 26, 27, 25, 14, 0, -10, -15, -16, -19, -24, -31, + -32, -27, -17, -5, 5, 15, 26, 35, 43, 49, 54, 57, 57, 52, 42, 29, + 18, 10, -3, -23, -46, -64, -71, -66, -53, -39, -27, -19, -11, 0, 5, 16, + 22, 23, 15, 1, -10, -15, -18, -17, -17, -20, -24, -22, -14, -4, 7, 16, + 25, 31, 36, 41, 47, 49, 49, 46, 41, 32, 21, 13, 3, -14, -33, -51, + -60, -60, -52, -39, -28, -20, -14, -7, 1, 9, 14, 16, 10, 1, -10, -15, + -14, -15, -15, -15, -17, -14, -11, -4, 5, 13, 22, 29, 33, 35, 39, 43, + 45, 45, 42, 35, 26, 17, 7, -10, -25, -38, -48, -53, -53, -46, -33, -23, + -16, -13, -8, -3, 4, 9, 7, 1, -6, -10, -13, -12, -12, -8, -7, -6, + -2, 3, 6, 10, 14, 23, 28, 29, 30, 29, 34, 39, 40, 36, 30, 21, + 13, 1, -15, -27, -36, -44, -48, -45, -36, -26, -17, -13, -10, -6, -2, 2, + 3, -3, -6, -10, -14, -13, -12, -7, -3, 1, 2, 5, 6, 10, 15, 19, + 25, 25, 26, 26, 29, 34, 35, 32, 29, 20, 13, 4, -12, -20, -27, -33, + -38, -41, -36, -27, -19, -13, -10, -8, -8, -7, -5, -5, -7, -9, -13, -18, + -15, -12, -5, 3, 7, 10, 10, 11, 13, 20, 27, 27, 23, 20, 20, 24, + 27, 25, 26, 23, 17, 7, -6, -13, -16, -20, -26, -32, -33, -28, -20, -13, + -12, -12, -16, -15, -15, -12, -10, -13, -13, -16, -12, -7, 0, 9, 14, 18, + 18, 14, 11, 14, 18, 21, 17, 10, 11, 15, 20, 21, 20, 20, 17, 9, + 2, -5, -10, -14, -21, -25, -29, -27, -23, -17, -13, -13, -16, -18, -20, -20, + -12, -8, -9, -15, -16, -10, -2, 9, 14, 18, 18, 18, 14, 14, 17, 20, + 18, 12, 8, 11, 13, 16, 18, 19, 16, 9, 3, 1, 1, -6, -13, -20, + -23, -21, -19, -15, -15, -14, -17, -21, -22, -22, -17, -11, -11, -13, -18, -14, + -4, 12, 21, 22, 23, 21, 20, 17, 16, 16, 12, 7, 1, 5, 7, 8, + 12, 15, 15, 10, 3, 0, 3, 1, -5, -12, -19, -19, -16, -11, -9, -11, + -14, -23, -28, -29, -24, -17, -13, -15, -19, -18, -10, 7, 22, 29, 30, 24, + 22, 18, 17, 17, 11, 4, -2, -3, 2, 4, 8, 13, 16, 13, 7, 4, + 9, 8, 2, -7, -16, -15, -14, -12, -10, -12, -12, -19, -25, -29, -25, -18, + -15, -18, -21, -19, -12, 1, 16, 28, 34, 32, 29, 23, 18, 15, 11, 4, + -3, -10, -8, -5, 0, 7, 12, 14, 10, 6, 10, 15, 13, 3, -7, -11, + -13, -13, -13, -12, -14, -20, -28, -31, -29, -20, -13, -14, -18, -18, -15, -3, + 12, 24, 33, 32, 29, 25, 22, 16, 11, 3, -3, -6, -7, -8, -3, 2, + 8, 11, 11, 9, 10, 13, 13, 8, 0, -6, -9, -9, -9, -10, -11, -18, + -26, -30, -29, -22, -17, -18, -20, -21, -17, -7, 6, 21, 34, 38, 34, 29, + 21, 17, 13, 8, 1, -8, -13, -15, -10, -3, 5, 10, 11, 10, 11, 15, + 16, 11, 3, -4, -7, -9, -8, -10, -13, -19, -26, -26, -23, -17, -15, -16, + -17, -17, -15, -9, -2, 10, 26, 31, 31, 24, 21, 18, 13, 6, 1, -6, + -8, -9, -8, -4, 0, 6, 10, 12, 15, 14, 13, 9, 5, -2, -7, -8, + -9, -8, -10, -18, -25, -25, -23, -18, -16, -19, -22, -18, -16, -10, 0, 10, + 24, 33, 35, 29, 22, 17, 13, 7, -3, -8, -12, -14, -12, -7, -3, 4, + 10, 14, 16, 17, 16, 16, 11, 3, -7, -11, -10, -7, -10, -19, -26, -27, + -23, -17, -14, -14, -17, -18, -16, -12, -3, 7, 20, 26, 28, 24, 20, 16, + 15, 10, 2, -8, -13, -11, -7, -2, -2, 4, 6, 9, 14, 17, 19, 15, + 8, -4, -12, -15, -11, -5, -8, -18, -25, -24, -17, -9, -6, -7, -11, -15, + -15, -13, -6, 4, 11, 15, 16, 15, 16, 13, 9, 5, 1, -3, -7, -5, + -2, 3, 5, 6, 8, 10, 14, 17, 18, 14, 3, -8, -15, -13, -9, -6, + -9, -19, -22, -19, -13, -6, -4, -5, -8, -13, -15, -10, -5, 5, 8, 8, + 8, 11, 14, 14, 8, 2, 1, 1, 2, -2, 1, 5, 6, 7, 7, 6, + 11, 13, 16, 13, 3, -6, -13, -14, -8, -5, -6, -15, -20, -15, -10, -5, + -2, -6, -6, -8, -12, -10, -8, -3, 5, 3, 3, 5, 7, 10, 6, 2, + -3, -2, 2, 8, 9, 12, 11, 8, 9, 8, 11, 13, 11, 10, 0, -12, + -20, -21, -13, -10, -11, -14, -16, -10, -3, 4, 8, 5, 2, -2, -4, -4, + -7, -4, -4, -5, -7, -8, -5, 0, 2, 2, 0, 1, 6, 11, 15, 19, + 19, 18, 14, 10, 12, 12, 11, 6, -6, -16, -23, -23, -17, -13, -12, -12, + -13, -8, -2, 8, 13, 13, 8, 4, 1, -3, -3, -3, -4, -11, -16, -16, + -13, -9, -5, -4, -2, 1, 6, 13, 17, 21, 24, 23, 18, 14, 10, 11, + 12, 8, -3, -16, -26, -27, -20, -17, -21, -21, -17, -7, 2, 10, 16, 19, + 18, 13, 10, 5, 2, -2, -5, -14, -22, -26, -21, -15, -11, -11, -6, -2, + 6, 16, 22, 27, 28, 28, 23, 17, 13, 10, 12, 7, -4, -18, -29, -32, + -24, -20, -21, -22, -18, -5, 5, 14, 19, 21, 20, 17, 13, 8, 5, -2, + -9, -18, -26, -26, -21, -14, -12, -11, -8, -2, 10, 16, 21, 24, 25, 27, + 24, 16, 11, 6, 7, 6, -4, -16, -25, -29, -25, -19, -19, -22, -18, -7, + 6, 15, 17, 18, 19, 18, 15, 10, 8, 3, -5, -15, -24, -30, -27, -19, + -15, -15, -13, -8, 5, 14, 20, 25, 28, 31, 30, 26, 18, 11, 9, 7, + -2, -14, -27, -33, -30, -25, -25, -27, -26, -15, 2, 17, 22, 23, 23, 22, + 22, 18, 14, 7, -4, -14, -24, -31, -30, -25, -19, -16, -16, -11, -3, 8, + 17, 24, 29, 31, 31, 29, 22, 17, 12, 8, 2, -12, -26, -36, -35, -30, + -26, -26, -29, -20, -5, 13, 24, 26, 26, 26, 28, 23, 19, 11, 1, -9, + -24, -34, -33, -30, -24, -21, -21, -17, -11, 1, 9, 19, 27, 33, 34, 30, + 28, 24, 21, 16, 7, -6, -23, -35, -40, -36, -33, -31, -32, -27, -13, 3, + 17, 25, 29, 34, 34, 30, 23, 17, 11, 0, -14, -27, -32, -33, -30, -26, + -21, -18, -15, -9, 1, 11, 22, 29, 32, 33, 30, 28, 23, 21, 13, 3, + -15, -30, -37, -38, -35, -35, -33, -28, -18, -5, 10, 22, 30, 37, 36, 32, + 26, 21, 14, 7, -6, -19, -28, -34, -32, -27, -21, -20, -21, -20, -11, 5, + 17, 25, 29, 30, 33, 35, 31, 27, 19, 8, -7, -25, -37, -42, -41, -39, + -35, -30, -22, -11, 4, 21, 32, 38, 39, 36, 29, 22, 15, 9, -4, -15, + -24, -32, -35, -31, -24, -18, -18, -19, -14, -3, 11, 21, 27, 31, 32, 34, + 34, 31, 27, 18, 1, -19, -33, -39, -38, -40, -39, -35, -28, -17, -3, 14, + 28, 37, 41, 40, 34, 30, 24, 18, 7, -6, -20, -30, -36, -34, -30, -26, + -26, -27, -26, -16, 0, 16, 26, 30, 33, 36, 42, 43, 38, 27, 10, -10, + -27, -39, -43, -43, -43, -40, -34, -26, -14, 2, 21, 36, 42, 40, 36, 33, + 30, 24, 16, 5, -11, -25, -34, -35, -32, -29, -30, -31, -31, -27, -15, 5, + 21, 27, 30, 34, 42, 51, 48, 40, 20, -3, -21, -32, -38, -40, -43, -42, + -38, -30, -18, -3, 15, 29, 40, 41, 39, 34, 31, 28, 20, 10, -4, -18, + -29, -33, -34, -34, -35, -37, -38, -34, -21, -6, 12, 22, 26, 33, 44, 55, + 56, 46, 26, 5, -11, -25, -36, -42, -47, -47, -43, -37, -24, -11, 9, 25, + 36, 38, 38, 40, 39, 39, 28, 17, 3, -10, -23, -30, -37, -38, -42, -44, + -43, -40, -30, -16, 3, 17, 26, 34, 44, 57, 61, 52, 34, 9, -7, -21, + -30, -38, -46, -49, -48, -39, -27, -13, 5, 22, 32, 35, 35, 37, 41, 43, + 33, 19, 4, -8, -16, -25, -32, -39, -42, -44, -42, -41, -33, -20, -4, 11, + 21, 28, 38, 49, 58, 54, 36, 16, -6, -16, -21, -28, -36, -46, -49, -42, + -29, -17, 0, 13, 26, 30, 30, 35, 41, 47, 41, 25, 9, -4, -12, -17, + -28, -38, -46, -52, -51, -49, -39, -23, -9, 4, 12, 23, 39, 54, 66, 62, + 43, 23, 2, -10, -16, -26, -36, -45, -51, -50, -37, -20, 0, 16, 27, 28, + 29, 38, 47, 50, 44, 28, 13, -2, -10, -16, -26, -35, -45, -55, -57, -56, + -44, -27, -13, -4, 5, 17, 34, 53, 64, 64, 46, 29, 13, 1, -8, -17, + -28, -39, -48, -51, -42, -26, -8, 9, 18, 20, 24, 34, 46, 53, 47, 33, + 15, 4, -4, -13, -22, -35, -47, -56, -59, -56, -48, -32, -18, -8, 3, 14, + 33, 52, 65, 64, 49, 31, 17, 5, -3, -13, -25, -36, -45, -49, -44, -31, + -14, 7, 16, 21, 21, 31, 48, 57, 53, 38, 20, 8, -3, -9, -21, -35, + -47, -57, -62, -62, -54, -38, -22, -12, -5, 7, 26, 49, 66, 69, 56, 37, + 24, 15, 6, -4, -17, -30, -43, -53, -47, -34, -18, -2, 9, 14, 17, 29, + 46, 58, 56, 43, 25, 13, 2, -5, -15, -30, -45, -59, -66, -65, -57, -43, + -28, -16, -10, 2, 21, 44, 66, 71, 62, 43, 28, 19, 13, 3, -12, -25, + -42, -51, -50, -38, -18, -3, 5, 12, 17, 30, 48, 59, 58, 45, 26, 11, + 0, -6, -15, -29, -45, -63, -71, -68, -58, -41, -28, -19, -12, -4, 16, 42, + 62, 70, 61, 43, 29, 21, 16, 8, -6, -20, -35, -45, -45, -37, -21, -6, + 3, 8, 14, 24, 42, 54, 58, 47, 29, 16, 3, -3, -12, -27, -42, -62, + -73, -74, -66, -52, -34, -23, -14, -5, 12, 38, 60, 72, 68, 49, 34, 23, + 17, 10, -3, -18, -31, -42, -42, -36, -20, -4, 5, 9, 11, 22, 37, 51, + 55, 46, 29, 13, 2, -9, -14, -25, -38, -53, -67, -72, -67, -53, -35, -23, + -17, -10, 6, 32, 55, 69, 67, 53, 36, 26, 19, 12, 2, -13, -26, -37, + -40, -36, -24, -7, 3, 9, 13, 20, 36, 49, 52, 47, 32, 17, 3, -12, + -19, -29, -38, -52, -66, -75, -72, -56, -36, -20, -15, -10, 2, 25, 48, 63, + 63, 52, 39, 28, 20, 14, 5, -6, -19, -30, -38, -35, -25, -8, 4, 8, + 11, 17, 33, 47, 54, 47, 34, 18, 4, -9, -19, -28, -40, -53, -65, -75, + -74, -60, -41, -22, -15, -12, -2, 18, 43, 59, 63, 55, 41, 31, 27, 20, + 13, 3, -11, -24, -35, -34, -26, -11, 2, 8, 9, 11, 22, 37, 47, 49, + 39, 22, 6, -7, -19, -26, -36, -48, -60, -74, -77, -66, -47, -26, -13, -8, + 1, 15, 36, 53, 63, 56, 45, 30, 22, 16, 10, 5, -7, -19, -32, -34, + -25, -7, 8, 16, 17, 17, 23, 37, 48, 51, 40, 22, 4, -14, -24, -33, + -39, -49, -61, -72, -77, -66, -47, -27, -13, -5, 1, 13, 30, 47, 59, 57, + 47, 31, 23, 17, 15, 6, -5, -18, -26, -30, -24, -10, 8, 19, 21, 20, + 22, 30, 40, 48, 41, 25, 3, -17, -29, -32, -37, -46, -59, -70, -73, -65, + -46, -27, -14, -4, 3, 15, 29, 41, 52, 54, 45, 31, 19, 15, 15, 9, + 1, -14, -26, -27, -21, -8, 10, 17, 23, 23, 23, 32, 39, 45, 44, 29, + 7, -16, -32, -40, -42, -49, -61, -72, -76, -69, -50, -28, -12, -2, 5, 17, + 31, 43, 48, 49, 44, 34, 24, 15, 13, 9, 5, -8, -24, -27, -21, -7, + 10, 20, 25, 29, 29, 32, 36, 41, 41, 34, 14, -12, -35, -46, -49, -52, + -61, -74, -78, -73, -56, -31, -14, 2, 10, 19, 31, 44, 54, 53, 47, 34, + 24, 16, 9, 4, -2, -12, -25, -28, -22, -7, 9, 23, 32, 36, 36, 36, + 37, 42, 42, 33, 15, -14, -36, -50, -57, -56, -62, -74, -81, -77, -59, -36, + -15, 2, 11, 20, 31, 44, 56, 56, 51, 39, 26, 15, 7, 1, -3, -13, + -26, -33, -31, -14, 9, 25, 36, 41, 40, 41, 40, 44, 44, 35, 17, -13, + -39, -54, -61, -64, -69, -76, -81, -78, -63, -39, -15, 4, 14, 24, 35, 45, + 54, 56, 53, 41, 25, 14, 7, 3, -4, -14, -26, -34, -31, -15, 9, 25, + 36, 41, 43, 44, 43, 46, 45, 35, 16, -9, -31, -49, -63, -69, -75, -78, + -84, -79, -66, -45, -22, 0, 13, 23, 35, 48, 56, 58, 53, 43, 30, 19, + 10, 4, -7, -18, -26, -33, -30, -17, 4, 24, 37, 44, 50, 50, 49, 46, + 43, 35, 16, -7, -30, -52, -65, -75, -78, -83, -85, -82, -70, -50, -26, -4, + 14, 26, 39, 53, 63, 64, 59, 49, 35, 18, 6, -2, -13, -25, -35, -40, + -36, -22, 3, 26, 38, 47, 54, 60, 61, 57, 50, 39, 20, -5, -26, -49, + -66, -80, -87, -91, -93, -88, -74, -54, -34, -12, 8, 24, 40, 55, 68, 70, + 66, 55, 41, 26, 14, 6, -9, -25, -37, -43, -39, -28, -9, 15, 32, 41, + 48, 59, 65, 65, 58, 45, 25, 5, -17, -38, -61, -77, -91, -97, -100, -94, + -79, -64, -44, -23, -2, 24, 42, 57, 72, 77, 74, 63, 48, 33, 21, 10, + -7, -27, -43, -45, -41, -29, -14, 4, 26, 40, 49, 58, 66, 69, 64, 48, + 29, 7, -13, -31, -53, -73, -89, -100, -102, -95, -83, -67, -51, -29, -7, 17, + 37, 55, 72, 81, 77, 67, 55, 40, 25, 12, -4, -22, -40, -45, -42, -31, + -19, -4, 15, 34, 48, 55, 63, 67, 66, 57, 41, 20, -4, -25, -46, -69, + -88, -104, -110, -106, -95, -79, -63, -39, -13, 15, 39, 60, 75, 88, 91, 81, + 66, 44, 27, 13, -3, -22, -41, -50, -48, -38, -26, -13, 6, 29, 46, 55, + 62, 66, 69, 63, 48, 26, 5, -14, -33, -57, -84, -105, -115, -113, -102, -88, + -73, -53, -26, 1, 31, 57, 78, 91, 95, 88, 75, 60, 41, 22, 1, -19, + -38, -51, -53, -48, -36, -22, -6, 19, 39, 53, 62, 65, 69, 67, 55, 36, + 14, -6, -28, -54, -79, -100, -111, -116, -110, -98, -83, -61, -35, -6, 26, 53, + 75, 89, 96, 96, 87, 71, 50, 29, 10, -9, -30, -44, -53, -50, -45, -32, + -19, 2, 23, 43, 55, 62, 66, 66, 62, 49, 30, 11, -12, -39, -70, -95, + -112, -118, -118, -109, -94, -74, -48, -18, 17, 47, 70, 88, 98, 99, 95, 80, + 61, 37, 14, -9, -26, -43, -51, -52, -48, -40, -25, -6, 17, 37, 52, 57, + 63, 64, 62, 55, 36, 17, -8, -34, -62, -86, -106, -117, -118, -110, -99, -83, + -57, -27, 10, 42, 67, 85, 96, 101, 101, 91, 69, 46, 21, 1, -21, -38, + -49, -54, -49, -44, -35, -18, 2, 24, 44, 55, 64, 67, 63, 59, 46, 29, + 7, -21, -51, -79, -104, -117, -122, -117, -108, -94, -70, -40, 0, 34, 63, 85, + 96, 104, 105, 99, 82, 59, 31, 4, -20, -37, -46, -51, -51, -50, -44, -28, + -8, 17, 38, 53, 60, 65, 67, 64, 54, 40, 18, -10, -40, -71, -98, -115, + -121, -118, -113, -103, -82, -52, -14, 22, 53, 77, 94, 106, 109, 104, 93, 76, + 50, 21, -11, -33, -43, -48, -53, -56, -56, -46, -27, 2, 29, 48, 58, 62, + 63, 62, 58, 49, 33, 5, -27, -57, -87, -108, -119, -118, -114, -106, -91, -68, + -31, 8, 42, 69, 88, 102, 110, 110, 100, 83, 60, 33, 3, -23, -39, -46, + -52, -57, -57, -51, -35, -14, 15, 38, 54, 63, 65, 66, 58, 51, 40, 17, + -11, -44, -76, -101, -114, -116, -111, -106, -96, -77, -47, -11, 28, 58, 81, 97, + 109, 112, 105, 95, 77, 53, 23, -9, -30, -45, -52, -58, -64, -61, -52, -35, + -9, 20, 44, 62, 67, 67, 65, 62, 54, 35, 7, -24, -60, -91, -110, -119, + -116, -112, -105, -90, -65, -31, 8, 43, 73, 94, 109, 117, 113, 105, 91, 68, + 39, 4, -24, -43, -56, -64, -67, -67, -61, -47, -21, 9, 35, 55, 63, 66, + 66, 61, 56, 46, 23, -10, -46, -81, -100, -111, -115, -112, -107, -94, -75, -48, + -12, 28, 59, 84, 103, 116, 120, 114, 103, 81, 56, 22, -10, -35, -53, -64, + -71, -73, -71, -59, -39, -10, 19, 43, 60, 66, 68, 67, 64, 53, 33, 7, + -27, -64, -91, -108, -115, -113, -108, -97, -82, -59, -27, 11, 46, 75, 98, 112, + 119, 117, 109, 89, 64, 34, 4, -24, -50, -62, -69, -69, -70, -65, -49, -23, + 8, 32, 52, 61, 64, 65, 64, 55, 39, 15, -16, -46, -76, -97, -109, -110, + -107, -102, -91, -71, -42, -4, 34, 66, 90, 106, 116, 121, 118, 101, 78, 47, + 15, -15, -44, -60, -70, -73, -75, -74, -63, -39, -7, 23, 45, 60, 66, 69, + 69, 62, 49, 29, 1, -32, -65, -94, -108, -112, -109, -102, -97, -83, -58, -22, + 18, 54, 84, 103, 116, 121, 120, 112, 91, 63, 29, -6, -34, -54, -66, -75, + -79, -81, -72, -50, -22, 9, 33, 50, 59, 67, 70, 70, 60, 43, 13, -20, + -51, -78, -97, -107, -111, -109, -105, -94, -72, -37, 5, 42, 72, 96, 114, 124, + 127, 118, 100, 75, 42, 10, -22, -47, -62, -72, -79, -84, -82, -64, -35, -2, + 23, 39, 50, 61, 69, 71, 66, 51, 27, -6, -36, -62, -81, -96, -104, -105, + -106, -101, -83, -52, -11, 27, 57, 82, 103, 120, 127, 122, 107, 82, 53, 19, + -12, -39, -55, -65, -73, -81, -81, -67, -40, -8, 16, 30, 41, 52, 62, 68, + 66, 56, 34, 3, -28, -53, -71, -86, -96, -102, -106, -103, -88, -62, -25, 15, + 47, 72, 90, 109, 120, 123, 115, 93, 63, 31, 1, -24, -40, -52, -64, -76, + -82, -73, -50, -22, 1, 18, 27, 39, 51, 63, 67, 61, 44, 18, -13, -38, + -53, -69, -83, -96, -105, -103, -93, -69, -36, -3, 30, 56, 77, 95, 111, 116, + 113, 97, 72, 42, 13, -12, -25, -38, -54, -70, -79, -74, -57, -32, -11, 4, + 15, 26, 40, 55, 65, 62, 51, 28, 1, -24, -40, -56, -73, -89, -101, -102, + -95, -79, -50, -17, 16, 47, 68, 88, 104, 114, 115, 102, 80, 53, 24, 0, + -18, -31, -45, -60, -73, -74, -63, -42, -21, -6, 6, 16, 28, 45, 56, 59, + 51, 35, 14, -9, -26, -41, -57, -73, -87, -97, -95, -85, -62, -32, -2, 26, + 50, 71, 91, 105, 111, 105, 89, 64, 40, 16, -4, -20, -35, -49, -64, -70, + -68, -53, -35, -18, -6, 5, 14, 29, 45, 55, 54, 39, 21, 4, -13, -25, + -42, -63, -77, -89, -90, -80, -66, -44, -19, 10, 35, 57, 76, 93, 104, 104, + 91, 68, 48, 29, 13, -6, -24, -42, -56, -63, -61, -54, -42, -27, -17, -6, + 5, 18, 33, 44, 47, 39, 25, 10, 0, -14, -29, -50, -67, -79, -85, -81, + -70, -53, -32, -5, 24, 47, 67, 84, 98, 103, 95, 77, 56, 37, 22, 6, + -14, -34, -48, -56, -57, -52, -48, -37, -28, -17, -6, 8, 23, 34, 41, 38, + 28, 15, 4, -4, -16, -38, -59, -73, -78, -75, -66, -54, -37, -19, 7, 32, + 53, 72, 87, 95, 92, 78, 58, 44, 32, 20, 2, -21, -38, -47, -48, -47, + -46, -42, -36, -26, -14, -5, 9, 20, 32, 35, 30, 19, 12, 8, -5, -25, + -48, -63, -71, -70, -63, -58, -44, -26, -6, 20, 40, 59, 79, 92, 93, 83, + 60, 47, 37, 29, 13, -10, -28, -40, -44, -44, -48, -47, -41, -33, -22, -13, + 0, 14, 29, 36, 34, 24, 18, 15, 4, -13, -39, -60, -69, -72, -68, -62, + -51, -34, -13, 9, 31, 52, 73, 88, 95, 87, 70, 55, 45, 35, 20, -2, + -23, -36, -42, -47, -48, -51, -50, -40, -30, -17, -8, 7, 23, 36, 37, 30, + 22, 19, 13, -3, -24, -49, -65, -71, -71, -64, -54, -40, -20, -3, 21, 44, + 65, 85, 92, 87, 72, 57, 48, 39, 29, 11, -12, -27, -36, -41, -42, -47, + -49, -45, -37, -28, -17, -4, 13, 28, 33, 29, 26, 23, 17, 6, -11, -33, + -53, -64, -66, -62, -55, -44, -29, -12, 10, 31, 51, 71, 84, 85, 77, 61, + 50, 41, 36, 22, 2, -17, -33, -38, -42, -45, -48, -46, -41, -34, -23, -9, + 7, 24, 35, 32, 28, 23, 17, 10, -4, -26, -49, -64, -68, -64, -58, -46, + -32, -13, 8, 28, 45, 65, 78, 82, 76, 62, 52, 45, 37, 23, 6, -10, + -26, -35, -41, -45, -46, -48, -48, -39, -27, -11, 3, 14, 23, 27, 28, 25, + 23, 15, 2, -17, -34, -52, -60, -61, -56, -44, -32, -17, -3, 16, 34, 54, + 66, 73, 68, 58, 47, 42, 37, 29, 17, 3, -14, -25, -31, -36, -39, -44, + -48, -44, -33, -20, -9, 2, 13, 22, 26, 24, 20, 14, 5, -7, -22, -39, + -50, -55, -51, -43, -32, -20, -7, 10, 28, 44, 57, 65, 67, 64, 54, 44, + 36, 28, 18, 4, -9, -23, -32, -39, -42, -46, -44, -38, -29, -19, -12, -4, + 10, 22, 27, 22, 14, 8, 1, -6, -17, -30, -43, -49, -47, -38, -26, -18, + -10, 3, 17, 34, 45, 54, 59, 57, 53, 45, 37, 30, 22, 11, -3, -14, + -24, -34, -40, -45, -43, -39, -29, -21, -14, -6, 3, 16, 20, 17, 10, 3, + 0, -6, -15, -25, -33, -38, -37, -31, -21, -12, -6, 5, 15, 27, 39, 46, + 50, 51, 47, 44, 36, 29, 20, 10, 1, -10, -18, -27, -36, -40, -42, -37, + -29, -21, -14, -7, 1, 10, 16, 10, 3, -2, -3, -6, -12, -22, -28, -30, + -28, -23, -16, -11, -7, 0, 7, 19, 31, 42, 47, 47, 46, 46, 40, 33, + 21, 10, 2, -6, -12, -24, -33, -37, -38, -36, -31, -21, -14, -7, -2, 2, + 7, 8, 4, -2, -7, -12, -14, -19, -23, -24, -20, -16, -11, -6, -2, 3, + 9, 16, 24, 33, 37, 40, 44, 44, 40, 33, 22, 13, 5, -3, -8, -21, + -30, -35, -34, -32, -30, -23, -13, -6, -3, -3, -2, -2, -4, -7, -9, -12, + -13, -13, -14, -14, -11, -12, -4, -2, 2, 0, 3, 10, 18, 27, 32, 35, + 38, 40, 37, 32, 23, 13, 8, 2, -4, -11, -22, -27, -31, -30, -29, -24, + -14, -7, -8, -7, -10, -10, -10, -10, -11, -12, -13, -12, -11, -11, -7, -2, + 4, 5, 3, -2, 0, 8, 15, 21, 26, 30, 32, 37, 37, 32, 26, 16, + 10, 4, -4, -9, -16, -21, -26, -29, -28, -23, -15, -11, -9, -11, -13, -14, + -14, -13, -13, -12, -13, -12, -8, -3, 3, 6, 8, 10, 7, 1, -3, 2, + 8, 17, 22, 22, 27, 32, 37, 35, 29, 18, 11, 2, -4, -8, -14, -17, + -21, -23, -25, -22, -17, -11, -9, -11, -16, -16, -16, -16, -14, -15, -14, -11, + -5, 0, 4, 5, 6, 7, 6, 4, 0, 3, 8, 16, 21, 20, 24, 28, + 34, 35, 29, 17, 8, 3, 1, -3, -9, -15, -20, -21, -23, -22, -21, -17, + -13, -14, -18, -23, -22, -17, -13, -10, -9, -8, 0, 6, 9, 10, 8, 6, + 6, 4, 0, -2, 1, 10, 17, 20, 22, 25, 29, 31, 29, 20, 10, 2, + -2, 0, -5, -11, -18, -20, -19, -19, -19, -18, -16, -14, -18, -26, -26, -22, + -16, -13, -9, -6, 1, 7, 10, 10, 7, 7, 7, 5, 0, -4, -2, 7, + 14, 19, 22, 26, 30, 32, 30, 22, 13, 6, 1, -2, -7, -13, -16, -18, + -19, -19, -21, -21, -19, -17, -16, -23, -25, -23, -17, -10, -9, -4, 2, 8, + 10, 12, 9, 7, 5, 4, 2, -3, -2, 3, 9, 18, 23, 28, 29, 28, + 27, 26, 19, 12, 6, 0, -7, -11, -15, -17, -20, -21, -20, -22, -23, -25, + -24, -26, -27, -25, -20, -13, -5, 3, 9, 11, 15, 17, 15, 10, 4, 0, + -4, -5, -4, 2, 5, 13, 19, 25, 29, 28, 26, 25, 20, 16, 11, 2, + -5, -10, -10, -10, -14, -17, -21, -24, -26, -29, -27, -28, -28, -26, -23, -17, + -8, 1, 12, 15, 16, 14, 13, 10, 6, 0, -5, -6, -5, 1, 6, 12, + 20, 27, 30, 28, 24, 23, 21, 17, 11, 4, -6, -9, -10, -10, -11, -16, + -18, -21, -24, -26, -29, -28, -27, -25, -23, -18, -11, -2, 11, 15, 15, 12, + 11, 9, 6, 1, -6, -6, -2, 3, 7, 11, 19, 26, 28, 26, 22, 21, + 23, 24, 17, 10, 4, 0, -2, -5, -10, -15, -20, -25, -32, -36, -36, -35, + -32, -30, -26, -19, -10, 2, 14, 21, 21, 17, 13, 10, 7, 1, -5, -5, + -6, -4, 0, 6, 12, 19, 22, 24, 20, 21, 24, 29, 28, 20, 13, 8, + 3, 2, -4, -9, -16, -27, -34, -41, -44, -41, -38, -35, -31, -27, -18, -3, + 13, 26, 29, 23, 18, 14, 11, 8, 4, -2, -8, -11, -9, -6, 4, 9, + 16, 17, 16, 16, 23, 33, 37, 33, 26, 19, 12, 8, 1, -7, -15, -30, + -41, -50, -53, -50, -43, -38, -34, -28, -17, -3, 13, 26, 30, 26, 19, 14, + 12, 9, 4, -2, -10, -14, -13, -7, 4, 9, 12, 13, 13, 17, 25, 32, + 40, 39, 32, 24, 15, 11, 8, 1, -10, -27, -43, -51, -55, -52, -49, -45, + -40, -32, -21, -8, 9, 23, 31, 30, 24, 19, 17, 16, 11, 4, -7, -15, + -18, -14, -6, 2, 5, 7, 9, 14, 24, 35, 45, 48, 45, 34, 25, 16, + 8, 2, -11, -27, -46, -59, -64, -61, -53, -46, -40, -35, -24, -9, 8, 23, + 30, 31, 27, 24, 21, 17, 12, 4, -6, -15, -19, -17, -12, -3, 3, 4, + 6, 12, 25, 37, 45, 47, 47, 43, 35, 23, 12, 2, -10, -24, -42, -60, + -71, -71, -63, -55, -45, -36, -22, -7, 9, 22, 30, 35, 34, 31, 24, 19, + 13, 6, -3, -13, -20, -21, -16, -9, -3, -2, 4, 11, 26, 38, 45, 50, + 49, 48, 42, 31, 16, 4, -9, -21, -38, -59, -72, -77, -70, -61, -53, -41, + -26, -9, 7, 17, 26, 34, 41, 41, 35, 25, 17, 9, 0, -10, -21, -24, + -22, -15, -9, -7, -2, 10, 25, 39, 44, 47, 49, 52, 50, 39, 22, 6, + -8, -20, -34, -54, -70, -78, -77, -68, -61, -49, -33, -15, 3, 16, 25, 32, + 43, 49, 47, 37, 25, 16, 3, -10, -22, -29, -27, -22, -15, -12, -7, 7, + 25, 42, 47, 50, 53, 57, 57, 46, 31, 11, -5, -22, -39, -56, -72, -81, + -85, -81, -71, -56, -36, -16, 4, 19, 29, 37, 48, 55, 56, 48, 34, 20, + 7, -10, -25, -32, -34, -28, -21, -17, -14, 0, 20, 40, 50, 51, 53, 58, + 61, 53, 39, 18, -2, -18, -36, -53, -70, -80, -85, -86, -79, -67, -46, -23, + -2, 17, 27, 35, 44, 55, 62, 57, 44, 26, 9, -10, -23, -29, -32, -28, + -24, -20, -15, -4, 15, 35, 47, 50, 49, 53, 57, 53, 43, 24, 5, -14, + -32, -50, -64, -5, 0, -2, -3, -3, -3, -3, -2, -2, 1, 2, 3, 5, + 8, 11, 11, 10, 8, 5, 1, -6, -13, -19, -21, -18, -15, -13, -10, -7, + -2, 4, 8, 12, 17, 28, 33, 29, 23, 14, 7, -5, -19, -33, -42, -36, + -28, -24, -17, -13, -8, 1, 7, 15, 23, 33, 42, 42, 35, 26, 15, 0, + -16, -30, -44, -45, -34, -27, -20, -16, -13, -4, 4, 12, 21, 29, 40, 45, + 40, 30, 20, 6, -13, -25, -38, -45, -38, -31, -24, -18, -15, -10, -4, 5, + 17, 27, 35, 44, 43, 37, 27, 15, -4, -19, -31, -44, -44, -35, -30, -22, + -19, -16, -8, 2, 15, 25, 32, 42, 47, 42, 32, 18, 0, -16, -26, -39, + -45, -38, -31, -25, -19, -18, -14, -5, 11, 23, 29, 39, 46, 45, 38, 25, + 7, -8, -18, -31, -44, -43, -35, -30, -25, -25, -20, -9, 7, 21, 27, 36, + 48, 51, 44, 32, 14, -3, -16, -28, -42, -46, -41, -33, -27, -24, -23, -15, + 1, 16, 27, 33, 42, 47, 46, 38, 21, 5, -9, -21, -34, -44, -45, -39, + -31, -28, -26, -20, -8, 9, 25, 34, 41, 49, 51, 47, 31, 11, -6, -18, + -30, -42, -48, -45, -36, -28, -26, -23, -12, 6, 23, 33, 38, 43, 51, 50, + 36, 15, 0, -12, -22, -35, -50, -50, -40, -31, -29, -27, -18, 1, 20, 32, + 36, 43, 52, 56, 45, 23, 2, -10, -20, -33, -48, -56, -49, -36, -30, -26, + -18, -5, 17, 33, 39, 40, 46, 52, 49, 32, 9, -8, -18, -26, -40, -54, + -53, -39, -30, -28, -23, -12, 10, 31, 39, 38, 42, 54, 54, 41, 17, -5, + -15, -22, -35, -53, -59, -47, -36, -30, -24, -14, 6, 27, 40, 42, 43, 51, + 56, 46, 26, 3, -13, -22, -33, -49, -61, -55, -41, -32, -26, -18, 0, 22, + 38, 45, 43, 48, 55, 50, 33, 11, -10, -21, -29, -43, -59, -60, -46, -35, + -28, -18, -6, 15, 35, 45, 46, 45, 52, 53, 41, 20, -6, -19, -26, -38, + -54, -62, -53, -39, -29, -19, -11, 6, 29, 44, 48, 45, 47, 52, 49, 32, + 5, -18, -26, -32, -45, -61, -61, -48, -35, -23, -14, -2, 22, 42, 52, 50, + 46, 50, 50, 38, 12, -15, -26, -31, -43, -59, -65, -53, -37, -25, -16, -6, + 16, 40, 53, 53, 47, 49, 51, 42, 22, -10, -27, -31, -38, -54, -67, -63, + -46, -27, -18, -7, 10, 31, 52, 59, 53, 48, 50, 46, 32, 3, -24, -34, + -39, -50, -66, -68, -54, -35, -20, -8, 6, 23, 47, 62, 59, 52, 50, 48, + 37, 13, -18, -35, -40, -46, -62, -72, -63, -43, -25, -10, 6, 20, 41, 59, + 63, 55, 49, 46, 39, 21, -9, -31, -39, -42, -52, -68, -68, -52, -32, -17, + -4, 9, 31, 54, 66, 63, 54, 51, 44, 32, 6, -26, -40, -44, -51, -65, + -72, -61, -41, -23, -5, 9, 25, 48, 64, 66, 59, 54, 46, 33, 12, -17, + -36, -45, -51, -62, -73, -67, -48, -31, -11, 8, 21, 44, 64, 70, 64, 57, + 49, 36, 20, -8, -34, -47, -52, -58, -68, -73, -59, -40, -19, 4, 17, 36, + 58, 72, 73, 65, 56, 41, 26, 4, -24, -44, -55, -63, -69, -73, -66, -51, + -28, -2, 18, 32, 51, 67, 75, 72, 62, 46, 29, 11, -13, -37, -54, -64, + -70, -71, -70, -58, -38, -13, 14, 30, 48, 64, 73, 76, 69, 52, 34, 15, + -7, -31, -50, -62, -69, -71, -71, -66, -47, -19, 8, 26, 40, 58, 73, 81, + 76, 57, 39, 23, 2, -22, -45, -62, -71, -73, -71, -69, -57, -32, 0, 26, + 41, 55, 70, 81, 83, 64, 41, 24, 6, -15, -39, -60, -71, -73, -69, -69, + -62, -40, -11, 20, 39, 51, 65, 78, 86, 75, 50, 29, 11, -8, -30, -53, + -70, -77, -71, -66, -67, -53, -22, 13, 37, 49, 60, 75, 89, 84, 58, 33, + 16, -2, -22, -47, -68, -77, -72, -67, -68, -60, -34, 0, 29, 47, 56, 69, + 85, 88, 69, 40, 20, 4, -13, -35, -61, -76, -74, -65, -66, -65, -47, -15, + 20, 43, 53, 64, 81, 89, 77, 50, 26, 9, -10, -29, -51, -71, -78, -71, + -66, -64, -52, -27, 9, 38, 54, 62, 73, 85, 82, 60, 34, 13, -3, -19, + -40, -65, -80, -74, -68, -69, -61, -40, -4, 29, 49, 61, 72, 86, 86, 70, + 45, 21, 3, -16, -33, -56, -80, -78, -70, -70, -65, -50, -18, 20, 48, 62, + 68, 80, 88, 78, 53, 26, 5, -12, -26, -45, -72, -81, -71, -67, -64, -56, + -34, 4, 37, 57, 63, 73, 85, 83, 63, 37, 16, 0, -17, -36, -63, -79, + -74, -70, -69, -63, -44, -10, 26, 52, 62, 69, 81, 84, 69, 45, 22, 3, + -15, -28, -52, -75, -76, -69, -67, -64, -52, -24, 14, 45, 60, 65, 74, 82, + 75, 54, 32, 12, -6, -21, -44, -68, -78, -74, -71, -69, -60, -34, 2, 34, + 55, 66, 73, 79, 78, 61, 39, 20, 2, -16, -34, -56, -72, -74, -70, -71, + -66, -47, -14, 21, 48, 61, 68, 76, 80, 69, 46, 27, 11, -7, -26, -50, + -68, -72, -70, -70, -69, -54, -24, 10, 39, 57, 66, 72, 76, 70, 52, 33, + 16, -4, -20, -39, -59, -70, -71, -69, -67, -60, -37, -6, 27, 50, 62, 67, + 72, 74, 61, 41, 25, 10, -10, -31, -51, -67, -74, -73, -73, -68, -48, -16, + 17, 45, 60, 66, 73, 75, 66, 48, 29, 15, -3, -24, -45, -62, -70, -72, + -74, -70, -55, -26, 7, 32, 51, 63, 70, 73, 67, 51, 35, 24, 9, -16, + -38, -54, -64, -68, -75, -75, -62, -36, -5, 22, 45, 60, 69, 74, 68, 57, + 43, 29, 15, -9, -29, -45, -60, -67, -75, -76, -64, -44, -16, 10, 32, 52, + 63, 68, 66, 59, 48, 36, 24, 6, -17, -35, -51, -60, -70, -78, -72, -55, + -27, 1, 20, 39, 56, 65, 68, 60, 51, 41, 31, 15, -9, -27, -44, -58, + -67, -75, -73, -58, -35, -8, 11, 32, 50, 60, 61, 57, 53, 47, 37, 25, + 4, -19, -35, -48, -60, -73, -76, -67, -46, -18, 2, 20, 40, 56, 64, 62, + 56, 49, 43, 34, 15, -10, -31, -45, -57, -70, -78, -69, -52, -27, -4, 13, + 34, 52, 60, 57, 53, 52, 46, 36, 22, 1, -19, -35, -50, -65, -73, -70, + -58, -41, -17, 4, 22, 42, 55, 58, 57, 55, 50, 43, 32, 12, -11, -30, + -47, -61, -71, -72, -63, -46, -26, -6, 13, 30, 47, 53, 54, 56, 52, 46, + 38, 24, 5, -20, -39, -52, -63, -67, -66, -57, -37, -15, 3, 18, 37, 50, + 55, 59, 55, 49, 45, 32, 15, -10, -34, -50, -61, -66, -66, -58, -42, -24, + -4, 11, 27, 44, 50, 54, 57, 53, 49, 39, 23, 2, -23, -43, -57, -64, + -67, -62, -50, -33, -14, 4, 18, 37, 48, 53, 57, 55, 52, 44, 30, 13, + -14, -38, -54, -62, -65, -62, -54, -42, -24, -2, 13, 28, 41, 48, 56, 57, + 52, 45, 37, 23, 0, -28, -47, -57, -62, -63, -59, -50, -34, -14, 1, 16, + 35, 48, 56, 59, 59, 54, 45, 31, 8, -20, -42, -56, -62, -64, -60, -52, + -40, -23, -5, 10, 28, 43, 52, 56, 57, 56, 49, 38, 21, -8, -33, -46, + -56, -60, -59, -56, -47, -32, -15, 0, 17, 34, 47, 55, 58, 57, 53, 43, + 30, 8, -24, -42, -52, -59, -58, -57, -51, -42, -26, -8, 11, 29, 42, 50, + 57, 59, 55, 48, 34, 15, -15, -36, -45, -52, -55, -58, -55, -43, -31, -17, + -2, 16, 37, 50, 56, 58, 58, 54, 43, 23, -8, -33, -40, -47, -54, -57, + -58, -48, -34, -23, -10, 9, 31, 48, 54, 55, 55, 57, 50, 32, 3, -28, + -37, -41, -49, -55, -58, -49, -36, -27, -17, 1, 21, 41, 50, 52, 51, 54, + 55, 41, 13, -18, -32, -35, -42, -50, -57, -55, -41, -32, -24, -10, 10, 33, + 47, 50, 51, 54, 59, 49, 24, -8, -26, -30, -37, -46, -56, -59, -46, -35, + -29, -18, 2, 25, 44, 48, 47, 51, 57, 56, 36, 5, -20, -28, -31, -40, + -51, -58, -52, -39, -33, -25, -8, 15, 38, 49, 47, 50, 56, 60, 46, 15, + -11, -25, -30, -36, -49, -60, -54, -39, -33, -30, -14, 8, 32, 47, 44, 44, + 51, 59, 52, 26, -4, -20, -24, -29, -41, -54, -55, -43, -34, -33, -26, -8, + 17, 37, 43, 42, 48, 59, 60, 42, 13, -11, -21, -25, -36, -51, -59, -51, + -38, -34, -32, -17, 10, 33, 43, 43, 44, 55, 60, 46, 21, -6, -18, -22, + -28, -42, -54, -52, -39, -30, -32, -25, -4, 20, 36, 39, 39, 48, 60, 57, + 36, 10, -11, -19, -22, -34, -51, -58, -48, -35, -36, -34, -13, 13, 35, 41, + 38, 46, 59, 61, 44, 20, -5, -20, -22, -30, -46, -56, -53, -39, -34, -36, + -22, 1, 25, 39, 39, 42, 53, 60, 54, 34, 10, -10, -17, -21, -39, -57, + -59, -48, -38, -43, -35, -11, 16, 37, 43, 42, 52, 61, 58, 41, 19, -3, + -16, -21, -31, -50, -59, -53, -40, -39, -39, -22, 5, 30, 40, 38, 45, 58, + 64, 52, 28, 5, -12, -17, -23, -44, -58, -56, -46, -40, -43, -33, -7, 22, + 39, 41, 44, 55, 64, 60, 40, 13, -7, -16, -21, -35, -56, -60, -52, -44, + -43, -40, -21, 11, 34, 40, 40, 50, 61, 64, 53, 29, 6, -10, -16, -25, + -47, -62, -61, -53, -49, -47, -35, -5, 26, 42, 45, 49, 58, 65, 59, 39, + 15, -5, -16, -22, -37, -56, -61, -56, -50, -47, -42, -21, 11, 33, 40, 44, + 53, 63, 66, 54, 29, 8, -6, -15, -28, -52, -64, -60, -57, -53, -49, -31, + 1, 28, 40, 42, 51, 63, 66, 56, 36, 14, -3, -13, -25, -45, -61, -61, + -58, -54, -47, -38, -11, 20, 36, 41, 44, 55, 64, 60, 47, 28, 9, -4, + -15, -32, -56, -67, -64, -62, -55, -48, -27, 8, 29, 41, 47, 57, 66, 65, + 56, 39, 17, 0, -13, -27, -49, -66, -68, -67, -58, -48, -36, -8, 22, 38, + 45, 53, 63, 65, 61, 51, 28, 11, -4, -20, -40, -62, -70, -71, -68, -55, + -44, -24, 9, 30, 42, 52, 66, 69, 64, 58, 42, 20, 4, -14, -34, -57, + -71, -73, -73, -63, -51, -35, -5, 23, 38, 48, 62, 71, 69, 65, 54, 32, + 14, -6, -26, -48, -68, -79, -82, -72, -57, -42, -18, 11, 33, 48, 63, 73, + 72, 68, 62, 46, 22, 0, -21, -42, -63, -76, -83, -80, -65, -49, -28, -2, + 23, 42, 58, 71, 75, 72, 68, 56, 33, 10, -12, -32, -54, -73, -84, -87, + -73, -54, -36, -15, 11, 34, 52, 67, 73, 73, 72, 66, 48, 21, -6, -26, + -47, -67, -80, -88, -81, -62, -41, -23, 0, 27, 47, 65, 74, 74, 71, 67, + 57, 33, 4, -20, -42, -64, -77, -88, -88, -72, -49, -27, -7, 16, 40, 63, + 75, 75, 74, 69, 64, 46, 16, -13, -35, -57, -74, -87, -93, -81, -58, -35, + -17, 6, 33, 59, 73, 76, 76, 71, 68, 58, 29, -4, -29, -48, -68, -83, + -94, -92, -70, -42, -22, -4, 21, 51, 73, 78, 76, 73, 70, 63, 40, 7, + -24, -42, -60, -79, -91, -92, -76, -52, -30, -12, 9, 39, 66, 76, 76, 75, + 74, 70, 54, 24, -12, -36, -52, -72, -93, -100, -90, -64, -38, -21, -5, 25, + 61, 81, 81, 77, 78, 76, 63, 33, -5, -33, -49, -67, -90, -100, -92, -71, + -44, -21, -8, 14, 49, 75, 82, 77, 76, 75, 66, 45, 10, -27, -45, -59, + -80, -98, -98, -81, -52, -26, -12, 2, 34, 71, 86, 80, 75, 77, 71, 54, + 23, -17, -44, -57, -74, -93, -99, -87, -65, -36, -14, -4, 20, 55, 79, 82, + 78, 78, 75, 65, 41, 1, -34, -52, -67, -88, -104, -98, -76, -47, -23, -12, + 6, 45, 81, 90, 81, 79, 81, 72, 50, 11, -28, -50, -61, -81, -102, -103, + -84, -57, -30, -13, 1, 30, 70, 92, 88, 81, 80, 75, 59, 27, -15, -48, + -62, -76, -97, -106, -94, -69, -39, -16, -4, 17, 59, 92, 94, 87, 86, 83, + 67, 36, -4, -38, -61, -77, -96, -111, -102, -80, -53, -26, -8, 14, 50, 89, + 101, 93, 87, 83, 73, 46, 7, -31, -58, -72, -87, -106, -106, -88, -59, -31, + -12, 5, 33, 74, 99, 99, 90, 84, 78, 57, 22, -18, -49, -70, -84, -100, + -108, -96, -72, -43, -21, -3, 24, 61, 95, 106, 99, 90, 82, 65, 34, -6, + -40, -66, -83, -96, -106, -102, -82, -52, -27, -8, 15, 48, 86, 107, 105, 94, + 85, 73, 45, 6, -32, -61, -80, -91, -102, -106, -92, -63, -35, -15, 8, 37, + 74, 102, 109, 98, 87, 76, 54, 21, -16, -50, -76, -89, -98, -104, -98, -76, + -46, -23, -2, 25, 60, 93, 111, 106, 92, 82, 65, 35, -5, -39, -66, -83, + -95, -105, -105, -86, -57, -33, -11, 15, 50, 86, 111, 115, 102, 88, 71, 43, + 7, -32, -64, -86, -96, -100, -102, -92, -67, -40, -13, 13, 42, 75, 103, 116, + 106, 90, 74, 49, 16, -21, -54, -80, -94, -98, -100, -94, -75, -50, -23, 4, + 30, 62, 95, 117, 115, 100, 81, 57, 28, -10, -46, -75, -95, -102, -101, -97, + -83, -61, -32, -2, 24, 55, 87, 111, 118, 106, 88, 65, 35, 0, -36, -67, + -89, -101, -102, -98, -89, -68, -43, -13, 16, 46, 80, 107, 121, 116, 98, 75, + 47, 11, -27, -62, -87, -101, -104, -100, -93, -77, -51, -18, 13, 36, 67, 99, + 119, 119, 103, 81, 53, 21, -16, -52, -79, -96, -106, -102, -93, -82, -60, -30, + 3, 30, 59, 88, 111, 121, 111, 89, 61, 30, -4, -41, -74, -94, -106, -104, + -95, -87, -70, -41, -8, 22, 49, 81, 106, 120, 118, 98, 73, 41, 8, -30, + -64, -87, -104, -111, -100, -91, -77, -51, -21, 13, 41, 73, 100, 117, 122, 107, + 83, 52, 19, -18, -55, -82, -101, -111, -105, -93, -83, -60, -29, 5, 35, 64, + 92, 112, 121, 112, 88, 61, 29, -7, -45, -75, -94, -108, -108, -96, -87, -67, + -37, -5, 26, 52, 83, 105, 116, 116, 97, 70, 41, 7, -33, -67, -91, -105, + -110, -99, -88, -73, -48, -18, 15, 45, 74, 98, 114, 118, 104, 79, 51, 17, + -21, -58, -86, -102, -109, -103, -90, -77, -54, -23, 9, 36, 62, 88, 107, 114, + 107, 88, 63, 30, -8, -46, -77, -96, -107, -108, -97, -81, -63, -36, -4, 30, + 59, 84, 104, 115, 112, 95, 69, 38, 5, -33, -69, -94, -104, -105, -99, -87, + -72, -44, -11, 21, 47, 71, 97, 113, 113, 99, 77, 49, 17, -19, -57, -87, + -101, -105, -103, -90, -72, -54, -24, 10, 41, 64, 86, 104, 111, 104, 85, 57, + 25, -7, -42, -75, -96, -101, -98, -92, -79, -61, -36, -4, 28, 51, 74, 98, + 110, 107, 94, 70, 38, 5, -30, -64, -89, -101, -101, -95, -79, -63, -43, -14, + 21, 48, 68, 90, 105, 108, 97, 74, 44, 12, -20, -52, -83, -96, -96, -92, + -82, -67, -49, -24, 10, 39, 59, 79, 99, 107, 101, 83, 54, 21, -11, -41, + -71, -92, -98, -95, -84, -68, -54, -35, -5, 28, 54, 73, 92, 103, 103, 90, + 64, 31, -4, -34, -63, -85, -94, -92, -84, -70, -56, -38, -11, 19, 44, 64, + 83, 95, 98, 90, 66, 39, 9, -22, -50, -73, -86, -89, -84, -72, -59, -45, + -23, 6, 35, 58, 75, 89, 96, 92, 75, 49, 19, -14, -42, -63, -80, -88, + -84, -74, -60, -48, -30, -5, 23, 52, 70, 82, 91, 91, 79, 57, 29, -3, + -33, -54, -70, -84, -87, -79, -65, -50, -35, -16, 10, 41, 68, 80, 85, 88, + 82, 64, 36, 3, -28, -49, -60, -72, -83, -81, -66, -49, -37, -22, -2, 28, + 58, 74, 78, 83, 81, 69, 45, 14, -18, -42, -55, -66, -77, -79, -68, -53, + -39, -25, -8, 17, 46, 67, 72, 75, 74, 70, 53, 24, -9, -34, -48, -55, + -64, -74, -70, -55, -40, -28, -17, 3, 33, 61, 70, 71, 69, 68, 61, 37, + 3, -28, -44, -50, -57, -70, -73, -58, -41, -30, -21, -8, 21, 52, 67, 69, + 66, 66, 64, 44, 10, -22, -39, -48, -52, -61, -72, -62, -43, -29, -20, -12, + 7, 38, 62, 68, 61, 56, 60, 51, 23, -12, -36, -43, -44, -49, -65, -65, + -45, -29, -22, -19, -7, 24, 52, 65, 57, 52, 58, 57, 36, 0, -30, -38, + -37, -39, -55, -66, -52, -33, -23, -21, -14, 10, 40, 60, 59, 49, 51, 54, + 43, 11, -21, -35, -37, -33, -42, -55, -49, -29, -19, -20, -19, -5, 23, 49, + 54, 43, 42, 50, 49, 23, -12, -30, -34, -29, -31, -49, -54, -35, -19, -16, + -18, -11, 10, 39, 55, 45, 35, 41, 47, 31, -3, -26, -33, -28, -23, -36, + -47, -36, -18, -11, -16, -16, -3, 21, 42, 42, 32, 32, 40, 35, 13, -13, + -25, -24, -17, -22, -37, -38, -25, -16, -16, -19, -11, 7, 30, 42, 34, 27, + 33, 35, 19, -6, -21, -23, -17, -14, -23, -29, -21, -11, -10, -17, -16, -4, + 14, 30, 31, 20, 21, 29, 24, 6, -11, -16, -11, -5, -10, -20, -22, -15, + -12, -17, -21, -15, 0, 20, 29, 22, 17, 23, 25, 16, -2, -14, -14, -7, + -2, -9, -14, -12, -9, -11, -17, -17, -11, 3, 18, 17, 9, 13, 19, 17, + 7, -5, -5, 3, 8, 3, -7, -10, -12, -14, -20, -22, -17, -7, 9, 17, + 10, 8, 15, 18, 11, 2, -3, 1, 8, 9, 5, -3, -9, -12, -18, -21, + -21, -19, -4, 10, 9, 2, 5, 14, 16, 11, 4, 5, 13, 16, 14, 6, + -8, -14, -19, -23, -24, -21, -13, -2, 7, 3, -2, 8, 12, 11, 9, 10, + 14, 19, 20, 16, 4, -9, -17, -23, -26, -27, -24, -14, -2, 1, -5, 3, + 15, 17, 14, 14, 17, 22, 25, 20, 9, -8, -19, -25, -30, -29, -26, -22, + -11, 0, -3, -3, 9, 16, 19, 20, 21, 24, 28, 28, 20, 2, -16, -25, + -30, -34, -33, -32, -23, -9, -6, -8, 2, 15, 21, 24, 26, 29, 33, 34, + 30, 14, -11, -26, -33, -38, -38, -37, -34, -23, -12, -7, 0, 11, 21, 29, + 34, 35, 37, 39, 35, 21, -5, -26, -34, -39, -40, -42, -42, -31, -17, -9, + -4, 7, 19, 31, 38, 38, 41, 42, 40, 28, 3, -22, -36, -42, -45, -46, + -46, -37, -23, -14, -6, 6, 20, 32, 40, 40, 44, 46, 41, 31, 13, -12, + -32, -44, -47, -48, -49, -44, -32, -20, -8, 3, 15, 27, 40, 45, 47, 50, + 47, 39, 21, -6, -29, -42, -46, -51, -56, -52, -41, -24, -13, -4, 11, 27, + 41, 51, 52, 53, 52, 45, 29, 2, -25, -45, -50, -52, -57, -56, -49, -32, + -16, -4, 9, 22, 36, 49, 55, 56, 56, 50, 35, 11, -14, -37, -51, -57, + -61, -61, -56, -41, -23, -8, 8, 21, 33, 48, 61, 64, 60, 54, 40, 17, + -8, -34, -52, -59, -62, -63, -60, -49, -30, -14, 2, 19, 33, 47, 60, 66, + 67, 65, 50, 25, -3, -26, -47, -59, -68, -72, -66, -57, -38, -20, -5, 14, + 30, 44, 61, 71, 71, 68, 57, 34, 7, -20, -43, -58, -68, -72, -69, -62, + -45, -25, -10, 7, 24, 42, 59, 70, 74, 73, 65, 46, 16, -15, -38, -53, + -65, -77, -77, -70, -54, -34, -19, 0, 20, 41, 60, 74, 82, 80, 71, 54, + 27, -8, -36, -55, -68, -78, -82, -76, -61, -40, -20, -2, 17, 36, 57, 74, + 83, 82, 74, 62, 39, 3, -31, -49, -62, -75, -84, -84, -69, -47, -27, -13, + 6, 31, 56, 73, 82, 86, 80, 68, 49, 14, -24, -46, -60, -74, -83, -86, + -76, -54, -32, -15, 3, 23, 48, 71, 85, 87, 80, 71, 57, 27, -12, -41, + -57, -68, -78, -88, -84, -64, -41, -23, -5, 16, 40, 65, 84, 90, 87, 77, + 63, 36, -3, -34, -57, -69, -76, -85, -87, -73, -48, -27, -8, 13, 34, 60, + 83, 91, 86, 77, 66, 44, 9, -26, -53, -68, -74, -83, -88, -80, -56, -33, + -13, 9, 29, 55, 79, 93, 89, 76, 67, 52, 21, -15, -46, -69, -74, -77, + -84, -86, -67, -42, -20, 4, 23, 43, 71, 94, 95, 80, 67, 56, 32, 0, + -37, -66, -74, -73, -78, -87, -76, -50, -25, 1, 21, 37, 61, 88, 97, 84, + 67, 57, 38, 8, -25, -59, -77, -77, -76, -81, -80, -61, -34, -6, 20, 36, + 55, 80, 96, 91, 70, 54, 39, 17, -14, -51, -75, -79, -75, -77, -80, -68, + -40, -11, 15, 33, 48, 71, 92, 91, 73, 57, 45, 24, -3, -38, -68, -79, + -77, -76, -80, -74, -51, -19, 12, 32, 46, 65, 88, 96, 83, 59, 40, 24, + 4, -31, -67, -83, -80, -73, -73, -72, -55, -24, 9, 31, 44, 58, 78, 90, + 84, 63, 42, 28, 10, -18, -53, -77, -82, -76, -73, -74, -65, -37, -2, 27, + 42, 55, 73, 88, 90, 72, 47, 28, 13, -12, -45, -74, -84, -78, -70, -68, + -63, -43, -9, 23, 42, 52, 64, 78, 84, 75, 52, 32, 17, -3, -32, -62, + -79, -78, -71, -67, -65, -52, -19, 15, 38, 50, 61, 73, 80, 79, 59, 34, + 18, 3, -21, -51, -75, -81, -72, -64, -61, -54, -31, 4, 31, 48, 55, 63, + 73, 78, 67, 40, 21, 8, -12, -39, -65, -80, -76, -65, -58, -52, -38, -8, + 25, 45, 56, 61, 67, 74, 69, 47, 22, 7, -10, -31, -56, -75, -77, -66, + -57, -49, -37, -14, 16, 40, 53, 57, 61, 67, 69, 55, 30, 11, -6, -25, + -47, -69, -78, -70, -59, -51, -40, -20, 10, 34, 51, 58, 59, 63, 66, 59, + 36, 14, -2, -19, -40, -61, -75, -71, -59, -51, -41, -27, -2, 26, 47, 58, + 58, 59, 64, 63, 46, 19, -2, -17, -35, -56, -71, -75, -64, -50, -40, -26, + -6, 21, 43, 55, 57, 56, 58, 59, 47, 23, 1, -13, -29, -48, -63, -69, + -61, -48, -40, -29, -11, 13, 35, 48, 53, 51, 53, 57, 50, 33, 9, -10, + -25, -42, -56, -65, -64, -51, -40, -29, -13, 9, 30, 44, 50, 48, 47, 50, + 46, 35, 13, -8, -20, -33, -47, -57, -56, -48, -38, -30, -16, 1, 21, 35, + 44, 46, 42, 44, 44, 39, 21, -3, -18, -30, -40, -51, -57, -51, -37, -26, + -14, 0, 16, 33, 42, 43, 37, 34, 37, 35, 22, 1, -17, -27, -34, -41, + -48, -45, -36, -25, -11, 0, 11, 24, 34, 38, 35, 30, 29, 30, 24, 8, + -11, -24, -31, -36, -42, -42, -35, -25, -12, -2, 9, 21, 29, 33, 32, 27, + 25, 26, 23, 9, -8, -21, -31, -34, -36, -37, -33, -26, -13, -2, 8, 18, + 24, 28, 29, 27, 22, 20, 21, 14, -2, -17, -27, -30, -31, -33, -32, -26, + -14, -3, 6, 15, 22, 27, 26, 25, 22, 17, 17, 13, 3, -12, -25, -30, + -31, -30, -27, -24, -14, 0, 8, 16, 20, 22, 22, 21, 16, 11, 13, 13, + 3, -8, -21, -27, -26, -25, -25, -23, -12, 0, 6, 12, 18, 20, 22, 20, + 15, 9, 9, 10, 3, -9, -21, -29, -28, -23, -20, -19, -10, 3, 13, 17, + 19, 19, 21, 17, 11, 4, 1, 4, 0, -8, -17, -25, -24, -21, -19, -16, + -9, 4, 13, 17, 19, 20, 22, 19, 11, 3, -4, -3, -4, -12, -18, -26, + -28, -23, -16, -10, -5, 5, 18, 25, 25, 22, 21, 19, 9, 0, -9, -11, + -10, -13, -16, -24, -27, -22, -14, -8, -2, 7, 17, 25, 25, 22, 20, 17, + 10, -2, -10, -12, -13, -15, -18, -20, -24, -22, -16, -8, 3, 11, 17, 25, + 27, 23, 21, 17, 9, 0, -10, -12, -13, -18, -19, -20, -24, -23, -17, -10, + 0, 11, 19, 26, 30, 26, 24, 20, 12, 3, -8, -15, -18, -22, -25, -25, + -25, -24, -20, -12, 2, 15, 20, 25, 31, 33, 29, 23, 12, 3, -5, -15, + -23, -28, -28, -25, -22, -22, -18, -10, 2, 15, 19, 23, 30, 32, 28, 24, + 15, 7, 1, -13, -23, -27, -29, -28, -26, -24, -20, -14, -2, 13, 20, 24, + 32, 34, 32, 29, 22, 9, -2, -10, -21, -30, -34, -34, -29, -22, -20, -18, + -5, 14, 23, 25, 31, 36, 35, 30, 22, 10, 0, -8, -21, -34, -39, -36, + -32, -27, -20, -15, -5, 14, 27, 28, 32, 36, 35, 33, 25, 14, 0, -11, + -21, -34, -40, -41, -39, -30, -20, -13, -6, 10, 27, 30, 32, 35, 34, 36, + 29, 17, 5, -7, -16, -33, -45, -45, -43, -33, -24, -18, -9, 8, 26, 32, + 33, 39, 38, 36, 31, 20, 10, -6, -19, -32, -45, -47, -46, -39, -25, -12, + -3, 8, 22, 32, 32, 35, 35, 32, 31, 23, 14, 0, -15, -26, -43, -51, + -50, -43, -29, -17, -6, 5, 19, 34, 36, 33, 37, 37, 34, 25, 16, 5, + -11, -26, -41, -51, -55, -51, -36, -21, -7, 7, 16, 28, 37, 35, 35, 36, + 34, 30, 20, 9, -7, -22, -37, -49, -56, -54, -42, -25, -11, 2, 13, 24, + 35, 38, 37, 38, 37, 32, 25, 16, 1, -21, -38, -47, -56, -58, -50, -34, + -14, 4, 13, 20, 31, 40, 39, 35, 36, 34, 28, 20, 5, -15, -33, -44, + -55, -63, -54, -38, -19, -2, 10, 17, 30, 40, 41, 36, 38, 41, 33, 22, + 9, -13, -36, -50, -55, -63, -61, -44, -22, 2, 18, 22, 28, 38, 42, 39, + 34, 35, 34, 27, 14, -7, -29, -43, -51, -60, -63, -50, -30, -10, 8, 16, + 21, 32, 40, 40, 38, 39, 41, 35, 24, 6, -20, -41, -54, -62, -65, -58, + -39, -16, 7, 18, 22, 29, 39, 43, 40, 35, 38, 37, 27, 12, -14, -37, + -51, -58, -64, -64, -47, -22, -2, 14, 18, 24, 36, 44, 45, 41, 43, 43, + 32, 17, -8, -35, -54, -63, -67, -68, -56, -29, -4, 16, 24, 26, 35, 44, + 47, 43, 38, 38, 36, 24, 0, -30, -50, -57, -59, -63, -61, -40, -11, 11, + 20, 20, 26, 39, 48, 46, 40, 39, 42, 33, 12, -20, -47, -58, -60, -62, + -61, -49, -23, 2, 17, 21, 22, 33, 48, 51, 45, 43, 43, 38, 20, -10, + -41, -58, -61, -64, -62, -55, -35, -9, 10, 21, 23, 32, 50, 57, 49, 45, + 45, 43, 26, -6, -38, -58, -62, -65, -67, -61, -44, -15, 10, 23, 26, 28, + 44, 59, 55, 46, 42, 41, 33, 6, -30, -57, -64, -62, -64, -62, -50, -26, + 2, 18, 26, 28, 39, 59, 60, 48, 43, 43, 37, 14, -22, -53, -67, -63, + -65, -66, -55, -33, -2, 19, 28, 31, 37, 55, 64, 53, 41, 39, 37, 20, + -16, -48, -66, -65, -62, -66, -60, -43, -12, 15, 26, 31, 37, 53, 69, 63, + 46, 39, 38, 27, -5, -44, -72, -73, -65, -65, -63, -52, -24, 11, 31, 36, + 38, 48, 65, 70, 53, 38, 34, 28, 5, -35, -69, -78, -70, -65, -63, -53, + -30, 2, 26, 38, 43, 49, 62, 69, 58, 40, 33, 28, 9, -25, -61, -78, + -75, -69, -64, -55, -37, -7, 22, 36, 43, 49, 57, 66, 62, 44, 31, 29, + 15, -16, -52, -76, -77, -69, -63, -57, -44, -16, 14, 33, 42, 48, 54, 65, + 68, 52, 33, 27, 19, -6, -41, -72, -82, -74, -65, -59, -48, -24, 7, 29, + 43, 50, 53, 60, 67, 58, 39, 28, 22, 2, -31, -64, -82, -79, -71, -61, + -49, -31, -2, 22, 40, 51, 55, 58, 65, 63, 46, 29, 21, 9, -21, -56, + -79, -83, -77, -65, -54, -37, -10, 16, 36, 50, 57, 60, 65, 64, 50, 33, + 22, 11, -13, -47, -73, -82, -80, -70, -57, -42, -19, 8, 30, 49, 58, 61, + 62, 64, 56, 41, 24, 11, -6, -35, -66, -80, -82, -75, -61, -45, -25, -2, + 22, 43, 57, 63, 64, 63, 58, 49, 31, 15, -2, -26, -58, -79, -85, -81, + -66, -49, -31, -9, 17, 39, 55, 64, 69, 67, 61, 53, 35, 16, 1, -20, + -49, -75, -86, -85, -74, -54, -34, -11, 11, 33, 53, 64, 70, 68, 59, 51, + 40, 22, 5, -15, -40, -66, -79, -81, -78, -63, -41, -19, 4, 25, 44, 58, + 67, 72, 65, 57, 47, 29, 11, -8, -31, -61, -81, -85, -82, -68, -47, -25, + -3, 21, 44, 59, 68, 73, 68, 56, 47, 33, 15, -7, -27, -52, -76, -82, + -82, -72, -52, -30, -7, 13, 36, 57, 67, 74, 72, 61, 48, 36, 20, -4, + -25, -47, -71, -81, -81, -75, -56, -33, -10, 11, 30, 49, 63, 73, 74, 63, + 48, 37, 25, 6, -20, -41, -63, -79, -81, -77, -65, -43, -19, 4, 25, 45, + 63, 73, 76, 70, 55, 41, 28, 10, -15, -38, -59, -77, -83, -79, -70, -49, + -25, -4, 20, 40, 59, 74, 76, 73, 62, 46, 33, 16, -10, -34, -51, -68, + -83, -85, -75, -58, -34, -11, 14, 35, 55, 73, 79, 76, 69, 51, 33, 20, + -2, -30, -53, -67, -81, -84, -76, -61, -39, -14, 11, 32, 49, 67, 77, 74, + 68, 55, 37, 23, 5, -22, -45, -59, -73, -84, -82, -68, -46, -24, 3, 26, + 43, 62, 75, 74, 72, 61, 42, 25, 10, -15, -40, -57, -70, -83, -84, -71, + -49, -28, -6, 20, 41, 59, 72, 72, 69, 63, 48, 29, 13, -8, -31, -51, + -66, -79, -84, -75, -56, -37, -16, 12, 36, 55, 71, 74, 72, 69, 54, 34, + 16, -5, -28, -47, -61, -75, -85, -80, -60, -38, -20, 4, 30, 53, 68, 71, + 69, 67, 57, 39, 20, 0, -21, -41, -58, -71, -79, -79, -66, -45, -25, -3, + 23, 45, 61, 68, 69, 70, 63, 47, 29, 8, -16, -37, -56, -71, -80, -81, + -71, -52, -30, -7, 17, 41, 60, 67, 67, 68, 65, 50, 30, 10, -14, -31, + -47, -65, -77, -79, -70, -53, -33, -14, 8, 34, 56, 62, 62, 66, 64, 54, + 36, 15, -8, -27, -42, -61, -73, -75, -70, -56, -36, -14, 5, 26, 49, 60, + 59, 61, 60, 54, 42, 23, -2, -22, -35, -53, -69, -75, -70, -58, -41, -20, + -3, 18, 43, 59, 57, 57, 60, 56, 44, 28, 7, -17, -32, -47, -63, -73, + -72, -62, -46, -23, -6, 12, 35, 55, 60, 57, 59, 56, 49, 35, 14, -13, + -28, -40, -58, -72, -73, -62, -50, -31, -13, 5, 30, 51, 59, 56, 58, 61, + 56, 38, 17, -9, -26, -37, -52, -68, -74, -63, -50, -32, -14, 1, 22, 45, + 57, 56, 51, 54, 54, 41, 21, -4, -22, -31, -44, -59, -69, -63, -48, -36, + -21, -7, 11, 35, 52, 56, 53, 54, 58, 48, 30, 8, -17, -32, -43, -57, + -68, -69, -56, -39, -22, -8, 6, 28, 49, 57, 54, 51, 55, 52, 35, 13, + -13, -29, -36, -49, -64, -70, -58, -39, -23, -11, 0, 19, 43, 57, 55, 47, + 49, 55, 43, 18, -9, -28, -35, -42, -57, -69, -65, -45, -25, -11, 1, 14, + 37, 55, 60, 50, 45, 48, 42, 21, -4, -25, -35, -40, -50, -60, -61, -46, + -27, -15, -6, 6, 25, 46, 56, 50, 43, 45, 47, 33, 9, -15, -30, -37, + -45, -58, -64, -56, -36, -18, -8, 4, 18, 40, 58, 59, 47, 39, 41, 35, + 12, -15, -32, -38, -39, -46, -57, -55, -37, -17, -7, 1, 11, 27, 48, 56, + 47, 37, 38, 38, 21, -6, -24, -32, -37, -43, -54, -57, -44, -25, -9, 2, + 11, 24, 44, 57, 51, 38, 32, 31, 21, -5, -28, -35, -36, -36, -45, -51, + -41, -25, -8, 3, 8, 17, 33, 48, 49, 37, 31, 30, 25, 7, -18, -30, + -34, -37, -40, -48, -47, -33, -16, 1, 11, 16, 28, 42, 50, 43, 30, 25, + 22, 10, -12, -28, -33, -34, -35, -41, -44, -33, -18, -2, 9, 12, 20, 32, + 43, 41, 29, 24, 22, 14, -3, -21, -29, -30, -31, -35, -41, -35, -21, -6, + 9, 13, 18, 27, 38, 42, 29, 18, 16, 13, 4, -15, -27, -28, -27, -28, + -34, -34, -23, -10, 5, 11, 14, 22, 32, 37, 31, 20, 16, 12, 6, -9, + -22, -25, -27, -26, -32, -34, -27, -15, 0, 10, 12, 18, 28, 36, 35, 23, + 14, 11, 8, -3, -19, -28, -28, -25, -27, -32, -28, -16, -2, 11, 14, 14, + 22, 30, 31, 24, 15, 11, 8, 2, -11, -22, -25, -25, -26, -30, -28, -18, + -7, 5, 12, 14, 19, 27, 30, 26, 19, 13, 9, 4, -6, -20, -26, -23, + -24, -27, -27, -19, -6, 4, 12, 12, 13, 22, 26, 22, 15, 11, 10, 6, + -2, -12, -19, -19, -21, -25, -25, -20, -11, -3, 5, 9, 13, 19, 24, 24, + 21, 15, 12, 7, 2, -9, -20, -22, -22, -23, -24, -22, -11, -2, 7, 11, + 13, 17, 21, 21, 18, 13, 11, 7, 1, -7, -15, -19, -19, -21, -20, -18, + -12, -4, 2, 8, 11, 15, 17, 16, 15, 13, 11, 8, 4, -3, -11, -16, + -15, -19, -20, -16, -12, -5, 2, 5, 8, 14, 17, 15, 11, 10, 9, 8, + 4, -2, -6, -11, -12, -14, -18, -13, -7, -6, -3, 2, 6, 10, 13, 13, + 9, 8, 9, 6, 1, 0, -5, -9, -12, -12, -13, -12, -4, 1, 3, 4, + 4, 7, 11, 10, 7, 3, 3, 4, 2, -2, -3, -6, -7, -6, -6, -8, + -5, 2, 1, 1, 0, 1, 5, 5, 3, 0, 0, 5, 5, 2, 3, 0, + -3, -5, -6, -8, -7, -2, -3, -4, -2, -2, 3, 6, 4, 1, -3, 1, + 5, 3, 2, 0, -2, -3, -4, -5, -5, 1, 2, -3, -3, -4, -3, 4, + 4, 0, -5, -3, 3, 3, 2, 1, 1, 0, 0, 0, -3, -2, 1, -2, + -4, -3, -4, 1, 5, 2, -5, -7, -2, 2, -2, -2, 0, 2, 3, 2, + 2, 3, 6, 4, -2, -5, -6, -2, 3, -2, -9, -11, -5, 0, -3, -4, + -2, 3, 7, 8, 4, 2, 4, 3, 0, -6, -8, -6, 2, 4, -3, -10, + -10, -5, -2, -4, -5, -3, 5, 11, 11, 8, 5, 5, 4, -2, -9, -9, + -2, 0, -5, -13, -14, -10, -5, -4, -2, 2, 6, 14, 15, 11, 8, 6, + 1, -5, -10, -12, -6, 1, -2, -10, -15, -11, -4, -3, -6, -5, 2, 14, + 19, 14, 10, 10, 8, 3, -6, -15, -12, -4, -4, -12, -18, -17, -10, -2, + 0, 1, 6, 16, 25, 21, 12, 8, 4, -2, -8, -18, -20, -11, -6, -9, + -14, -14, -10, -3, 0, 1, 6, 13, 23, 25, 17, 13, 9, 1, -6, -13, + -18, -14, -11, -13, -17, -19, -14, -8, -3, 1, 7, 14, 24, 30, 24, 16, + 12, 4, -5, -11, -18, -19, -15, -12, -14, -19, -18, -14, -9, 0, 8, 13, + 19, 27, 28, 22, 18, 9, -4, -11, -14, -16, -15, -16, -16, -17, -16, -14, + -13, -6, 4, 12, 19, 26, 31, 27, 19, 13, 3, -8, -12, -16, -18, -19, + -17, -16, -20, -18, -15, -10, 1, 10, 18, 24, 31, 30, 22, 18, 9, -4, + -10, -14, -17, -20, -22, -19, -19, -22, -18, -13, -2, 9, 16, 21, 29, 36, + 29, 19, 12, 1, -7, -10, -15, -22, -24, -20, -18, -21, -21, -17, -8, 7, + 16, 23, 27, 33, 35, 26, 17, 7, -5, -11, -14, -22, -27, -24, -19, -22, + -25, -19, -11, 5, 16, 21, 25, 33, 38, 31, 18, 9, -2, -10, -13, -22, + -29, -28, -21, -18, -24, -22, -15, -3, 14, 21, 24, 30, 38, 36, 24, 13, + 4, -5, -9, -16, -28, -32, -25, -21, -25, -27, -18, -7, 8, 18, 24, 31, + 40, 40, 29, 16, 6, -3, -8, -16, -27, -31, -27, -22, -24, -27, -21, -10, + 4, 16, 22, 28, 37, 40, 33, 19, 7, 1, -5, -12, -23, -32, -28, -23, + -23, -27, -26, -15, -2, 13, 21, 25, 34, 41, 38, 28, 14, 4, -3, -11, + -22, -34, -35, -30, -26, -28, -29, -20, -3, 14, 24, 27, 32, 41, 42, 34, + 17, 4, -4, -11, -20, -32, -38, -33, -28, -27, -27, -22, -9, 7, 20, 29, + 34, 39, 40, 37, 24, 10, 2, -7, -16, -28, -40, -40, -33, -29, -28, -27, + -16, 5, 21, 28, 32, 36, 41, 40, 30, 12, 1, -6, -11, -22, -37, -42, + -34, -30, -29, -27, -20, -3, 16, 27, 32, 34, 39, 41, 35, 20, 6, -4, + -11, -16, -32, -45, -41, -33, -31, -27, -23, -10, 13, 28, 33, 35, 38, 39, + 36, 25, 8, -6, -11, -14, -26, -42, -45, -34, -29, -25, -23, -15, 6, 26, + 36, 36, 36, 37, 36, 29, 14, -2, -12, -14, -23, -42, -50, -42, -32, -23, + -18, -15, 3, 25, 38, 39, 35, 35, 37, 33, 18, -3, -15, -18, -20, -34, + -48, -47, -34, -22, -14, -12, -4, 17, 35, 41, 37, 34, 33, 33, 24, 6, + -13, -22, -22, -30, -45, -51, -39, -23, -10, -6, -3, 13, 32, 41, 37, 30, + 29, 31, 27, 10, -10, -22, -23, -26, -38, -48, -44, -28, -12, -5, -3, 9, + 27, 38, 38, 32, 28, 29, 27, 17, -4, -21, -26, -27, -35, -47, -49, -33, + -12, 2, 5, 9, 23, 35, 40, 34, 21, 23, 25, 22, 5, -20, -28, -28, + -29, -39, -50, -43, -19, 3, 10, 7, 15, 29, 41, 43, 28, 22, 23, 22, + 12, -16, -33, -32, -32, -38, -46, -43, -21, 3, 15, 13, 16, 29, 35, 35, + 27, 19, 19, 19, 15, -8, -30, -31, -30, -32, -40, -44, -29, -2, 18, 17, + 11, 22, 34, 37, 32, 21, 18, 20, 17, -2, -28, -37, -34, -34, -38, -42, + -30, -7, 16, 22, 16, 20, 31, 31, 29, 23, 17, 18, 19, 6, -21, -37, + -35, -34, -35, -38, -35, -15, 14, 27, 21, 13, 23, 31, 31, 26, 16, 12, + 16, 12, -10, -35, -39, -35, -36, -36, -34, -21, 6, 24, 24, 16, 20, 29, + 28, 27, 22, 16, 17, 15, -4, -29, -41, -39, -40, -39, -36, -29, -6, 20, + 27, 21, 19, 28, 33, 31, 27, 18, 14, 13, 2, -22, -41, -43, -40, -39, + -34, -28, -12, 16, 28, 24, 19, 25, 29, 27, 24, 19, 15, 12, 4, -15, + -34, -41, -40, -37, -32, -26, -18, 5, 24, 24, 20, 21, 26, 27, 26, 24, + 18, 12, 6, -9, -30, -44, -45, -41, -33, -26, -19, -2, 23, 29, 24, 22, + 24, 28, 25, 22, 18, 13, 7, -7, -24, -40, -46, -42, -36, -28, -21, -6, + 15, 28, 25, 22, 25, 29, 28, 23, 20, 14, 6, -6, -22, -40, -47, -42, + -36, -28, -23, -10, 13, 30, 28, 21, 23, 27, 28, 21, 18, 16, 9, -2, + -17, -33, -44, -44, -38, -31, -23, -14, 5, 25, 32, 25, 23, 26, 29, 24, + 16, 13, 8, -2, -15, -31, -43, -44, -37, -30, -23, -14, 1, 21, 31, 27, + 22, 24, 28, 25, 17, 13, 10, 3, -10, -27, -40, -44, -38, -32, -26, -17, + -3, 16, 31, 31, 25, 25, 30, 29, 17, 8, 7, 3, -8, -25, -39, -43, + -37, -31, -27, -18, -4, 13, 29, 32, 26, 24, 27, 27, 17, 9, 8, 6, + -5, -20, -34, -39, -37, -34, -30, -21, -8, 6, 23, 34, 31, 29, 28, 27, + 22, 13, 6, 5, -4, -18, -34, -40, -37, -34, -29, -23, -10, 5, 21, 32, + 29, 27, 29, 26, 20, 12, 4, 3, 0, -12, -28, -37, -35, -31, -29, -23, + -13, 1, 16, 30, 33, 29, 27, 25, 21, 15, 5, -2, -3, -9, -22, -35, + -36, -31, -29, -24, -14, 0, 12, 27, 35, 31, 29, 26, 21, 16, 8, -2, + -3, -7, -19, -34, -36, -32, -31, -28, -18, -3, 11, 22, 32, 32, 30, 29, + 23, 16, 11, 2, -3, -6, -17, -32, -37, -32, -30, -31, -23, -6, 9, 18, + 30, 36, 32, 31, 25, 17, 13, 4, -6, -8, -14, -26, -36, -34, -31, -31, + -25, -11, 6, 16, 24, 34, 35, 33, 28, 17, 16, 10, -3, -9, -13, -23, + -34, -36, -32, -31, -27, -16, 2, 16, 22, 30, 35, 33, 30, 21, 15, 11, + 0, -7, -11, -20, -31, -35, -31, -31, -29, -21, -6, 13, 21, 25, 32, 34, + 33, 26, 18, 13, 4, -6, -10, -19, -29, -34, -34, -29, -27, -24, -12, 7, + 20, 25, 30, 33, 32, 29, 21, 13, 7, -5, -11, -18, -28, -35, -36, -29, + -25, -24, -16, 3, 21, 26, 28, 34, 37, 34, 26, 12, 4, -5, -13, -20, + -30, -35, -39, -35, -24, -19, -13, -2, 15, 27, 30, 32, 34, 31, 28, 18, + 5, -6, -15, -20, -24, -31, -37, -35, -24, -19, -16, -9, 8, 24, 30, 30, + 33, 35, 35, 24, 5, -5, -11, -20, -27, -34, -40, -39, -30, -21, -16, -9, + 4, 20, 32, 36, 36, 36, 35, 31, 13, -3, -13, -23, -27, -29, -41, -44, + -33, -19, -11, -10, -4, 14, 32, 38, 34, 33, 36, 33, 18, -4, -13, -20, + -25, -28, -37, -43, -34, -22, -14, -8, -4, 9, 26, 39, 38, 35, 35, 34, + 23, 3, -12, -21, -28, -28, -31, -41, -40, -27, -15, -7, -6, 2, 20, 37, + 42, 36, 34, 35, 28, 9, -10, -18, -24, -26, -29, -38, -42, -32, -21, -11, + -6, -3, 12, 33, 45, 41, 37, 37, 29, 13, -4, -17, -26, -28, -28, -33, + -39, -37, -26, -15, -8, -7, 6, 29, 47, 46, 39, 34, 30, 20, 1, -18, + -26, -26, -25, -29, -37, -40, -31, -17, -8, -7, 0, 20, 42, 51, 45, 38, + 30, 18, 7, -10, -24, -27, -26, -24, -29, -38, -37, -27, -14, -9, -6, 11, + 36, 51, 47, 42, 34, 24, 14, -3, -20, -25, -23, -22, -26, -37, -42, -33, + -17, -8, -7, 4, 28, 50, 54, 45, 35, 24, 15, 3, -16, -24, -25, -22, + -23, -32, -41, -37, -22, -11, -8, 0, 21, 44, 54, 46, 34, 26, 18, 7, + -11, -22, -21, -20, -21, -28, -40, -43, -30, -15, -10, -3, 16, 40, 56, 52, + 37, 24, 16, 9, -6, -21, -22, -18, -17, -22, -35, -43, -34, -21, -14, -9, + 7, 34, 53, 54, 40, 29, 21, 14, 4, -14, -21, -17, -17, -22, -33, -46, + -45, -31, -16, -8, 4, 25, 50, 60, 49, 31, 20, 15, 9, -5, -17, -18, + -15, -17, -26, -42, -50, -40, -24, -11, -2, 18, 43, 56, 52, 35, 21, 17, + 11, 0, -12, -18, -14, -15, -22, -36, -50, -46, -30, -15, -3, 12, 35, 53, + 55, 41, 24, 18, 12, 5, -4, -15, -18, -15, -20, -33, -46, -49, -37, -21, + -7, 7, 25, 46, 54, 45, 27, 18, 14, 10, 3, -8, -15, -16, -18, -28, + -41, -49, -44, -29, -12, 4, 17, 35, 49, 49, 34, 19, 16, 15, 9, 1, + -10, -14, -16, -24, -38, -50, -49, -36, -18, -3, 10, 26, 43, 49, 38, 22, + 18, 20, 16, 9, -5, -13, -16, -23, -36, -50, -53, -43, -25, -8, 6, 21, + 38, 48, 44, 27, 19, 21, 19, 13, -2, -13, -17, -21, -30, -45, -52, -46, + -29, -10, 3, 14, 29, 42, 44, 30, 17, 19, 21, 17, 6, -8, -14, -19, + -26, -39, -49, -48, -36, -18, -2, 11, 27, 37, 42, 37, 22, 18, 21, 19, + 9, -5, -13, -18, -24, -33, -45, -46, -39, -24, -8, 6, 20, 33, 40, 38, + 27, 19, 22, 23, 17, 4, -8, -14, -22, -29, -43, -48, -43, -32, -16, -2, + 13, 25, 34, 39, 33, 23, 21, 23, 20, 9, -4, -11, -19, -25, -33, -43, + -42, -34, -20, -7, 3, 14, 24, 32, 31, 22, 20, 26, 28, 20, 6, -5, + -11, -18, -28, -42, -44, -38, -28, -15, -5, 8, 19, 28, 31, 24, 21, 25, + 27, 22, 10, 0, -6, -12, -22, -34, -38, -34, -30, -20, -11, 0, 11, 20, + 26, 23, 19, 22, 27, 25, 17, 7, -2, -7, -17, -29, -35, -35, -34, -26, + -16, -5, 7, 15, 23, 28, 24, 21, 22, 24, 20, 11, -2, -8, -14, -24, + -29, -31, -31, -27, -18, -9, 0, 8, 15, 22, 23, 20, 21, 24, 24, 19, + 7, -4, -10, -19, -26, -32, -34, -33, -24, -12, -2, 6, 14, 22, 26, 23, + 22, 22, 22, 21, 10, 0, -6, -15, -21, -24, -28, -31, -28, -17, -7, 2, + 7, 13, 19, 23, 23, 21, 19, 21, 18, 8, -2, -11, -17, -21, -24, -30, + -33, -25, -11, 0, 4, 9, 16, 20, 21, 20, 18, 18, 20, 14, 4, -6, + -12, -15, -17, -25, -32, -32, -20, -6, -3, -3, 7, 18, 23, 19, 16, 19, + 26, 24, 11, 0, -6, -9, -15, -25, -33, -35, -26, -15, -9, -6, 5, 17, + 22, 21, 17, 18, 25, 26, 16, 4, -5, -7, -9, -18, -29, -38, -35, -21, + -11, -9, -4, 9, 22, 25, 20, 16, 22, 30, 24, 8, -4, -5, -5, -13, + -25, -36, -38, -26, -16, -11, -10, 2, 19, 25, 18, 12, 19, 30, 28, 14, + 1, -2, 3, -3, -17, -31, -36, -29, -21, -18, -19, -11, 7, 20, 16, 10, + 16, 30, 36, 24, 8, 4, 8, 6, -12, -32, -40, -35, -26, -21, -20, -14, + 2, 19, 20, 10, 12, 24, 35, 29, 13, 5, 7, 9, -3, -23, -37, -37, + -31, -23, -21, -19, -8, 12, 19, 10, 6, 19, 36, 37, 23, 11, 12, 16, + 7, -15, -35, -43, -38, -30, -27, -23, -16, 2, 18, 16, 7, 13, 30, 38, + 29, 17, 12, 16, 15, -4, -27, -40, -39, -32, -28, -28, -24, -8, 12, 14, + 5, 7, 26, 40, 36, 24, 18, 21, 21, 4, -20, -38, -41, -37, -34, -30, + -26, -15, 4, 14, 7, 3, 18, 37, 41, 33, 24, 22, 25, 14, -10, -33, + -44, -42, -36, -32, -29, -22, -6, 10, 9, 2, 9, 29, 40, 37, 32, 28, + 29, 21, 0, -24, -39, -44, -44, -38, -31, -24, -16, 0, 7, 3, 8, 24, + 38, 43, 41, 32, 28, 25, 9, -15, -34, -44, -44, -39, -31, -26, -20, -10, + 3, 2, 1, 14, 32, 44, 46, 39, 33, 31, 20, -7, -31, -45, -47, -44, + -38, -30, -26, -16, 0, 5, 4, 12, 30, 45, 52, 47, 36, 30, 22, 0, + -24, -40, -50, -49, -42, -31, -24, -19, -10, -3, 3, 11, 24, 39, 51, 55, + 49, 37, 27, 8, -18, -36, -50, -54, -47, -36, -29, -25, -16, -6, 4, 10, + 18, 34, 52, 59, 53, 39, 28, 15, -8, -29, -45, -53, -51, -43, -34, -29, + -23, -14, -4, 7, 17, 33, 52, 62, 61, 50, 37, 23, -4, -28, -44, -55, + -55, -48, -38, -30, -25, -18, -8, 5, 13, 25, 46, 61, 65, 57, 43, 30, + 8, -17, -36, -50, -55, -53, -47, -39, -32, -24, -15, -3, 11, 25, 45, 62, + 68, 63, 51, 37, 14, -14, -34, -46, -56, -57, -51, -44, -33, -25, -18, -6, + 8, 19, 36, 55, 67, 65, 53, 42, 23, -4, -26, -40, -50, -56, -54, -49, + -41, -31, -23, -12, 1, 15, 34, 53, 65, 68, 59, 49, 33, 6, -21, -37, + -47, -57, -60, -56, -48, -38, -28, -16, -2, 14, 33, 51, 64, 70, 63, 53, + 38, 13, -14, -34, -44, -53, -59, -59, -53, -42, -30, -19, -8, 5, 26, 47, + 61, 68, 64, 57, 48, 26, -3, -26, -39, -49, -58, -63, -59, -49, -37, -24, + -13, 1, 20, 42, 55, 65, 69, 64, 54, 34, 7, -18, -34, -44, -55, -65, + -64, -54, -42, -31, -19, -8, 12, 37, 54, 61, 67, 67, 60, 46, 22, -8, + -29, -40, -50, -64, -70, -63, -50, -34, -21, -13, 2, 28, 51, 62, 68, 68, + 61, 51, 32, 3, -23, -36, -47, -60, -70, -67, -58, -44, -27, -14, -2, 22, + 45, 58, 65, 70, 68, 56, 38, 16, -11, -32, -45, -58, -69, -70, -62, -52, + -34, -17, -6, 13, 38, 54, 64, 70, 67, 59, 47, 29, -2, -28, -40, -51, + -65, -74, -67, -54, -37, -20, -11, 5, 33, 53, 59, 63, 67, 62, 51, 34, + 7, -20, -35, -46, -59, -72, -70, -60, -46, -27, -12, 1, 24, 47, 60, 64, + 69, 66, 54, 39, 15, -13, -32, -44, -54, -68, -71, -60, -48, -32, -18, -7, + 14, 38, 54, 61, 68, 70, 60, 46, 26, -2, -23, -38, -50, -63, -72, -68, + -55, -39, -24, -13, 5, 31, 52, 61, 67, 71, 64, 53, 34, 7, -21, -36, + -46, -57, -69, -72, -60, -42, -27, -17, -2, 21, 45, 58, 65, 69, 66, 57, + 42, 15, -13, -30, -43, -54, -66, -72, -65, -47, -30, -18, -5, 15, 40, 57, + 64, 67, 62, 56, 46, 23, -6, -27, -39, -50, -58, -67, -67, -51, -32, -20, + -9, 9, 31, 51, 60, 64, 64, 58, 48, 27, 1, -20, -34, -46, -56, -65, + -70, -57, -37, -22, -14, 2, 26, 48, 62, 66, 64, 59, 51, 34, 8, -18, + -31, -42, -52, -61, -70, -63, -42, -24, -15, -3, 19, 43, 60, 63, 60, 57, + 52, 39, 14, -14, -28, -36, -46, -54, -65, -66, -49, -29, -17, -9, 10, 33, + 54, 64, 62, 58, 53, 42, 23, -5, -25, -35, -46, -54, -63, -67, -54, -33, + -17, -7, 7, 30, 51, 61, 58, 55, 51, 43, 28, 3, -21, -30, -37, -46, + -56, -63, -56, -39, -22, -12, -5, 16, 40, 57, 58, 55, 53, 48, 38, 19, + -10, -27, -35, -45, -56, -66, -65, -49, -28, -14, -6, 8, 34, 57, 60, 55, + 54, 50, 42, 26, -4, -28, -35, -42, -52, -62, -63, -51, -32, -14, -5, 3, + 24, 47, 57, 53, 50, 47, 41, 33, 11, -20, -35, -40, -46, -56, -65, -58, + -38, -17, -4, 1, 15, 41, 57, 55, 47, 45, 42, 35, 17, -13, -33, -38, + -41, -49, -58, -55, -41, -21, -4, 0, 7, 29, 50, 52, 45, 42, 40, 37, + 25, 0, -28, -38, -38, -44, -53, -58, -46, -26, -6, 3, 4, 18, 42, 53, + 47, 41, 39, 37, 30, 10, -21, -41, -43, -41, -47, -54, -46, -29, -8, 7, + 9, 13, 31, 46, 45, 37, 33, 33, 28, 15, -10, -35, -42, -38, -39, -45, + -46, -32, -10, 6, 9, 8, 19, 38, 44, 38, 30, 29, 30, 19, -3, -29, + -42, -38, -34, -40, -43, -32, -14, 3, 11, 11, 15, 30, 41, 39, 30, 25, + 25, 19, 4, -21, -40, -42, -32, -30, -33, -29, -15, 2, 11, 10, 8, 17, + 30, 35, 30, 23, 24, 23, 11, -11, -32, -43, -34, -26, -29, -29, -18, -3, + 9, 12, 9, 12, 26, 35, 32, 21, 18, 18, 12, -6, -29, -43, -36, -22, + -22, -25, -15, 1, 10, 11, 10, 8, 17, 29, 29, 21, 16, 17, 15, 2, + -21, -39, -39, -24, -17, -20, -16, -5, 9, 13, 10, 7, 12, 24, 28, 23, + 14, 12, 11, 4, -14, -33, -39, -28, -15, -14, -12, -6, 5, 11, 9, 7, + 7, 16, 26, 25, 16, 10, 11, 6, -8, -24, -37, -32, -17, -12, -11, -5, + 5, 11, 11, 10, 7, 12, 21, 21, 16, 7, 4, 3, -6, -20, -32, -32, + -20, -8, -5, 0, 5, 11, 11, 9, 8, 8, 13, 17, 16, 9, 3, 2, + -3, -13, -25, -31, -23, -9, -4, -2, 5, 11, 14, 11, 7, 6, 12, 15, + 12, 5, -2, -2, -3, -11, -22, -29, -24, -9, 0, 3, 8, 13, 13, 12, + 8, 4, 5, 7, 9, 6, -3, -5, -4, -5, -14, -24, -23, -13, 0, 4, + 6, 10, 14, 14, 9, 3, 3, 5, 6, 4, -4, -6, -5, -5, -9, -18, + -20, -15, -4, 6, 9, 11, 13, 13, 10, 5, 1, 0, -3, 0, -4, -6, + -6, -5, -4, -11, -16, -16, -9, 3, 8, 11, 11, 10, 11, 8, 3, -2, + -5, -4, -3, -5, -6, -6, -2, -5, -12, -15, -13, -2, 8, 9, 11, 11, + 11, 7, 4, 0, -6, -6, -4, -4, -6, -6, -2, 0, -7, -13, -15, -5, + 8, 13, 12, 9, 11, 9, 4, -5, -11, -11, -8, -5, -5, -5, 0, 4, + 3, -4, -11, -8, 3, 11, 12, 8, 7, 4, 2, -2, -10, -14, -13, -7, + -3, -4, -2, 3, 4, 1, -8, -8, 3, 13, 17, 12, 11, 7, 1, -6, + -16, -21, -19, -13, -7, -2, 3, 7, 10, 10, 1, -6, -2, 8, 14, 12, + 10, 4, -2, -6, -15, -21, -20, -15, -8, -2, 3, 5, 9, 14, 5, -6, + 1, 12, 18, 14, 9, 7, 2, -4, -18, -28, -27, -22, -12, -5, 3, 9, + 13, 18, 16, 5, 1, 7, 14, 13, 8, 5, -5, -9, -17, -26, -26, -23, + -15, -4, 5, 8, 11, 17, 17, 7, 2, 7, 16, 18, 10, 4, -2, -6, + -16, -31, -33, -27, -18, -9, 0, 7, 12, 18, 22, 16, 9, 9, 16, 20, + 13, 5, -2, -9, -18, -33, -37, -29, -22, -13, -4, 7, 15, 21, 25, 21, + 15, 13, 17, 20, 14, 5, -3, -8, -18, -35, -42, -36, -24, -16, -6, 5, + 13, 23, 27, 25, 20, 17, 19, 20, 15, 5, -3, -8, -21, -35, -45, -39, + -25, -18, -11, 3, 16, 25, 29, 27, 26, 24, 23, 21, 17, 8, -4, -12, + -23, -35, -46, -46, -34, -22, -15, -3, 13, 25, 31, 33, 34, 31, 28, 25, + 20, 11, -4, -12, -22, -38, -49, -51, -39, -26, -21, -11, 8, 24, 34, 35, + 36, 37, 35, 29, 21, 13, 0, -11, -20, -36, -48, -52, -46, -31, -22, -14, + 1, 19, 34, 38, 39, 40, 38, 34, 24, 15, 0, -14, -21, -34, -47, -53, + -50, -35, -22, -17, -5, 13, 31, 37, 38, 42, 41, 37, 28, 21, 9, -8, + -19, -30, -44, -50, -53, -46, -32, -23, -11, 7, 26, 39, 43, 49, 48, 42, + 32, 20, 9, -9, -21, -31, -46, -52, -54, -50, -35, -24, -13, 4, 23, 40, + 46, 48, 49, 46, 37, 26, 13, -4, -20, -29, -42, -50, -53, -54, -43, -31, + -21, -2, 17, 36, 47, 53, 56, 51, 42, 29, 17, 3, -16, -30, -41, -51, + -55, -57, -51, -35, -24, -9, 11, 30, 47, 53, 57, 55, 46, 34, 20, 6, + -12, -29, -43, -52, -55, -55, -55, -42, -29, -12, 8, 25, 41, 55, 62, 59, + 51, 37, 23, 10, -6, -24, -40, -51, -56, -58, -58, -48, -33, -19, 2, 22, + 41, 55, 61, 61, 56, 45, 28, 11, -3, -19, -37, -51, -57, -58, -58, -54, + -39, -23, -2, 20, 36, 52, 64, 65, 58, 48, 33, 19, 4, -13, -35, -51, + -58, -61, -62, -60, -47, -29, -7, 17, 34, 50, 67, 70, 62, 50, 35, 20, + 6, -8, -29, -47, -57, -62, -61, -60, -54, -37, -15, 10, 29, 44, 60, 68, + 66, 56, 42, 24, 12, 1, -19, -41, -55, -60, -62, -61, -57, -43, -21, 7, + 24, 36, 53, 66, 67, 59, 46, 30, 15, 5, -11, -32, -48, -58, -63, -62, + -59, -50, -32, -3, 22, 35, 49, 60, 66, 63, 53, 38, 19, 8, -5, -25, + -43, -57, -64, -64, -62, -54, -39, -13, 16, 32, 46, 59, 65, 66, 56, 45, + 26, 11, 3, -17, -39, -56, -65, -67, -62, -56, -44, -21, 10, 29, 40, 54, + 63, 68, 61, 49, 33, 13, 2, -14, -34, -50, -64, -67, -63, -56, -44, -26, + 2, 27, 38, 49, 57, 64, 61, 50, 36, 17, 6, -7, -27, -44, -60, -67, + -63, -57, -48, -32, -7, 22, 36, 44, 53, 60, 62, 55, 41, 21, 7, -3, + -20, -40, -58, -68, -65, -57, -47, -34, -14, 16, 37, 42, 47, 55, 59, 53, + 42, 27, 10, -2, -14, -30, -47, -60, -63, -57, -49, -38, -20, 5, 30, 40, + 44, 52, 57, 57, 46, 31, 13, -2, -12, -27, -44, -57, -64, -61, -50, -38, + -20, 2, 25, 39, 41, 49, 55, 54, 45, 32, 17, 0, -12, -23, -37, -50, + -59, -61, -52, -38, -22, -6, 17, 35, 39, 42, 48, 53, 48, 36, 22, 4, + -9, -18, -30, -45, -56, -59, -54, -42, -27, -10, 12, 29, 37, 38, 44, 50, + 47, 37, 25, 9, -5, -13, -23, -38, -50, -55, -54, -45, -32, -17, 5, 25, + 34, 35, 39, 46, 48, 40, 29, 13, -3, -11, -21, -33, -44, -51, -54, -47, + -34, -17, 2, 21, 32, 34, 34, 38, 42, 39, 27, 15, 1, -7, -13, -25, + -36, -45, -49, -46, -36, -23, -6, 15, 27, 31, 31, 34, 39, 38, 30, 18, + 3, -6, -10, -19, -32, -40, -46, -45, -36, -24, -11, 8, 24, 29, 27, 29, + 34, 36, 30, 18, 4, -5, -5, -12, -25, -34, -39, -41, -37, -24, -11, 4, + 18, 24, 25, 25, 29, 29, 26, 19, 5, -6, -6, -6, -18, -28, -33, -37, + -34, -24, -11, 2, 15, 24, 23, 20, 24, 27, 22, 14, 4, -4, -4, -5, + -15, -24, -26, -29, -32, -27, -13, 2, 14, 21, 21, 18, 21, 23, 20, 13, + 5, -3, -5, -4, -9, -16, -21, -25, -28, -25, -14, 1, 10, 16, 19, 16, + 16, 18, 16, 11, 5, -2, -5, -4, -6, -12, -17, -20, -22, -22, -17, -4, + 8, 13, 16, 15, 13, 15, 14, 10, 4, -4, -6, -6, -5, -7, -11, -15, + -17, -17, -15, -3, 10, 13, 14, 11, 7, 8, 9, 5, -3, -8, -7, -4, + -2, -2, -6, -10, -9, -10, -12, -5, 11, 15, 13, 11, 5, 6, 7, 3, + -6, -10, -8, -6, -6, -2, 1, -2, -6, -6, -7, -5, 8, 14, 10, 7, + 4, 0, 1, -2, -6, -12, -11, -6, -2, 4, 8, 4, -2, -2, -4, -5, + 3, 12, 8, 5, 4, 0, 0, -2, -8, -13, -15, -12, -7, -3, 6, 10, + 7, 5, 6, 4, 6, 14, 10, 3, 0, -6, -10, -7, -10, -16, -19, -15, + -8, 0, 11, 17, 13, 10, 11, 7, 5, 8, 9, 2, -4, -7, -12, -10, + -10, -16, -21, -19, -13, -4, 10, 21, 22, 17, 17, 14, 9, 9, 9, 3, + -7, -12, -17, -16, -14, -20, -25, -21, -15, -5, 10, 23, 27, 25, 22, 18, + 11, 8, 4, -2, -9, -14, -18, -19, -14, -15, -23, -25, -20, -10, 9, 22, + 29, 29, 26, 23, 16, 12, 6, 1, -6, -14, -18, -22, -20, -19, -27, -28, + -25, -18, 0, 19, 32, 36, 33, 31, 23, 14, 7, 1, -4, -15, -23, -25, + -24, -19, -25, -32, -29, -20, -3, 16, 31, 40, 38, 36, 29, 16, 9, 1, + -4, -12, -23, -26, -28, -24, -26, -34, -33, -24, -8, 12, 29, 41, 44, 44, + 37, 22, 11, 4, -4, -11, -24, -31, -32, -31, -30, -36, -39, -30, -11, 11, + 29, 43, 51, 50, 44, 32, 15, 4, -4, -11, -24, -32, -33, -33, -34, -38, + -42, -35, -17, 4, 24, 42, 56, 60, 52, 38, 19, 7, 1, -13, -28, -37, + -37, -35, -37, -39, -43, -37, -19, 3, 22, 41, 57, 64, 57, 44, 26, 7, + -2, -11, -24, -35, -41, -40, -38, -39, -43, -40, -24, 0, 20, 37, 55, 65, + 63, 50, 32, 9, -4, -10, -24, -36, -42, -42, -41, -41, -41, -39, -26, -2, + 19, 34, 51, 64, 66, 55, 38, 15, -3, -8, -20, -34, -42, -44, -43, -44, + -45, -45, -35, -12, 14, 31, 50, 66, 73, 65, 49, 28, 7, -6, -18, -35, + -45, -49, -51, -53, -51, -47, -37, -16, 10, 30, 49, 69, 78, 72, 56, 35, + 14, -4, -17, -33, -46, -51, -55, -56, -54, -51, -40, -20, 5, 26, 44, 64, + 76, 77, 64, 41, 19, 1, -14, -30, -43, -50, -57, -60, -58, -54, -43, -24, + -2, 21, 39, 61, 76, 79, 72, 52, 28, 9, -10, -26, -41, -49, -54, -61, + -62, -59, -51, -33, -10, 14, 34, 55, 75, 81, 79, 63, 39, 19, -2, -23, + -40, -51, -56, -64, -67, -64, -56, -39, -16, 9, 29, 51, 73, 83, 82, 73, + 50, 27, 9, -18, -40, -52, -56, -63, -69, -69, -61, -43, -20, 2, 21, 42, + 66, 81, 82, 76, 59, 36, 19, -6, -33, -50, -57, -61, -71, -76, -68, -52, + -28, -2, 17, 36, 62, 83, 86, 82, 69, 43, 22, 2, -28, -51, -60, -63, + -67, -76, -74, -57, -34, -7, 14, 29, 53, 76, 87, 84, 75, 54, 33, 14, + -18, -46, -58, -62, -69, -80, -84, -68, -44, -18, 7, 26, 49, 75, 91, 92, + 82, 64, 42, 21, -8, -43, -63, -68, -68, -75, -86, -76, -48, -22, 4, 23, + 41, 66, 87, 92, 83, 69, 51, 31, 6, -31, -59, -67, -69, -74, -88, -87, + -62, -34, -7, 17, 36, 62, 87, 96, 90, 76, 60, 39, 14, -23, -58, -70, + -71, -73, -83, -89, -68, -37, -13, 9, 26, 51, 79, 94, 91, 80, 68, 52, + 28, -8, -48, -67, -70, -73, -84, -96, -83, -49, -22, 0, 20, 44, 75, 96, + 98, 88, 75, 61, 40, 6, -39, -67, -72, -75, -83, -95, -91, -60, -29, -7, + 13, 36, 66, 89, 97, 92, 78, 65, 50, 22, -21, -58, -71, -73, -78, -91, + -98, -79, -45, -15, 4, 25, 56, 84, 101, 99, 86, 73, 60, 35, -9, -53, + -72, -77, -80, -90, -98, -85, -51, -20, -2, 18, 48, 77, 96, 99, 87, 75, + 62, 46, 9, -39, -68, -75, -75, -83, -95, -94, -67, -30, -7, 8, 34, 68, + 92, 102, 93, 82, 72, 58, 26, -24, -61, -75, -78, -85, -97, -99, -78, -42, + -12, 6, 28, 59, 87, 102, 99, 86, 74, 62, 38, -7, -52, -76, -81, -83, + -93, -100, -90, -57, -23, -2, 18, 48, 80, 102, 103, 92, 81, 71, 51, 9, + -41, -72, -83, -85, -93, -100, -92, -65, -32, -7, 13, 39, 72, 97, 103, 95, + 85, 73, 55, 25, -21, -61, -79, -83, -90, -99, -97, -77, -45, -17, 1, 24, + 59, 93, 107, 103, 92, 85, 72, 42, -6, -54, -80, -86, -91, -104, -105, -87, + -56, -23, 0, 18, 48, 85, 106, 106, 96, 87, 77, 52, 13, -35, -71, -84, + -88, -98, -106, -96, -70, -40, -14, 6, 31, 70, 103, 111, 103, 95, 88, 68, + 29, -19, -61, -84, -91, -99, -106, -101, -80, -51, -22, 2, 23, 56, 91, 109, + 108, 98, 89, 76, 45, 1, -44, -76, -87, -92, -102, -104, -90, -64, -34, -11, + 8, 37, 78, 108, 113, 106, 96, 85, 61, 19, -29, -68, -88, -94, -102, -104, + -93, -73, -46, -21, 2, 28, 63, 98, 113, 109, 100, 89, 70, 33, -14, -55, + -81, -91, -98, -104, -98, -79, -54, -30, -9, 18, 52, 89, 108, 110, 104, 96, + 79, 46, 2, -40, -71, -90, -100, -104, -100, -86, -67, -44, -19, 7, 40, 77, + 105, 115, 109, 99, 86, 58, 17, -29, -63, -86, -97, -101, -101, -92, -74, -50, + -26, -4, 28, 66, 98, 114, 113, 102, 90, 68, 33, -15, -53, -76, -93, -101, + -104, -96, -79, -57, -34, -15, 15, 56, 90, 110, 115, 105, 93, 75, 44, 0, + -43, -68, -86, -98, -101, -98, -83, -65, -42, -22, 4, 41, 79, 104, 113, 107, + 96, 81, 57, 16, -31, -59, -79, -95, -101, -100, -90, -71, -49, -30, -9, 28, + 67, 97, 110, 107, 97, 86, 65, 30, -14, -47, -67, -84, -98, -102, -96, -79, + -59, -41, -22, 14, 53, 90, 110, 111, 101, 90, 75, 45, 2, -39, -64, -79, + -93, -102, -101, -87, -64, -44, -28, 0, 39, 81, 108, 110, 102, 93, 82, 58, + 18, -25, -54, -70, -85, -101, -103, -94, -72, -53, -39, -14, 25, 70, 104, 112, + 103, 96, 88, 70, 34, -13, -48, -65, -78, -97, -108, -101, -79, -55, -42, -24, + 11, 56, 96, 111, 103, 94, 90, 77, 46, 5, -34, -56, -71, -92, -109, -109, + -91, -64, -46, -30, 0, 44, 89, 112, 108, 95, 88, 80, 57, 16, -27, -54, + -66, -82, -104, -112, -100, -71, -46, -34, -13, 29, 80, 111, 112, 97, 86, 84, + 69, 32, -15, -48, -61, -72, -94, -109, -106, -82, -54, -37, -23, 11, 61, 101, + 113, 101, 85, 80, 75, 48, 4, -37, -56, -64, -84, -107, -112, -90, -60, -37, + -29, -7, 43, 91, 111, 103, 86, 80, 77, 58, 20, -24, -52, -61, -75, -100, + -111, -99, -72, -44, -27, -12, 29, 77, 105, 106, 91, 80, 75, 64, 33, -9, + -43, -58, -69, -94, -111, -104, -78, -49, -28, -18, 11, 62, 97, 107, 94, 80, + 75, 69, 47, 6, -36, -55, -62, -81, -105, -108, -87, -59, -33, -18, 1, 46, + 86, 103, 97, 83, 75, 69, 52, 19, -23, -50, -59, -74, -97, -106, -91, -64, + -38, -21, -9, 26, 70, 95, 95, 80, 71, 69, 60, 35, -6, -40, -53, -64, + -87, -102, -96, -72, -45, -25, -14, 13, 56, 87, 95, 86, 75, 69, 60, 41, + 6, -32, -54, -62, -77, -95, -99, -79, -51, -23, -8, 6, 39, 75, 92, 87, + 72, 64, 62, 49, 21, -17, -47, -57, -67, -86, -97, -87, -59, -32, -16, -4, + 25, 63, 89, 92, 78, 67, 63, 53, 27, -10, -40, -55, -63, -78, -93, -89, + -65, -36, -17, -7, 11, 44, 77, 89, 79, 65, 61, 58, 41, 8, -26, -50, + -59, -67, -83, -90, -76, -47, -25, -13, 3, 30, 63, 85, 82, 70, 63, 58, + 45, 14, -18, -43, -56, -63, -74, -84, -78, -52, -26, -13, -2, 19, 46, 73, + 81, 68, 57, 55, 49, 27, -5, -32, -48, -54, -63, -77, -80, -60, -34, -17, + -5, 10, 34, 62, 79, 71, 57, 52, 48, 31, 2, -26, -45, -50, -53, -65, + -75, -63, -37, -16, -6, 4, 19, 45, 68, 70, 57, 49, 49, 39, 16, -11, + -33, -45, -49, -56, -70, -71, -51, -26, -8, 2, 13, 35, 63, 76, 63, 48, + 43, 38, 23, -7, -32, -45, -47, -47, -58, -67, -55, -30, -8, 0, 4, 20, + 46, 68, 65, 47, 38, 38, 31, 8, -19, -37, -44, -42, -48, -63, -62, -41, + -16, -2, 5, 16, 37, 61, 68, 53, 38, 34, 31, 14, -14, -33, -40, -38, + -41, -54, -60, -46, -20, -5, -3, 6, 25, 49, 63, 55, 38, 32, 33, 24, + 1, -23, -34, -35, -36, -45, -59, -55, -30, -9, -3, 2, 16, 39, 59, 59, + 44, 32, 30, 26, 7, -20, -33, -33, -32, -40, -53, -54, -35, -12, -3, -2, + 10, 29, 48, 55, 45, 32, 28, 27, 14, -10, -27, -30, -28, -34, -46, -53, + -41, -17, -5, -5, 5, 24, 44, 54, 46, 32, 25, 25, 18, -4, -25, -31, + -24, -27, -39, -47, -42, -21, -4, -2, 1, 15, 35, 46, 44, 31, 22, 23, + 20, 6, -15, -26, -23, -20, -29, -41, -42, -29, -11, -4, -4, 7, 26, 42, + 47, 37, 25, 21, 19, 9, -10, -25, -25, -18, -24, -38, -40, -29, -11, 1, + 0, 3, 19, 34, 42, 33, 19, 14, 15, 10, -5, -21, -24, -15, -13, -26, + -35, -31, -17, -2, 0, -2, 11, 26, 37, 34, 20, 14, 13, 12, 2, -17, + -25, -17, -12, -21, -31, -30, -19, -4, 4, 1, 9, 22, 32, 32, 19, 9, + 9, 10, 4, -11, -21, -16, -9, -14, -23, -26, -20, -8, 0, -2, 3, 15, + 26, 31, 24, 12, 9, 10, 6, -5, -17, -19, -12, -11, -18, -25, -22, -10, + 1, 2, 2, 11, 22, 29, 24, 10, 3, 5, 4, -4, -13, -15, -8, -5, + -10, -16, -18, -14, -5, -2, 0, 6, 13, 20, 23, 16, 6, 5, 5, 0, + -7, -12, -12, -8, -7, -12, -19, -18, -7, 0, 2, 7, 13, 18, 20, 13, + 3, -2, 1, -2, -6, -8, -6, -3, -2, -2, -10, -14, -10, -6, -4, 0, + 4, 9, 14, 15, 6, -2, -2, -2, -4, -4, -5, -3, 2, 3, -3, -10, + -9, -5, 0, 0, 0, 3, 8, 10, 3, -5, -7, -6, -4, 0, -2, -2, + 3, 7, 7, 2, -5, -6, -3, 2, 2, 0, 0, 2, 2, -4, -9, -9, + -7, -3, 2, 4, 8, 9, 6, 2, -3, -4, -3, -2, -2, -2, 0, 1, + -3, -8, -11, -8, -6, -4, 2, 6, 9, 10, 9, 8, 5, -4, -7, -3, + 1, 1, -6, -7, -6, -6, -11, -14, -10, -5, 3, 9, 12, 14, 13, 10, + 9, 1, -6, -5, -4, -3, -4, -6, -8, -12, -12, -13, -13, -11, -3, 9, + 16, 18, 15, 13, 14, 11, -2, -6, -4, -3, -5, -11, -13, -12, -14, -15, + -14, -10, -4, 6, 15, 22, 21, 16, 13, 12, 3, -7, -8, -7, -7, -10, + -14, -17, -16, -13, -12, -10, -7, 3, 15, 24, 26, 19, 16, 18, 12, -3, + -9, -10, -9, -11, -18, -22, -21, -17, -14, -14, -10, 0, 14, 26, 32, 28, + 23, 22, 21, 5, -9, -12, -16, -18, -22, -27, -27, -23, -17, -13, -8, 2, + 12, 25, 35, 36, 29, 21, 20, 11, -6, -14, -17, -19, -22, -27, -28, -24, + -20, -15, -11, -4, 7, 19, 32, 39, 35, 28, 25, 19, 4, -10, -17, -24, + -28, -31, -33, -30, -26, -19, -11, -3, 8, 19, 31, 42, 42, 34, 27, 21, + 9, -9, -19, -26, -31, -35, -34, -30, -26, -23, -13, -4, 4, 14, 25, 42, + 49, 41, 31, 27, 20, 3, -15, -28, -37, -38, -39, -38, -35, -29, -16, 0, + 9, 17, 26, 41, 52, 48, 36, 26, 19, 6, -16, -30, -39, -43, -41, -39, + -33, -29, -22, -5, 7, 13, 21, 36, 55, 56, 46, 34, 24, 15, -8, -29, + -44, -54, -50, -44, -39, -35, -27, -7, 11, 20, 25, 34, 54, 63, 53, 38, + 22, 14, 0, -27, -45, -56, -56, -46, -39, -36, -31, -14, 8, 19, 23, 29, + 46, 63, 61, 47, 30, 20, 8, -15, -39, -56, -62, -54, -44, -41, -38, -23, + -2, 16, 23, 28, 42, 63, 69, 58, 41, 25, 13, -7, -34, -56, -68, -64, + -50, -45, -43, -29, -7, 15, 26, 29, 40, 58, 72, 67, 48, 30, 16, 0, + -26, -53, -68, -69, -57, -47, -46, -36, -16, 9, 25, 30, 38, 53, 71, 74, + 58, 37, 17, 2, -21, -49, -70, -76, -64, -49, -43, -38, -21, 3, 25, 33, + 37, 49, 65, 74, 65, 45, 24, 8, -11, -40, -68, -79, -72, -57, -48, -42, + -29, -6, 20, 34, 39, 48, 63, 77, 74, 56, 31, 11, -8, -33, -61, -79, + -80, -68, -53, -45, -34, -16, 11, 31, 41, 51, 61, 75, 78, 64, 42, 19, + -3, -27, -55, -78, -84, -73, -59, -48, -37, -20, 5, 27, 40, 49, 58, 71, + 80, 71, 49, 23, 2, -20, -47, -72, -86, -82, -66, -52, -39, -26, -5, 20, + 39, 51, 59, 69, 79, 77, 61, 34, 7, -16, -42, -68, -88, -90, -75, -58, + -41, -26, -8, 17, 39, 52, 59, 65, 74, 77, 65, 41, 12, -12, -35, -60, + -81, -89, -79, -60, -45, -33, -17, 6, 31, 49, 59, 64, 73, 80, 74, 51, + 22, -5, -29, -54, -78, -92, -90, -70, -49, -35, -18, 3, 26, 48, 60, 64, + 68, 75, 75, 58, 31, 1, -25, -48, -73, -88, -90, -77, -56, -41, -23, -3, + 21, 43, 58, 64, 70, 75, 77, 64, 40, 12, -18, -44, -70, -87, -94, -87, + -64, -42, -22, -4, 16, 39, 58, 65, 66, 67, 74, 68, 46, 18, -12, -38, + -62, -82, -92, -89, -67, -45, -28, -9, 13, 31, 52, 64, 67, 66, 72, 71, + 53, 29, -3, -34, -59, -79, -94, -96, -77, -50, -29, -8, 12, 30, 49, 63, + 68, 67, 68, 70, 56, 34, 6, -29, -57, -77, -92, -99, -84, -56, -32, -10, + 11, 29, 45, 61, 69, 69, 68, 70, 60, 37, 12, -20, -50, -73, -90, -100, + -91, -64, -37, -14, 7, 25, 42, 57, 66, 67, 65, 67, 64, 45, 21, -9, + -41, -66, -84, -98, -95, -74, -47, -21, 3, 23, 39, 54, 64, 69, 69, 67, + 63, 50, 27, 0, -33, -63, -83, -94, -95, -79, -54, -26, -2, 18, 35, 49, + 61, 67, 67, 65, 64, 55, 33, 6, -25, -55, -82, -95, -98, -84, -60, -32, + -6, 17, 36, 48, 56, 64, 66, 65, 62, 55, 39, 14, -16, -46, -76, -92, + -96, -88, -69, -41, -9, 15, 33, 46, 54, 62, 68, 66, 59, 54, 44, 20, + -12, -41, -72, -92, -97, -90, -71, -46, -14, 15, 34, 48, 55, 59, 62, 63, + 60, 51, 42, 24, -6, -34, -63, -87, -95, -89, -75, -52, -23, 10, 31, 45, + 54, 58, 62, 66, 63, 51, 42, 30, 1, -32, -59, -84, -96, -93, -80, -58, + -28, 7, 32, 45, 53, 60, 64, 67, 62, 52, 41, 31, 9, -25, -55, -78, + -92, -91, -82, -65, -39, -2, 30, 43, 49, 56, 61, 65, 63, 54, 44, 33, + 16, -15, -47, -72, -88, -91, -84, -70, -45, -12, 22, 42, 48, 54, 58, 61, + 63, 56, 43, 32, 20, -4, -36, -65, -82, -87, -82, -72, -53, -23, 15, 40, + 46, 48, 55, 61, 62, 55, 43, 32, 21, 4, -26, -57, -75, -82, -80, -73, + -58, -30, 5, 35, 46, 47, 51, 57, 61, 57, 46, 34, 22, 9, -15, -47, + -71, -81, -80, -75, -62, -36, -4, 28, 46, 47, 49, 56, 60, 57, 48, 35, + 23, 12, -9, -39, -67, -78, -76, -71, -65, -45, -13, 21, 45, 50, 46, 50, + 58, 59, 49, 35, 23, 12, -4, -31, -62, -78, -74, -70, -65, -49, -18, 18, + 43, 51, 45, 48, 56, 56, 45, 30, 20, 12, 0, -24, -53, -71, -69, -63, + -60, -51, -25, 9, 36, 50, 47, 44, 50, 52, 45, 32, 21, 12, 1, -18, + -44, -66, -70, -64, -59, -51, -31, 2, 32, 50, 51, 46, 47, 52, 47, 32, + 17, 9, 0, -14, -34, -57, -67, -62, -56, -50, -33, -6, 24, 44, 51, 48, + 47, 48, 46, 34, 21, 12, 2, -13, -32, -51, -62, -62, -56, -51, -38, -13, + 18, 40, 51, 50, 45, 47, 46, 36, 20, 9, -2, -14, -28, -45, -59, -61, + -54, -48, -37, -15, 14, 36, 49, 52, 48, 44, 42, 33, 19, 10, 0, -13, + -26, -39, -52, -58, -54, -47, -37, -19, 9, 30, 44, 52, 48, 40, 38, 31, + 19, 7, -3, -12, -22, -31, -42, -51, -49, -43, -36, -22, 1, 22, 35, 45, + 47, 41, 37, 31, 23, 13, 3, -11, -22, -28, -36, -48, -53, -46, -35, -23, + -4, 17, 31, 45, 49, 41, 33, 29, 23, 13, 2, -11, -22, -26, -29, -38, + -46, -45, -34, -21, -6, 14, 25, 38, 46, 43, 35, 27, 19, 10, 3, -7, + -20, -28, -28, -32, -38, -41, -35, -23, -8, 10, 23, 33, 44, 44, 36, 27, + 18, 10, 0, -9, -22, -28, -28, -28, -33, -37, -32, -21, -7, 8, 20, 28, + 38, 41, 36, 27, 17, 8, -2, -6, -17, -28, -31, -28, -27, -30, -30, -22, + -7, 9, 19, 26, 35, 41, 37, 26, 16, 6, -5, -11, -18, -28, -31, -28, + -22, -23, -23, -18, -4, 11, 19, 24, 27, 33, 33, 24, 14, 3, -8, -11, + -15, -23, -29, -29, -21, -18, -19, -15, -5, 9, 16, 21, 26, 30, 32, 25, + 13, 2, -9, -13, -16, -21, -27, -27, -20, -12, -13, -14, -7, 9, 17, 20, + 24, 25, 26, 27, 15, 2, -9, -17, -17, -20, -25, -28, -23, -11, -6, -8, + -5, 7, 19, 23, 24, 24, 24, 25, 16, 0, -13, -22, -22, -22, -26, -28, + -22, -8, 2, 1, 0, 8, 18, 24, 24, 20, 18, 20, 15, 1, -12, -22, + -24, -22, -23, -25, -22, -13, 2, 7, 3, 8, 16, 25, 28, 21, 15, 15, + 15, 4, -13, -25, -29, -24, -20, -24, -21, -12, 1, 12, 10, 9, 16, 23, + 27, 21, 14, 12, 10, 3, -10, -21, -28, -27, -22, -22, -20, -14, -4, 10, + 14, 11, 17, 23, 29, 26, 15, 11, 10, 4, -12, -25, -33, -33, -26, -23, + -22, -12, 0, 13, 22, 19, 20, 25, 29, 25, 12, 5, 3, 0, -12, -25, + -32, -34, -27, -21, -20, -11, -2, 7, 18, 21, 22, 26, 30, 29, 21, 11, + 4, -5, -14, -29, -38, -38, -33, -27, -23, -10, 4, 12, 22, 29, 30, 30, + 31, 30, 21, 10, 0, -11, -19, -30, -39, -40, -36, -28, -20, -9, 4, 12, + 20, 29, 32, 30, 32, 32, 23, 12, 3, -8, -18, -27, -39, -44, -40, -32, + -25, -15, 1, 13, 22, 30, 37, 38, 36, 34, 26, 14, 2, -11, -22, -31, + -40, -45, -42, -35, -26, -14, 0, 12, 19, 26, 35, 39, 36, 33, 28, 18, + 6, -7, -18, -28, -37, -43, -43, -37, -30, -19, -6, 8, 20, 25, 34, 42, + 41, 37, 32, 22, 8, -7, -19, -32, -40, -44, -44, -38, -30, -20, -6, 8, + 19, 24, 30, 40, 41, 36, 29, 23, 13, -3, -16, -28, -39, -43, -44, -41, + -34, -23, -11, 2, 16, 25, 32, 41, 46, 42, 34, 26, 15, 0, -16, -29, + -40, -45, -45, -40, -32, -24, -12, -2, 12, 22, 26, 37, 45, 44, 34, 24, + 18, 6, -12, -24, -37, -41, -40, -40, -36, -30, -17, -4, 9, 18, 25, 37, + 45, 45, 40, 29, 19, 8, -8, -22, -38, -43, -42, -42, -35, -28, -17, -4, + 7, 17, 23, 33, 43, 43, 38, 28, 19, 12, -3, -19, -34, -40, -38, -40, + -38, -31, -22, -8, 5, 14, 21, 31, 44, 47, 41, 31, 20, 13, 3, -15, + -33, -45, -45, -41, -38, -31, -24, -10, 4, 15, 21, 29, 42, 47, 41, 33, + 22, 13, 4, -13, -29, -40, -41, -41, -41, -36, -26, -14, -2, 8, 17, 29, + 42, 50, 46, 37, 27, 17, 7, -9, -27, -41, -48, -45, -42, -38, -29, -15, + -2, 10, 18, 26, 38, 50, 51, 40, 28, 17, 6, -7, -24, -36, -43, -45, + -41, -38, -31, -18, -8, 2, 13, 26, 38, 44, 49, 42, 33, 22, 8, -4, + -20, -32, -41, -46, -44, -37, -32, -21, -8, 2, 14, 25, 35, 42, 47, 44, + 31, 19, 7, -4, -15, -28, -36, -42, -40, -34, -31, -24, -9, 0, 7, 18, + 30, 40, 44, 42, 32, 22, 12, 2, -10, -23, -31, -38, -42, -38, -31, -26, + -13, -3, 2, 14, 29, 40, 41, 40, 36, 26, 13, 1, -10, -19, -26, -35, + -43, -41, -33, -27, -17, -6, 1, 12, 27, 43, 47, 42, 37, 29, 14, 0, + -10, -21, -29, -34, -40, -42, -33, -26, -18, -5, 3, 10, 23, 39, 45, 39, + 33, 30, 18, 3, -8, -15, -22, -29, -37, -43, -36, -27, -22, -13, -4, 6, + 19, 36, 47, 47, 37, 33, 25, 6, -8, -15, -25, -31, -36, -43, -42, -32, + -21, -11, 0, 5, 15, 32, 46, 45, 35, 31, 28, 12, -6, -13, -20, -24, + -31, -41, -46, -38, -26, -18, -9, 1, 14, 31, 43, 48, 42, 33, 28, 15, + -5, -15, -18, -24, -31, -38, -41, -34, -26, -19, -8, 1, 10, 23, 37, 43, + 41, 32, 26, 19, 3, -12, -15, -18, -24, -34, -42, -38, -28, -20, -13, -4, + 6, 21, 37, 44, 43, 36, 28, 21, 8, -9, -16, -19, -25, -34, -42, -39, + -29, -21, -13, -3, 8, 19, 34, 42, 41, 36, 28, 20, 8, -7, -15, -16, + -19, -30, -41, -42, -31, -23, -15, -8, 3, 19, 36, 43, 39, 36, 30, 23, + 13, -6, -19, -21, -20, -26, -38, -43, -35, -25, -15, -7, 3, 14, 30, 42, + 40, 35, 28, 23, 16, 0, -14, -20, -19, -22, -34, -42, -37, -26, -15, -8, + 0, 12, 27, 40, 41, 35, 29, 22, 16, 4, -9, -19, -20, -20, -29, -39, + -39, -30, -19, -10, -3, 10, 24, 37, 42, 37, 31, 25, 18, 7, -7, -17, + -21, -20, -28, -38, -40, -33, -22, -11, -5, 9, 25, 37, 44, 40, 32, 24, + 17, 10, -5, -18, -24, -23, -28, -35, -38, -35, -26, -14, -5, 5, 19, 34, + 44, 42, 33, 23, 18, 13, 0, -15, -20, -22, -26, -33, -39, -35, -28, -18, + -10, 1, 18, 33, 43, 45, 38, 28, 20, 11, 2, -12, -22, -24, -28, -31, + -36, -35, -29, -21, -11, 0, 15, 30, 40, 44, 39, 31, 21, 13, 8, -5, + -17, -20, -25, -28, -32, -36, -34, -27, -18, -7, 9, 26, 39, 46, 45, 36, + 25, 14, 10, -2, -16, -24, -29, -31, -31, -36, -36, -27, -16, -7, 6, 23, + 37, 45, 44, 36, 26, 14, 8, 1, -14, -22, -23, -29, -32, -35, -36, -29, + -21, -14, 0, 16, 35, 46, 45, 39, 33, 20, 8, 3, -9, -21, -28, -32, + -34, -35, -36, -32, -25, -15, 1, 17, 32, 45, 49, 44, 35, 23, 7, 0, + -7, -17, -25, -30, -31, -32, -34, -31, -25, -18, -7, 10, 27, 43, 50, 45, + 35, 24, 13, 3, -7, -17, -24, -28, -30, -30, -33, -34, -26, -19, -11, 5, + 22, 39, 50, 48, 37, 26, 16, 5, -7, -18, -23, -27, -28, -28, -33, -34, + -24, -16, -11, 2, 17, 33, 48, 48, 37, 27, 18, 7, -5, -14, -20, -25, + -30, -31, -32, -37, -31, -20, -15, -3, 15, 30, 46, 53, 43, 31, 20, 11, + 0, -12, -21, -27, -31, -30, -30, -36, -33, -20, -10, -5, 9, 25, 41, 52, + 46, 34, 23, 15, 6, -9, -21, -27, -30, -31, -31, -37, -39, -25, -12, -7, + 1, 18, 36, 52, 53, 40, 28, 22, 13, -2, -18, -29, -32, -35, -34, -39, + -40, -28, -13, -7, -2, 12, 33, 50, 56, 44, 30, 24, 18, 4, -15, -29, + -32, -33, -33, -35, -40, -35, -20, -7, -2, 8, 25, 43, 54, 49, 35, 25, + 18, 8, -7, -23, -32, -32, -34, -34, -37, -36, -24, -11, -5, 2, 18, 36, + 51, 51, 39, 30, 24, 14, 0, -19, -32, -35, -35, -37, -38, -39, -29, -12, + -2, 3, 14, 29, 47, 54, 45, 33, 26, 17, 5, -12, -31, -37, -36, -38, + -38, -38, -32, -17, -3, 3, 9, 25, 42, 53, 49, 39, 31, 23, 10, -9, + -27, -38, -40, -41, -41, -41, -36, -23, -5, 5, 8, 18, 36, 51, 51, 43, + 34, 26, 16, 1, -20, -36, -40, -41, -42, -40, -38, -28, -10, 4, 7, 14, + 30, 48, 51, 45, 39, 31, 21, 4, -16, -33, -41, -43, -43, -39, -38, -32, + -15, 1, 7, 13, 25, 42, 52, 48, 39, 31, 22, 9, -10, -29, -40, -40, + -40, -38, -35, -34, -20, -2, 5, 9, 17, 33, 49, 50, 43, 34, 25, 13, + -4, -21, -36, -44, -44, -40, -35, -34, -26, -8, 5, 11, 17, 26, 43, 51, + 46, 36, 27, 16, 1, -16, -31, -42, -46, -43, -37, -35, -29, -12, 3, 11, + 17, 23, 37, 50, 52, 41, 29, 20, 4, -15, -30, -43, -49, -46, -39, -37, + -33, -15, 3, 13, 19, 23, 35, 52, 55, 44, 29, 20, 8, -12, -28, -40, + -48, -45, -39, -35, -32, -20, -2, 12, 16, 19, 28, 45, 55, 49, 35, 24, + 14, -3, -20, -36, -49, -53, -45, -38, -35, -27, -9, 8, 19, 23, 26, 40, + 55, 55, 41, 25, 15, -2, -19, -33, -46, -53, -47, -39, -35, -29, -14, 6, + 19, 24, 25, 35, 53, 59, 47, 29, 17, 7, -12, -30, -47, -58, -56, -47, + -39, -35, -22, -2, 17, 28, 30, 34, 50, 63, 56, 35, 19, 8, -9, -26, + -43, -56, -58, -49, -42, -38, -27, -9, 12, 26, 33, 34, 44, 60, 62, 44, + 23, 9, -4, -20, -40, -56, -63, -56, -44, -39, -30, -14, 8, 26, 35, 35, + 43, 60, 64, 50, 28, 13, 2, -16, -37, -53, -62, -61, -50, -42, -32, -17, + 2, 18, 32, 40, 44, 54, 63, 55, 37, 17, 4, -10, -31, -48, -61, -67, + -59, -45, -36, -24, -5, 17, 33, 43, 47, 54, 64, 59, 42, 20, 3, -10, + -28, -49, -63, -68, -63, -50, -37, -25, -7, 13, 31, 44, 48, 54, 61, 59, + 48, 27, 6, -10, -24, -43, -59, -67, -67, -56, -39, -28, -13, 8, 24, 42, + 51, 54, 58, 58, 52, 37, 14, -6, -20, -38, -54, -65, -70, -63, -45, -29, + -17, 2, 18, 37, 52, 56, 58, 56, 51, 42, 23, -2, -19, -34, -50, -62, + -70, -69, -52, -30, -17, -3, 15, 33, 50, 58, 58, 56, 52, 46, 29, 3, + -15, -31, -45, -58, -68, -71, -60, -38, -20, -5, 11, 25, 42, 58, 62, 58, + 51, 44, 36, 15, -10, -29, -43, -53, -64, -72, -67, -45, -21, -8, 4, 20, + 40, 60, 65, 57, 53, 48, 42, 21, -8, -27, -40, -50, -62, -71, -71, -54, + -29, -9, 3, 18, 34, 54, 68, 65, 57, 48, 40, 28, 2, -23, -41, -52, + -60, -71, -75, -60, -34, -12, 0, 13, 31, 52, 69, 66, 56, 50, 44, 33, + 7, -21, -38, -47, -55, -65, -75, -67, -41, -15, 2, 11, 23, 41, 61, 68, + 59, 49, 40, 34, 17, -11, -35, -47, -48, -55, -69, -72, -50, -21, 0, 8, + 15, 33, 56, 69, 62, 52, 44, 40, 26, -4, -30, -44, -48, -56, -69, -77, + -59, -28, -7, 7, 15, 30, 52, 68, 66, 55, 45, 38, 30, 6, -24, -43, + -49, -52, -64, -75, -65, -35, -10, 4, 11, 25, 45, 65, 67, 55, 48, 43, + 34, 13, -18, -39, -45, -49, -61, -75, -72, -45, -17, -2, 9, 20, 39, 61, + 70, 62, 52, 45, 36, 18, -9, -34, -47, -52, -58, -69, -72, -52, -23, -5, + 7, 17, 35, 54, 65, 63, 55, 45, 37, 23, 0, -27, -45, -49, -53, -63, + -71, -59, -31, -8, 7, 15, 28, 47, 61, 65, 58, 47, 38, 27, 6, -21, + -41, -49, -53, -62, -69, -62, -39, -14, 3, 14, 28, 46, 59, 64, 62, 51, + 39, 29, 11, -16, -40, -52, -55, -58, -65, -65, -47, -20, 1, 14, 24, 39, + 52, 59, 64, 56, 43, 33, 16, -8, -32, -49, -55, -58, -63, -65, -54, -29, + -3, 12, 21, 36, 51, 60, 65, 59, 46, 35, 21, -4, -28, -48, -56, -57, + -59, -60, -55, -37, -12, 9, 19, 32, 46, 54, 58, 58, 48, 36, 26, 7, + -18, -41, -53, -53, -52, -57, -58, -45, -19, 6, 15, 26, 42, 54, 59, 59, + 52, 39, 28, 10, -16, -40, -56, -56, -52, -51, -53, -45, -22, 4, 17, 24, + 35, 46, 56, 57, 52, 40, 30, 18, -7, -33, -54, -58, -52, -49, -53, -51, + -33, -5, 17, 26, 34, 43, 54, 58, 53, 42, 31, 19, 0, -24, -47, -60, + -55, -46, -46, -50, -39, -13, 13, 25, 32, 38, 48, 56, 52, 41, 30, 20, + 7, -15, -41, -58, -55, -44, -41, -44, -40, -19, 10, 25, 28, 32, 41, 53, + 52, 42, 31, 21, 13, -5, -32, -55, -60, -47, -36, -38, -40, -26, 2, 24, + 29, 28, 32, 46, 48, 40, 29, 21, 14, 1, -23, -48, -56, -46, -34, -33, + -36, -29, -7, 20, 28, 25, 26, 37, 46, 42, 30, 19, 15, 7, -13, -39, + -58, -54, -37, -27, -27, -29, -17, 13, 29, 28, 24, 31, 42, 42, 34, 21, + 11, 5, -10, -32, -51, -52, -40, -28, -24, -24, -18, 6, 27, 30, 26, 28, + 36, 38, 33, 22, 11, 6, -7, -26, -44, -49, -42, -30, -21, -17, -16, -5, + 18, 29, 26, 25, 29, 33, 33, 25, 13, 7, 0, -18, -36, -46, -45, -31, + -20, -16, -16, -9, 12, 28, 29, 24, 25, 29, 31, 26, 13, 2, -5, -15, + -26, -39, -46, -37, -19, -9, -9, -11, 1, 21, 31, 26, 21, 23, 26, 25, + 15, 4, -4, -10, -20, -32, -41, -38, -22, -10, -7, -9, -6, 11, 26, 29, + 22, 20, 21, 24, 19, 7, -6, -12, -17, -23, -30, -36, -27, -12, -3, 0, + -5, 3, 18, 28, 25, 18, 15, 16, 15, 7, -4, -10, -14, -19, -24, -30, + -26, -13, -3, 2, -3, -2, 12, 23, 26, 18, 13, 13, 14, 9, 0, -11, + -14, -15, -18, -24, -26, -16, -4, 4, 0, -5, 6, 17, 25, 21, 11, 7, + 8, 8, 1, -11, -14, -11, -10, -13, -20, -18, -7, 5, 7, -3, -2, 8, + 21, 23, 12, 4, 4, 8, 7, -5, -15, -14, -11, -9, -15, -20, -13, 1, + 8, 3, 0, 6, 17, 24, 16, 3, -2, 1, 0, -10, -17, -14, -8, -4, + -5, -11, -12, 0, 9, 6, -3, 1, 10, 18, 16, 5, -3, 0, 3, -4, + -13, -15, -10, -6, -4, -8, -13, -8, 5, 8, 5, 3, 9, 17, 18, 13, + 0, -7, -5, -5, -11, -14, -11, -6, 2, 2, -6, -9, 1, 8, 5, -2, + 1, 8, 14, 12, 2, -6, -5, -2, -6, -12, -10, -2, 3, 4, -5, -11, + -6, 5, 6, 0, 0, 7, 12, 14, 6, -7, -8, -6, -6, -9, -10, -5, + 4, 8, 4, -7, -11, -2, 6, 3, -2, 2, 9, 15, 12, -2, -8, -6, + -3, -5, -11, -9, 2, 10, 7, -5, -15, -10, 4, 6, -2, -2, 8, 14, + 14, 3, -9, -8, -5, -4, -8, -10, 0, 8, 9, 3, -9, -12, -3, 6, + 3, -3, 1, 8, 13, 5, -9, -13, -7, -2, -2, -6, -2, 9, 13, 6, + -6, -13, -10, 2, 4, -3, -2, 7, 13, 9, -6, -12, -11, -6, 0, -5, + -5, 7, 15, 13, 1, -10, -13, -4, 5, -2, -7, -2, 9, 9, -3, -11, + -11, -8, 2, 1, -3, 7, 15, 12, 4, -7, -13, -11, -2, 1, -4, -3, + 7, 11, 3, -8, -11, -10, 0, 1, -5, 2, 12, 17, 11, -2, -11, -11, + -3, 4, -4, -9, 1, 10, 3, -9, -11, -8, 0, 5, 1, 2, 11, 14, + 9, 1, -11, -15, -11, -3, 1, -3, 3, 12, 11, 1, -7, -9, -6, -3, + -5, -5, 5, 12, 9, 4, -3, -8, -8, -5, 0, -4, -3, 5, 6, -3, + -10, -7, -3, 0, 2, 3, 10, 14, 11, 4, -3, -11, -15, -15, -9, -5, + -5, 5, 13, 5, -2, 0, 2, 4, 1, -3, 4, 12, 11, 2, -5, -10, + -13, -13, -11, -6, -4, 3, 13, 9, 1, -2, 4, 5, 1, -5, 3, 12, + 13, 4, -9, -12, -14, -16, -17, -12, -5, 5, 16, 17, 6, 3, 9, 9, + 2, -8, -7, 2, 7, 4, -8, -12, -10, -13, -14, -13, -6, 4, 13, 19, + 10, 0, 6, 14, 8, -6, -9, 0, 7, 5, -8, -17, -13, -9, -14, -18, + -13, 2, 15, 23, 16, 4, 5, 16, 15, 0, -10, -6, 3, 6, -4, -15, + -15, -10, -11, -16, -16, -5, 10, 21, 18, 7, 2, 12, 18, 6, -7, -9, + 1, 7, 1, -14, -19, -15, -13, -16, -18, -8, 7, 19, 24, 16, 5, 8, + 16, 9, -4, -9, -5, 3, 4, -9, -19, -18, -13, -12, -17, -12, 2, 16, + 22, 17, 6, 4, 14, 13, 1, -8, -6, 2, 6, -5, -18, -20, -16, -14, + -18, -17, -5, 12, 23, 24, 14, 9, 15, 19, 9, -5, -8, -3, 2, -6, + -17, -23, -19, -14, -16, -17, -8, 7, 19, 24, 19, 10, 11, 17, 13, 3, + -5, -3, -2, -4, -14, -24, -25, -20, -18, -16, -10, 3, 16, 26, 28, 18, + 11, 15, 17, 9, -4, -7, -6, -6, -12, -24, -29, -22, -16, -15, -10, 0, + 13, 24, 27, 22, 14, 13, 16, 13, 2, -6, -7, -9, -12, -21, -29, -27, + -21, -15, -10, -3, 8, 21, 29, 26, 17, 13, 17, 19, 9, -5, -10, -9, + -12, -21, -30, -29, -22, -14, -10, -4, 7, 17, 26, 23, 17, 13, 12, 18, + 16, 5, -6, -10, -11, -19, -29, -32, -27, -18, -10, -4, 4, 13, 25, 26, + 21, 16, 11, 16, 17, 8, -5, -12, -12, -16, -25, -30, -27, -19, -10, -6, + 0, 10, 21, 24, 18, 15, 13, 16, 20, 14, 1, -10, -12, -15, -26, -31, + -29, -22, -12, -5, 0, 8, 19, 25, 22, 17, 14, 14, 19, 17, 4, -10, + -15, -15, -22, -30, -30, -26, -16, -6, 1, 7, 15, 23, 23, 18, 17, 17, + 17, 17, 8, -6, -15, -18, -24, -31, -29, -26, -19, -8, 2, 7, 15, 23, + 24, 21, 17, 15, 15, 17, 13, -4, -16, -20, -23, -30, -32, -27, -19, -8, + 3, 7, 14, 23, 24, 20, 16, 16, 15, 14, 10, 0, -12, -20, -24, -31, + -32, -25, -19, -10, 0, 9, 14, 22, 27, 23, 17, 17, 18, 12, 8, 1, + -12, -18, -23, -31, -34, -26, -17, -9, -2, 6, 14, 22, 27, 22, 16, 15, + 18, 17, 10, 3, -9, -17, -21, -31, -38, -32, -23, -13, -5, 4, 14, 21, + 30, 30, 21, 17, 18, 17, 10, 3, -8, -20, -23, -29, -38, -34, -25, -12, + 0, 3, 11, 17, 26, 31, 23, 15, 13, 16, 14, 5, -4, -15, -19, -23, + -35, -38, -32, -19, -7, -5, 6, 16, 25, 36, 32, 22, 19, 19, 15, 3, + -7, -16, -23, -26, -35, -42, -34, -19, -3, 1, 6, 18, 26, 37, 34, 20, + 15, 14, 14, 5, -7, -15, -21, -23, -28, -39, -37, -22, -5, 1, 3, 15, + 25, 35, 40, 27, 14, 14, 14, 6, -7, -14, -20, -25, -27, -36, -41, -28, + -8, 2, 4, 14, 24, 33, 40, 32, 17, 13, 12, 5, -7, -14, -17, -24, + -28, -34, -40, -32, -14, 1, 4, 13, 26, 33, 41, 40, 26, 15, 12, 4, + -9, -17, -20, -25, -31, -34, -41, -38, -20, 0, 7, 12, 24, 32, 40, 41, + 30, 17, 11, 4, -10, -18, -19, -21, -27, -31, -35, -36, -24, -5, 5, 9, + 21, 31, 37, 41, 36, 21, 11, 4, -8, -15, -18, -21, -26, -31, -34, -37, + -30, -12, 3, 9, 18, 30, 38, 44, 42, 29, 15, 7, -6, -18, -23, -24, + -25, -31, -34, -36, -33, -15, 3, 9, 17, 28, 38, 44, 42, 34, 20, 8, + -5, -18, -23, -22, -24, -30, -35, -35, -35, -24, -6, 6, 14, 25, 36, 42, + 45, 42, 28, 13, 1, -15, -26, -27, -26, -29, -35, -39, -38, -28, -10, 5, + 13, 21, 36, 47, 48, 45, 36, 21, 6, -11, -25, -31, -30, -29, -35, -41, + -41, -34, -18, 1, 15, 24, 35, 47, 52, 51, 42, 26, 8, -9, -25, -32, + -34, -32, -34, -40, -41, -35, -22, -5, 11, 21, 30, 44, 52, 51, 45, 32, + 15, -3, -19, -28, -33, -34, -36, -42, -44, -41, -30, -13, 6, 20, 29, 43, + 54, 56, 50, 37, 22, 4, -17, -31, -39, -39, -38, -40, -44, -41, -31, -14, + 4, 18, 26, 37, 52, 57, 54, 44, 29, 11, -9, -26, -38, -42, -40, -41, + -45, -46, -39, -24, -2, 17, 25, 35, 49, 59, 59, 52, 36, 19, -2, -22, + -38, -46, -45, -43, -44, -47, -41, -28, -7, 12, 22, 32, 45, 58, 60, 52, + 40, 26, 9, -14, -36, -46, -47, -44, -44, -50, -47, -34, -14, 8, 21, 30, + 42, 58, 65, 58, 46, 32, 14, -7, -30, -47, -51, -50, -45, -50, -51, -38, + -20, 4, 19, 28, 38, 53, 67, 63, 50, 40, 23, 2, -22, -43, -54, -55, + -50, -53, -57, -48, -31, -6, 17, 28, 39, 53, 69, 72, 60, 47, 29, 7, + -18, -39, -54, -59, -56, -53, -55, -52, -37, -16, 10, 25, 36, 48, 65, 75, + 68, 54, 40, 20, -6, -31, -52, -61, -61, -59, -63, -62, -46, -24, 2, 20, + 33, 50, 67, 79, 75, 62, 49, 30, 2, -29, -50, -63, -66, -65, -64, -64, + -50, -28, -6, 18, 34, 48, 62, 74, 79, 70, 54, 38, 14, -19, -45, -62, + -70, -71, -67, -68, -61, -39, -15, 10, 28, 45, 63, 77, 82, 77, 62, 47, + 25, -9, -40, -61, -70, -73, -69, -70, -66, -47, -23, 2, 23, 41, 57, 71, + 79, 83, 72, 55, 37, 6, -27, -51, -67, -76, -78, -77, -75, -60, -35, -12, + 13, 37, 59, 75, 82, 86, 81, 66, 48, 17, -23, -50, -66, -77, -83, -83, + -78, -66, -43, -18, 7, 31, 54, 73, 83, 87, 87, 74, 55, 29, -10, -41, + -61, -76, -85, -88, -84, -72, -53, -28, -3, 22, 51, 75, 84, 88, 92, 87, + 67, 40, 0, -38, -60, -77, -89, -94, -89, -77, -59, -34, -7, 17, 44, 73, + 88, 90, 91, 88, 74, 49, 12, -29, -57, -73, -84, -93, -94, -84, -68, -44, + -17, 8, 33, 64, 85, 90, 92, 91, 83, 63, 30, -15, -50, -71, -82, -92, + -96, -90, -74, -52, -26, 0, 24, 56, 82, 92, 93, 92, 89, 74, 42, 0, + -41, -67, -80, -93, -100, -97, -83, -62, -35, -8, 16, 43, 74, 91, 96, 96, + 93, 83, 56, 16, -28, -61, -79, -92, -99, -99, -90, -71, -45, -16, 9, 36, + 66, 88, 98, 97, 93, 87, 68, 31, -16, -52, -75, -89, -98, -103, -98, -81, + -54, -23, 1, 25, 56, 83, 97, 98, 92, 88, 76, 46, 1, -42, -68, -81, + -91, -99, -97, -82, -58, -30, -6, 15, 44, 73, 91, 94, 89, 85, 78, 55, + 16, -28, -59, -77, -87, -93, -95, -85, -65, -40, -16, 6, 33, 62, 85, 94, + 90, 86, 81, 66, 32, -15, -52, -73, -84, -90, -93, -87, -69, -45, -22, 0, + 22, 48, 75, 88, 88, 85, 80, 67, 42, 4, -36, -62, -77, -87, -90, -85, + -72, -52, -30, -11, 11, 36, 63, 83, 86, 86, 82, 74, 54, 17, -25, -55, + -72, -81, -88, -87, -77, -57, -34, -16, 4, 26, 54, 77, 84, 84, 82, 75, + 58, 27, -12, -45, -65, -76, -84, -84, -76, -61, -41, -24, -7, 15, 41, 67, + 78, 81, 80, 76, 67, 42, 5, -30, -54, -67, -79, -85, -79, -67, -50, -32, + -16, 6, 32, 58, 73, 77, 81, 78, 68, 49, 16, -19, -45, -63, -74, -80, + -77, -67, -53, -35, -20, -3, 20, 45, 65, 72, 76, 75, 68, 56, 29, -6, + -33, -52, -65, -75, -77, -70, -57, -42, -28, -13, 9, 34, 57, 70, 73, 75, + 72, 63, 41, 7, -24, -46, -60, -70, -75, -72, -59, -45, -31, -18, 0, 25, + 48, 63, 68, 70, 71, 65, 47, 17, -13, -33, -49, -62, -73, -73, -61, -48, + -37, -25, -10, 14, 39, 57, 64, 67, 70, 69, 54, 28, -3, -27, -44, -57, + -68, -74, -66, -50, -39, -26, -13, 5, 30, 50, 60, 62, 64, 65, 58, 38, + 9, -17, -35, -46, -59, -69, -67, -52, -40, -31, -20, -6, 18, 42, 55, 58, + 60, 65, 62, 47, 20, -10, -28, -39, -51, -66, -70, -58, -44, -34, -23, -10, + 11, 34, 51, 57, 58, 62, 63, 51, 29, 2, -21, -34, -46, -60, -69, -63, + -49, -37, -27, -15, 3, 26, 45, 55, 56, 58, 62, 55, 37, 11, -14, -29, + -39, -52, -65, -66, -52, -40, -30, -18, -5, 17, 39, 52, 54, 55, 58, 57, + 44, 21, -8, -24, -33, -45, -59, -66, -57, -43, -31, -20, -11, 7, 30, 47, + 53, 51, 52, 55, 51, 33, 4, -20, -29, -36, -49, -64, -63, -50, -36, -24, + -14, 0, 22, 43, 55, 53, 49, 52, 51, 39, 12, -16, -27, -33, -45, -60, + -66, -53, -37, -25, -16, -6, 16, 40, 53, 53, 47, 49, 51, 43, 22, 0, + 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, -2, -2, -2, -2, 0, -2, + 0, 0, 1, 2, 3, 4, 4, 4, 5, 6, 7, 6, 3, 1, 0, -3, + -5, -11, -17, -20, -20, -18, -16, -17, -17, -14, -10, -9, -13, -18, -19, -15, + -13, -12, -13, -8, 1, 12, 25, 32, 40, 45, 50, 49, 41, 32, 24, 16, + 9, 1, -12, -20, -23, -24, -20, -20, -18, -12, -11, -12, -7, 0, 10, 17, + 23, 25, 24, 21, 22, 23, 21, 10, 1, -5, -8, -11, -19, -29, -33, -32, + -26, -19, -16, -14, -12, -8, -7, -11, -19, -27, -29, -27, -25, -25, -24, -17, + -4, 13, 26, 34, 43, 54, 59, 56, 46, 33, 23, 15, 5, -11, -23, -32, + -35, -32, -30, -27, -23, -16, -11, -5, 3, 11, 23, 31, 36, 33, 28, 27, + 26, 21, 11, 1, -9, -14, -18, -23, -28, -35, -33, -26, -18, -12, -11, -7, + -4, -2, 0, -8, -19, -29, -33, -32, -30, -30, -25, -17, -4, 13, 26, 36, + 47, 55, 59, 53, 43, 32, 23, 12, 0, -14, -23, -30, -35, -35, -35, -33, + -28, -19, -11, -6, 3, 11, 22, 33, 39, 38, 34, 30, 27, 20, 11, 0, + -9, -17, -21, -26, -31, -34, -29, -19, -8, -3, 0, -3, 1, 4, 1, -11, + -25, -35, -37, -39, -35, -32, -27, -17, 0, 15, 29, 42, 55, 63, 62, 55, + 47, 38, 27, 14, -4, -20, -31, -40, -44, -46, -45, -41, -34, -25, -14, -3, + 8, 22, 32, 43, 44, 40, 36, 34, 26, 18, 8, -2, -11, -20, -25, -29, + -33, -31, -21, -10, -2, -2, -2, 4, 6, 9, 0, -14, -28, -35, -39, -38, + -38, -36, -30, -16, 0, 16, 29, 41, 55, 65, 67, 59, 49, 39, 28, 13, + -3, -19, -32, -42, -48, -51, -53, -47, -36, -22, -12, 0, 10, 24, 38, 46, + 48, 43, 39, 32, 26, 17, 6, -7, -16, -21, -26, -31, -34, -28, -16, -2, + 3, 1, 2, 8, 16, 12, 2, -15, -27, -34, -37, -41, -47, -44, -33, -16, + 1, 16, 31, 47, 65, 75, 73, 63, 52, 41, 27, 9, -14, -34, -47, -54, + -55, -58, -57, -50, -35, -17, 0, 8, 20, 34, 47, 54, 49, 42, 36, 29, + 21, 9, -4, -14, -21, -26, -30, -33, -28, -18, -5, 4, 6, 6, 8, 13, + 17, 12, -4, -21, -33, -39, -44, -49, -50, -46, -35, -15, 4, 22, 36, 55, + 72, 81, 78, 69, 54, 42, 27, 6, -19, -38, -52, -57, -62, -65, -64, -52, + -35, -17, -3, 8, 19, 33, 45, 50, 48, 42, 35, 29, 18, 7, -5, -11, + -20, -26, -29, -27, -20, -13, -4, 3, 8, 9, 11, 12, 12, 5, -8, -22, + -33, -42, -50, -53, -51, -42, -27, -11, 9, 27, 45, 62, 75, 78, 73, 60, + 48, 32, 14, -8, -30, -46, -54, -60, -64, -62, -53, -39, -23, -8, 5, 17, + 30, 41, 46, 44, 38, 30, 22, 11, 4, -5, -12, -20, -25, -26, -24, -17, + -7, 3, 8, 11, 12, 14, 15, 14, 9, -4, -17, -32, -44, -54, -57, -56, + -48, -36, -22, -5, 18, 41, 61, 74, 79, 75, 67, 55, 39, 20, -2, -20, + -37, -47, -56, -62, -63, -57, -44, -31, -18, -5, 7, 16, 28, 35, 38, 37, + 32, 25, 16, 8, 3, -2, -5, -11, -19, -21, -16, -7, 3, 6, 8, 7, + 8, 10, 9, 5, -4, -13, -23, -37, -49, -54, -54, -47, -38, -25, -9, 9, + 30, 50, 67, 77, 75, 69, 58, 42, 26, 7, -12, -31, -46, -52, -56, -59, + -58, -49, -36, -19, -5, 8, 14, 22, 28, 33, 35, 30, 23, 13, 4, 3, + 3, 0, -8, -12, -13, -10, -6, 2, 8, 11, 12, 11, 9, 4, -2, -5, + -12, -23, -35, -46, -52, -54, -48, -36, -22, -8, 9, 28, 46, 61, 70, 72, + 68, 58, 45, 27, 9, -8, -22, -35, -43, -48, -48, -46, -39, -33, -23, -12, + 1, 8, 11, 14, 16, 19, 19, 17, 11, 7, 8, 11, 13, 7, 5, 2, + 2, 2, 4, 6, 6, 5, 2, -3, -5, -9, -11, -17, -23, -29, -34, -40, + -45, -41, -32, -18, -5, 7, 19, 36, 54, 64, 67, 61, 55, 48, 36, 18, + 3, -11, -23, -36, -45, -46, -42, -39, -34, -27, -20, -11, 0, 10, 13, 14, + 12, 13, 13, 10, 7, 6, 9, 11, 11, 11, 10, 10, 8, 9, 9, 9, + 6, 1, -4, -12, -16, -22, -25, -28, -29, -30, -39, -43, -39, -26, -11, 0, + 8, 19, 33, 48, 58, 63, 61, 56, 50, 40, 25, 8, -5, -15, -24, -35, + -41, -42, -39, -32, -29, -25, -21, -13, -6, 0, 4, 2, 2, 3, 6, 6, + 7, 11, 17, 20, 22, 23, 24, 23, 21, 17, 12, 4, -5, -13, -22, -29, + -37, -41, -40, -36, -31, -32, -34, -34, -22, -6, 8, 14, 20, 29, 41, 50, + 56, 56, 49, 45, 39, 30, 17, 5, -8, -19, -28, -34, -35, -32, -27, -25, + -25, -23, -19, -12, -7, -4, -6, -10, -11, -7, 0, 4, 10, 14, 19, 26, + 32, 35, 34, 31, 25, 16, 6, -5, -17, -29, -39, -47, -51, -50, -44, -35, + -28, -27, -25, -18, -6, 10, 18, 21, 25, 31, 40, 46, 49, 48, 44, 42, + 37, 29, 19, 8, -5, -14, -21, -29, -30, -30, -27, -28, -32, -33, -31, -22, + -17, -15, -17, -19, -19, -9, 5, 16, 22, 25, 31, 38, 44, 47, 43, 34, + 20, 6, -9, -21, -35, -49, -59, -62, -60, -53, -42, -30, -22, -15, -6, 4, + 14, 23, 27, 28, 27, 30, 35, 38, 39, 42, 38, 35, 30, 25, 20, 12, + 4, -6, -18, -23, -22, -20, -22, -30, -37, -39, -34, -29, -27, -27, -26, -23, + -16, -3, 10, 21, 29, 35, 43, 46, 50, 49, 41, 28, 15, -2, -19, -35, + -50, -62, -67, -67, -60, -50, -36, -23, -14, -6, 3, 11, 21, 27, 27, 24, + 25, 27, 29, 31, 36, 41, 42, 39, 33, 27, 22, 17, 8, -3, -11, -15, + -15, -18, -25, -35, -42, -45, -42, -41, -41, -40, -38, -28, -12, 7, 22, 34, + 43, 51, 59, 62, 59, 49, 37, 20, 1, -19, -38, -54, -65, -73, -74, -69, + -55, -35, -19, -10, -2, 8, 18, 23, 25, 25, 22, 20, 19, 20, 22, 30, + 39, 44, 42, 39, 35, 32, 29, 18, 4, -8, -13, -15, -17, -24, -33, -43, + -47, -44, -42, -40, -40, -39, -32, -17, 3, 16, 28, 39, 47, 53, 56, 56, + 52, 40, 24, 5, -12, -29, -43, -54, -65, -72, -71, -56, -36, -20, -13, -4, + 5, 12, 18, 21, 23, 20, 18, 14, 16, 19, 27, 38, 45, 45, 42, 41, + 42, 37, 27, 15, 1, -8, -12, -13, -17, -30, -40, -47, -48, -47, -46, -46, + -45, -41, -28, -9, 11, 26, 38, 45, 51, 55, 58, 55, 47, 31, 10, -12, + -27, -39, -49, -58, -67, -69, -62, -46, -26, -13, -4, 2, 7, 14, 18, 21, + 20, 15, 11, 12, 14, 21, 32, 40, 44, 42, 42, 40, 37, 33, 22, 11, + 1, -7, -11, -11, -19, -30, -39, -43, -43, -42, -43, -44, -44, -36, -20, 0, + 14, 25, 35, 42, 46, 50, 50, 48, 36, 17, -3, -18, -30, -36, -43, -52, + -59, -60, -49, -35, -20, -12, -7, -4, 2, 8, 12, 12, 9, 9, 12, 16, + 23, 29, 39, 45, 46, 46, 43, 41, 37, 30, 20, 7, -5, -10, -11, -15, + -25, -39, -46, -45, -43, -42, -45, -46, -39, -26, -8, 8, 20, 31, 41, 45, + 48, 46, 44, 36, 21, 1, -20, -31, -33, -36, -44, -53, -59, -54, -41, -26, + -17, -12, -6, -3, 5, 7, 9, 11, 11, 12, 15, 20, 29, 36, 42, 46, + 45, 42, 40, 38, 33, 25, 13, 4, -7, -10, -11, -17, -29, -38, -38, -34, + -35, -39, -41, -39, -31, -16, -6, 4, 14, 24, 30, 34, 34, 35, 32, 22, + 8, -9, -16, -16, -17, -22, -33, -43, -46, -41, -34, -30, -25, -19, -14, -9, + -6, -2, 5, 9, 13, 15, 21, 29, 36, 43, 47, 46, 46, 42, 39, 37, + 31, 20, 10, 0, -6, -9, -14, -22, -29, -33, -31, -30, -34, -37, -37, -30, + -21, -12, -5, 1, 10, 20, 28, 31, 31, 28, 20, 12, 0, -8, -10, -10, + -16, -24, -33, -39, -44, -42, -35, -28, -23, -18, -14, -10, -4, 6, 12, 16, + 17, 22, 29, 33, 35, 38, 41, 43, 41, 38, 34, 30, 24, 16, 9, 3, + -4, -10, -15, -21, -23, -23, -23, -24, -28, -32, -31, -28, -22, -15, -10, -6, + 2, 11, 20, 23, 25, 19, 14, 9, 5, 3, 2, -2, -8, -19, -28, -36, + -42, -44, -39, -33, -28, -26, -20, -11, 0, 8, 15, 22, 28, 33, 35, 36, + 37, 38, 41, 40, 38, 32, 27, 21, 17, 11, 4, -3, -8, -12, -17, -18, + -16, -16, -15, -18, -22, -25, -26, -25, -23, -19, -15, -9, -2, 8, 13, 17, + 18, 17, 16, 15, 13, 10, 6, 0, -9, -21, -32, -42, -47, -46, -43, -36, + -30, -22, -15, -6, 4, 14, 22, 28, 33, 36, 37, 36, 35, 37, 36, 36, + 32, 27, 23, 16, 10, 5, 0, -7, -10, -12, -11, -11, -11, -10, -9, -11, + -16, -22, -27, -30, -30, -30, -25, -19, -9, 0, 7, 13, 18, 23, 27, 27, + 26, 20, 12, 1, -13, -27, -40, -50, -54, -54, -49, -42, -33, -21, -10, 1, + 14, 24, 30, 39, 44, 43, 38, 36, 38, 37, 34, 31, 28, 22, 13, 7, + 5, -2, -7, -11, -14, -13, -13, -8, -6, -6, -10, -12, -14, -19, -26, -34, + -38, -33, -26, -15, -7, 2, 7, 17, 26, 35, 40, 37, 29, 19, 7, -12, + -31, -44, -53, -56, -61, -62, -59, -46, -27, -9, 5, 14, 25, 36, 47, 53, + 51, 45, 37, 34, 32, 29, 26, 23, 18, 13, 5, 0, -3, -4, -6, -10, + -12, -12, -6, 2, 6, 2, -6, -12, -17, -21, -31, -41, -47, -43, -32, -20, + -11, -4, 9, 21, 40, 50, 48, 42, 34, 22, 5, -16, -36, -53, -58, -63, + -69, -73, -63, -43, -19, -2, 9, 19, 34, 50, 60, 61, 53, 42, 37, 32, + 30, 24, 21, 16, 11, 4, -4, -7, -6, -5, -5, -10, -14, -11, -4, 3, + 2, -2, -8, -13, -19, -26, -36, -42, -40, -33, -21, -9, 1, 10, 22, 36, + 49, 53, 47, 36, 19, 1, -18, -36, -51, -60, -65, -67, -67, -63, -47, -24, + -4, 11, 20, 33, 48, 57, 57, 52, 42, 33, 30, 28, 25, 19, 16, 12, + 8, 3, -2, -2, -2, -2, -5, -8, -10, -5, -2, 0, 0, -5, -8, -15, + -23, -32, -39, -38, -33, -24, -15, -7, 5, 16, 30, 45, 52, 49, 40, 23, + 4, -14, -29, -42, -55, -63, -67, -67, -61, -50, -35, -19, 0, 16, 31, 46, + 56, 59, 56, 47, 38, 34, 31, 28, 23, 16, 10, 4, 0, -2, -2, 0, + -5, -9, -12, -11, -7, -3, -3, -4, -5, -4, -7, -14, -26, -33, -32, -27, + -20, -15, -7, 2, 13, 21, 34, 42, 46, 40, 25, 7, -13, -27, -35, -44, + -54, -62, -64, -60, -51, -39, -26, -10, 8, 24, 40, 51, 58, 60, 54, 44, + 36, 29, 24, 19, 13, 8, 0, -6, -5, 0, 1, 0, -4, -3, -2, 0, + 1, -2, -5, -5, -4, -7, -17, -27, -31, -29, -24, -19, -15, -9, -3, 7, + 18, 27, 34, 39, 37, 26, 9, -9, -24, -32, -39, -47, -55, -60, -57, -51, + -42, -32, -20, -6, 14, 31, 48, 57, 60, 58, 52, 45, 35, 25, 21, 17, + 9, 0, -8, -10, -8, -7, -6, -9, -9, -6, -2, 0, -3, -6, -6, -2, + 1, -6, -15, -25, -25, -20, -17, -13, -11, -7, 1, 8, 16, 24, 31, 34, + 29, 16, -3, -17, -28, -35, -41, -47, -54, -56, -54, -46, -37, -27, -15, 4, + 23, 40, 50, 58, 60, 58, 50, 42, 34, 26, 19, 14, 4, -6, -13, -13, + -13, -14, -16, -15, -12, -9, -7, -7, -4, -4, 2, 7, 5, 0, -8, -11, + -13, -13, -11, -10, -11, -11, -9, 0, 8, 14, 22, 24, 19, 9, -3, -14, + -23, -29, -32, -38, -47, -54, -52, -44, -32, -23, -9, 8, 23, 39, 52, 59, + 58, 51, 46, 43, 33, 25, 16, 9, 4, -4, -11, -15, -16, -16, -15, -14, + -15, -16, -13, -7, -5, 2, 5, 5, 5, 6, 3, -4, -6, -4, -5, -10, + -16, -16, -13, -6, 4, 12, 15, 17, 14, 10, 4, -8, -17, -23, -30, -38, + -46, -52, -51, -41, -30, -20, -8, 9, 29, 47, 56, 57, 55, 52, 50, 45, + 34, 20, 10, 2, -2, -9, -16, -22, -24, -22, -21, -22, -19, -14, -7, -4, + 1, 5, 11, 15, 20, 17, 9, 3, 3, 0, -6, -15, -21, -23, -16, -9, + -3, 4, 10, 13, 15, 13, 4, -9, -15, -20, -27, -39, -48, -51, -47, -38, + -29, -21, -7, 16, 36, 48, 51, 52, 55, 60, 59, 49, 33, 20, 12, 7, + -2, -13, -24, -28, -27, -26, -30, -32, -29, -20, -9, 0, 3, 8, 16, 25, + 28, 23, 17, 12, 6, -2, -14, -26, -31, -27, -18, -10, -3, 7, 15, 22, + 24, 18, 9, 0, -9, -19, -34, -46, -57, -57, -51, -44, -38, -26, -5, 21, + 42, 48, 53, 58, 67, 75, 71, 57, 37, 23, 12, 3, -12, -27, -39, -43, + -43, -45, -47, -42, -28, -12, 2, 7, 12, 20, 32, 38, 37, 30, 21, 13, + 1, -13, -26, -34, -33, -26, -17, -10, -3, 9, 20, 25, 22, 13, 5, -3, + -13, -28, -43, -53, -56, -51, -46, -40, -31, -14, 10, 31, 41, 47, 56, 67, + 76, 73, 63, 46, 30, 19, 9, -7, -25, -39, -47, -50, -54, -52, -50, -38, + -22, -9, 4, 12, 22, 30, 39, 41, 39, 31, 22, 12, -3, -19, -30, -32, + -29, -23, -17, -9, 1, 12, 20, 24, 18, 10, 2, -7, -19, -35, -50, -59, + -59, -54, -49, -43, -31, -9, 15, 32, 41, 53, 70, 85, 87, 80, 64, 49, + 37, 23, 2, -23, -42, -52, -59, -66, -69, -68, -56, -38, -18, -2, 9, 19, + 31, 41, 49, 51, 44, 35, 21, 5, -9, -22, -29, -30, -26, -20, -14, -7, + 5, 15, 17, 14, 9, 2, -4, -16, -29, -45, -55, -56, -50, -46, -44, -36, + -19, 1, 19, 33, 46, 63, 79, 86, 84, 73, 60, 47, 32, 12, -10, -30, + -48, -59, -68, -72, -73, -64, -49, -30, -12, 2, 12, 26, 35, 45, 51, 51, + 44, 30, 15, 3, -9, -17, -20, -21, -19, -18, -14, 0, 10, 16, 15, 7, + -4, -10, -14, -24, -38, -51, -58, -55, -50, -44, -36, -23, -7, 10, 26, 41, + 57, 76, 89, 89, 81, 70, 59, 45, 25, 0, -24, -41, -56, -67, -75, -80, + -76, -63, -45, -26, -9, 6, 20, 32, 44, 52, 54, 53, 47, 35, 18, 3, + -6, -11, -14, -16, -19, -19, -12, -4, 5, 5, 0, -8, -12, -15, -21, -34, + -47, -51, -45, -39, -34, -30, -23, -12, 4, 17, 31, 45, 60, 72, 78, 75, + 69, 62, 53, 40, 18, -5, -24, -38, -50, -62, -73, -78, -74, -59, -41, -28, + -17, -4, 14, 33, 47, 55, 58, 55, 48, 39, 29, 16, 4, -5, -11, -18, + -21, -20, -15, -8, -7, -9, -13, -15, -16, -17, -23, -33, -43, -44, -41, -34, + -28, -23, -16, -8, 5, 21, 36, 50, 62, 73, 76, 73, 68, 59, 48, 30, + 9, -16, -35, -48, -59, -70, -77, -79, -72, -54, -38, -24, -8, 8, 29, 45, + 56, 61, 62, 56, 51, 39, 27, 16, 4, -8, -16, -22, -23, -25, -19, -16, + -17, -19, -20, -21, -18, -19, -25, -32, -38, -34, -24, -19, -15, -12, -7, 3, + 15, 28, 39, 48, 56, 63, 63, 63, 57, 47, 32, 14, -5, -22, -36, -46, + -58, -68, -73, -71, -61, -47, -35, -23, -9, 10, 29, 43, 52, 56, 56, 56, + 52, 45, 33, 19, 6, -5, -15, -22, -25, -26, -26, -29, -29, -26, -24, -20, + -19, -23, -27, -30, -27, -21, -18, -14, -10, -7, 0, 8, 18, 30, 40, 47, + 52, 54, 54, 55, 49, 39, 22, 7, -9, -24, -37, -50, -58, -65, -71, -67, + -59, -50, -39, -23, -6, 15, 32, 43, 51, 57, 61, 64, 61, 52, 37, 21, + 4, -11, -20, -26, -30, -35, -37, -39, -35, -29, -22, -17, -20, -22, -20, -18, + -17, -16, -13, -8, -3, 2, 7, 10, 17, 27, 35, 42, 43, 44, 45, 44, + 38, 28, 16, 3, -10, -22, -33, -46, -57, -64, -64, -59, -53, -46, -34, -17, + 3, 21, 32, 41, 48, 55, 60, 60, 54, 44, 31, 18, 3, -10, -19, -27, + -30, -32, -34, -35, -30, -23, -17, -17, -20, -20, -20, -17, -15, -13, -11, -8, + 1, 8, 12, 17, 23, 30, 39, 39, 37, 36, 35, 34, 27, 14, 0, -10, + -15, -23, -34, -46, -56, -60, -56, -49, -39, -32, -23, -8, 8, 23, 32, 38, + 44, 54, 58, 57, 48, 37, 29, 17, 4, -11, -21, -28, -29, -31, -34, -35, + -27, -20, -15, -16, -16, -17, -13, -10, -10, -11, -10, -4, 5, 11, 13, 15, + 21, 29, 33, 32, 28, 25, 25, 23, 16, 5, -6, -10, -16, -21, -30, -42, + -48, -48, -43, -34, -29, -21, -13, -3, 11, 22, 27, 34, 39, 48, 53, 48, + 42, 32, 23, 16, 4, -7, -18, -24, -24, -26, -28, -24, -19, -14, -13, -16, + -18, -18, -16, -14, -15, -16, -15, -7, 3, 11, 14, 21, 27, 33, 36, 33, + 30, 25, 22, 17, 9, -4, -15, -21, -24, -31, -39, -44, -44, -39, -30, -23, + -16, -8, 4, 14, 21, 23, 25, 29, 37, 43, 42, 36, 31, 25, 18, 11, + 4, -7, -11, -13, -16, -21, -22, -18, -14, -13, -16, -19, -21, -21, -19, -19, + -20, -18, -11, -2, 8, 14, 18, 23, 30, 34, 35, 31, 27, 21, 13, 2, + -11, -17, -23, -28, -36, -39, -40, -37, -31, -23, -14, -9, 0, 7, 13, 15, + 15, 16, 22, 27, 30, 28, 29, 32, 29, 23, 16, 9, 4, 1, -2, -7, + -14, -19, -14, -10, -10, -14, -18, -22, -24, -23, -26, -28, -27, -18, -8, -3, + 2, 9, 22, 33, 40, 40, 36, 30, 25, 20, 8, -8, -22, -29, -32, -39, + -48, -50, -42, -30, -19, -13, -8, 2, 11, 22, 25, 21, 17, 15, 20, 23, + 21, 20, 20, 19, 19, 16, 11, 9, 7, 7, 3, 0, -3, -5, -5, -5, + -7, -12, -22, -28, -32, -35, -35, -36, -30, -21, -12, -4, 3, 16, 29, 39, + 46, 45, 40, 34, 26, 13, -2, -17, -28, -37, -48, -57, -60, -52, -36, -19, + -12, -8, 2, 16, 28, 33, 28, 23, 21, 22, 21, 19, 18, 16, 14, 12, + 8, 6, 5, 5, 7, 5, 4, 5, 7, 9, 7, 3, -5, -13, -22, -28, + -35, -44, -49, -48, -38, -26, -14, -7, 4, 20, 38, 49, 54, 53, 49, 40, + 26, 8, -11, -24, -33, -46, -61, -70, -67, -52, -31, -14, -5, 4, 14, 27, + 36, 36, 33, 29, 26, 25, 21, 14, 10, 7, 8, 6, 5, 5, 6, 8, + 9, 10, 14, 18, 17, 13, 5, -4, -12, -20, -28, -37, -49, -56, -56, -48, + -36, -25, -15, -2, 16, 36, 51, 55, 57, 55, 48, 37, 20, 1, -17, -30, + -43, -60, -73, -76, -63, -43, -24, -14, -6, 7, 23, 39, 44, 38, 34, 31, + 32, 30, 24, 16, 8, 5, 6, 6, 5, 5, 6, 10, 10, 13, 16, 19, + 19, 14, 5, -7, -18, -25, -34, -45, -55, -61, -59, -51, -39, -25, -12, 5, + 27, 48, 58, 60, 61, 58, 49, 32, 14, -4, -20, -36, -54, -69, -79, -75, + -57, -35, -21, -15, -4, 12, 28, 39, 42, 41, 38, 38, 38, 33, 23, 13, + 8, 9, 11, 9, 5, 3, 6, 10, 13, 14, 15, 17, 16, 9, -6, -16, + -21, -27, -40, -56, -65, -67, -57, -45, -33, -23, -5, 21, 44, 60, 66, 67, + 65, 61, 47, 25, 2, -16, -34, -53, -72, -83, -82, -70, -51, -33, -20, -8, + 8, 25, 39, 46, 43, 43, 43, 43, 38, 27, 17, 9, 8, 10, 11, 9, + 5, 5, 8, 13, 14, 18, 20, 18, 12, -2, -13, -19, -25, -34, -48, -62, + -69, -67, -58, -46, -32, -14, 9, 30, 48, 60, 69, 72, 69, 57, 36, 13, + -6, -27, -47, -66, -79, -83, -77, -64, -46, -29, -13, 4, 17, 30, 39, 41, + 46, 48, 45, 40, 31, 20, 12, 10, 13, 14, 12, 11, 10, 10, 15, 17, + 20, 20, 17, 12, 0, -14, -24, -30, -37, -47, -60, -69, -68, -62, -51, -36, + -18, 5, 25, 45, 58, 65, 68, 67, 59, 42, 20, -2, -22, -42, -61, -75, + -81, -77, -66, -51, -35, -20, -4, 14, 28, 37, 38, 38, 42, 47, 43, 35, + 24, 17, 14, 14, 17, 20, 20, 17, 13, 14, 17, 18, 18, 17, 11, -2, + -15, -24, -31, -38, -46, -52, -58, -62, -61, -52, -38, -22, -4, 16, 35, 48, + 55, 60, 62, 57, 46, 26, 6, -17, -35, -53, -68, -76, -75, -66, -51, -38, + -23, -7, 10, 25, 35, 38, 37, 39, 40, 39, 30, 21, 16, 15, 15, 16, + 20, 24, 26, 27, 27, 26, 24, 21, 19, 11, -3, -16, -29, -40, -44, -50, + -54, -57, -58, -55, -48, -36, -21, -5, 13, 29, 41, 48, 52, 53, 50, 41, + 26, 7, -14, -33, -49, -62, -70, -69, -61, -48, -36, -21, -5, 16, 30, 35, + 35, 35, 32, 31, 29, 24, 17, 13, 13, 14, 15, 18, 26, 34, 39, 37, + 32, 29, 26, 22, 13, 1, -15, -29, -40, -46, -51, -54, -55, -52, -46, -40, + -32, -22, -10, 5, 19, 28, 33, 35, 37, 38, 33, 21, 8, -7, -20, -35, + -50, -57, -57, -49, -37, -28, -21, -8, 10, 25, 32, 32, 31, 27, 24, 22, + 20, 15, 13, 13, 15, 15, 19, 26, 36, 42, 43, 40, 33, 27, 22, 16, + 3, -13, -26, -37, -44, -50, -55, -54, -48, -42, -32, -24, -18, -10, -3, 8, + 20, 30, 31, 26, 22, 20, 15, 7, -7, -20, -32, -43, -52, -52, -46, -36, + -25, -16, -5, 9, 24, 38, 42, 39, 30, 23, 19, 15, 11, 8, 6, 6, + 6, 9, 18, 30, 42, 47, 45, 43, 38, 31, 22, 8, -9, -21, -33, -45, + -55, -59, -56, -47, -37, -29, -21, -13, -5, 2, 8, 13, 19, 22, 20, 15, + 9, 5, -3, -9, -20, -30, -39, -46, -45, -40, -31, -24, -16, -6, 7, 21, + 35, 39, 36, 31, 24, 22, 15, 10, 8, 5, 6, 3, 4, 12, 25, 40, + 48, 50, 48, 43, 37, 30, 17, -2, -18, -33, -45, -57, -64, -62, -53, -40, + -31, -23, -13, -3, 4, 11, 16, 19, 18, 17, 13, 7, -3, -10, -16, -22, + -31, -40, -45, -45, -41, -32, -24, -15, -5, 8, 24, 39, 47, 44, 38, 32, + 26, 20, 12, 3, -4, -4, -5, -4, 1, 11, 29, 41, 49, 51, 49, 45, + 38, 27, 9, -11, -27, -38, -52, -60, -64, -58, -45, -32, -21, -14, -5, 3, + 10, 13, 13, 14, 14, 12, 4, -6, -12, -17, -21, -25, -31, -35, -40, -39, + -33, -27, -19, -12, 1, 16, 29, 38, 42, 40, 36, 33, 30, 22, 11, 1, + -2, -2, -3, -2, 2, 16, 32, 44, 48, 46, 44, 39, 31, 19, 1, -21, + -36, -48, -58, -62, -59, -49, -38, -28, -20, -12, -2, 9, 16, 16, 15, 16, + 14, 9, 2, -7, -14, -19, -25, -31, -36, -38, -38, -36, -34, -28, -20, -7, + 8, 22, 33, 41, 46, 46, 42, 39, 33, 25, 14, 4, -4, -8, -8, -4, + 4, 16, 30, 38, 42, 46, 45, 38, 25, 10, -7, -24, -39, -51, -58, -59, + -53, -43, -34, -28, -21, -9, 5, 15, 17, 16, 15, 16, 15, 10, 2, -10, + -17, -21, -26, -33, -38, -40, -37, -34, -33, -28, -17, 0, 15, 29, 40, 48, + 50, 48, 44, 40, 34, 26, 15, 3, -6, -11, -11, -4, 7, 18, 24, 30, + 36, 38, 35, 31, 24, 13, -7, -25, -40, -50, -53, -51, -47, -41, -38, -33, + -25, -10, 4, 14, 19, 21, 22, 19, 19, 17, 7, -5, -15, -23, -31, -39, + -46, -49, -49, -46, -41, -33, -19, 0, 21, 39, 53, 61, 64, 63, 56, 50, + 42, 31, 15, -2, -13, -19, -19, -11, 0, 10, 15, 19, 27, 33, 37, 35, + 25, 9, -13, -28, -38, -44, -46, -50, -53, -51, -46, -38, -23, -7, 10, 20, + 21, 24, 25, 28, 28, 19, 8, -7, -18, -28, -36, -43, -52, -56, -57, -51, + -44, -31, -13, 7, 29, 46, 60, 66, 71, 68, 61, 54, 45, 32, 13, -5, + -17, -22, -20, -15, -8, -2, 8, 14, 24, 31, 35, 32, 21, 4, -13, -24, + -34, -42, -49, -55, -58, -54, -48, -38, -23, -4, 14, 26, 32, 31, 32, 36, + 34, 23, 7, -12, -25, -35, -47, -61, -68, -68, -61, -53, -42, -26, -7, 22, + 45, 61, 71, 75, 78, 74, 66, 56, 42, 24, 7, -13, -24, -29, -25, -18, + -11, -7, 2, 14, 27, 36, 38, 32, 19, 1, -14, -22, -33, -44, -56, -64, + -65, -60, -47, -32, -16, 3, 18, 31, 37, 37, 38, 41, 35, 20, 0, -18, + -31, -43, -56, -64, -69, -68, -60, -50, -36, -15, 6, 31, 50, 62, 71, 77, + 78, 74, 66, 54, 38, 20, 2, -15, -23, -26, -24, -22, -17, -7, 8, 20, + 29, 35, 33, 25, 13, -2, -14, -29, -42, -57, -67, -72, -67, -57, -42, -24, + -5, 13, 31, 43, 46, 47, 48, 43, 32, 14, -5, -22, -40, -55, -63, -68, + -69, -66, -57, -44, -25, -5, 18, 37, 55, 66, 75, 78, 75, 70, 62, 47, + 28, 9, -7, -19, -27, -30, -27, -21, -11, 5, 18, 28, 34, 36, 32, 24, + 12, -4, -20, -38, -55, -68, -75, -71, -65, -53, -35, -14, 6, 24, 39, 47, + 50, 48, 44, 36, 22, 5, -16, -34, -47, -56, -60, -60, -59, -54, -45, -28, + -9, 9, 25, 41, 53, 63, 67, 66, 65, 62, 54, 40, 22, 6, -8, -16, + -22, -23, -20, -11, 1, 13, 22, 27, 29, 26, 24, 15, 2, -15, -33, -49, + -64, -74, -74, -67, -55, -39, -20, -2, 16, 32, 45, 50, 49, 43, 35, 26, + 11, -9, -25, -35, -44, -49, -52, -54, -50, -39, -26, -12, 1, 14, 27, 39, + 48, 53, 55, 57, 56, 48, 36, 25, 15, 6, -5, -12, -17, -14, -8, 3, + 14, 21, 26, 23, 21, 21, 14, 3, -11, -26, -44, -61, -72, -72, -68, -56, + -42, -25, -11, 7, 24, 37, 44, 44, 40, 33, 25, 13, 0, -12, -24, -32, + -39, -41, -39, -36, -30, -24, -18, -10, 1, 11, 21, 29, 36, 41, 47, 51, + 51, 42, 35, 27, 19, 10, 1, -6, -10, -9, -2, 6, 11, 13, 13, 15, + 14, 10, 4, -9, -19, -31, -45, -58, -67, -68, -56, -43, -31, -20, -9, 7, + 21, 31, 35, 35, 33, 27, 18, 7, -3, -9, -13, -20, -27, -32, -33, -29, + -23, -19, -16, -12, -4, 6, 15, 23, 30, 39, 47, 49, 42, 35, 31, 27, + 22, 14, 2, -8, -9, -4, 5, 8, 8, 9, 7, 6, 3, 0, -5, -12, + -22, -35, -50, -58, -58, -50, -39, -32, -26, -19, -8, 7, 21, 26, 27, 25, + 22, 18, 11, 5, 2, 1, -3, -10, -19, -24, -23, -16, -15, -17, -20, -17, + -10, -2, 6, 12, 21, 32, 44, 45, 38, 30, 27, 31, 31, 21, 8, 1, + 0, 2, 8, 10, 7, 1, -3, -2, -4, -9, -12, -17, -25, -37, -47, -53, + -50, -42, -32, -27, -26, -22, -11, 5, 15, 18, 20, 22, 23, 22, 18, 15, + 14, 11, 7, -3, -14, -18, -17, -18, -22, -27, -27, -21, -14, -6, 3, 12, + 24, 34, 40, 39, 35, 32, 31, 34, 30, 19, 10, 4, 2, 5, 7, 7, + 1, -6, -10, -9, -8, -8, -11, -16, -25, -34, -41, -41, -36, -32, -33, -33, + -29, -22, -11, -2, 6, 13, 17, 22, 23, 22, 22, 24, 23, 20, 12, 0, + -7, -11, -14, -20, -26, -28, -26, -22, -15, -9, 2, 13, 25, 32, 33, 35, + 36, 37, 38, 35, 29, 19, 9, 5, 7, 6, 4, -3, -9, -12, -11, -6, + -4, -5, -10, -17, -26, -33, -37, -38, -38, -38, -41, -39, -31, -20, -9, -2, + 6, 15, 23, 31, 31, 31, 30, 29, 28, 21, 13, 2, -9, -17, -20, -23, + -26, -27, -26, -20, -14, -6, 6, 14, 22, 26, 32, 34, 35, 37, 37, 36, + 27, 15, 6, 6, 7, 5, -3, -13, -17, -17, -11, -5, -5, -6, -11, -18, + -24, -27, -30, -35, -40, -44, -44, -39, -28, -16, -6, 1, 9, 20, 31, 34, + 36, 37, 36, 33, 23, 14, 5, -3, -10, -17, -23, -30, -34, -31, -22, -14, + -8, 0, 7, 15, 20, 26, 30, 35, 40, 40, 34, 27, 18, 14, 9, 8, + 5, -2, -11, -15, -13, -8, -4, 0, 1, -6, -12, -18, -23, -29, -38, -45, + -52, -53, -47, -37, -28, -16, -5, 6, 17, 28, 37, 42, 43, 40, 37, 31, + 19, 8, 1, -7, -14, -22, -27, -33, -34, -28, -18, -8, 0, 5, 10, 14, + 19, 25, 33, 38, 39, 35, 27, 18, 13, 9, 8, 4, -3, -8, -12, -13, + -10, -4, 4, 4, -2, -7, -14, -21, -28, -36, -45, -53, -54, -50, -44, -34, + -20, -5, 7, 18, 28, 37, 39, 42, 40, 35, 28, 17, 7, 0, -7, -12, + -18, -23, -28, -28, -23, -17, -8, 2, 8, 9, 10, 12, 17, 25, 32, 33, + 28, 20, 13, 10, 10, 8, 6, 5, 1, -5, -6, -3, 3, 10, 10, 5, + -6, -15, -21, -28, -38, -49, -59, -62, -59, -51, -39, -25, -8, 7, 17, 28, + 37, 42, 44, 43, 38, 30, 17, 7, 0, -4, -10, -16, -24, -26, -27, -21, + -14, -9, -2, 5, 11, 14, 12, 13, 19, 26, 29, 26, 19, 13, 8, 8, + 9, 5, 2, 2, 4, 3, 1, 1, 5, 8, 7, 0, -10, -18, -25, -32, + -42, -52, -56, -53, -48, -38, -29, -14, 1, 14, 23, 30, 33, 33, 35, 33, + 26, 17, 9, 2, 1, 0, -5, -12, -19, -22, -21, -13, -8, -4, 5, 10, + 12, 10, 10, 14, 21, 25, 24, 15, 5, 3, 5, 7, 5, 2, 5, 10, + 12, 10, 9, 11, 13, 10, 2, -8, -18, -25, -32, -40, -50, -55, -53, -45, + -35, -27, -17, -4, 11, 20, 28, 30, 28, 29, 30, 28, 19, 10, 6, 6, + 5, 0, -10, -18, -20, -18, -14, -11, -10, -4, 6, 13, 13, 11, 13, 20, + 25, 24, 15, 7, 3, 4, 5, 4, 0, 3, 9, 14, 15, 11, 9, 8, + 8, 6, -5, -16, -24, -29, -35, -43, -48, -47, -42, -31, -23, -17, -7, 5, + 17, 24, 26, 22, 19, 19, 20, 17, 11, 5, 2, 2, 0, -4, -10, -14, + -14, -10, -8, -6, 1, 10, 19, 23, 22, 17, 16, 19, 18, 11, 1, -8, + -11, -10, -7, -4, 1, 7, 15, 22, 22, 18, 17, 16, 12, 4, -8, -21, + -29, -34, -39, -46, -49, -46, -37, -28, -19, -9, -2, 8, 19, 22, 20, 18, + 18, 19, 19, 12, 6, 3, 2, 0, -5, -10, -16, -18, -14, -9, -8, -3, + 6, 17, 25, 27, 26, 24, 25, 22, 15, 3, -8, -13, -13, -12, -11, -6, + 0, 9, 16, 19, 19, 16, 13, 10, 6, -5, -14, -22, -26, -32, -37, -41, + -39, -32, -23, -17, -14, -10, -3, 9, 17, 18, 10, 7, 10, 16, 18, 12, + 5, 1, 1, -4, -13, -18, -18, -15, -12, -11, -10, 1, 15, 29, 37, 35, + 31, 30, 30, 24, 11, -8, -18, -18, -15, -17, -20, -17, -6, 8, 15, 18, + 16, 15, 11, 12, 8, 0, -10, -16, -20, -28, -35, -38, -33, -27, -23, -21, + -19, -13, 0, 11, 14, 12, 9, 11, 18, 21, 19, 10, 2, -3, -5, -12, + -21, -28, -26, -20, -15, -12, -6, 9, 25, 38, 43, 42, 40, 38, 34, 23, + 6, -12, -18, -18, -18, -23, -25, -22, -13, 0, 7, 9, 8, 8, 11, 12, + 9, 6, 2, -5, -14, -21, -24, -24, -22, -22, -21, -22, -20, -12, -3, 4, + 5, 5, 6, 11, 15, 16, 10, 4, -2, -7, -11, -20, -25, -27, -21, -13, + -11, -5, 6, 22, 37, 46, 50, 49, 44, 39, 31, 16, -3, -15, -21, -24, + -27, -32, -33, -28, -17, -5, 5, 7, 7, 10, 15, 16, 15, 10, 4, -4, + -11, -18, -22, -22, -20, -22, -21, -21, -17, -10, 1, 6, 9, 10, 15, 19, + 18, 12, 5, 0, -9, -15, -23, -31, -36, -32, -24, -17, -11, -4, 12, 31, + 47, 53, 58, 60, 56, 49, 35, 15, -4, -16, -21, -25, -32, -42, -45, -35, + -23, -14, -8, 0, 6, 13, 20, 21, 19, 15, 9, 1, -6, -11, -13, -16, + -18, -20, -23, -20, -14, -8, 0, 2, 5, 11, 18, 18, 14, 6, -2, -10, + -18, -27, -34, -41, -40, -31, -20, -12, -7, 4, 23, 47, 64, 71, 71, 63, + 56, 46, 30, 12, -7, -22, -35, -42, -49, -52, -48, -34, -22, -14, -7, 3, + 15, 24, 27, 27, 24, 15, 6, -4, -8, -11, -13, -13, -15, -16, -14, -12, + -7, -2, 3, 10, 12, 14, 15, 7, 0, -7, -16, -25, -32, -40, -44, -44, + -36, -24, -11, 0, 6, 16, 36, 58, 72, 76, 71, 62, 51, 38, 24, 5, + -13, -30, -42, -50, -52, -53, -46, -33, -21, -15, -6, 7, 20, 25, 25, 21, + 18, 14, 7, 2, -5, -9, -9, -7, -8, -9, -10, -7, -3, 1, 6, 7, + 8, 9, 6, -2, -13, -23, -30, -35, -41, -45, -44, -38, -26, -15, -3, 11, + 19, 33, 52, 69, 75, 72, 65, 54, 42, 29, 13, -6, -25, -41, -49, -54, + -55, -48, -38, -26, -18, -8, 1, 13, 24, 29, 26, 19, 11, 5, 2, -2, + -6, -6, -6, -5, -7, -5, 1, 5, 9, 11, 8, 8, 7, 4, -6, -17, + -28, -35, -42, -47, -48, -45, -39, -29, -16, -5, 7, 18, 32, 45, 57, 64, + 67, 62, 54, 45, 35, 22, 5, -13, -28, -40, -47, -49, -46, -42, -32, -21, + -11, -4, 6, 15, 21, 21, 16, 12, 6, 1, -3, -5, -3, 3, 8, 9, + 8, 7, 7, 11, 12, 11, 6, -2, -9, -13, -20, -29, -40, -47, -47, -45, + -42, -37, -29, -16, -5, 7, 17, 27, 38, 48, 56, 59, 53, 44, 40, 37, + 30, 17, -2, -16, -25, -32, -35, -36, -35, -31, -23, -16, -10, -3, 4, 10, + 11, 8, 1, 0, 0, 0, 0, 1, 6, 14, 20, 21, 19, 15, 14, 13, + 11, 7, 0, -13, -21, -28, -37, -46, -51, -48, -43, -37, -32, -28, -21, -9, + 4, 17, 27, 32, 40, 45, 50, 51, 46, 40, 38, 35, 27, 12, -3, -13, + -23, -27, -29, -30, -29, -28, -23, -15, -10, -5, 2, 5, 5, 1, -2, -2, + 1, 4, 4, 8, 14, 19, 25, 26, 21, 15, 13, 12, 12, 5, -9, -21, + -30, -37, -43, -50, -51, -47, -42, -38, -34, -27, -17, -5, 10, 22, 30, 38, + 44, 49, 50, 46, 40, 37, 38, 33, 19, 4, -8, -14, -18, -22, -24, -24, + -22, -18, -16, -14, -10, -6, 1, 1, -6, -8, -9, -6, 0, 2, 8, 14, + 21, 28, 31, 27, 24, 21, 20, 16, 9, -3, -16, -26, -33, -42, -50, -55, + -56, -50, -43, -39, -38, -29, -13, 6, 18, 27, 33, 42, 51, 54, 53, 48, + 41, 39, 38, 29, 12, -5, -15, -19, -20, -23, -24, -22, -18, -17, -13, -12, + -10, -4, -3, -4, -7, -8, -9, -9, -7, 2, 9, 14, 21, 26, 27, 27, + 22, 20, 19, 17, 12, 1, -14, -25, -35, -41, -45, -50, -53, -54, -51, -47, + -41, -31, -18, -3, 12, 24, 35, 47, 55, 58, 57, 55, 49, 46, 40, 26, + 11, -5, -17, -22, -23, -23, -22, -21, -21, -18, -15, -9, -5, -3, -4, -6, + -7, -9, -12, -12, -8, 1, 7, 13, 14, 19, 23, 27, 26, 25, 25, 20, + 13, 4, -9, -22, -36, -42, -48, -55, -61, -62, -59, -54, -43, -32, -18, 0, + 18, 35, 49, 57, 60, 62, 63, 61, 57, 48, 33, 15, -2, -15, -24, -28, + -27, -22, -23, -24, -21, -13, -4, 3, 3, 1, -2, -4, -4, -9, -15, -16, + -13, -9, -5, 2, 7, 11, 19, 24, 28, 31, 29, 28, 24, 12, -4, -21, + -33, -38, -48, -61, -72, -76, -71, -61, -47, -34, -20, 2, 26, 45, 58, 65, + 69, 74, 75, 68, 55, 41, 28, 13, -7, -22, -32, -32, -29, -24, -23, -22, + -19, -7, 6, 7, 2, -2, -3, 0, -3, -10, -20, -24, -19, -12, -5, 1, + 5, 14, 23, 30, 33, 37, 39, 36, 24, 8, -10, -25, -33, -43, -55, -71, + -82, -82, -71, -57, -44, -29, -11, 13, 34, 52, 64, 70, 73, 77, 76, 65, + 50, 35, 20, 4, -13, -26, -31, -32, -27, -26, -25, -21, -10, 2, 8, 5, + 3, 0, 1, 2, -3, -12, -22, -24, -21, -16, -9, -3, 6, 14, 22, 28, + 34, 41, 42, 35, 23, 6, -10, -21, -32, -45, -61, -76, -85, -82, -70, -54, + -43, -29, -7, 18, 40, 55, 64, 71, 77, 81, 76, 62, 48, 32, 19, 6, + -10, -23, -30, -29, -28, -30, -27, -20, -10, -2, 3, 1, 0, 3, 6, 4, + -9, -18, -24, -22, -18, -14, -8, 0, 8, 16, 24, 32, 38, 42, 42, 31, + 15, -2, -14, -25, -38, -52, -67, -81, -85, -76, -63, -49, -37, -19, 3, 26, + 43, 57, 67, 75, 82, 79, 70, 56, 41, 28, 15, 1, -12, -22, -27, -27, + -28, -26, -21, -12, -3, 3, -2, -2, 1, 3, 1, -12, -22, -28, -29, -27, + -23, -18, -11, 3, 16, 25, 34, 44, 51, 52, 43, 27, 12, -2, -17, -34, + -51, -71, -82, -86, -83, -75, -61, -45, -27, -7, 16, 37, 53, 63, 72, 78, + 77, 68, 60, 45, 33, 20, 10, -2, -9, -15, -18, -22, -23, -19, -15, -8, + -5, -7, -8, -7, -4, -3, -10, -22, -29, -29, -24, -21, -18, -14, -3, 12, + 23, 27, 35, 44, 49, 47, 34, 18, 1, -11, -23, -40, -57, -73, -81, -80, + -74, -64, -50, -36, -19, 2, 22, 38, 49, 61, 69, 74, 69, 60, 50, 40, + 29, 20, 10, 2, -5, -9, -12, -16, -18, -14, -9, -6, -10, -13, -12, -10, + -11, -15, -23, -30, -31, -27, -25, -23, -19, -8, 8, 20, 28, 36, 45, 49, + 49, 41, 29, 15, -2, -15, -31, -49, -65, -76, -79, -77, -67, -55, -43, -30, + -13, 7, 25, 40, 51, 60, 66, 66, 62, 54, 45, 37, 29, 22, 14, 7, + 3, -3, -7, -10, -12, -10, -8, -12, -18, -19, -16, -13, -15, -23, -31, -33, + -29, -26, -25, -23, -15, 1, 14, 23, 31, 40, 50, 52, 46, 36, 21, 7, + -8, -24, -41, -58, -70, -75, -74, -67, -57, -43, -30, -18, -3, 13, 26, 39, + 48, 56, 60, 58, 51, 45, 42, 36, 29, 25, 20, 14, 9, 6, 3, 0, + -5, -6, -12, -17, -22, -21, -20, -24, -33, -37, -38, -35, -30, -28, -24, -17, + -3, 12, 24, 33, 43, 50, 52, 49, 40, 28, 13, -3, -18, -34, -51, -63, + -71, -72, -67, -59, -49, -37, -24, -10, 3, 16, 27, 37, 46, 50, 53, 51, + 49, 46, 43, 37, 32, 29, 25, 21, 17, 10, 4, -3, -8, -10, -11, -18, + -25, -29, -31, -34, -37, -40, -40, -37, -31, -25, -20, -13, 0, 17, 31, 41, + 48, 50, 49, 46, 36, 22, 8, -5, -20, -36, -49, -61, -67, -67, -61, -51, + -44, -36, -23, -9, 4, 13, 20, 30, 38, 46, 48, 47, 44, 44, 44, 46, + 42, 35, 31, 28, 24, 15, 5, -3, -6, -10, -18, -28, -35, -39, -41, -41, + -43, -45, -42, -36, -29, -23, -15, 1, 15, 28, 40, 47, 51, 51, 46, 37, + 27, 14, 2, -14, -29, -42, -49, -54, -62, -63, -57, -49, -41, -31, -21, -12, + -3, 6, 17, 25, 32, 40, 45, 49, 50, 48, 49, 49, 48, 44, 39, 34, + 26, 13, 4, -4, -11, -17, -23, -32, -41, -48, -48, -49, -48, -44, -39, -36, + -31, -21, -5, 13, 24, 35, 44, 51, 52, 47, 39, 30, 21, 8, -6, -18, + -34, -44, -50, -54, -59, -58, -53, -46, -38, -28, -18, -10, -4, 6, 16, 24, + 30, 37, 42, 48, 49, 47, 48, 51, 51, 49, 45, 35, 27, 17, 9, 0, + -12, -23, -32, -41, -48, -53, -55, -54, -53, -49, -43, -38, -27, -13, 5, 20, + 33, 44, 52, 58, 57, 50, 40, 29, 16, 5, -11, -29, -43, -53, -56, -62, + -65, -63, -54, -42, -33, -24, -16, -8, 3, 16, 23, 29, 33, 38, 44, 46, + 45, 43, 45, 49, 52, 48, 42, 37, 28, 19, 10, 0, -13, -25, -36, -42, + -47, -56, -58, -56, -53, -49, -48, -40, -26, -6, 13, 27, 39, 49, 59, 64, + 62, 53, 42, 29, 16, 2, -18, -37, -52, -60, -65, -71, -75, -68, -55, -41, + -30, -19, -10, 0, 14, 24, 33, 37, 38, 39, 42, 45, 45, 43, 45, 48, + 47, 46, 41, 35, 28, 19, 8, -6, -20, -30, -38, -44, -50, -55, -57, -59, + -57, -53, -46, -35, -19, 0, 17, 32, 45, 59, 66, 66, 59, 54, 46, 32, + 15, -5, -24, -43, -57, -65, -71, -76, -78, -71, -58, -41, -27, -16, -5, 5, + 15, 27, 37, 43, 43, 42, 42, 42, 43, 46, 46, 46, 45, 42, 41, 35, + 28, 18, 7, -6, -18, -29, -37, -44, -51, -56, -59, -61, -60, -55, -45, -33, + -18, -2, 18, 37, 50, 61, 67, 68, 65, 59, 47, 31, 10, -11, -32, -47, + -58, -71, -81, -86, -83, -70, -52, -36, -21, -9, 2, 13, 25, 35, 41, 44, + 43, 40, 39, 39, 40, 43, 43, 40, 39, 40, 40, 36, 28, 18, 9, -5, + -18, -28, -36, -44, -52, -57, -61, -64, -63, -56, -43, -27, -13, 6, 26, 44, + 56, 66, 71, 71, 64, 55, 42, 23, 3, -19, -38, -52, -66, -76, -82, -86, + -81, -67, -49, -32, -19, -8, 3, 15, 28, 36, 42, 43, 43, 41, 41, 40, + 40, 41, 40, 40, 41, 41, 36, 30, 24, 17, 10, -5, -19, -29, -37, -43, + -50, -57, -64, -66, -60, -50, -40, -28, -10, 12, 32, 45, 54, 59, 64, 67, + 63, 54, 35, 14, -6, -22, -35, -50, -64, -75, -82, -81, -73, -59, -46, -33, + -21, -8, 5, 19, 27, 33, 40, 44, 44, 42, 40, 42, 41, 40, 38, 39, + 38, 38, 35, 30, 21, 13, 4, -8, -16, -25, -35, -45, -53, -62, -65, -63, + -56, -47, -39, -25, -6, 15, 32, 45, 53, 58, 64, 65, 60, 48, 30, 9, + -7, -19, -31, -47, -60, -72, -79, -79, -73, -61, -50, -37, -24, -10, 3, 12, + 22, 33, 43, 47, 46, 44, 43, 45, 46, 45, 45, 43, 41, 38, 34, 26, + 16, 7, -2, -10, -19, -29, -39, -50, -59, -64, -62, -58, -51, -44, -34, -22, + -2, 16, 30, 41, 52, 56, 57, 58, 54, 42, 29, 13, 2, -12, -27, -42, + -56, -67, -71, -73, -70, -63, -55, -42, -26, -10, 2, 11, 20, 33, 41, 46, + 45, 43, 49, 53, 52, 48, 44, 43, 42, 38, 33, 22, 12, 4, -5, -13, + -23, -34, -43, -50, -57, -61, -60, -55, -49, -40, -29, -14, -2, 12, 25, 35, + 44, 51, 56, 56, 49, 39, 30, 20, 10, -2, -17, -32, -48, -60, -67, -74, + -77, -74, -66, -50, -36, -21, -9, 0, 14, 30, 43, 51, 53, 57, 62, 64, + 62, 58, 53, 48, 42, 36, 25, 12, 4, -4, -12, -21, -31, -38, -43, -45, + -47, -49, -47, -44, -40, -34, -28, -22, -11, 1, 11, 21, 28, 39, 49, 53, + 52, 49, 44, 38, 29, 16, -4, -24, -41, -57, -74, -86, -90, -86, -73, -59, + -44, -30, -16, 1, 21, 40, 54, 61, 66, 67, 71, 72, 65, 57, 49, 41, + 33, 24, 12, 1, -8, -12, -15, -22, -31, -37, -35, -31, -33, -36, -39, -40, + -38, -34, -32, -29, -24, -14, -2, 11, 24, 36, 48, 56, 61, 63, 59, 54, + 44, 27, 6, -19, -46, -68, -84, -94, -99, -98, -90, -72, -51, -30, -15, 1, + 22, 46, 64, 76, 78, 80, 81, 78, 72, 60, 45, 34, 24, 13, 0, -13, + -18, -18, -18, -22, -28, -29, -24, -19, -19, -26, -33, -38, -40, -40, -41, -42, + -41, -32, -15, 6, 22, 37, 50, 62, 74, 79, 76, 65, 50, 30, 6, -24, + -54, -78, -94, -106, -110, -103, -89, -69, -49, -29, -10, 11, 36, 57, 73, 78, + 80, 82, 83, 77, 66, 51, 37, 24, 14, 5, -5, -12, -17, -17, -17, -18, + -19, -17, -13, -13, -19, -28, -37, -44, -44, -48, -53, -59, -54, -35, -12, 11, + 29, 46, 61, 78, 88, 90, 84, 68, 49, 24, -6, -39, -71, -92, -104, -115, + -116, -108, -89, -66, -43, -21, 1, 24, 49, 68, 78, 82, 81, 81, 79, 71, + 56, 37, 24, 15, 6, -4, -9, -11, -9, -6, -6, -10, -11, -6, -4, -8, + -20, -33, -44, -55, -61, -65, -70, -68, -55, -31, -6, 15, 38, 61, 82, 97, + 101, 94, 80, 61, 37, 9, -25, -60, -88, -107, -119, -123, -116, -99, -77, -53, + -30, -5, 20, 47, 68, 80, 82, 82, 80, 77, 70, 57, 40, 23, 10, 3, + -2, -3, -4, -3, 2, 5, 7, 5, 5, 4, -4, -17, -32, -45, -60, -69, + -74, -79, -80, -70, -47, -20, 9, 32, 55, 76, 94, 104, 103, 91, 71, 46, + 16, -16, -48, -75, -97, -115, -121, -117, -101, -80, -57, -32, -8, 15, 39, 58, + 68, 73, 73, 73, 69, 61, 50, 39, 26, 15, 7, 4, 7, 12, 18, 19, + 20, 18, 17, 15, 10, -4, -20, -41, -57, -68, -77, -85, -91, -90, -76, -53, + -25, 2, 28, 55, 79, 97, 106, 104, 94, 77, 52, 22, -9, -39, -67, -92, + -111, -119, -115, -99, -79, -55, -33, -11, 15, 37, 55, 67, 71, 68, 61, 51, + 44, 40, 35, 24, 10, 3, 4, 13, 25, 36, 42, 41, 34, 29, 20, 12, + -2, -21, -43, -66, -84, -94, -96, -96, -93, -81, -55, -26, 4, 30, 56, 80, + 98, 107, 106, 95, 77, 53, 24, -8, -38, -64, -85, -101, -109, -109, -100, -80, + -55, -31, -8, 13, 31, 46, 56, 61, 59, 52, 43, 36, 30, 25, 16, 8, + 7, 11, 23, 37, 48, 56, 59, 56, 48, 33, 17, -5, -29, -54, -79, -96, + -106, -109, -105, -96, -82, -57, -25, 8, 38, 61, 79, 94, 103, 102, 92, 73, + 46, 19, -10, -36, -62, -81, -95, -101, -100, -90, -71, -47, -25, -3, 18, 31, + 41, 49, 53, 50, 42, 32, 21, 13, 9, 7, 8, 8, 12, 30, 49, 63, + 71, 76, 75, 67, 48, 25, -3, -30, -59, -87, -107, -120, -124, -117, -105, -89, + -63, -31, 5, 40, 63, 81, 92, 100, 100, 88, 69, 46, 20, -6, -31, -55, + -73, -87, -91, -88, -80, -64, -45, -22, 1, 16, 27, 34, 39, 45, 41, 31, + 20, 9, 4, 3, 1, 3, 6, 15, 32, 53, 71, 81, 85, 86, 78, 61, + 35, 3, -29, -63, -93, -113, -124, -128, -124, -110, -89, -64, -32, 5, 38, 62, + 80, 91, 98, 93, 80, 63, 42, 19, -5, -29, -51, -68, -78, -81, -79, -72, + -58, -40, -19, 0, 13, 21, 29, 35, 35, 29, 21, 14, 8, 2, -2, -3, + 1, 10, 20, 36, 56, 73, 84, 89, 89, 81, 65, 41, 6, -32, -63, -90, + -110, -124, -127, -123, -110, -89, -61, -30, 2, 33, 56, 71, 81, 86, 85, 74, + 58, 38, 17, -5, -21, -38, -52, -62, -69, -69, -64, -50, -34, -18, -5, 5, + 13, 23, 28, 27, 22, 15, 10, 6, 1, 0, -2, 2, 9, 23, 41, 56, + 72, 84, 88, 89, 81, 66, 45, 15, -20, -55, -84, -106, -119, -121, -116, -105, + -89, -67, -38, -7, 21, 44, 58, 69, 75, 74, 64, 50, 36, 22, 8, -10, + -26, -39, -47, -54, -56, -53, -47, -36, -25, -11, -2, 5, 14, 23, 24, 20, + 12, 7, 6, 6, 6, 4, 5, 10, 22, 39, 57, 72, 80, 82, 80, 73, + 62, 45, 18, -13, -48, -78, -96, -105, -105, -104, -97, -81, -64, -40, -15, 10, + 28, 40, 49, 54, 53, 49, 42, 31, 22, 13, 2, -9, -17, -22, -30, -38, + -40, -37, -33, -28, -22, -16, -10, -5, 5, 11, 11, 6, 3, 5, 11, 16, + 16, 18, 22, 29, 40, 54, 68, 75, 74, 72, 63, 49, 35, 15, -10, -37, + -63, -83, -94, -95, -89, -82, -73, -63, -46, -24, -2, 16, 25, 31, 35, 39, + 41, 37, 30, 22, 15, 11, 4, -3, -11, -18, -25, -31, -35, -33, -28, -22, + -18, -16, -13, -4, 5, 10, 11, 10, 5, 6, 14, 21, 23, 24, 27, 33, + 45, 59, 68, 72, 67, 57, 46, 34, 19, 0, -24, -49, -70, -81, -82, -77, + -70, -65, -60, -49, -34, -15, 2, 9, 13, 14, 18, 20, 21, 19, 18, 17, + 16, 15, 13, 10, 5, -3, -12, -20, -26, -28, -27, -24, -26, -25, -18, -9, + 3, 9, 10, 10, 11, 18, 27, 32, 33, 33, 35, 42, 51, 58, 59, 55, + 46, 36, 25, 16, 3, -15, -33, -50, -61, -65, -64, -59, -57, -56, -52, -42, + -29, -14, -5, -2, -3, 1, 8, 12, 13, 13, 16, 16, 18, 19, 19, 14, + 4, -3, -10, -19, -24, -24, -22, -20, -24, -23, -16, -2, 10, 16, 14, 13, + 16, 28, 35, 36, 35, 32, 33, 40, 45, 49, 47, 41, 31, 20, 12, 4, + -8, -16, -29, -41, -50, -53, -50, -49, -51, -51, -48, -40, -30, -20, -13, -13, + -12, -6, 2, 8, 12, 13, 16, 21, 26, 27, 23, 15, 8, 0, -10, -19, + -23, -24, -24, -26, -25, -21, -9, 5, 15, 19, 20, 22, 28, 36, 39, 38, + 36, 33, 33, 35, 37, 38, 36, 30, 20, 9, 4, -3, -10, -17, -26, -35, + -40, -45, -47, -51, -52, -49, -46, -39, -30, -23, -19, -17, -12, -5, 1, 4, + 7, 11, 18, 22, 22, 22, 20, 17, 12, 3, -8, -16, -18, -16, -17, -19, + -18, -12, 3, 13, 19, 20, 24, 29, 34, 35, 33, 32, 31, 31, 30, 26, + 24, 24, 25, 21, 14, 6, 0, -4, -5, -10, -19, -31, -37, -40, -47, -51, + -50, -49, -45, -39, -31, -25, -19, -12, -6, -3, 0, 2, 6, 13, 17, 18, + 16, 15, 16, 14, 7, -3, -10, -12, -13, -13, -14, -13, -6, 6, 18, 24, + 25, 26, 29, 33, 32, 26, 24, 23, 23, 22, 18, 14, 15, 21, 24, 22, + 14, 6, 4, 4, 1, -9, -21, -32, -41, -47, -50, -54, -54, -51, -47, -37, + -30, -21, -10, -3, 1, 4, 6, 7, 8, 7, 7, 7, 7, 6, 6, 5, + 2, -3, -8, -8, -6, -3, 1, 3, 9, 17, 25, 29, 32, 33, 29, 26, + 24, 23, 20, 17, 14, 11, 8, 8, 14, 21, 22, 17, 13, 9, 9, 7, + 1, -11, -25, -37, -44, -52, -53, -55, -55, -51, -43, -35, -24, -14, -4, 3, + 4, 4, 6, 7, 6, 3, -2, -2, 2, 6, 5, 1, -4, -8, -7, -5, + 3, 9, 9, 12, 17, 25, 32, 37, 37, 32, 25, 21, 19, 17, 15, 9, + 6, 6, 6, 8, 14, 23, 24, 20, 15, 14, 11, 3, -6, -18, -31, -44, + -53, -54, -57, -58, -55, -47, -37, -26, -16, -4, 7, 10, 10, 9, 7, 3, + -2, -6, -8, -6, -5, -4, -7, -10, -8, -6, 0, 6, 12, 16, 20, 27, + 33, 35, 35, 36, 34, 28, 21, 16, 10, 7, 7, 5, 3, 1, 5, 12, + 21, 25, 23, 17, 14, 13, 9, -3, -17, -30, -41, -50, -54, -59, -61, -55, + -46, -37, -26, -15, -4, 7, 14, 15, 12, 6, 1, -3, -7, -12, -14, -15, + -13, -12, -12, -12, -8, 0, 8, 15, 20, 25, 31, 36, 40, 41, 41, 38, + 33, 27, 21, 12, 4, 1, 0, -4, -5, -2, 5, 12, 17, 19, 19, 18, + 14, 11, 2, -9, -21, -32, -42, -49, -55, -57, -56, -49, -39, -30, -20, -8, + 3, 12, 17, 18, 12, 5, -2, -8, -14, -18, -21, -22, -21, -21, -19, -13, + -7, 4, 14, 24, 32, 39, 44, 48, 47, 44, 41, 38, 33, 27, 17, 7, + -3, -5, -5, -5, -5, -5, 3, 12, 17, 19, 16, 11, 7, 3, -6, -15, + -26, -36, -42, -48, -53, -54, -50, -40, -31, -22, -12, -2, 11, 19, 20, 13, + 6, 2, -5, -12, -21, -26, -29, -31, -30, -27, -21, -13, -2, 12, 25, 36, + 48, 57, 62, 60, 51, 46, 43, 37, 28, 15, 3, -8, -12, -14, -12, -10, + -7, -4, 8, 16, 20, 17, 14, 10, 6, -2, -12, -24, -32, -39, -45, -51, + -54, -52, -43, -32, -21, -12, -2, 11, 22, 28, 24, 13, 4, -6, -14, -23, + -32, -38, -41, -42, -39, -31, -20, -8, 6, 21, 37, 50, 63, 69, 68, 61, + 55, 48, 39, 29, 20, 9, -6, -15, -17, -13, -11, -7, -4, 3, 11, 13, + 16, 15, 10, 5, 0, -8, -15, -25, -31, -37, -42, -49, -52, -46, -37, -30, + -21, -12, 0, 14, 25, 28, 25, 15, 2, -11, -22, -29, -36, -44, -49, -49, + -43, -32, -18, -5, 13, 30, 50, 66, 74, 75, 71, 68, 61, 50, 37, 26, + 15, 3, -13, -22, -22, -20, -16, -14, -9, 1, 9, 11, 11, 9, 9, 9, + 6, -3, -15, -25, -32, -37, -41, -50, -53, -50, -41, -30, -20, -8, 6, 21, + 31, 33, 26, 15, 0, -12, -23, -34, -46, -56, -60, -54, -44, -31, -19, -2, + 21, 44, 66, 77, 81, 79, 75, 72, 63, 51, 35, 23, 10, -4, -16, -25, + -28, -26, -22, -16, -12, -7, -2, 4, 8, 10, 14, 14, 7, -3, -12, -20, + -28, -36, -42, -48, -53, -53, -43, -31, -19, -6, 12, 25, 31, 30, 26, 15, + -2, -17, -28, -40, -52, -60, -61, -53, -40, -25, -9, 11, 32, 56, 74, 84, + 85, 81, 76, 72, 61, 46, 29, 13, -2, -16, -23, -29, -33, -31, -25, -19, + -14, -8, 2, 10, 14, 18, 19, 17, 8, 1, -12, -24, -35, -42, -49, -54, + -57, -53, -43, -30, -13, 7, 22, 32, 34, 32, 26, 11, -8, -24, -40, -50, + -60, -66, -63, -53, -36, -17, 2, 23, 45, 67, 84, 90, 91, 85, 78, 72, + 62, 44, 24, 4, -9, -21, -32, -39, -41, -36, -30, -23, -17, -9, 2, 13, + 23, 27, 26, 19, 12, 2, -12, -26, -38, -47, -54, -59, -59, -53, -41, -23, + -5, 14, 28, 36, 36, 31, 21, 6, -13, -31, -46, -58, -66, -70, -65, -50, + -28, -7, 14, 35, 58, 76, 89, 96, 94, 90, 82, 72, 54, 35, 16, -5, + -21, -31, -40, -48, -47, -38, -28, -20, -13, 1, 15, 28, 33, 33, 27, 18, + 8, -6, -21, -37, -52, -64, -66, -65, -58, -47, -30, -9, 13, 28, 38, 43, + 40, 31, 15, -5, -24, -40, -57, -69, -75, -74, -65, -48, -26, -2, 24, 47, + 66, 83, 97, 102, 102, 101, 91, 73, 51, 28, 7, -15, -33, -45, -56, -60, + -54, -42, -28, -17, -4, 13, 26, 36, 38, 36, 29, 16, 2, -14, -34, -52, + -62, -66, -65, -63, -53, -36, -15, 9, 27, 36, 41, 40, 35, 25, 8, -16, + -37, -55, -68, -77, -81, -75, -60, -37, -12, 12, 35, 57, 75, 94, 105, 107, + 103, 97, 84, 64, 41, 18, -6, -25, -40, -51, -57, -56, -46, -32, -19, -6, + 7, 20, 30, 34, 32, 24, 12, 0, -17, -33, -47, -60, -65, -64, -58, -46, + -31, -12, 8, 26, 37, 43, 44, 41, 28, 11, -12, -31, -49, -67, -81, -87, + -85, -72, -52, -30, -6, 21, 45, 69, 87, 101, 110, 113, 110, 100, 77, 51, + 27, 8, -11, -32, -49, -59, -59, -53, -41, -27, -11, 3, 14, 24, 28, 28, + 24, 17, 5, -15, -32, -45, -54, -61, -58, -54, -44, -32, -13, 8, 26, 37, + 41, 40, 36, 29, 16, -3, -24, -47, -66, -81, -89, -88, -76, -58, -37, -16, + 10, 34, 58, 78, 94, 106, 111, 107, 97, 81, 58, 37, 17, 0, -17, -33, + -45, -51, -48, -38, -26, -14, -3, 9, 16, 19, 17, 14, 10, 0, -15, -30, + -42, -49, -52, -49, -44, -37, -25, -8, 9, 21, 29, 32, 35, 33, 29, 19, + 1, -18, -38, -58, -75, -85, -85, -79, -70, -52, -29, -6, 20, 44, 67, 89, + 101, 110, 114, 107, 93, 72, 49, 28, 10, -9, -25, -38, -48, -49, -42, -31, + -20, -11, 0, 9, 13, 12, 7, 5, 0, -11, -24, -36, -42, -44, -43, -38, + -28, -16, -4, 8, 16, 22, 29, 30, 29, 24, 13, 2, -14, -32, -51, -68, + -79, -83, -77, -69, -56, -41, -19, 6, 31, 53, 74, 90, 101, 108, 109, 101, + 83, 60, 38, 24, 9, -10, -25, -36, -40, -37, -29, -21, -13, -8, 0, 3, + 0, -5, -6, -8, -16, -27, -35, -39, -40, -33, -27, -21, -11, 3, 14, 21, + 24, 27, 26, 22, 19, 13, 3, -14, -32, -53, -66, -74, -80, -80, -75, -63, + -47, -28, -4, 19, 41, 66, 85, 99, 105, 106, 104, 95, 76, 51, 29, 13, + 2, -12, -27, -36, -38, -32, -22, -15, -12, -8, -3, -4, -9, -12, -14, -18, + -26, -31, -35, -36, -29, -20, -10, -2, 7, 16, 25, 25, 24, 19, 15, 10, + 4, -4, -16, -30, -44, -57, -67, -73, -75, -70, -60, -48, -34, -16, 5, 27, + 51, 71, 85, 92, 99, 101, 95, 82, 64, 44, 28, 14, 1, -12, -22, -28, + -27, -22, -18, -17, -15, -15, -15, -21, -23, -25, -24, -27, -31, -34, -30, -21, + -6, 7, 13, 17, 22, 27, 28, 24, 16, 7, -3, -10, -17, -27, -35, -43, + -50, -58, -68, -70, -65, -53, -42, -32, -22, -4, 15, 36, 54, 70, 83, 89, + 92, 91, 82, 68, 54, 42, 29, 14, 2, -9, -17, -21, -22, -20, -21, -20, + -23, -26, -30, -32, -32, -29, -27, -28, -30, -26, -15, 0, 15, 25, 25, 25, + 26, 27, 21, 11, 0, -9, -17, -24, -30, -38, -45, -47, -49, -55, -59, -56, + -48, -39, -28, -20, -9, 7, 26, 44, 55, 65, 72, 79, 80, 77, 66, 57, + 49, 41, 30, 19, 7, -2, -7, -12, -17, -22, -25, -29, -33, -36, -39, -41, + -36, -29, -26, -26, -22, -11, 2, 17, 28, 32, 31, 29, 28, 23, 11, -2, + -9, -17, -24, -36, -44, -48, -49, -50, -53, -54, -54, -47, -36, -25, -17, -7, + 7, 21, 36, 47, 55, 63, 70, 72, 69, 60, 52, 46, 42, 34, 23, 15, + 8, 3, 0, -7, -14, -21, -24, -27, -32, -39, -44, -43, -37, -29, -25, -23, + -16, -2, 14, 26, 32, 33, 32, 30, 25, 16, 4, -6, -16, -25, -36, -45, + -50, -54, -51, -51, -54, -54, -48, -36, -23, -15, -6, 5, 17, 31, 42, 51, + 59, 62, 63, 61, 56, 51, 43, 40, 38, 28, 20, 13, 9, 7, 2, -8, + -16, -23, -27, -31, -36, -40, -43, -39, -31, -23, -20, -15, -4, 11, 24, 31, + 32, 31, 30, 25, 17, 7, -3, -13, -23, -36, -48, -56, -58, -57, -53, -50, + -52, -51, -40, -25, -12, 0, 7, 16, 25, 36, 49, 58, 60, 59, 57, 54, + 49, 43, 36, 31, 26, 18, 13, 10, 6, 4, 0, -6, -12, -19, -22, -26, + -31, -35, -35, -32, -27, -22, -16, -7, 4, 13, 21, 26, 30, 29, 27, 22, + 15, 4, -7, -19, -31, -44, -55, -59, -59, -58, -54, -52, -49, -41, -28, -14, + 0, 10, 18, 26, 33, 44, 50, 53, 51, 50, 48, 46, 41, 37, 30, 24, + 21, 18, 15, 13, 8, 4, 0, -6, -9, -14, -19, -23, -27, -33, -33, -31, + -25, -19, -11, -3, 3, 11, 20, 28, 31, 28, 22, 14, 8, -3, -15, -29, + -40, -49, -57, -62, -60, -56, -50, -47, -42, -32, -18, -3, 11, 20, 25, 29, + 35, 43, 49, 51, 47, 43, 41, 37, 33, 29, 24, 18, 15, 14, 13, 11, + 8, 5, 1, 0, -5, -11, -19, -23, -24, -25, -25, -26, -22, -15, -9, -3, + 4, 12, 19, 25, 26, 24, 17, 11, 2, -11, -26, -37, -45, -53, -58, -59, + -57, -53, -47, -42, -35, -25, -10, 5, 15, 19, 22, 29, 37, 45, 48, 47, + 44, 44, 43, 40, 33, 24, 19, 14, 13, 12, 8, 2, -2, 1, 1, 1, + -4, -12, -15, -14, -13, -14, -18, -18, -15, -12, -8, -5, 2, 10, 18, 21, + 20, 15, 10, 3, -7, -18, -31, -42, -47, -50, -53, -57, -57, -51, -42, -34, + -25, -15, -5, 7, 16, 22, 30, 35, 40, 43, 42, 39, 39, 38, 38, 31, + 22, 16, 14, 15, 17, 16, 12, 6, 4, 5, 7, 6, 0, -8, -12, -13, + -15, -19, -21, -20, -17, -14, -11, -6, 2, 10, 18, 21, 21, 19, 11, -2, + -17, -29, -37, -42, -46, -52, -55, -58, -52, -42, -34, -24, -15, -5, 5, 12, + 17, 24, 32, 37, 37, 36, 33, 33, 35, 35, 32, 26, 22, 16, 17, 19, + 19, 14, 7, 5, 5, 6, 5, 0, -7, -10, -9, -6, -7, -13, -17, -15, + -11, -8, -7, -6, 1, 7, 12, 13, 11, 7, 0, -12, -25, -35, -40, -42, + -43, -44, -47, -49, -43, -34, -22, -12, -7, 0, 4, 9, 17, 25, 31, 33, + 33, 31, 30, 27, 28, 30, 29, 25, 20, 17, 20, 24, 22, 17, 11, 10, + 9, 9, 5, -6, -11, -13, -9, -5, -9, -16, -19, -16, -9, -6, -6, -2, + 4, 8, 11, 11, 6, -4, -11, -21, -34, -39, -41, -40, -38, -40, -44, -38, + -28, -17, -10, -6, -5, -3, 3, 10, 15, 17, 20, 23, 26, 25, 24, 26, + 28, 30, 30, 28, 25, 24, 23, 25, 22, 18, 14, 9, 5, 0, -7, -12, + -13, -12, -7, -6, -9, -12, -10, -4, 2, 2, 3, 3, 3, 6, 7, 3, + -9, -21, -28, -35, -40, -40, -37, -37, -36, -36, -29, -22, -11, -3, 2, 3, + 0, 1, 3, 6, 9, 10, 10, 10, 13, 16, 21, 24, 29, 31, 33, 33, + 33, 32, 30, 27, 23, 16, 12, 7, -2, -7, -14, -19, -16, -10, -5, -7, + -9, -9, -6, 2, 6, 8, 7, 4, 3, 1, -3, -9, -16, -25, -34, -39, + -41, -37, -33, -31, -31, -29, -22, -12, -4, 2, 7, 5, 1, -2, 0, 4, + 4, 2, 2, 5, 10, 14, 19, 24, 28, 32, 36, 38, 36, 34, 31, 27, + 23, 18, 11, 3, -5, -12, -15, -15, -11, -6, -5, -6, -8, -7, -3, 1, + 4, 6, 3, -2, -7, -9, -12, -19, -24, -30, -34, -36, -35, -32, -29, -26, + -22, -16, -10, -3, 4, 8, 9, 4, 0, -3, 0, 1, -5, -7, -5, 1, + 7, 13, 14, 17, 27, 35, 38, 37, 35, 33, 31, 29, 25, 19, 11, 3, + 0, -6, -10, -10, -7, -5, -5, -7, -7, -6, -3, 1, 4, 3, 0, -8, + -15, -18, -20, -23, -27, -30, -32, -33, -29, -28, -25, -20, -16, -13, -6, 1, + 6, 7, 4, 0, -5, -5, -5, -6, -7, -6, -2, 5, 10, 15, 20, 25, + 32, 34, 34, 34, 32, 29, 24, 22, 19, 14, 9, 6, 4, 2, 0, 0, + 2, 2, -2, -4, -6, -5, -5, -4, -4, -7, -12, -19, -25, -26, -26, -26, + -26, -29, -28, -28, -25, -22, -18, -14, -10, -5, 0, 3, 4, 5, 4, 3, + -2, -7, -10, -12, -9, -6, 0, 6, 11, 14, 16, 22, 30, 33, 34, 29, + 25, 23, 21, 22, 22, 20, 18, 16, 14, 13, 11, 11, 11, 6, -4, -12, + -16, -17, -16, -13, -16, -22, -26, -30, -30, -25, -21, -18, -17, -19, -18, -20, + -19, -15, -13, -9, -7, -6, -5, -2, 3, 5, 4, 0, -5, -8, -6, -6, + -6, -2, 4, 9, 11, 13, 15, 19, 23, 25, 22, 19, 16, 17, 20, 21, + 22, 23, 24, 25, 24, 23, 22, 21, 16, 7, -4, -14, -21, -23, -24, -24, + -28, -34, -38, -36, -31, -21, -13, -9, -8, -10, -11, -12, -14, -13, -12, -9, + -10, -12, -11, -9, -4, 3, 4, 1, -3, -4, 1, 4, 7, 10, 10, 11, + 12, 11, 8, 9, 11, 13, 11, 5, 4, 11, 20, 26, 29, 32, 35, 39, + 39, 34, 30, 23, 15, 5, -10, -23, -31, -34, -32, -33, -37, -42, -41, -32, + -21, -11, -6, -3, -3, -6, -8, -11, -14, -15, -14, -14, -14, -19, -20, -15, + -7, 0, -2, -3, 0, 4, 10, 17, 19, 18, 18, 20, 18, 11, 5, 1, + -2, -4, -7, -8, -4, 4, 14, 24, 32, 38, 46, 51, 52, 46, 37, 28, + 19, 5, -12, -29, -39, -44, -46, -46, -50, -48, -39, -29, -14, -4, 6, 9, + 8, 6, 0, -8, -13, -15, -18, -22, -28, -30, -26, -18, -9, -7, -4, 2, + 10, 18, 24, 26, 26, 23, 22, 21, 14, 3, -5, -9, -14, -16, -16, -11, + -4, 6, 14, 24, 37, 50, 58, 58, 53, 45, 36, 28, 17, 1, -18, -36, + -47, -53, -54, -53, -51, -43, -33, -20, -8, 5, 15, 17, 13, 5, -4, -12, + -14, -18, -23, -30, -34, -32, -24, -15, -10, -6, -3, 7, 18, 27, 32, 33, + 30, 28, 24, 19, 12, 2, -10, -18, -24, -26, -23, -16, -6, 4, 12, 25, + 39, 53, 60, 60, 58, 51, 42, 30, 16, 0, -20, -37, -49, -57, -61, -57, + -50, -40, -29, -17, -4, 9, 17, 17, 11, 5, -3, -8, -13, -21, -30, -35, + -34, -29, -22, -16, -11, -6, 1, 12, 24, 34, 39, 39, 35, 28, 21, 16, + 8, -3, -16, -29, -35, -34, -26, -16, -9, 1, 14, 30, 46, 56, 60, 62, + 59, 57, 46, 32, 15, -2, -17, -35, -51, -61, -61, -55, -46, -39, -30, -19, + -4, 10, 14, 13, 7, 3, -2, -6, -15, -24, -31, -33, -31, -26, -23, -19, + -11, -2, 6, 17, 30, 38, 41, 39, 34, 25, 18, 14, 6, -9, -24, -34, + -38, -34, -28, -18, -9, 0, 14, 32, 44, 52, 58, 63, 66, 59, 45, 31, + 18, 4, -17, -36, -53, -60, -59, -54, -46, -39, -30, -18, -3, 6, 8, 6, + 3, 1, -3, -11, -22, -29, -28, -23, -20, -20, -18, -10, -2, 7, 17, 27, + 34, 37, 38, 33, 26, 19, 15, 11, 0, -17, -31, -39, -40, -34, -27, -20, + -11, 1, 16, 31, 43, 52, 59, 67, 70, 62, 47, 32, 19, 4, -18, -39, + -53, -60, -57, -51, -44, -37, -30, -17, -6, 1, 2, 1, 0, -2, -7, -15, + -23, -27, -25, -19, -16, -15, -12, -4, 5, 15, 25, 33, 37, 34, 31, 27, + 22, 17, 11, 2, -11, -25, -35, -41, -41, -34, -23, -13, -4, 6, 18, 31, + 43, 54, 61, 65, 62, 53, 44, 34, 22, 2, -20, -38, -47, -50, -47, -43, + -42, -41, -32, -19, -13, -11, -10, -7, -5, -5, -9, -14, -18, -17, -12, -9, + -8, -6, 1, 6, 12, 16, 21, 25, 25, 23, 19, 18, 14, 11, 8, 0, + -10, -23, -34, -36, -32, -24, -16, -12, -6, 4, 15, 30, 42, 52, 59, 60, + 58, 53, 46, 39, 27, 5, -19, -35, -43, -44, -43, -45, -49, -48, -39, -31, + -27, -24, -19, -11, -6, -3, -4, -6, -8, -5, 3, 5, 7, 6, 7, 9, + 12, 13, 15, 14, 12, 11, 11, 9, 8, 5, 4, 0, -12, -22, -28, -26, + -21, -17, -13, -10, -5, 4, 14, 22, 32, 44, 56, 61, 59, 56, 48, 38, + 25, 7, -10, -24, -33, -38, -44, -50, -51, -47, -41, -41, -41, -37, -26, -14, + -6, 0, -2, -3, 5, 13, 19, 21, 16, 12, 9, 9, 10, 7, 3, 2, + 2, 1, -2, 0, 3, 4, 1, -4, -12, -16, -16, -9, -9, -10, -9, -5, + 2, 7, 11, 17, 27, 39, 51, 54, 52, 52, 49, 42, 28, 10, -4, -15, + -25, -36, -48, -56, -58, -56, -52, -53, -54, -45, -28, -11, -2, 3, 8, 15, + 24, 30, 34, 30, 22, 16, 12, 6, -4, -9, -9, -8, -12, -14, -12, -5, + 3, 4, 2, -3, -4, 0, 3, 2, -4, -6, -6, -5, -4, -5, -3, 8, + 21, 36, 44, 50, 55, 58, 55, 45, 33, 20, 5, -11, -27, -43, -55, -60, + -61, -62, -64, -66, -58, -40, -20, -6, 3, 8, 16, 26, 34, 39, 38, 30, + 21, 11, 2, -9, -14, -13, -13, -15, -16, -14, -6, 1, 4, 4, 3, 4, + 7, 10, 10, 5, -3, -7, -8, -9, -12, -14, -11, 0, 13, 28, 40, 51, + 58, 61, 60, 56, 47, 33, 15, -8, -28, -44, -55, -62, -72, -81, -83, -74, + -58, -39, -21, -6, 8, 18, 30, 40, 47, 49, 44, 33, 19, 6, -6, -14, + -19, -23, -26, -24, -19, -13, -5, -2, 2, 5, 8, 11, 14, 13, 9, 2, + -4, -8, -12, -15, -19, -18, -13, -3, 14, 30, 44, 53, 62, 66, 66, 59, + 48, 33, 12, -10, -31, -46, -58, -71, -79, -84, -81, -71, -54, -34, -14, 1, + 14, 26, 37, 44, 48, 49, 41, 29, 12, -3, -13, -17, -19, -24, -26, -22, + -16, -8, -3, -2, 3, 6, 10, 13, 12, 10, 6, 2, -4, -11, -18, -22, + -22, -19, -14, -3, 13, 30, 46, 61, 68, 71, 70, 64, 52, 32, 10, -12, + -31, -51, -67, -81, -88, -91, -84, -69, -51, -32, -12, 8, 25, 37, 43, 47, + 52, 50, 40, 23, 5, -8, -13, -18, -23, -28, -26, -19, -12, -6, -4, -2, + 2, 6, 11, 11, 5, 3, 4, 1, -9, -17, -21, -23, -22, -19, -14, 0, + 17, 37, 54, 65, 70, 75, 76, 67, 50, 30, 6, -15, -35, -56, -75, -88, + -93, -88, -78, -64, -47, -26, -3, 17, 31, 37, 42, 46, 48, 42, 27, 10, + 0, -3, -7, -14, -21, -21, -13, -4, 1, -2, -3, 1, 5, 7, 4, -3, + -8, -7, -7, -14, -19, -22, -23, -21, -20, -16, -6, 12, 32, 51, 63, 70, + 76, 78, 75, 63, 44, 20, -5, -26, -46, -67, -83, -94, -93, -83, -69, -55, + -40, -17, 8, 25, 34, 38, 43, 48, 45, 35, 20, 8, 2, 3, -2, -12, + -18, -15, -8, 0, 0, -5, -6, -4, -3, -5, -11, -15, -14, -12, -13, -16, + -19, -20, -20, -16, -10, -2, 11, 24, 42, 57, 64, 70, 73, 72, 64, 48, + 26, 4, -15, -35, -50, -68, -81, -88, -81, -68, -55, -44, -29, -10, 9, 22, + 25, 30, 37, 38, 35, 24, 14, 11, 13, 14, 9, 0, -5, -3, 3, 4, + -2, -10, -15, -15, -15, -19, -25, -24, -20, -18, -19, -20, -18, -16, -13, -9, + 1, 12, 25, 37, 53, 63, 69, 74, 73, 69, 56, 37, 15, -6, -25, -42, + -59, -75, -82, -81, -72, -61, -50, -35, -17, -2, 13, 20, 27, 31, 34, 34, + 28, 19, 14, 13, 15, 14, 8, 4, 3, 5, 5, 1, -6, -15, -18, -22, + -27, -33, -34, -31, -25, -24, -20, -19, -17, -10, -2, 9, 18, 28, 39, 51, + 60, 67, 71, 72, 67, 53, 35, 16, -4, -21, -40, -57, -70, -76, -74, -65, + -55, -44, -34, -21, -7, 6, 15, 18, 20, 24, 24, 21, 16, 15, 16, 17, + 17, 16, 13, 12, 13, 13, 9, 0, -12, -17, -22, -31, -40, -43, -40, -35, + -30, -26, -24, -20, -11, -2, 9, 19, 29, 39, 46, 54, 60, 66, 67, 66, + 58, 41, 21, 5, -11, -29, -47, -62, -68, -68, -65, -57, -49, -39, -27, -13, + -2, 6, 11, 18, 23, 24, 21, 19, 19, 21, 21, 18, 15, 11, 13, 15, + 15, 10, -2, -8, -14, -21, -30, -39, -44, -44, -40, -33, -29, -27, -21, -12, + -3, 6, 16, 28, 40, 48, 54, 56, 59, 61, 62, 57, 44, 28, 12, -3, + -22, -40, -55, -64, -63, -61, -56, -51, -41, -29, -15, -6, 1, 8, 15, 20, + 20, 18, 17, 18, 23, 23, 20, 17, 15, 18, 20, 20, 15, 4, -5, -11, + -20, -32, -43, -49, -48, -43, -36, -32, -29, -21, -13, 0, 11, 20, 30, 38, + 46, 50, 51, 53, 56, 53, 48, 41, 30, 19, 5, -10, -26, -42, -50, -56, + -57, -56, -53, -46, -38, -27, -18, -10, -2, 8, 16, 19, 24, 24, 22, 23, + 25, 23, 17, 16, 15, 16, 14, 10, 3, -5, -11, -20, -28, -35, -42, -44, + -42, -35, -29, -25, -19, -11, 0, 10, 20, 26, 31, 38, 45, 48, 46, 46, + 44, 41, 37, 30, 22, 13, 1, -15, -27, -36, -44, -49, -51, -52, -49, -44, + -37, -27, -20, -12, 1, 10, 19, 23, 28, 29, 28, 28, 24, 19, 17, 16, + 15, 14, 10, 4, -3, -10, -15, -23, -31, -36, -41, -41, -39, -32, -24, -19, + -11, -3, 5, 15, 24, 31, 36, 42, 45, 44, 41, 37, 33, 31, 29, 23, + 14, 2, -8, -16, -22, -31, -40, -44, -46, -46, -46, -44, -37, -28, -20, -10, + 2, 11, 20, 28, 32, 32, 29, 26, 22, 19, 17, 14, 12, 11, 8, 2, + -5, -14, -20, -24, -30, -34, -37, -38, -36, -30, -21, -14, -6, 2, 11, 19, + 26, 30, 34, 41, 44, 42, 38, 32, 27, 25, 24, 21, 11, 1, -9, -16, + -25, -34, -40, -43, -45, -48, -50, -49, -40, -27, -15, -6, 4, 15, 27, 36, + 40, 37, 32, 27, 22, 15, 11, 10, 8, 6, 0, -8, -14, -16, -17, -18, + -24, -31, -33, -33, -27, -22, -17, -10, -4, 6, 13, 17, 22, 27, 33, 38, + 39, 37, 35, 33, 31, 27, 23, 19, 11, 3, -7, -20, -30, -38, -42, -42, + -46, -53, -58, -53, -41, -27, -13, -2, 10, 19, 30, 39, 43, 38, 29, 23, + 18, 12, 8, 6, 6, 4, -3, -8, -12, -13, -10, -12, -17, -24, -25, -23, + -23, -23, -19, -12, -4, 2, 5, 9, 14, 22, 32, 37, 39, 39, 37, 37, + 33, 28, 27, 21, 12, 0, -14, -25, -33, -38, -43, -48, -54, -60, -59, -48, + -36, -20, -8, 2, 12, 26, 39, 44, 40, 32, 27, 23, 16, 8, 3, 3, + 2, 1, -4, -9, -9, -6, -6, -8, -13, -16, -18, -21, -22, -21, -16, -7, + -2, 0, -2, 2, 13, 25, 30, 34, 34, 34, 34, 33, 33, 31, 26, 21, + 11, -3, -15, -25, -31, -37, -48, -57, -62, -63, -56, -46, -35, -25, -12, 5, + 18, 32, 40, 40, 36, 32, 29, 22, 15, 7, 3, 0, 0, 0, 1, -2, + -2, 0, 0, -3, -4, -7, -13, -22, -28, -25, -17, -10, -10, -11, -10, -4, + 12, 26, 36, 39, 40, 41, 40, 37, 35, 33, 28, 19, 3, -11, -22, -30, + -37, -46, -56, -63, -65, -59, -52, -43, -29, -17, -4, 10, 23, 32, 36, 36, + 34, 29, 24, 19, 12, 5, -2, 0, 4, 7, 10, 9, 6, 5, 5, 5, + 0, -10, -20, -26, -29, -26, -20, -18, -19, -17, -9, 3, 16, 28, 36, 40, + 42, 43, 41, 40, 36, 33, 26, 16, 3, -10, -21, -31, -42, -53, -61, -65, + -63, -58, -52, -41, -31, -18, -4, 9, 21, 26, 29, 30, 31, 31, 28, 21, + 12, 6, 5, 10, 13, 13, 14, 9, 8, 7, 5, 0, -8, -17, -24, -28, + -27, -23, -17, -14, -12, -8, 2, 15, 26, 32, 36, 39, 38, 37, 36, 33, + 28, 21, 16, 10, 1, -13, -25, -34, -41, -50, -59, -62, -62, -53, -44, -37, + -28, -19, -6, 7, 14, 18, 22, 26, 28, 28, 21, 13, 6, 6, 15, 19, + 21, 20, 20, 18, 16, 13, 7, -3, -12, -21, -27, -31, -30, -24, -15, -11, + -8, 0, 10, 23, 29, 32, 34, 34, 34, 33, 32, 27, 23, 20, 17, 10, + -2, -15, -25, -34, -43, -52, -61, -63, -58, -49, -43, -41, -33, -22, -9, 3, + 11, 17, 21, 26, 30, 28, 23, 17, 15, 18, 22, 22, 20, 21, 21, 18, + 12, 4, -5, -11, -16, -22, -28, -32, -24, -14, -7, -5, 1, 11, 20, 27, + 30, 26, 25, 29, 30, 29, 22, 17, 18, 22, 20, 9, -8, -18, -25, -31, + -40, -53, -60, -58, -54, -46, -45, -42, -32, -20, -10, -2, 5, 12, 19, 25, + 27, 22, 18, 18, 21, 24, 25, 22, 24, 26, 27, 22, 10, 0, -7, -9, + -12, -21, -28, -28, -20, -9, -4, -2, 5, 14, 22, 24, 21, 15, 18, 24, + 28, 24, 19, 21, 26, 30, 22, 7, -6, -15, -23, -34, -50, -61, -66, -61, + -52, -50, -49, -45, -36, -22, -10, 1, 11, 15, 20, 26, 26, 24, 21, 21, + 27, 28, 24, 21, 22, 26, 24, 16, 5, -5, -7, -5, -11, -17, -22, -17, + -7, 0, 1, 4, 9, 16, 19, 18, 13, 12, 16, 22, 24, 23, 23, 28, + 33, 27, 16, 2, -12, -23, -33, -45, -57, -64, -64, -55, -51, -52, -49, -39, + -25, -13, -6, 1, 6, 12, 16, 18, 20, 18, 20, 25, 28, 28, 29, 31, + 36, 37, 28, 15, 7, 3, 0, -4, -14, -21, -23, -16, -7, -4, -3, 1, + 10, 16, 17, 10, 7, 9, 18, 24, 24, 24, 28, 34, 34, 26, 12, -3, + -15, -26, -40, -53, -61, -65, -62, -59, -57, -55, -49, -39, -27, -18, -6, 3, + 8, 14, 17, 21, 25, 26, 27, 28, 30, 32, 32, 31, 32, 28, 22, 14, + 6, 3, 0, -3, -8, -12, -12, -5, 0, 2, 1, 3, 6, 11, 11, 7, + 4, 6, 13, 20, 24, 28, 31, 32, 28, 19, 7, -7, -20, -32, -44, -53, + -58, -58, -55, -54, -53, -50, -46, -40, -27, -14, -6, -6, -5, 0, 8, 16, + 20, 23, 25, 30, 37, 42, 43, 41, 39, 34, 28, 18, 9, 4, 3, 0, + -10, -13, -12, -10, -5, 1, 1, 0, 4, 8, 7, 5, 6, 11, 19, 23, + 27, 32, 33, 27, 20, 10, 0, -15, -30, -41, -49, -52, -54, -55, -55, -53, + -50, -45, -40, -32, -24, -16, -11, -10, -8, -3, 6, 13, 17, 21, 29, 37, + 43, 48, 47, 43, 38, 35, 30, 19, 11, 7, 2, -5, -9, -9, -5, 1, + 1, 0, -2, 1, 3, 6, 5, 4, 5, 10, 16, 20, 24, 27, 25, 18, + 10, 3, -9, -21, -31, -39, -44, -47, -47, -44, -46, -48, -48, -45, -39, -36, + -30, -26, -25, -23, -19, -9, 4, 14, 24, 32, 41, 48, 54, 56, 57, 52, + 47, 40, 28, 17, 10, 4, -3, -8, -10, -8, -6, -5, -5, -5, -3, 0, + 3, 4, 4, 5, 7, 12, 19, 26, 27, 24, 18, 12, 5, -3, -12, -24, + -34, -43, -46, -48, -48, -46, -46, -45, -44, -42, -38, -33, -29, -26, -26, -22, + -14, -5, 5, 13, 23, 32, 40, 47, 52, 56, 57, 55, 52, 47, 36, 27, + 19, 11, 3, -5, -6, -8, -10, -13, -15, -14, -13, -11, -6, 1, 4, 7, + 11, 17, 21, 26, 28, 26, 19, 10, 2, -7, -17, -26, -36, -41, -45, -47, + -45, -44, -44, -41, -39, -40, -40, -37, -33, -34, -32, -26, -18, -9, 2, 12, + 26, 40, 47, 56, 63, 66, 66, 63, 60, 53, 40, 27, 14, 3, -8, -11, + -12, -15, -19, -19, -18, -15, -12, -8, 0, 6, 11, 13, 14, 17, 23, 29, + 27, 18, 9, 1, -7, -16, -25, -35, -43, -49, -47, -44, -43, -42, -40, -36, + -34, -33, -33, -33, -35, -34, -30, -23, -16, -9, 2, 14, 27, 39, 49, 58, + 66, 69, 68, 66, 61, 53, 45, 32, 18, 1, -11, -14, -17, -17, -20, -23, + -21, -17, -13, -3, 4, 10, 13, 14, 17, 18, 21, 24, 22, 15, 6, -4, + -12, -22, -28, -38, -49, -51, -48, -45, -43, -40, -38, -36, -35, -34, -33, -33, + -34, -35, -33, -29, -18, -6, 6, 19, 33, 46, 59, 71, 78, 78, 78, 74, + 67, 54, 39, 22, 6, -8, -16, -22, -25, -25, -26, -22, -17, -12, -3, 6, + 15, 17, 16, 14, 14, 16, 17, 16, 13, 6, -2, -11, -20, -27, -34, -43, + -49, -48, -44, -41, -39, -36, -33, -34, -33, -34, -32, -33, -35, -35, -30, -21, + -11, 0, 9, 23, 38, 52, 65, 74, 76, 76, 74, 70, 62, 47, 28, 13, + 2, -6, -14, -21, -23, -20, -18, -16, -13, -7, 1, 8, 10, 11, 9, 11, + 11, 13, 15, 16, 13, 8, -2, -11, -19, -27, -37, -47, -52, -51, -48, -46, + -43, -40, -38, -36, -35, -35, -38, -38, -33, -27, -21, -16, -7, 6, 21, 36, + 49, 61, 70, 75, 79, 78, 73, 62, 49, 35, 22, 8, -3, -12, -17, -20, + -18, -14, -13, -15, -12, -5, 4, 7, 8, 8, 9, 8, 9, 11, 14, 14, + 10, 4, -6, -15, -25, -35, -41, -48, -54, -53, -47, -42, -38, -37, -35, -31, + -31, -30, -30, -29, -26, -24, -19, -12, -2, 10, 22, 35, 48, 60, 70, 76, + 76, 73, 67, 57, 44, 28, 14, 5, -3, -8, -13, -14, -13, -10, -11, -11, + -8, -2, 4, 6, 5, 5, 5, 6, 10, 11, 10, 8, 4, -2, -9, -15, + -24, -35, -44, -50, -52, -49, -45, -42, -42, -40, -37, -37, -37, -33, -29, -26, + -24, -21, -16, -7, 6, 18, 30, 41, 54, 66, 75, 77, 79, 76, 67, 53, + 37, 21, 8, 2, -5, -10, -14, -14, -12, -12, -11, -10, -5, 4, 7, 4, + 1, 2, 6, 9, 9, 7, 5, 4, 0, -7, -14, -23, -32, -37, -43, -48, + -50, -51, -47, -42, -34, -32, -32, -34, -32, -26, -21, -18, -17, -14, -11, -4, + 5, 13, 24, 40, 55, 67, 72, 74, 76, 75, 67, 51, 37, 23, 11, 4, + -4, -11, -15, -17, -17, -16, -14, -13, -8, -2, 1, 1, 1, 3, 5, 9, + 7, 5, 4, 4, 3, -5, -14, -24, -32, -38, -41, -47, -52, -53, -49, -41, + -35, -34, -35, -33, -29, -24, -19, -13, -10, -9, -7, -2, 8, 17, 29, 43, + 56, 67, 74, 75, 75, 72, 64, 53, 38, 23, 13, 4, -5, -12, -16, -20, + -21, -18, -16, -14, -11, -8, -5, -3, 0, 2, 6, 6, 6, 5, 5, 6, + 3, -6, -19, -31, -37, -41, -45, -50, -52, -53, -48, -39, -32, -30, -26, -25, + -22, -16, -10, -7, -11, -10, -8, -2, 6, 17, 31, 45, 58, 68, 78, 80, + 76, 70, 65, 55, 37, 18, 5, -4, -10, -19, -25, -26, -24, -18, -13, -11, + -9, -6, -2, 4, 6, 5, 4, 3, 4, 2, 1, -3, -4, -11, -20, -29, + -38, -43, -45, -48, -51, -48, -44, -39, -35, -34, -31, -30, -25, -15, -8, -8, + -10, -8, 1, 11, 22, 33, 42, 54, 66, 76, 80, 75, 70, 66, 59, 42, + 23, 6, -4, -9, -17, -22, -27, -25, -19, -9, -7, -8, -5, 0, 4, 5, + 2, -2, -5, -5, -4, -6, -7, -6, -10, -16, -21, -29, -34, -37, -38, -41, + -44, -42, -36, -32, -33, -37, -39, -35, -27, -17, -12, -13, -12, -6, 6, 22, + 36, 44, 54, 66, 77, 82, 80, 75, 68, 59, 47, 29, 10, -3, -13, -18, + -23, -26, -27, -24, -16, -9, -5, -4, -2, 3, 6, 4, -2, -6, -8, -7, + -8, -8, -9, -10, -13, -16, -22, -29, -31, -30, -34, -36, -36, -32, -28, -30, + -36, -39, -38, -33, -28, -24, -24, -22, -15, -2, 13, 26, 38, 53, 67, 78, + 84, 88, 85, 81, 71, 59, 39, 13, -5, -14, -19, -26, -32, -34, -30, -22, + -13, -5, 0, 6, 7, 10, 8, 2, -4, -10, -12, -15, -18, -20, -20, -20, + -22, -24, -26, -26, -23, -23, -23, -24, -21, -17, -18, -25, -31, -35, -37, -37, + -36, -33, -29, -22, -10, 5, 19, 31, 45, 62, 75, 84, 86, 88, 87, 80, + 66, 45, 22, 4, -9, -18, -26, -34, -37, -33, -24, -15, -9, -3, 6, 13, + 15, 11, 2, -5, -10, -13, -20, -25, -27, -26, -25, -26, -29, -29, -23, -18, + -16, -19, -18, -15, -9, -6, -12, -21, -32, -36, -36, -40, -39, -36, -30, -21, + -10, 6, 20, 36, 55, 69, 79, 85, 90, 92, 88, 75, 56, 33, 12, -3, + -15, -24, -33, -37, -35, -28, -20, -12, -4, 6, 14, 18, 16, 9, 0, -8, + -15, -19, -27, -33, -35, -34, -34, -36, -36, -29, -19, -10, -10, -10, -8, -4, + -2, -2, -8, -18, -28, -36, -43, -48, -46, -36, -25, -14, -4, 10, 27, 46, + 65, 78, 86, 89, 87, 85, 78, 64, 42, 19, 0, -12, -20, -29, -34, -36, + -30, -22, -12, -6, 1, 8, 16, 18, 13, 2, -7, -12, -17, -24, -33, -38, + -39, -36, -36, -36, -34, -26, -18, -11, -7, -6, -5, -5, 1, 1, -5, -14, + -24, -33, -41, -42, -37, -28, -19, -10, 3, 16, 30, 47, 64, 76, 83, 85, + 83, 78, 69, 54, 37, 17, -2, -14, -21, -28, -32, -32, -27, -18, -11, -6, + 2, 12, 18, 16, 5, -5, -11, -14, -19, -30, -40, -47, -45, -38, -36, -34, + -33, -26, -15, -6, -2, 1, 1, 3, 5, 4, -3, -13, -26, -35, -41, -39, + -33, -23, -13, -5, 7, 21, 36, 53, 68, 79, 82, 78, 72, 66, 59, 47, + 30, 10, -6, -16, -21, -22, -25, -27, -25, -18, -10, -4, 4, 10, 11, 6, + -4, -11, -13, -18, -25, -34, -43, -45, -41, -36, -34, -32, -27, -19, -10, -5, + 0, 2, 5, 5, 5, 1, -7, -16, -25, -33, -38, -35, -25, -13, -6, 0, + 11, 27, 46, 60, 69, 70, 68, 69, 68, 62, 52, 39, 22, 8, -2, -11, + -18, -21, -22, -23, -24, -17, -10, -5, 1, 5, 5, 2, -3, -5, -9, -17, + -28, -41, -46, -48, -43, -42, -42, -39, -30, -19, -9, -3, 6, 11, 15, 16, + 12, 5, -2, -12, -23, -33, -37, -34, -25, -18, -8, 1, 15, 32, 48, 62, + 69, 68, 67, 63, 62, 58, 50, 34, 15, -2, -8, -10, -11, -16, -24, -24, + -19, -12, -6, -2, 2, 3, 1, 0, -6, -10, -17, -26, -37, -46, -48, -45, + -44, -42, -38, -32, -22, -12, -6, 4, 10, 14, 16, 15, 11, 5, -2, -11, + -23, -31, -29, -22, -18, -16, -11, 3, 17, 34, 50, 56, 59, 61, 63, 62, + 59, 53, 44, 32, 16, 3, -8, -9, -13, -20, -26, -27, -21, -16, -11, -9, + -6, 1, 7, 7, 0, -10, -15, -20, -30, -39, -45, -48, -48, -46, -41, -36, + -29, -20, -11, 3, 11, 14, 19, 21, 19, 15, 6, -3, -13, -18, -18, -17, + -20, -19, -12, 2, 15, 26, 36, 43, 51, 59, 61, 61, 57, 54, 49, 37, + 21, 9, 1, -8, -17, -25, -29, -28, -27, -23, -19, -13, -5, 2, 8, 5, + -4, -11, -13, -17, -27, -40, -49, -53, -53, -50, -44, -37, -28, -19, -7, 8, + 18, 22, 26, 26, 23, 17, 10, 0, -8, -15, -20, -25, -23, -19, -11, 0, + 13, 25, 34, 44, 54, 60, 62, 60, 58, 56, 52, 38, 21, 6, -6, -16, + -26, -32, -33, -30, -26, -24, -17, -8, 3, 13, 16, 10, 1, -7, -12, -18, + -34, -50, -61, -63, -58, -54, -50, -45, -33, -13, 6, 21, 27, 34, 37, 36, + 30, 20, 11, -2, -13, -24, -32, -37, -34, -24, -10, 2, 12, 25, 41, 55, + 61, 64, 65, 67, 64, 59, 48, 32, 16, 0, -12, -20, -27, -33, -33, -31, + -28, -23, -12, 0, 10, 13, 9, 2, -2, -7, -13, -25, -41, -56, -65, -66, + -62, -56, -53, -42, -25, -5, 13, 24, 34, 39, 42, 39, 32, 22, 11, -2, + -15, -27, -36, -37, -31, -22, -13, 0, 12, 27, 43, 55, 61, 64, 65, 63, + 60, 53, 42, 28, 10, -6, -20, -27, -28, -28, -25, -23, -20, -13, -2, 11, + 16, 14, 8, 2, -6, -14, -25, -38, -53, -67, -73, -73, -67, -58, -46, -32, + -14, 6, 24, 36, 43, 45, 44, 39, 30, 18, 5, -11, -25, -35, -39, -37, + -28, -17, -7, 4, 16, 32, 48, 58, 64, 66, 63, 61, 56, 46, 31, 18, + 3, -13, -21, -25, -23, -19, -15, -11, -7, -2, 6, 13, 14, 8, -3, -12, + -21, -32, -40, -55, -70, -78, -75, -67, -56, -47, -29, -12, 10, 29, 40, 47, + 49, 48, 43, 31, 15, 0, -16, -29, -39, -45, -41, -32, -18, -6, 3, 13, + 27, 43, 57, 64, 65, 61, 58, 52, 43, 32, 18, 6, -9, -18, -20, -17, + -12, -4, 1, 3, 7, 12, 17, 16, 9, -3, -15, -27, -39, -48, -60, -72, + -82, -82, -73, -58, -45, -33, -14, 7, 28, 42, 49, 51, 51, 48, 38, 22, + 2, -16, -30, -37, -42, -45, -40, -26, -11, 3, 11, 20, 34, 52, 65, 69, + 64, 54, 46, 38, 28, 16, 4, -11, -18, -16, -10, -4, 3, 13, 21, 23, + 22, 20, 18, 11, -2, -16, -34, -47, -59, -70, -76, -83, -83, -76, -64, -48, + -31, -12, 10, 30, 42, 50, 53, 51, 46, 37, 25, 8, -13, -30, -41, -45, + -43, -35, -23, -15, -5, 8, 17, 28, 40, 56, 64, 63, 55, 45, 34, 24, + 14, 7, -4, -12, -13, -9, -2, 11, 23, 31, 33, 33, 31, 26, 17, 4, + -14, -31, -48, -62, -75, -86, -90, -87, -79, -68, -54, -39, -18, 4, 23, 39, + 47, 52, 52, 47, 39, 29, 15, -5, -23, -35, -41, -40, -34, -26, -16, -8, + 2, 12, 22, 30, 43, 52, 58, 54, 45, 36, 25, 16, 7, -2, -7, -8, + -3, 4, 13, 24, 32, 39, 42, 39, 30, 19, 6, -10, -25, -44, -62, -79, + -88, -90, -85, -78, -70, -59, -45, -24, 0, 20, 35, 43, 48, 48, 46, 42, + 33, 20, 2, -19, -32, -38, -41, -37, -29, -19, -8, 1, 11, 19, 26, 35, + 43, 48, 48, 41, 35, 26, 16, 7, 0, 0, 3, 6, 10, 16, 24, 32, + 40, 44, 43, 33, 21, 8, -5, -19, -37, -54, -72, -84, -87, -81, -75, -68, + -61, -50, -33, -12, 8, 22, 29, 34, 40, 42, 41, 35, 24, 13, -2, -16, + -27, -33, -33, -27, -22, -17, -13, -4, 9, 18, 25, 31, 36, 42, 44, 40, + 32, 21, 12, 9, 7, 8, 9, 13, 17, 23, 29, 35, 40, 40, 35, 26, + 13, 0, -11, -24, -41, -60, -74, -80, -79, -73, -68, -63, -56, -43, -27, -10, + 6, 18, 24, 29, 34, 38, 37, 30, 20, 9, -3, -14, -24, -27, -27, -25, + -23, -18, -9, 2, 10, 19, 25, 30, 37, 40, 41, 33, 22, 16, 10, 6, + 6, 10, 16, 21, 28, 31, 35, 38, 44, 45, 34, 19, 5, -5, -17, -33, + -52, -68, -76, -78, -75, -71, -67, -62, -51, -37, -20, -7, 4, 13, 21, 29, + 34, 36, 33, 26, 17, 10, 0, -8, -13, -19, -21, -21, -17, -11, -6, 4, + 10, 13, 19, 25, 30, 31, 28, 20, 14, 10, 7, 7, 11, 20, 26, 32, + 36, 39, 41, 44, 46, 41, 30, 13, 0, -13, -27, -44, -62, -72, -74, -74, + -74, -71, -66, -57, -47, -32, -19, -9, 2, 14, 24, 28, 32, 34, 33, 25, + 17, 9, 2, -5, -10, -17, -22, -18, -13, -7, 0, 4, 10, 17, 23, 26, + 25, 21, 15, 9, 9, 7, 4, 7, 16, 27, 34, 39, 43, 48, 49, 52, + 49, 39, 24, 9, -3, -17, -32, -52, -67, -75, -75, -71, -70, -70, -66, -56, + -43, -31, -21, -12, -2, 11, 21, 27, 30, 33, 31, 29, 22, 15, 8, 0, + -6, -13, -14, -14, -11, -5, 0, 4, 8, 13, 16, 18, 15, 12, 10, 7, + 7, 6, 7, 14, 24, 36, 44, 46, 46, 49, 52, 53, 47, 35, 21, 9, + -6, -23, -43, -59, -68, -71, -74, -74, -76, -73, -64, -52, -39, -31, -25, -15, + 0, 12, 20, 24, 29, 32, 30, 26, 21, 16, 10, 4, -2, -7, -7, -5, + -3, 0, 3, 5, 6, 9, 8, 8, 6, 3, 2, 4, 5, 7, 14, 22, + 34, 43, 49, 57, 57, 55, 52, 48, 43, 31, 17, 2, -13, -33, -49, -59, + -63, -66, -72, -75, -76, -70, -61, -52, -44, -37, -30, -18, -4, 11, 20, 25, + 28, 32, 32, 30, 26, 19, 13, 5, 0, -4, -5, -3, 1, 2, 1, -3, + -2, 2, 6, 4, 2, -3, -2, 3, 10, 13, 18, 27, 40, 49, 56, 59, + 60, 56, 52, 47, 41, 30, 17, 1, -19, -39, -55, -64, -67, -70, -76, -81, + -78, -69, -56, -46, -40, -33, -24, -12, 3, 15, 22, 25, 26, 29, 27, 23, + 19, 14, 9, 4, 0, -2, 1, 5, 9, 7, 2, -3, -3, 3, 3, -2, + -10, -13, -10, -2, 7, 14, 22, 31, 45, 59, 65, 68, 65, 62, 58, 50, + 41, 28, 12, -9, -31, -49, -59, -65, -70, -76, -84, -84, -77, -63, -50, -45, + -40, -32, -21, -7, 7, 16, 24, 28, 29, 28, 23, 18, 15, 11, 6, 0, + -4, -3, 4, 11, 14, 11, 6, 5, 7, 7, 2, -7, -12, -16, -13, -6, + 1, 8, 17, 32, 50, 63, 68, 68, 69, 70, 65, 56, 43, 27, 7, -17, + -38, -52, -62, -71, -78, -86, -88, -84, -73, -59, -50, -43, -34, -25, -11, 2, + 11, 19, 23, 26, 26, 21, 17, 12, 9, 7, 5, 2, 2, 4, 11, 16, + 14, 10, 9, 10, 9, 1, -8, -16, -19, -16, -11, -6, 0, 8, 24, 43, + 57, 66, 70, 72, 72, 67, 63, 52, 37, 18, -5, -23, -41, -54, -62, -70, + -78, -81, -82, -76, -67, -56, -45, -36, -31, -22, -12, 0, 10, 16, 20, 21, + 17, 13, 7, 3, 3, 6, 6, 6, 9, 14, 20, 21, 20, 17, 17, 15, + 9, -3, -15, -23, -27, -20, -14, -9, -4, 9, 31, 49, 64, 70, 75, 78, + 76, 70, 60, 45, 31, 12, -11, -31, -46, -58, -66, -70, -73, -77, -74, -67, + -59, -52, -44, -36, -29, -22, -14, -6, 1, 11, 14, 14, 11, 6, 6, 7, + 10, 11, 12, 15, 18, 24, 23, 21, 19, 20, 18, 12, 0, -13, -20, -27, + -27, -22, -16, -11, 1, 19, 36, 52, 64, 73, 79, 81, 77, 69, 56, 43, + 26, 5, -16, -37, -54, -62, -66, -69, -72, -71, -65, -62, -56, -47, -39, -33, + -26, -19, -14, -12, -3, 9, 9, 3, -6, -4, 5, 11, 12, 11, 12, 20, + 29, 31, 29, 25, 25, 27, 24, 11, -6, -17, -25, -31, -32, -30, -26, -16, + 0, 17, 35, 51, 66, 78, 87, 88, 84, 73, 57, 40, 23, 3, -20, -42, + -57, -65, -69, -71, -70, -68, -63, -58, -52, -45, -38, -30, -26, -24, -23, -16, + -8, -2, -5, -9, -6, 1, 9, 12, 13, 17, 24, 32, 37, 37, 34, 32, + 33, 31, 19, 2, -15, -25, -31, -36, -38, -35, -27, -13, 4, 23, 40, 59, + 76, 91, 96, 91, 80, 69, 55, 35, 13, -12, -35, -52, -61, -66, -71, -70, + -63, -54, -48, -44, -42, -36, -31, -30, -34, -36, -33, -26, -20, -20, -21, -18, + -9, 5, 13, 18, 21, 29, 40, 47, 50, 49, 44, 40, 34, 23, 6, -14, + -27, -39, -45, -48, -45, -35, -23, -7, 11, 30, 51, 73, 89, 97, 96, 89, + 80, 63, 44, 25, 4, -18, -39, -53, -59, -63, -61, -58, -55, -52, -49, -45, + -39, -35, -37, -41, -46, -43, -38, -33, -29, -25, -18, -11, 3, 13, 20, 25, + 30, 38, 46, 51, 50, 47, 43, 37, 26, 9, -7, -19, -32, -45, -52, -51, + -40, -28, -12, 4, 19, 38, 61, 83, 94, 95, 89, 82, 67, 50, 30, 12, + -8, -26, -40, -52, -57, -56, -52, -48, -46, -44, -40, -34, -32, -32, -37, -44, + -47, -45, -41, -39, -35, -28, -17, -6, 7, 15, 23, 32, 40, 47, 52, 52, + 51, 46, 39, 32, 17, 1, -14, -26, -37, -46, -50, -45, -35, -25, -11, 5, + 24, 44, 62, 79, 88, 86, 79, 70, 59, 45, 25, 7, -13, -25, -36, -46, + -50, -51, -50, -46, -43, -41, -37, -34, -33, -36, -40, -43, -46, -46, -41, -36, + -31, -22, -10, 4, 13, 21, 30, 40, 47, 50, 53, 52, 47, 39, 30, 18, + 3, -12, -22, -33, -42, -47, -45, -36, -25, -14, -2, 14, 34, 52, 67, 76, + 77, 72, 65, 55, 43, 27, 12, -7, -21, -29, -36, -41, -44, -43, -39, -36, + -32, -27, -26, -26, -29, -33, -36, -43, -49, -48, -44, -38, -32, -22, -11, 4, + 15, 25, 34, 44, 50, 53, 54, 52, 44, 35, 23, 9, -4, -15, -27, -37, + -43, -45, -42, -34, -21, -9, 5, 19, 34, 50, 63, 70, 69, 63, 54, 46, + 35, 20, 4, -11, -23, -29, -33, -37, -41, -40, -33, -25, -20, -19, -21, -22, + -23, -26, -34, -42, -47, -46, -43, -36, -30, -22, -11, 5, 17, 28, 37, 45, + 52, 55, 53, 49, 41, 30, 19, 4, -12, -23, -33, -41, -45, -45, -40, -31, + -18, -3, 11, 23, 38, 51, 63, 64, 58, 51, 45, 36, 25, 10, -4, -15, + -24, -28, -32, -36, -35, -29, -19, -13, -13, -14, -13, -13, -13, -21, -33, -43, + -45, -45, -41, -38, -34, -25, -11, 4, 17, 29, 39, 49, 57, 60, 55, 48, + 39, 29, 16, 1, -14, -27, -35, -42, -47, -48, -42, -29, -15, -3, 10, 20, + 34, 48, 56, 57, 51, 45, 38, 30, 20, 7, -7, -17, -22, -26, -32, -36, + -31, -21, -9, -6, -8, -8, -4, 1, -4, -13, -26, -35, -39, -40, -42, -44, + -40, -29, -13, 3, 16, 29, 43, 58, 67, 67, 59, 49, 39, 27, 11, -9, + -28, -39, -47, -50, -53, -52, -44, -29, -12, 5, 13, 25, 38, 51, 57, 52, + 45, 38, 30, 21, 9, -4, -14, -21, -26, -29, -33, -28, -18, -7, 2, 2, + 2, 4, 8, 10, 5, -10, -25, -36, -42, -45, -49, -49, -45, -33, -14, 5, + 22, 35, 54, 69, 78, 76, 67, 53, 41, 27, 6, -17, -36, -50, -55, -60, + -63, -62, -51, -34, -16, -2, 9, 20, 34, 45, 50, 48, 42, 35, 29, 18, + 7, 0, 0, 0, 0, 0, 0, 7, 0, -1, -7, -18, -16, 3, 6, -18, + -29, -21, 6, 6, -12, -10, -10, -2, 4, 15, 21, 14, 4, 9, 29, 27, + 15, 9, 13, 20, 0, -21, -11, 3, -11, -37, -36, -7, 11, -4, -26, -23, + -4, 15, -4, -15, -11, -10, -1, 9, 23, 15, 8, 6, 24, 35, 19, 14, + 6, 17, 10, -15, -26, -7, -1, -23, -40, -24, 4, 10, -16, -25, -13, 11, + 10, -14, -15, -12, -6, 1, 19, 22, 6, 7, 15, 40, 31, 22, 7, 7, + 15, 5, -22, -21, -5, -9, -33, -32, -15, 5, -4, -19, -20, 1, 17, -4, + -15, -11, -12, -4, 9, 27, 13, 7, 11, 32, 44, 30, 14, 2, 7, 9, + -8, -25, -18, -9, -19, -30, -21, -4, 2, -10, -21, -13, 15, 8, -11, -13, + -16, -12, 0, 20, 24, 9, 9, 19, 44, 47, 25, 6, 2, 11, -1, -21, + -27, -19, -17, -20, -23, -17, -5, -5, -14, -20, 0, 15, -4, -7, -17, -17, + -8, 7, 25, 18, 7, 11, 31, 54, 41, 14, -1, 10, 3, -14, -27, -29, + -21, -16, -16, -18, -17, -11, -10, -16, -16, 10, 6, -3, -9, -19, -16, -2, + 18, 27, 16, 8, 19, 45, 54, 29, 5, 6, 4, -9, -18, -29, -30, -18, + -10, -9, -14, -20, -12, -13, -17, -5, 12, 7, 2, -16, -22, -13, 8, 25, + 23, 12, 11, 32, 53, 48, 17, 9, 9, -7, -16, -24, -37, -28, -12, -4, + -2, -18, -21, -18, -23, -17, 7, 11, 10, -4, -16, -22, -7, 21, 28, 18, + 9, 20, 43, 55, 37, 11, 11, 1, -14, -17, -31, -34, -21, -10, 4, -2, + -20, -23, -26, -29, -3, 6, 13, 8, -5, -23, -27, 7, 28, 27, 15, 12, + 32, 48, 50, 24, 9, 8, -12, -19, -26, -37, -35, -19, 3, 6, -12, -21, + -31, -38, -17, 6, 4, 14, 6, -8, -35, -15, 19, 26, 21, 7, 23, 43, + 52, 42, 14, 9, -2, -16, -21, -25, -33, -33, -4, 13, 3, -13, -30, -47, + -37, 1, 6, 7, 12, 6, -15, -31, -1, 22, 30, 14, 9, 37, 48, 50, + 26, 8, 6, -11, -22, -22, -25, -45, -22, 13, 15, 1, -22, -43, -56, -21, + 7, 6, 10, 15, -7, -25, -21, 7, 28, 21, 2, 25, 47, 53, 39, 11, + 10, 1, -20, -22, -18, -37, -42, 2, 15, 15, -8, -32, -57, -48, -9, 9, + 5, 14, 8, -14, -20, -13, 17, 33, 8, 9, 37, 52, 55, 25, 7, 8, + -11, -23, -15, -23, -47, -20, 12, 21, 10, -23, -50, -57, -31, 2, 10, 9, + 11, -8, -10, -18, -3, 30, 22, 1, 22, 45, 57, 45, 11, 11, 0, -23, + -22, -16, -36, -36, -6, 15, 18, -3, -43, -56, -49, -21, 5, 11, 12, -2, + -8, -9, -15, 12, 31, 9, 10, 34, 48, 60, 29, 16, 10, -17, -24, -21, + -27, -31, -17, 5, 14, 12, -22, -50, -48, -41, -9, 7, 13, -1, -8, -2, + -11, -5, 26, 19, 6, 21, 37, 55, 49, 25, 22, -5, -20, -24, -26, -29, + -23, -9, 8, 13, -1, -41, -48, -47, -30, -3, 12, 7, -12, -2, 1, -8, + 10, 20, 11, 16, 26, 40, 54, 42, 36, 7, -13, -18, -26, -29, -26, -14, + -2, 7, 8, -18, -45, -48, -45, -19, 6, 11, -10, -8, 5, -7, 2, 12, + 17, 15, 16, 23, 45, 55, 48, 27, -7, -12, -18, -30, -31, -17, -5, -3, + 4, 5, -24, -40, -50, -38, -8, 8, 1, -13, 1, -1, 3, 8, 15, 18, + 15, 15, 28, 52, 59, 47, 9, -9, -10, -25, -40, -29, -3, -5, -13, 1, + 3, -26, -47, -53, -23, -2, 5, -11, -6, 4, 6, 10, 10, 19, 11, 13, + 15, 42, 61, 61, 32, 3, -5, -12, -35, -43, -14, 1, -16, -13, 9, -1, + -33, -57, -46, -19, -3, -1, -16, -2, 5, 15, 6, 17, 9, 5, 9, 26, + 54, 65, 52, 21, 3, -6, -21, -48, -33, -4, -7, -22, -2, 18, -4, -47, + -58, -33, -11, 2, -13, -15, 3, 16, 15, 9, 15, -1, 5, 14, 48, 66, + 65, 37, 23, 2, -11, -42, -48, -20, -4, -23, -18, 18, 19, -17, -61, -52, + -27, -2, -5, -24, -7, 9, 20, 14, 18, 2, -3, 7, 34, 63, 68, 50, + 37, 19, -9, -25, -49, -38, -14, -14, -28, 6, 25, 9, -40, -62, -45, -17, + 3, -21, -16, -3, 12, 18, 18, 10, -6, 0, 16, 56, 69, 63, 43, 38, + 2, -20, -42, -44, -33, -14, -25, -10, 22, 18, -11, -55, -57, -37, -3, -10, + -26, -10, 2, 17, 21, 20, -3, -2, 5, 39, 67, 73, 56, 47, 22, -17, + -35, -43, -36, -28, -18, -20, 9, 22, 8, -33, -56, -53, -26, -2, -23, -24, + -11, 4, 23, 30, 4, -3, 0, 27, 60, 71, 69, 58, 43, -6, -35, -43, + -35, -36, -27, -18, -2, 19, 17, -9, -41, -51, -45, -10, -12, -31, -21, -9, + 8, 33, 17, 0, 2, 8, 50, 69, 75, 70, 64, 16, -31, -47, -35, -32, + -34, -25, -14, 10, 16, 5, -26, -42, -50, -32, -8, -22, -31, -22, -8, 22, + 32, 7, 6, 4, 28, 63, 69, 71, 78, 43, -20, -51, -41, -23, -34, -30, + -22, 2, 13, 9, -10, -31, -45, -44, -21, -19, -27, -36, -26, 2, 29, 24, + 12, 11, 13, 45, 69, 68, 81, 70, 6, -47, -52, -28, -23, -27, -26, -14, + 11, 10, -2, -18, -33, -43, -34, -25, -22, -36, -44, -14, 14, 29, 27, 22, + 18, 29, 60, 65, 71, 86, 41, -32, -57, -41, -23, -22, -22, -24, -4, 10, + 0, -11, -21, -31, -37, -37, -29, -29, -53, -33, -3, 16, 33, 31, 27, 23, + 46, 64, 65, 85, 71, -4, -48, -47, -31, -20, -15, -15, -19, 1, 0, -5, + -14, -21, -26, -40, -39, -28, -51, -50, -18, 4, 26, 38, 36, 30, 32, 61, + 64, 70, 80, 31, -35, -43, -40, -25, -19, -6, -17, -11, 0, -6, -11, -17, + -15, -31, -47, -39, -45, -62, -34, -8, 12, 36, 38, 41, 37, 51, 65, 60, + 71, 56, -7, -36, -38, -35, -27, -11, -5, -17, -8, -8, -9, -17, -13, -20, + -37, -47, -50, -62, -49, -16, 1, 25, 34, 43, 53, 49, 62, 58, 62, 65, + 22, -23, -31, -34, -35, -19, -3, -8, -18, -7, -4, -14, -17, -9, -27, -40, + -56, -68, -64, -27, -4, 9, 28, 37, 54, 60, 61, 59, 54, 63, 43, -1, + -25, -23, -37, -28, -8, 4, -10, -15, -3, -7, -26, -15, -11, -29, -51, -71, + -71, -49, -8, 5, 14, 30, 48, 66, 68, 63, 51, 56, 51, 18, -18, -20, + -25, -39, -23, -5, 3, -13, -6, -5, -21, -28, -10, -18, -43, -67, -78, -64, + -25, 1, 8, 15, 38, 60, 75, 74, 58, 54, 57, 28, -7, -18, -8, -31, + -34, -15, 4, -2, -4, 0, -15, -32, -21, -8, -28, -57, -77, -75, -44, -12, + 6, 8, 20, 49, 68, 77, 71, 53, 61, 41, 3, -18, -4, -14, -36, -28, + -7, 1, 7, 6, -8, -34, -35, -16, -15, -41, -66, -75, -59, -31, -4, 10, + 11, 31, 56, 72, 85, 63, 58, 55, 14, -17, -10, -1, -24, -30, -22, -6, + 11, 16, 9, -27, -43, -27, -15, -26, -53, -63, -66, -46, -21, 3, 13, 15, + 40, 63, 83, 78, 60, 67, 38, -9, -20, 4, -7, -23, -25, -22, 6, 24, + 20, -8, -48, -43, -24, -16, -39, -55, -57, -57, -36, -10, 9, 11, 22, 50, + 73, 88, 71, 65, 59, 14, -24, -9, -3, -15, -18, -31, -14, 25, 28, 10, + -36, -56, -41, -21, -29, -48, -47, -51, -50, -26, -2, 11, 6, 30, 57, 82, + 83, 69, 65, 35, -12, -16, -3, -10, -12, -21, -26, 11, 33, 26, -7, -56, + -54, -32, -26, -41, -39, -37, -52, -41, -16, 5, 7, 11, 37, 72, 91, 78, + 66, 55, 11, -19, -14, -15, -9, -7, -19, -8, 22, 30, 13, -32, -62, -44, + -31, -34, -40, -29, -40, -46, -29, -8, 2, 1, 18, 49, 84, 86, 72, 67, + 39, -6, -21, -25, -16, 2, -6, -12, 6, 23, 18, -7, -51, -56, -39, -33, + -41, -30, -24, -41, -36, -17, -8, -5, 7, 32, 66, 84, 78, 75, 58, 20, + -15, -29, -33, 2, 4, -1, 1, 11, 17, 4, -27, -56, -46, -36, -37, -39, + -22, -24, -38, -23, -16, -16, -7, 18, 46, 72, 82, 81, 72, 44, -1, -25, + -41, -18, 14, 8, 10, 0, 5, 2, -11, -40, -50, -42, -38, -37, -33, -11, + -27, -26, -20, -22, -13, 0, 31, 52, 73, 82, 80, 61, 26, -16, -37, -40, + 0, 18, 17, 12, -5, -8, -10, -21, -41, -43, -44, -36, -35, -20, -12, -23, + -14, -32, -21, -12, 15, 38, 58, 76, 82, 72, 46, 4, -26, -41, -23, 14, + 25, 18, 2, -23, -18, -14, -29, -35, -45, -42, -35, -29, -15, -19, -3, -23, + -32, -19, -1, 27, 40, 67, 81, 76, 61, 26, -11, -33, -36, -6, 28, 28, + 13, -15, -38, -19, -20, -26, -36, -46, -35, -32, -20, -21, -4, -4, -28, -25, + -16, 13, 31, 49, 74, 79, 69, 48, 8, -16, -33, -21, 7, 33, 24, 5, + -32, -38, -22, -21, -22, -41, -43, -32, -25, -23, -16, 6, -9, -29, -28, -5, + 20, 39, 58, 75, 71, 60, 22, 0, -18, -27, -10, 16, 30, 15, -14, -49, + -34, -19, -16, -27, -43, -31, -25, -27, -24, -1, 7, -15, -32, -22, 3, 28, + 50, 61, 67, 59, 38, 13, 5, -17, -16, -3, 21, 23, 3, -34, -49, -28, + -17, -19, -34, -34, -18, -26, -32, -16, 14, 6, -23, -34, -11, 14, 44, 54, + 56, 60, 44, 25, 18, 2, -18, -9, 3, 21, 9, -14, -45, -39, -24, -22, + -28, -32, -18, -17, -36, -30, 5, 21, -5, -31, -27, 1, 30, 56, 46, 50, + 47, 32, 29, 20, -4, -9, -9, 4, 10, -2, -28, -38, -31, -33, -26, -26, + -19, -9, -24, -38, -11, 24, 10, -17, -36, -14, 14, 48, 49, 37, 43, 39, + 33, 32, 11, 1, -5, -11, -6, -3, -16, -29, -28, -40, -38, -27, -20, -6, + -11, -31, -29, 15, 22, 0, -25, -25, 2, 31, 51, 38, 35, 41, 41, 34, + 27, 8, 6, -7, -20, -14, -7, -20, -19, -34, -52, -35, -23, -11, -5, -18, + -33, -5, 26, 5, -11, -27, -11, 17, 43, 43, 30, 29, 46, 45, 38, 17, + 6, 2, -22, -27, -16, -16, -18, -18, -53, -48, -23, -19, -3, -10, -21, -19, + 18, 12, -6, -20, -21, 6, 29, 42, 31, 23, 37, 54, 48, 31, 13, 13, + -13, -31, -25, -16, -16, -11, -38, -62, -33, -28, -7, -3, -12, -17, 6, 16, + 2, -11, -17, -5, 15, 35, 34, 25, 23, 44, 55, 41, 22, 14, 2, -29, + -32, -23, -11, -13, -18, -60, -50, -32, -16, -6, -11, -4, 3, 11, 3, -1, + -14, -8, 5, 20, 39, 31, 24, 26, 54, 57, 37, 16, 8, -19, -32, -27, + -17, -17, -17, -36, -58, -40, -32, -11, -11, -2, 6, 10, 2, 0, -4, -12, + 1, 8, 33, 42, 26, 17, 35, 63, 53, 26, 6, -9, -27, -30, -25, -17, + -23, -24, -47, -51, -38, -17, -11, -6, 12, 17, 8, -8, -1, -10, -7, 4, + 18, 40, 33, 18, 22, 49, 70, 46, 12, -11, -16, -23, -27, -19, -28, -26, + -36, -50, -48, -31, -13, -13, 10, 20, 21, 0, -6, -1, -7, 3, 15, 32, + 40, 24, 17, 31, 58, 67, 28, -2, -21, -14, -31, -18, -24, -33, -33, -49, + -49, -41, -18, -20, -2, 20, 23, 19, -12, -7, -2, -3, 10, 22, 33, 37, + 21, 23, 39, 72, 51, 10, -17, -18, -20, -29, -17, -33, -36, -49, -48, -47, + -24, -16, -15, 11, 24, 30, 6, -12, -2, -2, -1, 18, 29, 35, 27, 25, + 25, 56, 63, 23, -5, -19, -14, -23, -21, -21, -38, -52, -54, -40, -32, -15, + -23, -7, 18, 31, 22, -2, -7, 3, 0, 12, 21, 34, 31, 28, 22, 35, + 66, 40, 2, -19, -19, -15, -21, -16, -30, -60, -62, -42, -33, -18, -18, -22, + 4, 29, 29, 14, -2, -4, 5, 6, 16, 28, 36, 24, 29, 26, 52, 49, + 14, -13, -24, -19, -14, -15, -17, -53, -75, -54, -32, -18, -11, -26, -18, 18, + 28, 25, 13, -6, 4, 13, 9, 17, 37, 24, 28, 33, 37, 49, 26, 1, + -19, -26, -16, -11, -7, -33, -77, -71, -45, -15, -8, -18, -30, 1, 25, 21, + 26, 3, 5, 17, 14, 11, 33, 27, 17, 34, 38, 42, 33, 6, -11, -28, + -22, -12, -3, -16, -60, -81, -62, -25, -2, -14, -27, -17, 20, 18, 24, 18, + 6, 16, 21, 12, 24, 28, 12, 26, 44, 42, 35, 13, -5, -21, -31, -18, + -2, -2, -42, -77, -76, -47, -10, -6, -22, -24, 4, 16, 18, 25, 18, 18, + 24, 20, 20, 32, 14, 11, 40, 49, 41, 21, -6, -13, -27, -28, -5, 5, + -18, -59, -79, -63, -30, -6, -11, -28, -11, 8, 10, 23, 27, 17, 24, 25, + 25, 28, 19, 8, 25, 47, 46, 27, -5, -15, -18, -33, -20, -5, -3, -35, + -70, -66, -51, -22, -7, -21, -19, -3, 6, 17, 29, 26, 23, 28, 25, 32, + 23, 14, 11, 39, 50, 38, 3, -19, -10, -21, -29, -12, -3, -12, -55, -65, + -56, -42, -14, -10, -23, -11, -3, 10, 23, 32, 26, 28, 28, 35, 29, 22, + 13, 18, 41, 43, 18, -16, -18, -14, -29, -21, -11, -8, -32, -61, -52, -52, + -30, -11, -18, -16, -10, 2, 22, 35, 30, 25, 32, 34, 40, 27, 19, 11, + 23, 39, 32, -1, -22, -14, -22, -23, -14, -11, -17, -45, -52, -51, -51, -22, + -17, -19, -17, -10, 11, 35, 39, 29, 26, 34, 43, 43, 27, 16, 12, 25, + 31, 18, -13, -20, -19, -22, -12, -14, -15, -28, -44, -47, -53, -33, -15, -22, + -24, -20, 5, 27, 38, 31, 21, 27, 46, 51, 40, 18, 8, 13, 23, 24, + 3, -21, -22, -22, -8, -9, -22, -26, -31, -40, -51, -44, -17, -15, -26, -31, + -10, 24, 35, 37, 25, 21, 42, 57, 53, 30, 11, 7, 11, 21, 12, -11, + -23, -25, -12, 0, -18, -32, -31, -30, -45, -46, -26, -13, -25, -39, -25, 15, + 36, 29, 25, 20, 37, 58, 63, 46, 15, 3, -2, 19, 16, -2, -19, -25, + -23, 4, -4, -31, -36, -29, -32, -43, -37, -17, -16, -39, -43, -2, 34, 31, + 21, 17, 30, 62, 67, 62, 27, 9, -9, 3, 26, 8, -18, -26, -26, -5, + 9, -23, -44, -33, -26, -33, -40, -28, -12, -30, -52, -24, 23, 33, 15, 14, + 22, 54, 75, 68, 47, 14, -9, -12, 19, 23, -12, -20, -20, -13, 11, -6, + -40, -41, -19, -23, -34, -34, -14, -13, -48, -48, 4, 35, 23, 7, 13, 40, + 77, 78, 57, 31, -3, -18, 3, 27, 7, -24, -19, -16, 1, 5, -29, -49, + -28, -13, -26, -34, -26, -4, -30, -57, -24, 22, 30, 6, 7, 31, 63, 86, + 68, 42, 10, -19, -13, 15, 25, -10, -22, -14, -7, 6, -11, -45, -40, -14, + -24, -35, -31, -12, -8, -51, -44, -2, 29, 11, -1, 22, 47, 74, 78, 49, + 25, -8, -26, -4, 26, 12, -16, -19, -11, -1, -1, -28, -45, -22, -13, -29, + -29, -23, -1, -26, -55, -26, 14, 20, -3, 13, 39, 63, 80, 61, 33, 8, + -22, -25, 10, 22, -1, -14, -15, -7, -1, -14, -37, -26, -13, -25, -28, -26, + -2, -5, -48, -44, -7, 18, 3, 9, 30, 49, 71, 70, 45, 23, -13, -33, + -5, 22, 11, -7, -17, -14, -6, -8, -29, -29, -15, -19, -26, -31, -15, 6, + -25, -52, -30, 7, 7, 2, 21, 40, 60, 67, 52, 33, 7, -29, -19, 16, + 22, 4, -8, -15, -11, -6, -23, -24, -10, -11, -23, -27, -22, 1, 0, -34, + -45, -14, 2, 1, 15, 35, 52, 62, 49, 36, 21, -16, -26, 1, 20, 12, + -7, -10, -20, -10, -19, -28, -9, -8, -15, -26, -27, -11, 2, -15, -41, -34, + -10, -7, 6, 32, 48, 56, 51, 35, 26, 1, -24, -10, 15, 18, 2, -9, + -17, -18, -11, -32, -6, 2, -9, -18, -22, -17, -3, -2, -21, -34, -26, -13, + -8, 20, 47, 53, 52, 38, 24, 5, -14, -15, 9, 14, 4, -6, -14, -21, + -14, -28, -22, 12, 0, -10, -23, -24, -13, 2, -10, -23, -34, -26, -13, 4, + 39, 58, 51, 45, 28, 6, -9, -11, 3, 17, 7, -3, -10, -18, -15, -22, + -35, 2, 18, 2, -11, -23, -20, -1, 0, -15, -24, -39, -25, -6, 17, 52, + 56, 47, 35, 6, -10, -8, 0, 13, 13, -2, -9, -13, -13, -25, -43, -16, + 21, 19, -3, -21, -25, -10, 2, -5, -14, -30, -40, -13, -1, 34, 58, 51, + 44, 18, -10, -9, -2, 6, 12, 7, -7, -12, -12, -18, -40, -33, 9, 32, + 19, -9, -23, -15, 1, 3, -9, -18, -40, -28, -4, 7, 47, 59, 49, 24, + 1, -13, -5, 1, 10, 11, 5, -12, -12, -15, -35, -42, -9, 23, 33, 9, + -22, -24, -5, 1, -5, -12, -30, -40, -7, -3, 22, 56, 58, 35, 11, -12, + -9, -5, -1, 7, 13, -4, -13, -13, -25, -43, -29, 10, 34, 32, -6, -27, + -8, 3, -5, -13, -22, -40, -18, -3, -1, 37, 61, 46, 23, -5, -13, -4, + -4, -7, 12, 14, -10, -18, -22, -34, -35, -10, 22, 39, 23, -15, -14, 5, + 3, -8, -15, -36, -23, -1, -7, 14, 51, 57, 37, 8, -13, -7, -2, -14, + -6, 20, 3, -21, -26, -27, -30, -27, 1, 28, 36, 7, -10, 0, 5, -8, + -14, -30, -29, -3, -10, -5, 31, 56, 46, 19, -7, -10, 3, -11, -21, 9, + 19, -10, -30, -29, -19, -24, -20, 10, 35, 29, 8, -1, 5, -2, -13, -28, + -33, -3, -1, -13, 12, 49, 55, 31, -1, -12, 2, -3, -26, -2, 21, 2, + -28, -34, -21, -17, -29, -12, 23, 34, 19, 6, 7, 4, -4, -23, -40, -10, + 7, -12, -2, 34, 55, 36, 8, -10, 1, 3, -19, -18, 15, 15, -10, -33, + -30, -9, -19, -25, 4, 32, 30, 16, 11, 10, 3, -15, -35, -27, 9, -4, + -10, 16, 52, 42, 12, -7, -6, 4, -6, -21, -2, 17, 0, -20, -41, -13, + -9, -31, -16, 18, 34, 23, 14, 9, 10, -7, -26, -34, -3, 10, -10, 2, + 42, 51, 16, -8, -11, -2, -2, -11, -9, 9, 2, -8, -36, -31, 3, -23, + -30, -1, 27, 27, 23, 15, 18, 3, -17, -31, -19, 8, 1, -4, 24, 51, + 30, -11, -16, -6, -3, -5, -10, 3, 1, -10, -22, -41, -4, -6, -29, -18, + 12, 25, 26, 23, 20, 11, -10, -21, -27, -4, 7, 0, 13, 41, 40, 3, + -24, -11, -1, -2, -3, 5, 5, -14, -15, -35, -20, 0, -19, -24, -4, 11, + 23, 31, 24, 16, -3, -13, -23, -14, 2, 3, 18, 32, 38, 21, -20, -29, + -5, -2, 0, 5, 11, -14, -22, -25, -26, -3, -11, -26, -11, -2, 8, 32, + 34, 24, 2, -8, -16, -13, 1, 1, 10, 31, 31, 33, 1, -36, -22, 0, + 0, 8, 18, -3, -27, -22, -22, -10, -9, -24, -16, -5, -16, 16, 40, 34, + 8, -3, -13, -12, 1, 1, 3, 30, 30, 24, 18, -28, -35, -13, -2, 6, + 19, 10, -25, -28, -15, -9, -10, -19, -20, -3, -15, -8, 27, 42, 25, 1, + -14, -18, 7, 9, -1, 19, 37, 19, 23, -10, -41, -26, -9, 2, 20, 19, + -17, -35, -21, 0, -9, -18, -20, -7, -8, -24, 6, 37, 43, 14, -10, -22, + 3, 18, 4, 6, 36, 23, 16, 4, -32, -37, -19, -3, 17, 27, 0, -37, + -34, -3, 7, -17, -27, -19, -1, -20, -13, 17, 44, 35, 2, -22, -9, 19, + 20, 2, 26, 32, 15, 5, -17, -40, -29, -9, 10, 28, 17, -23, -41, -21, + 9, -2, -27, -30, -5, -7, -21, -4, 27, 47, 27, -14, -21, 11, 29, 14, + 15, 32, 20, 4, -11, -31, -38, -15, 2, 22, 22, -3, -32, -34, -6, 8, + -13, -38, -19, 0, -16, -14, 6, 37, 39, 11, -18, -4, 25, 25, 16, 24, + 27, 7, -10, -24, -38, -25, 0, 12, 23, 8, -16, -31, -23, 0, 0, -27, + -33, -2, -9, -16, -11, 17, 41, 32, 5, -15, 12, 25, 24, 21, 27, 14, + -4, -21, -31, -29, -4, 9, 19, 9, -9, -19, -25, -10, -5, -15, -38, -13, + -6, -13, -17, -1, 30, 36, 27, -2, 2, 20, 24, 25, 24, 19, 2, -16, + -32, -29, -13, 8, 18, 16, -6, -13, -21, -15, -14, -13, -26, -22, -6, -11, + -14, -14, 11, 30, 37, 17, 1, 13, 20, 23, 24, 21, 5, -10, -32, -31, + -15, 0, 17, 22, -3, -15, -17, -11, -15, -19, -23, -22, -8, -8, -13, -18, + -8, 18, 40, 38, 12, 12, 15, 21, 23, 24, 7, -9, -22, -34, -19, -6, + 11, 30, 9, -17, -20, -16, -11, -22, -30, -27, -8, -7, -10, -19, -16, -2, + 32, 52, 31, 17, 16, 13, 21, 19, 19, -9, -17, -30, -25, -7, 3, 29, + 25, -9, -21, -20, -11, -14, -29, -37, -14, 2, -5, -14, -22, -12, 13, 50, + 49, 27, 23, 15, 13, 9, 18, 7, -22, -22, -28, -11, -5, 19, 35, 13, + -20, -24, -18, -8, -22, -38, -31, 2, 3, -6, -26, -22, -3, 38, 56, 42, + 34, 21, 12, 6, 11, 17, -15, -24, -20, -15, -6, 9, 29, 29, -4, -28, + -23, -14, -13, -30, -39, -16, 9, 6, -12, -33, -16, 19, 57, 49, 41, 30, + 13, 4, -1, 6, -4, -27, -21, -13, -6, 2, 12, 34, 12, -24, -24, -20, + -16, -24, -38, -33, 2, 12, -2, -30, -31, 2, 45, 59, 46, 41, 24, 8, + -3, -6, 1, -15, -25, -16, -3, 5, 2, 21, 28, -11, -26, -23, -18, -20, + -32, -40, -14, 14, 11, -10, -40, -20, 30, 60, 55, 42, 34, 15, 6, -12, + -12, -4, -19, -21, -9, 8, 4, 10, 28, 6, -25, -22, -20, -22, -29, -38, + -27, 5, 16, 4, -24, -39, 12, 51, 61, 51, 41, 27, 10, -7, -25, -9, + -10, -17, -15, 0, 9, 5, 21, 15, -13, -27, -17, -21, -23, -38, -33, -11, + 10, 6, -4, -38, -17, 36, 55, 55, 45, 35, 21, 4, -27, -25, -2, -10, + -14, -13, 3, 5, 14, 16, 0, -24, -21, -18, -22, -36, -39, -17, -3, 5, + 3, -15, -28, 16, 50, 53, 52, 43, 29, 13, -14, -36, -10, -1, -15, -15, + -6, 6, 5, 13, 4, -11, -24, -17, -18, -27, -43, -18, -12, -7, 4, 3, + -17, -4, 38, 53, 52, 48, 41, 23, 0, -31, -30, 2, -7, -14, -13, -5, + 3, 11, 7, -4, -21, -25, -21, -19, -39, -23, -9, -19, -8, 5, -1, -10, + 24, 46, 48, 46, 44, 32, 10, -18, -37, -7, 0, -12, -14, -13, -4, 8, + 9, 1, -16, -29, -28, -17, -33, -31, -6, -21, -21, -4, 12, 3, 13, 41, + 46, 44, 46, 44, 20, -7, -36, -27, 6, -3, -18, -21, -12, 2, 12, 6, + -5, -27, -36, -21, -20, -34, -12, -8, -29, -16, 11, 15, 10, 28, 47, 46, + 41, 45, 35, 5, -24, -30, -5, 3, -14, -26, -16, -7, 7, 8, -3, -18, + -39, -32, -16, -28, -26, -8, -23, -26, 0, 19, 16, 20, 42, 55, 45, 38, + 39, 20, -11, -24, -13, -2, -6, -25, -22, -7, -5, 13, 0, -11, -36, -41, + -20, -16, -29, -16, -14, -28, -12, 13, 17, 15, 32, 50, 57, 41, 38, 30, + 2, -14, -9, -3, -3, -19, -33, -10, -7, 7, 7, -13, -30, -42, -28, -13, + -17, -26, -14, -22, -15, 7, 19, 15, 26, 46, 59, 51, 34, 33, 12, -7, + -11, -4, -5, -13, -38, -23, -3, 3, 15, -7, -32, -45, -34, -21, -11, -27, + -25, -21, -19, -1, 13, 15, 22, 37, 53, 62, 46, 34, 15, -2, 0, -4, + -8, -9, -34, -38, -8, 4, 17, 3, -25, -50, -44, -26, -12, -13, -32, -24, + -20, -7, 11, 18, 17, 33, 50, 65, 57, 41, 24, 0, 5, 5, -9, -11, + -25, -44, -25, -1, 17, 13, -18, -42, -51, -33, -20, -7, -27, -29, -23, -16, + 0, 14, 14, 28, 48, 60, 66, 51, 34, 4, 0, 15, -3, -14, -20, -35, + -37, -12, 12, 27, -7, -37, -50, -40, -29, -15, -15, -30, -24, -15, -7, 6, + 17, 25, 46, 59, 68, 63, 43, 20, -6, 14, 10, -8, -20, -30, -34, -22, + -2, 24, 15, -30, -49, -49, -37, -28, -15, -26, -28, -18, -11, -7, 7, 27, + 42, 58, 70, 70, 53, 35, 4, 0, 18, -1, -15, -32, -31, -26, -12, 12, + 28, -4, -44, -53, -44, -39, -25, -23, -28, -19, -11, -12, -16, 13, 42, 56, + 71, 71, 57, 45, 23, -3, 10, 11, -6, -27, -35, -25, -22, -1, 23, 17, + -29, -54, -46, -44, -39, -29, -28, -21, -15, -15, -26, -12, 39, 57, 70, 73, + 60, 49, 41, 13, 1, 11, 0, -16, -32, -25, -15, -14, 10, 23, -5, -48, + -46, -42, -49, -43, -31, -24, -15, -13, -24, -32, 18, 59, 71, 77, 67, 57, + 47, 33, 3, 5, 5, -9, -23, -33, -16, -14, -5, 17, 12, -29, -44, -35, + -50, -57, -43, -30, -18, -11, -22, -39, -9, 44, 68, 82, 69, 61, 49, 42, + 18, 5, 5, -8, -12, -26, -14, -7, -9, 5, 16, -6, -36, -32, -42, -62, + -55, -39, -29, -15, -14, -34, -30, 20, 59, 82, 79, 66, 58, 45, 38, 9, + 1, -7, -11, -16, -19, -3, -6, -6, 9, 5, -22, -32, -32, -58, -70, -56, + -42, -24, -16, -25, -39, -9, 41, 72, 86, 73, 65, 46, 40, 30, -4, -7, + -14, -12, -20, -3, 4, -5, 1, 8, -9, -27, -25, -40, -67, -67, -55, -38, + -24, -17, -25, -28, 16, 61, 81, 82, 71, 60, 37, 42, 17, -14, -17, -11, + -13, -8, 10, 2, -2, 1, -1, -17, -20, -26, -54, -69, -70, -58, -34, -25, + -16, -23, -9, 37, 70, 87, 80, 68, 44, 38, 39, -5, -27, -19, -12, -6, + 13, 10, 4, 1, 1, -5, -19, -20, -37, -59, -71, -71, -54, -35, -17, -9, + -20, 11, 49, 80, 86, 72, 54, 36, 45, 23, -25, -34, -16, -9, 11, 17, + 8, 5, -4, -2, -15, -19, -26, -50, -69, -77, -71, -51, -29, -7, -11, -6, + 26, 64, 87, 78, 60, 40, 42, 45, 2, -38, -34, -12, 10, 24, 10, 11, + 3, -1, -6, -20, -16, -31, -61, -81, -80, -69, -41, -16, -5, -8, 10, 47, + 81, 86, 70, 44, 36, 48, 32, -21, -48, -31, -3, 24, 24, 10, 15, 0, + 2, -17, -21, -18, -45, -81, -87, -80, -57, -33, -11, -6, 2, 30, 74, 86, + 77, 55, 34, 42, 48, 13, -39, -50, -20, 15, 34, 14, 16, 12, 4, -5, + -26, -16, -19, -64, -92, -91, -65, -43, -26, -12, -1, 16, 47, 83, 76, 66, + 40, 33, 45, 33, -8, -52, -41, -5, 32, 30, 15, 25, 13, 8, -22, -28, + -11, -34, -85, -101, -86, -52, -36, -25, -13, 15, 32, 69, 80, 69, 52, 32, + 37, 39, 19, -30, -54, -24, 10, 38, 25, 25, 22, 18, -6, -35, -20, -14, + -59, -98, -99, -68, -41, -30, -23, 5, 28, 52, 74, 67, 59, 43, 32, 35, + 32, -2, -47, -38, -13, 23, 33, 31, 26, 27, 16, -29, -37, -15, -33, -80, + -104, -89, -54, -35, -31, -11, 17, 42, 63, 68, 60, 59, 37, 27, 33, 22, + -28, -37, -26, 3, 32, 38, 30, 25, 30, -3, -41, -29, -23, -55, -90, -98, + -76, -39, -32, -21, 4, 36, 52, 61, 61, 63, 48, 24, 28, 34, -10, -31, + -29, -14, 15, 37, 37, 28, 31, 19, -27, -40, -24, -38, -69, -95, -96, -60, + -32, -26, -10, 19, 45, 53, 58, 59, 58, 29, 23, 39, 14, -21, -25, -23, + 1, 27, 43, 34, 34, 21, 0, -36, -32, -31, -49, -84, -102, -83, -41, -22, + -19, -1, 35, 49, 52, 53, 56, 39, 23, 34, 33, -3, -23, -22, -10, 17, + 36, 36, 39, 26, 8, -16, -34, -29, -36, -61, -93, -95, -58, -26, -18, -11, + 22, 48, 53, 53, 51, 41, 31, 33, 37, 16, -15, -24, -14, 4, 29, 34, + 41, 32, 8, -7, -19, -28, -30, -54, -83, -101, -76, -40, -20, -21, 1, 36, + 54, 55, 44, 33, 32, 35, 36, 30, 7, -26, -19, -5, 22, 36, 37, 37, + 15, -3, -5, -15, -24, -43, -75, -94, -87, -47, -29, -25, -14, 26, 48, 62, + 49, 29, 23, 35, 45, 38, 19, -16, -28, -7, 10, 29, 32, 38, 23, -2, + -10, -6, -12, -28, -67, -90, -98, -59, -32, -28, -25, 3, 43, 56, 59, 25, + 16, 24, 46, 43, 31, 0, -31, -14, 5, 25, 29, 32, 29, 6, -13, -6, + -3, -8, -49, -85, -97, -75, -31, -30, -30, -12, 31, 50, 61, 40, 12, 14, + 34, 53, 43, 20, -23, -20, -3, 21, 29, 23, 24, 15, -10, -8, -1, 2, + -25, -75, -98, -92, -42, -31, -35, -24, 14, 41, 50, 49, 22, 11, 20, 45, + 52, 39, 0, -26, -12, 9, 35, 25, 18, 14, 1, -13, -6, 4, 3, -49, + -89, -102, -61, -27, -30, -27, -4, 34, 46, 46, 32, 17, 13, 26, 47, 50, + 29, -19, -22, -4, 30, 37, 15, 7, 7, -5, -10, -4, 9, -20, -72, -100, + -86, -41, -33, -31, -16, 18, 43, 34, 32, 27, 23, 15, 31, 47, 48, 9, + -24, -16, 12, 43, 25, -2, 0, 9, -9, -15, 2, 8, -40, -87, -99, -69, + -37, -31, -19, 6, 38, 35, 25, 31, 35, 26, 18, 36, 49, 40, -10, -22, + -9, 29, 40, 6, -12, 6, 6, -16, -11, 9, -6, -61, -95, -90, -58, -35, + -26, -5, 23, 36, 18, 21, 36, 41, 28, 22, 38, 52, 23, -17, -17, 7, + 39, 21, -12, -13, 16, -8, -22, -5, 6, -25, -77, -93, -79, -46, -30, -11, + 15, 36, 22, 5, 29, 47, 47, 24, 22, 41, 48, 7, -15, -4, 22, 33, + 6, -23, 4, 8, -21, -15, -1, -5, -49, -79, -92, -71, -43, -20, 11, 31, + 29, 4, 16, 40, 55, 41, 22, 31, 50, 25, -9, -2, 8, 23, 16, -17, + -6, 8, -10, -15, -6, -4, -29, -56, -80, -86, -61, -42, 0, 30, 33, 12, + 2, 24, 47, 55, 37, 28, 39, 40, 4, -1, 6, 6, 16, -4, -13, 1, + -2, -9, -11, -11, -21, -35, -55, -82, -80, -64, -24, 27, 36, 23, 3, 10, + 35, 61, 55, 40, 35, 35, 19, 6, 12, 4, 1, 3, -12, -3, -2, -4, + -4, -14, -23, -30, -37, -58, -83, -84, -58, 8, 37, 33, 11, 3, 20, 46, + 62, 55, 50, 28, 16, 12, 15, 9, -4, -9, -9, -4, -5, -7, 2, -7, + -28, -35, -31, -36, -67, -90, -86, -23, 28, 38, 25, 5, 13, 34, 58, 58, + 69, 50, 15, 10, 20, 16, -3, -14, -14, -2, 1, -12, -3, 3, -20, -36, + -39, -26, -46, -81, -98, -61, 6, 27, 30, 16, 12, 25, 50, 57, 66, 74, + 31, 4, 16, 21, 8, -13, -21, -10, 8, -5, -11, 6, -8, -31, -40, -29, + -30, -66, -93, -84, -22, 17, 22, 26, 16, 20, 43, 56, 56, 70, 60, 17, + 8, 18, 15, -10, -26, -21, 6, 7, -12, -1, 1, -20, -33, -34, -31, -51, + -79, -92, -52, -6, 9, 19, 23, 21, 40, 57, 59, 60, 72, 43, 17, 13, + 18, 3, -23, -32, -5, 14, -7, -11, 7, -12, -26, -31, -37, -46, -66, -85, + -67, -21, -5, 3, 16, 22, 37, 54, 59, 55, 60, 58, 30, 16, 13, 11, + -15, -34, -23, 9, 7, -12, -2, -4, -19, -16, -31, -49, -64, -76, -72, -35, + -12, -14, 0, 15, 34, 53, 60, 58, 53, 57, 43, 30, 18, 12, -4, -27, + -28, -8, 14, -3, -9, -2, -13, -9, -17, -49, -66, -70, -69, -44, -15, -19, + -11, 2, 21, 53, 64, 68, 55, 48, 44, 36, 28, 15, -1, -18, -23, -19, + -4, 5, -3, 1, -9, -7, -1, -35, -70, -74, -70, -50, -21, -14, -22, -7, + -1, 39, 66, 77, 69, 46, 38, 36, 38, 22, 5, -12, -16, -12, -17, -8, + -5, 2, 1, -6, 5, -13, -64, -78, -73, -60, -31, -14, -17, -16, -10, 7, + 61, 79, 81, 57, 38, 28, 32, 24, 9, -4, -10, -4, -11, -20, -13, -2, + 11, 4, 4, -2, -41, -76, -76, -69, -43, -22, -12, -17, -14, -14, 25, 74, + 92, 79, 47, 31, 26, 26, 11, 3, -5, 0, 0, -20, -26, -11, 9, 14, + 9, 4, -24, -61, -76, -74, -53, -30, -13, -8, -12, -25, -8, 51, 90, 93, + 63, 42, 21, 18, 13, 6, 2, 1, 8, -12, -30, -27, -2, 14, 18, 11, + -13, -48, -68, -79, -70, -44, -19, -2, -5, -21, -31, 18, 77, 100, 81, 55, + 29, 7, 8, 6, 7, 4, 14, 0, -26, -34, -13, 9, 16, 17, 1, -35, + -58, -70, -82, -62, -29, -2, 1, -14, -36, -15, 50, 89, 95, 71, 46, 5, + -6, 4, 11, 3, 11, 14, -12, -31, -22, -2, 8, 16, 16, -15, -53, -56, + -80, -81, -41, -5, 9, -3, -30, -34, 17, 73, 97, 86, 63, 25, -12, -6, + 11, 13, 1, 15, 4, -19, -25, -5, 2, 9, 19, 10, -39, -48, -61, -95, + -67, -17, 12, 8, -23, -43, -9, 49, 85, 91, 76, 50, 1, -23, 2, 22, + 5, 2, 14, -5, -23, -12, 0, -2, 13, 17, -15, -48, -43, -83, -88, -38, + 5, 17, -11, -41, -28, 27, 67, 83, 82, 65, 29, -21, -18, 21, 19, -7, + 3, 6, -8, -14, 1, 0, 0, 13, 2, -34, -42, -59, -99, -63, -12, 17, + 0, -35, -42, 1, 53, 69, 79, 72, 53, -1, -34, 2, 32, 3, -8, 1, + 2, -2, -3, 8, -2, 3, 7, -18, -40, -39, -76, -81, -35, 9, 17, -22, + -46, -24, 34, 59, 68, 74, 66, 27, -26, -22, 31, 24, -10, -11, 0, 14, + 1, 5, 8, -5, -2, -10, -34, -35, -48, -77, -59, -13, 20, -4, -37, -35, + 8, 47, 55, 68, 74, 49, -4, -34, 10, 39, 1, -13, -11, 14, 14, 3, + 20, 6, -9, -14, -29, -37, -28, -56, -66, -42, 9, 9, -25, -38, -14, 27, + 45, 54, 72, 61, 21, -25, -14, 31, 19, -10, -15, -2, 22, 6, 22, 24, + -4, -20, -28, -38, -24, -28, -54, -57, -20, 14, -10, -29, -26, 2, 29, 39, + 61, 66, 39, -6, -25, 16, 30, 0, -16, -8, 12, 13, 18, 38, 10, -20, + -36, -34, -31, -16, -33, -56, -42, 0, 0, -21, -22, -12, 11, 25, 49, 68, + 53, 14, -20, -3, 29, 15, -11, -12, 3, 13, 13, 42, 34, -12, -39, -37, + -27, -22, -18, -44, -50, -21, 3, -12, -15, -18, -5, 9, 27, 60, 60, 32, + -6, -12, 21, 25, -4, -12, -2, 7, 8, 33, 53, 8, -37, -41, -25, -22, + -16, -27, -47, -34, -10, -10, -15, -15, -15, -5, 5, 41, 63, 44, 12, -11, + 10, 32, 10, -14, -8, 8, 5, 19, 53, 34, -24, -43, -25, -14, -15, -19, + -35, -35, -20, -12, -8, -14, -17, -19, -13, 19, 55, 53, 22, -8, 4, 31, + 26, -8, -13, 6, 10, 7, 39, 50, -2, -41, -31, -10, -13, -23, -31, -33, + -24, -15, -7, -13, -16, -22, -23, -6, 38, 55, 34, 1, -1, 23, 34, 9, + -18, -3, 14, 9, 20, 51, 24, -28, -37, -6, 2, -20, -30, -27, -21, -22, + -6, -12, -17, -21, -32, -27, 9, 49, 43, 12, -4, 14, 34, 24, -9, -12, + 12, 19, 13, 30, 37, -3, -35, -15, 12, -10, -31, -30, -15, -18, -13, -3, + -19, -20, -31, -35, -17, 28, 44, 22, 0, 7, 28, 27, 5, -15, 1, 20, + 20, 17, 28, 19, -21, -23, 12, 8, -22, -32, -20, -8, -15, 0, -13, -23, + -25, -43, -36, 4, 37, 30, 11, 4, 22, 28, 15, 0, -10, 9, 23, 14, + 11, 24, 5, -21, 2, 17, -8, -27, -27, -7, -10, -6, -1, -20, -26, -39, + -53, -20, 23, 36, 17, 7, 14, 28, 16, 12, -3, 2, 19, 16, 2, 14, + 19, -8, -5, 17, 4, -15, -26, -10, -4, -12, 1, -8, -23, -38, -58, -41, + 0, 29, 23, 11, 16, 21, 15, 9, 11, -6, 11, 20, 4, 3, 24, 5, + -5, 10, 17, -6, -15, -15, 6, -15, -8, 0, -11, -37, -54, -56, -24, 13, + 29, 12, 15, 20, 19, 6, 16, 5, -2, 10, 11, -3, 22, 18, 0, 6, + 20, 10, -6, -12, 1, -6, -23, 0, 1, -23, -56, -60, -43, -10, 19, 22, + 15, 22, 18, 6, 11, 17, -2, -5, 10, 4, 7, 23, 1, 3, 16, 22, + 5, -1, 0, 5, -21, -14, 6, -6, -46, -64, -54, -29, 1, 17, 18, 24, + 25, 10, 1, 17, 9, -8, -1, 15, 6, 20, 11, 2, 14, 25, 16, 9, + 5, 7, -11, -26, -5, 4, -27, -62, -62, -40, -17, 8, 11, 21, 29, 17, + -2, 10, 17, -8, -16, 6, 13, 11, 15, 3, 8, 24, 26, 14, 12, 12, + 4, -26, -15, 1, -12, -50, -64, -48, -27, -10, 5, 8, 32, 31, 1, -1, + 18, 0, -23, -6, 18, 14, 11, 5, 3, 17, 35, 25, 16, 18, 14, -11, + -27, -8, -6, -30, -55, -53, -36, -20, -5, 5, 14, 43, 13, -6, 11, 11, + -22, -22, 7, 19, 13, 10, 1, 7, 30, 36, 22, 23, 23, 6, -28, -20, + -6, -23, -43, -49, -43, -29, -19, 3, 1, 34, 29, -4, 3, 13, -13, -32, + -3, 20, 14, 11, 5, 2, 23, 42, 34, 22, 23, 21, -13, -26, -14, -19, + -32, -38, -43, -32, -29, -6, 4, 16, 35, 9, -4, 11, 0, -33, -22, 9, + 13, 12, 9, 3, 14, 35, 47, 34, 23, 27, 8, -22, -19, -16, -30, -29, + -42, -33, -32, -23, 4, 9, 24, 20, -1, 3, 10, -20, -36, -5, 13, 9, + 11, 8, 8, 21, 43, 48, 27, 22, 23, -7, -25, -20, -28, -25, -31, -36, + -28, -33, -8, 11, 14, 14, 6, -8, 7, -5, -39, -25, 7, 14, 9, 10, + 12, 15, 29, 55, 41, 23, 22, 9, -12, -23, -28, -24, -23, -34, -26, -31, + -21, 9, 19, 9, 1, -3, -1, 7, -32, -38, -9, 13, 11, 9, 11, 14, + 21, 46, 53, 32, 24, 12, -2, -16, -26, -24, -17, -34, -33, -25, -24, -4, + 17, 14, -3, -4, -7, 3, -13, -46, -25, 2, 17, 5, 8, 12, 18, 32, + 56, 38, 29, 15, 8, -4, -22, -30, -14, -22, -42, -25, -15, -10, 6, 17, + 1, -5, -7, -10, -2, -38, -37, -7, 15, 9, 2, 8, 21, 26, 43, 44, + 29, 18, 7, 12, -9, -25, -24, -11, -35, -43, -17, -5, 3, 10, 9, -3, + -3, -23, -9, -23, -45, -22, 7, 15, 2, 4, 17, 33, 31, 45, 35, 23, + 8, 17, 6, -16, -26, -14, -20, -48, -27, -2, 6, 11, 9, -1, 6, -15, + -28, -18, -39, -32, -7, 11, 7, 6, 7, 33, 30, 31, 41, 27, 7, 13, + 24, -3, -18, -22, -9, -40, -41, -10, 4, 9, 17, 3, 5, -4, -37, -29, + -29, -35, -19, 1, 10, 3, 7, 25, 41, 19, 31, 32, 13, 5, 27, 14, + -6, -19, -12, -23, -48, -22, 7, 8, 16, 11, 1, 6, -29, -46, -32, -32, + -20, -5, 7, 4, 3, 21, 43, 32, 15, 29, 16, 8, 19, 26, 3, -9, + -22, -13, -42, -37, -8, 11, 14, 25, 9, 4, -17, -50, -44, -30, -25, -14, + -1, 11, 1, 18, 36, 41, 12, 14, 18, 14, 15, 20, 17, 6, -14, -18, + -27, -39, -19, 5, 12, 24, 27, 8, -13, -49, -53, -32, -27, -19, -12, 7, + 7, 12, 31, 43, 26, 2, 8, 14, 22, 13, 17, 18, 6, -17, -26, -36, + -28, -6, 14, 25, 35, 20, -6, -42, -57, -37, -23, -23, -20, 0, 9, 8, + 25, 41, 40, 7, -4, 1, 23, 21, 14, 22, 20, -2, -24, -34, -31, -13, + 8, 24, 37, 33, 8, -32, -62, -44, -20, -22, -27, -9, 9, 7, 16, 31, + 42, 20, -10, -13, 10, 26, 7, 13, 25, 18, -11, -35, -39, -20, 0, 17, + 37, 37, 19, -17, -58, -55, -26, -18, -25, -21, 0, 14, 12, 20, 38, 35, + 0, -19, -9, 24, 19, 3, 21, 31, 17, -24, -42, -30, -3, 13, 34, 42, + 28, -2, -45, -62, -38, -22, -19, -20, -12, 12, 17, 11, 29, 42, 18, -16, + -20, 3, 24, 2, 4, 26, 36, 0, -38, -45, -13, 12, 27, 41, 34, 14, + -27, -62, -55, -30, -19, -15, -16, -2, 18, 11, 14, 37, 31, -6, -22, -12, + 15, 10, -10, 12, 36, 30, -19, -46, -33, 11, 24, 28, 35, 28, -5, -44, + -65, -44, -23, -11, -9, -8, 5, 14, 10, 25, 37, 14, -17, -18, -2, 14, + -7, -6, 23, 43, 10, -33, -38, -9, 24, 24, 28, 30, 11, -21, -57, -61, + -39, -12, -5, -5, -3, 7, 10, 17, 31, 30, -3, -20, -14, 6, 1, -16, + 2, 38, 38, -5, -30, -24, 13, 25, 21, 28, 15, 1, -34, -64, -62, -23, + 0, 2, -1, -1, 5, 14, 24, 33, 14, -12, -23, -4, 7, -18, -18, 18, + 43, 25, -9, -22, -2, 21, 19, 24, 20, 11, -13, -47, -69, -46, -7, 5, + 6, -1, -4, 9, 21, 31, 25, 5, -15, -20, 3, -8, -33, -7, 29, 37, + 20, -10, -10, 9, 15, 17, 14, 12, 1, -23, -55, -70, -30, 5, 13, 2, + -8, -1, 15, 25, 30, 15, -1, -20, -8, -3, -31, -28, 8, 31, 41, 15, + -6, 0, 9, 14, 12, 9, 8, -10, -28, -63, -55, -12, 17, 11, -7, -13, + 8, 22, 26, 19, 9, -7, -13, -5, -23, -39, -10, 17, 41, 38, 8, 0, + 5, 7, 12, 5, 7, -6, -8, -39, -60, -35, 7, 19, 6, -10, -6, 15, + 26, 22, 15, 9, -8, -13, -24, -45, -29, -1, 29, 48, 30, 2, 6, 5, + 9, 5, -1, -5, -4, -13, -51, -51, -16, 20, 13, 0, -11, 7, 25, 22, + 18, 17, 10, -8, -22, -50, -43, -13, 15, 46, 42, 16, 7, 8, 7, 7, + -1, -6, -10, -4, -27, -45, -36, 5, 16, 7, -5, -5, 20, 22, 19, 19, + 22, 7, -15, -43, -62, -29, 3, 35, 43, 27, 11, 9, 8, 4, 2, -9, + -13, -7, -15, -30, -43, -16, 12, 13, 4, -8, 12, 24, 17, 16, 24, 25, + -3, -38, -72, -52, -9, 25, 42, 30, 21, 8, 14, 4, 6, -3, -13, -12, + -13, -18, -36, -34, 3, 14, 9, -9, 5, 26, 18, 13, 26, 34, 13, -31, + -69, -68, -16, 19, 35, 29, 22, 6, 16, 3, 2, 6, -5, -15, -20, -19, + -21, -34, -17, 8, 16, -2, -3, 24, 27, 16, 23, 34, 32, -10, -56, -80, + -45, 6, 29, 29, 22, 10, 14, 13, -4, 6, 7, -8, -27, -27, -18, -20, + -28, -8, 14, 8, -7, 11, 29, 21, 17, 25, 35, 16, -36, -77, -67, -14, + 25, 30, 22, 11, 10, 19, 5, 2, 6, 5, -18, -34, -25, -13, -23, -19, + 4, 13, 0, 7, 24, 32, 24, 22, 31, 30, -12, -62, -76, -41, 9, 28, + 24, 15, 6, 18, 16, 6, 6, 7, -7, -32, -37, -16, -18, -24, -8, 11, + 7, 7, 20, 31, 35, 25, 24, 33, 9, -40, -72, -58, -16, 17, 27, 16, + 6, 10, 22, 12, 8, 8, 2, -23, -43, -26, -16, -24, -18, 2, 6, 7, + 21, 29, 36, 32, 21, 27, 22, -21, -57, -67, -38, -4, 26, 21, 9, 3, + 18, 25, 18, 10, 2, -11, -42, -36, -24, -27, -23, -9, 5, 2, 17, 32, + 42, 36, 27, 18, 25, -2, -39, -58, -51, -27, 11, 27, 11, 1, 9, 24, + 25, 21, 5, -8, -31, -37, -30, -33, -24, -15, 0, -2, 13, 31, 48, 47, + 33, 15, 18, 10, -27, -50, -52, -44, -12, 21, 21, 5, -1, 13, 33, 30, + 16, -6, -26, -39, -33, -35, -28, -20, -10, -8, 4, 27, 51, 61, 45, 21, + 13, 14, -11, -39, -40, -44, -36, 1, 25, 16, 1, 2, 27, 40, 28, 3, + -22, -38, -38, -32, -33, -21, -18, -14, -8, 18, 50, 66, 60, 27, 7, 12, + -3, -31, -36, -37, -46, -27, 18, 26, 5, -3, 8, 35, 43, 16, -14, -36, + -43, -32, -32, -25, -16, -23, -14, 6, 46, 64, 74, 49, 9, 4, 7, -23, + -37, -34, -41, -44, -8, 31, 19, -5, 0, 21, 47, 33, -2, -33, -43, -43, + -32, -29, -14, -22, -23, -6, 34, 62, 75, 71, 30, 0, 8, -13, -37, -34, + -35, -45, -34, 18, 31, 5, -5, 7, 35, 44, 12, -23, -45, -49, -40, -29, + -18, -18, -27, -15, 22, 57, 74, 80, 57, 15, 4, -1, -39, -34, -34, -40, + -46, -4, 25, 13, -3, 2, 22, 44, 25, -10, -38, -44, -50, -34, -20, -14, + -31, -21, 5, 47, 63, 81, 76, 38, 8, 9, -30, -45, -35, -36, -43, -20, + 9, 14, 5, 3, 7, 36, 32, 3, -32, -43, -50, -40, -28, -13, -24, -28, + -2, 35, 56, 73, 86, 58, 23, 21, -10, -49, -45, -33, -39, -25, -3, 5, + 5, 8, 5, 18, 32, 17, -19, -45, -49, -41, -35, -22, -19, -31, -12, 28, + 52, 59, 76, 74, 41, 31, 10, -39, -58, -41, -32, -27, -5, -3, 3, 8, + 8, 10, 24, 22, -4, -39, -52, -42, -35, -30, -18, -28, -22, 20, 53, 52, + 60, 73, 62, 43, 31, -18, -56, -61, -35, -28, -9, -6, -3, 3, 9, 10, + 12, 18, 8, -23, -53, -50, -31, -35, -24, -28, -26, 3, 48, 55, 52, 59, + 66, 57, 46, 7, -37, -67, -53, -24, -11, -4, -6, 0, 3, 13, 10, 7, + 10, -6, -38, -58, -36, -30, -30, -26, -26, -11, 33, 60, 56, 49, 59, 67, + 58, 32, -15, -58, -69, -34, -14, -8, -6, 1, -4, 7, 8, 2, 4, 4, + -21, -54, -49, -30, -30, -28, -29, -18, 13, 53, 60, 50, 44, 63, 61, 49, + 11, -33, -71, -49, -19, -9, -10, 5, 2, -1, 4, -1, 4, 5, -5, -38, + -55, -40, -28, -21, -25, -26, -2, 40, 61, 56, 39, 53, 66, 54, 33, -4, + -55, -63, -29, -18, -12, 3, 11, -4, -4, -9, -3, 4, 4, -18, -49, -49, + -35, -18, -18, -25, -16, 24, 51, 60, 42, 43, 66, 57, 42, 21, -23, -63, + -44, -26, -18, -10, 13, 9, -8, -18, -17, 5, 5, -4, -35, -47, -42, -24, + -11, -20, -21, 5, 36, 56, 53, 37, 60, 59, 40, 34, 11, -34, -52, -33, + -21, -15, 1, 21, 2, -19, -33, -10, 8, 3, -20, -42, -41, -33, -14, -16, + -18, -7, 21, 43, 54, 39, 47, 61, 44, 31, 27, -4, -41, -47, -28, -23, + -9, 11, 15, -9, -34, -34, 1, 10, -2, -30, -38, -34, -18, -15, -17, -10, + 10, 27, 43, 42, 42, 53, 54, 36, 24, 14, -15, -42, -36, -32, -22, 1, + 13, 7, -26, -48, -24, 11, 10, -14, -35, -32, -19, -16, -15, -11, 5, 18, + 31, 34, 41, 48, 51, 46, 28, 26, 8, -26, -36, -33, -35, -12, 7, 12, + -8, -45, -47, -9, 13, 5, -24, -32, -17, -14, -16, -11, 6, 14, 20, 26, + 27, 47, 49, 49, 34, 25, 22, -6, -31, -27, -39, -30, -10, 13, 6, -28, + -57, -31, -3, 12, -7, -28, -19, -8, -21, -18, -2, 18, 17, 17, 19, 34, + 47, 53, 42, 34, 30, 13, -22, -20, -30, -44, -32, -4, 15, -7, -45, -49, + -18, 4, 10, -14, -18, 0, -11, -26, -7, 15, 23, 10, 10, 20, 34, 51, + 49, 38, 41, 30, -8, -28, -15, -39, -47, -28, 5, 10, -26, -55, -34, -9, + 10, 3, -13, -4, 1, -21, -19, 3, 25, 13, 5, 9, 18, 36, 54, 39, + 40, 46, 16, -27, -17, -23, -47, -47, -18, 9, -2, -47, -51, -23, 0, 4, + 0, 1, 9, -11, -20, -9, 20, 23, 4, 2, 8, 20, 45, 46, 38, 53, + 41, -13, -30, -19, -36, -52, -40, -9, 5, -23, -53, -35, -6, 4, 3, 6, + 10, 5, -16, -17, 6, 30, 12, 0, -4, 9, 32, 47, 43, 55, 57, 16, + -27, -30, -28, -44, -52, -31, -6, -8, -43, -43, -15, -1, -1, 8, 10, 13, + 2, -18, -11, 21, 23, 6, -5, 0, 19, 33, 41, 56, 67, 44, -5, -34, + -35, -32, -46, -47, -27, -7, -30, -44, -23, -2, -2, 3, 7, 14, 18, -1, + -19, 4, 20, 16, -5, -9, 10, 27, 30, 46, 65, 63, 26, -22, -42, -34, + -41, -46, -40, -18, -25, -39, -28, -4, 1, -1, 5, 10, 24, 19, -8, -6, + 11, 20, 4, -13, 2, 22, 24, 36, 59, 70, 51, 5, -39, -39, -43, -47, + -45, -31, -30, -39, -33, -7, 1, -2, 1, 4, 19, 25, 5, -5, 1, 12, + 13, -12, -12, 18, 25, 21, 46, 68, 69, 36, -17, -39, -44, -51, -43, -33, + -35, -41, -38, -15, 8, 0, 0, 0, 13, 26, 19, 5, 0, -1, 10, -2, + -14, 5, 25, 19, 29, 54, 71, 59, 9, -31, -43, -56, -50, -32, -38, -47, + -42, -26, 8, 10, -3, -3, 7, 20, 23, 16, 8, -5, 3, 2, -17, -6, + 22, 20, 18, 40, 66, 71, 37, -13, -36, -52, -61, -38, -32, -47, -51, -38, + -7, 19, 6, -6, 4, 14, 19, 21, 19, 2, -5, 0, -13, -12, 14, 21, + 13, 27, 53, 71, 57, 12, -25, -42, -61, -54, -33, -38, -52, -50, -22, 13, + 17, -4, 1, 16, 17, 19, 25, 11, -2, -2, -11, -18, 6, 21, 15, 18, + 43, 66, 67, 34, -7, -30, -49, -58, -42, -36, -42, -54, -36, -2, 20, 4, + -4, 11, 16, 17, 26, 17, 4, 1, -8, -22, -8, 17, 16, 17, 27, 55, + 66, 48, 10, -25, -36, -49, -52, -42, -39, -47, -46, -18, 13, 14, -1, 3, + 13, 19, 27, 18, 2, 5, 1, -14, -17, 6, 13, 16, 26, 44, 64, 54, + 27, -15, -30, -33, -49, -50, -43, -44, -45, -30, -1, 13, 3, 6, 10, 22, + 30, 21, 3, 2, 2, -3, -18, -9, 8, 11, 23, 35, 55, 58, 37, 1, + -25, -18, -33, -51, -48, -46, -41, -30, -17, 6, 3, 7, 9, 16, 30, 27, + 9, 3, 3, 1, -10, -18, 0, 3, 12, 37, 46, 52, 40, 15, -23, -16, + -14, -39, -48, -48, -45, -31, -20, -7, 1, 4, 14, 13, 21, 26, 16, 2, + 1, 1, 1, -16, -12, 1, 5, 29, 50, 47, 39, 21, -11, -21, -3, -23, + -41, -45, -47, -37, -21, -13, -6, 1, 16, 20, 22, 22, 18, 10, 2, 1, + 6, -7, -16, -10, 0, 16, 51, 53, 38, 22, -1, -21, -1, -4, -30, -41, + -45, -45, -28, -13, -13, -8, 13, 24, 26, 15, 13, 15, 8, -4, 1, -2, + -11, -15, -11, 2, 40, 56, 44, 21, 1, -16, -10, 5, -16, -32, -38, -41, + -36, -22, -14, -15, 4, 24, 32, 18, 7, 14, 14, 4, -2, -1, -8, -12, + -15, -6, 24, 50, 51, 28, 1, -13, -14, 4, 1, -18, -31, -35, -36, -33, + -21, -21, -5, 19, 38, 23, 3, 5, 17, 15, 2, -3, -7, -8, -18, -14, + 12, 39, 50, 35, 2, -14, -14, -3, 6, -6, -24, -27, -32, -40, -25, -22, + -12, 8, 35, 34, 10, 2, 5, 19, 9, -6, -4, -3, -15, -18, 4, 30, + 42, 40, 13, -17, -16, -7, 3, 5, -14, -21, -24, -41, -37, -23, -18, -1, + 22, 37, 17, 4, -1, 11, 17, 1, -7, -4, -12, -22, -6, 24, 35, 33, + 25, -7, -26, -15, 2, 14, 3, -16, -19, -33, -42, -27, -23, -10, 15, 28, + 27, 8, 2, 5, 20, 11, -4, -6, -7, -19, -11, 17, 31, 26, 25, 6, + -24, -25, -6, 11, 14, -3, -13, -25, -39, -33, -23, -17, 7, 19, 26, 19, + 4, 1, 15, 14, -1, -5, -10, -14, -22, 8, 33, 28, 20, 16, -13, -26, + -17, 9, 22, 5, -8, -18, -37, -35, -28, -23, -4, 12, 16, 28, 12, 1, + 12, 18, 3, -2, -9, -10, -27, -10, 29, 34, 18, 16, 2, -26, -29, -3, + 27, 19, -4, -10, -29, -36, -30, -29, -12, 9, 3, 18, 21, 7, 12, 17, + 3, -2, -7, -7, -19, -26, 15, 36, 21, 12, 9, -15, -30, -18, 19, 30, + 6, -5, -21, -32, -25, -29, -22, 6, 0, 3, 20, 14, 12, 18, 12, 0, + -9, -12, -9, -26, -4, 31, 28, 11, 10, -6, -24, -29, 3, 35, 19, -3, + -15, -26, -19, -23, -31, -6, 4, -7, 13, 19, 17, 20, 18, 9, -9, -19, + -5, -17, -20, 16, 34, 18, 9, 0, -16, -25, -10, 30, 29, 3, -10, -19, + -19, -16, -29, -19, 3, -9, -5, 13, 21, 24, 16, 13, 1, -23, -14, -12, + -19, -2, 28, 21, 8, 1, -11, -23, -19, 16, 41, 14, -8, -13, -9, -13, + -18, -27, -4, -5, -12, -1, 19, 31, 18, 10, 16, -20, -22, -13, -14, -12, + 18, 26, 12, 4, -4, -17, -18, -1, 38, 31, -5, -14, -7, -7, -14, -24, + -13, -3, -13, -12, 7, 30, 34, 14, 18, -5, -33, -18, -10, -14, 1, 19, + 14, 6, -8, -13, -15, -2, 19, 40, 8, -13, -9, -4, -8, -18, -20, -9, + -14, -16, -7, 22, 37, 23, 16, 10, -26, -28, -13, -9, -5, 14, 14, 9, + -9, -17, -13, -1, 8, 31, 26, -6, -10, -4, -2, -12, -19, -11, -11, -17, + -12, 6, 34, 29, 15, 16, -7, -35, -25, -9, -6, 8, 14, 12, 1, -15, + -14, 3, 10, 19, 29, 8, -10, -9, 1, -7, -20, -10, -9, -17, -17, -1, + 30, 35, 18, 15, 5, -28, -33, -17, -6, -4, 8, 13, 5, -14, -19, 1, + 14, 14, 20, 17, 0, -8, -2, -3, -14, -18, -9, -12, -18, -6, 21, 37, + 26, 7, 10, -13, -33, -24, -6, -2, 0, 9, 11, -5, -19, -7, 16, 18, + 13, 18, 11, -2, -6, -3, -6, -22, -10, -11, -16, -11, 17, 34, 32, 9, + 9, 2, -26, -30, -14, -2, -5, 3, 8, 3, -16, -12, 8, 21, 13, 13, + 15, 2, -3, -5, -5, -20, -16, -8, -16, -20, 6, 32, 34, 14, -4, 6, + -12, -26, -20, -7, -6, -4, 4, 7, -2, -15, 1, 17, 15, 9, 15, 10, + 0, -3, -7, -15, -22, -4, -7, -19, -7, 29, 36, 20, -6, -1, 0, -17, + -19, -12, -9, -7, -1, 2, 6, -3, -8, 10, 18, 9, 8, 21, 4, -2, + -8, -13, -20, -12, -2, -16, -14, 14, 39, 26, -3, -17, 1, -6, -16, -12, + -7, -9, -9, 0, 3, 11, -3, 0, 15, 13, 3, 19, 12, -8, -6, -14, + -19, -16, 0, -6, -17, 3, 33, 35, 5, -18, -9, 1, -15, -11, -8, -8, + -16, -8, 1, 15, 15, 3, 11, 19, 2, 12, 26, 0, -10, -13, -21, -11, + 1, -1, -18, -2, 23, 35, 17, -12, -21, -2, -8, -9, -8, -9, -12, -17, + -5, 10, 22, 8, 7, 18, 7, -1, 23, 13, -13, -19, -23, -14, 5, 2, + -15, -13, 17, 30, 22, -3, -24, -7, -2, -9, -6, -10, -8, -21, -19, 5, + 22, 22, 13, 15, 13, -3, 11, 18, -4, -20, -28, -20, 4, 11, -10, -18, + 6, 26, 17, 3, -20, -12, -2, -11, -7, -8, -8, -16, -27, -7, 19, 30, + 21, 19, 15, 4, 3, 18, 2, -17, -33, -24, 0, 17, 1, -16, -6, 24, + 19, 5, -17, -18, 1, -8, -12, -7, -11, -10, -22, -14, 10, 29, 29, 32, + 23, 13, 0, 9, 6, -12, -28, -36, -7, 13, 12, -8, -17, 12, 24, 6, + -10, -20, 1, 1, -13, -9, -12, -16, -20, -17, 0, 21, 27, 31, 35, 20, + 7, 0, 2, -13, -19, -37, -19, 8, 18, 9, -16, -9, 20, 11, -2, -25, + -13, 8, -4, -16, -13, -18, -23, -17, 0, 14, 29, 27, 43, 35, 17, -1, + -4, -13, -22, -29, -31, -2, 17, 20, -5, -21, 6, 16, 5, -16, -25, 4, + 11, -12, -17, -20, -27, -19, -2, 13, 26, 27, 36, 46, 32, 7, -8, -18, + -26, -25, -32, -16, 12, 26, 11, -18, -11, 4, 13, -1, -27, -12, 14, 2, + -21, -23, -31, -26, -11, 10, 24, 30, 29, 43, 50, 24, -4, -16, -34, -28, + -28, -27, -1, 27, 24, -5, -21, -12, 6, 16, -13, -28, 1, 13, -9, -23, + -33, -32, -18, 2, 24, 34, 33, 34, 50, 49, 12, -11, -34, -37, -28, -25, + -14, 14, 28, 10, -10, -25, -9, 21, 15, -27, -15, 12, 2, -18, -33, -36, + -24, -7, 13, 30, 39, 42, 35, 54, 36, 1, -29, -45, -35, -26, -17, -1, + 20, 19, 2, -23, -30, 1, 30, -5, -32, 1, 7, -8, -27, -37, -25, -12, + -1, 23, 37, 51, 38, 41, 49, 16, -15, -41, -40, -31, -21, -11, 4, 19, + 15, -8, -33, -19, 22, 20, -21, -13, 2, -6, -17, -36, -32, -11, -8, 9, + 28, 48, 54, 36, 48, 30, 3, -30, -41, -34, -24, -15, -6, 2, 17, 8, + -19, -37, 0, 31, 3, -20, -6, -4, -7, -31, -35, -9, -3, -4, 16, 37, + 62, 44, 41, 33, 13, -11, -36, -39, -29, -21, -11, -11, 6, 14, -2, -28, + -24, 15, 22, -5, -10, -11, -10, -20, -35, -13, 2, -5, 2, 21, 55, 64, + 46, 37, 19, 2, -23, -36, -28, -23, -17, -18, -17, 10, 11, -12, -32, -7, + 23, 16, -7, -14, -17, -8, -27, -23, 1, 1, 0, 6, 31, 63, 60, 46, + 21, 7, -12, -29, -24, -18, -24, -23, -27, -11, 11, 5, -16, -19, 11, 21, + 4, -9, -21, -15, -17, -30, -5, 7, 2, -1, 9, 48, 65, 59, 30, 13, + -4, -25, -19, -6, -22, -33, -32, -31, -3, 7, -3, -20, -4, 14, 11, -1, + -11, -19, -13, -20, -16, 9, 7, 2, -3, 27, 60, 69, 44, 12, 7, -18, + -20, 1, -4, -35, -38, -34, -22, -9, 4, -2, -11, 8, 8, 2, -6, -19, + -23, -14, -16, 3, 13, 2, 2, 12, 47, 65, 62, 22, 10, -3, -21, -9, + 9, -17, -46, -40, -34, -23, -6, 4, -1, 3, 7, 2, -4, -13, -25, -18, + -11, -4, 18, 3, -2, 5, 30, 58, 66, 39, 12, 9, -10, -18, 8, 5, + -41, -49, -38, -33, -18, -4, 2, 7, 8, 2, -7, -12, -18, -23, -12, -6, + 18, 15, -8, 0, 21, 44, 62, 48, 22, 14, 7, -16, -7, 18, -18, -52, + -44, -42, -32, -18, -1, 12, 10, 6, -8, -20, -11, -18, -19, -10, 14, 24, + 2, -5, 14, 34, 57, 51, 27, 19, 20, -1, -13, 15, -1, -42, -45, -49, + -38, -28, -15, 13, 19, 10, -1, -23, -16, -11, -24, -10, 6, 21, 14, -5, + 3, 24, 48, 58, 29, 17, 24, 18, -6, 4, 8, -28, -38, -46, -50, -36, + -29, 3, 22, 15, 4, -18, -31, -7, -20, -17, 5, 11, 18, 4, -2, 15, + 37, 58, 35, 11, 26, 31, 11, -2, 6, -13, -32, -39, -55, -45, -38, -17, + 21, 23, 11, -10, -31, -18, -11, -25, 1, 9, 14, 15, 0, 7, 26, 49, + 49, 13, 10, 33, 26, 8, 4, -5, -25, -35, -46, -53, -41, -35, 5, 24, + 17, 0, -25, -26, -14, -24, -9, 6, 5, 17, 6, 6, 20, 38, 55, 30, + 3, 25, 38, 18, 10, -4, -16, -30, -42, -51, -46, -41, -16, 21, 23, 14, + -16, -30, -16, -17, -17, 0, 2, 12, 16, 3, 17, 28, 46, 49, 14, 13, + 39, 30, 17, 4, -9, -20, -38, -49, -50, -50, -34, 4, 21, 20, 4, -29, + -23, -15, -15, -8, -3, 7, 19, 8, 9, 26, 35, 47, 29, 6, 29, 35, + 26, 13, -5, -18, -29, -42, -49, -51, -50, -16, 11, 23, 18, -17, -34, -14, + -15, -9, -10, -2, 17, 14, 5, 21, 33, 44, 38, 14, 23, 37, 30, 20, + 6, -8, -26, -34, -47, -52, -54, -34, 0, 16, 19, 5, -29, -20, -13, -10, + -9, -10, 4, 19, 11, 13, 29, 37, 36, 22, 22, 39, 32, 23, 10, 2, + -18, -32, -40, -54, -56, -49, -23, 8, 17, 11, -15, -26, -11, -13, -9, -15, + -11, 14, 17, 10, 23, 34, 36, 24, 21, 35, 42, 26, 12, 2, -4, -23, + -31, -47, -57, -50, -33, -7, 17, 11, -2, -18, -12, -12, -11, -10, -21, -6, + 18, 19, 21, 33, 35, 28, 23, 34, 51, 40, 12, -2, 1, -9, -27, -43, + -59, -53, -39, -23, 4, 15, 1, -10, -14, -9, -8, -10, -22, -18, 5, 19, + 16, 27, 34, 28, 23, 27, 47, 53, 27, -3, -4, -1, -13, -33, -53, -57, + -45, -31, -13, 14, 4, -4, -11, -9, -9, -11, -19, -28, -16, 10, 24, 23, + 35, 24, 26, 26, 38, 60, 44, 2, -13, -3, -5, -19, -44, -58, -49, -33, + -26, 1, 14, 1, -4, -5, 0, -7, -14, -29, -26, -11, 20, 27, 30, 32, + 21, 27, 34, 59, 58, 22, -11, -10, -6, -10, -29, -55, -53, -38, -34, -16, + 12, 9, -5, -8, 5, 1, -16, -31, -32, -28, 0, 26, 26, 33, 23, 24, + 33, 49, 61, 37, 3, -15, -8, -11, -19, -43, -56, -44, -34, -25, -2, 17, + 5, -11, 2, 12, -2, -23, -32, -35, -23, 14, 26, 27, 35, 23, 32, 45, + 58, 47, 19, -5, -9, -10, -16, -27, -46, -48, -41, -34, -18, 11, 20, -6, + -10, 12, 9, -18, -34, -38, -29, -7, 17, 27, 32, 30, 30, 46, 52, 51, + 28, 6, -8, -9, -15, -24, -32, -41, -45, -40, -30, -1, 23, 10, -12, 2, + 17, -2, -31, -39, -32, -18, -6, 18, 29, 38, 32, 45, 54, 54, 33, 11, + 2, -9, -11, -19, -32, -33, -41, -45, -40, -18, 16, 19, 2, -6, 13, 12, + -20, -43, -35, -21, -18, -5, 21, 35, 36, 46, 58, 52, 38, 17, 9, -5, + -9, -13, -29, -32, -28, -41, -43, -36, 0, 22, 18, -4, -3, 17, 2, -33, + -43, -25, -18, -16, 4, 27, 38, 47, 64, 57, 40, 18, 10, 5, -7, -10, + -22, -39, -24, -30, -42, -39, -22, 13, 28, 14, -9, 3, 17, -16, -51, -36, + -17, -23, -18, 8, 35, 50, 66, 68, 43, 23, 12, 13, -1, -11, -17, -32, + -27, -22, -40, -38, -37, -10, 22, 34, 1, -10, 8, 6, -39, -48, -27, -19, + -25, -10, 18, 49, 66, 78, 54, 26, 17, 16, 3, -7, -15, -25, -29, -12, + -32, -37, -35, -28, 3, 38, 26, -7, -4, 11, -15, -46, -42, -26, -23, -24, + -2, 34, 66, 81, 70, 30, 19, 21, 10, -5, -11, -25, -29, -12, -20, -37, + -33, -39, -17, 25, 46, 6, -11, 2, 0, -29, -44, -41, -30, -27, -17, 12, + 58, 79, 84, 46, 19, 22, 19, 2, -7, -26, -35, -12, -1, -29, -33, -39, + -36, 3, 46, 31, -11, -6, -1, -14, -38, -46, -39, -32, -22, -5, 40, 76, + 88, 64, 23, 22, 30, 12, -8, -20, -39, -22, 0, -13, -29, -33, -43, -20, + 24, 49, 13, -12, 2, -6, -26, -45, -45, -39, -32, -15, 19, 68, 85, 77, + 32, 22, 35, 27, 0, -18, -36, -38, -6, 3, -17, -29, -44, -37, -2, 40, + 34, -8, -6, 3, -18, -44, -47, -44, -43, -21, 3, 49, 76, 80, 53, 21, + 35, 39, 15, -18, -35, -42, -23, 2, -3, -19, -33, -42, -23, 16, 46, 16, + -8, 2, -6, -37, -45, -47, -51, -33, -8, 31, 68, 74, 66, 33, 35, 45, + 36, -3, -33, -40, -34, -7, 5, -8, -18, -35, -39, -13, 32, 32, 3, -1, + 5, -26, -46, -50, -52, -44, -20, 15, 59, 68, 69, 50, 32, 42, 48, 21, + -26, -42, -42, -24, 2, 2, -8, -20, -38, -35, 6, 33, 17, -2, 5, -6, + -41, -55, -57, -46, -33, -6, 40, 64, 62, 63, 45, 38, 54, 40, -4, -42, + -50, -40, -11, 6, -2, -8, -24, -41, -19, 17, 28, 10, 0, 1, -26, -52, + -64, -51, -40, -23, 19, 54, 56, 61, 60, 38, 52, 55, 24, -30, -50, -47, + -27, 4, 8, -6, -11, -30, -36, -6, 19, 25, 4, 1, -9, -38, -64, -61, + -42, -36, 0, 44, 55, 51, 66, 50, 49, 62, 46, -5, -48, -51, -40, -11, + 11, 4, -14, -15, -36, -25, 1, 19, 15, -1, -2, -18, -53, -69, -48, -42, + -20, 21, 51, 45, 56, 62, 51, 60, 59, 23, -32, -53, -49, -28, 5, 17, + -12, -18, -22, -32, -12, 9, 20, 1, -6, -5, -29, -70, -62, -48, -32, 2, + 36, 45, 44, 62, 62, 60, 64, 47, -10, -45, -54, -42, -11, 21, 5, -19, + -18, -23, -20, -1, 15, 4, -6, -2, -6, -51, -72, -57, -44, -13, 19, 40, + 41, 51, 65, 66, 69, 63, 14, -32, -47, -50, -30, 10, 14, -12, -16, -18, + -16, -14, 7, 8, -6, -8, -1, -21, -65, -67, -54, -29, 1, 26, 38, 44, + 53, 69, 77, 73, 37, -17, -41, -46, -37, -10, 13, -1, -11, -14, -14, -10, + -6, 9, -5, -6, -11, -3, -43, -67, -68, -42, -15, 12, 27, 40, 47, 65, + 80, 83, 55, 7, -34, -43, -34, -22, -5, 2, -3, -2, -13, -10, -11, 3, + -2, -4, -13, -5, -15, -51, -72, -63, -31, -3, 16, 29, 42, 55, 78, 91, + 68, 25, -11, -40, -32, -22, -21, -9, -1, 8, -1, -19, -11, -3, 1, -5, + -11, -12, -3, -29, -58, -70, -48, -18, 6, 15, 35, 50, 68, 89, 84, 37, + 11, -27, -38, -19, -20, -23, -8, 10, 18, -10, -19, -8, 4, 0, -11, -14, + -7, -20, -42, -63, -60, -37, -4, 7, 23, 41, 67, 82, 90, 53, 19, -4, + -34, -23, -20, -31, -22, 5, 25, 8, -17, -20, 0, 10, -5, -20, -9, -12, + -31, -47, -60, -53, -26, -3, 12, 32, 58, 81, 85, 70, 27, 9, -19, -26, + -19, -28, -31, -8, 24, 21, -2, -26, -11, 14, 10, -20, -18, -8, -24, -33, + -53, -56, -44, -23, 3, 22, 44, 77, 85, 74, 40, 17, -3, -21, -21, -24, + -36, -25, 11, 22, 15, -13, -28, 5, 23, 0, -28, -12, -19, -26, -42, -56, + -48, -39, -17, 12, 34, 62, 84, 73, 52, 26, 9, -12, -21, -22, -31, -30, + -1, 15, 16, 6, -25, -14, 23, 19, -17, -21, -13, -24, -34, -54, -44, -39, + -36, -9, 27, 46, 79, 79, 59, 38, 16, -2, -17, -25, -25, -27, -10, 5, + 10, 15, -4, -24, 5, 29, 5, -24, -18, -19, -28, -48, -50, -35, -38, -28, + 10, 33, 62, 82, 62, 46, 27, 4, -8, -23, -24, -25, -15, -3, 0, 8, + 6, -12, -9, 22, 25, -6, -21, -22, -28, -45, -53, -39, -30, -37, -11, 20, + 43, 75, 66, 53, 41, 10, -8, -16, -25, -23, -15, -2, -4, -5, 4, 1, + -7, 8, 29, 19, -9, -21, -24, -42, -55, -48, -30, -31, -19, 5, 23, 61, + 74, 58, 53, 26, -7, -11, -18, -25, -14, 0, 1, -16, -8, 4, 0, 3, + 20, 28, 11, -16, -19, -38, -58, -55, -35, -27, -16, -1, 5, 32, 63, 61, + 56, 44, 3, -17, -13, -22, -19, -4, 5, -8, -21, -6, 7, 8, 12, 25, + 25, 2, -17, -26, -54, -64, -47, -32, -11, 5, 3, 16, 40, 60, 58, 56, + 26, -16, -19, -16, -20, -8, 0, -4, -20, -22, 1, 12, 9, 17, 30, 20, + -2, -15, -42, -68, -57, -44, -19, 11, 6, 10, 19, 42, 58, 58, 45, 6, + -23, -18, -13, -13, -3, -3, -10, -26, -14, 9, 15, 12, 26, 27, 10, -7, + -25, -61, -68, -54, -36, 10, 15, 13, 16, 19, 42, 55, 52, 31, -9, -25, + -18, -15, -7, -3, -9, -23, -26, -2, 15, 19, 19, 26, 18, 7, -10, -41, + -72, -60, -51, -8, 25, 22, 20, 13, 19, 45, 51, 44, 19, -15, -28, -15, + -7, -4, -9, -19, -28, -14, 6, 18, 18, 24, 22, 12, 1, -17, -55, -67, + -56, -35, 19, 33, 30, 20, 9, 23, 44, 48, 39, 6, -22, -25, -9, -8, + -9, -15, -29, -21, -3, 10, 16, 20, 23, 13, 7, -4, -31, -63, -61, -50, + -11, 33, 37, 30, 12, 7, 24, 44, 48, 28, -4, -28, -14, -4, -14, -14, + -27, -27, -8, 5, 13, 15, 19, 19, 11, 3, -12, -44, -64, -58, -31, 17, + 40, 39, 24, 8, 3, 30, 46, 42, 16, -18, -21, -6, -16, -18, -26, -32, + -15, 1, 6, 10, 10, 15, 12, 10, -3, -23, -51, -63, -50, -4, 34, 41, + 33, 17, -4, 10, 35, 42, 32, 5, -15, -8, -10, -18, -21, -30, -22, 0, + 3, -2, -2, 6, 5, 4, 3, -7, -25, -45, -45, -18, 25, 33, 32, 21, + 7, 8, 20, 30, 31, 20, 3, -7, -10, -14, -17, -23, -29, -12, 6, -2, + -11, -11, -4, 2, 3, -7, -10, -27, -33, -21, 13, 27, 23, 19, 8, 15, + 17, 18, 21, 23, 19, 2, -12, -10, -9, -15, -27, -28, -2, 9, -8, -18, + -17, -4, 9, -6, -7, -10, -17, -13, 2, 21, 20, 14, 4, 15, 25, 15, + 11, 14, 19, 13, -13, -17, -6, -5, -20, -36, -23, 4, 6, -18, -28, -20, + 6, 6, 0, 3, 5, 5, 28, 31, 31, 49, 55, 35, 11, 27, 26, 4, + 7, 11, 31, 54, 38, 26, 34, 35, 20, -10, -32, -43, -47, -43, -20, -7, + -37, -55, -62, -61, -63, -34, -21, -35, -28, -10, 15, 24, 23, 5, -31, -38, + -6, 23, 19, 15, 24, 20, 31, 57, 54, 28, 13, 33, 20, 1, 4, 17, + 38, 44, 33, 31, 43, 36, 10, -14, -34, -53, -53, -46, -22, -22, -38, -46, + -54, -60, -58, -29, -25, -39, -29, -12, 11, 25, 27, 6, -31, -33, -3, 27, + 32, 21, 13, 16, 38, 60, 53, 26, 18, 28, 11, -2, 8, 26, 37, 34, + 36, 42, 47, 31, 6, -14, -41, -61, -54, -49, -26, -30, -41, -40, -44, -54, + -48, -23, -28, -41, -33, -7, 14, 26, 29, 3, -32, -27, 6, 33, 35, 18, + 5, 21, 45, 61, 49, 25, 30, 22, 0, -5, 9, 37, 39, 27, 33, 47, + 50, 31, 1, -22, -51, -65, -59, -45, -31, -40, -36, -29, -35, -49, -41, -28, + -39, -44, -26, -8, 6, 27, 31, -5, -31, -18, 14, 33, 31, 17, 4, 25, + 48, 57, 45, 32, 27, 9, -6, -5, 14, 43, 36, 29, 39, 51, 50, 31, + 0, -32, -65, -73, -62, -37, -36, -46, -36, -23, -26, -37, -32, -35, -46, -42, + -22, -11, 2, 30, 28, -8, -29, -12, 22, 33, 32, 15, 4, 25, 49, 58, + 50, 36, 20, 2, -9, -3, 21, 43, 37, 32, 44, 55, 53, 33, -7, -42, + -67, -72, -64, -43, -43, -46, -35, -17, -17, -24, -31, -40, -47, -39, -18, -15, + 0, 33, 22, -14, -22, 5, 29, 29, 28, 11, 7, 23, 49, 54, 50, 37, + 13, -6, -11, -6, 25, 44, 38, 26, 40, 57, 54, 28, -12, -48, -70, -73, + -66, -43, -43, -43, -29, -12, -15, -16, -32, -48, -51, -38, -24, -19, 4, 31, + 12, -16, -14, 21, 34, 24, 24, 13, 10, 27, 49, 53, 53, 33, 6, -9, + -16, -4, 33, 48, 37, 24, 45, 61, 54, 23, -15, -60, -76, -76, -60, -48, + -45, -38, -26, -11, -3, -5, -33, -49, -52, -35, -25, -21, 7, 24, 1, -15, + -1, 34, 30, 23, 29, 17, 5, 26, 49, 55, 53, 26, -3, -16, -16, 4, + 38, 43, 33, 33, 49, 59, 45, 19, -18, -63, -78, -79, -58, -50, -39, -31, + -21, -11, -2, -3, -30, -49, -51, -35, -29, -20, 8, 12, -10, -11, 17, 37, + 27, 29, 29, 13, 2, 33, 56, 55, 38, 18, -7, -19, -17, 13, 40, 42, + 33, 35, 52, 58, 40, 10, -28, -68, -84, -78, -56, -47, -36, -30, -17, -7, + 5, -4, -30, -49, -51, -34, -30, -18, 10, 1, -18, -9, 30, 39, 26, 32, + 28, 9, 7, 38, 51, 45, 35, 16, -13, -28, -11, 27, 41, 41, 34, 45, + 58, 54, 29, 7, -33, -69, -80, -78, -59, -43, -31, -24, -15, -3, 9, -4, + -29, -51, -51, -33, -27, -8, 8, -13, -24, -1, 40, 41, 29, 31, 22, 7, + 15, 46, 48, 38, 33, 11, -19, -28, -7, 26, 42, 36, 39, 54, 54, 48, + 20, 3, -39, -68, -79, -78, -54, -37, -32, -27, -16, 5, 11, -6, -31, -50, + -49, -33, -24, -3, -3, -29, -26, 13, 44, 36, 30, 32, 17, 7, 28, 43, + 37, 31, 28, 4, -17, -27, -5, 24, 46, 43, 48, 56, 50, 41, 20, -1, + -47, -64, -82, -78, -48, -35, -34, -26, -14, 6, 9, -10, -31, -46, -43, -33, + -21, 1, -16, -38, -15, 24, 38, 35, 44, 33, 10, 15, 37, 43, 30, 22, + 18, 4, -20, -29, 0, 30, 43, 48, 54, 52, 46, 35, 19, -9, -41, -60, + -83, -73, -44, -29, -37, -27, -12, 6, 8, -10, -28, -45, -43, -25, -9, -3, + -33, -43, -4, 32, 35, 37, 49, 24, 7, 26, 47, 35, 17, 11, 14, 3, + -21, -30, 6, 30, 44, 60, 56, 44, 37, 33, 15, -11, -40, -63, -82, -61, + -36, -33, -39, -26, -13, 0, 4, -9, -29, -42, -37, -18, -7, -13, -39, -34, + 2, 30, 34, 45, 49, 16, 11, 37, 45, 26, 11, 8, 9, -1, -26, -25, + 17, 31, 46, 62, 52, 42, 29, 26, 15, -12, -45, -64, -71, -48, -34, -35, + -33, -27, -16, 1, 2, -10, -23, -41, -32, -12, -6, -29, -46, -28, 12, 26, + 36, 54, 43, 10, 23, 52, 43, 18, -2, 5, 5, -7, -25, -11, 19, 22, + 49, 61, 50, 40, 24, 20, 15, -10, -47, -62, -62, -45, -34, -30, -30, -23, + -16, -6, -1, -8, -25, -38, -29, -9, -10, -39, -42, -19, 5, 23, 48, 57, + 33, 7, 32, 57, 39, 8, -7, 3, -2, -16, -16, 1, 20, 22, 48, 55, + 46, 39, 17, 16, 17, -9, -48, -58, -54, -40, -37, -28, -26, -22, -23, -5, + 2, -11, -28, -37, -27, -10, -18, -44, -35, -18, 3, 31, 54, 52, 25, 13, + 45, 61, 29, -4, -10, 0, -5, -16, -8, 4, 21, 21, 50, 54, 45, 31, + 4, 20, 18, -15, -43, -48, -48, -39, -33, -28, -25, -22, -21, 0, -1, -19, + -29, -29, -22, -11, -29, -42, -30, -17, 3, 38, 61, 46, 24, 25, 53, 58, + 20, -10, -9, -5, -16, -12, 4, 11, 22, 17, 48, 51, 43, 16, 2, 18, + 13, -15, -35, -46, -43, -38, -31, -23, -27, -24, -13, 3, -8, -25, -29, -27, + -22, -18, -36, -38, -31, -19, 6, 46, 60, 36, 24, 33, 56, 44, 10, -8, + -9, -12, -24, -7, 14, 23, 18, 11, 45, 47, 39, 13, 5, 16, 1, -19, + -22, -39, -45, -45, -31, -20, -24, -16, -6, -3, -19, -24, -25, -26, -22, -24, + -39, -35, -25, -13, 8, 54, 64, 36, 29, 41, 56, 36, 5, -12, -11, -14, + -26, -6, 24, 33, 7, 12, 45, 44, 30, 13, 10, 17, -4, -17, -16, -34, + -46, -50, -30, -20, -23, -12, 1, -11, -26, -27, -24, -21, -19, -34, -48, -32, + -23, -10, 13, 66, 65, 33, 32, 48, 55, 25, 0, -8, -1, -18, -36, -4, + 40, 33, -1, 17, 37, 35, 25, 10, 14, 10, -13, -15, -9, -26, -46, -51, + -32, -18, -15, -4, 3, -17, -31, -28, -25, -20, -26, -48, -48, -27, -20, -13, + 19, 71, 61, 28, 33, 56, 50, 12, -8, -2, 5, -24, -41, 2, 52, 29, + -1, 24, 36, 26, 16, 14, 19, 6, -19, -12, 1, -21, -49, -50, -28, -12, + -3, 2, -2, -25, -32, -29, -24, -14, -31, -61, -44, -17, -15, -9, 28, 72, + 61, 25, 38, 61, 41, 7, -7, 4, 3, -32, -36, 9, 45, 21, 4, 30, + 33, 15, 11, 18, 17, -1, -18, -7, -4, -22, -47, -45, -24, -6, 2, 5, + -7, -27, -34, -28, -21, -14, -42, -69, -40, -11, -16, -3, 41, 68, 53, 29, + 48, 61, 32, 0, -5, 8, 2, -33, -28, 9, 31, 16, 16, 34, 22, 0, + 10, 24, 10, -9, -19, -6, -8, -26, -38, -34, -20, -10, 1, 11, -9, -33, + -31, -32, -25, -18, -50, -65, -40, -15, -8, 13, 47, 65, 50, 33, 54, 62, + 24, -2, 2, 12, -6, -31, -20, 12, 21, 10, 28, 34, 9, -5, 20, 20, + -2, -13, -10, -4, -18, -33, -26, -16, -19, -14, 6, 8, -14, -31, -32, -29, + -29, -31, -51, -69, -47, -12, 2, 21, 49, 56, 43, 45, 62, 54, 16, -2, + 7, 9, -13, -22, -4, 12, 7, 13, 37, 33, 7, -4, 23, 9, -8, -8, + -2, -8, -33, -38, -7, -1, -22, -19, 11, 7, -21, -29, -29, -29, -31, -32, + -55, -80, -49, -7, 16, 31, 43, 45, 44, 56, 66, 45, 12, 2, 10, 3, + -18, -13, 7, 9, -2, 17, 38, 22, 1, 5, 17, 4, -14, -12, -1, -11, + -43, -38, 6, 5, -22, -15, 12, 0, -23, -26, -28, -31, -32, -36, -60, -82, + -46, 3, 24, 35, 38, 41, 46, 59, 62, 41, 13, -1, 3, -6, -18, 3, + 22, 2, -9, 20, 36, 18, 10, 7, 4, -5, -17, -9, -2, -18, -55, -30, + 17, 6, -20, -10, 6, -5, -16, -26, -32, -27, -30, -42, -69, -84, -41, 13, + 31, 42, 37, 38, 45, 63, 65, 41, 12, 3, 1, -18, -10, 23, 27, -2, + -12, 17, 36, 26, 13, 4, -2, -5, -14, -14, -11, -26, -54, -19, 21, 8, + -16, -8, 6, -7, -20, -30, -33, -24, -33, -50, -74, -82, -32, 18, 34, 42, + 38, 34, 50, 69, 58, 34, 16, 7, -9, -29, -2, 41, 32, -7, -15, 11, + 34, 30, 9, 2, -3, -7, -23, -21, -15, -30, -52, -10, 18, 10, -8, -4, + 5, -4, -25, -33, -26, -22, -42, -59, -79, -72, -20, 23, 36, 41, 37, 34, + 54, 74, 53, 22, 17, 15, -17, -34, 10, 52, 37, -8, -11, 12, 33, 23, + 8, 4, -1, -16, -31, -25, -18, -38, -49, -3, 19, 11, -4, 0, 7, -8, + -34, -31, -19, -26, -52, -62, -79, -55, -7, 23, 41, 47, 41, 33, 61, 75, + 43, 22, 21, 13, -26, -33, 17, 58, 39, -6, -8, 13, 27, 10, 5, 13, + -2, -32, -43, -32, -19, -38, -36, -3, 12, 4, 4, 13, 6, -22, -41, -31, + -13, -33, -59, -71, -76, -35, 2, 20, 39, 53, 47, 39, 60, 62, 37, 26, + 22, 5, -33, -29, 26, 64, 40, 0, -5, 12, 21, 8, 16, 10, -13, -39, + -49, -37, -25, -41, -30, -6, 9, 9, 13, 23, 0, -30, -44, -26, -13, -45, + -67, -76, -68, -20, 10, 19, 39, 55, 50, 46, 57, 50, 37, 30, 16, -3, + -34, -22, 34, 65, 40, 13, -2, 6, 19, 12, 21, 5, -23, -49, -52, -38, + -33, -36, -24, -9, 10, 12, 25, 23, -11, -29, -43, -27, -21, -55, -73, -77, + -50, -2, 19, 19, 35, 59, 59, 49, 45, 40, 36, 27, 4, -10, -24, -12, + 31, 59, 44, 22, -5, 4, 19, 20, 12, -4, -27, -52, -50, -45, -39, -24, + -23, -13, 16, 20, 30, 15, -16, -28, -37, -30, -36, -64, -79, -73, -28, 17, + 24, 14, 36, 65, 68, 45, 33, 39, 40, 22, -2, -5, -11, -11, 28, 58, + 57, 20, -13, 0, 27, 23, 1, -15, -35, -58, -55, -52, -39, -20, -22, -9, + 20, 29, 30, 10, -15, -31, -39, -32, -48, -72, -86, -59, -4, 27, 19, 17, + 44, 77, 69, 31, 26, 40, 38, 14, -6, 0, 1, -11, 26, 67, 62, 10, + -18, 6, 31, 20, -5, -22, -44, -66, -61, -50, -31, -17, -24, -7, 24, 34, + 31, 3, -17, -31, -36, -40, -61, -73, -76, -46, 11, 34, 20, 22, 56, 83, + 60, 22, 24, 46, 32, 5, -4, 9, 0, -8, 31, 73, 53, 0, -13, 16, + 28, 14, -15, -31, -51, -74, -64, -43, -25, -22, -25, -1, 30, 37, 20, -2, + -20, -36, -39, -55, -69, -75, -69, -32, 21, 36, 22, 31, 63, 76, 50, 22, + 25, 49, 29, 3, 4, 9, 2, 0, 43, 74, 37, -8, -1, 28, 24, 8, + -22, -42, -65, -80, -60, -31, -25, -31, -24, 8, 41, 37, 10, -3, -22, -40, + -45, -60, -69, -69, -55, -15, 32, 37, 25, 42, 72, 70, 37, 21, 32, 41, + 20, 5, 15, 8, 0, 9, 46, 62, 26, -7, 8, 28, 21, 4, -29, -53, + -79, -82, -57, -25, -27, -32, -21, 14, 48, 35, -1, -7, -24, -44, -52, -70, + -69, -60, -38, 1, 34, 33, 32, 57, 70, 58, 34, 26, 31, 31, 16, 14, + 14, 3, 8, 25, 47, 47, 18, -2, 13, 25, 19, -2, -33, -64, -87, -83, + -53, -24, -29, -32, -17, 21, 46, 27, -4, -12, -30, -51, -61, -73, -60, -46, + -17, 9, 25, 32, 47, 69, 61, 48, 41, 30, 26, 24, 18, 24, 15, 2, + 14, 37, 42, 34, 17, 9, 19, 20, 11, -7, -35, -79, -97, -79, -45, -21, + -29, -33, -12, 26, 43, 27, -3, -15, -43, -58, -66, -69, -52, -37, -2, 16, + 24, 38, 61, 72, 56, 43, 41, 32, 28, 22, 22, 26, 12, 1, 23, 45, + 34, 21, 8, 17, 22, 19, 4, -18, -47, -93, -97, -70, -40, -29, -33, -22, + -5, 24, 44, 19, -6, -23, -53, -60, -74, -63, -41, -20, 10, 18, 19, 40, + 70, 70, 47, 41, 43, 37, 27, 14, 24, 32, 10, 1, 29, 44, 27, 12, + 7, 28, 32, 9, -11, -27, -56, -100, -94, -64, -43, -38, -31, -7, 0, 27, + 41, 11, -7, -35, -60, -62, -75, -54, -29, -5, 17, 22, 14, 46, 80, 72, + 46, 42, 44, 42, 24, 16, 31, 32, 9, 4, 33, 45, 22, 5, 8, 41, + 34, 0, -22, -36, -69, -100, -92, -65, -40, -44, -25, 0, 5, 28, 36, 4, + -12, -50, -64, -64, -68, -46, -19, 2, 25, 28, 19, 44, 72, 67, 46, 45, + 44, 39, 21, 21, 38, 29, 1, 9, 39, 39, 13, -4, 9, 54, 41, -11, + -38, -51, -76, -91, -92, -65, -44, -47, -17, 12, 11, 21, 27, 6, -24, -59, + -65, -67, -61, -40, -17, 8, 31, 26, 20, 49, 74, 65, 45, 48, 47, 36, + 25, 28, 36, 25, 5, 19, 42, 28, 6, -2, 21, 56, 27, -22, -45, -62, + -83, -92, -84, -65, -49, -37, -8, 15, 16, 22, 23, -1, -38, -65, -66, -65, + -51, -35, -15, 20, 42, 26, 25, 51, 70, 60, 45, 52, 47, 25, 25, 39, + 33, 24, 16, 31, 37, 14, 3, 2, 33, 55, 14, -35, -55, -67, -84, -88, + -84, -68, -47, -28, -1, 17, 22, 24, 17, -14, -54, -66, -64, -61, -46, -32, + -10, 26, 45, 24, 29, 52, 66, 57, 49, 56, 41, 16, 29, 46, 31, 22, + 24, 37, 30, 12, -1, 5, 40, 39, 1, -41, -63, -72, -89, -89, -77, -62, + -48, -17, 5, 13, 26, 31, 10, -29, -62, -64, -65, -54, -41, -25, -4, 32, + 52, 29, 32, 55, 61, 55, 56, 57, 35, 17, 33, 40, 28, 27, 37, 36, + 26, 14, -3, 13, 41, 22, -13, -45, -65, -78, -90, -87, -70, -56, -47, -12, + 9, 18, 35, 27, -5, -41, -63, -61, -65, -52, -37, -17, 5, 35, 52, 34, + 38, 55, 58, 53, 60, 54, 31, 21, 33, 34, 30, 35, 40, 32, 29, 15, + -4, 18, 30, 11, -25, -53, -69, -85, -91, -82, -66, -54, -36, -7, 6, 20, + 40, 19, -17, -52, -63, -60, -65, -50, -32, -11, 9, 34, 50, 40, 46, 51, + 56, 60, 60, 50, 28, 23, 33, 33, 31, 40, 43, 38, 38, 13, -6, 13, + 19, -2, -34, -57, -78, -91, -85, -73, -63, -55, -28, -1, 6, 26, 39, 13, + -28, -56, -61, -55, -61, -43, -27, -13, 12, 38, 48, 49, 54, 46, 52, 64, + 64, 48, 27, 22, 28, 33, 36, 44, 42, 39, 44, 15, -3, 10, 6, -19, + -46, -60, -81, -92, -83, -73, -52, -44, -22, -5, 5, 38, 37, -6, -41, -55, + -54, -49, -53, -45, -28, -9, 19, 41, 47, 56, 57, 41, 56, 69, 64, 42, + 26, 23, 27, 36, 39, 44, 39, 48, 53, 12, -4, 2, -8, -33, -61, -72, + -84, -87, -80, -73, -49, -36, -12, -5, 9, 42, 24, -15, -44, -50, -51, -51, + -51, -45, -26, -4, 20, 40, 47, 64, 58, 38, 61, 71, 55, 37, 32, 23, + 30, 34, 39, 50, 43, 58, 53, 9, 4, -3, -27, -49, -71, -79, -79, -79, + -82, -70, -44, -26, -7, -5, 16, 36, 9, -18, -40, -47, -49, -45, -42, -43, + -20, 1, 21, 40, 53, 72, 54, 36, 64, 66, 41, 30, 36, 26, 28, 31, + 44, 57, 48, 62, 45, 13, 3, -14, -47, -65, -77, -87, -78, -71, -75, -68, + -43, -16, -2, -1, 18, 20, -4, -18, -37, -46, -50, -36, -39, -46, -15, 7, + 23, 41, 62, 72, 49, 41, 69, 59, 33, 29, 38, 24, 28, 31, 52, 59, + 49, 61, 45, 21, 2, -31, -64, -73, -78, -89, -79, -71, -77, -62, -36, -8, + 3, 5, 15, 5, -10, -17, -34, -49, -50, -27, -37, -43, -12, 14, 25, 45, + 67, 68, 48, 48, 64, 48, 27, 33, 41, 25, 24, 32, 64, 66, 51, 62, + 41, 21, -7, -43, -77, -81, -83, -87, -74, -71, -77, -54, -29, -1, 7, 13, + 12, -6, -9, -18, -38, -54, -44, -21, -37, -41, -8, 16, 28, 53, 73, 61, + 46, 52, 60, 35, 25, 34, 38, 20, 25, 42, 73, 62, 60, 58, 39, 22, + -19, -54, -85, -88, -95, -88, -65, -69, -73, -47, -22, 3, 14, 15, -5, -14, + -6, -23, -42, -52, -34, -19, -42, -38, 0, 18, 30, 62, 76, 61, 49, 52, + 49, 26, 23, 34, 33, 22, 21, 50, 78, 68, 66, 47, 40, 22, -23, -66, + -95, -102, -97, -74, -61, -77, -68, -36, -12, 9, 15, 13, -18, -14, -5, -31, + -50, -44, -21, -25, -49, -25, 8, 16, 30, 70, 82, 56, 45, 55, 39, 21, + 25, 31, 24, 21, 28, 64, 81, 68, 64, 47, 44, 15, -30, -77, -101, -104, + -96, -71, -66, -76, -53, -22, -9, 6, 22, 10, -22, -15, -13, -38, -48, -32, + -9, -33, -49, -14, 10, 11, 37, 77, 85, 51, 44, 48, 30, 18, 21, 26, + 16, 21, 36, 71, 76, 73, 68, 48, 35, 4, -38, -81, -103, -109, -91, -67, + -71, -69, -40, -15, -12, 3, 23, 7, -23, -17, -24, -41, -45, -24, -11, -46, + -46, -1, 10, 8, 49, 84, 83, 48, 50, 48, 27, 16, 18, 20, 14, 26, + 44, 72, 75, 82, 71, 47, 26, -6, -45, -80, -107, -110, -88, -70, -69, -58, + -28, -9, -12, 2, 23, 2, -21, -19, -35, -38, -33, -13, -17, -50, -35, 8, + 9, 10, 57, 89, 74, 45, 52, 41, 24, 15, 11, 14, 13, 22, 54, 72, + 74, 86, 72, 41, 13, -14, -47, -86, -113, -111, -88, -72, -67, -42, -18, -11, + -11, 2, 18, -2, -17, -27, -44, -37, -28, -12, -26, -49, -22, 9, 3, 21, + 69, 87, 63, 46, 49, 36, 24, 13, 11, 11, 8, 26, 64, 68, 76, 89, + 74, 38, 3, -17, -44, -86, -117, -114, -86, -65, -58, -38, -19, -7, 0, 8, + 9, -5, -20, -37, -45, -29, -19, -15, -36, -39, -10, 6, 4, 33, 79, 81, + 55, 48, 42, 30, 23, 10, 13, 10, 3, 27, 62, 60, 76, 88, 68, 30, + -5, -21, -49, -89, -120, -115, -81, -54, -46, -34, -14, -1, 7, 9, 1, -6, + -18, -45, -52, -29, -16, -17, -35, -36, -12, 5, 11, 47, 81, 72, 53, 51, + 39, 28, 24, 9, 13, 7, 5, 36, 57, 55, 82, 90, 62, 31, -10, -29, + -55, -91, -121, -115, -76, -47, -38, -34, -13, 1, 13, 9, -4, -9, -17, -49, + -56, -26, -9, -12, -33, -40, -17, 12, 25, 57, 71, 62, 52, 50, 35, 22, + 21, 14, 11, -2, 10, 41, 50, 48, 85, 87, 66, 29, -15, -34, -64, -97, + -121, -108, -73, -43, -37, -28, -7, 7, 16, 6, -7, -5, -15, -59, -56, -19, + -4, -14, -37, -42, -10, 21, 38, 66, 63, 57, 52, 49, 28, 22, 28, 16, + 5, -3, 22, 47, 38, 45, 79, 85, 68, 23, -16, -34, -70, -100, -122, -107, + -62, -39, -38, -25, -4, 15, 18, 2, -3, 0, -27, -70, -51, -17, -3, -16, + -44, -40, -1, 27, 45, 67, 57, 54, 48, 39, 17, 18, 28, 17, 3, -3, + 27, 49, 37, 42, 69, 86, 66, 16, -17, -37, -72, -99, -117, -101, -55, -39, + -36, -24, 1, 20, 13, 4, 4, -5, -46, -74, -43, -9, -4, -28, -49, -33, + 6, 33, 63, 68, 54, 53, 49, 33, 18, 21, 24, 15, 7, 9, 33, 42, + 35, 39, 70, 85, 55, 10, -16, -40, -75, -98, -113, -92, -47, -38, -35, -21, + 1, 21, 15, 8, 7, -14, -62, -70, -30, -11, -15, -34, -49, -23, 9, 39, + 64, 58, 51, 56, 42, 20, 16, 19, 16, 16, 4, 13, 40, 46, 33, 31, + 65, 83, 49, 3, -24, -41, -73, -98, -105, -77, -45, -41, -30, -13, 7, 19, + 12, 13, 8, -26, -68, -61, -22, -14, -25, -38, -40, -18, 12, 47, 68, 59, + 49, 51, 42, 19, 17, 17, 12, 13, 5, 18, 41, 47, 26, 26, 67, 78, + 44, -2, -31, -47, -71, -97, -96, -67, -44, -42, -29, -11, 13, 21, 13, 17, + 8, -34, -68, -54, -17, -18, -36, -43, -35, -12, 14, 50, 69, 56, 49, 44, + 35, 16, 13, 17, 13, 13, 6, 27, 46, 50, 24, 28, 66, 64, 28, 0, + -25, -49, -75, -99, -87, -54, -42, -38, -28, -8, 20, 19, 11, 17, 1, -41, + -62, -49, -18, -27, -41, -39, -29, -8, 15, 55, 73, 55, 42, 42, 33, 16, + 12, 12, 9, 6, 14, 40, 52, 48, 21, 31, 60, 50, 23, 0, -32, -60, + -76, -90, -73, -44, -39, -36, -32, 1, 29, 20, 6, 13, -3, -41, -53, -43, + -21, -34, -47, -38, -22, -2, 22, 54, 65, 49, 38, 42, 32, 17, 12, 7, + 6, 3, 21, 48, 53, 42, 24, 39, 53, 38, 15, -3, -38, -65, -76, -85, + -59, -36, -35, -40, -26, 15, 26, 12, 6, 10, -12, -40, -49, -33, -26, -41, + -53, -36, -12, 5, 28, 50, 61, 46, 34, 37, 31, 20, 12, 1, 0, 5, + 32, 53, 56, 41, 23, 39, 48, 35, 13, -10, -44, -72, -81, -79, -50, -27, + -34, -41, -18, 20, 27, 12, 5, 1, -19, -36, -40, -22, -34, -50, -55, -33, + -3, 14, 33, 52, 54, 35, 27, 36, 37, 25, 7, -13, 1, 19, 41, 50, + 50, 38, 32, 43, 41, 32, 6, -17, -46, -69, -79, -75, -43, -20, -34, -38, + -8, 23, 26, 12, 6, -8, -23, -30, -30, -23, -46, -56, -52, -29, 6, 23, + 35, 44, 47, 31, 25, 33, 40, 26, -4, -22, 3, 28, 39, 40, 50, 40, + 28, 34, 37, 28, 0, -22, -50, -70, -81, -72, -34, -22, -36, -33, 2, 24, + 25, 12, 4, -15, -24, -26, -25, -23, -46, -56, -50, -24, 10, 33, 36, 40, + 35, 21, 25, 43, 47, 25, -13, -25, 11, 40, 36, 40, 56, 38, 27, 31, + 33, 24, -4, -24, -53, -71, -80, -59, -34, -27, -31, -27, 8, 24, 25, 17, + 2, -22, -25, -26, -19, -24, -51, -58, -40, -9, 14, 37, 36, 35, 27, 14, + 28, 48, 46, 19, -19, -24, 18, 40, 29, 41, 50, 29, 29, 27, 33, 18, + -12, -29, -53, -71, -75, -48, -33, -32, -25, -14, 13, 24, 19, 17, 2, -25, + -28, -28, -18, -28, -55, -59, -30, -3, 20, 41, 34, 24, 15, 15, 36, 49, + 39, 17, -17, -17, 22, 41, 33, 45, 38, 26, 30, 24, 27, 10, -11, -34, + -58, -70, -66, -38, -32, -36, -21, -2, 14, 28, 19, 14, 0, -25, -29, -28, + -17, -30, -57, -51, -22, 3, 23, 39, 34, 15, 11, 17, 38, 46, 39, 15, + -18, -14, 27, 40, 37, 45, 32, 28, 30, 29, 28, 1, -16, -38, -55, -65, + -62, -37, -31, -34, -17, 9, 18, 27, 18, 9, -1, -22, -35, -29, -17, -32, + -57, -45, -17, 15, 30, 30, 25, 8, 10, 19, 35, 46, 37, 4, -19, -8, + 31, 33, 33, 42, 28, 22, 24, 29, 23, -6, -21, -43, -54, -59, -55, -32, + -34, -39, -10, 19, 30, 25, 9, 2, -2, -20, -38, -30, -23, -41, -51, -35, + -12, 24, 32, 22, 12, 8, 16, 23, 32, 48, 33, 1, -16, 0, 29, 30, + 33, 36, 24, 23, 22, 33, 14, -14, -20, -42, -55, -50, -44, -27, -38, -41, + -3, 31, 35, 23, 5, -2, -4, -15, -34, -33, -38, -47, -40, -26, -3, 31, + 31, 9, 2, 13, 14, 20, 38, 53, 27, -6, -14, 11, 30, 23, 32, 28, + 25, 22, 24, 32, 5, -20, -26, -45, -49, -40, -36, -37, -48, -40, 8, 40, + 37, 16, -3, -6, -2, -9, -27, -42, -52, -48, -32, -21, 8, 39, 28, -2, + -5, 13, 17, 23, 40, 45, 19, -4, -3, 18, 15, 19, 33, 30, 29, 22, + 21, 22, 0, -17, -27, -46, -48, -33, -31, -38, -53, -33, 23, 43, 31, 11, + -7, -5, -3, -8, -26, -49, -59, -48, -25, -14, 15, 41, 23, -8, -6, 11, + 10, 26, 49, 41, 12, 0, 10, 19, 4, 22, 31, 25, 25, 24, 20, 12, + -4, -10, -37, -50, -37, -23, -26, -43, -55, -18, 34, 41, 28, 10, -9, -6, + -3, -8, -27, -57, -62, -37, -15, -8, 24, 44, 23, -10, -6, 3, 8, 39, + 55, 30, 12, 11, 20, 8, 3, 27, 26, 20, 21, 24, 19, -1, -10, -14, + -42, -47, -25, -14, -28, -49, -50, -5, 38, 38, 23, 9, -11, -9, -1, -5, + -33, -64, -59, -34, -14, -2, 32, 49, 17, -11, -6, -2, 11, 46, 46, 19, + 16, 23, 24, -3, 3, 29, 29, 16, 17, 22, 11, -12, -12, -18, -50, -43, + -15, -11, -30, -53, -38, 10, 31, 31, 25, 3, -16, -3, 3, -8, -41, -67, + -53, -24, -14, 3, 35, 46, 17, -2, -7, -9, 16, 49, 41, 20, 22, 34, + 21, -5, 5, 31, 29, 12, 14, 18, 8, -22, -17, -20, -52, -38, -13, -19, + -32, -48, -25, 11, 23, 29, 26, 1, -14, 1, 1, -18, -47, -60, -47, -31, + -11, 13, 45, 39, 8, -2, -2, -11, 16, 43, 35, 25, 34, 40, 18, -7, + 6, 34, 28, 14, 7, 11, 2, -23, -25, -29, -51, -30, -11, -24, -38, -40, + -15, 9, 18, 29, 32, -1, -10, 0, -9, -27, -48, -52, -46, -30, -2, 27, + 47, 30, 10, 7, -6, -15, 12, 35, 28, 30, 45, 42, 19, -4, 11, 29, + 21, 6, 1, 3, -3, -27, -31, -34, -40, -22, -18, -31, -35, -30, -18, 5, + 19, 32, 28, -9, -7, 1, -14, -30, -42, -45, -47, -28, 7, 38, 45, 23, + 14, 20, -2, -24, 7, 32, 30, 37, 43, 41, 22, 7, 18, 22, 14, 4, + -7, 4, -7, -36, -37, -37, -27, -15, -26, -34, -34, -29, -18, 4, 19, 31, + 20, -4, 0, -3, -21, -32, -37, -41, -40, -25, 14, 49, 44, 18, 19, 25, + -1, -19, 5, 26, 35, 38, 46, 41, 18, 18, 16, 13, 12, 2, -5, -3, + -23, -44, -37, -32, -20, -20, -33, -28, -32, -32, -16, 1, 17, 31, 17, -2, + 2, -3, -22, -33, -39, -40, -34, -23, 15, 56, 44, 15, 27, 23, -4, -14, + 2, 22, 38, 37, 48, 40, 25, 24, 15, 11, 2, -2, -3, -15, -31, -40, + -37, -33, -17, -17, -28, -29, -41, -34, -7, 1, 13, 31, 17, -2, 4, 1, + -20, -35, -47, -37, -24, -10, 22, 52, 38, 26, 35, 26, -2, -9, 4, 23, + 40, 38, 46, 39, 32, 31, 16, 2, -7, -8, -2, -21, -38, -44, -38, -31, + -18, -15, -29, -35, -45, -32, -1, -3, 4, 30, 16, 3, 8, 4, -20, -42, + -48, -30, -17, -8, 21, 49, 41, 30, 38, 23, -2, -5, 1, 21, 35, 37, + 44, 40, 40, 33, 17, 1, -13, -10, -9, -35, -41, -41, -39, -33, -19, -12, + -27, -40, -48, -28, -4, -10, 10, 28, 15, 9, 12, 5, -24, -43, -43, -23, + -18, 0, 26, 47, 43, 35, 40, 20, -1, 1, 4, 20, 28, 37, 42, 42, + 46, 31, 22, 8, -17, -15, -15, -42, -41, -37, -44, -37, -16, -13, -33, -41, + -41, -20, -11, -17, 10, 18, 13, 16, 17, 1, -24, -38, -38, -27, -21, 9, + 29, 46, 44, 43, 38, 18, 3, 6, 6, 12, 19, 38, 41, 47, 44, 28, + 29, 11, -26, -25, -27, -45, -39, -39, -48, -41, -18, -13, -33, -38, -36, -21, + -19, -14, 13, 11, 11, 26, 17, -6, -25, -32, -32, -35, -14, 21, 31, 38, + 49, 49, 34, 19, 13, 10, 4, 9, 20, 37, 41, 45, 39, 29, 35, 6, + -28, -28, -35, -43, -37, -42, -50, -44, -20, -20, -37, -37, -27, -16, -23, -11, + 10, 5, 17, 36, 16, -16, -23, -21, -33, -38, -5, 23, 28, 35, 55, 55, + 31, 17, 18, 12, 3, 4, 21, 33, 41, 45, 31, 32, 39, 3, -29, -35, + -41, -40, -38, -45, -55, -45, -26, -31, -36, -26, -22, -22, -29, 1, 9, -1, + 24, 39, 8, -19, -17, -14, -32, -34, 5, 29, 29, 35, 58, 51, 32, 29, + 23, 11, 1, 6, 29, 37, 38, 36, 24, 43, 39, -2, -32, -44, -45, -36, + -36, -45, -55, -51, -37, -35, -30, -22, -20, -32, -24, 6, 2, 3, 30, 36, + 3, -17, -16, -18, -29, -24, 10, 31, 25, 34, 58, 44, 33, 37, 26, 8, + 5, 10, 37, 36, 35, 29, 22, 47, 36, -6, -36, -51, -49, -34, -38, -48, + -58, -53, -46, -42, -24, -23, -22, -32, -13, 4, -7, 8, 35, 30, 6, -14, + -20, -19, -21, -20, 14, 34, 29, 43, 52, 37, 39, 43, 24, 8, 7, 15, + 45, 33, 36, 24, 25, 43, 25, -10, -39, -53, -47, -34, -39, -53, -56, -54, + -56, -42, -21, -23, -29, -25, -5, 1, -10, 12, 35, 27, 7, -14, -25, -19, + -11, -10, 13, 31, 37, 44, 42, 37, 45, 44, 24, 14, 13, 24, 40, 28, + 35, 23, 31, 35, 15, -16, -38, -53, -45, -37, -48, -56, -54, -63, -63, -40, + -23, -24, -27, -19, 3, 1, -11, 14, 33, 24, 5, -16, -28, -17, -6, -1, + 15, 38, 39, 38, 29, 36, 54, 42, 20, 20, 19, 32, 38, 30, 31, 23, + 33, 23, -1, -17, -35, -44, -43, -47, -51, -51, -56, -71, -67, -45, -28, -23, + -23, -13, 12, -1, -15, 15, 33, 20, -2, -22, -25, -17, -3, 10, 24, 46, + 44, 31, 26, 41, 53, 42, 23, 23, 26, 39, 37, 32, 24, 28, 36, 11, + -7, -19, -38, -39, -37, -49, -54, -51, -62, -76, -68, -51, -28, -19, -21, 1, + 22, -3, -11, 14, 25, 16, -5, -25, -25, -15, -2, 20, 36, 51, 42, 19, + 19, 43, 58, 43, 25, 21, 35, 46, 41, 34, 17, 26, 33, 5, -15, -25, + -39, -34, -37, -55, -50, -49, -69, -80, -67, -50, -31, -18, -12, 12, 17, -5, + -5, 14, 17, 6, -15, -27, -22, -14, 3, 37, 49, 48, 40, 22, 22, 36, + 51, 44, 29, 22, 42, 49, 41, 29, 16, 29, 31, -9, -30, -33, -35, -29, + -38, -55, -45, -54, -79, -80, -65, -51, -34, -16, -2, 18, 18, 5, 7, 8, + 6, 3, -19, -21, -22, -19, 12, 51, 53, 48, 39, 22, 18, 36, 46, 42, + 35, 31, 44, 46, 42, 31, 24, 35, 21, -25, -39, -33, -30, -24, -41, -53, + -47, -60, -81, -81, -63, -53, -40, -14, 6, 24, 20, 8, 7, 0, -1, -4, + -21, -23, -29, -16, 30, 60, 55, 50, 37, 19, 19, 35, 43, 46, 37, 29, + 43, 49, 43, 32, 27, 31, 13, -35, -46, -36, -26, -28, -44, -52, -47, -65, + -84, -84, -68, -49, -27, 0, 10, 15, 19, 15, 9, -3, -10, -16, -20, -26, + -28, -2, 41, 59, 62, 56, 37, 16, 15, 31, 43, 50, 42, 30, 41, 49, + 49, 38, 28, 23, 5, -42, -55, -42, -21, -22, -40, -49, -54, -71, -86, -81, + -62, -44, -21, 5, 17, 16, 25, 23, 0, -13, -17, -17, -24, -32, -21, 15, + 45, 58, 66, 52, 33, 15, 9, 35, 42, 44, 44, 36, 38, 50, 52, 40, + 28, 16, -11, -48, -60, -43, -22, -21, -40, -53, -58, -78, -90, -79, -61, -42, + -9, 14, 15, 16, 22, 21, -4, -20, -21, -19, -30, -31, -10, 26, 54, 63, + 69, 51, 33, 12, 13, 40, 42, 45, 42, 33, 36, 53, 57, 44, 24, 3, + -24, -53, -63, -45, -21, -15, -39, -57, -63, -78, -89, -76, -55, -34, 3, 18, + 9, 16, 21, 15, -8, -26, -28, -25, -32, -24, 4, 34, 56, 67, 75, 48, + 22, 7, 23, 44, 39, 40, 40, 35, 40, 59, 59, 44, 18, -6, -31, -54, + -58, -44, -20, -13, -43, -63, -69, -80, -88, -71, -48, -21, 12, 16, 12, 18, + 13, 6, -12, -27, -32, -30, -34, -20, 13, 46, 63, 74, 73, 40, 15, 13, + 39, 46, 33, 32, 35, 36, 48, 58, 61, 43, 16, -13, -36, -57, -62, -41, + -22, -16, -42, -66, -73, -79, -85, -65, -38, -7, 13, 9, 7, 16, 11, -2, + -18, -36, -39, -26, -25, -16, 21, 53, 64, 74, 68, 36, 19, 22, 38, 44, + 32, 28, 32, 38, 52, 60, 56, 43, 13, -25, -39, -54, -52, -35, -30, -27, + -46, -70, -79, -80, -79, -58, -26, 3, 15, 6, 0, 12, 6, -8, -27, -45, + -39, -17, -16, -13, 28, 57, 67, 71, 57, 37, 22, 25, 41, 46, 29, 24, + 34, 44, 56, 55, 52, 44, 7, -27, -38, -48, -44, -35, -31, -29, -46, -77, + -83, -73, -70, -48, -15, 6, 9, 1, 1, 9, -3, -20, -41, -48, -30, -5, + -14, -9, 39, 63, 70, 66, 47, 36, 25, 32, 40, 43, 26, 21, 36, 47, + 59, 50, 49, 35, 0, -26, -36, -44, -41, -36, -35, -33, -50, -79, -79, -66, + -63, -36, -8, 6, -3, -9, 2, 3, -13, -30, -49, -46, -18, -2, -15, 4, + 42, 58, 65, 61, 50, 38, 28, 37, 40, 38, 28, 30, 38, 48, 50, 42, + 46, 28, -3, -28, -37, -36, -36, -39, -36, -37, -59, -79, -69, -62, -52, -24, + -2, 3, -12, -11, 4, -5, -29, -42, -53, -39, -12, -4, -4, 14, 37, 52, + 63, 58, 50, 37, 34, 37, 36, 37, 38, 36, 35, 47, 46, 44, 42, 18, + -7, -30, -34, -32, -34, -41, -37, -45, -66, -74, -64, -57, -36, -12, 1, -8, + -23, -7, 6, -18, -39, -49, -53, -29, -5, -1, 10, 19, 30, 46, 59, 58, + 50, 36, 37, 37, 32, 40, 46, 38, 34, 44, 42, 41, 36, 9, -9, -27, + -29, -26, -34, -40, -40, -56, -69, -66, -56, -46, -22, -7, -7, -19, -21, 3, + 1, -35, -48, -53, -49, -22, -3, 12, 23, 18, 22, 46, 66, 59, 47, 38, + 43, 35, 30, 46, 51, 39, 33, 41, 37, 42, 24, 2, -8, -22, -23, -24, + -33, -39, -50, -66, -69, -59, -49, -31, -13, -10, -17, -25, -16, 1, -17, -50, + -55, -58, -42, -17, -1, 20, 31, 14, 15, 48, 70, 59, 42, 38, 45, 33, + 33, 51, 53, 36, 35, 37, 36, 37, 12, 0, -9, -16, -18, -22, -33, -42, + -59, -67, -62, -52, -40, -20, -11, -15, -23, -23, -11, -3, -28, -51, -59, -61, + -38, -14, 4, 26, 30, 10, 18, 53, 71, 56, 40, 42, 45, 32, 34, 53, + 52, 37, 36, 32, 37, 32, 10, -3, -10, -10, -11, -17, -31, -46, -62, -63, + -54, -44, -30, -14, -14, -23, -27, -22, -11, -11, -35, -51, -65, -59, -32, -11, + 11, 29, 25, 8, 24, 63, 73, 51, 38, 46, 44, 29, 34, 51, 51, 39, + 34, 27, 34, 23, 3, -5, -9, -6, -10, -18, -33, -51, -66, -60, -50, -35, + -20, -10, -21, -33, -29, -17, -9, -20, -39, -55, -71, -57, -26, -7, 11, 23, + 22, 11, 35, 70, 71, 46, 39, 48, 42, 29, 33, 51, 47, 38, 31, 28, + 35, 17, 0, -12, -7, 0, -4, -15, -36, -56, -67, -56, -42, -26, -15, -12, + -29, -36, -28, -15, -13, -25, -40, -58, -70, -49, -23, -6, 8, 19, 17, 18, + 49, 76, 66, 40, 42, 49, 39, 25, 35, 51, 43, 40, 30, 31, 32, 15, + -1, -14, -7, 1, -2, -17, -40, -59, -61, -51, -38, -21, -10, -17, -34, -35, + -28, -18, -17, -24, -40, -64, -65, -40, -18, -8, 5, 13, 17, 31, 61, 75, + 60, 41, 43, 47, 34, 20, 36, 47, 43, 41, 31, 32, 26, 7, -7, -16, + -6, 0, -3, -22, -44, -60, -56, -47, -34, -19, -8, -20, -39, -40, -27, -18, + -20, -29, -44, -63, -56, -38, -23, -11, 4, 14, 21, 42, 65, 71, 59, 45, + 42, 34, 21, 20, 42, 48, 44, 41, 31, 34, 24, 6, -10, -20, -11, 4, + 0, -20, -48, -57, -47, -39, -30, -17, -4, -24, -43, -40, -26, -19, -24, -29, + -45, -59, -51, -37, -25, -14, 3, 15, 27, 51, 72, 76, 61, 44, 38, 23, + 12, 21, 43, 46, 45, 40, 31, 35, 21, 5, -17, -22, -13, 3, 1, -24, + -51, -52, -43, -37, -28, -8, -7, -38, -46, -36, -21, -21, -31, -33, -45, -51, + -47, -40, -30, -13, 4, 14, 33, 60, 76, 76, 61, 47, 30, 16, 8, 20, + 40, 45, 48, 37, 37, 37, 22, 3, -19, -20, -10, 4, -6, -30, -49, -44, + -41, -38, -23, -1, -14, -41, -44, -36, -22, -26, -35, -33, -45, -52, -48, -40, + -32, -9, 6, 18, 35, 65, 85, 80, 62, 46, 24, 6, -1, 23, 41, 48, + 45, 31, 42, 40, 23, -6, -21, -15, -6, 0, -13, -31, -44, -41, -38, -32, + -15, 0, -22, -40, -41, -36, -24, -31, -28, -32, -46, -49, -47, -43, -30, -6, + 9, 19, 46, 77, 87, 77, 61, 42, 18, -2, -7, 22, 39, 51, 41, 32, + 43, 35, 13, -18, -18, -10, -5, -8, -21, -29, -39, -42, -41, -23, -3, -3, + -32, -39, -38, -34, -31, -35, -23, -32, -46, -50, -51, -46, -26, 0, 12, 20, + 54, 87, 91, 72, 60, 38, 13, -10, -11, 24, 44, 52, 43, 39, 45, 34, + 2, -19, -8, -1, -8, -19, -19, -25, -35, -42, -39, -17, 7, -7, -38, -36, + -36, -37, -37, -31, -20, -34, -49, -53, -50, -43, -19, 6, 10, 25, 66, 91, + 84, 67, 60, 36, 1, -18, -10, 27, 48, 52, 42, 42, 38, 25, -3, -18, + -5, -2, -13, -22, -24, -28, -35, -45, -35, -4, 14, -17, -41, -36, -33, -35, + -41, -29, -20, -38, -51, -54, -46, -33, -14, 6, 14, 37, 74, 87, 76, 65, + 64, 29, -9, -22, -7, 23, 52, 55, 46, 42, 25, 17, -5, -12, -4, -3, + -17, -25, -33, -36, -33, -39, -30, 5, 12, -25, -37, -33, -34, -42, -41, -25, + -22, -41, -52, -53, -40, -25, -10, 11, 21, 43, 72, 78, 74, 69, 58, 15, + -13, -15, -4, 22, 54, 58, 53, 41, 15, 6, -2, -1, -3, -6, -18, -24, + -42, -40, -29, -32, -20, 13, 8, -25, -35, -34, -29, -42, -43, -27, -27, -42, + -51, -50, -30, -14, -5, 17, 26, 46, 70, 72, 72, 69, 48, 2, -13, -9, + -3, 19, 55, 59, 53, 30, 1, -1, 5, 8, -7, -15, -19, -25, -48, -45, + -31, -28, -10, 15, 1, -24, -35, -35, -22, -37, -43, -36, -35, -41, -47, -45, + -18, -6, -1, 24, 32, 51, 65, 65, 67, 63, 37, -3, -13, -9, 1, 29, + 54, 60, 50, 18, -4, -4, 13, 9, -10, -15, -17, -30, -54, -47, -29, -20, + -8, 4, -8, -15, -29, -35, -21, -37, -43, -46, -37, -33, -48, -39, -10, 3, + 13, 31, 34, 54, 56, 57, 63, 56, 32, -3, -16, -6, 14, 38, 48, 53, + 40, 11, -3, 1, 6, -2, -11, -9, -11, -28, -54, -54, -29, -8, 2, -8, + -16, -13, -27, -31, -21, -32, -45, -54, -36, -27, -44, -33, 1, 16, 25, 29, + 39, 56, 48, 51, 57, 48, 22, 3, -14, 0, 22, 39, 42, 46, 36, 7, + -7, 0, 0, -3, -8, -8, -15, -34, -50, -49, -27, -3, 0, -15, -14, -16, + -28, -26, -21, -34, -56, -55, -32, -30, -41, -23, 8, 20, 31, 33, 45, 53, + 38, 42, 54, 40, 18, -3, -9, 14, 33, 37, 34, 34, 27, 8, -5, -1, + -9, -3, -1, -8, -19, -35, -43, -42, -28, -7, 1, -18, -13, -17, -29, -24, + -21, -34, -55, -52, -34, -30, -26, -9, 15, 28, 28, 32, 55, 50, 29, 38, + 45, 35, 17, -3, -1, 18, 36, 40, 27, 24, 19, 0, -5, -1, -14, -7, + -2, -12, -20, -30, -40, -42, -25, -5, -5, -24, -14, -16, -25, -20, -26, -38, + -52, -49, -35, -31, -13, 8, 16, 28, 29, 42, 57, 40, 23, 32, 35, 30, + 12, -5, 9, 22, 40, 38, 19, 17, 16, -1, -9, -7, -12, -6, -5, -13, + -18, -29, -39, -39, -18, -3, -19, -26, -11, -18, -24, -19, -30, -40, -51, -45, + -30, -24, 0, 19, 22, 28, 36, 49, 54, 41, 22, 30, 31, 26, 10, 2, + 10, 26, 43, 28, 14, 16, 7, -6, -12, -9, -9, -5, -12, -19, -16, -29, + -35, -34, -8, -8, -35, -20, -7, -26, -23, -23, -30, -39, -53, -38, -25, -12, + 11, 24, 24, 29, 47, 50, 48, 36, 20, 29, 24, 15, 5, 8, 12, 32, + 40, 21, 17, 11, 0, -3, -15, -14, -7, -4, -13, -17, -16, -28, -31, -23, + -6, -20, -37, -15, -12, -29, -22, -28, -30, -38, -54, -34, -20, -4, 21, 33, + 24, 33, 50, 45, 40, 33, 27, 28, 14, 8, 8, 11, 11, 30, 33, 26, + 20, -1, -8, -4, -17, -16, -2, -7, -22, -20, -20, -26, -26, -15, -10, -27, + -35, -12, -19, -31, -21, -23, -23, -42, -57, -31, -11, 9, 35, 33, 23, 39, + 53, 47, 40, 31, 31, 21, 10, 9, 11, 10, 13, 26, 35, 33, 13, -11, + -10, -4, -19, -22, 3, -2, -28, -26, -16, -21, -24, -12, -12, -31, -34, -17, + -27, -34, -25, -17, -19, -48, -59, -29, -2, 27, 46, 26, 22, 43, 54, 44, + 38, 30, 29, 16, 6, 15, 15, 6, 9, 22, 36, 37, 9, -20, -10, -5, + -21, -21, 2, -5, -29, -31, -18, -11, -17, -11, -15, -32, -34, -23, -30, -30, + -25, -15, -22, -52, -50, -17, 9, 36, 42, 26, 29, 50, 53, 40, 33, 32, + 27, 14, 7, 9, 7, 4, 12, 22, 36, 36, 3, -27, -16, -9, -20, -21, + -1, -12, -31, -27, -13, -12, -18, -12, -17, -33, -39, -29, -34, -35, -23, -7, + -25, -55, -42, -10, 20, 43, 40, 27, 33, 51, 51, 37, 34, 31, 21, 9, + 8, 5, 2, 11, 16, 18, 34, 35, 3, -22, -17, -16, -20, -17, -7, -20, + -32, -28, -14, -12, -10, -8, -17, -34, -41, -35, -34, -31, -19, -8, -27, -48, + -29, -4, 26, 50, 44, 32, 37, 50, 49, 40, 36, 22, 11, 11, 12, 5, + 3, 14, 12, 13, 34, 37, 9, -23, -24, -16, -21, -16, -17, -30, -27, -27, + -20, -10, -10, -9, -18, -39, -46, -42, -35, -31, -14, -9, -33, -42, -19, 1, + 36, 55, 41, 32, 46, 55, 47, 35, 32, 18, 6, 7, 9, -2, 7, 17, + 8, 13, 34, 32, 10, -22, -27, -14, -20, -21, -26, -31, -23, -27, -22, -6, + -5, -11, -21, -39, -46, -46, -37, -30, -14, -12, -33, -31, -8, 6, 41, 55, + 40, 38, 54, 57, 39, 30, 33, 17, 2, 1, 4, 7, 14, 14, -2, 11, + 37, 31, 11, -26, -30, -16, -20, -18, -21, -27, -32, -28, -12, 0, -4, -11, + -23, -40, -46, -43, -33, -26, -16, -15, -29, -19, -1, 13, 44, 58, 41, 49, + 68, 59, 36, 28, 36, 18, -9, -9, 4, 17, 20, 7, -6, 18, 36, 22, + -1, -30, -26, -19, -25, -26, -31, -35, -33, -21, -3, -8, -10, -14, -24, -40, + -45, -43, -35, -20, -18, -20, -22, -12, 0, 15, 48, 58, 41, 58, 77, 57, + 30, 27, 33, 7, -23, -16, 11, 23, 21, 2, -5, 24, 33, 10, -10, -24, + -19, -25, -37, -30, -30, -34, -29, -14, -5, -16, -8, -8, -26, -50, -47, -41, + -30, -16, -25, -24, -14, -6, 3, 23, 50, 51, 49, 69, 81, 56, 29, 33, + 30, -2, -29, -14, 15, 26, 18, 2, -1, 31, 28, 0, -20, -21, -21, -32, + -43, -34, -33, -36, -23, -4, -8, -20, -8, -11, -25, -44, -41, -39, -32, -17, + -30, -22, -4, 1, 6, 31, 48, 47, 63, 80, 82, 52, 31, 38, 23, -13, + -33, -11, 20, 29, 14, -1, 9, 34, 19, -12, -26, -13, -23, -46, -46, -38, + -39, -35, -24, -3, -7, -17, -15, -16, -25, -45, -37, -37, -33, -26, -36, -20, + 5, 3, 4, 32, 42, 50, 76, 83, 75, 49, 34, 36, 17, -24, -33, -12, + 23, 32, 10, 1, 23, 30, 7, -17, -22, -8, -27, -49, -50, -42, -38, -28, + -18, -3, -8, -13, -14, -15, -24, -43, -35, -33, -29, -27, -34, -15, 16, 8, + 5, 32, 43, 62, 84, 84, 73, 53, 40, 30, 6, -26, -34, -15, 25, 28, + 8, 9, 38, 27, -4, -26, -21, -12, -33, -54, -47, -48, -38, -21, -14, -2, + -3, -11, -25, -18, -26, -32, -34, -34, -29, -31, -35, -10, 18, 11, 7, 33, + 47, 68, 83, 81, 71, 58, 42, 20, -5, -25, -36, -15, 23, 23, 7, 20, + 40, 21, -14, -35, -21, -16, -40, -58, -52, -52, -31, -11, -9, -6, -1, -15, + -26, -15, -29, -31, -36, -31, -29, -36, -32, -4, 17, 8, 15, 36, 48, 66, + 77, 83, 77, 59, 38, 9, -11, -20, -34, -12, 22, 20, 14, 33, 39, 16, + -22, -36, -23, -21, -40, -56, -52, -47, -24, -10, -4, 3, 1, -17, -22, -18, + -28, -26, -32, -30, -32, -30, -22, 1, 15, 15, 27, 42, 52, 62, 75, 85, + 80, 59, 35, 1, -16, -20, -35, -12, 18, 17, 18, 40, 34, 5, -34, -38, + -27, -28, -42, -60, -58, -48, -18, -4, 0, 3, -4, -18, -20, -22, -35, -29, + -27, -34, -42, -28, -12, 3, 8, 19, 31, 40, 45, 60, 75, 79, 76, 62, + 37, -2, -20, -22, -31, -11, 13, 15, 31, 43, 27, 0, -28, -33, -36, -37, + -43, -58, -61, -47, -13, 1, 1, 3, -5, -12, -17, -25, -36, -27, -25, -39, + -45, -24, 1, 0, 8, 25, 43, 45, 42, 57, 76, 76, 73, 60, 37, -8, + -25, -22, -25, -6, 9, 21, 41, 41, 15, -6, -18, -33, -48, -40, -38, -57, + -64, -46, -6, 9, -4, 1, -1, -9, -18, -28, -33, -24, -27, -42, -45, -18, + 2, 3, 13, 31, 49, 43, 37, 60, 74, 68, 68, 60, 30, -12, -28, -23, + -19, -8, 5, 26, 48, 37, 11, -12, -17, -37, -54, -40, -41, -58, -65, -42, + 5, 12, -8, 0, 2, -6, -22, -29, -30, -28, -37, -44, -42, -9, 6, 7, + 17, 33, 44, 42, 40, 61, 72, 57, 63, 61, 24, -16, -34, -21, -15, -12, + 3, 31, 47, 28, 7, -10, -15, -43, -51, -38, -45, -61, -61, -31, 10, 8, + -3, 6, 5, -8, -24, -27, -28, -31, -44, -42, -29, -3, 6, 10, 24, 40, + 44, 45, 46, 57, 62, 56, 65, 56, 16, -13, -32, -18, -12, -10, 11, 32, + 39, 25, 6, -10, -19, -48, -44, -38, -49, -63, -61, -19, 12, 3, 4, 6, + 3, -9, -25, -26, -27, -38, -46, -39, -18, 1, 12, 20, 29, 33, 36, 49, + 47, 54, 59, 49, 63, 51, 8, -12, -25, -18, -18, -6, 20, 33, 28, 19, + 4, -9, -27, -43, -41, -45, -55, -64, -51, -13, 7, -3, 0, 7, 3, -12, + -28, -27, -33, -46, -51, -33, -10, -5, 15, 31, 34, 26, 32, 47, 51, 53, + 47, 50, 61, 41, 1, -8, -12, -21, -20, 5, 27, 29, 16, 13, 8, -9, + -28, -40, -40, -44, -55, -62, -40, -8, 5, -2, 4, 11, 4, -15, -26, -26, + -37, -49, -47, -27, -8, -3, 22, 45, 38, 22, 34, 47, 55, 52, 39, 44, + 58, 32, 2, 0, -7, -25, -21, 10, 29, 30, 9, 0, 0, -7, -26, -38, + -40, -53, -61, -53, -30, -5, 1, -2, 5, 10, 3, -18, -25, -33, -43, -51, + -46, -20, -10, -8, 26, 52, 35, 19, 32, 47, 56, 46, 33, 44, 48, 20, + 10, 11, -7, -29, -20, 15, 35, 28, 2, -9, -8, -6, -26, -32, -36, -54, + -64, -52, -22, 1, 3, 2, 3, 15, 2, -22, -24, -34, -41, -45, -39, -19, + -9, 1, 35, 57, 37, 18, 27, 46, 52, 41, 37, 44, 40, 18, 16, 13, + -7, -29, -14, 23, 36, 17, -6, -17, -2, 1, -24, -38, -43, -59, -62, -44, + -22, -4, 7, 2, 5, 16, -2, -24, -27, -36, -43, -48, -37, -20, -5, 14, + 40, 52, 36, 20, 26, 43, 46, 40, 41, 42, 28, 19, 19, 9, -4, -21, + -10, 27, 32, 10, -6, -16, -4, -5, -14, -37, -48, -59, -58, -36, -24, -1, + 13, -3, 7, 16, -5, -19, -32, -38, -46, -43, -32, -22, -7, 22, 49, 57, + 37, 22, 20, 37, 41, 36, 46, 41, 21, 19, 16, 9, -2, -25, -9, 27, + 24, 8, -12, -11, -2, -9, -10, -39, -51, -59, -59, -35, -21, 2, 15, -5, + 10, 11, -12, -19, -35, -39, -46, -35, -29, -26, -5, 37, 60, 53, 36, 26, + 19, 33, 37, 33, 48, 41, 18, 17, 19, 11, -8, -23, -3, 30, 21, -5, + -14, -2, -6, -9, -9, -42, -59, -64, -54, -33, -16, 6, 14, 0, 15, 4, + -14, -17, -35, -45, -46, -33, -27, -22, 2, 42, 56, 49, 37, 26, 19, 26, + 23, 36, 58, 44, 11, 8, 23, 10, -7, -15, 3, 26, 12, -10, -8, 3, + -10, -7, -13, -46, -58, -60, -57, -40, -11, 9, 9, 3, 13, -6, -12, -17, + -42, -53, -45, -28, -23, -14, 11, 49, 60, 49, 40, 27, 14, 16, 13, 43, + 62, 46, 6, 8, 22, 7, -9, -10, 11, 23, 4, -17, 2, 6, -6, -7, + -21, -51, -58, -58, -55, -38, -12, 12, 10, 13, 1, -15, -7, -14, -47, -62, + -45, -29, -19, -2, 21, 51, 63, 46, 37, 31, 16, 0, 4, 43, 64, 43, + 6, 9, 24, 4, -15, -2, 14, 9, -9, -15, 14, 7, -11, -10, -29, -53, + -54, -57, -48, -35, -9, 13, 9, 11, -5, -6, -2, -22, -57, -60, -39, -24, + -11, 5, 30, 52, 62, 49, 42, 38, 11, -9, 7, 45, 61, 44, 10, 15, + 21, -4, -15, 3, 13, 1, -13, -9, 13, 7, -9, -13, -32, -51, -53, -56, + -44, -35, -9, 15, 11, 7, -8, 0, -2, -34, -65, -56, -31, -24, -7, 20, + 37, 49, 56, 47, 47, 39, -3, -16, 12, 40, 53, 45, 16, 23, 17, -7, + -8, 7, 8, -5, -12, -7, 7, 7, -4, -17, -38, -56, -60, -50, -37, -33, + -8, 7, 9, 0, -6, 7, -8, -47, -71, -50, -25, -23, 0, 33, 41, 46, + 52, 53, 54, 35, -6, -9, 13, 32, 50, 48, 23, 25, 13, -4, -3, 0, + -1, -7, -7, -8, 3, 6, -3, -22, -41, -55, -62, -46, -30, -24, -5, 0, + 5, 2, 3, 10, -20, -57, -69, -41, -19, -16, 5, 37, 47, 46, 49, 54, + 58, 29, -4, -6, 7, 21, 49, 49, 24, 24, 12, -2, -5, -9, 0, 0, + -10, -15, 2, 8, -4, -23, -42, -57, -66, -43, -22, -16, -11, -8, 3, 5, + 7, 4, -28, -61, -61, -36, -19, -11, 10, 45, 51, 43, 46, 52, 54, 26, + 3, -8, -3, 15, 52, 48, 27, 30, 15, -1, -9, -14, 0, -2, -15, -17, + -2, -1, -5, -23, -37, -62, -64, -34, -17, -15, -19, -8, 4, 7, 8, -8, + -37, -55, -50, -33, -19, -5, 16, 49, 54, 44, 45, 52, 53, 32, 3, -12, + -5, 14, 46, 46, 38, 34, 21, 6, -13, -21, -2, -3, -18, -19, -14, -9, + -2, -14, -44, -74, -56, -26, -15, -16, -18, -6, -1, 7, 6, -20, -43, -48, + -35, -32, -24, 1, 23, 51, 54, 41, 42, 52, 49, 32, 3, -14, -5, 19, + 42, 47, 43, 38, 27, 10, -18, -19, -5, -7, -18, -27, -23, -9, 2, -8, + -51, -75, -41, -19, -15, -13, -15, -11, -5, 10, 1, -30, -37, -40, -30, -33, + -24, 6, 30, 49, 49, 45, 43, 52, 39, 24, 7, -10, -7, 12, 33, 44, + 48, 43, 36, 7, -29, -18, -6, -14, -23, -36, -32, -12, 2, -16, -60, -65, + -27, -22, -22, -9, -6, -14, -6, 11, -10, -38, -35, -27, -26, -35, -15, 18, + 39, 47, 48, 51, 55, 51, 28, 22, 13, -5, -6, 5, 27, 46, 57, 49, + 39, 1, -29, -12, -7, -15, -28, -48, -39, -11, -1, -28, -61, -51, -22, -30, + -22, -3, -4, -21, -6, 8, -23, -45, -29, -18, -27, -32, -11, 24, 44, 40, + 46, 56, 61, 44, 17, 18, 19, 1, -11, -2, 24, 48, 57, 54, 45, 2, + -27, -12, -11, -18, -32, -49, -41, -16, -10, -32, -47, -33, -25, -34, -13, 6, + -5, -24, -13, -4, -29, -43, -29, -18, -25, -21, -1, 25, 44, 40, 49, 67, + 60, 31, 12, 18, 24, -2, -18, -5, 22, 45, 62, 65, 46, -5, -21, -12, + -12, -17, -36, -57, -48, -23, -15, -29, -35, -28, -33, -31, -3, 12, -16, -32, + -12, -19, -36, -33, -25, -22, -29, -10, 14, 30, 41, 35, 51, 73, 57, 27, + 16, 21, 14, -4, -12, -2, 21, 41, 62, 71, 43, -7, -12, -19, -22, -23, + -46, -57, -51, -35, -20, -17, -22, -26, -37, -27, 7, 12, -24, -31, -14, -29, + -34, -30, -22, -20, -21, 2, 15, 26, 40, 45, 55, 66, 52, 28, 20, 17, + 10, -1, -12, -4, 21, 43, 65, 74, 39, 1, -9, -25, -27, -24, -45, -61, + -55, -43, -22, -9, -12, -24, -32, -26, 9, 7, -25, -31, -30, -40, -31, -26, + -19, -20, -11, 14, 18, 27, 45, 54, 52, 61, 49, 33, 24, 15, 5, 0, + -14, -2, 24, 44, 62, 67, 37, 12, -9, -30, -29, -33, -49, -66, -58, -51, + -25, -2, -6, -19, -31, -24, 6, 3, -21, -37, -43, -42, -31, -25, -17, -19, + -5, 15, 19, 30, 52, 56, 45, 54, 52, 38, 22, 11, 8, 0, -16, 2, + 27, 44, 63, 60, 34, 16, -10, -25, -31, -38, -55, -68, -62, -53, -18, 5, + -2, -17, -31, -16, 5, -4, -22, -43, -50, -38, -32, -21, -16, -11, 8, 10, + 19, 32, 60, 60, 43, 46, 51, 37, 24, 13, 8, -6, -17, 4, 32, 52, + 56, 52, 39, 23, -5, -23, -41, -48, -64, -65, -63, -57, -14, 9, 3, -18, + -28, -9, 0, -11, -25, -47, -53, -38, -30, -19, -11, 0, 10, 11, 23, 42, + 66, 60, 42, 49, 53, 36, 24, 20, 9, -17, -18, 3, 39, 59, 49, 41, + 39, 26, 1, -24, -53, -59, -70, -61, -66, -58, -12, 17, 7, -20, -26, -7, + -7, -16, -30, -51, -60, -45, -26, -11, -5, 5, 8, 10, 23, 48, 66, 55, + 40, 48, 48, 33, 30, 25, 2, -21, -15, 10, 41, 51, 44, 37, 41, 27, + 6, -28, -60, -65, -70, -63, -70, -55, -6, 21, 1, -20, -15, -2, -15, -24, + -32, -54, -66, -45, -22, -8, 6, 13, 5, 15, 31, 51, 64, 58, 41, 42, + 44, 35, 36, 29, 0, -20, -9, 14, 43, 53, 46, 39, 39, 24, 7, -33, + -69, -75, -73, -70, -75, -46, 4, 17, -2, -18, -6, 3, -18, -32, -38, -61, + -65, -39, -17, -2, 10, 10, 5, 19, 33, 55, 61, 54, 39, 40, 41, 41, + 40, 30, -6, -25, -6, 22, 44, 48, 42, 42, 37, 23, 11, -42, -73, -77, + -75, -74, -75, -39, 4, 8, -5, -15, 1, -1, -30, -33, -38, -69, -66, -40, + -14, 3, 16, 8, 5, 21, 39, 60, 59, 48, 40, 38, 39, 42, 42, 30, + -8, -20, 0, 26, 48, 51, 48, 43, 29, 21, 1, -47, -70, -80, -83, -80, + -70, -25, 0, -2, -9, -6, 9, -7, -29, -33, -49, -72, -59, -29, -3, 3, + 11, 6, 14, 27, 47, 61, 54, 47, 43, 34, 42, 45, 39, 21, -10, -17, + 4, 29, 53, 54, 47, 39, 29, 22, -11, -53, -70, -83, -86, -77, -61, -19, + -6, -7, -12, -2, 9, -14, -29, -35, -61, -70, -54, -25, -8, 2, 11, 8, + 17, 27, 54, 60, 50, 45, 42, 40, 43, 39, 35, 18, -9, -7, 8, 28, + 55, 56, 49, 32, 30, 15, -21, -53, -71, -88, -87, -74, -45, -12, -11, -15, + -14, 6, 12, -12, -30, -48, -66, -60, -44, -18, -8, 5, 13, 15, 21, 31, + 51, 57, 48, 43, 42, 40, 43, 37, 29, 16, -3, -1, 7, 35, 60, 54, + 38, 26, 29, 5, -30, -54, -72, -93, -87, -69, -34, -14, -19, -25, -12, 13, + 6, -17, -37, -56, -66, -49, -38, -18, -11, 1, 17, 24, 26, 32, 47, 52, + 50, 49, 45, 39, 40, 33, 32, 13, 4, 3, 3, 47, 65, 52, 29, 27, + 20, -5, -35, -56, -76, -90, -79, -63, -27, -17, -26, -24, 0, 12, -2, -16, + -33, -61, -61, -42, -33, -17, -16, -6, 22, 30, 25, 29, 45, 50, 46, 53, + 41, 37, 37, 33, 28, 17, 15, 2, 15, 54, 64, 46, 21, 25, 9, -12, + -39, -58, -77, -87, -75, -46, -21, -23, -34, -24, 9, 9, -7, -17, -40, -67, + -53, -33, -27, -22, -26, -4, 34, 34, 25, 27, 46, 44, 52, 59, 37, 30, + 35, 32, 26, 25, 16, 2, 30, 62, 57, 33, 19, 17, -7, -25, -43, -58, + -80, -82, -64, -36, -26, -26, -33, -17, 11, 4, -9, -18, -45, -62, -44, -30, + -24, -28, -29, 5, 38, 32, 25, 30, 48, 41, 53, 57, 35, 28, 26, 27, + 31, 29, 14, 12, 47, 63, 48, 35, 24, 4, -19, -32, -46, -55, -76, -77, + -58, -31, -30, -33, -36, -8, 12, -4, -9, -22, -51, -57, -30, -23, -27, -40, + -31, 18, 36, 31, 30, 33, 39, 36, 56, 51, 32, 27, 20, 24, 39, 30, + 16, 29, 55, 53, 43, 36, 21, -5, -28, -39, -45, -55, -71, -70, -47, -27, + -35, -36, -25, -2, 1, -4, -6, -23, -48, -48, -25, -16, -25, -46, -23, 24, + 30, 35, 34, 29, 33, 37, 51, 41, 30, 21, 12, 27, 47, 33, 19, 38, + 51, 43, 39, 36, 15, -17, -35, -35, -42, -55, -68, -62, -45, -33, -40, -36, + -19, -5, -4, -3, -6, -24, -47, -38, -17, -13, -37, -48, -13, 26, 30, 36, + 32, 27, 29, 36, 48, 38, 27, 9, 5, 34, 47, 31, 30, 49, 47, 36, + 38, 28, 11, -21, -32, -32, -47, -56, -60, -54, -40, -39, -42, -31, -12, -5, + -7, -1, -4, -21, -39, -28, -11, -13, -45, -42, -2, 23, 25, 42, 33, 26, + 26, 33, 44, 34, 20, 1, 5, 36, 47, 38, 40, 47, 37, 35, 38, 20, + 1, -23, -26, -35, -49, -56, -55, -48, -40, -46, -42, -28, -12, -12, -10, 2, + -6, -25, -32, -25, -13, -22, -43, -30, 5, 18, 24, 45, 35, 29, 21, 27, + 39, 28, 16, 2, 9, 39, 40, 44, 55, 45, 25, 31, 34, 15, -1, -18, + -25, -41, -49, -50, -52, -46, -42, -48, -40, -23, -9, -18, -13, 9, -1, -24, + -27, -22, -14, -30, -41, -26, 8, 15, 25, 40, 36, 26, 15, 26, 35, 21, + 11, 2, 17, 44, 37, 54, 63, 37, 16, 31, 27, 12, -3, -12, -24, -45, + -47, -46, -45, -40, -44, -55, -40, -17, -12, -22, -7, 19, -2, -22, -24, -15, + -17, -36, -36, -11, 16, 10, 17, 38, 43, 25, 15, 25, 26, 14, 7, 2, + 25, 39, 38, 63, 67, 30, 16, 25, 18, 14, -5, -9, -26, -43, -45, -47, + -42, -38, -52, -57, -35, -14, -22, -27, 0, 23, -5, -24, -22, -12, -21, -40, + -31, 1, 19, 6, 11, 35, 44, 22, 18, 28, 14, 4, 4, 11, 32, 34, + 38, 70, 68, 22, 18, 17, 15, 17, 0, -10, -31, -45, -43, -42, -34, -36, + -62, -61, -25, -11, -28, -29, 3, 25, -3, -26, -15, -12, -28, -34, -21, 9, + 17, 2, 10, 31, 40, 24, 23, 28, 5, -3, 6, 19, 35, 33, 42, 72, + 59, 22, 22, 12, 17, 17, 2, -11, -31, -40, -40, -36, -28, -40, -66, -57, + -18, -15, -32, -22, 9, 22, -3, -23, -8, -12, -31, -32, -12, 18, 15, -1, + 9, 25, 36, 26, 27, 20, -7, -5, 12, 23, 29, 33, 45, 70, 48, 25, + 20, 8, 16, 9, 4, -11, -33, -39, -37, -34, -30, -46, -65, -50, -23, -22, + -30, -19, 13, 22, -4, -21, -6, -15, -32, -28, -3, 18, 9, 0, 9, 21, + 30, 28, 30, 12, -14, -1, 17, 19, 27, 41, 51, 63, 35, 28, 22, 12, + 10, 6, 9, -14, -31, -36, -31, -27, -38, -49, -62, -48, -29, -25, -27, -13, + 13, 13, -3, -9, -9, -21, -30, -20, 4, 12, 4, 5, 12, 19, 27, 33, + 29, 6, -12, 2, 21, 17, 31, 45, 54, 55, 31, 31, 25, 14, 3, 5, + 11, -14, -27, -33, -24, -27, -41, -49, -63, -53, -37, -26, -22, -7, 11, 8, + 0, -3, -14, -19, -27, -14, 8, 5, 2, 9, 12, 20, 25, 31, 18, 0, + -6, 8, 20, 14, 27, 43, 59, 48, 24, 28, 25, 14, 2, 8, 6, -15, + -26, -30, -16, -28, -44, -53, -61, -58, -37, -27, -21, -4, 8, 3, 1, -2, + -18, -21, -24, -11, 3, -4, 3, 15, 17, 20, 22, 29, 15, 3, -2, 8, + 17, 18, 30, 46, 56, 40, 21, 29, 26, 14, -1, 5, 4, -6, -22, -29, + -13, -27, -46, -51, -62, -61, -37, -28, -14, 2, 7, 0, 5, -2, -16, -17, + -19, -10, -7, -9, 11, 20, 22, 18, 17, 25, 19, 4, -1, 10, 19, 25, + 32, 44, 53, 36, 19, 29, 24, 10, -4, 5, 4, -2, -22, -24, -13, -31, + -48, -56, -63, -60, -40, -31, -11, 8, 8, 2, 8, -6, -20, -17, -12, -10, + -20, -12, 14, 30, 26, 10, 14, 24, 24, -1, -7, 12, 25, 27, 30, 40, + 52, 34, 17, 28, 24, 7, -9, 1, 8, 3, -20, -20, -16, -33, -53, -59, + -62, -61, -47, -29, -5, 15, 5, 1, 9, -8, -20, -14, -5, -12, -30, -11, + 20, 37, 25, 10, 19, 25, 19, -5, -2, 18, 28, 26, 29, 41, 49, 31, + 20, 30, 24, 1, -8, 4, 10, 3, -17, -12, -18, -40, -57, -61, -62, -59, + -48, -23, 0, 18, 5, 5, 12, -9, -19, -9, -2, -20, -37, -7, 25, 39, + 23, 11, 25, 26, 10, -10, 5, 23, 24, 26, 30, 40, 42, 27, 23, 31, + 18, -7, -5, 2, 7, -1, -10, -10, -22, -45, -59, -63, -62, -58, -45, -21, + -1, 17, 10, 13, 7, -18, -21, -5, -3, -27, -38, -7, 26, 38, 21, 20, + 31, 23, 0, -9, 15, 25, 21, 28, 33, 35, 35, 29, 28, 31, 12, -5, + 0, 0, 4, 0, -3, -14, -27, -48, -57, -69, -66, -61, -40, -19, 1, 16, + 13, 16, -3, -18, -17, -4, -9, -30, -33, -1, 24, 35, 28, 34, 31, 16, + -4, -2, 22, 29, 20, 27, 38, 33, 30, 30, 31, 33, 9, 1, -3, -7, + 2, 6, -1, -22, -31, -50, -61, -74, -67, -52, -34, -25, 1, 19, 21, 14, + -8, -18, -14, -10, -14, -27, -26, -5, 21, 35, 38, 40, 31, 12, -1, 5, + 22, 29, 19, 31, 41, 28, 30, 28, 31, 28, 12, 7, -13, -11, -2, 13, + -5, -26, -32, -52, -67, -80, -65, -46, -34, -26, 2, 15, 25, 9, -8, -14, + -16, -10, -18, -25, -25, -9, 20, 37, 46, 35, 26, 10, 7, 8, 18, 27, + 18, 31, 39, 25, 29, 29, 34, 26, 20, 2, -18, -10, -5, 12, -9, -22, + -31, -48, -74, -79, -66, -42, -34, -22, -1, 14, 25, 13, -6, -19, -16, -8, + -19, -22, -21, -5, 21, 41, 51, 32, 25, 14, 19, 13, 14, 21, 21, 32, + 34, 26, 26, 30, 32, 25, 25, -3, -19, -13, -2, 8, -12, -24, -32, -46, + -75, -79, -67, -43, -33, -18, -7, 12, 25, 18, 0, -23, -13, -7, -23, -18, + -15, -4, 21, 48, 51, 27, 27, 23, 22, 12, 12, 19, 22, 28, 28, 28, + 28, 31, 28, 23, 28, -3, -20, -22, -5, 0, -14, -23, -28, -50, -78, -81, + -63, -44, -34, -19, -14, 10, 25, 18, -6, -19, -5, -11, -30, -17, -8, 2, + 21, 54, 45, 25, 28, 33, 25, 9, 12, 21, 26, 23, 24, 33, 37, 35, + 20, 23, 32, -1, -21, -25, -12, -11, -12, -19, -27, -53, -78, -79, -55, -42, + -31, -26, -18, 12, 24, 13, -9, -12, 0, -20, -33, -13, 1, 6, 26, 55, + 38, 25, 33, 45, 26, 7, 13, 21, 26, 16, 18, 38, 44, 33, 14, 25, + 30, 4, -24, -32, -21, -18, -19, -19, -25, -54, -79, -78, -53, -43, -29, -28, + -20, 6, 20, 12, -3, 0, -3, -35, -28, 1, 9, 8, 25, 46, 34, 30, + 37, 44, 19, 13, 20, 17, 20, 12, 18, 49, 49, 23, 13, 28, 33, 3, + -34, -37, -28, -30, -21, -10, -26, -57, -77, -74, -52, -40, -25, -32, -22, 3, + 17, 12, 3, 8, -15, -40, -18, 10, 10, 4, 32, 39, 27, 38, 48, 39, + 11, 18, 28, 17, 15, 5, 23, 61, 46, 21, 23, 35, 26, -3, -31, -37, + -39, -38, -23, -3, -29, -60, -74, -68, -58, -37, -27, -35, -22, -7, 15, 23, + 14, 8, -27, -41, -6, 19, 14, 9, 35, 31, 31, 48, 54, 35, 11, 27, + 26, 4, 7, 11, 31, 54, 38, 25, 34, 35, 20, -10, 19, 3, -8, -45, + 64, -15, -41, 23, 40, -58, 22, 29, -27, -28, 42, -36, 21, -12, -19, 39, + -14, 3, -18, 32, -27, 18, -8, -43, 43, 25, -52, 6, 19, 13, -7, -50, + 55, 5, -46, -22, 94, -53, -33, 35, 27, -45, -2, 20, 19, -30, -23, 47, + 8, -58, 5, 76, -67, -22, 42, 30, -54, 8, 23, 11, -51, 3, 47, -33, + -7, 5, 27, -33, 34, -35, 17, 4, -26, 5, 17, -30, 33, 5, -29, -5, + 44, -18, -50, 60, -33, 10, -5, 10, -7, 1, -5, 19, -36, 3, 37, -17, + -51, 52, 37, -64, 9, 4, 37, -44, -13, 25, 45, -75, -9, 79, -34, -57, + 53, 24, -59, 18, 22, -3, -24, 10, -2, 18, -53, 29, 35, -20, -43, 37, + 18, -17, -31, 8, 45, -49, 8, 11, 9, -23, 30, -24, -22, 29, 14, -43, + 27, 13, -22, -1, 2, 22, -37, 5, -5, 38, -43, 6, 36, -21, -20, 20, + 0, -5, -27, 27, 21, -53, 4, 52, -2, -84, 70, 5, -29, -19, 36, -6, + -8, -12, 3, 35, -32, -25, 48, 6, -60, 49, 4, -27, -13, 31, -15, -9, + -4, 31, -13, -25, 29, 12, -34, -6, 30, -41, 36, -23, 6, 31, -30, 0, + 17, -45, 47, -5, -47, 19, 28, -8, -30, 27, -6, 15, -54, 34, 21, -27, + -9, 25, 3, -45, 26, 27, -52, 22, 20, -29, 34, -46, 22, 40, -69, -27, + 108, -49, -54, 69, -11, -3, -18, 3, 15, -12, -23, 29, -8, 4, -23, 50, + -38, -8, 33, -32, -2, 26, -27, 12, 13, -39, 56, -31, -22, 28, 2, -39, + 54, -20, -36, 51, -6, -34, 15, 2, 1, 2, -36, 42, 2, -10, -39, 64, + -36, -16, 24, 1, -1, -18, -10, 54, -27, -54, 80, -18, -61, 51, 27, -76, + 64, -30, -1, 9, -19, 24, 13, -29, -13, 49, -18, -46, 43, 6, -47, 42, + -28, 14, 18, -18, 2, 14, -39, 25, 16, -58, 33, 29, -49, 16, 41, -62, + 43, -17, -17, 25, -10, -28, 41, -5, -30, 27, 14, -53, 27, 35, -63, 16, + 30, 0, -30, -10, 22, 31, -57, 0, 68, -59, 2, 37, -30, 6, -3, -19, + 35, -29, 1, 20, 22, -68, 33, 39, -71, 21, 27, -22, -1, 3, 0, 18, + -16, -13, 17, 4, -37, 44, -15, -26, 48, -29, -11, 34, -25, -4, 25, -48, + 43, 4, -49, 28, 42, -72, 7, 59, -36, -28, 45, -9, -28, 25, -19, 23, + -9, -40, 47, 18, -85, 78, -2, -53, 39, -17, 2, 14, -36, 10, 63, -78, + 17, 59, -66, -8, 54, -49, 14, 1, 5, 2, -18, 16, -12, 30, -58, 22, + 53, -83, 17, 79, -84, 19, 17, -34, 44, -33, -27, 82, -62, -19, 91, -93, + 22, 49, -51, -25, 48, -12, -6, 1, -2, -1, 22, -32, -1, 59, -78, 12, + 58, -49, -26, 70, -40, -8, 16, -8, 12, 10, -65, 74, -1, -97, 90, 0, + -56, 23, 25, -17, 11, -23, 14, 9, -24, -31, 77, -41, -48, 95, -38, -46, + 59, -1, -57, 49, -33, 19, 18, -46, 34, 31, -79, 47, 11, -38, 10, 19, + -14, -10, 26, -29, 28, -17, -27, 48, -15, -51, 78, -14, -73, 64, 12, -55, + 29, 3, -24, 52, -65, 26, 50, -75, -5, 81, -76, 0, 42, -6, -26, 10, + 18, -14, 4, -24, 33, 2, -69, 61, 43, -101, 40, 54, -73, 22, 18, -41, + 44, -19, -43, 94, -69, -13, 65, -26, -46, 35, 24, -34, -2, 23, -13, 6, + -19, 4, 38, -56, 14, 40, -37, -19, 66, -57, -9, 50, -47, 21, 6, -31, + 55, -34, -50, 98, -44, -47, 44, 28, -51, 6, 31, -3, -34, 8, 11, 6, + -18, -27, 78, -48, -28, 55, -2, -60, 57, -37, 14, 15, -48, 49, 22, -96, + 74, 23, -83, 36, 18, -17, -25, 41, -12, -4, -2, 1, 9, -14, -18, 36, + 12, -77, 54, 32, -67, 20, 38, -67, 61, -53, 32, 21, -60, 27, 41, -74, + 27, 33, -30, -6, 22, -1, -30, 20, 1, -4, -22, 9, 8, 37, -65, 18, + 61, -69, -3, 37, -19, -15, 15, -16, 57, -78, 20, 66, -67, -27, 76, -37, + -16, 11, 11, -5, -18, 10, 16, -5, -38, 36, 9, -20, -32, 73, -41, -36, + 62, -33, -9, 34, -41, 35, -7, -40, 65, -35, -26, 33, 2, -43, 42, -4, + -9, 5, -11, 19, -10, -16, 11, 16, -28, -9, 41, 2, -70, 67, -3, -55, + 23, 33, -26, 6, -29, 43, 16, -85, 51, 28, -54, 7, 27, -9, 2, -18, + 27, -4, -42, 31, 10, -19, -9, 18, 8, -24, -3, 45, -57, 25, 0, -7, + 15, -28, 10, 33, -46, -6, 52, -36, -15, 46, -29, -4, 12, -14, 34, -57, + 16, 40, -41, 3, 16, 8, -32, 16, 15, -17, -27, 47, -30, -1, 14, -5, + 16, -17, -33, 70, -44, -42, 84, -34, -27, 18, 15, 3, -20, -22, 55, -35, + -22, 31, 10, -11, -27, 27, 13, -28, -10, 41, -21, -3, -22, 41, -21, -13, + 6, 34, -68, 46, 25, -65, 50, -21, -1, 10, -33, 34, 1, -43, 58, -34, + -2, 13, 8, -25, 0, -2, 34, -29, -26, 45, -12, 4, -34, 32, 15, -54, + 17, 53, -76, 41, 4, -17, 13, -26, 13, 31, -47, 1, 52, -53, 11, 8, + 14, -31, -7, 19, 30, -60, 26, 27, -22, -10, 0, 18, -13, -24, 52, -38, + -17, 68, -60, 26, -9, -25, 41, -29, -8, 40, -25, -9, 26, -28, 15, -9, + -3, 11, -21, -1, 44, -47, 19, 0, 3, -14, -12, 38, -22, -23, 37, -10, + -13, 9, -6, 21, -14, -39, 61, -4, -68, 60, 6, -43, 28, -14, 21, -22, + -13, 36, -7, -40, 46, -14, -5, -18, 20, 22, -49, 22, 10, -18, 21, -30, + 9, 34, -54, 19, 22, -34, 27, 7, -45, 30, 0, -20, 23, -23, 29, -10, + -21, 25, 3, -23, -1, 5, 16, -33, 14, 25, -21, -11, 16, 3, -22, 5, + 6, 32, -73, 27, 62, -72, 5, 26, -21, 30, -37, 4, 40, -45, 5, 18, + -18, -1, 12, -3, 0, -18, 28, -8, -14, 11, -11, 13, -15, -3, 27, -17, + -30, 65, -45, -5, 28, -25, 1, 20, -36, 38, -11, -20, 35, -23, -20, 27, + 11, -42, 13, 17, 1, -25, 20, 10, -33, 10, 6, -7, 9, -26, 40, -3, + -63, 74, -30, -11, 10, -10, 5, 17, -47, 53, -10, -47, 29, 31, -45, 4, + 16, 14, -15, -33, 40, -11, -3, -10, 2, 18, -20, 9, 22, -44, 19, 20, + -42, 25, -5, -11, 25, -25, -3, 47, -63, 28, 20, -42, 7, 39, -41, 2, + 13, 10, -24, -8, 41, -26, -1, -13, 9, 42, -60, 0, 61, -54, -4, 19, + -6, 11, -19, -13, 52, -37, -26, 66, -38, -30, 49, -18, -11, 5, 7, 10, + -30, 4, 17, 2, -12, -15, 38, -19, -20, 30, -16, -23, 38, -13, -16, 29, + -22, 26, -17, -35, 62, -30, -35, 51, -16, -27, 40, -16, 3, -8, -4, 9, + 4, -26, 11, 20, -11, -38, 56, -19, -29, 31, 7, -39, 17, 10, 6, -8, + -41, 45, 26, -79, 36, 42, -58, 21, 6, -10, 7, -19, 17, -1, -15, -12, + 53, -22, -32, 24, 25, -59, 24, 22, -36, 10, 18, -27, 44, -45, 0, 42, + -45, -2, 30, -27, 12, 23, -38, 13, 5, 4, -4, -20, 1, 43, -27, -36, + 43, 14, -51, 12, 40, -41, 5, 18, -11, -1, -5, -11, 53, -56, -29, 91, + -41, -45, 57, -7, -18, -3, -4, 29, -20, -19, 20, 26, -57, 31, 17, -22, + -13, 28, -31, 3, 36, -33, 9, 17, -39, 42, -9, -54, 58, 6, -69, 44, + 30, -50, 24, 3, -17, 9, -20, 17, 8, -23, 1, 46, -50, 1, 27, 1, + -49, 37, 5, -17, 4, -5, 7, 18, -55, 39, 36, -85, 37, 48, -63, 5, + 27, -13, -6, -4, 5, 24, -26, -12, 42, -25, -34, 33, 20, -33, -13, 29, + -2, 7, -34, 12, 37, -50, 1, 47, -46, -1, 56, -54, -18, 59, -35, -6, + 12, -16, 20, -2, -27, 43, -12, -34, 22, 25, -41, -7, 43, -20, -18, 19, + -1, 1, -6, -20, 54, -55, -12, 67, -24, -56, 56, -8, -12, -7, -3, 16, + 20, -48, 20, 32, -46, 8, 23, -17, -38, 54, 1, -34, 2, 30, -1, -21, + -18, 38, -14, -35, 41, 3, -36, 19, 22, -45, 40, -32, 12, 12, -26, 2, + 35, -54, 34, 14, -25, -30, 47, 10, -53, 24, 13, -4, -18, 3, 5, 27, + -61, 38, 15, -39, 6, 40, -36, 0, 2, -6, 28, -40, 7, 46, -37, -30, + 59, -21, -29, 6, 48, -55, 12, 30, -21, -6, 5, -2, 1, -14, -7, 46, + -41, -4, 35, -8, -33, 29, -20, 26, -31, -10, 63, -46, -4, 12, 7, -11, + -15, 26, -14, -22, 54, -47, 12, 9, -1, -8, -7, -8, 41, -12, -60, 77, + -21, -26, 11, 13, 1, -26, -9, 59, -45, -16, 38, -3, -27, -1, 28, -8, + -19, 11, 20, -41, 34, -23, 22, -20, -9, 6, 51, -79, 40, 18, -40, 23, + -5, -19, 13, 2, 3, -4, -35, 71, -39, 5, -30, 33, 6, -29, -3, 38, + -29, -5, 18, -9, -4, -11, 16, 15, -32, -14, 77, -83, 30, 10, -10, -19, + 20, 15, -17, -19, 29, 7, -32, 6, -1, 14, -14, -6, 5, 36, -58, 47, + -18, -14, 4, 8, 8, -24, -15, 60, -36, -20, 43, -32, 3, -2, 1, 9, + -5, -8, 30, -33, 6, 6, 2, -12, -11, 24, 1, -22, 9, 34, -61, 25, + 11, -5, -18, -1, 38, -19, -33, 49, -19, -21, 18, -7, 1, 5, -4, -3, + 13, -30, 25, -5, -12, 2, 8, 17, -37, 0, 50, -38, -26, 40, -15, 7, + -24, 31, -11, -8, 6, -6, -3, 1, 9, -8, 6, -20, 25, 0, -21, 7, + 22, -48, 29, -4, 10, -22, 7, 22, -9, -34, 45, -15, -31, 30, -2, 0, + -30, 46, -18, -6, -17, 31, -6, -7, -21, 8, 45, -47, -7, 31, -17, -11, + 25, -20, 17, -30, 47, -38, -2, 5, 16, -36, 24, -2, 3, -7, 6, 10, + -23, 5, -11, 35, -42, 17, 0, 21, -35, 11, 16, -18, -15, 36, -24, -3, + 9, 5, 13, -49, 36, -11, -2, -14, 37, -32, 13, -1, 0, -2, -2, -8, + 17, -11, -21, 30, -1, -1, -41, 72, -65, 14, 14, 12, -41, 21, 4, 15, + -32, -1, 25, -9, -18, 3, 29, -38, 35, -22, 14, -20, 16, -6, -6, -13, + 29, -4, -17, 7, 14, -6, -38, 54, -32, 3, -16, 36, -39, 42, -40, 36, + -22, -13, 17, 14, -36, 12, 23, -25, 6, -25, 53, -33, -12, 5, 37, -46, + 6, 20, 9, -53, 52, -16, -22, 24, -9, 10, -17, 12, -20, 48, -73, 40, + 18, -30, -20, 52, -34, 11, -6, 0, 1, -15, 24, -16, 16, -30, 44, -27, + -10, 0, 34, -52, 24, 3, 2, -6, 12, -25, 35, -38, -14, 72, -73, 7, + 31, 15, -50, 20, 12, -5, -25, 23, 3, -10, -9, 15, 9, -41, 28, 6, + -5, -36, 44, -13, 10, -19, 2, 14, -10, -29, 56, -27, -35, 58, -19, -27, + 17, 16, -30, 10, -7, 15, -12, -3, 11, 18, -30, -13, 38, -17, -16, 3, + 32, -37, 23, -24, 30, -12, -26, 40, -14, -52, 59, 12, -55, 16, 35, -20, + -30, 39, -24, 21, -26, 12, 13, -10, -19, 23, 2, -35, 17, 33, -30, -17, + 39, -15, 12, -53, 50, -13, -25, 2, 50, -42, -1, 25, -22, 6, -5, 3, + -4, 2, -18, 39, -25, -3, 1, 29, -57, 22, 26, -22, -18, 34, -10, -10, + -11, 13, 31, -77, 46, 23, -22, -35, 61, -24, -13, 7, -3, 0, 4, -24, + 27, 12, -50, 35, 13, -19, -37, 69, -46, -4, 13, 5, -8, 6, -25, 40, + -26, -13, 38, -12, -28, 21, 22, -57, 40, -15, 11, -19, 4, 19, 9, -36, + 3, 42, -35, -30, 46, 0, -50, 59, -26, 9, -16, 12, -10, 10, -33, 44, + -8, -29, 8, 42, -43, -6, 26, -19, 14, -30, 34, 4, -21, -17, 49, -31, + -24, 34, 14, -53, 32, 13, -26, 12, -22, 26, -3, -22, -11, 66, -59, 0, + 43, -27, -23, 42, -32, 7, -7, 11, 9, -19, -1, 15, 16, -58, 43, 1, + -32, 11, 36, -44, 18, 0, 4, -4, -7, -22, 50, -22, -44, 67, -14, -43, + 37, 2, -32, 15, 7, 8, -22, -1, 14, 19, -43, 0, 40, -30, -14, 28, + 10, -32, 11, 1, 21, -33, -9, 31, 15, -72, 61, 4, -40, 21, 14, -37, + 22, 4, -4, -9, 5, -8, 23, -16, -22, 35, -24, 0, 12, 3, -17, 15, + 2, -10, -6, -8, 21, 7, -58, 40, 43, -75, 25, 28, -25, -18, 28, -15, + 6, -5, -4, 22, -5, -39, 37, 1, -30, 12, 23, -27, -8, 34, -22, 0, + -12, 15, 10, -28, 2, 45, -45, -9, 36, -22, -7, 13, -7, 6, 2, -18, + 17, 10, -34, 9, 18, -22, -1, 22, -9, -17, 23, -1, -22, 21, -20, 20, + -17, -6, 38, -33, -18, 55, -32, -21, 26, -5, -9, 5, -8, 16, 9, -47, + 36, 11, -36, -3, 38, -7, -48, 44, -2, -11, 2, -16, 15, 11, -36, 33, + -3, -18, 9, 19, -46, 26, -1, -11, 20, -24, 12, 16, -16, -17, 37, -32, + -6, 13, 13, -33, 25, 14, -27, 8, 1, -18, 22, -5, -15, 32, -46, 37, + -2, -19, -13, 38, -32, 8, 2, -4, 15, -12, -4, 19, -25, -10, 37, -19, + -11, -10, 57, -54, 19, -17, 18, 3, -18, -9, 27, -6, -36, 57, -23, -21, + 14, 11, -23, 32, -53, 56, -24, -5, -3, 11, -16, 16, -7, -20, 17, 11, + -3, -31, 42, -33, 14, -6, -2, -8, 39, -56, 48, -21, -20, 30, -8, -20, + 12, 15, -32, 41, -36, 29, -25, 14, -22, 22, -19, 9, 4, 10, -31, 17, + 11, -14, -1, -7, 17, -16, 6, -18, 64, -88, 47, 6, -20, -5, 22, -13, + 18, -28, 2, 25, -19, -10, -3, 29, -23, 11, -22, 39, -25, 13, -27, 20, + -2, -18, 15, -3, 3, 9, -17, -8, 38, -57, 35, 1, -9, -24, 43, -32, + 30, -30, -3, 19, -3, -21, 12, 14, -12, 2, -5, 11, -37, 37, -3, -13, + -4, 10, 11, -4, -38, 41, -9, -27, 37, -37, 16, 17, -7, -15, 22, -40, + 33, -2, -16, 4, 3, 8, -4, -20, 21, -3, -10, 8, -26, 37, -21, 8, + 0, -3, -3, 0, -8, 20, -15, -32, 54, -10, -26, 17, -12, 10, 24, -71, + 51, 3, -21, 9, -3, 17, -22, 2, 15, -21, -11, 39, -25, 11, -27, 28, + 3, -11, -26, 45, -43, 24, 7, -39, 47, -24, -15, 27, -13, -15, 35, -27, + 15, -17, 9, 0, -7, 0, 4, -9, 13, -3, -16, 28, -29, 21, -23, 11, + -4, 10, -30, 64, -63, 13, 28, -30, 16, -13, 0, 25, -39, -2, 53, -40, + 5, -19, 41, -25, -6, -3, 37, -40, 6, 8, 0, 6, -34, 32, 4, -27, + 13, 15, -34, 52, -63, 40, -5, -22, 5, 24, -32, 22, 11, -26, 14, -22, + 26, -21, 10, -8, 5, -10, 46, -66, 44, -20, 14, -7, -27, 23, 30, -53, + 24, 10, -37, 44, -40, 21, -11, 3, 6, 20, -47, 27, 5, -2, -18, -4, + 29, -13, -20, 27, 9, -47, 43, -37, 55, -62, 14, 33, -13, -28, 24, -9, + 23, -35, -4, 32, -14, -13, 28, -10, -30, 46, -43, 43, -46, 13, 13, -10, + 7, -3, -20, 39, -19, -19, 14, -15, 39, -31, -10, 25, 2, -34, 41, -35, + 15, -4, -3, 22, -18, -27, 46, -1, -36, 10, -4, 42, -56, 13, 31, -19, + -18, 28, -29, 27, -32, 24, 10, -44, 20, 32, -32, -17, 32, -13, 13, -35, + 20, 32, -53, 20, 9, -16, 16, -36, 39, -3, -33, 43, -26, 2, 2, 2, + -17, 24, -22, 14, -3, -12, 31, -28, -8, 26, -29, 19, -4, -15, 33, -39, + 22, 16, -37, 6, 17, -4, -13, -12, 37, 9, -65, 34, 25, -27, -9, 7, + 5, 10, -36, 45, -11, -41, 42, -6, -21, 7, -5, 31, -5, -57, 62, -12, + -15, -16, 23, 4, -24, 12, 26, -35, -11, 44, -25, -8, -1, -4, 28, -11, + -37, 61, -48, 23, -1, -30, 29, -8, -2, 6, -19, 18, 15, -41, 30, -4, + -11, -11, 28, -10, -4, -37, 81, -45, -43, 61, -19, 1, -11, 0, 31, -30, + -25, 68, -43, -11, 0, 27, -1, -33, -7, 77, -54, -30, 44, -6, -5, -14, + 17, -6, -10, 6, 30, -68, 50, -16, 5, 5, -30, 30, 26, -69, 36, 8, + -34, 37, -28, 11, 0, -1, 9, 1, -41, 53, -22, -24, 23, 5, -9, -11, + 12, 28, -61, 28, 36, -68, 51, -33, 25, -6, -26, 7, 53, -65, 2, 47, + -25, -23, 17, 20, -4, -51, 38, 29, -67, 31, 1, 22, -35, -8, 40, -9, + -46, 47, -13, -8, 5, -15, 37, -27, -20, 45, -16, -45, 59, -37, 19, -6, + 2, 1, -11, -3, 34, -42, 0, 33, -30, 16, -13, 13, 2, -23, 18, -5, + -26, 43, -24, 15, -26, 4, 35, -15, -62, 64, 19, -75, 50, -8, 8, -14, + -12, 31, -19, -30, 45, -10, -12, -10, 36, 3, -53, 14, 45, -37, -22, 42, + -25, 21, -36, 21, 37, -61, 5, 47, -49, 19, -4, 5, 1, -12, 7, 3, + -11, 2, 18, -28, 13, -4, 18, -13, -20, 33, -22, -8, 21, -12, -10, 24, + -9, 2, -27, 15, 33, -41, -18, 56, -40, 9, -5, 6, 20, -44, 11, 39, + -35, -22, 50, -7, -36, -6, 41, -10, -30, 15, 20, -22, 7, -11, 16, 6, + -51, 59, -21, -26, 24, 12, -24, 8, -7, 12, 3, -36, 27, 18, -42, 22, + 9, -22, 11, -2, 15, -40, 38, -13, -16, 8, 24, -33, 15, -13, 4, 23, + -42, 17, 30, -34, -5, 28, -22, 11, -23, 30, -14, -28, 37, 12, -46, 11, + 31, -23, -12, -7, 36, -17, -6, -4, 25, -18, 4, -29, 53, -48, 4, 24, + -9, -21, 30, -1, -20, 2, -13, 51, -51, -1, 39, -23, -18, 33, -23, 3, + 3, 2, -13, 11, 4, -13, 15, -14, -3, 1, 24, -53, 55, -24, -17, 36, + -1, -49, 45, -7, -12, -2, -4, 24, -23, 1, 6, 23, -51, 30, -8, 14, + -29, 17, 12, -9, -21, 21, 1, 3, -32, 21, 30, -59, 27, 25, -21, -26, + 36, -24, 16, -23, 15, 10, -15, 11, -11, -3, 14, 1, -30, 32, -24, 27, + -25, 10, -12, 29, -33, 7, -5, 25, -29, 14, 15, -42, 20, 18, -27, 1, + 21, -19, 17, -18, 2, 19, -12, -34, 47, -21, -6, 9, -2, 14, -32, 32, + -23, 14, -21, 21, 0, -13, -8, 42, -35, -19, 33, 4, -34, 23, -5, -6, + 22, -31, 21, -8, -5, -3, 15, -22, 10, 2, 7, -17, 11, 3, -10, 2, + -1, -2, -9, 25, -20, 11, -18, 17, -3, -12, 2, 9, -1, -10, 5, 0, + 15, -40, 36, -5, -28, 16, 24, -34, 16, -1, 13, -32, 11, 9, 5, -26, + 5, 32, -32, 4, -1, 29, -38, 8, 7, -6, 5, -2, -5, 18, -26, -2, + 39, -42, 0, 26, 2, -43, 45, -30, 20, -11, -6, -3, 16, -7, -6, 3, + 12, -13, 5, -7, -21, 47, -29, -11, 9, 36, -45, 8, 0, 22, -28, -7, + 32, -22, -9, 20, 12, -40, 24, -8, 14, -28, 10, 9, 12, -29, 15, -7, + 15, -23, 5, 14, -24, 12, 8, 4, -38, 36, -4, -7, -30, 47, -13, -24, + 16, 23, -46, 29, -3, -10, 20, -43, 35, 0, -4, -30, 47, -18, -21, 16, + 19, -35, 11, 19, -21, -11, 27, -12, -9, 16, -21, 23, -32, 30, 3, -22, + -15, 51, -38, -1, -2, 11, 15, -28, -1, 16, 13, -42, 23, 4, -6, -32, + 61, -24, -35, 34, 29, -55, 4, 13, 9, -6, -26, 35, -6, -11, -11, 19, + -6, -3, -15, 43, -41, 4, 22, -1, -34, 18, 15, -35, 18, -1, 23, -35, + 18, -2, -9, 1, 10, -18, 17, -18, 21, -8, -17, 24, -1, -20, -7, 26, + -11, 6, -33, 42, 0, -40, 9, 46, -48, -6, 24, 13, -39, 8, 41, -43, + 3, 6, 6, -7, -6, -8, 42, -37, -11, 39, -16, -26, 25, 3, -24, 9, + 11, 6, -34, 17, 14, -12, -22, 20, 0, 14, -38, 27, 10, -37, 22, -1, + -5, -7, 11, 4, -3, -29, 38, -5, -26, 4, 20, -17, 6, 2, 11, -17, + -10, 40, -49, 10, 26, -8, -24, 11, 12, 5, -36, 21, 20, -22, -29, 28, + 30, -30, -24, 31, 25, -70, 39, 4, -16, 3, 9, -13, 16, -26, 23, 19, + -46, 1, 29, 6, -37, 8, 27, -8, -33, 36, -24, 5, 14, -8, -8, 1, + 4, 15, -27, -11, 44, -38, 6, 12, -3, -12, 20, -17, 16, -35, 28, -4, + 0, -13, 8, 23, -24, -16, 28, 11, -58, 48, 6, -39, 11, 24, -9, -8, + -25, 42, -16, -14, 12, 2, 13, -31, 6, 26, -10, -48, 64, -22, -21, 6, + 28, -15, -11, -2, 22, -30, 11, 15, -25, 13, 2, -1, -7, -4, 6, 17, + -37, 17, 0, 1, 14, -23, 4, 16, -23, 6, 12, -31, 30, 6, -18, -25, + 45, -7, -20, -15, 44, -38, 9, 22, -37, 24, 6, -20, 14, -17, -8, 44, + -27, -22, 16, 30, -33, -18, 20, 31, -50, 11, 27, -21, -4, -3, 26, -15, + -24, 15, 20, -27, 16, -12, 9, 5, -24, 3, 26, -27, 5, 15, -19, 9, + -9, 26, -25, -5, 10, -4, -6, 31, -45, 18, 24, -23, -23, 27, -3, 2, + -18, 9, 13, -18, 19, -17, 7, -1, -24, 31, 5, -49, 31, 32, -40, -7, + 10, 14, -12, -12, 5, 21, -30, 25, -12, 4, -18, 9, 11, -13, -20, 37, + -8, -3, -13, -3, 33, -21, -32, 44, -7, -22, 28, -24, 5, 12, -19, 2, + 6, 2, -16, 11, 10, -6, -23, 31, -25, 7, 6, -16, 18, 1, -35, 40, + -9, -18, 12, 4, -2, -25, 20, 19, -16, -35, 46, -14, -8, -3, -1, 24, + -12, -25, 26, -4, -6, 3, -12, 20, -24, 18, 9, -20, -2, 18, -13, -1, + -16, 8, 26, -35, 12, 10, -11, 6, 2, -30, 46, -43, 16, 6, 1, -20, + 26, -18, 8, -13, 9, -3, 3, 1, -25, 29, 13, -50, 12, 41, -47, 15, + 14, -12, 2, -3, -1, 14, -25, -3, 26, -23, 19, -35, 41, -5, -23, -1, + 31, -30, 8, -15, 32, -29, -7, 22, 10, -35, 12, 6, -2, 20, -50, 36, + 7, -17, -4, -1, 7, 2, -21, 19, -12, 1, 28, -25, -5, 9, -3, -12, + 32, -45, 16, 21, 0, -43, 21, 28, -19, -38, 45, -15, -8, 28, -43, 39, + -12, -23, 13, 19, -39, 23, -3, 17, -32, 6, 20, -5, -32, 23, 8, -15, + -1, 11, 9, -28, 5, 20, -18, -6, 9, -18, 50, -50, -8, 49, -30, -5, + -4, 14, -19, 28, -21, 2, 4, 11, -20, 6, 3, -5, -24, 54, -34, -14, + 26, -4, -2, -16, 5, 20, -23, 1, 6, -9, 32, -37, 1, 25, -22, -8, + 31, -6, -37, 31, 0, 3, -37, 24, 25, -27, -20, 27, 1, 4, -26, 13, + 3, -14, 12, -6, 6, -3, -6, 18, -14, -27, 38, 5, -36, 14, 13, -22, + 26, -13, -22, 36, -23, -5, 3, 18, -12, -23, 31, -5, -24, 23, -15, 17, + -7, -23, 20, 6, -4, -19, 20, -8, 15, -32, 13, 17, -30, 17, 13, -19, + -8, 4, 24, -18, -29, 36, 7, -21, -20, 28, 13, -17, -31, 36, -9, -7, + 7, 6, -9, -4, 7, -6, 10, -32, 41, -26, 12, -10, -12, 35, -10, -39, + 36, -9, -7, 7, 6, -9, -4, 11, -14, 5, -7, 9, -13, 24, -27, 4, + 14, 7, -31, 19, -14, 17, -5, -34, 57, -31, -7, -6, 28, -15, -11, 2, + 25, -21, -14, 15, 18, -35, 12, 1, 9, -20, -2, 32, -37, 26, -17, 7, + 1, -10, -18, 54, -37, -16, 23, 11, -13, -23, 34, -5, -16, -10, 25, -28, + 30, -10, -7, -5, 18, -24, 25, -24, 18, -11, 0, 3, -19, 34, -12, -12, + 2, 3, -13, 32, -37, 20, 4, -6, -25, 29, -3, -2, -11, -2, 28, -38, + 18, 7, -5, -7, 0, -4, 21, -36, 30, -19, 25, -29, -15, 48, -11, -43, + 33, 33, -64, 17, 26, -12, -18, 9, -1, 18, -33, 23, -13, 21, -18, -13, + 18, -2, -20, 20, 6, -15, 4, -12, 28, -27, 1, 10, -5, 3, 0, -17, + 15, 17, -30, 2, 5, -8, 17, -11, -2, 9, -20, 23, -27, 23, -10, -3, + 7, -3, -25, 31, 9, -28, -9, 30, -5, -28, 15, 29, -36, -9, 29, -11, + -20, 33, -27, 21, -14, -12, 21, -3, -9, -2, 12, -5, -27, 27, 7, -20, + -11, 32, -9, -15, -1, 9, 20, -42, 12, 9, -4, 3, -6, -3, 6, 0, + -12, 15, -25, 27, -6, -6, -6, 6, -2, -4, 5, 9, -20, 12, 8, -17, + -10, 30, -12, -24, 25, -15, 18, -21, 21, -8, -6, -9, 12, -6, 15, -33, + 26, 8, -32, 13, 21, -12, -28, 20, 11, -6, -28, 27, 11, -21, -10, 22, + -1, -11, -7, 24, -12, -27, 35, -8, 0, -20, 23, -10, 9, -30, 32, -15, + 3, -7, 6, -2, 10, -17, 1, 8, -4, -5, -3, 14, -9, 1, -11, 18, + -13, 15, -33, 22, 14, -32, 11, 9, -1, -17, 14, 0, -3, -16, 29, -21, + -4, -1, 28, -24, -2, -11, 41, -25, -23, 24, 6, -18, -13, 37, -21, -2, + -4, 29, -40, 11, 12, 4, -25, 12, -9, 23, -17, -14, 27, -2, -26, 9, + 18, -14, -1, -15, 29, -18, -4, 5, 12, -26, 18, -3, -7, 3, 13, -10, + -25, 44, -38, 11, 8, -2, -25, 28, -9, 12, -13, -13, 10, 27, -53, 19, + 16, -4, -20, 12, 12, -21, 5, 12, 3, -35, 22, 8, 0, -28, 18, 16, + -25, -3, 9, 8, -3, -19, 8, 24, -34, -4, 38, -16, -30, 29, -1, -2, + -25, 28, -1, -21, 11, 10, -18, -1, 10, 1, -7, 0, 1, -7, 15, -15, + -5, 16, 2, -22, 8, 0, -1, 26, -34, -22, 56, -26, -11, 12, 9, -9, + -9, 4, 7, -8, -1, 8, 0, -21, 10, 19, -8, -25, 17, 10, -18, 3, + -4, 26, -15, -29, 30, 9, -46, 36, 12, -33, 1, 18, -2, -16, 4, 16, + -10, -16, 11, 2, 8, -19, 5, 1, 10, -21, 20, -8, -1, -3, 1, 7, + -19, 7, 11, -12, 5, 5, -26, 29, -11, -5, -2, 12, -13, 9, -22, 23, + 3, -20, 4, 17, -16, -13, 17, 15, -16, -34, 37, -5, 8, -32, 23, 17, + -36, -2, 36, -25, -4, 28, -18, -20, 15, 4, 7, -12, -24, 43, -19, 0, + -11, 25, -9, -12, -7, 10, -1, 11, -2, -12, 13, -27, 30, -9, -15, 8, + 17, -28, 18, -9, 3, 7, -8, -10, 16, -26, 35, -22, -10, 37, -35, 1, + 11, 11, -19, -2, 9, 17, -37, 11, 10, 9, -16, -12, 27, -11, -22, 16, + 24, -48, 25, -1, -3, 4, -20, 13, 39, -72, 34, 1, 2, -6, 4, -1, + -8, 2, -8, 18, -10, -1, -5, 19, -30, 5, 30, -16, -26, 36, -26, 3, + 21, -27, 10, 4, -10, 0, -4, 15, 9, -41, 32, -11, 2, -11, 15, -3, + -7, -8, 16, -3, -21, 23, -2, -9, -4, -2, 20, -5, -37, 49, -20, -6, + -9, 17, 17, -36, -8, 40, -24, -5, 3, 8, 5, -12, -6, 15, 2, -27, + 28, -4, -23, 16, 5, -1, -26, 29, 11, -38, 22, -12, -8, 38, -34, -3, + 10, 4, -2, -5, -8, 24, -16, -20, 21, 1, -7, 11, -7, -4, -15, 15, + 15, -21, -6, 10, -1, 17, -45, 23, 29, -42, 2, 18, -5, -6, -1, 22, + -20, -19, 16, 21, -20, -18, 23, 2, 5, -41, 36, 10, -34, 12, 12, -25, + 11, 1, 6, -6, -11, 20, -11, 10, -11, -12, 13, 8, -21, 5, -1, 14, + 3, -26, 5, 27, -39, 18, 7, -27, 34, -20, 13, -20, 7, -4, 25, -23, + -16, 7, 47, -35, -29, 37, 10, -35, 4, 12, -1, 0, -15, 25, -23, -12, + 35, 7, -51, 28, -1, 16, -33, 5, 27, -21, 2, -5, 13, -3, 0, -20, + 27, -30, 8, 16, -4, -13, 14, -15, 19, -12, -6, 8, -9, 19, -27, 4, + 20, -9, -12, 21, -37, 41, -22, 1, 1, 13, -33, 20, 14, -30, -2, 22, + 21, -51, 3, 38, -7, -35, 17, 6, 11, -43, 33, 9, -36, 10, 31, -24, + -13, 16, -6, 24, -36, -1, 16, 19, -45, 20, 11, 2, -30, 31, -21, -14, + 29, -4, -12, 3, -6, 9, 15, -37, 20, -4, 8, -18, 12, -7, 17, -8, + -12, -9, 23, 8, -28, 1, 29, -19, -18, 27, -2, -8, -28, 44, -4, -36, + 15, 33, -30, -13, 13, 14, -20, -7, 25, -11, -5, -8, 21, -1, -8, -37, + 50, 1, -53, 27, 28, -21, -10, 4, 16, -24, 10, 6, -12, 0, 2, 6, + 1, -13, 2, 21, -26, 3, 13, -19, 10, 9, -18, -3, 22, -18, -1, -2, + 14, -1, -23, 21, -6, -2, -9, 20, 5, -35, 1, 34, -21, -16, 22, 1, + -8, -5, 1, 18, -12, -23, 18, 5, -17, -7, 37, -6, -35, 6, 47, -44, + -7, 20, 5, -10, -23, 35, -6, -12, -12, 39, -27, -10, 9, 21, -21, -6, + 2, 5, 1, 6, -28, 17, 20, -31, -3, 15, 7, -26, 31, -40, 43, -32, + 23, -19, 11, -22, 26, -6, -1, -25, 33, 2, -25, -7, 9, 26, -16, -30, + 29, 20, -47, 13, 16, -9, -19, 18, 23, -32, -17, 32, 21, -38, -13, 14, + 43, -66, 19, 23, 5, -50, 47, -20, 2, -11, 22, -5, -6, -21, 4, 38, + -15, -32, 12, 35, -35, -4, 7, 18, -17, -1, -7, 6, 5, 0, 0, -7, + 0, -8, 21, -10, 5, -28, 30, 3, -17, -29, 57, -16, -17, -10, 28, -9, + -20, 26, -12, 3, -20, 27, -3, -7, -42, 65, -9, -45, -3, 63, -33, -11, + -6, 28, -17, -1, -6, 6, 7, -12, 0, 25, -21, -30, 54, -9, -37, 1, + 28, 7, -42, 18, 11, 17, -46, 24, -9, 27, -38, 22, -20, 23, -21, 11, + -6, 42, -71, 20, 32, -11, -43, 44, -3, -4, -27, 12, 24, -8, -18, -8, + 30, -19, -23, 44, -8, -30, 0, 45, -39, 0, -1, 28, -16, -17, -15, 44, + -13, -11, -13, 36, -24, -11, 12, 17, -30, 8, 17, -10, -18, 9, 22, -18, + -15, 3, 25, -25, 11, -6, 5, 7, -18, -3, 15, -1, -17, 8, 28, -32, + -17, 36, 8, -41, 12, 7, 13, -22, -14, 18, 41, -57, -1, 25, 10, -40, + 18, 11, -8, -23, 25, -16, 37, -45, 17, 10, 2, -60, 64, -15, -3, -16, + 22, -9, 9, -27, 30, -7, -21, 3, 20, -10, 6, -12, 15, -19, 14, -19, + 3, 22, -8, -29, 37, -28, 29, -26, 11, -15, 15, -17, 21, -26, 18, 5, + -5, -11, 2, 16, -10, -10, -5, 29, -30, 4, 3, 18, -21, 4, 1, 8, + -13, -10, 1, 40, -35, -26, 44, 5, -38, 8, 30, -24, 0, -1, 0, 12, + -18, -1, 18, -8, -28, 39, -18, 24, -35, 24, -36, 46, -41, 12, -3, 24, + -37, 31, -28, 32, -16, 2, -27, 39, -34, 7, 24, -19, -6, 14, -10, -1, + 14, -16, -4, 25, -26, -4, 8, 22, -40, 33, -30, 22, -15, 36, -63, 39, + 1, 10, -54, 36, 9, 5, -51, 49, -13, 5, -7, -7, 15, -9, -10, 2, + 12, -18, 6, 3, 18, -29, 9, 10, -10, 1, -20, 20, -3, -1, -13, 21, + -26, 41, -36, 2, 23, -23, -10, 39, -41, 17, -10, 8, 7, -13, 23, -54, + 66, -26, -50, 54, 17, -66, 59, -46, 30, -10, 6, -8, -18, 19, 16, -32, + 12, 6, -2, 3, -36, 33, -6, -7, 12, -16, 6, 14, -21, 14, 16, -58, + 37, 3, 0, -35, 44, -16, 17, -38, 28, -14, 25, -45, 28, -21, 32, -31, + 11, 17, -24, 11, 5, -24, 18, -6, -3, 0, -3, 21, -33, 24, 20, -78, + 66, -8, -24, 3, 17, -14, 24, -41, 34, -25, 27, -32, 17, -5, 13, -26, + 28, -29, 22, -8, -16, 33, -30, 2, 25, -27, 1, 31, -36, -7, 31, -8, + -12, -5, 17, -7, 5, -26, 32, 1, -18, -16, 27, -7, -10, 2, 21, -42, + 30, -3, -19, 33, -40, 19, 6, -13, -5, 17, -10, 28, -63, 40, 6, -10, + -9, 7, -3, 12, -20, -1, 17, -1, -6, -14, 18, 1, -19, 12, 5, -9, + -2, -14, 33, -3, -44, 51, -17, -6, -16, 36, -35, 29, -31, 31, -24, 15, + -23, 33, -35, 20, -4, -1, -19, 27, -1, -29, 25, 1, -20, 25, -23, -13, + 62, -50, -18, 43, -20, 1, -4, 16, -18, 4, -16, 36, -42, 42, -42, 38, + -28, 9, -10, 31, -40, 30, -39, 30, 8, -28, 11, 9, -7, -6, -8, 10, + 22, -36, -5, 26, 4, -41, 30, 12, -11, -10, -14, 37, -29, 3, -6, 9, + -5, 15, -30, 40, -26, 12, -25, 25, -21, -12, 46, -17, -39, 47, 7, -57, + 45, -14, 1, -13, 21, -21, 14, -7, 7, -11, 18, -34, 25, 7, -28, 22, + 1, -12, 11, -24, 4, 38, -44, 17, 2, -12, 19, -17, 0, 9, 17, -55, + 29, 3, 3, -27, 48, -38, 16, -17, 24, -19, 26, -49, 29, 9, -18, -25, + 50, 2, -31, -20, 43, -3, -35, 23, 13, -34, 9, 20, -15, -8, 29, -37, + 29, -21, 4, -8, 36, -52, 29, -8, 6, -18, 35, -34, 22, -21, 10, 5, + -11, -13, 35, -26, -3, 12, -17, 13, 1, -12, -4, 24, -18, -6, 18, -7, + -13, 17, -4, -30, 48, -41, 10, 34, -39, -22, 73, -48, -12, 12, 22, -14, + -31, 18, 29, -17, -21, 22, -3, -8, -12, 25, -11, 13, -41, 36, -3, -2, + -27, 37, -6, -36, 17, 18, -7, -10, 4, -5, 10, -21, 13, 15, -21, 2, + -1, -5, 8, -1, -16, 29, -24, 14, -18, 26, -24, 17, -26, 21, -18, 24, + -49, 82, -52, -11, 36, -22, -17, 30, -21, 1, 1, -1, 8, -2, -7, 2, + 17, -9, -36, 37, -5, -15, -4, 27, -20, 11, -31, 46, -18, -13, -11, 58, + -67, 19, -4, 40, -43, 9, -14, 41, -32, -16, 46, -19, -13, 5, -5, 6, + 2, -16, 10, -9, 18, -13, 3, 24, -37, 11, 1, 0, -8, -9, 28, -1, + -41, 40, -10, 6, -13, 1, -11, 30, -28, -10, 30, 1, -36, 17, 28, -54, + 51, -24, 1, -6, 6, -12, 33, -48, 23, 18, -17, -23, 27, 11, -23, -13, + 27, -7, -1, -24, 35, 3, -48, 35, 8, -20, -3, 3, 16, -11, 8, -35, + 32, 7, -27, -22, 81, -85, 36, -7, 16, -16, 2, 0, 13, -28, 12, -16, + 24, 6, -25, -14, 47, -15, -25, 3, 37, -41, -5, 32, -25, 11, 6, -16, + 25, -34, 14, 8, 13, -52, 30, 6, 13, -56, 56, -27, 13, -11, -6, 16, + -12, -1, 18, -40, 18, 19, -13, -11, 7, -2, 9, 10, -39, 9, 46, -48, + -18, 59, -32, -3, 14, -10, 10, -13, 10, -13, 14, -11, -10, 5, 31, -43, + 10, 23, -16, 3, -29, 50, -23, -19, 16, 15, -19, 3, -20, 39, -19, -14, + -6, 54, -44, -12, 18, 30, -56, 28, -15, 22, -16, -15, 31, -8, -9, -1, + 1, 1, 2, -8, 9, 10, -43, 41, -9, 8, -48, 62, -30, -9, 13, 6, + -24, 32, -31, 8, -4, 16, -27, 27, -19, -1, -6, 37, -40, 14, -3, 0, + 25, -59, 34, 18, -18, -21, 17, 13, -11, -8, -11, 43, -40, 1, 6, 24, + -37, 10, 14, -4, -12, -2, 17, 11, -40, 10, 16, 17, -51, 24, 14, -4, + -31, 22, 18, -32, 15, -24, 46, -38, 9, 2, -2, 14, -15, -12, 15, 3, + -28, 29, -7, -6, 13, -7, -6, 2, 3, -17, 28, -28, -9, 37, -17, 0, + 3, 10, -19, -5, 19, -17, 12, -25, 30, -19, 8, -27, 49, -15, -27, 9, + 10, 7, -31, 6, 30, -12, -45, 41, 24, -42, -1, 28, -2, -38, 29, -18, + 23, -4, -43, 35, 26, -54, 23, 7, 6, -30, 17, -14, 32, -40, 24, -13, + 17, -15, -11, 16, 16, -20, -26, 47, -10, -26, -6, 41, -19, -22, 36, -41, + 33, 5, -32, 12, 28, -51, 19, 27, -40, 7, 35, -34, 9, -22, 42, -20, + -15, -3, 43, -55, 15, 23, -10, -11, 3, 14, -32, 31, -26, 21, 7, -44, + 15, 40, -22, -41, 54, -17, -17, 8, -6, 10, 11, -17, -6, 15, -2, -20, + 31, -19, 4, -17, 22, 0, 2, -36, 39, 0, -31, 23, -38, 59, -15, -29, + -13, 69, -50, -22, 43, -11, -16, 0, 16, -9, -10, 13, 5, -8, -18, 27, + -8, -2, -12, 13, -1, -16, 16, -18, 27, -11, -19, 39, -28, -26, 28, 36, + -85, 72, -40, 24, -10, 0, -9, 30, -29, -11, 22, -13, -7, 23, -10, -14, + 6, 13, -15, 22, -31, 12, 0, 0, -3, -15, 19, 14, -21, -22, 27, 35, + -72, 36, -3, 18, -54, 50, -29, 38, -47, 14, 19, -11, -25, 27, 9, -23, + -2, 2, 16, -6, -24, 22, 10, -27, 7, 16, -30, 11, 24, -40, 31, -28, + 29, 1, -28, 7, 17, 3, -45, 40, -11, -7, 4, 19, -45, 24, 24, -50, + 48, -35, 11, 9, -12, -14, 30, -23, 8, 7, -15, -7, 53, -59, 13, 5, + 15, -46, 49, -48, 57, -36, -20, 34, 1, -10, -15, 15, 20, -36, -9, 35, + 6, -39, 7, 14, 27, -81, 70, -21, 5, -22, 21, -6, 1, -13, 19, -19, + 4, -10, 35, -43, 31, -3, -7, -15, 40, -56, 33, -1, -33, 51, -35, -2, + 24, -18, 5, 0, 4, -16, 10, -6, 9, -28, 37, -38, 45, -35, 0, 37, + -38, 7, 19, -32, 3, 17, -2, -23, 19, 15, -23, 5, -2, 13, 1, -37, + 8, 59, -80, 26, 13, 15, -31, -8, 30, -7, -7, -19, 22, -2, -9, -2, + 12, -7, 3, 1, -25, 47, -53, 35, -5, -27, 21, 15, -25, 13, -24, 42, + -41, 19, 2, -13, 1, 23, -40, 37, -45, 46, -8, -41, 44, -11, -17, 23, + -9, -20, 22, -3, -15, 22, -23, 19, -7, 2, -34, 65, -56, 7, 28, -8, + -37, 37, 3, -8, -34, 39, -11, 9, -29, 6, 35, -14, -49, 48, 5, -25, + 5, -25, 66, -47, -9, 28, -7, -12, 0, 17, -20, -2, 21, -12, -23, 54, + -50, 20, 7, -20, 7, -2, 3, 4, -26, 26, -6, -14, 15, -3, -10, 12, + -10, -4, 23, -33, 14, -12, 38, -55, 36, 0, -6, -5, 0, -4, 7, 0, + -14, 2, 8, -11, 13, 5, -33, 41, 4, -62, 40, 8, -6, -8, -31, 52, + -4, -44, 25, 20, -18, -24, 32, -11, -9, -4, 30, -37, 34, -31, 7, 30, + -29, -14, 28, -10, -9, 6, 0, -5, 14, -9, -3, -2, 10, -22, 29, -22, + -2, 6, -5, 16, -25, 6, 27, -19, -9, -11, 29, -13, -5, -6, 16, 5, + -20, -1, 30, -20, -8, 7, -8, -2, 3, 14, -9, -24, 35, -7, -14, -12, + 32, -5, -18, -15, 35, -7, -13, -1, -4, 27, -20, -30, 58, -15, -29, 9, + 15, -16, -3, 1, 4, 5, -4, -11, 17, 3, -29, 28, -10, -18, 20, -7, + -2, 4, 2, -17, 22, -3, -31, 23, 23, -32, -14, 34, -3, -14, -13, 11, + 21, -26, -16, 36, -7, -13, 15, -8, -3, -1, -11, 15, -8, -4, -4, 24, + -21, 1, 11, 3, -22, 5, 15, -24, 0, 37, -31, 7, -18, 15, 16, -15, + -19, 26, 0, -10, -26, 31, 6, -19, -6, 21, -19, 20, -13, -3, 13, -2, + -32, 24, 2, -8, -10, 36, -29, -10, 19, 10, -25, 5, -9, 31, -23, -21, + 21, 26, -25, -9, -5, 35, -17, -34, 17, 42, -44, -11, 30, 11, -40, 18, + 8, -6, -11, 11, -26, 39, -18, -23, 37, -12, -32, 45, -8, -22, 5, 16, + -15, -10, 6, 17, -15, -3, 9, -22, 41, -22, -25, 29, 5, -30, 6, 12, + 17, -32, 7, 20, -26, 9, 9, -10, 7, -17, 10, 11, -16, -7, 12, 5, + -4, -26, 25, 24, -46, -4, 50, -39, -11, 8, 35, -36, 2, -9, 33, -7, + -22, -26, 76, -37, -41, 33, 28, -43, 14, 6, 2, -8, 2, -20, 34, -19, + -2, -4, 15, -6, -23, 28, -3, -32, 33, -16, 7, -11, 14, 9, -10, -30, + 35, -25, 17, -14, 1, 14, 12, -38, 16, 15, -7, -30, 15, 18, -24, -6, + 47, -38, 6, 7, -9, -2, -3, 1, 12, -8, -23, 20, 35, -47, -14, 51, + -9, -48, 19, 20, 0, -25, -2, 20, 16, -29, -25, 60, -17, -23, -8, 31, + -4, -30, 12, 20, -14, -4, -1, 17, -11, -9, 7, 7, -17, 1, -12, 25, + -5, -20, 15, 19, -29, 2, 5, 11, -19, -18, 31, 1, -27, 18, -17, 51, + -53, -2, 29, 4, -37, 17, 11, -11, -23, 41, -17, -10, 13, -4, -8, 18, + -27, 17, 1, -19, -7, 51, -37, -28, 53, 4, -47, 5, 18, 17, -32, -8, + 14, 36, -46, 3, 11, 11, -24, 4, 0, 16, -7, -26, 25, 20, -44, 7, + 20, -12, 2, -14, 4, 33, -38, 1, 8, 20, -34, -12, 61, -46, -19, 44, + -10, -4, -18, 12, 12, -8, -26, 16, 22, 2, -51, 18, 53, -56, -5, 30, + -9, -22, 32, -11, -18, 18, 13, -25, -7, 8, 9, 3, -20, 1, 32, -27, + -9, 5, 19, -20, -13, 18, 8, 3, -35, 22, 31, -47, -2, 16, -8, 15, + -10, -22, 54, -20, -23, -6, 51, -52, -13, 48, -23, -11, 28, -30, 38, -6, + -50, 28, 33, -58, 2, 34, 16, -53, -1, 55, -13, -42, 15, 23, -7, -33, + 13, 21, -14, -6, 2, -2, 27, -43, 27, 11, -19, -16, 26, -16, -4, 16, + -17, 1, 20, -17, 8, -17, 6, 26, -25, -24, 40, -13, 6, -14, -14, 29, + 3, -32, -5, 46, -21, -28, 38, -30, 6, 28, -47, 3, 65, -67, -5, 61, + -34, -27, 31, 12, -30, -7, 11, 19, 0, -43, 18, 47, -52, -20, 52, -14, + -9, -10, -5, 55, -45, -29, 55, 16, -83, 28, 36, -23, 6, -8, -13, 37, + -17, -30, 32, -9, -6, 10, -19, 16, 4, 9, -35, 22, -1, -17, 3, 8, + 10, -10, -21, 40, -27, -5, 16, -6, -27, 47, -23, -26, 48, -18, -19, 14, + -1, -9, 5, 1, -20, 58, -57, -14, 55, -16, -40, 37, -6, 11, -19, -22, + 43, 2, -55, 27, 37, -38, -29, 58, -6, -11, -22, 4, 26, -7, -67, 67, + 21, -56, 19, 15, -5, 0, 2, -41, 37, 10, -65, 49, 8, 1, -19, 1, + 9, 8, -20, -9, 22, -14, -3, 4, -1, 13, -6, -11, 15, -8, -15, 13, + 16, -38, 14, 24, -39, 20, 9, -17, 14, -15, 7, 3, -12, -3, 30, -25, + -24, 43, -1, -40, 18, 17, 0, -22, -14, 31, 20, -68, 35, 32, -43, -9, + 35, -16, 4, 2, -35, 35, 27, -81, 40, 31, -21, -30, 29, -12, 13, 10, + -42, 26, 17, -33, -1, 16, 12, -29, 6, 4, 21, -27, -9, 39, -6, -54, + 40, -14, 15, -4, -17, 20, 4, -18, -4, 23, -24, -3, 30, -41, 15, 17, + -4, -29, 19, 4, -9, -10, 12, 17, -21, -7, 26, -19, -17, 17, 3, 1, + -3, -30, 47, 16, -62, -4, 68, -29, -54, 43, -1, -4, 20, -42, 22, 34, + -32, -43, 63, -12, -26, 8, -6, 10, 22, -66, 55, 25, -65, 15, 9, 21, + -22, -28, 36, 5, -16, -51, 102, -49, -12, 6, 21, -12, -23, 24, -15, 11, + -14, -8, 31, 4, -53, 64, -35, 13, -28, 23, -23, 22, -16, 13, -22, 23, + 27, -51, -8, 41, 6, -66, 36, 13, 4, -26, 7, 11, 9, -34, 0, 35, + -21, -15, 10, 34, -57, 60, -69, 60, -22, 1, -27, 27, 14, -27, 1, -13, + 35, -2, -51, 36, 35, -49, 5, -1, 31, -42, 25, -26, 34, -7, -60, 98, + -46, -22, -1, 49, -45, -2, 10, 26, -33, 25, -36, 37, -19, 4, -3, -7, + 9, 7, -8, -29, 48, -23, 0, -33, 45, 0, -23, -16, 47, -7, -31, -9, + 38, -2, -36, 18, -8, 43, -55, 16, -1, 41, -72, 54, -35, 24, 4, -46, + 47, -11, 6, -40, 24, 10, 8, -38, 16, 16, 24, -98, 80, 2, -28, -28, + 44, 11, -47, 31, -7, 35, -42, -25, 41, 12, -64, 34, 14, -2, -21, 24, + -14, 11, -3, -24, 22, -28, 46, -51, 38, -22, 35, -40, 2, 11, 22, -48, + 23, -9, 34, -35, -24, 52, -7, -37, 9, 36, -21, 0, -32, 61, -44, 6, + -1, -16, 41, -28, 19, -37, 49, -11, -38, -8, 65, -53, 9, -21, 59, -37, + 8, -33, 59, -13, -80, 67, 19, -39, -28, 70, -21, -25, -3, 23, 17, -29, + -44, 83, -41, 0, -23, 53, -27, -12, 21, -19, 21, -21, 13, -4, -12, -5, + 38, -58, 34, 10, -22, -16, 47, -8, -39, 19, 12, 4, -46, 39, -24, 48, + -69, 45, -18, 10, -5, -2, -4, 10, -5, 7, -17, -3, 20, 0, -40, 26, + 40, -64, 11, 34, 1, -49, 11, 35, -22, -14, -32, 98, -47, -37, 9, 76, + -70, -8, 7, 63, -92, 56, -49, 77, -64, 2, 41, -28, -25, 37, 0, -26, + 35, -40, 16, 3, 14, -46, 22, 18, -6, -9, -11, 22, 26, -44, -46, 94, + -60, 18, -37, 69, -33, 5, -20, 42, -32, -20, 24, -1, -10, -12, 39, -31, + 13, 1, 9, -47, 42, -26, 39, -73, 48, 48, -73, -13, 56, 14, -78, 38, + 11, 12, -50, 8, 39, 3, -79, 73, 2, -25, -17, 23, 27, -58, 26, -37, + 67, -49, 11, -12, 62, -82, 64, -41, 3, 26, -17, -45, 55, -4, -22, 10, + -2, 38, -54, 8, 5, 47, -79, 7, 54, -7, -64, 41, 49, -73, 29, -24, + 54, -51, -4, 14, 33, -84, 82, -46, 17, -25, 57, -44, -2, 11, 8, 15, + -66, 46, 19, -25, -44, 58, 10, -38, -23, 77, -48, -3, -12, 24, 24, -70, + 37, 21, -15, -48, 81, -66, 44, -29, 6, 4, 9, -30, 31, -24, 5, 19, + -51, 34, 21, 11, -92, 78, 19, -44, -54, 104, -47, -8, -19, 29, 45, -78, + 6, 55, -11, -75, 66, -10, 8, -38, 24, 10, 4, -57, 66, -20, -25, 20, + 6, 9, -71, 100, -60, -6, 8, 28, -37, 29, -42, 78, -58, -22, 42, 10, + -69, 34, 33, -36, 29, -54, 81, -54, 0, 7, 1, -19, 22, -14, 4, -3, + 32, -13, -59, 86, -54, 4, 0, 21, -35, 43, -68, 91, -31, -53, 38, 48, + -72, -15, 50, 3, -11, -72, 96, -1, -49, -23, 81, -21, -57, 15, 63, -67, + 5, 25, -27, 34, -48, 49, -26, 12, -33, 66, -73, 14, 35, -20, -27, 45, + -24, 12, -12, 0, 24, -50, 33, -26, 45, -65, 47, -7, -4, -9, 19, -19, + -2, 15, -17, 30, -39, 25, 2, -3, -57, 109, -86, 10, 14, 31, -53, 7, + 32, 5, -44, -20, 84, -35, -34, -6, 99, -97, 1, 23, 40, -65, 15, 9, + 36, -45, -22, 55, 4, -55, -3, 73, -80, 63, -49, 28, 2, -10, -19, 24, + -13, 8, 1, -15, 5, 22, -4, -57, 72, -41, 16, -45, 76, -57, 30, -26, + 38, -16, -34, 32, 12, -53, 22, 47, -46, -4, 6, 45, -65, 32, -21, 45, + -44, -22, 69, -44, -16, 29, 19, -59, 40, -7, 42, -77, 39, -4, 29, -74, + 27, 38, -12, -60, 69, 7, -32, 1, -9, 50, -56, -15, 19, 47, -75, 44, + 5, -22, 27, -7, -22, 0, 23, -30, 1, 4, 33, -44, 29, -24, 57, -67, + 17, 18, 4, -59, 32, 48, -72, 28, -2, 13, -10, -21, 16, 58, -117, 85, + -14, -5, -34, 21, 29, -27, -20, 31, 23, -49, 16, -14, 51, -74, 24, 38, + -38, -16, 56, -33, -7, 3, 0, 36, -80, 49, 23, -19, -48, 76, -61, 43, + -41, 27, -11, 23, -30, 8, 3, 15, -14, -22, 16, 3, 15, -39, 11, 38, + -13, -70, 88, -41, 2, 4, -30, 80, -84, 15, 37, -6, -61, 58, -19, 27, + -72, 64, -6, -16, -30, 59, -21, -21, -12, 44, 22, -101, 78, -10, -16, -11, + 20, -21, 31, -36, 37, -18, -20, 46, -24, -23, 10, 21, -36, 32, -38, 68, + -50, 12, -6, 19, -33, 14, -16, 20, -11, -14, 47, -59, 56, -14, -27, 5, + 29, -43, 49, -96, 106, -35, -41, 28, 35, -30, -29, 37, 12, -11, -58, 79, + -31, -16, -11, 43, -13, -25, 3, 71, -76, -13, 64, -39, 3, -45, 66, -13, + -1, -45, 80, -40, 6, -29, 26, -12, 6, -19, 21, -4, 9, 0, -37, 44, + -28, 11, -22, 19, 7, 1, -45, 60, -13, -42, 32, -16, 31, -50, 35, 10, + -22, -23, 60, -62, 21, -2, 39, -49, -4, 24, 30, -53, -23, 66, -33, 2, + -34, 69, -33, -10, 7, 24, -51, 28, 0, 9, -24, -3, 38, -24, -16, -9, + 68, -81, 38, -16, 35, -34, -4, 16, 20, -43, 10, 7, -3, 14, -30, 38, + -39, 38, -20, -12, -20, 78, -79, 22, -4, 44, -48, -6, 37, -2, -25, -24, + 60, -41, 15, -30, 50, -43, 7, 9, 27, -64, 45, 5, -15, -17, 1, 49, + -56, 3, -11, 69, -78, 37, -5, 38, -60, 26, -2, 9, -51, 53, -20, -3, + 9, -1, 38, -74, 40, 6, -13, -54, 69, -24, 6, -22, 31, 0, -17, 12, + -13, 8, -9, 20, -53, 56, -27, 29, -63, 41, 8, 11, -73, 59, 15, -25, + -21, -1, 61, -69, 10, 17, 28, -59, 34, -14, 32, -54, 17, 22, -11, -47, + 63, 7, -56, 46, -28, 50, -96, 60, 2, 0, -37, 36, -11, 15, -38, 41, + -19, -31, 46, -12, -25, 9, 49, -67, 47, -48, 51, -30, -15, 23, 19, -43, + 8, 17, 4, -11, -29, 54, -48, 38, -28, 10, -9, 38, -48, 27, -47, 55, + 3, -59, 22, 41, -5, -59, 38, 5, 31, -101, 72, 11, -36, -18, 54, -25, + -1, -30, 54, -28, -34, 61, -27, 13, -46, 55, -21, -10, -21, 52, -34, -8, + 30, -21, 20, -11, -21, 22, -2, -46, 79, -84, 60, -9, 13, -57, 51, 2, + -16, -38, 34, 15, -23, -7, -6, 53, -38, -22, 29, 23, -63, 65, -34, -21, + 34, -7, -19, -8, 24, 13, -8, -63, 110, -56, -8, -37, 79, -56, -3, -3, + 62, -57, 19, 9, 8, -20, -29, 27, 13, -28, -19, 79, -80, 58, -31, 24, + -16, -35, 46, 0, -52, 36, 21, -29, 16, -23, 26, -29, 38, -42, 26, -41, + 60, -29, -16, -4, 42, 7, -85, 53, 47, -54, -29, 67, -53, 39, -58, 45, + -5, 5, -37, 61, -56, 27, 17, -40, 1, 15, 17, -43, 19, 4, 30, -49, + 12, -1, 49, -64, -27, 96, -41, -47, 45, 8, -38, 35, -50, 74, -81, 54, + -14, 24, -64, 57, -5, -25, -19, 27, 16, -27, 4, 16, 2, -25, 26, -31, + 22, -35, 56, -54, 0, 55, -23, -29, 9, 38, -38, 12, -41, 74, -28, -29, + -3, 61, -71, 36, -32, 43, -19, -14, 21, 0, -10, -19, 32, -42, 20, 11, + 23, -94, 107, -13, -53, 5, 35, -17, -11, -25, 32, 40, -76, 29, 32, -9, + -65, 80, -42, 6, -22, 42, -27, -2, 10, -2, 13, -41, 32, 10, -17, -26, + 53, -50, 40, -42, 30, -19, 41, -50, 33, -20, -1, 40, -67, 8, 29, 15, + -58, 25, 32, 15, -81, 46, 14, -8, -51, 24, 40, -44, 17, 10, 2, -26, + 47, -68, 49, -49, 50, -27, -3, -20, 84, -62, -32, 52, 12, -52, 0, 42, + -30, 24, -47, 45, -16, 11, -51, 74, -47, -9, 45, -19, -18, -5, 41, -39, + 11, -33, 56, -20, -14, -8, 64, -85, 60, -23, -13, -3, 33, -20, -25, 57, + -34, 2, -23, 42, -21, 3, -49, 85, -35, -27, 1, 54, -34, -31, 24, 15, + 6, -45, 54, -30, 12, -27, 40, -61, 39, 1, -5, -18, 17, 14, 7, -33, + -27, 83, -44, -40, 21, 66, -82, 32, -7, 33, -54, 27, 3, 2, -13, -15, + 52, -57, 14, 14, -6, -27, 54, -45, 23, -11, 16, -27, 27, -33, -3, 36, + -46, 47, -15, -8, -7, 67, -93, 12, 34, 17, -73, 32, 15, 29, -44, -17, + 47, 2, -40, -31, 81, -43, 3, -24, 52, -32, 4, 1, 20, -48, 20, 40, + -68, 23, 14, 19, -64, 46, -8, 17, -48, 55, -29, 23, -59, 48, -2, -27, + 11, 1, 21, -30, 25, -24, 29, -41, 21, 0, -15, -17, 64, -47, 1, 31, + -22, 2, -11, 22, -56, 69, -53, 32, -30, 31, -16, 32, -68, 29, 42, -39, + -49, 80, 17, -74, 17, 0, 55, -88, 25, 29, 14, -72, 56, 0, 0, -33, + 20, 5, -34, 35, -33, 45, -37, 23, -9, 10, -54, 67, -22, -13, -15, 41, + -14, -16, 8, 0, 19, -51, 56, -51, 39, -20, 19, -34, 26, -18, 19, -31, + 23, 0, 12, -31, 7, 45, -65, 22, 4, 24, -73, 74, -13, -34, 18, 23, + -16, -25, -2, 40, 5, -84, 76, -4, 6, -74, 75, -7, -10, -51, 60, -13, + 0, -45, 50, 18, -57, 20, 21, -7, -26, 47, -51, 28, -19, 12, -13, 3, + -1, 20, -23, 1, 28, -18, 3, -41, 67, -72, 34, -11, 33, -47, 47, -9, + -20, -2, 28, -21, -27, 11, 26, -15, -25, 57, -44, 46, -67, 49, -5, -30, + 1, 42, -36, -9, 22, 7, -13, -34, 67, -29, -16, -26, 84, -49, -21, -11, + 77, -53, -43, 62, 0, -3, -32, 23, 13, -5, -69, 88, -42, 7, -17, 37, + -35, 27, -6, -13, -11, 31, -17, -28, 45, -17, 8, -32, 41, -48, 39, -35, + 41, -16, -28, 41, -3, -13, -26, 23, 12, -22, -50, 104, -57, 9, -28, 67, + -53, -7, 0, 45, -41, -22, 50, -8, -21, -9, 38, -19, -18, -2, 55, -76, + 38, -12, 39, -49, -14, 64, -24, -45, 25, 50, -66, 23, -15, 32, -36, 32, + -46, 44, -14, 2, -16, 22, -7, -11, 14, -28, 21, 4, -10, -18, 63, -66, + 30, -20, 36, -35, -16, 26, 12, -37, 6, 50, -35, -15, 6, 48, -64, 4, + 12, 46, -85, 33, 12, 25, -49, -11, 77, -53, -18, 19, 29, -41, -1, 3, + 39, -70, 55, -6, -1, -23, 38, -22, -12, 1, -11, 36, -39, 5, 15, 33, + -55, 32, -8, 6, -37, 39, -32, 4, 27, -23, 11, -1, 10, -28, 19, -24, + 52, -69, 27, 21, 11, -72, 52, 17, -35, -13, 16, 33, -44, 4, 19, 18, + -60, 13, 35, 12, -93, 82, 9, -35, -20, 26, 40, -74, 14, 18, 28, -66, + 37, 4, 9, -43, 34, -15, 17, -35, 38, -11, -14, 14, -5, 2, -36, 54, + -35, 2, 1, 29, -35, 9, -4, 24, -32, -5, 31, -19, -17, 28, 34, -86, + 49, 13, -16, -52, 71, -29, 3, -30, 51, -1, -36, 6, 25, 4, -75, 56, + 10, -21, -18, 37, -16, 17, -53, 60, -7, -38, -9, 63, -18, -70, 67, 1, + -19, -32, 50, -20, 11, -23, 24, -10, -3, -21, 32, -26, 7, 12, -19, 35, + -29, 26, -41, 32, -22, 14, -43, 41, 7, -16, -24, 57, -20, -35, 25, 7, + -11, -20, 31, -18, 10, -34, 44, -7, -22, -9, 49, -33, -18, 26, -4, 12, + -63, 51, 11, -16, -40, 80, -28, -37, 5, 61, -78, 22, 16, -3, -10, -5, + 26, -8, -2, -43, 68, -42, -24, 39, 11, -31, 15, -9, 18, -20, -1, 7, + -17, 26, -30, 31, -31, 42, -28, -1, -15, 49, -51, -2, 26, 3, -12, -11, + 7, 22, -9, -51, 70, -27, -14, -13, 53, -37, -12, 9, 44, -57, -14, 51, + -6, -27, -10, 60, -55, 2, 14, 18, -45, 32, -19, 29, -27, -12, 31, 14, + -54, 17, 41, -62, 51, -40, 40, -40, 12, -8, 28, -39, 16, 10, 10, -46, + 37, 12, -42, 17, -4, 2, -17, 35, -34, 38, -30, 21, -6, -36, 36, 13, + -56, 14, 53, -36, -13, -1, 61, -64, 7, -3, 54, -63, 5, 14, 34, -67, + 10, 46, -27, -18, 26, 20, -41, 14, -13, 40, -66, 20, 38, -34, -11, 39, + -16, 11, -26, 7, 28, -58, 26, 0, 30, -61, 44, 11, -30, -17, 66, -40, + -33, 35, 6, -21, -2, 9, 16, -13, -39, 79, -71, 27, 9, -9, -29, 28, + 4, -17, 1, 14, 2, -20, -2, 16, 24, -67, 20, 37, -4, -80, 75, 18, + -46, 2, 10, 25, -31, -28, 43, 19, -75, 59, -13, 14, -40, 29, 7, -22, + -20, 44, -20, -16, 10, 32, -21, -42, 61, -19, -29, 12, 39, -55, 32, -4, + 0, -2, -24, 40, -19, -38, 34, 22, -33, 11, -3, 31, -49, 21, -16, 40, + -54, 12, 29, -19, -8, 17, 17, -52, 28, 22, -39, -2, 45, -42, 23, -46, + 51, 11, -68, 26, 55, -34, -44, 45, 9, -19, -43, 57, -16, -5, -9, 40, + -24, -12, 8, 29, -54, -4, 50, -37, 0, 11, 7, -4, 0, -25, 57, -62, + 19, 18, -7, -22, 12, 19, -27, 9, -5, 15, -19, 2, 15, 4, -45, 36, + -5, 8, -48, 60, -13, -35, 36, -19, 21, -24, -7, 23, -24, -22, 73, -58, + -5, 34, 25, -71, 19, 30, 0, -43, -4, 50, -9, -21, -21, 69, -28, -46, + 24, 29, -45, 12, 3, 21, -13, -28, 47, -9, -37, 21, 22, -46, 21, 8, + -1, -32, 42, -22, 14, -27, 19, 16, -29, 3, 17, -1, -39, 28, 21, -42, + 8, 47, -45, 2, -16, 50, -20, -54, 50, 9, -25, -12, 41, -29, 8, -3, + -5, -13, 25, -16, 19, -30, 15, 15, -2, -52, 38, 38, -69, 12, 37, 9, + -54, 10, 36, 5, -79, 27, 57, -35, -40, 48, 21, -41, 13, -3, 10, -29, + 4, 18, 4, -50, 52, 1, -28, -6, 41, -25, -22, 34, -22, 10, -5, 3, + -6, -1, 2, 26, -48, 24, 12, 5, -54, 36, 18, -32, -6, -3, 48, -28, + -21, 22, 35, -63, 6, 43, -28, -27, 42, -7, -22, 6, 21, 8, -56, 31, + 23, -10, -73, 76, 18, -49, -26, 70, -21, -23, -8, 35, 0, -42, 7, 42, + -26, -28, 47, -31, 0, 13, 11, -25, 14, -6, 10, -13, -26, 40, -14, -5, + -8, 42, -36, 1, 15, -10, -34, 47, -24, 5, -22, 38, 14, -39, -10, 53, + -26, -67, 72, 0, -15, -25, 29, 19, -29, -25, 50, -14, -31, 10, 42, -44, + -24, 81, -40, -32, 12, 45, -41, -5, -1, 47, -27, -54, 54, 32, -64, 4, + 26, 1, -1, -41, 44, 4, -22, -22, 47, -30, 7, 5, 3, -37, 45, 1, + -53, 44, -1, -20, 7, 12, -13, 9, -23, 26, -2, -47, 32, 37, -61, 6, + 42, 0, -25, -43, 76, -23, -38, -10, 73, -24, -57, 47, 45, -70, 3, 19, + 7, -19, -8, 10, 24, -12, -36, 66, -60, -1, 50, -32, -19, 8, 26, 2, + -44, 11, 53, -42, -26, 20, 42, -52, 14, 16, -26, -11, 42, -41, 16, 16, + -23, 13, 1, -6, 17, -18, -41, 71, -39, -23, 40, 13, -30, 2, 19, 0, + -39, 10, 24, -15, -25, 12, 66, -81, 6, 47, 9, -69, 12, 47, -9, -36, + -27, 76, 9, -107, 58, 53, -68, 19, -10, 39, -49, 8, 14, -11, -17, 21, + 18, -25, -17, 47, -4, -48, 32, -9, -4, -3, 8, -5, 29, -40, 13, 14, + -31, 24, 7, -48, 27, 37, -61, 22, 15, 7, -46, 17, 10, 22, -45, -9, + 56, 1, -73, 43, 34, -51, -15, 40, 2, -47, 35, 8, 27, -87, 31, 86, + -94, -27, 67, 10, -44, -15, 43, 11, -46, 6, 9, 33, -71, 35, 26, -30, + -18, 37, -18, -9, 20, -15, 1, 5, 9, -2, -23, -11, 50, -42, -3, 24, + 6, -21, 17, -5, -8, 11, -26, 24, -19, -9, 33, 22, -78, 38, 44, -48, + -53, 80, 6, -66, 14, 36, 8, -37, -15, 66, -24, -75, 87, -14, -27, -10, + 45, -12, -38, 13, 33, 7, -67, 20, 75, -55, -67, 85, 8, -52, -11, 45, + -10, 13, -34, 12, 26, -36, 7, -1, -1, -7, 23, -27, 18, 15, -12, -28, + 27, -6, 9, -52, 40, 26, -50, 3, 51, -10, -71, 67, 10, -59, 4, 56, + -27, -20, -19, 58, 6, -81, 38, 49, -39, -39, 47, 14, -25, -40, 54, -2, + -20, -38, 82, -25, -51, 44, 24, -60, 8, 51, -47, -2, 6, 22, 9, -34, + -20, 78, -56, -25, 36, 19, -49, 17, 32, -50, 44, -29, 4, -11, 14, 3, + -13, -11, 19, 13, -24, 28, -32, 33, -37, 39, -61, 119, -76, 120, -70, 99, + -122, 89, -113, 91, -123, 122, -123, 77, 86, -116, 6, -118, 123, -23, 64, -93, + 17, 24, -125, 124, -125, 124, -24, -12, 56, 87, -54, 38, -91, 64, -2, -41, + 126, -127, 20, 8, -48, -62, 127, -128, 88, -43, -18, 86, -100, 44, -32, -26, + 71, -13, 6, 51, -33, -50, 106, -59, 33, 5, -20, 69, -56, 54, -48, -6, + 38, -5, -38, 35, -1, 12, -1, 4, 23, -56, 19, -7, 5, -4, 31, -38, + 3, -12, -9, -25, -7, 24, -32, 17, -21, -22, 24, -20, 6, -18, 0, -15, + 5, -16, 15, 3, 2, -10, 3, 27, -31, 37, -12, 32, -5, 2, -21, 27, + -14, 20, -8, 5, 15, -7, -11, 20, -37, 7, -23, 17, -22, 11, -14, 8, + -44, 39, -52, 26, 3, 14, -10, 51, -45, 29, -19, 19, -3, 41, -21, 46, + -23, 10, 16, -25, 3, 7, -30, 19, -9, -5, -1, 1, -19, 1, -24, -23, + 51, -48, -10, 17, -34, -38, 60, -71, 26, -43, 65, -59, 70, -26, 61, -51, + 63, -51, 42, -25, 58, -36, 31, 10, -14, -9, 8, -18, 8, 4, 8, 7, + 31, -52, 39, -53, 53, -56, 24, 11, 1, -20, -8, -32, -18, -10, -25, 4, + 1, 37, -37, 42, -42, 53, -57, 52, -18, 30, 11, 20, -52, 55, -61, 56, + -50, 24, -26, 38, -42, 36, -1, -43, 58, -46, 6, 18, -35, 31, -36, 28, + -55, 55, -98, 52, -41, 26, -24, 48, -31, 48, -26, 30, 19, -17, 23, -8, + 13, 15, 19, -7, -23, 41, -36, 20, -39, 65, -64, 66, -38, -9, 7, -14, + -10, -3, 6, 15, -19, -40, 53, -67, -11, -12, -25, 23, -11, -12, 46, -48, + 39, -20, 20, -14, 31, -54, 71, -25, 2, -8, -5, -9, 1, 7, 27, 17, + -14, 43, -31, 27, 11, -33, 20, -2, -33, 45, -38, 17, -9, -11, -17, -22, + -19, 20, -25, 4, 29, -35, 14, -17, 1, -7, 19, 2, 16, 32, -3, -17, + 4, 0, -9, 17, 5, -8, 52, -32, 40, -39, -5, -18, 14, -21, 31, 10, + -17, 8, -34, -7, 1, -44, 7, 10, -8, -6, -18, -25, -1, -19, 16, -29, + 62, 6, 9, 21, 0, -14, 4, 5, 20, 13, 27, -1, 18, -5, 21, -31, + 11, 2, -9, -4, 21, -27, 8, -21, -28, -19, 14, -12, 5, -20, 20, -36, + 4, -18, -27, -4, -4, 15, 4, 48, -7, -11, 20, -6, 7, 20, 1, 20, + 0, 35, -35, 28, -37, 7, -43, 21, -22, 23, -18, 12, -22, -13, -20, -11, + 7, 23, -10, 19, -18, 17, -41, 4, -16, -8, 21, 11, -4, 10, 30, -24, + 32, -15, 15, -13, 28, -5, 38, -10, 0, -22, -13, -12, 24, -18, 30, -7, + 4, -16, 27, -28, -3, -1, 18, -14, 31, -24, -3, -13, -19, -36, -2, -31, + 9, -2, -12, 17, 12, -50, 46, -49, 43, -15, 13, 22, 15, -25, 10, -8, + -6, 14, -2, 24, 15, 9, 17, -13, 5, 14, -15, 7, 20, 4, 4, 18, + -16, 3, -47, 31, -46, 19, -24, 5, -19, -1, -42, 14, -44, 18, -7, -1, + 15, 9, -35, 32, -44, 39, -46, 23, -16, 36, -25, 45, -34, 32, -8, 10, + 5, 28, 0, 12, 11, 3, 20, -23, 6, -8, 16, 7, 17, -19, 32, -44, + 3, -8, -21, -8, -5, 2, -29, 2, -3, -19, -14, 3, 7, -23, 10, 1, + 3, 8, 13, -44, 20, 21, -16, 23, 3, 5, 10, -11, 32, -11, 13, -7, + 30, 4, 16, -7, -6, -7, 14, -40, 4, -16, -26, 3, -1, 0, -6, 5, + -50, 37, -27, 18, -16, -14, 6, -1, -4, -15, 8, -12, 14, 9, -22, 42, + -10, 23, -11, 36, -15, 13, 30, 1, 47, -20, 33, -14, -12, 1, -20, -9, + -9, -11, -13, 7, -37, 25, -47, 14, -13, 4, -12, 9, -32, 18, -48, -1, + -35, -1, -7, 35, -20, 53, -4, 34, -7, 13, 19, 9, 30, 6, 45, -22, + 23, -18, -6, -1, 3, -30, 14, -15, 9, -39, 10, -33, -13, -24, 10, 14, + 14, -10, 2, -34, -4, -20, -21, -14, 40, -10, 17, -14, 28, -17, 37, -26, + 69, -15, 38, 2, 21, -25, 37, -61, 13, -9, 5, -17, 18, -41, 22, -57, + -1, -9, -13, 24, -10, 38, -5, 8, -16, -2, 1, 12, -25, -2, -13, 2, + 2, -16, -19, 32, -30, 22, 20, -4, 12, 11, -17, 19, -17, -3, 20, -33, + 65, -27, 32, -14, 8, -8, 13, -19, 9, -2, 7, 33, -40, 18, -18, -18, + 6, -23, -11, -11, -28, 4, -11, -15, -14, -8, -5, 34, -6, 19, 1, -3, + 9, -1, 5, 5, 14, -11, 40, -3, 18, -20, 16, -7, 2, -5, 9, -16, + 9, -17, 0, -17, 4, -17, -3, 3, 8, -14, -19, 12, -21, -7, 1, -2, + -8, 16, 3, -6, 35, -23, 33, -13, 11, 12, 3, -7, 26, -11, 19, -18, + 23, -22, 39, -49, 39, -50, 11, -38, 26, -29, 10, -6, -22, 15, -8, 15, + -37, 36, -43, 39, -43, 18, -26, 1, 11, 4, -2, 9, 7, 2, 7, 19, + 1, 1, -4, 16, -5, 16, -9, -3, 4, -4, -1, -17, 0, 11, 16, -27, + 12, -15, 15, -3, 0, 10, -3, -5, 12, -13, -7, -13, -31, -1, -3, -17, + 15, -31, 25, -10, 15, -1, 2, 4, 10, 7, 32, -13, 7, -22, 2, -10, + 16, 1, -15, 19, -24, 16, -18, -12, 18, -9, 9, 24, -8, 8, 11, 0, + -31, 17, -55, 21, -43, 40, -40, 29, -54, 44, -34, 22, 11, 16, 7, 19, + 21, -6, 2, -7, -16, 22, 0, -1, -4, 5, -8, 26, -42, 4, -6, -21, + 35, -16, 8, 0, -22, -13, 11, -31, 7, -28, 4, 17, -12, -18, -2, -23, + 23, -1, 19, 34, 7, 7, 35, -19, 11, -8, -17, 8, 4, 16, -16, -13, + 9, -15, -5, -1, -6, 7, 3, 11, 1, -7, -24, 21, -31, 36, -3, -10, + 8, 2, -17, 12, -24, 6, -3, 9, 15, 3, 13, -8, -13, -3, 6, -19, + 14, -33, 16, -17, -5, -31, 3, -29, 24, -7, -6, 35, -20, -5, 34, -20, + 25, -3, 10, 25, 8, 14, -13, 0, 1, 17, -33, 51, -38, 45, -32, 39, + -3, -2, -24, 3, -18, 14, -4, -44, 2, -25, -15, -2, -23, 3, -2, -2, + 20, -14, 8, -10, -4, 21, 11, -13, 32, -4, 8, 19, -16, -2, -2, -2, + 14, -2, -1, 27, -26, 20, 11, -13, 10, -3, -7, 12, -13, -3, -30, -16, + 10, -26, -3, -10, -2, -9, 15, -17, 1, -2, -7, 14, -8, 12, -3, -1, + 2, 47, -26, 22, -19, 16, 2, 13, -3, 21, -10, 22, -32, 43, -24, 16, + 0, 5, -2, 12, -44, -12, 1, -26, 1, -36, 5, 2, 9, -17, 20, -37, + 14, -9, -5, 6, -3, -13, 23, -19, 25, -33, 6, 17, 10, 19, 15, -4, + 12, 5, -9, 33, -20, 26, -9, 11, -2, 11, -21, -7, -13, -4, -8, -12, + 0, -10, -9, 8, -33, 9, -26, 8, 6, -8, 12, 7, -8, 0, 7, -16, + 25, -8, 27, 12, 0, 9, -9, 4, -17, 14, -16, 11, -8, 18, -2, 4, + 2, -20, -18, 22, -16, -5, 3, -24, 13, -10, -12, -10, 2, -16, 33, -15, + 21, -15, -4, -19, 29, -22, 18, 2, 20, 12, 18, -22, -7, -16, 7, -19, + 14, 1, -17, 33, -22, 38, -8, 3, -3, 21, -17, 51, -43, 15, -22, -23, + -6, -12, -14, 14, 9, 6, 4, -31, 3, -16, -14, 22, -22, 5, 13, -25, + 17, -2, -18, 7, 1, 5, 36, -16, 23, 4, -15, 29, -20, 10, 1, 24, + 17, 16, -4, -16, -37, -11, 1, -33, 27, -36, 17, -22, 2, -33, 16, -29, + 32, -7, 24, -12, 14, -12, 22, -16, 15, -20, 19, 9, 14, 12, -1, -24, + 13, -6, -1, 32, -19, 24, 12, -26, 4, -31, -38, 18, -16, -13, 3, -14, + -1, 11, -15, 15, 0, -2, 30, -6, 35, -23, 10, -35, 5, -14, 17, -21, + 20, 4, 7, 8, -5, -15, 20, -25, 26, 6, -3, 3, 5, -24, 26, -35, + 4, 0, -6, 13, -23, 8, -25, 1, -2, 9, 3, 17, 4, 0, 13, -15, + 3, -21, -16, 4, -5, -10, 11, -2, 7, 23, -22, 25, -19, 18, 25, -9, + 14, -21, -7, 11, -24, 22, -12, -7, 6, 9, -33, 11, -20, 2, -9, 2, + 3, -13, 12, -15, 23, -21, 16, -16, -2, 8, 13, -12, 18, -10, 16, -12, + 20, -18, 18, -1, 21, -21, 20, -30, -6, 10, -2, 13, -6, -15, 6, 2, + -1, 1, -19, 9, -15, -3, -11, 0, -5, 1, 5, 1, -4, -8, 1, -16, + 23, 0, -23, 2, 8, -6, 38, -4, 2, 13, -17, 31, -4, -8, 22, -14, + 0, 12, -22, 7, -7, 11, 4, -4, -12, -9, -22, 2, -17, -17, -11, 7, + -17, 19, -24, 9, -8, -6, 29, -4, 10, 4, 4, 23, -1, 9, -6, -12, + 23, 16, -6, 33, -29, 12, -7, -10, 17, -4, -18, 21, 0, -14, -2, -20, + -21, 10, -28, 5, -18, -4, 0, -11, 1, 5, -17, 3, 9, 20, 6, 1, + -7, 2, -7, 3, 9, -22, 29, 6, -1, 25, -10, 6, -1, 4, 12, 18, + -13, 28, -11, 6, -15, -14, -22, -7, 5, -14, 1, -16, -12, -5, 5, -9, + 4, -1, -14, 21, -10, -5, 0, -17, -7, 2, -10, 6, 11, 1, 37, -17, + 6, 21, -24, 41, 2, 23, 0, 10, -18, 16, -26, 14, -21, -19, 18, -9, + -14, -1, -9, -14, -3, -7, -10, 7, -7, 19, -11, 15, -25, -3, -6, 2, + 8, -10, 4, 12, -3, 11, -2, -2, 5, 31, -9, 39, -21, 14, -23, 18, + -16, -1, -3, -6, 0, 22, -9, -5, -17, -4, -12, 2, -3, -7, 10, -10, + 7, -20, -19, -10, 0, -14, 32, -15, -18, 13, -9, 2, 17, -14, 6, 36, + -9, 28, 1, 0, 17, -10, 5, 17, -8, 12, -2, 3, 2, -22, -6, -14, + 6, 8, -11, -14, 2, -23, 25, -35, 3, -18, 1, -14, 22, -1, -12, -7, + -9, 13, -4, 12, 4, -3, 18, 0, 1, 8, -14, 14, -2, 1, 17, -3, + -14, 35, -17, 19, -14, -6, 1, -9, 18, -17, -4, -13, -2, -14, 10, -10, + -6, 0, 3, 5, -12, -13, -3, -6, -6, 11, -13, -7, 13, -2, 6, 13, + -7, 11, -5, 23, 1, 29, -17, 23, -10, 18, -16, 12, -20, 10, 7, -9, + -5, -21, -9, 5, -13, -2, 0, -15, -11, 3, 0, -18, 5, -25, -2, 3, + -2, -3, 4, 8, 14, -7, 15, 4, 8, 19, 9, 11, 7, -3, 14, -11, + 1, 15, -35, 3, 3, -10, -16, 0, -15, 2, 3, -12, 27, -23, 32, -15, + 10, -14, 3, -27, 10, -15, 12, -24, 7, 2, 9, -2, -2, -1, 3, 1, + 1, 8, -4, 0, 6, -6, 1, 1, -1, 8, -11, 31, -27, 13, 4, -3, + 5, -1, 0, 2, 9, 0, 12, -31, 4, -27, 1, -25, 20, -21, -14, 12, + -14, 0, -5, -23, 18, -1, 15, 19, -5, 20, -8, 14, -7, 16, 3, 0, + 8, 10, 0, -8, -10, 3, -8, 9, -12, 4, 15, -6, 2, -12, -29, -3, + -16, -11, 35, -18, -1, -28, 7, -12, 0, 7, -5, 22, 10, 10, -4, 6, + -13, 21, -23, 20, 8, -13, 11, 15, -6, -6, -22, -1, 3, 14, 7, 11, + -27, 12, -17, -12, 8, -15, 3, -8, 12, -12, 5, -30, 12, -18, 9, -2, + 3, 4, 15, 1, 5, -9, 0, -8, 24, -2, 21, 5, -4, -4, 14, -15, + 0, -1, 3, 17, -5, 13, -19, -10, -4, -6, -4, -7, 18, -27, 8, 1, + -12, -21, -13, 1, -9, 11, 1, -3, -1, 22, -21, 9, 6, -3, 20, -2, + 17, 7, -12, 1, 4, 4, -9, 9, -20, 24, 7, -9, -3, -7, -6, 10, + 7, 3, 9, -2, -3, -4, 1, -19, -8, -16, 0, -12, 0, -25, 4, -22, + 10, -9, 0, -3, 15, -1, 8, 11, -15, 10, 13, 1, 22, -5, 15, 1, + 24, 6, 0, -6, 5, 5, 10, 8, -1, -11, -14, 3, -31, 2, -22, -4, + -8, -15, -2, -31, -12, 6, -7, 5, 2, 3, -4, 19, 3, 4, 7, 7, + -8, 31, -6, 26, 1, -2, 2, -3, -10, -4, -4, 9, 3, 12, -16, 16, + -9, -1, 5, 4, -7, 13, -17, 0, -11, -13, -22, 1, -9, 4, -7, 7, + -10, 5, -1, -6, -3, -21, 7, -10, 18, -3, 1, -7, -11, 11, -8, 12, + 20, 3, 13, 16, -1, 3, 13, -3, 23, 16, -3, 15, -14, 12, -6, -8, + -28, 0, -33, 4, -11, -12, -13, -21, -17, -16, -5, -12, 16, -7, 15, -6, + -5, 3, -9, 21, 17, 13, 14, 11, 21, -12, 31, -18, 7, 12, 8, 9, + 7, 1, -3, -7, -14, 17, -35, -10, -2, -18, -8, -10, -20, -22, 2, -10, + -3, 1, -1, 4, -5, 11, -20, 11, -6, 27, 7, 18, 8, -1, 2, 3, + 11, -9, 5, 5, -7, 29, -6, 20, -21, 23, -15, 19, -19, 2, -22, 11, + -26, -7, -10, -30, -1, -3, -6, 15, -22, 16, -7, -9, -2, -7, -5, 11, + 17, -13, 2, 8, -5, 6, 27, -6, 12, -6, 4, 15, 3, 14, -3, -12, + 11, -2, 6, 5, 4, -6, -12, 0, -32, 2, -22, 22, -12, -5, -7, -11, + -7, 6, -1, -3, -3, -16, 2, -1, 0, 0, -7, -2, 1, 12, -4, 5, + 20, 1, 16, -2, 14, -1, 19, 8, 29, -8, 7, -14, -2, 3, -13, 8, + -40, 22, -18, 2, -14, -8, -11, -8, 12, -21, -1, -10, -12, -6, -4, -14, + 6, -19, 7, 14, 1, 11, 11, -11, 25, 1, 14, -5, 31, 0, 22, 4, + 1, 3, 6, -3, 4, -2, -20, -7, -26, 1, -12, -7, -10, 2, -1, -5, + -7, -8, -10, 6, -7, -6, 10, -17, 6, 3, 15, -8, 15, -7, 12, 1, + 9, -4, -2, 10, 9, -1, 10, -4, 9, -8, 17, 0, -13, -7, -2, -11, + 3, -2, -15, -4, -11, -5, -9, 1, 8, -10, 8, -8, -6, -18, 21, -19, + 26, -19, -1, -11, 10, 4, 12, -10, 16, -10, 17, 8, 13, -1, 17, 1, + 5, -1, 11, -8, 9, 16, -17, 3, -26, -17, -14, 6, -17, 4, -20, 0, + -1, -6, -4, 2, -15, 13, -3, -1, 0, -2, -8, 11, 7, -3, -8, 5, + 14, -1, 28, -19, 13, -4, 8, 1, 11, 7, 6, -8, -2, -13, -10, -22, + 6, 11, -1, -1, -5, -13, 18, 3, -10, 9, -17, -8, 9, -9, 1, -17, + -4, -16, 18, -6, 15, -10, 17, 5, 0, -5, 0, -11, 12, 15, 4, 8, + 5, -4, 0, -2, 3, -17, -2, -1, 11, -6, -7, 2, -33, 23, -6, -1, + -2, -2, -1, -8, 3, -29, -2, -34, 16, -3, 16, 1, 10, -12, 23, 0, + -3, 16, 12, 19, 23, -1, 8, -26, 16, -32, 26, -13, 2, -11, 5, -1, + -15, -9, -16, 7, -6, 14, -15, 5, -10, -7, -9, -9, 6, -17, 13, 18, + -5, -3, -4, -4, -18, 28, -6, 13, 17, 24, -2, 9, -14, 1, -11, 7, + 17, 1, -15, 10, -23, -4, -12, 5, -20, 17, -10, 6, 0, -9, 4, -8, + -15, 6, -16, 7, 9, 3, 6, -12, -17, 0, 4, 13, 22, -4, 10, -8, + 7, -12, 5, 5, 1, 11, 2, 10, -3, -2, 3, -10, -5, -7, -4, -18, + 17, -2, -14, -16, -7, -10, -3, 6, -1, 14, -11, 15, -18, 2, -6, 0, + -1, 0, 20, -17, 1, 6, 2, 6, 12, -3, 7, 25, -5, 17, -14, 0, + -6, 0, -2, -5, -1, -10, 8, 2, -9, -19, -7, -17, 5, 3, -7, 4, + -15, -5, 9, -12, -1, -5, 3, -5, 26, -2, 3, -4, 5, 3, 7, 10, + 5, 6, 6, 26, -17, 0, -1, 3, -3, 10, -7, -7, -9, 11, -18, 0, + -16, -6, -5, 3, 7, -14, -14, 0, -21, 14, -8, -1, -12, 2, 1, 2, + -3, -1, -3, 18, 5, 5, 9, 12, 7, 18, 8, 5, -25, 16, -15, 16, + -7, 9, -22, 1, 14, -13, -5, 2, -6, -8, 13, -17, 6, -16, 1, -5, + -14, -6, -6, -15, -2, 9, -9, -18, 15, -19, 12, 7, 4, 8, 14, 15, + 6, 10, -3, 9, -7, 23, -17, 21, -20, 7, 0, -9, 8, -10, 1, 4, + 2, 3, -9, -9, -15, -6, -21, -16, -6, 0, -11, 19, -8, -9, 5, -6, + 0, 5, 14, 7, 1, 12, 8, 7, -5, 12, 8, -4, 19, 4, -7, 2, + 3, -12, -8, -1, 0, 5, 7, -5, -8, -22, -8, -21, -2, -9, 10, -20, + 13, -6, 8, -17, -9, -6, 2, 5, 8, 6, -3, 10, -9, -2, 15, -6, + 20, 7, 11, 10, -3, -4, -8, 25, -25, 18, -12, 17, -6, 20, -22, -1, + -17, -10, 5, -10, 9, -13, -9, -6, 10, -25, -5, -2, -5, 13, 2, -5, + -8, -10, 11, -27, 10, -4, 11, 0, 33, -4, 10, -14, 1, 12, -2, 27, + -8, 6, 11, 9, -12, -4, -10, -13, 12, 5, 1, -10, -14, -15, -8, -7, + -9, 3, -5, 10, 3, -11, -12, -13, -3, -3, 3, 2, 9, 17, -6, 25, + -3, -3, -8, 19, 3, 30, -10, 12, -22, 7, -5, -10, -3, 21, -8, 12, + 6, -5, -13, -13, -9, -9, -1, -23, 13, -17, 15, -22, -11, -18, 8, -14, + 20, 1, 4, -5, 3, 3, 5, 11, 1, 2, 27, 1, 10, -7, -8, -2, + -2, 7, -1, 17, -5, 24, -7, 5, -10, -20, -6, 5, -4, -5, -1, -18, + -5, -14, -1, -20, 1, 7, -7, 12, -4, -2, -4, 2, 8, 0, 7, 1, + 6, -2, 18, -5, -7, 4, 3, -2, 13, 4, 0, 2, -3, 2, -10, -6, + 1, -6, 6, -7, -3, -21, -2, -12, 5, -1, -9, 7, -3, 13, 5, 5, + -8, 0, -8, 19, -5, 13, 13, -7, 3, 0, -10, 0, -8, 20, -8, 13, + -20, -5, -7, 3, 5, -7, 2, -5, -4, -14, 11, -23, -13, 2, -1, 12, + 13, 5, -6, 23, -9, 9, -6, -9, 18, -13, 16, -3, -7, -17, 3, -13, + 12, -9, 4, 0, 0, 13, -18, -1, 3, -13, 20, -5, 1, -20, 15, -23, + 18, -4, -8, 5, -7, 16, 4, 6, -3, 7, -21, 19, -17, -7, 9, 5, + 3, -5, -3, -16, -9, 25, -9, 12, -5, 10, -5, 9, -4, -6, -3, 4, + 10, -2, 11, -12, -2, -14, 8, -23, -5, 0, -8, 9, -2, -11, -3, -9, + 9, 2, 2, 4, -5, 7, 11, -16, 0, -6, 7, 6, 25, 5, 6, -4, + 3, 4, 3, 2, -8, -3, 5, -1, -11, -4, -9, -3, -15, 10, -12, -5, + 11, -4, -7, 6, -29, -5, 6, 11, 3, 9, -18, 13, -14, 19, -1, -2, + 4, 5, 12, 1, 5, -8, 3, 1, 20, -6, 2, 3, -16, 10, -10, -18, + -11, -7, -7, 9, -4, -8, 9, -15, 13, -13, -3, -7, 3, 8, 11, -6, + -16, 1, -8, 20, 4, 15, -5, -3, 11, -5, 6, 0, -5, 10, 13, 0, + -6, -11, 0, 11, -11, 10, -7, -8, 1, 16, -9, 2, -22, -9, 0, 4, + 5, -12, -22, 2, -8, -8, 14, -16, 0, 13, 0, 9, -7, 2, -1, 7, + 8, -3, -3, 2, 15, 5, 10, -7, 12, -4, 22, -4, -3, -12, -2, -15, + 8, -2, -22, 7, -10, 5, 12, -20, -9, -11, -2, -12, 2, -9, 5, -3, + 11, 7, -9, 4, -4, 24, -7, 21, -15, -3, 2, 14, -1, 5, 18, -12, + 13, 3, 5, -10, -11, 0, -8, -2, -4, 2, -15, 9, -10, -16, -9, -7, + 0, -1, 3, -8, -10, 5, -8, 4, -3, 8, -2, 20, 1, 6, -4, -9, + 4, 14, 7, -1, 3, -5, 18, -7, 20, -6, -10, 8, 1, -2, 3, -4, + -5, -3, -6, 0, -16, -7, 12, 0, -17, 4, -31, -7, 1, 1, -4, 8, + -11, 6, -1, 11, -5, -7, -4, 2, 4, 15, -3, 21, -5, 20, 3, -12, + 21, -1, 10, 5, 6, -20, -1, -18, 2, 3, -4, -5, -1, 6, -2, -11, + -17, -15, -13, 0, 6, -18, 7, -18, 7, -7, 6, 7, -10, 18, 16, 2, + -1, 3, -11, 6, 14, 1, 15, -2, 29, -8, 17, -14, 2, -19, 12, 8, + -6, -1, -23, 6, -11, 7, -19, -18, 0, 1, -8, -8, -4, -20, 8, -8, + 4, 10, -12, 13, 0, 18, -10, -3, -4, 6, 4, 17, 7, -2, 18, -9, + 14, -10, -4, -11, 4, 3, 23, -17, -6, -2, -7, -7, 9, -10, 1, 2, + -4, -14, -7, -6, -8, -4, 7, 2, -3, 3, 0, 13, -10, -4, -9, -6, + 18, 11, -4, 16, -8, -4, 1, -1, 7, 3, 3, 3, 10, -15, -2, -9, + 9, 0, 2, 2, -9, 12, -7, 0, -23, -7, -19, 2, -1, 0, 4, -15, + 7, 3, -3, 0, 9, -12, 19, 4, 8, -13, -6, 5, -1, 14, 10, 9, + 13, -3, 16, -18, 13, -18, 7, -10, 13, -6, -11, -3, 7, -23, -6, -11, + -21, 9, -1, 4, -3, -16, 0, -12, 7, 14, -5, 15, 0, 6, -5, -3, + -9, 9, 4, 10, 4, -2, -7, 10, -1, 10, -6, -14, 15, -4, 13, -4, + -4, -14, 5, -2, 4, -9, 3, -14, 2, 3, -10, -1, -9, 0, 3, -6, + 12, -16, 0, 4, 10, -25, 6, -5, 2, 8, 3, -2, -4, 15, 4, 7, + 2, -1, -6, 10, 11, 2, -2, -14, 6, -3, 0, -3, -9, -10, 1, -1, + -15, 9, -29, 9, -10, 7, -3, -3, -10, -2, 14, 4, -6, 0, 1, 12, + 4, 18, -15, 19, 1, 15, 1, 1, 3, -10, 8, -1, 7, -30, 8, -19, + -2, -5, -9, -10, 0, -1, 6, -4, -12, 1, -18, 10, -1, -12, 2, 7, + 12, 11, 0, -4, -1, 6, 10, 17, -8, 1, -12, 5, -2, 1, -7, -1, + 4, 3, -3, -1, -18, 8, -9, 0, -2, 8, -12, 12, 7, -5, -2, -16, + -7, 9, -5, 11, -9, -4, 3, 1, -9, -1, -2, -6, 7, 12, 0, -8, + 9, -10, 3, 0, 2, -3, 11, 14, 4, 3, -12, 3, -3, 2, 12, -4, + -2, -2, 9, -21, -5, -28, -6, -10, 6, 7, -6, -3, -24, 7, -11, 10, + 0, 8, 13, 10, 6, -7, -2, -5, 7, -1, 9, 18, -2, 12, -4, 7, + -26, 13, -6, 19, 6, 6, -5, -16, -6, -8, -18, -2, 1, -11, 3, 4, + -16, -8, -10, -3, 2, -3, 5, 5, 0, 11, 0, -14, 0, 1, 14, 11, + 13, 0, -2, 5, -1, -4, -2, -4, 5, 21, 3, 14, -5, -22, 5, -11, + -3, -6, -3, -11, 0, -5, -13, -10, -18, 3, 9, -10, 2, 3, -11, 11, + -11, 5, -19, 23, -1, 20, 18, 4, -3, -6, 9, 4, -3, 8, 4, 6, + 2, 5, -14, -6, -3, 2, -6, -4, -3, -11, 0, -5, 0, -21, -2, -10, + 11, 5, -4, -5, -5, -8, 10, -10, 4, -1, 6, 12, 9, 2, 8, -20, + 8, -2, 11, -11, 1, -4, 5, 6, -6, 6, -14, 14, 4, -2, 12, -3, + -10, 8, -5, -15, -9, -1, 5, 8, -3, 0, -23, -9, -11, 4, -12, 3, + -4, 4, 1, 15, -12, 3, 13, 2, 5, 8, -8, 7, 11, -3, 17, -11, + 5, 3, 19, 13, 3, -11, -11, -2, -9, -7, -4, -24, -1, -17, -3, -17, + 0, -15, 2, -1, -5, -4, 3, 2, 2, 11, -4, 3, -6, 11, 8, 3, + 6, 3, 7, 7, 6, -6, 2, 0, 14, 14, 3, 8, -6, 4, -3, 6, + -13, -2, -9, -4, 5, -13, -5, -21, -1, -6, -1, -5, -14, 8, -7, 5, + -7, -17, -11, 7, 3, 20, 7, 1, -3, 4, 5, 14, -3, 5, 3, 10, + 8, 6, -6, -2, 6, 3, 7, -6, -3, -3, -6, -1, -27, -11, -17, 0, + 11, 7, 1, -7, -9, -13, 5, -11, 0, -10, 15, 2, 5, -2, -5, 1, + 6, 6, -6, -5, 6, 2, 5, 3, 10, -16, 11, 8, 18, 3, 13, -11, + 7, 5, -7, -6, -20, 15, -1, 10, -1, -13, -17, -11, -3, -13, -4, -14, + -3, -2, -6, 6, -28, 9, -8, 10, 0, 12, -2, 10, 9, 1, 3, -6, + 5, 17, 24, 18, 3, 4, -9, -4, 2, -8, -4, -2, -11, 1, -8, -12, + -9, -10, 5, 0, -7, -9, 7, -18, 6, -10, -12, -1, -1, 13, 1, 18, + 2, -3, 4, 3, 3, -3, 3, 10, 9, 7, 5, -8, -7, 0, 3, -7, + 7, -2, -2, 5, -10, 2, -5, -3, -1, 4, 1, -2, -10, 4, -9, -5, + -12, -18, 3, 6, -3, 3, -15, -1, -13, 6, -2, 8, 0, 8, 16, -2, + 17, -4, 8, 3, 23, -1, 11, -8, 10, -4, -5, -3, -13, -2, -1, -2, + 2, -9, -13, -13, -2, -11, -2, -20, -5, 0, 3, 2, -1, -10, 1, 8, + 3, 9, 6, 4, -3, 13, 3, 4, 11, 2, 11, 8, -2, -1, -2, -2, + -2, -1, -21, -1, -14, 8, 6, -8, -10, 2, -16, 4, -3, -1, -10, 7, + -1, 4, -4, -12, 3, -2, 13, 2, -3, -9, -2, 6, -7, 8, -8, -5, + 12, 7, 8, -3, 6, -1, 16, 0, 7, -8, 3, -7, -1, 0, -6, -4, + -8, 6, -1, 4, -19, 2, -3, -8, -3, -12, 4, -6, 2, -7, 1, -13, + 2, 9, -1, 17, -19, 3, -3, 23, 9, 6, 3, 6, 6, -5, 11, -11, + 1, 0, -5, 6, -6, -4, -5, -7, 3, -4, -14, -9, -7, -1, 5, -11, + 4, -19, 14, -4, 3, 4, 2, 0, 9, -2, -3, 2, -2, 10, 15, -3, + 14, -6, -4, 6, 1, -8, 11, -9, 4, 3, -9, 2, 2, -2, 2, -2, + -9, -2, -2, 1, -6, -6, -22, -16, -10, 12, 0, 5, -8, -2, -4, -2, + 5, -1, 7, 7, 9, 1, 7, 6, -1, 10, 11, 5, -3, 8, 1, -1, + 8, -15, -6, -10, 12, 0, 2, -5, -9, -12, -7, -4, -14, -4, 0, -1, + 5, -7, -8, -12, 0, 2, 16, -3, 11, -4, 16, 11, 2, -3, 2, 8, + -1, 7, -13, 4, -3, -1, 3, -10, -2, -11, 3, 2, 3, -7, -10, -5, + -10, 12, -8, 5, -7, 15, 1, -10, 7, -16, 1, 3, 4, -5, 7, -7, + 4, -2, -1, -8, 0, -2, 17, 10, -2, 6, -5, 3, 10, -7, 2, -3, + 4, 5, 5, -3, -8, -8, -1, 1, 7, -5, -11, -2, -10, -4, -15, -7, + -10, -2, 2, -4, -10, -8, 0, 2, 6, 3, 2, 3, 10, 14, 8, 7, + 3, 5, -5, 20, -6, -1, -2, 0, 1, -2, -2, -8, 3, -3, 10, -14, + 3, -3, -2, 0, -5, 0, -15, 4, -2, 0, 4, -7, 3, -8, 7, -14, + -2, -6, 4, 2, 3, -10, -2, 5, -3, 12, -2, -5, -9, 1, 4, 1, + 11, -12, 15, 5, 20, 10, -5, 1, 5, 3, -13, 6, -16, 5, 1, -5, + -8, -3, -14, -6, -2, -5, -8, -17, -9, 3, -6, -2, -3, -3, 1, 14, + 2, 4, 5, 3, 8, 7, 12, 0, 11, 4, 16, 2, -3, -9, -1, 1, + -1, -3, -6, -14, 4, -6, 2, -14, -9, -11, -1, 0, 0, -5, -6, -10, + 5, -5, 2, -3, 2, 2, 17, -2, -1, -3, 3, 11, 1, 10, 2, 7, + 6, 5, -5, -3, -3, -2, 7, 2, 1, -18, -5, -2, -3, -5, 0, -2, + 0, 8, -9, -10, -15, -7, -2, -1, 6, -8, 16, -10, 13, -4, 2, -4, + 4, 7, 9, 6, -5, -2, 8, -1, 11, -6, -1, 5, 8, 0, 9, -20, + 0, -9, 4, -3, 1, -4, -11, 2, -6, 0, -12, 0, 1, 5, -2, 1, + -7, -4, 3, -1, -10, 3, -3, 7, 4, 8, -9, -6, -10, 0, 0, 2, + -4, 6, 9, 10, 2, 0, -1, 2, 14, 3, 7, -7, 2, -2, -2, -6, + -9, 2, -3, 6, -3, -7, -9, -10, -2, 2, -1, -11, 2, 1, 7, -4, + -7, -19, 3, -1, 6, 6, 6, 6, 0, 6, 7, 3, -1, 3, 8, 3, + 4, -10, -5, -7, 5, -4, -14, 2, -8, 5, -2, 2, -16, -4, -11, 2, + 4, -1, 2, -1, 0, 5, 4, -12, 3, 9, 7, 13, -3, -7, 2, 6, + -1, 7, -1, -1, 5, -5, 7, -11, -9, -13, 2, 5, 2, -2, -7, 5, + 4, -4, -2, -15, -4, 3, 0, 0, -5, 2, -7, -1, 9, -2, -1, 5, + 1, 1, -4, -5, -4, 6, 8, 7, -5, 4, -7, 4, 0, 1, -6, -5, + -2, 5, -1, 0, 1, 1, 3, 9, -4, -2, -4, -9, -1, 4, -17, 1, + -13, 11, -1, 6, -9, -1, 5, 1, 8, -3, 4, -5, 1, 7, -5, 1, + -3, 5, 3, 4, -7, -11, -7, 1, 5, -13, 11, -11, 1, 3, 6, -9, + 6, -5, -7, 4, -13, 5, -7, 10, 5, 6, -15, -1, 6, 4, 18, -7, + -7, -3, -4, 2, -5, 3, -4, 9, -4, 3, 3, -3, -10, 0, -1, 2, + 5, -3, 7, 3, 2, -6, -11, -2, -1, 4, -5, 4, -5, 0, -5, 5, + -5, -4, 2, 4, 2, 5, -8, -13, -3, 0, -1, -2, 4, 6, 9, 1, + 3, -7, -1, 1, 12, 1, 1, -1, -5, -1, 2, -8, -9, -7, -2, 3, + 10, -6, -7, -12, -7, -4, -5, 6, 0, 10, 5, 7, -4, -2, -8, 10, + 5, 9, 4, -1, -1, -1, -1, -1, -2, -3, 3, 9, -2, 9, -14, -13, + -8, -10, 1, 1, 3, 3, 1, -3, -12, -5, -7, 1, 6, 6, -2, -7, + -3, -3, 2, 2, 4, -9, 14, 8, 11, -3, 5, -11, 1, -1, 5, 3, + 8, 2, 8, -2, -6, -13, -10, 0, 4, 3, 4, -3, -9, 1, -5, -5, + -6, 1, -2, 2, -10, -6, -15, 1, -5, 4, -1, 2, 2, 4, 10, 4, + 2, -13, 0, 4, 8, 17, 2, 5, 4, 2, -6, 5, -5, 0, 8, -2, + -1, -5, -4, -5, -1, -5, -4, -5, 0, 0, 1, -9, -15, -3, -12, 1, + -1, -7, 10, 2, 5, -1, 2, -6, 2, 2, 10, 10, -1, 2, -2, 4, + 5, 0, -6, 12, 5, 3, -1, -8, -8, -4, -4, 3, -11, 0, -1, -1, + 0, -2, -14, -6, -9, 2, 1, 7, -4, 3, -1, 0, -3, 1, 2, 7, + 5, 4, 3, -2, -3, 1, 6, -1, 6, -11, 7, 2, -6, 2, -4, 0, + 2, 3, -7, -9, 3, 0, 4, -6, 0, -21, 0, -5, -1, 0, -1, 1, + -6, -1, -1, 0, -7, 5, 7, -2, 8, -4, -1, 3, 9, -6, 10, -6, + 7, 9, 10, 9, -6, 5, -14, 6, -5, 1, 2, -3, 0, -9, -10, -14, + -2, -3, 6, -8, -15, 3, -9, 0, -3, 0, -6, -1, 3, 9, 10, 3, + 3, -10, 6, 1, 3, -1, 9, 12, 4, 4, -9, -7, -5, 8, 6, 1, + 1, -4, -5, -5, -1, -11, -3, -4, 1, -1, 1, -10, -7, -2, -3, -4, + -3, -6, 11, 5, 3, 2, -8, -5, -2, 3, 9, 13, 5, 4, 4, 0, + -5, -1, -5, 9, 2, 3, -9, -4, 3, -6, 2, 1, -9, 5, -2, 3, + -2, -9, -8, -15, -5, -3, 3, -13, 11, 6, -3, 1, -6, -6, -1, 6, + 4, 6, 7, 1, 5, 0, 8, -6, 7, 2, 6, 2, -5, 0, -3, -1, + 3, -7, -1, -3, 5, 7, 6, -18, -10, -11, -7, -3, 10, -4, 3, -4, + -8, -5, -12, -3, -4, 12, 10, 2, -4, 6, 3, 1, 2, 0, -3, 3, + 7, 7, -5, 2, -4, 1, 3, 11, 2, 3, 4, -2, -7, -5, -17, -11, + 4, -3, 5, -7, -7, -6, -1, -8, -5, -5, 1, 7, 1, 2, -1, -9, + 7, 1, 7, 3, 3, 6, 9, 6, 1, -6, -4, 2, 5, 7, 4, -2, + 1, 3, -11, -1, -16, -2, -6, 1, 3, -8, -15, -11, 4, -1, 9, -2, + -5, 0, 6, 0, -7, 0, -8, 4, 2, 6, 2, 0, 2, 6, 2, -2, + 4, -2, 4, 14, 2, 2, -6, -6, -3, 4, -4, -1, -4, 1, -3, -6, + -1, -13, -1, -2, 7, -8, -7, -10, 0, 4, 3, -8, -3, 1, 4, 6, + 4, 6, -3, 5, 3, 4, 0, 6, 1, 4, 7, -3, -10, 8, -1, 9, + -1, 1, -11, -7, -3, -3, -6, -8, -9, -6, 1, -3, -6, -6, -5, 0, + 0, 2, -3, 0, 6, 4, 3, 2, 7, 4, 11, 14, 5, -1, -5, 1, + -2, 7, 3, 0, 1, 2, -5, -7, -10, -12, -10, -5, -5, -6, -6, -9, + 1, -8, -2, -1, -9, 1, 8, 2, -5, -2, -5, 0, 5, 6, 6, 7, + 8, 10, 2, 0, -3, -1, 2, 13, 3, 0, -6, 0, 1, -3, 0, -12, + -2, 4, -4, 4, -8, -11, -1, -2, 1, -1, 2, -12, 3, -6, 1, -12, + -7, -7, 3, 0, 9, 0, 1, 6, 1, -1, 2, 1, 2, 8, 9, -3, + -1, 0, 7, 3, 8, -1, -4, -1, 1, 3, -9, -1, -17, -3, -2, -4, + -4, -3, -4, -6, -11, -15, -2, -5, 6, 10, 1, 3, -1, -3, 13, 7, + 1, 6, 4, 4, 9, 5, -3, -5, 9, 3, 5, -3, 1, -3, 3, 0, + -7, -5, -7, 0, -5, 0, -1, -15, -11, -4, -5, -10, 2, -7, 5, -4, + 1, -9, 2, 1, 8, 7, 10, 2, 2, 0, 4, 3, -2, 0, 4, 2, + 6, 8, -2, 4, 4, -2, 5, -3, -6, 3, -3, -5, -9, -8, -11, -5, + -1, -1, -5, -7, -5, -8, 0, -3, 5, -7, 11, 1, 0, 2, -3, -1, + 3, 9, 6, -3, 8, 1, 11, 2, 8, -3, -3, 6, 2, 1, 2, -7, + -3, -2, -4, -8, -3, -3, 5, -10, -10, -4, -12, -2, 3, -5, 3, -6, + -8, -2, 5, -3, 0, 1, 4, 8, 4, 5, 0, 4, 8, 1, 7, -3, + 0, 3, 4, 4, -5, -2, -7, -3, 0, 5, -5, -9, 3, -2, -1, -2, + -5, -1, -4, -3, -11, -4, -5, -6, 0, 5, 0, -5, 5, 3, 8, -1, + 3, 3, 2, 5, 7, -4, 3, 1, 3, 10, 2, -7, 1, 0, 6, -4, + -3, -5, -7, -2, -4, -3, -6, 0, -10, 4, -6, -4, -7, -2, 1, -4, + -1, -3, -1, 2, 6, 2, 4, -2, 2, 4, 2, 5, -3, 4, 2, 1, + 0, 8, -3, 2, 5, -5, 3, -5, -2, 5, -5, 3, -1, -4, -3, 4, + -10, -5, -7, -4, -4, 0, 0, -7, -1, -1, 2, 1, -2, -12, -4, -1, + 0, 4, -5, 2, 0, 3, 12, 11, 3, 11, -1, -3, 6, -6, 1, 1, + 7, 6, -7, -1, -7, -4, -4, -7, -8, -1, -6, -6, -2, -3, -5, 0, + -4, 8, -7, 1, 4, -3, 6, 1, -7, 3, 5, 6, 5, 13, 2, 2, + -4, 4, -3, 1, 4, -4, 2, -3, -10, -10, -7, -2, -2, -2, 0, -6, + -2, 1, -3, -4, -2, -5, -2, 7, 1, 6, -5, 6, -1, -1, 2, -3, + 4, 11, 2, -1, 2, -7, -5, 8, 0, 3, -3, -5, -1, -2, 3, 1, + -4, 4, 7, 0, 2, 3, -3, 0, 1, -5, -15, -5, -3, 1, 3, -3, + -11, -4, -7, 1, -2, -1, -1, 0, 1, 1, -5, -1, 3, -2, 7, 1, + -4, -1, 0, 4, 5, 3, 3, -1, 8, 11, 1, 4, 1, -5, 7, -6, + -4, -2, -4, -2, 3, -8, -3, -13, -6, 3, -3, -7, -4, -7, 3, 3, + -3, 2, -1, 1, -4, -2, -2, -5, 1, 11, 9, -2, 6, -3, 7, 7, + 1, 1, -7, 2, -3, 1, 4, -4, -4, 5, 1, 0, -3, -6, 2, -3, + 0, -8, -12, -6, -2, -3, 6, -1, -9, 0, -1, 1, 3, -2, -1, 0, + 1, 6, 0, -3, 5, 1, 6, 1, -1, 4, 1, 7, -3, -1, -1, -4, + 4, 14, -1, -1, 2, -4, -1, -6, -8, -8, -3, -2, 2, -9, -5, -7, + -12, 5, 0, -3, -4, -3, 5, 4, 3, -2, -6, 4, 7, 3, 5, 7, + -3, 8, 0, -5, -1, -1, 11, 10, 3, 4, -8, -3, -3, 1, -3, 0, + -4, -3, 1, -7, -8, -16, -7, -6, -2, 3, -7, -2, 1, -4, 0, -5, + -5, 1, 5, 10, 5, 0, 3, 0, 1, 13, 0, 5, 9, 6, 8, -1, + -4, 0, -3, 6, 4, -4, 0, -3, -15, -2, -12, -15, -3, -6, 2, 1, + -3, -4, -9, -9, -3, -3, -2, 3, 4, 9, 0, 2, 1, 2, 14, 5, + 3, 8, 2, 7, 4, -4, -4, -1, -9, 9, -5, -1, -7, -10, -2, -7, + -4, 0, -5, 2, 5, 1, 0, -5, -5, -1, -1, -3, 4, -8, 5, 3, + -4, 4, -5, -3, 9, 4, 8, 0, 0, 2, 0, -2, 0, -2, -7, 12, + -1, 5, -4, 2, -3, 0, 2, -2, -4, -2, 2, -5, 3, -7, -9, -4, + -3, -2, -6, -6, -2, -6, -1, -7, -8, 1, 3, 6, 10, 4, 5, 0, + 5, 8, 1, 3, 8, 5, 11, 12, -7, 4, 0, -3, 2, -1, -8, -7, + -4, -2, -6, -9, -6, -13, -4, -1, 0, -9, -5, -3, -4, -2, 3, 1, + 1, 9, 4, 2, 6, -1, 3, 6, 2, 0, -3, 3, 2, 6, 3, -1, + -4, 4, 1, 2, 2, -5, -8, -1, -3, -1, -9, -4, 1, -5, 5, -7, + -4, 0, 3, -10, 3, -3, -5, 1, 5, 4, 1, -5, 1, -5, 4, 1, + -6, 0, 5, 8, 8, 1, 6, 0, 3, 4, 2, -3, 1, -3, -3, 3, + -10, -6, -8, -2, -1, -3, -6, -6, -5, -6, -6, -5, 5, -3, 5, 6, + -2, -1, -1, -4, 6, -2, 6, 6, 2, 12, 8, -2, 3, -6, -2, 5, + 4, -3, -2, -5, -4, -7, -6, 1, -5, 2, 2, 0, 1, -7, 0, -4, + -2, -1, -2, -5, 7, -5, -2, -3, -2, -3, 4, 4, 9, 0, 1, 1, + -5, -3, -4, -4, 4, 3, 6, 1, -2, -2, -7, 4, 1, 1, -3, 3, + -1, 2, 0, -7, 0, 0, -1, -3, -2, -1, -5, -2, -3, -8, -5, -5, + -1, 5, 5, 2, 2, -3, 4, 3, 4, 6, 3, -1, 10, -4, -3, -2, + -3, 0, -4, 0, -2, -2, 0, 2, -5, -2, -5, -9, 8, -2, -1, -1, + -3, -3, -2, -6, 2, 1, 2, 9, 0, 1, 4, -5, 2, 4, -6, -1, + 2, -1, 6, 3, 0, -5, -3, -1, 0, 3, -3, 0, -6, -2, -3, -4, + -2, 0, 3, 2, 2, 0, -10, 1, -6, -5, -1, -2, 5, 3, 6, -2, + -6, -1, -3, 2, 4, 1, -1, 0, 1, 1, 3, -1, 5, -1, 7, 6, + 1, -2, 0, -6, -2, -2, -8, -2, -2, -3, -5, -5, -8, -3, -1, 5, + -3, 1, 2, 1, 2, -3, -2, -3, 2, 6, 2, 6, 0, 0, -2, 9, + -1, 3, -2, 3, 0, 0, 0, -6, -6, -1, -5, -7, 1, -3, -6, 2, + -2, -1, -5, -2, 1, 4, 2, 2, -3, -1, 6, -2, 2, 4, -3, 2, + 2, 2, -3, 1, 0, -4, 2, -1, -2, 3, 1, 1, -1, -5, -8, -2, + -5, 0, 1, -6, 3, -4, 2, 3, -6, 3, 0, 2, -2, -1, -4, -2, + -4, 4, 0, -3, 0, -6, -3, 10, -3, 3, 0, 4, 7, 3, 0, 5, + 1, 5, 1, -3, -2, 0, -6, 3, -1, -7, -5, -7, -1, -2, -2, -2, + -3, -2, 2, -2, -1, -3, -3, 2, -2, -6, -3, -3, 4, 3, 2, 0, + -1, 5, 5, 8, 2, 2, -2, 4, 0, 5, -5, -3, -1, -3, -3, -6, + -4, -2, 3, 0, -2, -2, -5, 5, -1, 3, -1, -1, -3, 0, 0, -5, + -4, -3, -2, 5, 0, -4, -4, 1, 2, 6, 0, -3, -1, 2, 3, 7, + -3, 0, -4, -2, 4, 3, 0, 1, 3, -3, 1, -7, -4, 0, 1, 1, + -4, -4, -4, -9, -1, -2, -3, -2, -3, -3, 4, 3, -1, -4, 2, 4, + 4, 3, 2, -1, 0, 9, -1, 4, 2, 7, -1, 6, -2, -2, -5, -1, + -9, -2, -2, -6, -1, -1, 1, -8, -6, -5, -1, -1, 1, -4, -5, 3, + 1, 5, 3, -3, 0, -2, 7, 0, 1, -2, 3, -1, 5, -1, -5, 7, + -1, 3, 2, -5, -6, -2, 4, 2, -1, -3, -1, -1, -1, -1, -2, -4, + 1, -5, 3, -1, -3, -5, 2, 6, -6, -1, -5, -4, 4, -1, -1, -2, + -1, 2, 0, 3, 1, 4, 2, 7, -1, 2, 0, -2, 1, 4, -5, -3, + -7, -2, 0, -1, -1, -3, 0, 0, -2, -6, 2, -4, 2, -4, 1, -7, + -2, -1, 5, 3, -2, -7, -4, 1, 6, 4, 5, 1, 4, 0, 5, 1, + -1, 2, 0, -3, -3, -5, -6, 3, -1, 5, -1, -2, 1, 1, 4, 2, + -6, -3, -4, -3, 2, -2, -8, -3, -6, -4, -2, -11, 0, 0, 1, 6, + -3, -2, 1, 2, 10, 8, 4, -2, -1, 2, 2, 1, -2, 3, 1, 5, + 3, -1, 0, -4, 4, -7, -2, -7, -8, -4, -3, -2, -7, -7, -3, -1, + 5, -2, 0, -7, 2, -1, 3, 1, 4, 6, 5, 8, 3, 2, -1, 3, + -3, 0, 0, -5, -1, 1, 1, -5, -3, -2, 6, 4, 5, -4, -8, -4, + -3, -2, -5, -4, -4, -4, 2, -3, -2, -4, -4, -4, 6, 1, 0, 1, + 3, 3, 5, 2, 1, 0, 6, 2, -1, 1, -3, -3, 2, -1, 0, 1, + 3, 1, 4, -4, -5, -10, -8, 1, -6, -3, -4, -6, -3, 0, 2, -3, + -1, 2, 0, 8, 1, 4, 4, 3, 6, 3, 1, 3, 5, 1, 2, -4, + -7, -3, -3, 3, 0, -7, -5, 0, -3, -1, -2, -4, 0, -5, 1, -6, + -1, -5, -3, 1, 4, -1, -3, 3, 3, 5, -1, -2, 2, -1, 2, 1, + -1, -5, 5, 1, 2, 2, -4, 0, -1, 3, 0, -2, -1, 2, 1, 5, + 4, -3, -5, 0, -2, -2, -6, -3, -3, -4, -1, -5, -4, -1, -2, 0, + 2, -2, -6, -3, 1, 1, 1, -1, 3, 4, 7, 2, 3, 4, -1, 7, + 2, 3, 1, -1, 1, -2, 0, -4, -5, -6, 0, -2, -7, -2, -5, -5, + 1, -4, -5, -5, 3, -1, 1, 2, -2, 0, 1, 4, 1, -4, 2, 2, + 0, 9, 2, 0, 4, 3, 1, 2, -4, -2, -4, 3, -4, -2, -6, 0, + -1, 5, 2, -4, 0, -4, -4, -1, -5, -4, -7, -3, 1, 0, -2, -1, + -5, 1, 0, -1, 0, 2, 4, 0, 3, -2, 1, 2, 6, 0, 1, 5, + 0, 3, 3, 2, -5, -2, 1, 5, 2, -2, -5, -9, 0, -6, -1, -6, + -7, -5, -4, 0, -2, -5, -3, 2, -2, 3, 2, 0, 9, 2, 0, 4, + -3, 4, 5, 8, 6, -2, -4, -1, 0, -2, -2, 1, -5, 2, -5, -1, + -4, -3, -4, 0, -2, -7, -3, -1, 0, -1, 0, -6, 3, -2, 5, 2, + -1, -2, 1, 0, 1, -1, -3, 2, 3, 1, 2, -4, -3, -1, 5, 5, + 3, -4, 0, 1, 2, 5, -5, 1, -5, 2, -2, 2, -4, -3, 0, -4, + -3, -9, -7, -4, 2, -2, 1, -6, -3, 0, 1, 5, 1, -5, 0, 0, + 2, 1, 2, 0, 6, 4, 6, 3, 2, 3, 1, -2, -2, -9, -4, -1, + 4, 0, -1, -5, -8, -5, -4, 0, -4, -1, -3, 0, 0, -4, -3, -1, + 1, 2, 0, -2, -3, 1, 3, 2, 3, 3, 0, 8, 2, 7, -1, 3, + -2, 4, 0, 0, 1, -4, 5, -1, -3, -3, -6, -4, 2, 1, -5, -4, + -7, -4, -4, -7, -2, -10, 1, 0, 1, -3, 4, -2, 5, 2, 1, -3, + -1, 2, 8, 4, 5, 0, 1, 4, 5, 2, 2, -2, 1, -4, 0, -3, + -3, -1, 0, 2, -4, -4, -5, -1, -7, 0, -4, -5, -1, -3, 2, -2, + 0, 3, 0, 2, 0, 1, -2, 2, 4, -1, 0, -3, -1, 1, 3, 2, + -3, 2, 0, 2, 2, -1, 2, -2, -3, 0, 0, -2, 2, -2, 4, -3, + -6, -7, -6, 2, -1, -4, -1, -7, -1, -3, 3, -1, 0, -2, 2, 2, + -3, 3, -4, 5, 7, 6, 3, 1, -1, 6, 2, 1, 0, -1, -1, 1, + -3, 1, -3, -5, -5, -3, -8, -3, -11, -1, -1, 0, -8, -2, -5, 3, + 4, 0, 1, -2, 2, 0, 6, 4, 1, 4, 1, 5, 0, 0, 1, 2, + 5, 0, 1, -10, 0, -5, 2, 0, -6, -6, -2, -2, 2, -3, 0, -4, + 2, -4, 1, -3, -4, 1, -2, 2, 1, -2, 0, 3, 2, -3, -1, -5, + -3, 4, 2, 3, -1, 4, 1, 5, -1, 2, -3, 2, -3, 0, -3, -2, + 1, 1, 5, 1, -2, -5, 1, -1, -4, -3, -7, 0, -5, -4, -4, 0, + -4, 4, 0, -1, 1, -8, 1, 0, 9, 1, 2, -2, 5, 5, 1, 6, + -1, 6, 3, 1, 1, -2, -2, -4, -3, -2, -3, -7, -4, -4, -1, -3, + -8, -1, -8, 4, -5, 0, -3, 1, 0, 4, -1, 0, 1, 3, 3, 4, + -4, 6, -2, 2, 5, 4, -3, 4, -3, 5, 0, -4, 0, 0, -1, 0, + -4, -4, 3, -1, -2, -4, -8, -9, -5, -4, 4, -4, 1, -4, 1, 1, + -1, -1, -1, 3, 2, 3, 0, 1, 2, 1, 5, 3, 1, 0, 5, 3, + 3, 0, -5, -4, -2, 5, 0, -2, -5, -2, -6, -2, -5, -8, -2, 1, + -1, -3, -7, -8, -6, 0, 4, 7, -2, 7, -1, 7, 3, 2, -5, 0, + 2, 0, 1, -3, 2, 2, 3, 3, -3, 0, -2, 3, -1, -1, -4, -6, + -2, -3, 4, -4, 0, -4, 6, -2, -6, -2, -7, 1, 2, -1, -3, -2, + -2, 3, -1, 0, -3, -1, 4, 7, 4, 0, 2, -1, 0, 6, -2, 1, + 1, 5, 4, 1, -3, -3, -2, 2, 2, 1, -6, -6, -3, -4, -2, -6, + -5, -4, -5, -2, -8, -8, -3, 0, 4, 0, 1, -1, 2, 5, 4, 2, + 2, 3, 3, 4, 10, 0, 2, 0, 3, 1, 1, 0, -3, 1, -3, 1, + -7, 0, 1, -2, 1, -6, -4, -10, -1, -4, -2, -2, -3, 2, -4, 1, + -5, -4, -4, 2, 1, 1, -4, -1, 3, 1, 6, 2, -2, -2, 3, 3, + 2, 7, -5, 5, 0, 8, 1, -1, 2, 3, -1, -6, 0, -10, 3, -1, + -1, -5, -6, -8, -2, 0, -3, -5, -8, -4, 2, -3, -1, -2, 0, -1, + 7, -1, 3, 2, 4, 7, 3, 4, -1, 5, 1, 9, 1, -2, -1, -1, + 1, -3, -2, -6, -7, 1, -3, -1, -9, -4, -6, 0, 2, -3, -2, -4, + -3, 0, -4, -1, -4, 0, 1, 6, -1, 1, -1, 3, 5, -1, 3, 4, + 5, 7, 4, -2, 0, -2, 0, 3, 1, -1, -8, -2, -1, -2, -5, -1, + -2, -2, 2, -5, -7, -9, -2, -3, -2, 1, -5, 4, -4, 5, -1, -1, + -3, 2, 3, 7, 3, -1, 3, 4, -1, 5, -4, 0, 4, 4, 3, 4, + -9, 1, -5, 2, -2, -2, -3, -7, -1, -2, -2, -5, -3, -1, 1, -2, + -1, -4, -4, 1, -1, -7, 0, -1, 2, 5, 4, -4, -5, -4, 0, 2, + 1, -1, 3, 5, 4, 0, 0, -1, 3, 8, 3, 3, -4, 0, 1, 0, + -2, -6, -2, -4, 3, -2, -3, -5, -6, -3, -1, -1, -7, 0, 0, 3, + -5, -4, -11, 0, 0, 3, 3, 1, 1, 1, 4, 6, 1, 1, 2, 9, + 3, 3, -4, -4, -3, 2, -1, -6, 1, -5, 2, 0, -1, -8, -5, -6, + 1, 0, -2, -1, -2, -1, 2, 0, -9, 0, 5, 4, 7, -3, -3, 3, + 4, 2, 4, 0, -1, 3, 1, 5, -5, -6, -7, 0, 3, 0, -2, -4, + 3, 3, -3, -4, -7, -2, 4, 1, -1, -4, -1, -6, -2, 3, -2, -3, + 1, 4, 1, -1, -4, -3, 3, 4, 5, -2, 2, -3, 4, 0, 3, -3, + -3, 0, 3, 1, -2, -1, -3, 2, 4, -2, -2, -3, -1, -1, 3, -11, + -2, -8, 5, -1, 3, -5, -2, 2, -1, 3, -3, 0, -1, -1, 5, -2, + 0, -2, 3, 2, 3, -2, -6, -3, 2, 4, -6, 5, -6, 1, 2, 3, + -6, 2, -3, -4, 3, -9, 2, -6, 3, 4, 2, -9, -1, 1, 2, 8, + -3, -4, -1, -2, 2, -2, 2, -3, 3, -1, 1, 2, -1, -6, 1, 2, + 2, 1, -2, 2, 3, 1, -3, -6, -3, 0, 1, -3, 0, -3, -1, -4, + 2, -4, -3, -1, 4, 0, 5, -6, -7, -1, 0, 0, -3, -1, 2, 4, + 0, 3, -4, -1, 1, 7, 4, 2, -1, -4, 0, 2, -4, -5, -5, -1, + 1, 4, -5, -4, -6, -3, -2, -3, 2, -2, 5, 2, 3, -4, -2, -5, + 6, 3, 4, 2, -3, 1, 0, 0, 1, -3, -1, 1, 7, 0, 6, -6, + -7, -2, -7, 0, -1, 0, 2, 1, -2, -7, -2, -5, 0, 2, 0, -3, + -5, -1, -3, 0, -1, 0, -6, 8, 4, 5, -1, 1, -4, 1, 1, 4, + 2, 5, 3, 6, 0, -2, -9, -4, -1, 0, 0, 1, -1, -4, -1, -5, + -5, -5, 0, 0, 1, -6, -5, -9, 0, -3, 0, -2, 0, 0, 3, 4, + 2, 1, -7, 1, 3, 4, 9, 1, 4, 4, 2, -4, 2, -2, 1, 5, + -2, 0, -3, -4, -3, -2, -4, -4, -4, 1, -1, 2, -6, -8, -3, -8, + -1, -2, -4, 5, 2, 3, -1, 0, -4, 2, -1, 5, 5, -1, 3, 0, + 3, 3, 0, -4, 9, 4, 2, -1, -6, -4, -2, -2, 2, -7, 0, 0, + -2, -2, -2, -10, -4, -7, 0, -2, 2, -2, 2, 1, 0, -3, 0, 1, + 6, 3, 2, 0, 0, -1, 2, 3, -1, 4, -5, 6, 2, -3, 0, -3, + 0, 1, 0, -5, -6, 1, 0, 1, -5, -2, -14, 0, -4, -1, -1, -1, + 1, -3, 0, -2, -1, -4, 4, 5, -1, 5, -1, 3, 3, 5, -3, 5, + -3, 5, 5, 6, 4, -6, 2, -9, 4, -4, 0, 1, -2, -1, -8, -6, + -11, -2, -3, 3, -6, -8, 3, -5, 1, -3, 1, -3, 1, 3, 5, 6, + 2, 1, -6, 4, -1, 1, 0, 7, 7, 2, 3, -6, -4, -4, 3, 3, + 0, 1, -1, -2, -4, 0, -8, -2, -3, 1, -2, 1, -5, -2, -1, -3, + -3, -4, -3, 7, 4, 1, -1, -6, -5, -3, 2, 5, 8, 3, 3, 2, + 1, -4, -1, -2, 6, 3, 2, -4, -1, 1, -5, -1, -1, -5, 2, -2, + 1, -2, -7, -5, -11, -4, -3, 3, -8, 8, 4, -2, -2, -4, -4, -1, + 4, 3, 5, 5, 2, 4, -1, 6, -3, 6, 2, 3, 0, -4, 0, -2, + -2, 0, -5, -2, -1, 4, 3, 1, -13, -8, -8, -5, -3, 7, -2, 3, + -2, -5, -3, -8, -2, -3, 8, 6, 1, -2, 5, 3, 1, 2, 0, -1, + 2, 4, 3, -5, 1, -3, 0, 1, 7, 1, 2, 3, -1, -4, -4, -10, + -7, 3, 0, 2, -5, -5, -4, -1, -7, -3, -3, 1, 3, 0, 0, -1, + -6, 6, 1, 4, 1, 2, 5, 6, 4, -1, -4, -3, 1, 2, 5, 2, + -1, 1, 3, -8, -1, -10, -2, -5, 0, -1, -6, -10, -7, 2, -2, 6, + -1, -2, 1, 4, -1, -5, -1, -5, 4, 1, 4, 2, 1, 3, 4, 0, + -2, 1, -1, 3, 8, 2, 1, -4, -3, -3, 3, -3, -1, -4, 0, -4, + -6, -2, -8, 1, -2, 5, -6, -5, -6, 0, 3, 1, -6, -3, 1, 2, + 4, 2, 4, -2, 3, 3, 3, 1, 5, 1, 2, 3, -2, -6, 6, -1, + 6, -2, 1, -7, -5, -2, -3, -6, -6, -6, -4, 0, -2, -4, -4, -3, + 0, -1, 1, -3, -1, 3, 1, 1, 0, 6, 4, 8, 10, 5, 0, -3, + 1, -2, 5, 2, 1, 1, 1, -4, -6, -8, -8, -8, -5, -4, -5, -4, + -5, 0, -5, -3, 0, -7, 0, 4, 1, -4, -1, -4, -2, 4, 4, 5, + 6, 6, 7, 0, 0, -1, 0, 2, 9, 2, 1, -3, 0, 1, -3, 1, + -9, -1, 3, -4, 3, -6, -7, -2, -1, -1, -1, 1, -9, 2, -5, 1, + -8, -6, -6, 1, -1, 6, 0, 2, 5, 2, 0, 2, 1, 2, 6, 5, + -2, -1, 0, 4, 1, 6, 0, -2, 1, 0, 3, -7, -1, -13, -4, -3, + -3, -3, -2, -3, -5, -9, -11, -2, -3, 4, 7, -1, 2, 0, -2, 8, + 5, 1, 4, 3, 2, 7, 3, -2, -4, 7, 2, 3, -2, 1, -1, 2, + 0, -5, -4, -4, 0, -4, 0, -1, -10, -9, -3, -5, -8, 1, -5, 3, + -3, 0, -7, 1, 0, 5, 4, 7, 1, 1, 0, 2, 2, -2, -1, 2, + 1, 4, 6, -1, 4, 3, -1, 4, -2, -3, 3, -1, -2, -6, -6, -7, + -3, -1, 0, -4, -6, -5, -6, 0, -3, 3, -5, 7, 0, -1, 1, -3, + -1, 1, 6, 3, -3, 7, 1, 10, 1, 6, -1, -2, 5, 2, 1, 1, + -4, -2, 0, -3, -7, -2, -4, 4, -8, -8, -4, -10, -2, 2, -4, 1, + -5, -7, -1, 3, -1, 1, 1, 4, 6, 2, 2, 0, 4, 7, 0, 5, + -2, 0, 3, 3, 3, -3, -1, -5, -2, 0, 3, -4, -6, 2, -1, 0, + -2, -4, 0, -4, -3, -9, -3, -4, -4, 0, 3, -1, -4, 3, 1, 5, + -2, 1, 2, 2, 4, 5, -3, 2, 1, 3, 7, 1, -5, 1, 0, 5, + -3, -2, -3, -4, 0, -3, -2, -5, 0, -8, 3, -6, -4, -6, -2, 2, + -4, -2, -3, -2, 1, 4, 2, 3, -2, 2, 4, 1, 4, -2, 3, 2, + 1, 1, 7, -1, 2, 4, -4, 2, -4, -2, 5, -4, 3, -1, -3, -2, + 3, -8, -4, -6, -3, -3, -1, 0, -6, -1, 0, 1, 1, -2, -10, -3, + -1, 0, 2, -5, 1, 1, 2, 10, 8, 2, 8, -1, -2, 4, -5, 2, + 2, 7, 6, -6, -1, -5, -4, -3, -6, -7, 0, -5, -5, -1, -2, -5, + 0, -4, 6, -6, 0, 3, -3, 4, 0, -6, 2, 5, 5, 4, 10, 0, + 2, -3, 3, -2, 0, 3, -3, 2, -3, -8, -8, -5, -1, -1, -1, 0, + -5, -2, 0, -3, -4, -1, -5, -2, 5, 0, 5, -4, 4, -1, -1, 1, + -3, 3, 9, 2, -1, 1, -6, -3, 7, 1, 3, -2, -4, 0, -1, 3, + 1, -3, 4, 6, 0, 1, 2, -3, 0, 0, -5, -13, -4, -2, 1, 2, + -3, -10, -4, -7, 1, -2, -2, -1, 0, 1, 1, -4, -1, 2, -2, 7, + 1, -3, 0, 0, 4, 5, 2, 2, -1, 6, 9, 1, 3, 1, -5, 5, + -6, -5, -2, -4, -2, 2, -7, -4, -11, -5, 3, -3, -6, -4, -6, 3, + 3, -3, 2, 0, 1, -3, -1, -2, -4, 1, 10, 8, -2, 4, -3, 6, + 6, 1, 0, -7, 2, -2, 1, 3, -4, -4, 4, 1, 0, -2, -5, 2, + -2, 0, -7, -11, -5, -2, -2, 5, -1, -8, -1, -1, 1, 2, -2, -1, + 1, 1, 5, 0, -3, 5, 1, 6, 1, -1, 3, 1, 6, -3, -1, -1, + -3, 4, 12, -1, -1, 2, -4, -1, -6, -8, -7, -3, -2, 1, -9, -5, + -6, -10, 5, 1, -2, -3, -2, 5, 4, 3, -1, -5, 4, 6, 3, 4, + 6, -2, 7, 0, -4, -1, -1, 9, 8, 2, 2, -8, -3, -3, 0, -2, + 0, -4, -2, 0, -6, -7, -14, -6, -5, -1, 3, -6, -2, 1, -3, 0, + -4, -5, 1, 5, 9, 4, 0, 3, 0, 1, 12, 0, 4, 8, 5, 7, + -1, -4, 0, -3, 5, 4, -4, 0, -3, -13, -2, -10, -14, -3, -5, 2, + 1, -3, -4, -8, -8, -3, -2, -2, 3, 4, 8, 0, 2, 1, 2, 12, + 5, 3, 8, 2, 6, 3, -4, -4, -2, -8, 8, -5, -2, -6, -10, -2, + -6, -4, 0, -4, 2, 5, 1, 0, -4, -4, -1, -1, -3, 4, -7, 4, + 3, -3, 4, -4, -3, 8, 4, 7, 0, 0, 2, -1, -2, -1, -2, -7, + 11, -1, 5, -4, 2, -2, 0, 2, -2, -4, -2, 1, -5, 3, -6, -9, + -3, -3, -2, -5, -5, -2, -6, -2, -7, -8, 1, 3, 5, 9, 4, 4, + 0, 5, 8, 1, 3, 7, 5, 10, 11, -7, 3, 0, -3, 1, -1, -7, + -7, -3, -2, -6, -9, -6, -12, -4, -1, 0, -8, -5, -3, -3, -2, 3, + 1, 1, 9, 4, 2, 5, -1, 2, 6, 2, 0, -3, 2, 2, 5, 2, + -1, -4, 4, 1, 1, 2, -5, -8, -1, -3, -1, -9, -4, 1, -4, 5, + -6, -4, 0, 3, -9, 3, -3, -5, 1, 4, 4, 1, -4, 1, -4, 4, + 1, -6, 0, 5, 7, 8, 1, 6, 0, 3, 4, 2, -3, 1, -3, -3, + 3, -9, -6, -7, -2, -1, -3, -5, -6, -5, -5, -6, -5, 4, -3, 5, + 5, -2, -1, -1, -3, 6, -2, 5, 6, 2, 11, 8, -1, 3, -6, -2, + 5, 4, -3, -3, -5, -3, -7, -5, 0, -5, 2, 1, 0, 1, -7, 0, + -3, -2, -1, -2, -5, 7, -4, -2, -3, -2, -3, 4, 4, 9, 0, 1, + 1, -5, -3, -4, -4, 4, 3, 6, 0, -2, -2, -6, 4, 1, 1, -3, + 3, -1, 2, 0, -7, 0, 0, -1, -3, -2, -1, -5, -2, -3, -8, -5, + -5, -1, 5, 5, 2, 2, -3, 4, 3, 3, 6, 3, -1, 10, -4, -3, + -2, -3, 0, -4, 0, -2, -2, 0, 1, -4, -2, -5, -9, 8, -2, -1, + -1, -3, -3, -2, -6, 2, 1, 2, 9, 0, 1, 3, -4, 2, 4, -6, + -1, 2, -1, 6, 3, 0, -5, -3, -1, 0, 3, -3, 0, -6, -2, -3, + -4, -2, 0, 3, 2, 2, 0, -10, 1, -6, -5, -1, -2, 5, 3, 6, + -2, -6, -1, -3, 2, -1, 0, 0, -1, 0, 0, 0, 1, -2, 2, -2, + -5, -1, -2, 16, 12, -18, -10, 3, -14, -10, 16, -1, -3, -16, 28, 3, + -1, -1, 12, -5, -6, 6, 7, -7, -18, -28, 11, 0, 6, -2, 26, -21, + -10, -1, 24, -3, 20, -19, 15, -14, -3, -3, 15, -35, -2, 6, -14, 30, + 6, -36, -8, 17, 0, -27, 26, 16, -38, 8, -14, 57, 3, -31, -14, 34, + -20, 33, 2, -6, -7, -28, 20, -24, 8, 13, 8, -39, 17, 40, -42, -11, + 13, -46, 1, 28, -22, 11, -3, -14, 5, 20, -12, -4, 49, -22, -24, 39, + -11, -1, -9, 37, -30, 13, 34, 4, -11, -25, 18, -22, 1, 29, -17, -3, + -26, -16, -21, 12, -18, 7, -17, -6, 51, 0, -21, 10, 24, -45, 8, 14, + 31, -10, -37, 6, 0, 24, 3, -18, -13, 14, 11, 0, 7, -1, -38, -29, + -21, 32, -30, 22, -26, 14, -40, 55, -36, 30, -12, 8, 31, -16, 19, -15, + 23, -48, 36, 1, 63, 3, 24, 0, -3, 14, 26, -21, 15, 47, -21, -80, + 14, -4, -25, -33, 11, 25, -35, -44, 13, -2, -48, -11, -23, -7, 27, -4, + -15, -22, 5, 26, -36, 50, 23, 11, -23, -14, 19, 32, 14, 38, -66, 56, + -11, 26, 18, -12, 17, -30, -6, -54, 22, 77, -62, -12, -16, 34, -25, 2, + 14, -62, 12, 20, -22, -50, 58, -29, -58, 4, 28, 30, 13, 25, -78, 38, + 45, -19, -7, 52, -61, 27, 17, -21, -4, 6, 37, -24, -38, 73, 8, -16, + 21, -2, -15, -19, -19, 18, 3, 7, -48, -10, -10, 10, 4, 13, -13, -4, + 0, 46, -12, 6, -18, -25, 4, 14, 27, -22, -37, 14, -6, -17, 55, 40, + -111, 63, 9, -38, -16, 46, -35, 4, 0, -10, -8, -12, 58, -69, 1, 66, + -38, 21, -33, -6, 10, 0, 10, -11, 18, -16, 32, -7, -10, -25, 65, -42, + 42, -62, 18, -3, -2, -8, 21, 4, -71, 13, 40, -3, 18, -19, -29, 15, + -66, 60, -50, -6, 67, -80, 17, 66, -21, -20, -15, 68, -16, 72, -4, -23, + 4, 53, -8, 8, -4, 0, 27, -26, -22, 25, -31, 7, -39, -18, 27, -43, + -25, -33, -6, 17, -16, 0, -55, 6, 26, -3, -67, 7, 60, -83, 25, 15, + 45, -8, 51, -55, 28, 42, 42, -17, 37, -6, 17, 8, 11, -1, 59, -7, + -45, 14, -41, 107, -49, -50, -25, 63, -58, -27, -57, 19, 13, -13, -27, 19, + -42, 63, -113, -1, 44, 8, 1, -10, -33, 0, 55, -41, 15, 0, 76, -17, + -39, 60, -20, 28, 54, -93, 15, 83, -30, 4, -56, 49, -58, 30, -28, 2, + 54, -64, 83, -128, 86, 24, -40, -27, -66, 51, 11, -51, 59, 6, 20, -58, + -24, 78, -7, -23, -27, 1, -3, -24, 10, -6, -16, 34, 39, -37, -17, 26, + 52, -69, -7, 11, 24, -62, 38, -13, 41, 5, -2, -5, -12, 15, 77, -49, + -10, 74, -12, -11, -38, 32, -24, 25, -6, 19, -24, -2, -38, 63, -91, 64, + -27, -11, -56, -43, 27, -41, -55, -15, 1, -4, 27, 8, 37, -57, 3, 28, + -11, -4, 46, -39, 3, 12, 100, -33, 39, 17, 6, 49, 5, 38, -12, 10, + 21, -35, 23, -6, -36, 10, -9, 3, -1, 13, -65, -40, 36, -25, -28, 5, + -37, -20, -14, 31, -16, -32, -16, 4, 15, -11, 26, -16, 29, -42, 46, 7, + 39, -1, -5, -9, 33, -31, 35, -33, -7, 17, 56, -24, 22, 14, -22, -34, + 44, 16, 11, -46, 43, -48, -27, 43, 36, -45, 21, 11, 0, -98, -22, 87, + -126, 52, -45, 34, -28, -17, -31, 23, -38, 23, 25, -11, 25, -63, 21, 13, + 19, 47, 28, -23, 20, 21, -5, -14, 112, -30, -67, 37, 43, -12, -57, 34, + -9, -29, 52, -19, 14, -51, 0, 26, -69, 3, -18, -24, -34, 31, -15, -33, + -36, 10, -20, -38, 63, 0, 44, -50, 72, 25, -16, -6, 6, 15, 23, 31, + 3, -20, -9, 19, 63, 17, -18, -5, -12, -87, 31, 26, -37, -29, 49, -42, + -15, 14, 11, -16, -31, 46, -19, -13, -37, 59, -91, 47, 4, -11, -26, 39, + -29, -24, 48, 10, 39, -11, 45, -51, -1, -24, 47, -19, 39, -34, -29, -17, + 1, 56, -25, -16, -13, 0, 48, -71, 49, 2, -2, -45, -10, 59, -17, -25, + 9, 9, 44, 42, -32, -23, -49, 46, -11, -50, 76, -43, -45, -1, 41, -8, + 2, 71, -36, -61, 35, 21, -13, -36, 44, -45, 26, -45, -21, 28, -37, 39, + -29, 15, 4, -5, 24, -7, 7, 3, 68, -80, 26, 24, -22, 8, 26, 28, + 10, -26, -3, 16, -51, 85, -8, -14, -54, 39, -28, -9, -25, 46, -39, -20, + 34, 11, -25, -7, -12, -41, 12, -17, -5, -43, -8, 0, 18, 13, 9, 28, + -40, 34, 0, 13, 40, -20, 5, 22, -25, -13, 51, 9, -34, 43, -16, -18, + 2, 35, -4, -28, 14, -37, 6, -8, 31, -49, 9, -31, 61, -55, 35, -46, + -37, -12, 32, 74, -59, -30, -21, 5, 38, 3, 48, -35, -42, 2, 29, 81, + -8, -37, 24, 42, -31, 18, -11, -21, -67, 98, -18, 11, -26, -14, -76, 11, + 71, -70, 30, -52, 37, -45, 61, 6, -33, -44, 58, 24, -16, -51, 49, -28, + 51, -6, -15, 46, 10, -24, 36, -4, 6, -30, 46, -66, 54, 27, -16, -34, + -23, 90, -61, -49, 22, -3, -22, 17, -35, -11, -59, 23, 2, -25, 69, -24, + -26, -28, 37, 12, 11, -63, 27, 18, 3, 34, -25, 9, -14, 29, 4, 24, + 21, -77, 12, 14, 37, 1, 45, -63, 1, 49, -14, -23, -7, -4, -42, 48, + -57, 18, -36, 17, 15, -37, 47, 1, -41, -14, 11, 49, -32, 32, -36, -19, + 21, -11, 39, -31, 43, 0, -24, 15, 6, 9, -46, 5, 21, -23, 2, -28, + -15, 59, -13, -29, 50, -7, -45, -12, 23, -1, 27, 6, -17, 7, -4, -3, + -3, 53, -10, 17, -52, 19, 24, -8, -7, 19, -51, -30, 55, -22, -22, 29, + -38, -25, 39, 3, 34, -84, 26, -37, 42, 15, 4, -4, -16, -33, 29, 17, + 43, -93, 24, -6, -20, -14, 107, -29, -36, 69, -21, 10, -7, 74, -67, 38, + -23, -8, 27, -35, -49, 29, -8, -4, 7, -8, 5, -38, -28, -33, 22, 70, + -37, -10, -56, 26, 5, 7, 59, -21, -58, 10, -2, 6, 49, -16, -9, -38, + 60, 13, 43, -43, 23, -14, -9, 38, 17, -38, -15, 29, 6, -5, -11, -3, + -4, -65, 45, -13, 26, -13, -4, -5, -38, 48, 0, 4, -40, 40, -48, 23, + 21, 23, -42, 5, -17, 13, -9, 12, -3, 5, -25, 34, -24, -3, -18, 16, + -44, 13, 27, -30, 44, -54, 6, -18, -3, 4, 21, -25, -13, 22, -20, -12, + 37, -10, -10, 5, 24, -17, 23, 9, 0, 4, 3, 12, 26, -27, 17, 9, + -41, 69, -1, 15, -37, 15, -6, 0, -1, 3, -13, -23, -18, 27, -5, 21, + -16, -41, -2, 20, 13, -27, 6, -21, 8, 6, 0, 6, -5, -21, -22, 73, + -40, 4, 6, 21, -8, -5, 29, -47, -1, 1, 19, 3, -10, -1, 2, -48, + -11, 45, -27, 11, -33, -21, 21, 7, 12, -22, 21, -40, 13, 27, -20, 37, + 5, -18, -18, 35, 40, -11, 20, -25, 10, -4, 33, 12, -29, 9, -20, -30, + 34, 24, -9, -10, -24, -16, 8, 22, 6, -58, -5, -13, 18, 5, -43, 10, + -16, -25, 13, 70, -25, -7, -25, -19, 16, 58, -46, -5, 6, -5, 40, -24, + 22, 50, -73, -7, 7, 32, 39, -27, -23, -23, 56, -35, 21, 17, -40, 40, + -52, 4, 0, 49, -29, -42, 24, 9, 31, 2, -46, 0, -9, -5, 9, -31, + 64, -5, -45, -26, 42, -4, -34, -8, -3, 32, -15, -8, 22, -24, 13, -31, + -2, 31, 10, -10, -18, 8, 24, 20, -29, 2, 14, 23, 25, -4, -19, 20, + -25, -5, -3, 23, -8, 52, -42, -17, -7, 29, -26, 2, -19, 55, -50, -28, + 1, -10, -7, 7, -41, 16, 21, 1, -20, 0, 16, -19, 14, -39, 86, -17, + -34, -64, 73, 0, 20, -28, 30, -22, 9, 58, -4, -8, -18, -20, 31, -21, + 1, 26, -49, 5, 41, -25, -13, -6, -7, 6, 10, 42, -30, -26, -43, 11, + 44, -54, 31, -10, -11, -17, 25, 32, -43, 64, -23, 3, -37, 33, -30, -4, + -35, 47, -29, 9, 23, -34, -5, 64, -37, 32, -11, -44, 21, 25, -19, 8, + 6, -25, 34, 2, -18, -23, 38, 20, 7, 21, 1, -32, -37, 50, -9, -25, + 34, -61, 55, -32, 7, -48, 20, 13, 0, -35, 17, 9, -42, -28, 14, 42, + -33, -25, -5, 21, 41, -60, 32, -7, 38, -9, -3, 20, -4, 29, -69, 62, + -16, 35, -64, 45, 10, 5, -1, -18, -18, -1, 5, 32, 0, -21, -12, -23, + 29, -15, 13, -39, -3, -3, 6, 35, -24, -23, -7, -2, 44, -10, -37, 25, + 25, -25, -23, 7, 40, 4, -40, -18, 21, -2, -3, 1, -16, 45, -26, -2, + -16, 18, 41, -64, 8, -26, 40, 5, -32, 8, 18, -1, 15, -1, 9, 2, + 2, -13, -12, 35, -9, 13, -62, -29, 72, 18, 7, -30, 26, -7, -29, 39, + -38, 31, -56, -25, -3, 17, 2, -3, -46, 35, 6, 27, -39, -3, 3, 31, + -25, -19, -2, 38, 26, -77, 22, 18, 40, 3, -22, 65, -48, 33, -16, -37, + 78, -34, 1, -52, 23, 16, 1, -37, 17, 12, 1, -4, 8, -27, -1, -11, + -18, 27, -23, -10, -11, -19, -6, -7, 51, -74, 16, 20, 17, -14, 7, 7, + -13, -8, -5, -11, 39, 21, -5, -44, 31, 64, -38, -18, 20, 40, -4, -10, + 10, -23, 23, -6, -20, 11, 9, 10, 6, -23, -11, 1, 17, -56, 56, -40, + 0, -17, -60, 84, -80, 16, -13, 4, -25, 12, 17, -42, -26, 54, -29, 12, + -5, 37, 16, -62, 94, -5, -2, -2, -2, -9, 5, 51, -25, -5, -11, 5, + 16, -14, -9, 43, -44, -8, 27, 2, -1, 9, -18, -6, 5, 23, -46, -9, + 13, 16, -10, -10, -23, 59, -47, -14, 23, 29, -15, -14, -30, 21, -21, 0, + 14, -3, 25, -16, -35, -2, -8, 32, -19, 22, -23, -37, 30, -33, -19, 11, + 12, -32, 47, -4, 27, 11, 9, -35, 39, 29, -18, -2, -11, 27, -2, 13, + 0, 18, -26, 15, -25, 26, -4, 21, -29, -33, 18, -8, -31, -5, 21, -1, + -38, -28, 41, -18, -4, -22, 47, -12, -44, 55, -79, -5, 19, -10, 25, 4, + 21, 15, -28, 13, -6, 45, -24, 25, 10, -26, 4, 2, 31, 3, -7, 3, + 5, -23, 51, -9, -32, -5, 35, -32, -21, -20, 35, -40, -10, 20, -8, 7, + -5, -38, -1, -24, 39, -26, 20, -16, -9, -27, 25, 34, -32, 1, 12, -13, + 3, 37, 13, 3, -31, 27, 30, 5, -15, -21, 2, 10, -13, 16, 36, -9, + -59, 41, -10, 61, -60, -35, -11, 7, 5, -28, 30, 5, -23, -66, 34, 50, + -26, -19, -10, 11, 8, 8, -35, -5, -11, 56, -24, 10, 35, 16, -10, -19, + 30, 4, -11, 23, 0, -6, 6, 36, -15, 0, 15, -14, -26, -8, -5, 15, + -31, -45, 42, -30, 0, -9, 6, -22, 9, -22, 7, -8, 15, -19, -3, -13, + 29, -14, 9, -16, 3, -5, -10, 63, 0, 4, 4, 20, 16, -21, 18, 31, + -24, -19, 31, 54, -39, -7, -16, 5, -3, 0, -29, 16, 6, -29, -25, -52, + 49, -9, -66, -3, 50, -3, -2, -14, 4, -8, 33, -40, 2, 15, -6, -17, + -4, 10, 48, -16, 14, -9, 27, 10, 2, 2, 40, -35, 5, -10, 7, 28, + 1, 4, -30, -4, 0, 1, -14, -13, -11, 26, -17, 13, -44, -9, -6, -23, + 17, 11, 11, -21, -11, 0, 9, 8, 8, -30, 29, 10, -26, -12, 15, 17, + 4, -26, 14, 19, 20, -9, -24, 39, 23, -10, -35, 8, -6, 18, -25, 15, + -17, 41, -48, -31, -5, 47, -14, -20, -4, -7, 5, -19, 3, 21, 12, -23, + 15, -24, 8, 3, -25, 2, 28, 14, 21, 25, -72, 15, 26, -6, 45, -27, + 29, -30, -17, 23, 6, -2, 27, -46, 13, 9, 15, -57, 27, 1, -18, 1, + -11, -2, -20, -16, -23, 24, 18, -21, -5, -15, -14, 26, -12, 30, -48, 37, + -24, -3, 23, 9, -5, 9, 8, -43, 23, 26, 6, 28, -29, 30, -8, -12, + 25, -18, 33, -48, -4, 29, 1, -8, -4, -20, 41, -22, 1, 12, -33, 0, + -17, -16, 29, -3, -2, -36, 6, -1, -11, 4, -24, 40, -24, -5, 26, -2, + -28, 13, -11, 35, -9, -2, -3, -6, 13, 10, 1, 11, -22, 22, -27, -5, + 20, 11, -1, 8, -23, 8, 7, -7, 17, -6, 16, -9, -10, 3, 13, -3, + -17, 19, -21, 6, -13, -15, -7, 22, -15, -7, 11, -20, -19, -6, 0, 28, + -10, -7, -13, 9, 7, 1, -11, -6, 21, -33, -4, 52, -11, -1, -2, -2, + -4, 32, 17, -31, 7, 12, 2, -5, 11, -1, -6, 1, 3, -11, 5, 4, + -15, -8, 10, 5, -18, 5, -26, -11, 22, -15, -23, 22, 19, -30, 3, 1, + -5, 10, -17, 10, -2, 10, 7, -17, -5, 36, -12, -24, 27, 22, -3, -11, + -6, -7, 20, 5, -21, 0, 23, -31, -27, 14, 2, 8, 7, -15, 0, 13, + -7, -3, -21, 33, -4, -26, 7, 5, -7, -7, 1, 3, 4, 11, -24, 6, + 11, -7, 14, -9, -11, -1, 34, -22, 11, 1, -18, 17, 4, -19, 28, -15, + -7, -11, 12, 1, -7, -9, -12, 17, -20, 6, 5, 2, -10, 12, -23, -3, + 26, -1, 4, 6, -25, 12, -3, -26, 2, 15, 14, -18, -6, -17, 14, 4, + -10, 21, -13, 5, -15, -20, 27, 6, 8, -11, 18, 15, -34, 17, -2, -13, + 41, -9, -10, -6, -2, 7, -11, -4, 28, -26, -6, 25, 17, -36, -2, 33, + -39, -15, 11, -2, 26, -32, -31, 21, 26, -11, -24, 12, -17, 4, -33, 24, + 14, -10, 12, -19, -3, 28, 11, -8, 0, 26, -17, -7, 8, -6, 20, 26, + -29, -27, 25, -14, -2, 10, -16, 39, -24, -17, -4, -13, 24, -10, -3, -20, + 25, -1, -24, 24, -20, -5, 21, -26, 7, 21, -26, 15, 17, 6, -34, 5, + 11, -27, 20, 17, -13, -8, -16, 9, 33, -36, 19, 5, 4, -2, -33, -12, + 38, -17, -10, -4, 19, 14, -4, -32, -41, 64, 5, -38, 28, 6, -2, -11, + -22, 11, 17, 17, -24, 23, -7, 9, 10, -38, 0, 25, -9, -6, -27, 20, + 2, -27, 34, -23, 17, -22, 4, 12, -43, 29, -8, 25, -19, 13, -17, -11, + 27, -8, 14, -19, 12, 9, -22, -6, 11, -10, 17, -4, 2, -3, 15, -47, + 32, -18, 11, 14, 0, 8, -33, -14, -12, 23, 17, -12, -4, 13, -27, 10, + -17, 20, -2, -11, -11, 27, 18, -21, -6, 26, -18, 9, -7, 27, -12, 3, + -9, -9, 22, 7, -38, -2, 14, -16, 12, -21, -10, 22, 1, -28, 20, 31, + -11, -49, 9, 16, -4, -7, -4, -5, 46, -39, 9, -18, 16, 22, -24, -13, + 14, 29, -10, 3, -23, 4, 11, -33, 30, 18, -9, 5, -11, 4, -20, 30, + -9, -14, -7, -9, 4, 0, 4, -15, -11, 23, 5, -24, 26, -6, -8, -17, + 21, 0, 3, 13, -10, -13, 19, -16, -10, -5, 10, 8, 22, -19, 4, -8, + 0, -24, 38, 12, -33, 10, -9, 5, -13, 11, 3, 7, -18, -12, 11, -4, + 8, -17, -7, 16, -9, -2, -9, 0, 10, -2, -1, -1, 12, -6, 13, -18, + 18, -6, 10, 1, -3, 9, -2, -30, 23, -9, 29, -11, -31, 10, 6, -21, + -19, 54, -30, 18, -12, -26, 23, -10, -31, 23, -5, 49, -34, 4, -18, 3, + 11, -24, 27, 12, -24, 3, -13, 3, 16, -6, -7, 1, 19, -8, -3, -11, + 13, -14, 19, 10, 17, -21, 14, -40, 12, 13, -5, -3, 21, -14, -29, 16, + -24, 1, 10, -1, -3, 6, -15, -16, 16, -4, 2, 23, -32, -1, 7, -5, + 13, 4, -15, 33, 1, -7, -7, -12, 13, 6, -8, 2, 21, 2, -21, 17, + -14, -19, 36, -2, -16, -4, 3, 9, 15, -39, 3, 9, -10, -3, -12, -7, + 28, -19, 8, -18, 22, -18, -11, -2, 17, 23, -15, -24, 11, 13, -14, -10, + 9, 4, 14, -10, -13, 13, -3, -12, 25, 6, -12, 12, -19, -3, 19, -10, + -13, 19, 10, 18, -31, -15, 19, -9, -14, -6, 25, -18, 2, 17, -41, 11, + 16, -20, 3, -10, 16, 9, 14, -27, -1, -3, 9, -19, 36, -6, -4, -4, + -16, 5, -7, 24, -1, -30, 13, -8, -4, -9, 47, -37, 3, 21, -24, 1, + 3, 11, 5, -10, -8, 20, -31, 16, 10, -1, 0, -9, -1, -6, 14, -6, + 6, -17, 20, 3, -23, 10, -14, 17, -16, -2, 26, 7, -20, -10, 9, -18, + 31, -35, 3, 14, -8, 13, -27, -4, -4, 26, -20, -9, 14, 22, -27, -4, + 18, 9, 9, 3, -13, -20, 15, -13, 6, 12, -5, -6, -12, 0, 4, -10, + 18, -7, -8, -15, 1, -11, 17, 5, -11, 14, -6, -11, 4, 10, -5, 13, + 0, -7, 15, -2, -16, 2, -3, 9, -6, 2, 34, -11, -17, -8, 21, 13, + -21, -4, 14, -7, -7, -19, 13, -7, 4, -25, 7, 16, -14, -40, -11, 36, + 3, -10, 4, -10, 7, -1, -1, 4, 14, 6, -14, -14, 17, 23, -13, -2, + -1, -12, 9, 8, 1, -7, 22, -29, 7, 7, 0, -24, 13, -10, 18, -1, + -3, 13, -24, 30, -32, -5, 18, -2, -6, -8, 11, -18, -12, 17, -11, 0, + 5, -4, -14, 31, -15, -16, 13, 12, -4, 4, -4, -1, -11, -15, 26, -18, + 29, -15, -3, -8, 6, 6, -34, 22, 0, 11, -18, 16, 20, -19, -21, -5, + 11, 21, 10, 10, -27, -5, 3, 2, -5, 9, -9, -1, 1, -11, -3, 8, + 4, 1, -1, -11, 19, -1, -21, -5, -2, 11, -2, -8, 10, -7, -1, 2, + -18, 3, 0, 7, 2, 7, 1, 1, -28, -14, 10, 19, 12, -21, 7, -19, + 20, -2, -3, -1, 17, -11, -13, -16, 32, 4, -5, -3, 4, -4, 18, -2, + -17, -6, 16, -3, 4, -12, 4, -2, 2, 6, -18, 20, -24, 17, -10, 19, + -16, -17, 8, -7, -5, 16, -12, -18, 11, 9, 2, -8, 17, -9, -3, -13, + 7, -6, 30, -15, -11, 5, 14, -2, -15, -5, 14, 13, -12, -24, -10, 22, + -2, -8, -1, 21, -5, -19, -16, 8, 42, -6, -27, -12, 23, 10, -17, -14, + 16, 14, -16, -2, 9, -2, 16, -9, -31, 22, 0, -2, 3, 4, -5, 20, + -24, -5, 13, -1, -5, -10, -6, 8, -11, 2, 8, -8, -5, -9, 1, -6, + 16, -1, -18, 4, 9, -3, 6, -4, 6, 9, -7, -9, -1, 10, -7, 4, + 3, -3, 4, -8, -5, 3, -4, 10, 6, -15, 2, 3, -5, -2, -3, -12, + 18, 2, -16, 7, 13, 0, -19, -8, 11, -6, -1, -9, 5, 13, -8, -6, + 6, 7, 11, -11, -6, 13, -2, -5, -1, 9, -2, -7, -15, 10, 5, -1, + -13, 8, 0, -6, -2, -2, 18, -16, -7, 2, 3, -4, 6, -11, 4, 6, + 1, -5, 22, -11, -5, -6, -3, 11, -1, -1, 4, 1, -4, -13, -4, 11, + -9, 1, 9, -1, -8, 1, -5, -7, 5, -14, 18, -1, -12, 11, -12, 16, + -5, -11, 11, -2, 15, -7, -18, -10, 0, 18, -12, 8, 3, 6, -16, -3, + 3, 6, 0, -1, -3, 4, 9, 3, -17, -7, 11, 11, -19, 5, 15, -12, + -3, -12, 4, 11, -19, 0, 0, -14, 21, -15, 2, 8, 3, 8, -8, 5, + -18, 9, -2, -8, 23, -5, -16, 5, 3, -20, 13, 11, -6, -15, 5, 4, + -12, 2, 10, -5, -12, 5, -14, -2, 18, 11, -14, 0, 28, -10, -20, 4, + 7, 9, -13, -6, 15, 11, -9, -6, 14, -8, 10, 4, -12, 11, -18, 13, + -17, -9, 16, -4, -14, -7, 17, -24, -5, 4, 6, -6, 14, 2, -24, -22, + 11, 13, 8, -16, 6, 13, -28, 10, -2, 11, 8, -1, -8, -14, 22, 3, + -5, -13, 18, 7, -26, 15, 20, -6, -10, 4, 11, 5, -8, -3, -5, 0, + -1, -6, 0, 4, 4, -14, -1, 1, 8, -14, -10, -4, 6, 4, -8, 3, + -9, 0, 11, -4, -7, 5, 4, 6, -29, 18, 22, -19, -16, -11, 17, 7, + -4, 3, -23, 20, 8, -19, 3, 13, 13, -16, -18, 15, -6, 0, 3, 17, + -7, -4, 2, -22, 21, -1, -2, -1, -15, 13, 3, -7, 4, 0, -7, 8, + -7, 11, 3, -2, -8, 10, -15, 0, 9, -14, -8, 8, -2, -9, 10, -13, + 9, 7, -6, 2, -12, -4, 6, -12, 8, 12, 3, -10, 6, 7, 1, -2, + -11, -1, 7, -7, 8, -13, -10, 11, -9, -10, -8, 20, 9, -11, 8, -5, + -4, 6, -3, 5, 13, -13, -7, -7, 6, 19, 0, -9, 9, -1, -3, 4, + -7, 0, -2, -4, -5, 5, 0, -5, 14, -19, -14, 18, -1, -5, 3, -12, + 18, -19, 4, -15, -10, 10, 10, -17, -4, 19, -6, -2, 5, 11, -4, -3, + 9, -22, 28, -6, -5, 0, -1, 11, -11, -13, 22, 3, -8, -9, 1, 3, + 0, 1, 2, 7, -5, -25, 10, 6, 6, 2, -11, 8, -16, 15, -20, 5, + 9, -6, -13, -5, 14, 6, -21, 22, -7, -14, 4, 26, -8, -13, 8, 1, + -10, -13, 11, 10, -10, 2, -13, -9, 15, 0, 10, -30, 14, 7, -13, -5, + -12, 8, 10, -4, 10, 12, -15, -7, 5, 2, 2, 10, -13, -3, 0, 21, + -2, -16, 9, 3, -1, 6, 15, -3, -21, 10, -8, 5, 1, 1, 2, -19, + 10, -7, -3, -1, 8, 6, -26, -10, 18, -28, -3, -3, 4, 0, -7, 6, + -10, -2, 25, -19, 5, -11, -2, 14, 4, -5, -3, 4, -5, 6, -2, -3, + 11, -1, 13, -12, 5, 20, -15, -3, 17, 4, -14, -5, 11, 3, 1, 6, + 11, -20, 10, -4, -4, -4, -4, -18, -7, 5, 10, -25, 7, -9, -15, 1, + -4, 4, 4, -4, -1, -18, 9, -6, 4, 7, -19, 10, 0, 3, -6, 12, + 18, -5, 2, 4, -4, 11, 2, 5, 2, 1, 3, -4, 3, 4, -3, -2, + -8, 11, 5, -10, -12, 12, -6, 6, -9, -6, 4, 9, 0, -9, 4, 3, + -7, -5, -12, 19, 2, -28, 1, 0, 9, -10, -6, 3, 3, -11, -4, 6, + 7, -7, -3, 5, -12, 9, 10, -12, 7, 5, 5, -6, -9, 16, 6, -16, + 3, 8, -17, 12, -5, 2, 1, 21, -25, -10, 5, -2, 15, -6, 1, 3, + 5, -16, -2, -16, 32, -17, 7, -13, 6, -1, -4, 0, -4, 10, -2, -17, + -7, 29, 0, -13, -1, -1, 2, 12, -4, 3, -2, 4, -19, -1, 18, 2, + -3, -15, -2, 10, -4, 1, -2, -5, 20, -5, -6, -7, 9, 0, -2, -24, + 5, 15, -2, -11, 1, 0, -2, -14, -2, -4, 7, 4, -4, -9, 2, 4, + -8, 8, -1, 2, 10, -13, 4, 10, -4, 27, -22, 17, -18, -2, 5, 8, + -1, 4, -6, 2, -1, 9, 1, -3, 16, -21, -18, 2, 10, -14, 9, 3, + -14, -9, 0, -16, 9, -10, 11, -12, -3, 1, -10, 3, -2, 2, -13, 13, + 10, -1, 4, 4, 1, -3, 9, 0, 4, 8, -14, 10, -4, 0, 8, 11, + -2, 2, -11, 3, -13, -8, 11, 4, 1, -7, 4, -21, 0, 1, -4, -22, + 17, -8, -16, 10, 4, -2, 0, -4, 2, -2, 2, -6, 10, 3, 3, 5, + -1, 6, 5, 2, -6, -3, -2, 7, -4, -4, 12, 1, -30, 12, -7, 3, + 4, -6, -7, -9, 9, -1, 7, -10, 12, -16, 2, -8, 23, -5, -5, -1, + -8, 10, 3, -14, -12, 25, 7, -13, -6, 4, 15, -3, -23, 9, 12, -9, + -13, 18, -9, 5, 1, -17, -4, 13, -10, 11, -10, -1, 6, 0, -7, -2, + 9, -4, 9, -24, 7, 6, -5, 4, 15, -15, 11, -5, -24, 9, 11, -16, + 2, 0, -9, -2, 10, 7, -12, 8, -12, -6, 10, 6, 10, -14, -5, 20, + -16, 7, 8, -1, -19, 24, 2, -10, 15, 6, -6, -21, 3, -3, 15, -9, + -3, 3, -2, -4, -3, -9, 5, 0, -5, -3, -15, -4, -1, 1, -14, 33, + -12, -18, 9, -2, -10, 9, 9, -1, -1, -5, 10, -3, 2, 4, 2, -9, + -1, 25, -2, -3, 15, -17, -7, 8, -7, 0, 10, -13, 9, -11, 0, -3, + 18, -15, -11, 5, 0, -12, -2, 7, -6, -4, -9, 11, -6, 8, 1, -14, + 3, 16, -10, -3, 2, 6, 4, 9, -9, -2, 0, 2, -3, 15, 3, -10, + -4, -8, -1, 10, -13, -9, 16, -9, -3, -2, 5, -6, -6, -9, 10, 8, + -4, 14, -7, -19, 12, 1, 2, 1, 4, -1, -6, -3, -3, 5, 7, -2, + 0, 0, -5, 0, -6, 1, 6, -5, -4, 5, -6, 5, -4, -8, 15, -5, + -7, 0, 3, -8, 0, 3, -8, -4, 6, -4, -4, 15, -5, -8, -7, 4, + 7, -10, -6, 15, -4, -13, 7, 2, 2, 1, -4, 5, 0, 0, 1, 4, + -7, 4, 4, -2, 4, 5, 1, -18, 12, 4, -3, -6, 11, 0, -13, -1, + 1, -12, 3, 13, -9, -15, 7, 0, -4, -8, 0, 5, 0, -9, 1, 1, + -3, 0, 3, 5, -10, 6, -1, -4, 4, 15, -15, -5, -9, 18, -2, 0, + 15, -11, -9, 0, 6, -2, 8, 1, -8, -9, 7, 3, -7, -3, 6, 1, + -5, 0, -5, -5, 0, -3, 11, 1, -3, -8, -4, -4, 5, 9, -6, -7, + 4, 15, -13, 5, -4, 2, -6, -2, 0, 5, 4, -4, 0, -6, 8, 3, + -2, -4, -4, -11, 4, 10, -1, -4, -2, -1, -3, 1, -4, -2, 3, 1, + -4, -11, 12, -4, 5, -2, 7, -12, -2, 4, -4, 5, 8, 1, -8, 14, + -11, -1, 1, 4, 0, 5, -5, 2, -7, -7, 10, 3, 1, -13, 0, -4, + 5, -9, -1, 1, -11, -5, 5, 2, -6, 5, -5, -8, 12, -2, 7, -1, + -10, -5, -7, 14, 9, 3, -5, -2, 5, 4, -2, 0, -5, 2, 3, 3, + -12, 6, 3, 2, -9, -1, 24, -13, -9, -1, -2, 0, 7, -6, -17, 14, + -12, -5, 10, 1, -4, -1, -1, 1, -3, 2, -2, -11, 1, -1, -1, 1, + 10, -3, 2, 1, 5, -7, 1, -1, -5, 7, 1, 7, -4, 5, -11, -8, + -8, 7, 8, 6, 0, -15, -1, 7, 0, -6, -3, 7, -4, -3, -2, 1, + 5, 8, -6, -4, 11, 3, -14, -6, -3, -6, 9, -5, 4, -5, 2, 3, + -13, -3, 1, -4, -3, 11, -1, 0, 7, -16, -6, 11, 5, 0, 4, 5, + -2, -3, -2, 8, 7, -16, 1, 2, 6, 3, -17, 11, -2, -2, -9, 6, + 0, -7, 6, -22, -2, 14, 3, -11, 0, -6, -2, -7, -7, 1, 4, 14, + -1, -6, 0, 7, 3, -14, 4, 15, -4, -9, -2, 12, 14, -10, 5, 9, + -11, -2, -9, 2, -9, 11, 2, -21, 7, 6, -11, -1, 0, 0, 1, -9, + 4, 0, -10, 1, 3, -3, -7, 12, -9, -2, 4, 6, 3, -8, 0, 1, + -2, -14, 12, 11, -5, 10, -3, -1, 3, -6, 1, 0, -3, 8, -1, -18, + 12, 5, -13, -4, 17, -1, -6, 1, -11, 0, -6, 2, -2, -2, 5, 3, + -17, 2, -5, 11, -4, 8, 8, -19, -6, 14, -6, -6, 0, 5, 0, -8, + 7, 13, -6, -5, 6, -2, -9, -1, 8, 3, -4, -4, 10, -10, -9, 7, + 2, -6, 14, 0, -15, 3, 5, -4, -10, 8, 0, -6, -11, 3, 10, -9, + 1, 8, -7, 2, -1, -6, -8, 6, 2, -8, -2, 16, -3, -3, -1, 5, + -3, -8, 6, 9, -6, 1, -1, -1, 2, -6, 6, -1, -9, 3, 9, -10, + 1, 5, -4, -14, 2, 1, 7, -5, 3, -2, -13, 5, 10, -9, -8, 14, + -6, -19, -3, 19, -3, -3, 6, -4, -10, 3, -1, -4, 5, 5, 1, 0, + -1, 11, 4, -10, 3, -5, 4, -7, 1, 8, -3, 1, 2, 0, -10, 2, + 5, -15, -3, 8, -8, -6, 5, -2, -5, -5, 11, 0, -12, -7, 5, 2, + -5, 2, -1, -4, 2, 7, -12, 5, 6, -3, 5, -1, 12, 7, -13, -3, + 0, 3, 0, 13, -1, -4, 0, -9, 5, -6, 5, -2, -10, -6, -2, 9, + -8, 5, -6, -10, 5, 4, -6, -2, 1, 1, 6, -14, 10, -3, -4, -5, + 1, 8, -16, 7, 7, -1, 0, 3, -5, 2, -1, -3, 11, -11, 9, 8, + -18, 3, 8, 13, -4, -5, -9, 4, -2, -4, 9, 5, -6, -5, -15, -3, + 17, -6, 2, -8, 4, 4, -4, -12, -3, -2, -2, -4, 5, -4, 1, 7, + -12, -6, 8, 6, -2, 1, -3, 3, 10, -3, 7, -11, 12, 4, -1, -1, + 1, 0, -11, 11, 4, 0, -2, -9, -2, -2, -8, -1, 5, -4, -5, -5, + 1, 10, -8, -11, -5, -4, 5, -1, 1, 6, -2, -5, -5, 3, 6, -2, + 6, -3, 0, 4, 5, 2, 4, -2, 1, 5, -2, -6, 11, -1, -5, 8, + -14, 6, -2, -6, -11, 4, 2, -14, 6, -9, 5, -4, -3, 4, -12, -2, + 2, -5, 4, 7, -5, 3, 6, -1, -3, -6, 0, 7, 0, 1, 6, 9, + 4, -2, -7, -4, 7, 4, 4, -5, -5, 0, 3, -6, -1, 7, -2, -18, + -1, 3, -15, 5, -2, -2, 0, 4, -10, -4, 3, 4, -10, 4, -1, 5, + 4, -7, 8, -7, 0, 3, 2, -7, 13, 0, -2, -6, -6, 5, 10, -10, + 4, -1, 2, -1, -5, 7, 5, -3, -7, 1, -5, 10, 1, -11, 7, 6, + -10, -15, 12, 2, -4, 1, 0, -5, 3, 0, -2, 6, -5, -4, -13, -2, + 3, 1, 4, 3, 3, -10, -7, -7, 11, -2, 2, 2, -7, 4, -1, 6, + 2, 0, 8, 3, 0, -7, 8, 3, 5, -8, -3, -2, 2, 3, -12, -4, + -3, 12, -12, -4, 7, -3, -10, -10, -4, 6, -2, -8, 9, 1, 1, 1, + -3, -6, 12, -5, -6, -1, 11, -7, 5, 6, 2, 9, -11, 6, -2, 8, + 1, -6, 4, 3, -6, -3, 5, -4, 4, 1, -19, -1, 3, 4, 0, 0, + -10, -1, -3, -5, -3, 0, 11, -1, -12, -2, 6, 0, -3, 3, 4, -1, + -7, 1, -2, -1, 2, -1, 0, 2, -2, 4, -5, -4, 11, -4, -5, -3, + 7, 5, -8, 3, 6, -9, 0, 9, -5, -2, 5, -4, -6, 0, 7, -1, + -2, 0, -1, -6, -9, -6, -1, 8, 4, -1, -9, -5, 13, 2, -11, -5, + 9, 0, -8, -1, 5, -2, -5, -3, -2, 7, 5, -4, -13, 3, 11, -8, + 3, 0, 2, 5, -12, -6, 6, 3, -4, -1, 8, 1, -5, -7, -6, 2, + 8, 5, -2, -9, 7, -6, -2, 13, -7, 2, 1, -1, -5, 3, 7, -1, + -11, 9, -6, -4, -2, -5, -1, 2, -1, 3, 8, -7, -1, -9, 0, 0, + -1, 2, 5, -2, 1, -2, -3, 6, 6, -3, -6, -5, 4, -1, 1, 5, + 1, -1, -2, -3, -4, 4, 3, 1, -7, 5, -1, 0, -8, -6, 1, 7, + -3, -6, -2, 3, -1, -3, 2, 2, 0, -9, 1, -2, 4, 4, -5, 1, + -1, 1, 6, -2, 2, -5, -4, -1, 14, -3, 2, -9, 1, -2, -4, 1, + -1, 7, -9, 5, 2, -3, 2, -2, -9, -2, 4, -1, 2, -2, -2, 0, + -1, -1, -2, 3, 1, -1, -3, -6, 3, 7, -5, -3, 9, -5, -4, -5, + 8, -4, 2, 2, 8, -10, -1, 8, -14, 0, 6, -7, -1, 2, -3, 2, + -4, 5, 2, -5, -4, 5, 1, -6, 3, 6, -4, -1, -3, 3, -7, 0, + 1, 0, -4, 7, 6, -13, -3, 3, 2, -15, 8, 3, -3, -6, 9, -4, + -1, 9, 1, -6, -6, 7, 1, 1, -2, 6, -1, -4, -1, -1, -7, 5, + 3, 0, -5, -2, 8, -2, -8, 6, 7, -16, -5, 6, -6, -1, 1, 7, + -4, -3, -6, 3, -10, -3, 8, -9, -1, 5, -1, -7, 5, 2, -1, 1, + 5, 1, 2, -4, -5, 1, 1, 3, 1, -5, -2, 3, 2, -7, -1, 7, + 5, -5, -7, 5, 0, 3, -1, -4, -4, 4, 0, -4, 1, 6, -3, -7, + 0, -3, -3, -1, 0, -2, -4, 2, 1, -2, 3, -1, 0, -1, -6, 9, + -5, 4, -1, -1, 4, -2, 5, -8, 2, -3, -2, 2, -3, 10, 2, -3, + -5, 2, -4, -1, -3, -7, 9, 1, 0, 0, -5, 1, -2, -12, 6, 8, + -18, 4, -1, 4, -1, 5, -5, -3, 3, -1, 4, -5, 9, -5, -4, -5, + 2, 5, -1, -4, 0, -3, -2, 8, -5, 2, 1, -13, 3, 1, 4, 5, + -8, 2, 8, 1, -1, 1, -9, 1, -2, -4, 1, 4, -3, 4, -4, -5, + 6, 5, -6, -3, -3, 1, 1, -7, 1, 2, 1, -5, -4, -2, 2, -6, + 6, 3, 7, -10, -9, 4, 1, -5, 6, 9, 3, 1, -2, -4, 3, 4, + -1, -6, 3, 1, -2, -9, 4, 4, -5, 4, -10, 2, -4, -5, -1, 1, + 2, 0, 2, -8, 1, 3, -4, -13, 0, 10, -1, -4, 5, 0, -4, 5, + -3, 2, -5, 2, 1, 2, 4, 2, 2, -10, 5, 3, -11, -2, 3, 3, + 0, -6, -2, 1, 1, 2, -1, -8, -1, -5, -4, -3, 5, 8, -4, -4, + 2, 0, -2, -2, 1, -5, 0, 13, -8, -6, 4, 8, -6, -1, 6, -2, + 4, -5, 3, 5, -7, -8, -2, -3, 7, 8, -8, -3, 1, 5, -5, -5, + 9, -4, -7, -5, 4, 3, -6, 5, 1, -1, 3, 0, -6, -9, 0, -6, + 1, 4, 10, 5, -13, 0, 6, -2, -4, 2, -2, 6, -1, -4, 0, -11, + 6, 3, -1, -3, 14, -1, -15, 1, 2, 3, -1, 4, -3, -6, 0, 3, + 0, -6, 10, -3, -14, -2, 10, -3, -9, -4, 0, 6, -1, 7, -3, -5, + -6, 1, 0, -5, 11, -2, 1, -2, 5, -1, -4, -1, -3, -4, 2, 11, + 2, -4, 1, 2, -12, 7, 3, -1, -11, 3, 15, -8, -11, 0, 0, 2, + -7, 1, -3, -4, -3, -5, -4, 6, 11, -7, -8, -1, 6, -5, -3, 6, + 8, 3, -6, 1, -1, -1, -1, -5, -3, 8, 7, 4, -9, 1, -2, -4, + -6, 9, -4, 3, -8, 0, 6, -2, -4, -2, -2, -6, 8, -7, 3, 1, + 3, -1, -3, 2, 1, -6, -9, 3, -5, 8, 5, -10, 7, 5, -3, -2, + -1, -3, -1, -4, -7, 6, 6, 3, -7, 0, 0, 1, 0, -7, 3, -1, + 0, 1, 2, 2, 2, -11, -8, 9, 6, 2, -6, -1, 1, -3, 3, 1, + -6, 2, -3, -2, -1, 2, -4, 0, -4, -2, 0, -3, -2, -6, 5, 2, + 0, -1, -3, -1, 3, 1, -2, 0, 2, 2, 0, 1, 7, 1, -4, -2, + -6, 4, 3, -1, -4, -1, 3, 3, -9, -2, 0, -2, -1, -5, 6, 1, + -5, 1, -5, 9, -10, -4, 0, -4, 6, 1, -3, -5, 9, -2, -5, 2, + 0, 6, -6, 2, 5, 10, -8, -3, -2, -1, 4, -3, -1, -4, 0, -1, + 1, -4, 0, 5, -8, -1, -5, -1, -1, 3, 3, 3, 2, -14, -5, 1, + 2, 3, 1, -1, 2, 5, -2, 2, -5, 2, 3, -2, -2, -3, 4, 4, + 4, -6, 3, 1, -10, 1, -6, 6, -2, -3, 0, -3, 1, -3, 1, -1, + -4, -5, -4, 7, -2, -2, -3, 6, -5, -5, 2, -6, 1, 4, 3, -8, + 11, 4, -4, -1, 2, 3, -5, -2, 1, 7, -4, 2, 4, -10, 7, -7, + -1, 0, -3, 5, -4, -1, -4, 5, -7, 3, 3, -11, -2, -1, 5, 1, + -1, 0, 6, -11, 0, 1, -2, 1, 0, -1, -4, 2, 9, -2, -9, -4, + 2, 0, 2, -1, 1, 1, -7, 5, -3, 4, -1, -3, -8, 5, 7, -1, + -1, -3, 3, -7, 0, 4, -3, -3, 1, 6, 0, -1, 0, -5, -1, 0, + -4, 0, 0, -3, 1, -4, 1, 7, -3, -13, -2, -2, -1, 3, 5, 2, + -6, 1, 6, -2, -6, 8, -1, -6, 0, 4, 6, -2, 0, -2, -4, 3, + 5, -4, -7, 2, 5, -3, -3, 3, 1, -10, -7, 3, 1, -3, 2, 4, + -7, -3, 0, 2, -5, -3, 3, -2, 0, 3, 5, -6, -1, 4, -2, 0, + 5, 1, -2, -2, 3, 2, -1, -3, -3, -7, 7, 3, -1, -2, 0, 0, + 1, -2, 1, 0, -15, -1, 3, 2, -3, 4, 0, -7, 0, -1, -1, -4, + -3, 2, -1, -1, 11, -3, -1, -5, -1, 2, 2, 0, 1, 2, 3, 4, + -6, -3, -2, 1, 0, -4, 2, 1, -1, -5, 1, -1, -7, 2, -2, -5, + 0, 2, -2, 3, 5, 0, -2, -6, 6, -7, 3, -4, -6, 1, 6, 3, + 1, -2, -3, -4, -6, -1, 7, -2, 0, -3, 0, 9, -3, -5, -1, 3, + 0, -1, -3, 6, 1, -6, -3, 3, 6, 0, -6, -4, 2, 1, -1, 2, + -5, 4, 1, -2, -5, 0, 7, -9, 3, -1, 1, -6, 0, -5, -1, 1, + -1, 0, -4, 2, -2, -2, 1, 6, -1, -5, 0, 0, 0, 1, 3, 2, + 2, -1, -3, 0, 1, 5, 1, -5, -7, 2, 6, -3, -3, -3, 2, -7, + -5, 5, 0, 0, -3, -4, -1, 3, -4, -5, 1, 5, -1, -2, -4, 0, + 5, 2, 0, 2, 2, -1, -1, -5, 5, 3, -1, -4, 1, 0, -1, -2, + -1, 2, 2, -4, -4, 2, -2, -3, -4, -3, 0, 3, -3, -2, -2, 4, + 1, -2, -2, 1, 2, -6, -1, 2, 6, 1, -2, 0, 4, -3, -1, -2, + -1, 5, 1, -11, 4, 3, -1, -6, 2, -2, 3, -4, -8, -2, -1, 4, + 0, 3, -2, -1, -2, -2, 1, 3, 3, -7, 0, 2, 10, 0, -4, 3, + -3, 0, 0, 3, -4, 6, -4, -8, 2, 1, 3, -14, 1, -1, -2, 0, + 0, -5, -1, 2, -6, -1, 3, 0, -5, -3, 3, 1, 6, -2, 0, 6, + 2, -7, 1, 3, -5, 5, 8, 0, -1, 1, -4, -6, -2, 6, 4, -4, + -1, 1, -10, 0, -4, 0, -3, 2, 0, -8, 3, -3, 0, 2, -1, 1, + -8, -1, -1, -3, -1, 4, 1, 6, 1, 0, 0, -2, 0, -2, 7, -4, + 3, -1, 2, 0, -2, -2, -8, 3, 2, -1, -4, 3, 0, -3, -5, 2, + -3, -3, -2, 5, 2, 1, 1, -4, 1, -1, 4, 6, -4, 0, -6, -4, + 1, 3, 3, -1, -2, -7, -1, -3, 6, -6, 2, 1, 5, -8, -5, -1, + 2, -1, -3, -1, -1, 5, -7, 3, 3, 1, 4, -4, -3, -3, 8, 1, + -2, 4, 4, -2, -8, 2, 1, 0, 2, 0, -6, 3, -2, -8, -2, 5, + -1, -6, 0, 2, -1, -5, -2, -2, 6, 0, -5, -2, 3, 0, -5, -1, + 6, 7, 2, -8, -4, 6, 2, -6, -4, 12, 2, -5, -2, -6, 1, 1, + -3, -7, -3, 11, -3, -6, -1, 3, -2, -4, -4, 4, -3, 4, -2, -3, + 1, 7, 0, -8, 7, 1, -2, -4, -6, 13, 0, -3, 1, 2, -1, -4, + -3, 1, 3, -2, -3, -1, 0, 3, -1, -10, -1, 2, -8, -3, 3, 2, + 1, 4, -6, -2, 1, -3, -1, -4, 6, 5, -1, -5, -1, 9, -2, 0, + -4, 0, 1, -3, 4, -5, 1, 3, -4, -6, 0, 4, -2, -6, 9, -1, + -3, 2, -4, 0, 4, -7, -4, -1, 1, 4, 0, -1, 6, -2, -2, 4, + -3, -1, -6, -2, 2, 3, 1, -3, 8, -10, -10, 7, 0, -2, -1, -4, + 3, -6, 0, -5, -5, 5, 3, -6, 1, 5, 0, -1, 1, -1, 0, 0, + 0, -5, 7, -2, -1, 2, -1, 3, 0, -6, 4, -3, -2, -3, -2, 1, + 3, 3, 0, -2, -1, -9, 2, 2, -1, 4, -4, 4, -10, 7, -8, 2, + 1, -1, 0, -1, 4, 2, -7, 7, -6, -4, 3, 11, -5, -6, 1, 3, + -4, -6, 2, 2, -2, -3, -7, -4, 6, 0, 7, -13, 6, 2, -9, -2, + -5, 3, 8, 0, 0, 5, -5, -4, 3, 0, 2, 4, -7, 0, -1, 10, + -3, -6, 7, 2, -1, 0, 6, -2, -7, 4, -2, -1, -2, 1, -3, -9, + 6, 0, -4, 0, 3, 3, -11, -4, 7, -16, -2, 0, 2, 1, -2, 2, + -5, -1, 12, -6, 2, -7, 2, 6, 0, -4, -1, 1, -3, 2, -1, 0, + 7, -2, 2, -6, 2, 7, -9, -4, 8, 2, -9, -3, 8, 1, -1, 4, + 5, -11, 2, 1, -1, 0, 0, -6, -2, 2, 6, -13, 2, -3, -8, 1, + 1, 3, -2, -3, -2, -7, 4, -6, -2, 3, -10, 5, -2, 1, -3, 5, + 8, -4, -1, 2, -1, 6, 2, 3, 2, -2, 0, -1, 0, 4, 1, -1, + -2, 7, 1, -7, -5, 7, -5, 2, -5, -4, 0, 3, 3, -2, 0, -1, + -9, -4, -9, 10, 1, -14, 0, -1, 6, -8, -3, 3, -1, -6, -1, 5, + 3, -5, -1, 3, -6, 5, 7, -10, 5, 5, 2, -4, -3, 9, 4, -11, + 0, 5, -11, 7, -6, 2, 2, 12, -15, -8, 2, -3, 7, -5, 3, 3, + 1, -10, 0, -9, 17, -11, 7, -6, 2, 1, -3, 0, -1, 5, -2, -10, + -4, 16, -1, -7, -1, -3, 1, 11, -3, 1, -3, 2, -12, -2, 12, 3, + -1, -10, -2, 6, -3, 1, -1, -4, 12, -1, -2, -7, 6, -1, -1, -16, + 5, 11, -3, -7, 1, -1, -2, -6, -4, -5, 3, 4, -3, -8, -1, 3, + -5, 3, 1, 2, 6, -10, 1, 7, 0, 21, -15, 11, -12, 0, 1, 4, + 1, 4, -4, -1, 3, 7, 0, -5, 10, -15, -14, 2, 6, -11, 5, 3, + -10, -6, -1, -11, 4, -9, 6, -9, -2, 2, -8, 3, 0, 2, -9, 7, + 7, 2, 2, 0, 3, 1, 6, 0, 3, 6, -10, 6, -4, 1, 7, 9, + -1, 0, -7, 1, -11, -8, 9, 4, 0, -6, 2, -16, 0, 1, -2, -16, + 10, -7, -12, 7, 4, -1, -1, -4, 2, -1, 2, -5, 8, 3, 3, 4, + -2, 4, 3, 2, -4, -2, -1, 5, -5, -3, 9, 2, -22, 8, -6, 1, + 3, -5, -4, -6, 7, 0, 5, -8, 9, -13, 0, -6, 18, -3, -3, -1, + -6, 7, 3, -11, -9, 19, 6, -10, -6, 3, 12, -2, -18, 7, 8, -7, + -10, 14, -8, 5, 1, -15, -4, 11, -6, 9, -8, -1, 5, 1, -6, -2, + 7, -3, 7, -20, 6, 5, -4, 3, 12, -12, 11, -4, -22, 7, 9, -13, + 1, 0, -8, -1, 9, 6, -10, 5, -9, -5, 8, 5, 8, -12, -4, 16, + -14, 7, 6, -1, -16, 21, 2, -9, 13, 5, -4, -19, 2, -3, 12, -7, + -2, 3, -2, -4, -3, -8, 4, 1, -4, -4, -14, -3, -1, 1, -11, 30, + -11, -16, 8, -2, -9, 8, 8, -1, -1, -5, 10, -4, 1, 4, 3, -8, + -1, 23, -2, -2, 14, -15, -7, 7, -7, 0, 9, -12, 8, -10, 0, -3, + 16, -13, -11, 5, -1, -10, -2, 6, -5, -4, -9, 10, -6, 7, 1, -13, + 2, 14, -9, -3, 2, 6, 4, 8, -8, -2, 0, 2, -3, 14, 3, -10, + -4, -8, -1, 10, -13, -8, 15, -9, -3, -2, 5, -5, -6, -9, 9, 7, + -4, 14, -7, -18, 12, 1, 2, 1, 4, -2, -6, -3, -2, 5, 7, -2, + 0, 0, -4, 0, -6, 1, 5, -5, -4, 5, -6, 5, -4, -8, 15, -5, + -6, 0, 3, -8, 0, 3, 0, -1, 0, -4, 6, -16, 22, -7, 3, -5, + 2, 2, 1, -3, 4, -8, 4, 4, 0, -5, -9, 4, -5, -4, 3, 2, + 1, 3, -4, 6, -15, -1, 4, 1, -9, 3, 1, -8, 3, -6, 11, -5, + 6, -11, 17, -15, -2, -19, -11, 1, -4, 8, 0, 5, 18, -11, 0, 13, + -4, 6, -13, 4, -11, -1, -7, -7, 11, 10, -9, 17, -11, 20, -6, 7, + -14, 23, -7, -2, -2, 7, -10, 2, 0, 2, 5, 6, -8, 5, -4, -10, + 9, -4, 6, 0, -7, 8, -7, 1, -20, -4, -1, -3, 6, -10, -6, -15, + -11, 10, -5, 19, 3, 1, -19, -11, -1, -9, 9, 22, 24, 10, -5, -18, + -8, -23, 14, 11, 0, 31, 43, -9, 0, -7, -15, -28, -35, -30, 3, 5, + -5, 11, 52, 55, 7, -5, -10, -12, -25, -43, -12, 4, -37, -47, -21, -5, + 4, -11, 1, 31, 27, 34, 46, 48, 61, 10, 16, 8, 7, -14, -40, -47, + -36, -51, -42, -15, 4, 12, -32, -42, -10, -4, 10, 1, 15, 50, 31, 5, + 15, 38, 37, 29, 15, 22, 11, -4, -35, 10, 3, -18, 1, -14, -33, -5, + -47, -25, -13, -2, 15, -6, 5, -29, -17, -19, -1, 3, 7, 2, 17, 28, + -8, -23, 7, 7, 36, 15, 2, 1, -2, -9, 1, 6, 20, 6, 14, -3, + 21, -11, -12, -35, 11, -20, -18, -36, -23, -27, -19, 1, 10, 14, 27, 6, + 44, 14, -9, 3, 20, 27, 45, -8, -13, 16, -16, 24, -10, -9, -3, -38, + -19, -14, -38, -38, -41, 13, 40, -37, 5, -7, -7, -4, 4, -31, 32, 22, + 15, 9, 13, 10, 10, -17, 22, 30, 9, -6, 27, 66, 47, -17, -21, -20, + -9, -36, -73, -3, 22, -35, -12, 6, 7, 4, -17, -45, 22, 17, -17, 3, + -9, -4, 11, -10, 13, -4, 8, 38, 3, 20, 42, -22, 9, 23, -28, -21, + 3, 10, 1, 26, -28, -18, -9, 7, -30, -41, -24, -9, 10, -6, 31, -5, + 2, 29, -9, 1, -27, -24, 7, -19, -5, 10, -13, 21, 21, 3, 30, -11, + -17, 34, -11, 8, 7, -8, 1, 11, -1, 7, -13, 1, -3, 23, -12, 8, + -19, -3, 20, -78, 42, -23, 4, -29, -16, -5, 38, -49, 30, -26, 26, 16, + 8, -33, 53, 19, -20, 12, 5, 23, -11, 4, -6, 42, -111, 67, -40, 29, + -32, -20, -77, 113, -46, -12, 8, -5, -14, 35, -52, 94, -5, -61, 58, -36, + 41, -83, 21, -19, 61, -68, 37, -37, 12, 66, -69, -16, 100, -88, 48, 21, + -39, 73, -24, -2, 45, 65, -59, 53, -103, 95, -97, 1, -14, -4, -41, 9, + -13, -18, 16, -26, 9, 26, -15, 25, -16, 6, 8, 26, -52, 35, -21, 4, + -2, -11, -4, 22, 0, 21, -40, 65, -6, -13, -11, -7, 32, -46, -48, 16, + -26, -3, 0, -42, 87, -68, 34, 17, -14, 43, 23, -15, 30, 20, 47, -19, + -33, -12, 15, 1, -37, 15, -12, -11, -7, 15, -75, 36, -41, 27, -8, -7, + -12, 10, -4, 49, -6, 42, -32, 4, 20, 33, -65, 24, -52, 10, 13, -17, + -15, 60, -14, -55, 35, -16, 50, -83, -3, 29, 58, -75, 71, -46, 47, -32, + 44, -57, 10, -43, 33, 22, -48, 51, -41, 6, 7, 39, -3, -41, 7, -9, + 37, -66, 22, 26, -13, 74, -87, 127, -39, -16, -29, -11, -8, -57, -15, -45, + 52, -74, -5, -2, 103, -126, 85, 20, 28, -7, 53, -38, 58, -10, -11, 33, + -70, 20, 1, 40, -36, 26, -58, 58, -23, 61, -71, -7, -39, 43, 22, -18, + -1, -61, 90, -37, 35, -58, 30, -62, 27, -45, 47, -59, -6, -35, 70, -49, + 9, -30, 92, -15, 21, 1, 26, 6, -19, 90, -43, 49, -46, 10, 6, 15, + -90, 67, -51, -11, 4, 28, -36, 24, 41, -68, 24, -34, 63, -40, 17, -30, + 18, -39, 14, -38, 15, 9, -54, 54, -20, 36, -21, -14, -13, 11, 23, 11, + -54, 56, -25, 37, -46, 49, -74, 81, -40, 51, -44, 57, -69, 51, -50, 61, + 27, -112, 111, -114, 106, -85, 49, -61, 75, -18, 26, -68, 32, -15, -25, 21, + -15, 38, -46, 80, -119, 126, -85, 41, -40, 77, -65, 28, -6, -39, 45, -87, + 39, -63, 81, -32, 4, -32, 44, -25, 42, -12, -15, 21, -1, -56, 21, 23, + -30, 33, -28, -3, 32, 4, -36, 60, -20, 13, -3, 22, -43, 101, -88, 59, + -53, 18, 8, 22, -33, -52, 34, -32, 35, -90, 112, -107, 56, -59, 43, -60, + -18, -4, -21, 45, 11, -48, 11, 38, -27, 58, -49, 65, 19, 54, -38, 35, + -37, 24, -11, 44, -62, 41, -16, -48, -8, 31, -68, 17, -3, -5, 52, -51, + -10, 16, -26, 18, -29, 56, -41, 3, 5, -10, -37, 61, -14, -10, -9, 20, + -8, 8, -2, -16, 44, -17, 14, -33, 30, -2, -27, 16, 3, 0, 51, -42, + 32, -20, 8, -11, -24, 10, 12, -15, 6, -32, 10, 21, -38, -11, -12, 23, + 13, -64, 19, 34, -23, -23, 16, 10, 39, 2, -36, 55, -31, 0, -29, 18, + 8, 12, -61, 73, -28, 54, -34, 21, 9, 7, 53, -34, -29, 19, -7, -44, + 7, 15, -16, -18, -31, 10, -29, 36, -69, 7, 4, 33, -72, 45, 14, 0, + -8, 35, -13, 26, 16, -28, -3, -32, 45, -4, 8, -20, 65, -24, 2, -24, + 40, -16, -16, 20, 8, 2, -3, -2, 23, -15, -11, -30, 19, -51, -19, -5, + -36, 18, 24, -4, -1, 46, -90, 60, 4, 23, -17, 16, 60, -24, 0, 18, + 0, 5, -6, -24, 27, -34, -28, -7, -4, 22, -30, -11, -3, -1, -44, 36, + -38, -6, -9, 55, -34, 16, 27, 28, -65, 62, 22, -32, 36, 7, 2, 27, + -19, 50, -71, 44, -19, -67, 13, -3, -14, -30, 33, 5, -12, -48, 60, -47, + -28, 9, -6, 24, -11, -1, 13, 62, -53, 26, 7, -9, 6, 58, -38, -10, + 0, 5, -23, 23, 8, -14, -19, 21, -9, 35, -17, -28, 14, 27, -17, -14, + -29, 24, 6, -85, 74, -16, -18, -2, -19, 47, -29, -18, -15, 52, 0, 7, + -10, -23, 45, 13, -11, 12, -28, 27, -26, 19, -69, 74, -55, 35, -21, 41, + -24, -11, 39, -19, 7, 0, 7, -31, 10, 7, -45, -17, 25, -12, 9, -19, + 3, 28, -53, 76, -19, -25, 49, -2, 6, -11, 24, -12, -23, 17, -1, -15, + -10, -36, 26, -25, 0, -44, 59, -67, 45, -31, 5, 15, 56, -12, -14, 12, + 10, 24, -52, 37, 5, -35, 52, 23, -55, -6, 24, -49, 26, 31, -24, 10, + -33, 33, -11, 1, -49, 8, 7, 6, -78, 12, -22, 10, -11, 13, 13, -18, + 38, 50, -18, -5, 64, -52, 59, 33, 3, -9, -6, -6, 26, -64, 18, -38, + -47, 18, -33, 4, -39, 40, -31, -1, -23, 48, -30, 18, 17, 32, -20, 32, + 19, 24, -58, 49, -38, -9, 15, -28, 16, -3, -2, -28, 33, -22, 23, -1, + -34, 33, -48, 67, -55, 21, 51, -66, -2, 21, -5, -17, 24, -63, 53, 8, + -19, 9, -11, 36, -37, -35, 43, -35, -3, -44, 68, -43, 53, -24, -5, 45, + -16, -7, 14, 49, 3, -16, 22, -10, 2, -28, -9, -6, -5, 32, -76, -22, + 35, -26, -35, -12, 0, 3, 13, 6, 36, 7, -32, 69, -15, 45, -20, -21, + 35, 35, 1, -25, 11, 34, -24, -33, -9, 5, -25, -49, 31, -41, 15, -42, + 25, -30, 42, -80, 32, 2, -18, 33, -12, -9, 43, -1, 4, -12, 54, -51, + 22, -1, 18, 28, -29, 18, 7, 10, -19, 8, -1, 12, -21, -6, -11, 4, + 4, -28, -8, 22, -27, -5, 9, -25, 20, -19, -36, 41, -8, 20, -32, 16, + -29, 29, -13, 13, 4, 1, 17, 8, 0, 9, 22, -1, -3, 28, -11, -39, + 36, -31, 5, -11, -27, 22, -39, 7, 15, -24, 19, 8, -37, 75, -52, 54, + -65, 22, -13, 23, -26, 32, -19, 10, -8, -3, 12, 16, -44, 25, -23, 14, + 9, -46, 20, 2, -4, -8, -6, 18, 4, -2, -3, -15, 4, 16, -9, -5, + 34, -29, 27, -54, 98, -65, 11, -18, 16, -13, 0, -2, 0, 22, -43, 31, + -46, 58, 2, -25, -2, 16, -2, -29, 17, 18, -26, 21, -17, 5, -4, -9, + 0, -34, 50, -27, -3, 4, 31, -3, -47, 32, -25, 36, 6, -47, 33, -28, + 39, -36, 42, -28, 5, -3, -2, 25, 27, -47, 20, 22, -5, -15, 1, -9, + 16, -25, -10, -43, 40, -12, -19, 22, -24, -5, 14, -44, 42, -32, 32, -45, + 40, 41, -17, 27, -44, 38, -16, 15, -36, 39, -13, -19, -4, 34, 1, -9, + 9, -16, -2, -29, 31, -31, -4, 35, -21, -52, 63, -41, 2, -7, 30, -35, + 13, 9, 15, -4, 14, -36, 18, -14, 55, -50, -6, 22, -23, -11, -5, 12, + 17, -13, -43, 44, -33, 41, -42, 45, 3, -12, 26, 11, -11, 35, -76, 39, + 2, 0, 3, -4, 15, -19, -6, -33, 11, 5, 16, -25, -2, 19, -7, -43, + 30, 20, -27, -18, 12, 14, 33, -50, 14, -15, 23, 8, 2, -10, -4, 53, + -86, 24, -9, 41, -34, -21, 22, 24, -54, 27, 13, 2, -9, 14, -29, 21, + 40, -43, -9, -3, 27, -3, -22, 18, 10, -23, -15, 1, 14, -12, 3, -30, + 30, -22, -28, 36, -15, 39, -57, 21, 3, -3, 33, -13, -2, 6, 20, -6, + 4, -13, -5, -18, 13, -7, 7, 26, -26, 16, 7, -64, 37, -7, 10, -20, + 12, -11, 7, -34, 37, -12, -24, 34, -18, -18, 39, 9, -42, -24, 43, 2, + -16, 25, 12, -16, 8, 12, -44, 32, -9, 23, 1, -37, 40, -23, -17, 18, + -42, 23, -12, -7, 10, -6, 6, -13, -13, 30, -23, 36, -4, 7, 17, -18, + 18, -3, 8, 5, -1, -13, -15, 2, -5, -16, 7, -52, 23, -38, 30, -30, + 16, -26, 21, -22, 24, 3, 20, -28, 22, 22, -31, 42, -16, -11, 32, -26, + 0, 31, -14, 11, -15, 14, -17, -9, 10, 11, 27, -38, -4, 14, -18, 36, + -44, 0, -11, 16, -14, -2, 16, -34, -23, 22, 4, -24, 14, -13, 16, 31, + -28, -10, -6, 51, -27, 13, -49, 3, 68, -38, 1, 8, -27, 26, -16, 0, + 15, -36, 7, -6, 38, -11, 0, -14, 10, -4, 22, -48, 31, -1, 23, -38, + 1, 15, -7, 10, -1, -3, 4, -1, 10, -2, -12, 3, -22, 5, 9, 8, + 4, -14, 12, -3, -7, 22, -20, 3, -6, 13, -15, -8, -7, 16, -14, -1, + -3, 6, -17, 12, 22, -44, 68, -67, 50, 13, -20, -11, -4, -20, -3, 22, + -13, -20, 28, -7, 2, 11, -9, -23, 5, 5, -26, 24, -31, 2, 20, 15, + 2, -7, 4, 19, -6, 41, -51, -3, 24, 27, -30, 25, -37, 1, -7, -2, + -4, -26, -1, 12, 5, -12, 9, -30, 5, 11, 26, -18, -32, 42, 7, 0, + -23, 10, 10, -20, 53, -49, 6, -39, 18, 3, -27, 41, -21, 16, 28, 14, + -24, -15, 19, 5, 16, -31, -1, 45, -25, -6, -16, -4, -19, 37, -47, 21, + 2, -14, -7, 30, -35, 13, -30, 14, 21, 11, -18, -28, 37, 12, -18, 9, + 5, -1, 33, -41, 3, -7, -19, 8, -14, 12, 15, -18, -4, 44, -25, 22, + -46, 19, 40, -25, -12, -5, 17, 7, -53, 25, 4, -10, 14, 16, -31, 40, + -27, -11, -4, 28, -40, -5, -9, -3, 34, -47, 33, -5, 11, -33, 33, 0, + -14, 35, -18, -27, 11, 14, -37, 35, -20, 7, 15, 2, 27, -17, 15, -31, + -1, 11, -27, 24, -26, 14, 13, -35, 20, -13, -2, 16, 16, -6, 2, 15, + -7, -22, 51, -36, -2, 20, -19, 23, -20, -19, -9, -14, 8, -4, -13, 35, + -66, 36, -37, 3, 19, -1, 15, 32, -45, 71, -15, -5, 12, 34, -33, 24, + -5, 20, -43, 42, -59, 13, -12, -69, 66, -29, -34, 17, 7, -28, 24, 5, + -27, 51, -40, -9, 46, 3, -17, 36, -56, 63, -7, -31, -19, 53, -12, -10, + 4, 19, -47, 35, 0, -40, 17, -14, 13, -11, 11, 3, -39, 22, 5, 21, + -19, -11, 25, -4, -5, 20, -13, 25, -6, -16, -16, 29, -61, 25, -33, 12, + -17, 7, -19, 34, -27, 15, -19, 32, -26, 54, -46, 6, 9, 14, -6, -6, + 23, -32, 58, -19, -5, 15, 46, -42, 39, -7, -23, -7, -14, -22, 42, -66, + 0, 4, -8, -11, -4, -3, -7, 7, -23, 30, -14, 19, 8, -9, 20, 36, + 5, -24, 25, 12, -20, 16, -53, 60, -49, -26, 24, -87, 67, -49, 13, -7, + 5, -14, 5, 11, 38, -3, -15, 27, 26, -36, 20, 30, -47, 29, -5, 9, + -10, 38, -65, 47, -49, -4, -10, -6, 1, -1, -28, 16, -14, 3, -14, 27, + -8, 1, 2, 23, 21, -53, 40, 24, -16, -12, -2, 11, 17, -8, -18, 8, + -25, 28, -10, -12, 13, -51, 10, 35, -10, -8, -9, 8, 10, 14, -20, 4, + -9, 37, -5, -2, 2, 4, -9, -5, 16, -16, -23, 13, 7, -9, 14, -49, + 13, 8, -3, -13, -9, 22, -8, 12, -13, 36, -36, 35, -17, 23, -12, 0, + -37, 50, -31, -8, -31, 43, -4, -11, 0, 3, -7, -19, 16, -16, -28, 46, + -28, 27, -13, 33, -21, -1, 39, -13, 3, -4, 4, -39, 74, -30, -17, 33, + -3, -20, -12, 24, -94, 75, -63, 54, -62, 23, 4, 12, -33, 22, -35, 16, + 12, -28, 34, 2, -12, -3, 22, 23, -31, -6, 26, 4, -41, 8, 37, -15, + 21, -7, 18, -51, 42, -27, 35, -45, 35, -30, 18, 9, -20, 1, 18, -12, + -51, 61, -61, 24, -20, 1, 11, -5, -2, -12, 11, 20, -35, -2, 37, -21, + 23, -15, -2, 19, -51, 82, -50, 20, 29, -26, -34, 49, -2, -16, 11, -17, + -4, 6, 15, -35, 13, -15, -10, -17, 15, 4, -42, 43, -31, 34, -30, 53, + -43, 40, -22, 9, 9, -24, 64, -41, 29, -17, 8, -15, 8, 2, -27, 7, + 10, -28, 0, 30, -50, 6, -13, -14, -21, 11, 9, 13, -47, 35, -11, 32, + 28, -28, 1, 32, 2, -19, 28, -24, 9, 0, 19, -6, 16, -33, 6, -23, + 33, -31, -1, -4, 26, -22, -22, -10, -11, 18, -26, 19, -8, -4, 21, -14, + 36, -2, 12, -48, 49, -1, -13, -5, 8, -3, 9, -4, -18, 15, 28, -50, + 10, 4, -7, 4, -39, 37, -39, 11, 2, -20, 13, 4, -6, 0, 35, -17, + -9, 6, 38, -21, -1, -1, 12, -2, -16, 15, 7, -22, 18, -23, 11, 3, + -9, -39, 29, -31, 44, -41, 0, 5, 21, -9, -25, 25, -6, 38, -55, 38, + -14, 6, -26, 38, -24, 39, -39, -15, 17, 16, -20, -27, 17, 24, -20, -20, + 33, 8, -31, 2, 2, 27, 11, -4, -7, 31, -20, -9, 4, -4, 17, -32, + 2, -18, 31, -35, 38, -52, 42, -1, -28, -26, 25, 3, -51, 42, -35, 35, + -39, 44, -38, 20, 20, -51, 34, 45, -10, -7, 27, -19, 33, -49, 22, 2, + -7, -5, -27, 59, -24, -20, 21, -8, -15, 24, -51, 3, 9, -23, 24, -30, + 2, 29, -26, -2, 4, 10, 0, -18, 50, 3, 9, -14, 17, -18, 24, -13, + -33, 7, 25, -50, 2, -2, 30, -58, 31, -8, 23, -11, -1, -24, 21, 1, + -41, 47, -30, 28, -39, 56, -16, -20, 51, -45, 33, 6, 23, -12, -19, -2, + 7, 1, -14, -5, -11, -20, 25, -17, 7, -22, 21, -19, 34, -47, -2, 1, + 33, -30, 14, 20, 6, -9, 17, 13, -22, 19, -58, 23, 26, -15, -52, 2, + 18, 10, -13, 46, -5, -8, -6, 4, -14, 5, 11, -13, -7, 42, -25, 8, + -37, 35, -10, 6, -25, 16, 15, -15, -9, -20, 18, -23, 26, -34, 35, -22, + -10, 9, 14, -6, -21, 27, -8, 4, 1, 3, -19, 28, 2, -7, 30, -8, + -13, 11, -9, -9, -19, 12, 0, -23, -1, -23, -6, 27, -31, 41, -28, 13, + 5, 9, -21, 6, 2, -2, 18, -16, 31, -25, 40, -38, 39, -13, 8, 14, + -3, 9, -30, 6, -12, -7, -15, 30, -64, 6, -22, 13, -8, 14, -40, 9, + 32, -35, 14, -1, 12, -25, 63, -25, 35, -2, 19, -5, -3, 20, -29, -1, + 35, -37, 53, -46, 4, -14, 22, -27, 23, -64, 8, 5, -25, 41, -18, 14, + -42, 53, -56, 35, -42, 71, -63, 45, -38, 29, -12, 33, -22, 0, 24, -13, + 3, 13, 1, -10, -19, 11, 19, -38, 5, -2, -18, -21, 33, -54, 41, 9, + 4, -1, -21, 3, 3, 37, -31, 34, -40, 34, -19, 30, -26, 23, -53, 55, + -8, -13, -16, 7, -13, 46, -38, 2, -3, 17, -1, -26, 18, -57, 68, -27, + 23, -19, 32, -39, 2, 2, -18, 12, -16, 4, -23, 38, -65, 40, -5, 13, + 19, -26, -13, 60, -25, 7, 1, 10, 22, -24, 23, -20, -16, -17, 14, -32, + 26, -4, 17, -15, 9, -29, 4, -29, 11, 36, -18, -19, -2, 5, 28, -23, + 31, 6, 4, 18, -14, 4, -7, 0, -45, 61, -31, 5, -15, -23, -21, 52, + -62, 4, 22, 1, -9, 15, -24, -27, 60, -49, 38, 0, -6, 1, 13, 7, + 4, 19, 6, 0, 27, -28, -14, -21, 17, -1, -30, 23, 10, -36, 18, -19, + 2, -18, 0, 6, -1, 7, -1, -37, 26, 15, -35, 41, -24, 10, 10, -9, + -12, 12, 7, 3, 10, -11, 11, -14, 27, -49, 71, -55, 25, 8, -11, 11, + -5, -22, 7, 15, -17, -11, 18, 4, -54, 43, -38, 27, -1, 7, -13, 19, + 10, -41, 50, -41, 13, 9, 10, -41, 38, -13, 13, -2, -2, -4, 9, -36, + -5, 22, -31, -18, 8, 21, -22, 21, -24, 12, 3, 16, -24, 25, -16, 22, + -35, 14, 3, 11, 12, -22, 40, -11, -25, 14, 0, 14, -2, 2, -10, -12, + 14, -51, 11, -21, 55, -27, 9, 3, 38, 7, -25, 5, -19, 6, -14, 0, + -10, 21, -57, 35, 18, -21, 21, -40, -13, 24, -24, -12, 10, -1, 11, 10, + -12, -5, 38, -45, 23, 26, -13, -9, 32, 6, -3, 30, -28, -28, 27, 3, + -10, -11, -10, 16, -28, 21, -12, -3, -1, -33, 14, -30, 12, -20, 40, -15, + 7, 19, -18, -1, -1, 9, 4, -23, 32, 17, -19, 12, 16, -45, 4, -6, + 18, -28, 36, -44, 44, -29, 10, 4, 14, -8, -13, 9, -30, 39, -17, -5, + 10, -10, 5, -1, -16, 17, -7, -9, -10, 15, -21, 9, 10, 8, -10, -6, + 3, -21, 34, -3, 6, -4, 15, 3, -2, 4, 26, -44, 30, -43, 2, 9, + -5, -7, -18, 16, -28, 0, 5, -7, 0, 7, 0, -7, 21, -14, 17, 15, + 2, -40, 7, 44, -30, 55, -33, -19, 40, -30, 17, -1, -20, -20, -20, 5, + 14, 1, -7, -32, 26, -11, -11, 24, -23, 17, 17, 8, -19, 18, 11, -6, + 17, -4, -13, 14, -9, 21, 9, -16, -8, 2, -16, 3, -9, -32, 6, -36, + -4, 0, 10, -36, 26, -11, 3, 31, -20, 1, 7, 4, 45, -35, 39, 0, + 4, 28, -21, 29, -39, 27, 15, -6, -14, 17, -25, -33, 16, -15, 18, -43, + 28, -61, 33, 1, -27, 13, -19, -20, 26, 11, -27, 16, -21, 33, -13, 43, + -44, 13, 24, -10, 35, -39, 36, 20, -39, 68, -68, 23, -16, -7, 0, 36, + -30, -13, -27, 42, -21, -4, -23, -2, 23, 0, -3, -3, 2, 4, -15, -5, + 28, -10, -20, 24, -7, 27, -58, 31, -7, -29, 39, -40, 41, -35, 8, -25, + 30, 31, -17, -9, 3, 36, -8, -18, -11, 29, -2, 6, -25, 21, -5, -8, + -17, -24, 20, -26, 20, -23, 46, -26, -13, 8, 13, 2, -15, 4, -9, 28, + -25, -19, 49, 18, -50, 45, -11, -17, 5, -61, 15, 4, -22, -1, 22, 23, + 33, -55, 46, -25, 37, 18, 2, -9, 11, -47, 23, -8, -25, 37, -32, 2, + 5, 12, -18, -5, 19, -27, -7, 20, -40, 32, -44, -21, -29, 58, 8, -9, + 57, -28, 29, -32, 14, -14, 4, 23, -33, 16, -4, -16, 21, 38, -37, 23, + 10, -32, 17, 17, -12, -59, 9, -3, -12, 22, -13, -8, -26, 16, 1, 33, + -9, -17, 16, -7, 21, -44, 26, 5, 35, -36, -1, 13, 36, -36, 39, -36, + 17, -13, 2, -33, 20, -13, -51, -2, 9, -2, 35, -21, 19, -20, 18, -19, + -5, 30, -39, 30, 22, -35, 74, -52, 33, -15, 17, -21, -13, 11, 6, -25, + 25, -31, 29, -18, 18, -52, 40, -11, -17, -26, 56, -56, 69, -53, -14, 32, + -10, -8, -2, 18, -14, 20, -18, 20, 22, -27, 0, -25, 56, -46, 16, -28, + 52, -5, -33, 76, -75, 36, -1, -42, 42, -46, 13, -13, 25, -7, 35, -55, + 5, 63, -56, 11, -24, 13, -8, -10, -27, 15, -15, 44, -66, 52, -3, -6, + 0, 23, -33, 79, -55, 30, -27, 37, -18, -6, -2, -19, 52, -22, -50, 60, + -32, 28, -56, 44, -28, 15, -37, -9, -28, 63, -75, 9, 39, 28, -21, 5, + -17, 15, 2, -13, 30, 13, -14, 10, -12, 30, -22, -10, 4, -8, -9, 14, + 6, -39, 34, -6, 4, 1, -5, 0, 33, -73, 34, -12, 23, -9, 53, -47, + 17, 3, -18, -6, 2, -19, -12, -7, -45, 72, -9, -71, 55, -58, 50, -18, + -36, 37, 19, -11, 13, -35, 32, 6, 5, 18, -6, 19, -26, 32, 16, 20, + -43, 20, -10, -7, 16, -7, -68, 21, -36, 7, 19, -22, 19, -3, -35, -37, + 25, 21, -57, 67, -9, 9, 32, -11, 28, -18, 35, -41, 60, -19, 29, 0, + -38, 29, -6, -35, 0, 25, -37, -1, -31, -42, 30, -19, -21, 36, -66, 53, + -33, 15, 16, -13, 20, -35, 73, -4, 18, 39, 4, 1, 3, 21, -2, -12, + -18, -51, 44, -17, -50, 48, -30, -16, -13, -35, -7, 25, -33, -14, 14, 0, + 8, -30, 45, -13, 50, -53, 28, 60, -33, 23, -7, -2, 15, 36, -11, 9, + 19, -44, 4, -21, 19, -5, -27, -45, 48, 9, -47, -23, 12, 3, -25, -8, + -21, 63, 1, -29, 31, -18, 19, 16, -24, -17, 50, -65, 65, -56, 93, -45, + -17, -25, 45, -18, 23, -53, 50, -15, -12, -39, 51, -11, 11, 13, -31, 54, + -14, -29, 22, -11, 10, -41, -19, 52, 10, -51, -60, 72, -13, 12, -38, 19, + -2, 31, -56, 37, -4, -10, 22, -14, -33, 48, -40, 38, -14, 27, -24, 19, + 29, 17, -31, -2, -41, 34, -17, 2, 5, 5, -13, -30, 14, 9, -9, 7, + -11, 15, 5, -28, -2, 0, 45, -30, -25, 1, 10, 29, -55, -24, 52, -5, + 5, 20, -25, 20, -15, 14, -64, 95, -53, 32, 13, -26, 31, -8, -27, 18, + 48, -57, -3, -10, 25, -24, -32, -9, 18, 18, -33, -15, 27, -22, 14, -5, + 10, 51, -21, -25, 19, 5, -15, -29, 16, 1, 33, -39, -12, 56, 14, -63, + 36, -2, -17, 52, -11, -37, 5, 19, -52, 38, -23, -60, 93, -75, 52, -30, + -2, -11, 49, -11, -25, 1, 42, -35, 26, -35, -9, 24, -1, 10, -6, -12, + 7, 4, 22, -10, 41, -25, -8, -4, -2, 28, -43, 19, -32, 4, -27, 9, + -47, 51, -16, 12, -52, 49, 8, 7, -37, 27, -33, 80, -44, 6, 5, 28, + -15, 16, 15, 2, -12, 50, -77, 38, -38, -45, 30, 8, -37, -13, -8, -18, + 50, 3, -54, 29, 29, -20, 4, 52, -57, 62, -52, -2, -9, 62, -64, -5, + 24, 23, 0, -7, -23, 48, 25, -78, -9, 38, 18, -46, 30, -51, 39, 4, + -48, 22, 15, 13, -39, 8, 10, 31, -20, -22, 21, -17, 17, -23, 22, 22, + -24, -36, 11, 31, -16, -28, 34, -4, 0, -20, 6, -2, 35, -13, -60, 36, + 24, -45, 21, -2, 36, 0, -73, 66, -37, 39, -66, -18, 22, 17, -17, -25, + 24, 36, -47, 3, 25, 7, 8, 0, 1, 14, 20, -21, 4, 21, 12, -77, + 17, -4, -12, 31, -57, 38, -11, -4, -31, -6, 29, -34, 11, 13, -20, 82, + -36, -36, 40, -28, 77, -68, 12, 2, 34, -23, 5, -31, 11, -5, 44, -105, + 79, -31, -29, -16, 37, 8, 18, -14, -9, 32, -10, -11, -7, 0, 41, 34, + -56, 7, 13, -2, -31, 33, -67, 42, -31, -2, 22, -49, 18, -34, -11, 38, + -40, 56, -16, 14, -2, 24, 0, 0, 41, -21, -8, 6, -11, 11, 11, -45, + 26, 4, -17, -7, -26, -30, 7, -21, -29, 56, -29, 37, -3, 2, -8, -3, + 22, 11, 40, -13, 58, -6, -38, 48, -23, 15, -52, -14, -6, 49, -66, -20, + -11, 34, -32, -44, 41, 4, 20, -59, -24, 77, 23, -24, -17, 42, 19, -3, + -19, -34, 54, 17, -22, -17, 46, -24, -9, 3, -22, 40, -47, -49, 72, 4, + -18, -48, -33, 55, -4, -41, -51, 105, -26, -3, -22, 64, 28, -51, 31, 2, + 15, 27, -62, 18, 21, 6, -15, -54, 52, -14, -46, 7, -30, 32, -1, 6, + -37, 39, -3, -23, -20, 24, 23, 17, -25, -6, 67, -36, -11, -37, 56, -79, + 3, 30, 45, -39, -17, -2, 21, 2, -4, -3, 3, 1, 16, -16, 9, 30, + -37, 8, -6, 46, -65, 3, 14, -59, 104, -60, 2, 46, -29, -30, -2, -10, + 24, -52, 63, -31, 81, -85, 18, 35, 16, -32, -18, -24, 45, -16, -15, -13, + 37, -15, -20, -42, 91, -45, -15, -9, -16, 64, -11, -23, 31, -18, 38, -42, + 3, 12, 1, 5, -5, 22, -44, 69, -31, -18, 15, 21, -64, -13, 34, -37, + 30, -26, -15, 6, -3, 44, -28, 11, -3, -1, 16, -18, 25, -14, -26, 69, + -56, -5, 31, -51, 24, 3, -36, 9, 52, -34, 31, 21, -11, -68, 31, -24, + 53, -25, -29, 31, 23, -20, 9, -15, -11, 19, 12, -47, 84, -60, -16, -11, + 17, -4, -15, 30, -45, 32, 34, -63, -7, 68, 0, -35, 17, 7, 33, -31, + -8, 7, -32, 43, -13, -18, 15, 31, -32, -34, 5, 8, -16, 20, -26, -29, + 32, -9, -20, 17, 33, -31, -13, -5, 86, -52, 23, -19, 2, 13, 14, -7, + -20, 36, -16, -3, 8, 0, 14, -69, 76, -77, 25, -14, -17, 3, 39, -14, + -46, 31, -2, -7, 37, -45, -6, 24, 28, -37, 22, 13, -35, 4, 8, 23, + 7, -43, 53, -59, 23, 16, 4, -25, -15, 23, -9, -20, 26, -18, -1, 25, + -3, -48, 53, 2, -43, 7, 14, -34, 15, 28, -33, 53, -2, -59, 31, -34, + 40, 19, -27, 20, -2, 8, 2, 3, -8, -8, 4, -57, 62, 24, -72, -4, + 17, -17, -3, -10, -26, 42, -30, 12, -29, 31, -10, 3, 24, 2, 21, -1, + -36, 52, -7, 21, 14, -32, -18, 73, -45, -6, 8, -12, -66, 21, 25, -17, + -6, -35, -14, 27, 26, -47, 40, -51, 56, -19, -24, 31, 6, 4, 11, -3, + 37, -47, 41, -32, 50, 0, -72, 25, 16, -19, -1, -2, -4, -41, 20, 6, + 9, -3, -44, 32, -54, 83, -30, -26, -8, 46, -47, 29, 5, -19, 37, -9, + -20, 65, -14, -21, -4, 10, 28, -28, 18, -29, 35, -25, 3, -17, -31, 4, + -4, 0, -9, 41, -42, -34, 40, -15, 8, -24, -8, 36, 22, -18, -27, 70, + -39, 39, 1, -5, 57, -54, 12, 36, 3, -13, -1, -32, 69, 6, -64, -50, + 13, -13, -34, 22, -13, 0, -10, -38, 41, -11, -22, -3, 11, 4, 38, 22, + -10, 24, 32, -23, 23, -6, 8, -4, 21, -61, 66, -35, -41, 7, 5, -29, + -19, -45, 23, -2, 46, -84, 78, -59, 40, -10, -18, 79, -35, -5, -1, 36, + 16, 13, -21, -31, 52, 2, -50, 34, -5, -36, -37, 65, -42, 1, 16, -42, + 35, -8, -50, -6, 41, -16, 27, -41, 22, 64, -50, -11, 31, -18, -17, 5, + -3, 34, 34, -40, -41, 66, -37, 20, -11, -20, 29, -5, -14, -15, 45, -33, + -37, -11, 36, -25, 18, -8, 20, 1, -23, 60, -32, 0, 34, -24, -32, 64, + -39, -35, 48, -7, -13, 4, -39, 32, 0, 1, -31, 2, -12, 43, -38, -8, + 26, 0, -57, 53, 19, -22, -10, 17, -30, 57, 6, -31, 33, 10, 0, -48, + 29, -4, -23, 6, -7, 31, -39, 15, -41, 38, -19, 5, -37, 23, 11, -28, + -14, 59, -48, 8, 22, -20, 50, 15, -34, -26, 67, -8, -15, -21, 53, -27, + -9, 13, -24, -35, -10, 9, -15, -13, 18, -38, 28, 22, -14, 2, -22, 42, + -20, 22, 12, -20, 45, -16, 17, -16, 22, 34, -27, -13, -7, 1, -21, -1, + 13, -44, 36, -51, -8, 16, -7, -30, -46, 90, -54, 35, 1, 11, 9, 5, + 1, -19, 20, 11, 21, -1, -49, 41, -6, 0, 37, -74, 9, 20, -12, -47, + 65, -68, 28, -5, -26, 15, 14, -3, -23, 8, 18, -22, 13, 3, 31, -21, + -5, 8, 24, -21, 48, -20, -21, 41, -43, 4, 18, 21, -60, 9, -27, 1, + 13, -15, -33, 15, 23, -48, -8, 53, -50, 1, 6, -40, 90, -10, -15, 51, + -52, 53, 29, -68, 50, 52, -30, -21, 7, -1, -8, -29, 11, -47, 6, 18, + -12, -25, 53, -34, -23, -6, 19, -7, -13, 7, 5, -2, 14, 11, -15, 51, + -29, 6, 12, 20, -27, 29, -12, 4, -18, -5, 2, -17, 10, -19, 2, -8, + -5, 56, -82, 49, 0, -42, 48, -25, 19, 6, -41, 17, 35, -18, -17, -29, + 26, 10, 4, -24, 26, -35, 47, -36, 2, 2, -23, 27, -42, 55, 0, -21, + 19, 21, -8, 1, -3, -15, 7, 12, -23, -29, 47, -12, 4, -28, 17, 16, + -7, -31, -8, 25, -6, 0, 13, -20, 6, 3, -7, 19, -21, -37, 27, 41, + 7, -14, 12, -59, 57, 6, -49, -2, -8, 0, 19, 13, -20, -5, 16, 23, + 4, -15, -33, 14, 2, 15, -26, -28, 10, 45, -17, -24, 14, 17, -39, 22, + -8, 48, -51, -1, -16, 52, -34, -21, 11, 13, 18, -57, 26, 15, 27, -36, + -12, 40, -7, -14, 15, -86, 91, -20, -13, -7, 53, -43, 33, -25, 13, 3, + -38, -19, 28, 28, -18, -74, 58, -3, 40, -27, -34, 30, 28, -1, -22, 2, + 9, -8, -12, 12, 21, -35, -2, -17, 17, 2, -27, 22, -36, 38, -11, 2, + -20, 7, 20, -29, 39, 11, -3, 9, -24, 47, -36, 28, -14, -16, 38, -37, + 12, -15, 18, -69, 56, -31, 17, -16, -18, -13, 21, -6, -9, -25, 37, 6, + -1, -2, 5, -1, -26, 39, 6, -3, -10, 0, 12, 30, -12, -31, 24, 13, + -14, 9, -23, 31, -43, -17, -2, 13, -23, -14, -21, 21, 19, -22, -12, 24, + 41, -26, 10, 12, 19, -3, 9, -12, 26, 12, -52, -4, 16, -3, 0, -43, + 7, 5, -14, -9, 12, -28, 15, -23, -2, 35, -12, -8, -10, 24, 57, -55, + 26, -18, 19, 44, -30, 0, -5, 50, -56, -1, 8, -5, -39, 9, 19, -39, + 38, -73, 30, -1, 2, 16, -24, 6, 29, -71, 70, -18, -6, 8, 31, 4, + -13, 23, -11, 31, -56, 57, -25, 10, 15, -44, -10, 16, -17, -44, 18, -28, + 10, 8, -21, -4, -9, 28, 20, -16, 17, -17, -6, 30, 0, 11, -21, 25, + 25, -1, 31, -56, 31, 14, -32, 2, -19, 4, -17, -26, -13, 42, -59, 15, + -29, 53, -4, 1, -23, 13, 31, 5, -22, 3, 30, -28, 2, -24, 37, 1, + -3, -18, 18, 41, -40, 3, -40, 48, -31, -5, -20, 5, 9, 0, -30, -1, + 26, -15, -5, -6, 51, -25, -27, 7, 44, -11, 10, -32, 14, 46, -31, 6, + -11, 37, -33, -14, 19, -4, 22, -50, 26, -45, 21, 1, -23, 10, -15, 17, + -63, 53, -14, -18, 56, -49, 21, 25, -7, 4, -21, 52, -33, 19, 3, 11, + -9, -7, 0, -49, 22, -17, 25, -10, -11, 5, -19, 35, -26, 20, -7, -21, + 37, -25, 29, -23, 3, 6, 17, -26, 27, 5, -16, 10, -9, -24, 11, -4, + -17, 9, -5, -13, 1, -2, 10, 5, -13, 21, 0, 8, 9, -22, 12, 13, + -24, -3, -22, 42, -18, 3, -4, -15, 1, -2, 8, -17, -13, -2, 1, 23, + 10, -2, -31, 23, 17, -15, -9, -24, 31, 2, 19, -24, 4, -22, 28, -5, + -20, 34, -57, 26, 71, -51, 28, -24, -12, 28, 10, -35, -4, -6, 7, -7, + 8, -52, 61, -52, 7, -9, -21, 9, 18, -19, 3, 34, -53, 56, -29, 20, + -11, 22, 4, -1, 23, 2, 1, 24, -15, 3, -32, 13, 21, -37, 6, -11, + -25, 22, 7, -2, -41, 4, 10, -30, 39, -24, -7, 8, 12, 9, -1, -35, + 13, 3, 9, -18, 21, 26, -14, 41, -8, -35, 31, -29, 17, -20, -12, 20, + -30, 27, -26, 21, -9, -6, 5, -14, 3, -11, 15, 2, 8, -14, -5, 20, + 4, 0, -31, 9, 4, 25, -24, 5, -5, -13, 27, -7, -32, 1, -5, -10, + 28, 7, -4, 11, 10, 22, -3, -22, -15, 6, -3, -3, -27, -25, 5, 8, + -10, -17, 18, -18, 12, 32, -18, 1, 25, -25, 50, 7, 2, 0, -3, -3, + 16, -20, 9, -14, -15, 21, -27, -3, -17, 23, -31, -4, -18, 31, -21, 6, + 0, 18, -16, 27, 3, -7, -17, 17, -15, -11, 19, -16, 6, 1, 12, -18, + 5, -6, 24, 0, -19, 22, -23, 43, -35, 18, 22, -40, 1, 12, -4, -18, + 26, -53, 34, 1, -10, 1, -18, 27, -25, -24, 33, -31, 9, -43, 53, -29, + 33, -17, 5, 23, -7, 2, 23, 29, 1, -8, 20, -10, -1, -22, -3, -17, + 4, 22, -61, -23, 31, -26, -29, -12, 2, -3, 12, 10, 26, 5, -29, 61, + -9, 32, -18, -14, 29, 31, 2, -19, 9, 31, -20, -31, -7, 5, -22, -47, + 31, -40, 15, -39, 22, -27, 40, -78, 31, 4, -19, 33, -13, -8, 41, -1, + 5, -12, 53, -51, 22, -1, 18, 28, -29, -1, 0, 0, 11, 13, -2, -7, + -5, -3, -3, 1, 2, -6, 0, 3, 8, 9, 5, 0, 14, -5, -28, -39, + -39, -36, -37, -27, -43, -49, -13, 4, 6, -7, 0, -1, 3, 23, 39, 29, + 35, 41, 21, 35, 0, 0, 21, 59, 67, 31, 21, 13, -3, 18, 34, 28, + 5, 3, 13, 3, 0, 12, -7, -33, -27, -39, -14, -34, -50, -30, -37, -35, + -53, -74, -70, -61, -62, -62, -50, -44, -61, -36, -3, -23, -15, -12, -17, -20, + -6, 11, -6, -12, -6, -17, 7, 46, 71, 87, 79, 70, 77, 104, 109, 66, + 37, 34, 27, 31, 40, 43, 31, 23, 17, 2, 10, 24, 32, 66, 56, 17, + -13, -55, -54, -21, 19, -19, -56, -77, -37, -27, -10, -6, -38, -36, -37, -3, + 23, 25, 25, 19, 35, 34, -7, -5, 28, 60, 66, 65, 51, 34, 22, 53, + 51, 15, 20, 11, 21, 21, 16, 24, -2, -23, -36, -35, -21, -29, -51, -51, + -47, -57, -85, -80, -70, -100, -97, -82, -78, -76, -64, -51, -56, -54, -49, -70, + -62, -53, -54, -60, -57, -65, -78, -76, -62, -39, 0, 31, 13, 6, 31, 54, + 55, 43, 30, 13, 9, 31, 23, 43, 28, 24, 36, 36, 24, 30, 54, 70, + 113, 103, 75, 4, -3, 40, 55, 50, 23, 9, 25, 29, 48, 41, 29, 14, + 6, 40, 63, 49, 39, 71, 80, 64, 21, 12, 17, 29, 68, 71, 52, 36, + 24, 37, 24, 1, 5, 3, -6, -4, 1, 13, -3, -22, -35, -31, -27, -58, + -59, -43, -55, -71, -76, -71, -88, -103, -95, -98, -85, -77, -68, -71, -58, -50, + -47, -52, -46, -40, -47, -44, -48, -56, -60, -91, -96, -68, -15, -6, -16, 9, + 3, 29, 31, 29, 8, 10, -6, 5, 10, -6, -4, -6, 15, 7, -2, 2, + -5, 30, 91, 107, 74, 8, -3, 14, 27, 32, 26, 17, 21, 18, 34, 49, + 20, -3, 2, 30, 42, 20, 36, 68, 79, 81, 52, 27, 22, 37, 80, 95, + 77, 77, 72, 74, 57, 55, 56, 41, 35, 22, 40, 58, 32, 23, 24, 26, + 0, -7, 6, -2, -16, -26, -31, -45, -46, -64, -77, -79, -73, -72, -75, -59, + -49, -56, -35, -48, -44, -50, -43, -59, -58, -40, -78, -119, -123, -95, -73, -40, + -52, -45, -29, -18, -3, -1, -11, -21, -28, -12, -24, -29, -21, -29, -16, -3, + -5, -30, -40, 1, 69, 96, 78, 31, 14, 23, 17, 19, 33, 20, 9, 9, + 45, 50, 14, 3, 12, 13, 16, 7, 14, 35, 54, 75, 56, 24, 1, 18, + 47, 47, 60, 62, 66, 69, 46, 54, 53, 38, 11, 18, 44, 41, 28, 33, + 37, 22, 14, 15, 13, 13, 1, -1, -13, -6, -11, -38, -33, -47, -40, -46, + -31, -29, -22, -9, -5, -9, 9, 4, -23, -14, -4, -3, -26, -69, -87, -74, + -60, -42, -49, -33, -28, -16, 9, 2, -16, -22, -25, -25, -33, -32, -44, -58, + -41, -11, -19, -51, -77, -43, 24, 47, 49, 34, 21, 5, -9, 5, 18, -10, + -14, 2, 23, 26, -3, -7, -4, 2, -3, -10, -4, -6, 38, 64, 50, 25, + 1, 11, 17, 21, 36, 58, 62, 46, 46, 61, 56, 27, 11, 20, 18, 27, + 15, 31, 26, 23, 17, 7, 16, 0, -9, -10, -3, -8, -14, -25, -36, -56, + -41, -39, -50, -30, -12, -23, -8, 10, 23, 17, -2, 3, 14, 26, 7, -33, + -48, -53, -52, -35, -30, -30, -23, 3, 21, 17, 8, 7, -8, -1, 0, -6, + -29, -50, -26, 10, 5, -38, -64, -41, 5, 22, 49, 63, 38, 20, 13, 26, + 15, -7, -9, -1, 28, 9, 1, -4, -12, -1, -5, -20, -38, -32, 6, 38, + 36, 16, 10, 0, -8, -13, 15, 41, 25, 30, 30, 52, 35, 17, 8, 3, + -5, -5, -6, 4, 7, 4, 4, 3, 3, -20, -25, -23, -28, -22, -18, -47, + -50, -54, -62, -67, -62, -48, -43, -44, -31, -10, 17, 10, -8, 1, 22, 24, + 17, -1, -21, -40, -39, -26, -38, -32, -21, 2, 17, 26, 29, 18, 5, 15, + 35, 19, -11, -37, -9, 33, 17, -6, -30, -23, -10, 22, 65, 73, 71, 47, + 57, 66, 38, 15, 16, 23, 34, 35, 27, 10, 11, 21, 32, -4, -26, -29, + 4, 29, 28, 38, 32, 17, -6, -6, 17, 32, 21, 31, 39, 49, 36, 27, + 25, 13, -1, -11, -8, -1, -15, -11, 4, -7, -9, -14, -38, -46, -35, -31, + -43, -53, -54, -72, -84, -88, -86, -79, -73, -86, -69, -40, -16, -23, -28, -13, + -9, 5, 5, -10, -34, -45, -48, -52, -61, -59, -42, -38, -9, 13, 19, 8, + -14, 18, 42, 28, -18, -31, -3, 11, 21, 13, -9, -17, -22, 9, 57, 71, + 62, 68, 83, 82, 65, 38, 38, 31, 52, 57, 45, 23, 25, 51, 56, 21, + -2, -8, 7, 21, 28, 55, 55, 37, 15, 17, 30, 30, 30, 48, 55, 65, + 55, 54, 61, 42, 24, 22, 13, 6, 6, 4, 4, 17, 19, 1, -20, -23, + -25, -27, -26, -44, -44, -62, -79, -91, -83, -76, -99, -104, -87, -63, -51, -40, + -42, -40, -29, -16, -6, -31, -40, -47, -63, -68, -81, -76, -81, -75, -49, -15, + -5, -34, -38, 2, 15, 8, -29, -43, -33, -18, -11, 8, -9, -42, -45, -14, + 25, 33, 41, 54, 67, 75, 71, 46, 30, 23, 52, 55, 38, 20, 25, 53, + 59, 35, 17, 6, 3, 5, 27, 64, 61, 49, 40, 40, 45, 36, 38, 63, + 69, 69, 77, 85, 78, 76, 63, 48, 38, 42, 28, 15, 30, 35, 41, 27, + 14, 0, -4, -2, -14, -16, -15, -35, -65, -63, -56, -64, -80, -94, -77, -71, + -46, -34, -42, -37, -21, -6, -5, -16, -20, -35, -44, -62, -66, -66, -96, -94, + -58, -26, -32, -44, -50, -14, 2, -9, -26, -41, -53, -49, -27, -5, -28, -59, + -65, -47, -20, -11, 7, 15, 28, 51, 57, 32, 7, 2, 30, 32, 15, 0, + 7, 30, 30, 24, 21, -2, -19, -20, 6, 37, 40, 31, 40, 45, 30, 29, + 35, 49, 52, 69, 74, 78, 89, 79, 72, 62, 60, 51, 37, 29, 29, 42, + 51, 46, 30, 32, 18, 2, 8, 13, 15, -13, -35, -35, -38, -40, -53, -71, + -70, -58, -34, -38, -32, -28, -9, 10, 10, 7, 11, -7, -28, -21, -26, -47, + -80, -84, -49, -18, -28, -38, -32, -8, -4, 4, 3, -23, -46, -44, -19, -5, + -22, -42, -55, -56, -35, -25, -12, -8, 11, 43, 51, 33, 1, 0, 24, 18, + 1, -5, 0, 1, 9, 15, 21, -2, -38, -36, -19, 2, 2, 19, 26, 19, + 20, 10, 11, 20, 31, 37, 49, 62, 64, 61, 60, 61, 50, 51, 32, 10, + 16, 27, 31, 33, 33, 36, 7, -6, 3, 14, 12, -10, -21, -40, -34, -33, + -47, -65, -67, -60, -40, -40, -44, -25, -10, -4, 14, 26, 22, 4, -7, 8, + 8, -22, -67, -65, -33, -19, -24, -20, -18, -8, 1, 26, 30, -2, -22, -25, + -6, 5, -1, -13, -38, -43, -31, -21, -16, -16, 9, 47, 61, 35, 22, 22, + 31, 24, 10, 13, 5, -2, 0, 28, 34, 1, -21, -30, -28, -18, -5, 5, + 18, 20, 14, 6, 6, 12, 9, 20, 33, 39, 51, 51, 42, 51, 51, 48, + 20, 9, 7, 5, 7, 15, 28, 19, -1, -16, -15, -4, 4, -16, -30, -41, + -45, -41, -50, -79, -77, -69, -65, -64, -56, -45, -40, -28, -4, 21, 17, -8, + -9, 21, 16, -18, -56, -58, -44, -39, -24, -22, -28, -22, -4, 29, 31, 13, + -9, -16, -3, 11, 13, 1, -18, -33, -15, -11, -23, -22, 11, 52, 58, 50, + 46, 50, 49, 36, 40, 40, 17, 6, 20, 37, 45, 29, 9, -7, -12, -11, + -6, 9, 30, 25, 26, 26, 17, 19, 15, 21, 24, 46, 55, 47, 43, 56, + 64, 52, 33, 25, 13, -3, 2, 10, 21, 26, 4, -15, -16, -13, -2, -11, + -32, -43, -37, -44, -61, -77, -78, -82, -82, -80, -71, -61, -72, -59, -21, 5, + -2, -27, -10, 15, 7, -14, -44, -59, -67, -55, -37, -38, -50, -45, -23, 5, + 23, 9, -6, -19, -15, 5, 14, 2, -22, -22, -10, -17, -35, -38, -3, 35, + 38, 43, 57, 51, 44, 49, 57, 46, 25, 14, 24, 35, 54, 41, 31, 22, + 1, -7, -4, 12, 23, 34, 37, 35, 35, 36, 26, 24, 33, 55, 62, 53, + 58, 70, 70, 73, 62, 51, 38, 14, 6, 20, 31, 32, 27, 4, -9, -1, + 9, -8, -21, -22, -27, -33, -53, -64, -67, -82, -86, -83, -67, -75, -97, -77, + -36, -15, -27, -32, -18, -1, -1, -6, -31, -62, -73, -68, -52, -52, -68, -69, + -50, -21, -2, 4, -10, -33, -29, -4, 2, -10, -29, -22, -8, -27, -55, -49, + -27, -6, 12, 31, 43, 31, 38, 44, 54, 48, 25, 11, 19, 30, 36, 41, + 41, 29, 11, -1, -9, 0, 15, 27, 34, 36, 46, 46, 26, 27, 39, 51, + 59, 62, 62, 73, 76, 77, 85, 78, 58, 35, 23, 21, 37, 53, 37, 22, + 15, 16, 20, 3, 0, -2, -2, -14, -33, -35, -45, -69, -77, -59, -53, -76, + -96, -74, -41, -30, -25, -26, -19, -4, 7, 11, -8, -40, -62, -62, -51, -55, + -69, -74, -71, -44, -15, -2, -14, -36, -38, -8, -7, -27, -33, -17, -12, -38, + -51, -57, -58, -41, -14, 8, 19, 15, 15, 31, 46, 40, 21, 9, 7, 10, + 20, 25, 33, 28, 16, 1, -18, -13, 0, 6, 12, 30, 39, 39, 26, 20, + 32, 41, 45, 53, 64, 63, 62, 80, 84, 87, 81, 51, 29, 21, 44, 52, + 41, 33, 29, 31, 27, 12, 8, 16, 10, -4, -7, -7, -29, -62, -57, -37, + -44, -68, -81, -70, -48, -33, -23, -22, -17, -5, 16, 31, 14, -15, -33, -42, + -41, -37, -53, -65, -74, -54, -16, 2, -12, -33, -19, -1, -10, -22, -17, -8, + -8, -18, -33, -48, -62, -57, -31, -1, 7, 0, 9, 22, 40, 40, 27, 14, + 4, 3, 10, 14, 21, 31, 20, 0, -13, -19, -17, -15, -7, 12, 29, 28, + 13, 20, 18, 18, 31, 38, 47, 49, 51, 56, 67, 87, 84, 56, 30, 20, + 31, 41, 31, 24, 32, 33, 20, 7, 14, 15, -2, -1, 13, 4, -28, -53, + -45, -34, -38, -59, -75, -72, -58, -44, -26, -26, -29, -8, 14, 34, 28, 10, + -9, -22, -26, -24, -30, -54, -78, -56, -13, -4, -17, -16, -5, 1, -6, -9, + -8, -1, 3, -2, -4, -28, -53, -58, -37, -10, 1, -1, 6, 20, 34, 46, + 40, 25, 19, 11, 7, 10, 23, 33, 28, 16, -3, -3, -17, -31, -14, 4, + 15, 20, 20, 16, 10, 14, 19, 23, 37, 45, 35, 37, 53, 76, 83, 62, + 34, 20, 27, 28, 13, 17, 29, 21, 7, 9, 13, -4, -17, -4, 13, 2, + -27, -53, -47, -39, -46, -56, -77, -87, -77, -58, -45, -46, -47, -33, -6, 17, + 22, 16, 1, -20, -25, -10, -21, -57, -79, -57, -32, -24, -23, -18, -3, -1, + -6, -4, -4, -5, 3, 13, 14, -6, -38, -51, -39, -22, -4, -1, 3, 14, + 32, 45, 46, 46, 33, 25, 15, 9, 28, 38, 32, 28, 26, 14, -9, -21, + -15, -5, 10, 24, 22, 22, 21, 15, 15, 23, 36, 42, 35, 31, 41, 72, + 87, 68, 46, 42, 34, 19, 14, 25, 25, 11, 14, 18, 14, -7, -24, -7, + 12, 4, -19, -41, -47, -44, -41, -52, -74, -92, -88, -72, -59, -63, -68, -53, + -34, -11, 12, 19, -7, -27, -15, -5, -22, -54, -76, -66, -52, -47, -41, -29, + -17, -12, -12, -10, -11, -19, -7, 12, 19, 3, -23, -42, -48, -31, -19, -14, + -6, 1, 20, 35, 39, 50, 51, 33, 16, 17, 30, 31, 32, 41, 39, 28, + 14, -7, -14, -5, 8, 18, 27, 34, 29, 22, 21, 26, 38, 51, 39, 27, + 43, 75, 84, 73, 75, 68, 46, 32, 31, 35, 27, 15, 23, 36, 26, 0, + -13, -4, 12, 14, 1, -23, -36, -36, -32, -36, -60, -83, -84, -70, -67, -70, + -66, -67, -62, -27, 8, 13, -11, -22, -7, 4, -16, -44, -63, -67, -63, -63, + -53, -42, -33, -25, -15, -10, -22, -27, -18, -1, 16, 9, -13, -32, -46, -42, + -31, -30, -24, -8, 5, 11, 25, 49, 50, 33, 25, 20, 21, 24, 29, 34, + 41, 41, 26, 5, -5, -7, -4, 12, 23, 33, 37, 29, 19, 24, 49, 53, + 33, 33, 49, 65, 73, 80, 89, 85, 63, 48, 50, 46, 30, 20, 35, 46, + 39, 17, 0, 2, 15, 23, 18, -2, -20, -24, -12, -19, -45, -60, -66, -70, + -66, -56, -61, -74, -74, -38, 0, 6, -8, -15, 3, 13, -1, -24, -42, -52, + -65, -64, -54, -54, -47, -31, -19, -12, -21, -32, -27, -12, 7, 13, -2, -24, + -36, -37, -44, -47, -32, -20, -18, -9, 12, 30, 38, 35, 26, 18, 17, 16, + 13, 25, 36, 37, 32, 18, 2, -11, -10, -5, 3, 28, 38, 20, 8, 25, + 42, 40, 28, 30, 40, 46, 54, 70, 87, 82, 66, 61, 59, 48, 28, 20, + 32, 43, 43, 24, 8, 1, 7, 23, 25, 3, -13, -9, -8, -15, -28, -40, + -58, -71, -60, -49, -58, -80, -82, -50, -17, -5, -13, -12, 6, 13, 8, -3, + -24, -42, -54, -59, -57, -60, -59, -43, -24, -15, -20, -30, -35, -25, 1, 11, + -2, -12, -18, -33, -48, -49, -41, -37, -32, -21, -8, 13, 27, 27, 27, 23, + 16, 8, 7, 15, 22, 32, 35, 22, 9, 0, -18, -26, -8, 20, 25, 11, + 4, 18, 32, 29, 22, 29, 30, 27, 38, 60, 75, 70, 68, 69, 67, 52, + 30, 19, 27, 36, 40, 34, 10, -2, 6, 21, 20, 4, -2, -4, -7, -9, + -12, -25, -52, -66, -53, -42, -53, -79, -86, -58, -33, -23, -16, -12, 0, 12, + 17, 13, -5, -24, -38, -44, -50, -59, -61, -51, -33, -15, -11, -28, -36, -23, + -4, 5, 5, 7, -3, -17, -31, -40, -38, -37, -36, -29, -14, 4, 15, 25, + 34, 30, 24, 19, 9, 8, 22, 33, 31, 30, 31, 16, -14, -26, -13, 14, + 17, 7, 8, 18, 24, 23, 28, 31, 23, 18, 30, 50, 62, 61, 63, 75, + 73, 59, 40, 23, 20, 30, 43, 35, 11, 0, 8, 15, 12, 6, 3, -6, + -10, -3, -1, -15, -46, -62, -47, -38, -54, -77, -84, -70, -53, -40, -30, -21, + -12, 1, 16, 20, 5, -12, -21, -33, -44, -52, -64, -64, -44, -17, -15, -27, + -30, -26, -15, -3, 6, 12, 9, -2, -17, -26, -29, -36, -41, -32, -21, -10, + 6, 18, 27, 34, 37, 25, 11, 14, 21, 26, 27, 37, 48, 33, -1, -19, + -8, 7, 8, 8, 16, 16, 17, 25, 34, 36, 23, 16, 28, 44, 53, 54, + 61, 74, 79, 75, 56, 30, 19, 31, 45, 35, 15, 9, 9, 9, 11, 9, + 5, -8, -14, 0, 9, -10, -40, -53, -44, -38, -51, -72, -84, -80, -69, -58, + -45, -38, -30, -13, 5, 13, 8, 0, -14, -25, -30, -46, -67, -72, -55, -34, + -26, -28, -31, -31, -26, -17, -4, 9, 11, 2, -4, -12, -22, -33, -38, -40, + -34, -18, -7, 2, 17, 33, 38, 29, 19, 20, 22, 17, 19, 38, 57, 43, + 15, 2, -1, 1, 3, 10, 18, 15, 14, 25, 38, 40, 27, 21, 28, 38, + 46, 50, 55, 66, 81, 90, 71, 40, 30, 37, 44, 39, 26, 18, 12, 8, + 14, 19, 8, -11, -13, 5, 15, -2, -28, -42, -36, -34, -45, -60, -76, -83, + -77, -65, -59, -55, -43, -28, -13, 5, 11, 2, -9, -11, -17, -37, -61, -71, + -65, -49, -38, -36, -34, -35, -36, -32, -16, -2, 1, 3, 0, -7, -13, -25, + -39, -46, -42, -30, -22, -15, 2, 21, 30, 24, 22, 28, 19, 5, 11, 33, + 50, 45, 31, 17, 6, -1, 0, 8, 16, 12, 11, 23, 37, 40, 33, 29, + 29, 33, 45, 48, 46, 58, 83, 97, 84, 59, 45, 46, 47, 46, 42, 31, + 16, 12, 23, 29, 16, -5, -9, 10, 21, 10, -12, -24, -25, -25, -29, -42, + -64, -73, -70, -66, -63, -58, -52, -42, -22, 0, 8, 4, 1, 3, -1, -19, + -44, -61, -63, -57, -50, -39, -33, -37, -39, -36, -27, -14, -4, 0, 0, 0, + -1, -13, -30, -42, -43, -37, -36, -30, -10, 8, 12, 15, 26, 31, 16, 1, + 4, 21, 37, 41, 38, 29, 13, 0, -1, 6, 8, 3, 7, 17, 26, 34, + 35, 27, 24, 32, 40, 37, 32, 45, 72, 89, 86, 70, 57, 48, 45, 49, + 50, 37, 16, 11, 25, 34, 20, -3, -7, 7, 18, 15, 2, -14, -20, -15, + -17, -32, -49, -61, -67, -65, -60, -61, -63, -54, -33, -12, -1, 1, 2, 10, + 12, -3, -26, -43, -57, -60, -54, -45, -38, -38, -39, -39, -35, -23, -13, -6, + -3, 2, 7, -2, -20, -30, -34, -42, -47, -38, -19, -9, -5, 7, 24, 31, + 19, 3, 0, 10, 23, 33, 40, 36, 18, 5, 4, 4, 0, 0, 0, 5, + 16, 29, 30, 22, 22, 31, 36, 27, 21, 32, 54, 74, 81, 77, 65, 49, + 44, 50, 55, 40, 16, 10, 24, 31, 20, 3, -6, -1, 11, 16, 5, -9, + -13, -12, -14, -22, -36, -53, -63, -62, -59, -63, -69, -67, -48, -25, -14, -10, + -1, 10, 16, 10, -6, -26, -45, -54, -55, -50, -42, -39, -39, -40, -39, -29, + -19, -15, -8, 4, 11, 3, -6, -11, -21, -38, -48, -40, -26, -21, -16, -3, + 18, 30, 24, 12, 6, 4, 11, 29, 41, 39, 28, 18, 11, 8, 5, 1, + -4, -2, 11, 25, 25, 19, 23, 33, 35, 25, 17, 23, 39, 57, 74, 81, + 72, 53, 47, 56, 60, 44, 23, 16, 22, 29, 25, 10, -4, -3, 7, 11, + 6, -3, -9, -11, -9, -12, -26, -42, -56, -59, -55, -61, -73, -75, -60, -42, + -32, -23, -12, 0, 12, 15, 7, -10, -30, -46, -53, -53, -46, -41, -43, -45, + -41, -32, -30, -26, -14, -1, 5, 2, 3, 3, -9, -30, -43, -40, -31, -31, + -28, -12, 8, 20, 25, 22, 9, 0, 6, 21, 34, 39, 35, 26, 18, 16, + 14, 4, -7, -5, 9, 21, 19, 16, 23, 35, 37, 28, 20, 20, 26, 43, + 67, 82, 74, 57, 54, 62, 63, 52, 33, 21, 23, 30, 28, 14, 1, -1, + 3, 8, 7, -1, -7, -9, -6, -5, -15, -34, -49, -51, -51, -60, -72, -76, + -70, -57, -46, -37, -25, -13, 3, 14, 14, 3, -15, -33, -48, -52, -47, -45, + -49, -49, -41, -37, -39, -35, -21, -10, -5, -2, 6, 12, 1, -19, -32, -34, + -36, -39, -34, -23, -9, 9, 23, 25, 14, 3, 2, 12, 25, 36, 37, 30, + 24, 25, 24, 10, -5, -4, 9, 18, 15, 14, 23, 34, 38, 36, 30, 19, + 15, 32, 61, 78, 75, 63, 60, 67, 71, 62, 42, 29, 30, 33, 32, 20, + 8, 4, 6, 8, 8, 3, -5, -9, -2, 3, -7, -25, -37, -42, -45, -54, + -66, -74, -74, -67, -58, -49, -40, -27, -9, 5, 13, 13, 0, -21, -39, -45, + -44, -49, -54, -50, -44, -44, -47, -42, -29, -21, -19, -11, 5, 12, 4, -8, + -18, -28, -36, -40, -40, -36, -24, -4, 14, 21, 17, 7, 0, 3, 17, 32, + 34, 29, 28, 34, 33, 17, 0, 0, 9, 13, 12, 14, 20, 27, 38, 46, + 39, 21, 11, 24, 51, 71, 74, 66, 64, 73, 78, 71, 54, 40, 38, 41, + 38, 28, 17, 11, 9, 12, 14, 7, -3, -5, 3, 9, 2, -12, -23, -28, + -35, -45, -55, -65, -71, -68, -62, -57, -50, -37, -22, -7, 10, 20, 12, -8, + -24, -32, -39, -48, -52, -49, -45, -49, -52, -44, -34, -33, -30, -18, -3, 5, + 5, 1, -8, -19, -29, -37, -43, -45, -37, -18, 0, 13, 18, 10, -1, -3, + 10, 24, 26, 23, 29, 38, 37, 21, 8, 5, 6, 8, 10, 12, 11, 16, + 34, 49, 46, 27, 10, 15, 38, 59, 67, 63, 63, 72, 81, 77, 61, 48, + 45, 45, 42, 35, 23, 13, 11, 17, 18, 9, -3, -5, 3, 10, 6, -3, + -12, -19, -24, -34, -46, -57, -64, -65, -66, -63, -56, -48, -39, -22, 1, 17, + 16, 3, -8, -17, -30, -44, -47, -44, -47, -53, -52, -44, -41, -41, -38, -28, + -14, -3, 3, 3, -2, -9, -17, -28, -42, -49, -46, -34, -17, 3, 14, 9, + -3, -6, 5, 15, 13, 15, 26, 36, 35, 25, 16, 8, 2, 4, 9, 6, + 1, 4, 22, 43, 48, 31, 11, 7, 24, 45, 55, 54, 55, 68, 79, 77, + 66, 54, 48, 47, 47, 41, 27, 14, 11, 18, 20, 10, -2, -6, 0, 7, + 8, 2, -6, -12, -14, -23, -38, -49, -55, -62, -66, -63, -60, -59, -53, -37, + -12, 8, 13, 10, 7, -4, -21, -35, -37, -39, -47, -53, -51, -45, -44, -44, + -42, -36, -24, -10, 0, 2, 1, 1, -3, -15, -30, -42, -49, -45, -30, -6, + 10, 7, -2, -3, 5, 9, 6, 11, 23, 32, 35, 33, 25, 14, 6, 9, + 12, 8, -2, -4, 13, 36, 48, 39, 18, 7, 17, 34, 43, 45, 50, 62, + 74, 78, 71, 59, 51, 49, 52, 48, 32, 16, 12, 19, 21, 13, 1, -6, + -5, 2, 6, 2, -4, -6, -9, -18, -29, -40, -51, -60, -65, -63, -63, -68, + -68, -53, -30, -12, 0, 10, 13, 3, -14, -25, -29, -35, -45, -52, -52, -49, + -47, -47, -47, -46, -35, -20, -10, -5, -1, 4, 4, -4, -15, -30, -47, -54, + -41, -15, 1, 0, -2, 2, 6, 4, 3, 7, 16, 26, 35, 38, 32, 20, + 12, 14, 18, 12, -1, -8, 3, 27, 46, 44, 26, 14, 17, 28, 35, 38, + 44, 55, 69, 78, 77, 66, 55, 54, 60, 58, 41, 24, 17, 19, 23, 20, + 7, -4, -4, 0, 2, 1, 0, -2, -4, -10, -17, -28, -42, -55, -59, -56, + -61, -72, -74, -63, -47, -32, -14, 5, 13, 7, -4, -12, -19, -28, -38, -46, + -51, -50, -46, -47, -51, -52, -43, -30, -20, -13, -5, 0, 4, 4, 2, -13, + -40, -55, -47, -25, -12, -8, -3, 3, 5, 4, 2, 3, 7, 18, 32, 41, + 36, 25, 18, 21, 25, 21, 5, -9, -3, 19, 41, 45, 34, 24, 23, 27, + 30, 33, 38, 47, 62, 78, 82, 72, 61, 61, 67, 66, 54, 37, 24, 23, + 28, 25, 15, 5, 0, 0, 0, 1, 2, 2, -1, -4, -5, -15, -34, -47, + -49, -49, -58, -69, -73, -70, -63, -51, -30, -8, 5, 7, 3, -4, -11, -20, + -29, -41, -49, -50, -46, -49, -54, -56, -50, -42, -33, -22, -13, -10, -6, 5, + 12, -1, -30, -50, -50, -38, -27, -18, -10, -3, 1, 2, 2, -2, -4, 6, + 24, 36, 36, 27, 19, 22, 30, 28, 10, -8, -10, 9, 30, 39, 35, 30, + 26, 26, 28, 29, 29, 35, 53, 73, 80, 74, 65, 63, 69, 72, 64, 47, + 33, 28, 29, 28, 21, 12, 6, 2, -2, 1, 4, 1, -2, 2, 6, -4, + -23, -35, -38, -42, -51, -60, -66, -70, -71, -63, -45, -23, -5, 4, 6, 3, + -2, -7, -18, -32, -42, -43, -43, -47, -52, -54, -53, -51, -42, -27, -20, -21, + -14, 4, 17, 10, -13, -35, -45, -44, -37, -26, -17, -11, -3, 3, 3, -3, + -9, -4, 13, 31, 35, 27, 19, 23, 34, 36, 19, -3, -10, 2, 19, 31, + 35, 33, 29, 30, 32, 28, 22, 26, 43, 63, 76, 75, 67, 65, 71, 75, + 70, 57, 43, 36, 34, 30, 26, 21, 14, 5, 1, 4, 3, -2, -2, 6, + 11, 3, -11, -22, -29, -36, -43, -50, -57, -67, -74, -72, -60, -40, -19, -5, + 2, 4, 6, 3, -8, -23, -32, -35, -40, -45, -47, -51, -57, -58, -47, -33, + -30, -32, -24, -5, 13, 14, 1, -18, -36, -45, -42, -35, -27, -20, -11, 0, + 3, -3, -12, -12, 1, 21, 31, 25, 16, 20, 34, 40, 26, 5, -7, -6, + 7, 21, 27, 26, 27, 31, 33, 27, 17, 15, 28, 50, 65, 68, 64, 62, + 68, 74, 72, 61, 51, 44, 35, 29, 28, 25, 15, 7, 5, 5, -1, -8, + -5, 3, 8, 4, -4, -12, -22, -32, -38, -42, -50, -61, -72, -77, -73, -57, + -36, -20, -11, -2, 7, 8, -3, -14, -22, -30, -38, -41, -42, -49, -60, -62, + -52, -41, -40, -41, -34, -18, 0, 11, 10, -3, -23, -38, -42, -40, -36, -31, + -20, -6, 2, -1, -13, -19, -9, 12, 25, 20, 12, 17, 30, 39, 34, 17, + -2, -8, 1, 13, 19, 21, 23, 31, 37, 32, 18, 10, 18, 36, 55, 62, + 60, 60, 67, 73, 72, 68, 61, 51, 41, 35, 34, 28, 18, 12, 11, 8, + -2, -9, -7, 0, 4, 5, 3, -3, -14, -24, -31, -36, -41, -50, -64, -77, + -80, -68, -51, -37, -26, -11, 3, 6, 2, -3, -13, -24, -32, -33, -34, -46, + -60, -62, -54, -47, -46, -47, -43, -31, -13, 4, 12, 6, -9, -23, -34, -39, + -40, -38, -29, -14, 0, 2, -11, -22, -15, 4, 17, 16, 11, 13, 25, 39, + 41, 28, 9, -3, 0, 9, 15, 15, 19, 30, 40, 39, 26, 12, 11, 28, + 45, 54, 56, 60, 66, 70, 73, 74, 69, 58, 49, 45, 42, 32, 22, 18, + 19, 14, 3, -6, -7, -4, 0, 5, 6, 3, -5, -14, -24, -30, -32, -38, + -53, -71, -78, -72, -63, -54, -39, -22, -8, 1, 6, 6, -4, -18, -25, -23, + -25, -39, -54, -58, -54, -49, -49, -50, -49, -42, -26, -7, 7, 9, 2, -9, + -20, -30, -38, -43, -39, -22, -2, 3, -9, -20, -16, -2, 11, 14, 10, 10, + 20, 36, 46, 40, 22, 8, 6, 11, 13, 12, 15, 26, 41, 46, 36, 20, + 14, 24, 38, 47, 54, 60, 64, 69, 76, 81, 76, 66, 60, 58, 53, 40, + 30, 27, 27, 22, 12, 3, -3, -4, -1, 4, 8, 8, 5, -4, -15, -21, + -21, -25, -41, -58, -69, -71, -70, -64, -51, -35, -23, -9, 5, 10, 1, -13, + -17, -15, -19, -32, -46, -54, -54, -51, -50, -52, -55, -53, -40, -22, -6, 3, + 4, -2, -10, -19, -32, -47, -49, -32, -11, -3, -10, -20, -20, -10, 2, 7, + 5, 2, 10, 28, 42, 41, 29, 16, 10, 11, 11, 7, 6, 17, 35, 45, + 39, 26, 18, 19, 26, 37, 47, 53, 56, 61, 73, 81, 76, 68, 65, 65, + 59, 46, 36, 31, 28, 25, 19, 9, -1, -6, -4, -1, 2, 8, 9, 0, + -10, -15, -14, -18, -32, -46, -57, -68, -74, -71, -61, -51, -41, -23, -2, 8, + 2, -8, -11, -10, -13, -23, -37, -48, -53, -51, -49, -53, -59, -60, -53, -37, + -19, -7, -3, -2, -1, -6, -22, -43, -52, -42, -21, -9, -12, -20, -23, -16, + -4, 3, -1, -6, 0, 18, 34, 40, 33, 22, 16, 16, 13, 5, 0, 9, + 27, 39, 40, 32, 24, 18, 19, 29, 40, 44, 46, 55, 69, 77, 75, 71, + 70, 70, 65, 55, 45, 37, 32, 30, 26, 17, 7, 0, -5, -6, -1, 8, + 11, 4, -5, -7, -7, -13, -21, -30, -44, -59, -69, -69, -65, -63, -56, -36, + -13, 1, 1, -4, -6, -5, -6, -12, -25, -40, -47, -47, -46, -50, -56, -62, + -61, -48, -30, -18, -12, -6, 4, 6, -7, -32, -49, -46, -30, -16, -12, -19, + -25, -20, -7, 0, -3, -9, -7, 8, 26, 36, 34, 27, 24, 24, 19, 7, + -2, 4, 18, 31, 38, 38, 30, 20, 18, 26, 34, 35, 38, 48, 62, 71, + 73, 72, 73, 72, 70, 64, 53, 43, 38, 35, 30, 23, 16, 7, -4, -10, + -4, 6, 8, 3, -1, -2, -4, -9, -12, -19, -33, -51, -61, -65, -69, -73, + -70, -52, -30, -13, -6, -5, -7, -5, -2, -5, -17, -31, -41, -45, -44, -45, + -53, -64, -67, -58, -43, -31, -26, -17, -1, 10, 3, -19, -41, -48, -39, -23, + -16, -21, -27, -24, -12, -3, -5, -13, -15, -3, 16, 28, 29, 26, 28, 31, + 24, 10, 0, 0, 8, 20, 33, 38, 32, 22, 19, 24, 28, 28, 30, 40, + 52, 61, 68, 71, 72, 73, 73, 69, 59, 51, 45, 39, 32, 28, 26, 15, + 0, -9, -5, 2, 4, 2, 1, -1, -4, -6, -5, -10, -24, -41, -50, -56, + -66, -76, -77, -66, -47, -27, -15, -11, -10, -5, 0, -1, -8, -20, -33, -40, + -40, -40, -48, -62, -70, -64, -51, -43, -39, -29, -11, 7, 10, -5, -28, -43, + -41, -28, -20, -22, -29, -28, -17, -6, -5, -14, -20, -12, 6, 19, 22, 23, + 30, 35, 31, 20, 8, 0, 1, 13, 29, 37, 33, 26, 25, 27, 27, 25, + 26, 33, 43, 54, 63, 67, 70, 74, 76, 72, 66, 61, 54, 44, 37, 36, + 34, 24, 8, -3, -4, -2, 0, 2, 3, -1, -5, -3, 2, -2, -16, -29, + -36, -44, -57, -70, -79, -76, -60, -41, -27, -19, -14, -8, -1, 3, 0, -10, + -24, -33, -33, -32, -40, -55, -65, -63, -56, -51, -48, -40, -23, -1, 12, 7, + -13, -32, -37, -29, -21, -21, -28, -29, -19, -6, -2, -12, -20, -14, 0, 11, + 16, 22, 30, 37, 38, 33, 21, 7, 0, 9, 26, 36, 35, 32, 32, 32, + 31, 28, 27, 30, 38, 50, 58, 63, 70, 78, 79, 76, 74, 72, 64, 53, + 46, 45, 44, 34, 20, 9, 3, -1, 1, 7, 7, 0, -4, 2, 8, 5, + -5, -15, -23, -30, -41, -58, -73, -77, -68, -53, -38, -28, -21, -14, -5, 4, + 7, -1, -15, -25, -25, -24, -32, -48, -59, -61, -59, -57, -57, -54, -39, -16, + 4, 8, -5, -24, -33, -30, -24, -24, -32, -35, -26, -11, -6, -14, -20, -19, + -10, -2, 5, 13, 21, 29, 37, 40, 30, 11, 0, 4, 17, 27, 30, 31, + 31, 32, 32, 29, 23, 23, 31, 40, 45, 52, 63, 72, 74, 73, 75, 75, + 67, 56, 51, 50, 46, 38, 29, 18, 6, -3, -1, 5, 3, -4, -7, -2, + 4, 5, -2, -11, -17, -21, -30, -47, -66, -78, -77, -66, -53, -42, -34, -27, + -16, -3, 6, 1, -12, -21, -21, -21, -28, -42, -54, -60, -60, -61, -65, -67, + -57, -35, -11, 1, -3, -18, -30, -30, -25, -27, -36, -41, -32, -19, -13, -17, + -22, -22, -19, -14, -6, 2, 7, 17, 31, 41, 34, 17, 3, 1, 8, 17, + 23, 25, 26, 30, 32, 28, 22, 21, 25, 30, 34, 42, 54, 63, 66, 70, + 77, 77, 69, 61, 57, 55, 49, 44, 39, 28, 11, 2, 2, 5, 3, -3, + -8, -4, 3, 6, 2, -4, -9, -11, -16, -31, -52, -68, -75, -71, -61, -50, + -43, -38, -26, -8, 5, 4, -6, -13, -14, -13, -19, -31, -44, -51, -52, -55, + -64, -71, -67, -49, -24, -4, -1, -12, -22, -21, -18, -22, -33, -39, -33, -22, + -16, -16, -17, -19, -20, -16, -9, -4, -2, 5, 18, 31, 37, 32, 21, 11, + 9, 12, 17, 20, 24, 28, 32, 31, 28, 26, 26, 26, 28, 34, 43, 51, + 57, 65, 74, 77, 75, 72, 68, 63, 59, 56, 53, 44, 31, 19, 12, 11, + 8, 3, -2, -3, 0, 4, 5, 2, 0, -1, -3, -11, -25, -42, -58, -66, + -65, -59, -54, -51, -42, -27, -11, -2, -3, -6, -7, -7, -9, -16, -27, -36, + -40, -44, -52, -63, -70, -66, -49, -28, -15, -13, -16, -16, -13, -16, -24, -31, + -33, -29, -24, -19, -17, -19, -20, -18, -14, -13, -12, -6, 7, 22, 33, 35, + 28, 18, 12, 12, 14, 17, 21, 27, 31, 31, 30, 30, 28, 25, 25, 30, + 36, 42, 49, 58, 67, 74, 76, 75, 71, 66, 62, 60, 59, 53, 41, 29, + 19, 14, 11, 7, 1, -3, -2, 1, 3, 3, 1, 0, 0, -3, -11, -26, + -44, -59, -65, -63, -60, -57, -52, -41, -25, -11, -4, -4, -6, -6, -6, -9, + -17, -27, -35, -39, -44, -53, -65, -71, -65, -47, -28, -16, -15, -16, -15, -14, + -17, -25, -32, -33, -29, -24, -19, -17, -19, -20, -18, -14, -13, -12, -6, -2, + 1, 6, 5, 21, 46, 42, 15, 0, 5, 34, 48, 29, -4, -31, -33, -17, + 26, 49, 32, 0, -21, -15, 14, 24, 24, 16, 0, 3, 11, 11, 11, 5, + 9, 9, 8, 11, 30, 27, 22, 7, -3, -3, 10, 2, -2, -4, -13, -4, + -4, -2, -2, -3, -7, -6, -14, -15, -14, -14, -13, -3, -14, -16, -18, -13, + -15, -16, -22, -20, -14, -3, -6, -4, -14, -11, -6, -10, -15, -15, -16, -9, + -10, -19, -3, -5, -17, -15, -18, -16, -14, -14, -12, -15, -7, -22, -19, -17, + -20, -11, -17, -14, -11, -8, -10, -13, -12, -11, -6, -6, -9, 1, 1, -3, + 0, 6, -2, -9, 7, -8, 8, 4, 3, 1, -6, -2, -2, 2, -5, -7, + -4, -7, -8, -9, -6, -6, 0, -8, -12, -12, -13, -8, -4, -7, -3, -11, + -6, -15, -7, -9, -9, -3, -10, -8, -9, -15, -10, -2, 2, -7, -16, -17, + -15, -13, -9, -6, -5, -7, -9, -15, -17, -12, -19, -12, -8, -8, -4, -6, + -3, 0, -4, -11, -13, -7, -6, -2, 4, 4, 8, 10, 4, 3, 3, 4, + 7, 12, 11, 14, 15, 20, 20, 18, 16, 17, 15, 14, 15, 22, 23, 28, + 34, 29, 28, 17, 22, 24, 23, 25, 28, 28, 30, 24, 19, 16, 13, 18, + 20, 15, 8, 2, 3, 0, 2, 0, -3, -2, -9, -20, -23, -25, -24, -23, + -27, -33, -38, -39, -44, -36, -42, -44, -48, -53, -54, -56, -52, -50, -40, -35, + -44, -43, -44, -39, -28, -24, -23, -22, -15, -9, 2, 11, 19, 28, 31, 31, + 32, 35, 43, 61, 70, 78, 81, 73, 78, 78, 78, 85, 82, 85, 88, 87, + 84, 83, 83, 79, 74, 62, 49, 45, 42, 43, 44, 38, 30, 18, 6, -5, + -15, -17, -15, -22, -28, -38, -46, -48, -50, -58, -59, -72, -80, -83, -89, -88, + -89, -87, -81, -84, -93, -105, -110, -109, -110, -102, -96, -82, -65, -62, -60, -60, + -60, -51, -43, -37, -28, -16, 1, 15, 28, 35, 41, 46, 53, 56, 60, 66, + 77, 91, 101, 102, 101, 99, 104, 103, 97, 91, 86, 90, 91, 86, 85, 79, + 75, 71, 59, 48, 39, 35, 33, 32, 28, 22, 15, 13, 7, 3, -7, -15, + -16, -18, -19, -23, -28, -29, -33, -37, -47, -52, -56, -63, -61, -70, -67, -70, + -72, -72, -80, -93, -91, -99, -103, -96, -108, -105, -109, -112, -94, -81, -73, -67, + -71, -77, -69, -63, -57, -38, -27, -15, 0, 4, 6, 19, 26, 41, 53, 49, + 56, 58, 69, 84, 91, 95, 101, 103, 98, 93, 85, 87, 102, 102, 103, 95, + 81, 78, 78, 71, 66, 60, 51, 50, 44, 39, 34, 34, 32, 27, 15, 0, + -6, -8, -3, -3, -11, -10, -18, -21, -26, -35, -39, -38, -44, -48, -53, -63, + -61, -61, -71, -63, -86, -89, -86, -107, -99, -109, -108, -109, -108, -121, -128, -105, + -102, -83, -67, -88, -82, -76, -78, -62, -47, -41, -19, -6, 1, 7, 13, 33, + 44, 64, 61, 59, 68, 73, 93, 98, 107, 114, 109, 123, 107, 100, 105, 100, + 111, 117, 100, 93, 92, 86, 85, 80, 70, 59, 58, 47, 38, 41, 33, 40, + 38, 25, 16, 1, -2, -3, -3, -4, -10, -16, -12, -21, -28, -28, -36, -38, + -39, -52, -61, -61, -67, -63, -65, -76, -77, -86, -95, -95, -107, -109, -112, -112, + -121, -121, -122, -105, -79, -80, -71, -80, -84, -73, -70, -56, -43, -28, -10, 6, + 11, 17, 31, 43, 63, 69, 69, 65, 77, 88, 101, 113, 112, 127, 122, 122, + 115, 104, 112, 116, 122, 117, 106, 99, 97, 96, 94, 86, 75, 70, 61, 53, + 44, 41, 46, 47, 45, 28, 19, 9, 5, 9, 1, -8, -14, -20, -24, -26, + -28, -29, -36, -39, -42, -45, -41, -42, -45, -46, -49, -47, -50, -55, -53, -61, + -63, -67, -83, -78, -89, -91, -88, -100, -93, -108, -110, -110, -115, -90, -100, -91, + -80, -91, -73, -62, -60, -41, -33, -36, -25, -16, -9, 8, 18, 35, 40, 57, + 61, 66, 95, 94, 106, 114, 105, 117, 111, 117, 118, 115, 120, 111, 109, 111, + 104, 102, 106, 93, 88, 76, 66, 63, 52, 53, 31, 27, 25, 5, 12, 1, + -5, 0, -15, -17, -23, -27, -27, -31, -31, -37, -44, -41, -43, -43, -35, -45, + -43, -41, -50, -49, -51, -57, -58, -62, -72, -76, -79, -81, -82, -86, -92, -94, + -100, -109, -110, -102, -99, -96, -83, -96, -83, -67, -73, -45, -41, -42, -27, -27, + -19, -5, 7, 14, 30, 44, 46, 57, 75, 84, 98, 108, 102, 112, 114, 110, + 120, 115, 116, 117, 108, 112, 107, 104, 108, 99, 96, 90, 73, 69, 66, 57, + 48, 36, 26, 18, 13, 6, -3, 3, -8, -14, -15, -26, -25, -26, -33, -33, + -40, -45, -45, -45, -42, -43, -44, -45, -48, -46, -55, -57, -58, -62, -67, -73, + -78, -80, -81, -82, -89, -93, -99, -106, -108, -115, -100, -95, -103, -77, -91, -85, + -59, -63, -48, -32, -36, -33, -18, -14, -6, 11, 21, 27, 47, 55, 56, 81, + 92, 96, 114, 106, 111, 116, 110, 121, 113, 115, 115, 105, 111, 106, 101, 103, + 100, 92, 84, 74, 66, 60, 58, 43, 29, 29, 13, 9, 10, -6, -2, -6, + -16, -18, -22, -27, -30, -30, -35, -44, -43, -46, -46, -42, -44, -48, -45, -46, + -50, -54, -51, -61, -63, -61, -85, -76, -80, -94, -75, -98, -97, -93, -111, -103, + -106, -97, -97, -90, -79, -93, -73, -64, -67, -39, -38, -41, -20, -20, -12, 11, + 10, 30, 40, 48, 62, 62, 85, 91, 99, 111, 101, 112, 111, 113, 120, 112, + 119, 111, 108, 114, 101, 102, 104, 89, 91, 79, 63, 67, 56, 52, 41, 29, + 26, 12, 14, 3, -5, 1, -14, -15, -19, -27, -24, -30, -31, -34, -43, -43, + -45, -48, -40, -48, -48, -45, -51, -49, -53, -56, -57, -63, -69, -76, -86, -80, + -86, -90, -87, -98, -101, -101, -108, -103, -88, -96, -88, -77, -89, -70, -60, -56, + -39, -34, -30, -26, -11, -4, 6, 26, 27, 42, 54, 57, 72, 86, 95, 105, + 107, 108, 112, 109, 116, 118, 112, 117, 108, 109, 107, 104, 103, 99, 97, 83, + 77, 71, 57, 60, 49, 35, 30, 21, 11, 11, 4, -2, -3, -13, -17, -22, + -24, -28, -29, -29, -39, -39, -44, -44, -41, -45, -44, -50, -49, -49, -56, -50, + -60, -62, -55, -82, -70, -82, -90, -80, -95, -95, -100, -105, -112, -112, -93, -102, + -91, -81, -91, -77, -60, -65, -45, -33, -40, -25, -21, -14, 5, 10, 30, 35, + 49, 61, 61, 87, 94, 102, 109, 109, 112, 112, 116, 117, 116, 118, 116, 106, + 113, 108, 101, 110, 96, 91, 84, 69, 66, 58, 54, 38, 29, 26, 12, 11, + 6, -2, -2, -8, -16, -20, -23, -27, -28, -33, -34, -44, -43, -43, -47, -39, + -44, -47, -43, -47, -49, -50, -52, -57, -58, -68, -75, -76, -83, -86, -86, -91, + -97, -98, -103, -109, -102, -91, -99, -84, -81, -93, -65, -66, -60, -37, -42, -33, + -25, -18, -9, 6, 16, 28, 41, 49, 57, 68, 84, 93, 102, 106, 106, 110, + 107, 116, 114, 111, 119, 106, 111, 108, 101, 104, 99, 94, 85, 76, 68, 61, + 56, 49, 34, 28, 21, 10, 10, 2, -3, -3, -13, -15, -24, -26, -28, -34, + -31, -42, -45, -43, -48, -44, -43, -47, -47, -47, -48, -51, -57, -57, -63, -70, + -72, -80, -86, -81, -92, -88, -96, -103, -100, -113, -110, -96, -101, -96, -79, -91, + -82, -59, -68, -47, -34, -39, -29, -18, -13, -5, 18, 22, 32, 54, 52, 64, + 83, 90, 100, 108, 109, 110, 113, 113, 116, 113, 117, 113, 106, 111, 103, 100, + 101, 98, 86, 82, 73, 59, 61, 53, 36, 34, 24, 12, 10, 5, -5, -3, + -8, -17, -18, -24, -27, -29, -30, -35, -40, -41, -45, -43, -43, -42, -45, -46, + -44, -50, -49, -55, -58, -55, -71, -70, -79, -87, -77, -92, -88, -95, -104, -100, + -115, -107, -91, -105, -85, -83, -97, -67, -68, -65, -37, -43, -33, -29, -21, -9, + 0, 18, 23, 35, 55, 48, 69, 87, 86, 108, 107, 103, 117, 106, 117, 118, + 113, 122, 109, 111, 111, 102, 110, 101, 98, 92, 77, 73, 62, 59, 54, 34, + 34, 21, 11, 15, 2, 2, 2, -14, -12, -23, -26, -26, -33, -30, -40, -44, + -42, -49, -41, -41, -44, -43, -46, -49, -51, -59, -54, -63, -67, -64, -84, -79, + -76, -91, -82, -87, -100, -100, -101, -118, -101, -89, -107, -81, -82, -93, -65, -57, + -57, -36, -26, -39, -17, -9, -13, 14, 21, 26, 45, 53, 54, 76, 88, 95, + 111, 106, 111, 114, 109, 120, 115, 115, 116, 110, 105, 109, 104, 98, 105, 94, + 83, 81, 68, 60, 62, 49, 32, 33, 18, 9, 12, 0, -3, -3, -13, -18, + -20, -24, -27, -26, -31, -37, -40, -42, -42, -43, -42, -44, -48, -48, -47, -51, + -54, -52, -56, -64, -68, -75, -84, -79, -89, -91, -93, -104, -105, -110, -114, -97, + -97, -96, -78, -89, -81, -58, -66, -47, -34, -40, -31, -23, -14, -6, 14, 22, + 31, 54, 55, 63, 87, 91, 103, 113, 105, 111, 113, 109, 119, 112, 117, 114, + 106, 113, 106, 105, 105, 99, 93, 81, 74, 61, 58, 55, 36, 30, 25, 10, + 11, 6, -5, 1, -8, -16, -19, -25, -27, -32, -32, -37, -44, -41, -47, -43, + -39, -43, -44, -45, -46, -46, -56, -53, -55, -72, -64, -74, -91, -72, -88, -97, + -80, -100, -105, -100, -111, -111, -88, -100, -99, -74, -97, -79, -54, -68, -43, -32, + -41, -26, -10, -16, 6, 22, 19, 41, 51, 49, 69, 86, 88, 103, 107, 100, + 119, 110, 111, 125, 110, 115, 115, 104, 108, 106, 99, 98, 98, 82, 76, 71, + 60, 60, 52, 34, 30, 25, 9, 11, 3, -6, 0, -15, -18, -21, -27, -27, + -30, -31, -38, -39, -43, -43, -39, -43, -44, -46, -47, -47, -54, -53, -59, -58, + -65, -71, -75, -81, -75, -90, -83, -90, -100, -95, -111, -109, -101, -97, -100, -84, + -86, -89, -62, -64, -50, -34, -37, -30, -21, -11, -8, 10, 19, 26, 47, 49, + 59, 76, 89, 99, 107, 109, 110, 115, 113, 119, 115, 114, 115, 106, 111, 103, + 103, 101, 98, 94, 81, 78, 65, 63, 59, 43, 34, 25, 17, 10, 7, -4, + -3, -6, -14, -16, -23, -24, -28, -29, -33, -41, -41, -46, -43, -40, -44, -44, + -46, -46, -47, -50, -54, -56, -58, -69, -70, -76, -83, -75, -87, -87, -91, -100, + -100, -109, -108, -97, -98, -93, -83, -88, -76, -61, -59, -43, -36, -33, -28, -18, + -11, -4, 14, 21, 31, 52, 51, 63, 84, 90, 101, 111, 104, 113, 113, 111, + 118, 112, 114, 109, 108, 109, 102, 106, 101, 98, 94, 79, 74, 66, 58, 55, + 39, 29, 24, 13, 11, 5, -4, 0, -10, -15, -17, -24, -25, -28, -29, -34, + -41, -41, -47, -42, -44, -46, -45, -50, -45, -50, -55, -48, -60, -60, -65, -76, + -77, -83, -84, -91, -92, -94, -106, -103, -109, -106, -89, -101, -82, -81, -88, -63, + -66, -54, -36, -40, -31, -25, -16, -7, 6, 17, 30, 41, 55, 56, 73, 89, + 92, 109, 104, 106, 114, 104, 117, 113, 110, 116, 105, 108, 106, 100, 102, 98, + 94, 85, 74, 67, 59, 55, 48, 31, 28, 19, 10, 12, 0, 2, -2, -11, + -11, -21, -21, -26, -30, -30, -40, -43, -43, -44, -40, -39, -41, -43, -42, -46, + -52, -52, -58, -63, -65, -75, -79, -83, -80, -89, -85, -88, -101, -94, -104, -114, + -93, -97, -104, -78, -92, -89, -60, -68, -48, -36, -36, -26, -21, -8, -5, 12, + 23, 26, 47, 50, 54, 77, 85, 96, 109, 102, 114, 112, 109, 125, 112, 114, + 118, 102, 110, 103, 99, 101, 96, 92, 79, 76, 66, 59, 61, 43, 32, 31, + 14, 10, 9, -5, -2, -9, -17, -18, -28, -25, -31, -31, -31, -42, -38, -43, + -41, -39, -43, -44, -47, -45, -48, -51, -53, -54, -61, -64, -67, -77, -76, -82, + -81, -89, -93, -97, -106, -108, -105, -96, -99, -88, -82, -92, -67, -64, -60, -38, + -38, -36, -24, -20, -16, 4, 11, 21, 36, 46, 53, 66, 85, 88, 103, 108, + 102, 115, 107, 112, 115, 109, 114, 104, 106, 106, 99, 102, 101, 92, 89, 81, + 67, 66, 58, 47, 39, 28, 21, 11, 12, 2, -2, 2, -12, -12, -17, -25, + -24, -29, -30, -36, -39, -41, -41, -41, -39, -41, -44, -44, -47, -51, -52, -54, + -59, -63, -65, -75, -79, -75, -90, -81, -89, -99, -92, -109, -109, -105, -99, -97, + -92, -80, -90, -71, -58, -60, -37, -32, -37, -19, -15, -14, 9, 14, 23, 42, + 46, 56, 67, 83, 96, 100, 111, 106, 111, 114, 111, 117, 111, 112, 109, 103, + 107, 100, 99, 103, 92, 88, 82, 65, 66, 59, 48, 39, 27, 22, 12, 9, + 5, -5, 0, -12, -16, -17, -26, -25, -26, -31, -34, -40, -41, -41, -41, -40, + -42, -47, -43, -46, -46, -52, -50, -52, -61, -59, -74, -75, -77, -83, -84, -91, + -92, -105, -100, -106, -109, -81, -103, -86, -73, -96, -64, -62, -59, -38, -39, -36, + -28, -15, -11, 3, 18, 25, 37, 53, 53, 67, 89, 85, 106, 103, 98, 115, + 99, 114, 115, 103, 116, 103, 104, 109, 98, 101, 98, 91, 84, 75, 67, 60, + 55, 50, 31, 28, 20, 7, 15, 0, -3, 2, -15, -12, -19, -25, -24, -32, + -32, -38, -44, -44, -45, -42, -41, -44, -43, -46, -44, -44, -58, -48, -63, -67, + -63, -87, -75, -83, -90, -81, -94, -95, -95, -107, -109, -99, -95, -99, -85, -85, + -90, -68, -62, -60, -36, -34, -39, -15, -13, -9, 14, 15, 29, 42, 50, 55, + 68, 87, 91, 101, 107, 106, 110, 113, 114, 115, 114, 112, 108, 105, 106, 98, + 98, 100, 88, 84, 75, 63, 63, 57, 46, 34, 28, 18, 10, 8, 0, -5, + -5, -15, -19, -20, -26, -26, -26, -31, -36, -40, -42, -43, -42, -39, -44, -44, + -42, -44, -47, -51, -52, -54, -65, -63, -76, -81, -68, -93, -84, -85, -104, -92, + -105, -109, -95, -95, -96, -84, -82, -84, -64, -64, -52, -39, -37, -33, -23, -11, + -9, 10, 20, 25, 49, 46, 60, 76, 82, 98, 101, 104, 110, 108, 108, 116, + 111, 111, 113, 104, 108, 106, 101, 98, 99, 92, 80, 79, 63, 61, 59, 41, + 35, 27, 18, 13, 9, 2, 0, -5, -12, -15, -20, -22, -26, -27, -30, -38, + -39, -42, -40, -39, -40, -40, -45, -43, -47, -49, -54, -53, -57, -70, -59, -80, + -77, -72, -93, -75, -91, -99, -93, -105, -108, -97, -92, -99, -80, -84, -84, -61, + -59, -49, -35, -28, -34, -14, -9, -10, 19, 17, 27, 47, 47, 61, 72, 87, + 95, 105, 104, 110, 111, 109, 117, 109, 111, 109, 103, 103, 102, 97, 95, 100, + 85, 81, 77, 61, 64, 55, 42, 34, 26, 17, 10, 9, -3, -2, -5, -13, + -15, -20, -23, -27, -27, -32, -37, -38, -41, -40, -41, -39, -43, -43, -40, -48, + -47, -49, -55, -61, -59, -70, -80, -69, -87, -83, -79, -97, -89, -98, -101, -107, + -96, -93, -101, -77, -90, -84, -62, -63, -49, -36, -34, -30, -15, -12, -2, 11, + 20, 32, 39, 53, 56, 71, 87, 89, 103, 101, 109, 109, 109, 118, 106, 114, + 111, 101, 107, 102, 93, 99, 94, 84, 85, 71, 65, 62, 54, 45, 32, 30, + 16, 12, 8, -5, -2, -9, -14, -16, -24, -22, -27, -29, -31, -38, -41, -38, + -44, -42, -41, -47, -45, -44, -48, -50, -50, -52, -62, -57, -69, -79, -69, -83, + -88, -78, -99, -97, -92, -109, -106, -91, -100, -93, -76, -91, -80, -60, -66, -48, + -37, -38, -32, -18, -15, -4, 11, 14, 31, 42, 48, 60, 69, 85, 94, 96, + 102, 107, 103, 109, 115, 104, 112, 109, 100, 106, 103, 95, 97, 96, 84, 82, + 73, 60, 62, 54, 41, 33, 27, 17, 14, 7, 0, 0, -8, -11, -16, -23, + -23, -29, -29, -32, -39, -40, -40, -40, -41, -40, -46, -48, -45, -50, -51, -54, + -56, -64, -63, -71, -78, -73, -84, -82, -87, -95, -93, -102, -102, -108, -95, -96, + -95, -76, -90, -77, -57, -61, -42, -33, -35, -26, -13, -14, 3, 15, 17, 36, + 45, 54, 60, 80, 89, 96, 108, 101, 111, 110, 109, 118, 107, 110, 109, 102, + 103, 103, 95, 97, 96, 83, 82, 70, 60, 61, 51, 38, 28, 23, 11, 8, + 4, -7, -3, -10, -16, -17, -22, -25, -27, -29, -35, -38, -43, -42, -41, -40, + -39, -43, -42, -44, -45, -46, -53, -51, -55, -68, -65, -75, -79, -77, -88, -83, + -94, -93, -101, -105, -96, -96, -92, -85, -85, -83, -71, -64, -57, -41, -41, -31, + -27, -17, -7, 2, 18, 23, 38, 48, 51, 68, 78, 91, 98, 102, 106, 108, + 110, 112, 115, 110, 115, 107, 107, 108, 99, 102, 97, 94, 87, 76, 70, 63, + 60, 49, 39, 30, 22, 16, 8, 4, 0, -4, -10, -14, -20, -24, -25, -31, + -30, -37, -41, -40, -41, -38, -39, -40, -42, -41, -43, -48, -44, -55, -58, -57, + -71, -71, -73, -78, -79, -80, -88, -89, -95, -99, -103, -101, -88, -98, -85, -79, + -90, -62, -60, -54, -35, -35, -27, -21, -9, -3, 7, 22, 26, 38, 52, 54, + 67, 87, 89, 101, 105, 103, 114, 107, 117, 112, 107, 116, 100, 105, 103, 94, + 98, 93, 87, 80, 73, 65, 59, 56, 45, 31, 28, 19, 6, 10, -3, -5, + -4, -17, -16, -22, -24, -25, -30, -28, -39, -37, -40, -44, -40, -44, -46, -46, + -47, -51, -50, -55, -55, -60, -67, -65, -81, -75, -78, -93, -78, -97, -101, -94, + -113, -104, -92, -96, -91, -79, -86, -79, -58, -58, -49, -34, -34, -33, -14, -12, + -5, 20, 19, 34, 49, 49, 66, 76, 91, 98, 98, 105, 104, 107, 111, 110, + 109, 108, 108, 103, 101, 102, 97, 95, 96, 80, 75, 71, 56, 58, 49, 33, + 28, 20, 13, 7, 4, -4, -7, -9, -18, -22, -22, -28, -30, -30, -38, -41, + -41, -43, -40, -41, -40, -44, -43, -45, -48, -49, -55, -55, -59, -67, -66, -82, + -70, -81, -86, -78, -101, -92, -98, -111, -98, -95, -95, -89, -76, -91, -70, -56, + -61, -38, -34, -33, -25, -12, -10, 1, 21, 15, 39, 47, 48, 68, 75, 90, + 97, 101, 103, 106, 106, 110, 111, 104, 111, 101, 99, 103, 96, 94, 95, 92, + 75, 79, 64, 55, 64, 43, 36, 30, 17, 13, 9, 3, -4, -3, -12, -16, + -18, -23, -25, -26, -29, -35, -38, -42, -40, -39, -41, -38, -48, -42, -45, -50, + -49, -52, -57, -63, -57, -78, -76, -67, -94, -75, -88, -100, -92, -103, -106, -97, + -88, -96, -81, -77, -85, -60, -55, -51, -35, -30, -33, -19, -9, -10, 17, 16, + 30, 46, 48, 64, 72, 86, 96, 101, 104, 105, 111, 104, 116, 109, 107, 110, + 104, 101, 104, 100, 93, 100, 86, 77, 78, 59, 60, 54, 40, 32, 23, 18, + 9, 9, 0, -5, -6, -14, -17, -20, -23, -25, -26, -31, -35, -39, -40, -36, + -40, -37, -40, -45, -42, -45, -48, -51, -50, -57, -64, -62, -76, -78, -71, -90, + -84, -88, -101, -97, -105, -108, -94, -97, -92, -81, -87, -76, -63, -58, -42, -36, + -33, -27, -15, -10, -2, 18, 19, 34, 49, 47, 66, 78, 86, 102, 104, 104, + 111, 109, 112, 115, 112, 110, 108, 106, 101, 102, 98, 96, 97, 86, 79, 72, + 62, 61, 51, 39, 32, 20, 15, 10, 2, 1, -4, -9, -13, -18, -22, -24, + -25, -29, -33, -37, -41, -39, -37, -39, -39, -43, -46, -46, -49, -49, -56, -54, + -57, -68, -66, -73, -77, -79, -83, -90, -96, -95, -107, -110, -98, -97, -98, -76, + -87, -83, -56, -68, -49, -34, -43, -28, -26, -18, -8, 3, 14, 22, 39, 47, + 54, 70, 83, 90, 101, 100, 104, 107, 102, 113, 103, 106, 109, 95, 106, 99, + 95, 101, 92, 93, 83, 74, 66, 60, 56, 44, 33, 26, 17, 12, 8, 1, + 2, -4, -11, -10, -21, -19, -25, -29, -28, -39, -38, -41, -41, -37, -40, -42, + -43, -42, -45, -47, -48, -56, -52, -59, -69, -67, -78, -78, -79, -88, -86, -95, + -100, -99, -112, -95, -92, -101, -77, -86, -86, -62, -65, -51, -39, -35, -31, -26, + -8, -11, 7, 26, 21, 45, 53, 50, 76, 86, 90, 105, 102, 105, 109, 108, + 115, 107, 112, 110, 100, 108, 100, 96, 100, 93, 89, 79, 72, 64, 58, 56, + 42, 31, 28, 14, 10, 9, -5, -2, -6, -14, -15, -22, -22, -27, -28, -31, + -41, -37, -41, -42, -37, -41, -45, -43, -45, -47, -48, -49, -58, -53, -64, -71, + -68, -82, -75, -83, -91, -87, -103, -97, -104, -111, -90, -98, -95, -77, -91, -76, + -61, -63, -43, -41, -35, -29, -23, -7, -7, 13, 22, 24, 50, 50, 59, 82, + 82, 99, 102, 100, 110, 105, 111, 113, 104, 114, 103, 104, 107, 96, 102, 97, + 92, 90, 77, 73, 64, 58, 53, 38, 31, 23, 13, 12, 3, 0, -2, -11, + -10, -17, -21, -20, -29, -27, -33, -40, -38, -44, -39, -39, -43, -41, -42, -42, + -46, -42, -53, -53, -52, -71, -67, -73, -83, -80, -81, -89, -93, -91, -100, -106, + -97, -96, -93, -88, -81, -85, -79, -59, -58, -48, -30, -36, -28, -11, -9, -2, + 21, 22, 32, 50, 52, 58, 79, 89, 90, 104, 104, 100, 113, 111, 109, 114, + 109, 107, 103, 104, 99, 94, 97, 91, 78, 79, 65, 58, 61, 47, 37, 30, + 23, 14, 10, 7, -7, -4, -8, -21, -17, -23, -30, -26, -30, -36, -37, -39, + -38, -38, -36, -38, -45, -41, -45, -49, -51, -56, -57, -63, -64, -69, -78, -70, + -80, -84, -84, -91, -100, -98, -106, -108, -90, -103, -90, -80, -93, -65, -64, -52, + -38, -37, -27, -26, -12, -6, 3, 18, 22, 36, 48, 54, 69, 84, 89, 105, + 103, 106, 117, 105, 117, 113, 106, 113, 101, 105, 101, 99, 98, 93, 94, 83, + 75, 70, 60, 55, 49, 33, 27, 19, 10, 8, -2, -2, -7, -13, -12, -22, + -20, -23, -28, -28, -35, -39, -40, -41, -40, -42, -40, -43, -42, -42, -44, -46, + -49, -52, -59, -60, -70, -74, -71, -84, -82, -88, -96, -98, -100, -105, -102, -88, + -95, -83, -79, -87, -62, -62, -52, -40, -39, -31, -27, -14, -10, 7, 17, 25, + 42, 49, 59, 72, 85, 92, 103, 103, 102, 111, 104, 113, 110, 104, 112, 102, + 107, 103, 101, 99, 97, 92, 81, 76, 64, 61, 54, 42, 33, 24, 17, 11, + 8, -2, -2, -5, -13, -12, -22, -23, -26, -31, -32, -38, -40, -43, -39, -40, + -41, -40, -44, -41, -44, -47, -51, -49, -62, -55, -68, -78, -68, -89, -79, -81, + -96, -85, -101, -100, -103, -98, -91, -97, -79, -83, -87, -61, -64, -55, -31, -41, + -29, -15, -19, 3, 9, 18, 33, 36, 56, 54, 71, 87, 87, 103, 103, 103, + 110, 107, 113, 112, 108, 111, 101, 104, 103, 92, 101, 92, 84, 84, 66, 65, + 59, 51, 45, 31, 27, 16, 10, 6, -3, -3, -9, -15, -16, -22, -24, -25, + -30, -28, -36, -40, -36, -42, -38, -41, -45, -44, -47, -47, -49, -51, -52, -54, + -62, -68, -73, -78, -81, -84, -83, -97, -94, -101, -113, -100, -99, -96, -87, -83, + -85, -75, -60, -60, -43, -36, -38, -27, -20, -15, 0, 14, 19, 33, 47, 49, + 67, 78, 90, 100, 103, 105, 107, 108, 110, 112, 109, 109, 107, 102, 105, 100, + 99, 98, 95, 84, 80, 69, 59, 60, 48, 36, 31, 18, 14, 9, 3, -2, + -5, -10, -15, -19, -24, -25, -28, -31, -34, -39, -41, -40, -38, -40, -38, -43, + -43, -42, -48, -47, -53, -54, -58, -67, -63, -79, -73, -78, -90, -80, -98, -97, + -101, -109, -105, -93, -98, -90, -76, -93, -66, -60, -59, -33, -42, -32, -26, -18, + -9, 0, 17, 21, 38, 48, 53, 69, 82, 93, 101, 107, 102, 112, 108, 111, + 115, 105, 112, 103, 105, 104, 96, 103, 95, 95, 85, 76, 68, 63, 59, 47, + 38, 26, 19, 13, 7, 1, -3, -4, -14, -12, -19, -23, -21, -29, -29, -35, + -40, -41, -42, -39, -43, -42, -46, -43, -47, -45, -48, -54, -47, -66, -61, -68, + -85, -66, -90, -84, -84, -103, -91, -106, -105, -96, -90, -92, -81, -79, -86, -59, + -59, -53, -34, -36, -33, -19, -10, -10, 17, 20, 26, 52, 48, 60, 75, 85, + 95, 102, 104, 102, 111, 107, 113, 110, 109, 111, 103, 107, 102, 97, 96, 95, + 85, 77, 73, 56, 60, 52, 37, 33, 22, 16, 11, 7, -3, -4, -6, -16, + -14, -21, -24, -24, -28, -32, -37, -38, -42, -36, -37, -39, -39, -43, -40, -42, + -48, -50, -50, -64, -57, -70, -84, -63, -90, -81, -77, -101, -85, -99, -105, -102, + -100, -92, -99, -79, -89, -86, -58, -65, -49, -29, -41, -26, -11, -19, 6, 12, + 14, 39, 37, 52, 60, 68, 90, 90, 104, 102, 106, 111, 108, 118, 109, 109, + 111, 98, 106, 101, 90, 101, 90, 82, 86, 63, 65, 63, 48, 47, 29, 25, + 16, 10, 6, -6, -3, -13, -18, -16, -26, -25, -25, -32, -30, -39, -43, -37, + -43, -39, -39, -48, -44, -46, -53, -50, -56, -59, -59, -67, -72, -77, -76, -84, + -83, -84, -100, -95, -103, -115, -98, -93, -103, -82, -82, -91, -60, -62, -54, -34, + -35, -31, -23, -13, -11, 7, 19, 21, 43, 48, 55, 73, 85, 94, 104, 102, + 109, 110, 105, 118, 107, 109, 113, 98, 106, 103, 96, 99, 98, 90, 82, 79, + 62, 62, 58, 41, 34, 26, 14, 10, 8, -3, -2, -5, -14, -13, -20, -20, + -24, -26, -28, -38, -39, -42, -42, -41, -41, -42, -48, -41, -43, -50, -41, -49, + -59, -50, -68, -74, -67, -82, -80, -89, -87, -101, -101, -93, -121, -85, -90, -105, + -65, -93, -82, -55, -69, -49, -38, -46, -32, -27, -19, -5, 3, 19, 26, 41, + 53, 52, 81, 81, 95, 104, 90, 113, 101, 105, 118, 99, 113, 109, 100, 109, + 104, 98, 104, 96, 89, 83, 71, 66, 57, 56, 38, 28, 29, 8, 17, 6, + -2, 3, -24, -13, -79, -103, -120, -116, -104, -87, -76, -63, 63, 82, 97, 108, + 119, 99, 70, 69, 80, 91, 92, 98, 115, 124, 127, 113, 82, 42, 4, -44, + -70, -82, -100, -87, -62, -58, -71, -65, -79, -60, -102, -113, -62, -44, -31, -31, + -22, -18, -3, 4, 11, 20, 28, 11, 15, 18, 27, 18, 7, 13, 26, 11, + -19, -69, -108, -84, -51, -21, -3, -6, -18, -17, -31, -33, -18, 2, 4, 26, + 47, 48, 77, 117, 127, 127, 127, 121, 110, 86, 72, 62, 46, 11, 17, -2, + -7, -13, -44, -60, -61, -61, -63, -72, -79, -99, -116, -127, -128, -128, -124, -81, + -51, -4, 5, -6, 7, 8, 9, 31, 31, 16, 34, 28, 34, 34, 46, 78, + 84, 93, 69, 47, 40, 64, 44, 27, 22, 0, -29, -8, 15, -6, -36, -66, + -68, -42, 0, 6, 1, 13, 24, 41, 64, 58, 50, 40, 4, 0, 3, -24, + -3, 21, 28, 26, 9, -30, -42, -61, -85, -92, -91, -96, -87, -74, -31, -20, + -38, -14, -44, -17, 18, -25, -9, 7, 1, 11, -2, -19, 12, 47, 76, 72, + 58, 68, 69, 82, 86, 76, 58, 9, -23, -12, -7, -22, -2, 0, -9, -2, + -15, -10, -3, -22, -17, -38, -44, -33, -24, -27, -16, 0, -15, 20, 19, 18, + 1, 10, 41, -1, -25, -25, -11, 30, 37, 9, 45, 37, -30, -30, 21, 5, + -26, -43, -56, -42, -48, -48, -29, -62, -76, -42, -23, -12, -14, 8, 45, 36, + 40, 25, 14, 11, 40, 46, 55, 65, 30, 17, 30, 36, 33, 18, 13, 16, + 15, 46, 37, 2, -1, -26, -36, -19, -21, -36, -62, -51, -48, -20, -2, 3, + -12, -12, -10, -35, -37, -49, -22, 14, 61, 40, 60, 75, 33, 41, 48, 38, + 29, -32, -45, -56, -64, -61, -30, -20, 30, 10, -46, -37, -35, -30, -24, -12, + -23, -34, -29, -22, -20, -14, 4, 44, 77, 49, 10, 8, 24, 20, 28, 31, + 27, 40, 35, 69, 39, 54, 38, 26, 22, 43, 36, 7, 14, 2, -25, -50, + -51, -56, -42, -55, -46, -36, -44, -36, -35, 1, 23, 11, -3, -34, -66, -33, + -12, -31, -27, -13, -1, 21, 31, 23, 0, -11, -3, -2, 9, 27, 5, -8, + -2, -17, -13, 10, 9, 3, 35, 32, 43, 24, 15, 2, -15, -9, -5, 2, + 5, 27, 25, 42, 76, 61, 17, 25, 14, -5, -17, -24, -6, 11, 23, 7, + -8, 5, -11, -23, -27, -48, -30, -12, -26, -36, -37, -39, -46, -61, -55, -23, + -20, -22, -14, -10, -16, -16, -22, -11, -3, -14, -34, -16, 9, 28, 25, 50, + 63, 52, 56, 46, 50, 54, 56, 45, 54, 29, 20, 21, 0, 0, 6, 16, + 28, 14, -1, -9, -10, -4, -9, -13, -7, -21, -27, -29, -40, -41, -35, -42, + -64, -11, 9, 2, -12, -24, -37, -40, -34, -29, -34, -12, -26, -20, -6, -4, + 5, 5, 27, 1, -17, 2, 21, 12, 8, 9, 15, 23, 24, 1, 5, 22, + 25, 28, 57, 55, 41, 33, 36, 27, 5, 1, 15, 34, 23, 4, 20, 18, + -1, -21, -22, -15, -17, -8, -6, -6, -12, -15, -26, 1, 29, -8, -40, -52, + -55, -19, -21, -36, -48, -56, -29, -15, -29, -39, -46, -35, -14, -11, -16, 1, + 27, 22, -10, -14, -7, -12, -12, 23, 55, 48, 65, 42, 20, 46, 45, 49, + 42, 38, 34, 25, 33, 21, 10, 38, 40, 26, 22, 37, 33, 12, 4, 7, + -14, -49, -41, -36, -53, -40, -35, -44, -31, -22, -19, -50, -78, -80, -78, -48, + -31, -18, -27, -28, -7, -17, -11, 5, 32, 39, 19, 14, 22, 34, 37, 23, + 20, 40, 40, 27, 14, 11, 7, 29, 34, 19, 32, 7, -15, -12, -24, -12, + 8, 6, 21, 34, 29, -6, -22, -15, 1, -1, 24, 27, 20, 36, 42, 45, + 27, -14, -50, -34, -14, -26, -25, -10, 10, -4, -28, -30, -34, -69, -91, -85, + -74, -51, -38, -24, -19, -9, -7, -30, -35, -30, -36, -12, 25, 32, 44, 50, + 45, 51, 68, 94, 90, 74, 60, 52, 64, 48, 30, 11, 11, 11, 2, 14, + 24, 16, 13, -7, -17, -9, -12, -20, -32, -45, -54, -58, -35, -23, -46, -51, + -33, -28, -29, -24, -36, -30, -24, -22, -20, -13, -9, -14, -7, 10, 26, 22, + 9, 9, 10, -2, -9, -15, -11, -1, 19, 27, 33, 28, 5, 3, 5, 6, + 10, 14, 24, 32, 36, 40, 41, 37, 19, 11, 3, -7, -10, -7, 6, 27, + 38, 28, 23, 16, 18, 15, -7, -33, -20, -13, -24, -25, -19, -15, -26, -52, + -56, -48, -41, -36, -30, -32, -30, -15, -38, -49, -47, -32, -17, -17, -11, -3, + 3, 8, 24, 28, 16, 6, 1, 7, 28, 41, 42, 69, 87, 78, 73, 62, + 30, 14, 9, 7, 15, 32, 20, 10, -8, -20, 2, 9, -2, 5, 12, -4, + -12, -19, -32, -37, -29, -24, -28, -39, -43, -40, -44, -28, -25, -33, -39, -37, + -34, -29, -28, -25, -19, -1, -5, -22, -12, 2, 6, 38, 46, 25, 30, 41, + 47, 37, 21, 7, -7, -8, 11, 39, 48, 43, 35, 27, 25, 22, -1, -22, + -11, 13, -4, -13, -3, -8, -7, -11, -17, -5, 5, 9, 8, 15, 25, 16, + 22, 20, 5, -16, -27, -29, -30, -9, 9, 9, 3, -14, -50, -56, -56, -79, + -92, -80, -57, -24, 12, 10, 11, 4, -22, -21, -13, -2, 4, 10, 15, 8, + 35, 72, 53, 44, 25, 25, 48, 56, 69, 53, 50, 75, 85, 71, 33, 12, + -16, -32, -25, -14, -5, -16, -23, -19, -22, -39, -41, -47, -45, -33, -35, -39, + -38, -35, -34, -29, -28, -28, -23, -10, -7, -9, -11, -18, -5, 13, 1, -13, + -8, -5, 6, 27, 46, 43, 25, 8, 11, 16, 18, 23, 30, 12, 5, 10, + 7, 5, -6, -4, -5, 1, 10, 9, 15, 21, 17, 10, -8, -16, 10, 33, + 34, 23, 13, 17, 17, 9, 11, 7, -4, -8, -8, -22, -27, -26, -19, -7, + -18, -16, -16, -47, -62, -55, -36, -16, -25, -33, -30, -34, -42, -49, -41, -43, + -31, -20, -3, 28, 48, 66, 64, 36, 20, 26, 21, 22, 39, 51, 45, 39, + 40, 53, 56, 39, 24, 16, 12, 16, 24, 27, 16, 13, 7, -18, -33, -50, + -47, -33, -24, -20, -26, -32, -31, -46, -53, -58, -56, -29, -13, -11, -2, 8, + -11, -24, -11, -9, -6, -2, -6, 1, 4, 5, 11, 6, 7, 16, 30, 28, + 19, 15, 7, 4, 11, 27, 22, 6, 9, 11, 3, 4, 17, 27, 18, 11, + 12, 5, 2, -2, -6, -7, -2, 10, 12, 9, 1, -2, 3, 4, 11, 21, + 30, 28, 6, -9, -18, -22, -22, -38, -41, -27, -18, -18, -27, -27, -23, -32, + -35, -32, -34, -30, -25, -24, -18, -9, -5, 5, -5, -26, -19, -11, -4, 11, + 37, 48, 46, 50, 53, 50, 45, 45, 37, 18, 24, 44, 38, 43, 47, 29, + 15, 11, 10, 12, 4, -8, -6, -4, -17, -27, -28, -36, -34, -37, -53, -53, + -46, -38, -38, -37, -28, -24, -23, -37, -42, -30, 0, 20, 18, 12, 14, 9, + 2, 6, 15, 13, 10, 14, 12, 2, 12, 29, 21, 1, 7, 21, 19, 14, + 15, 15, 4, -1, 5, -1, -4, 0, -2, 3, 6, 6, 13, 21, 15, 7, + 3, 5, 2, -3, 3, 3, 5, 8, 10, 16, 14, -1, -7, 2, 11, 12, + -10, -35, -42, -26, -21, -37, -44, -44, -47, -42, -27, -27, -23, -15, -16, -20, + -21, -14, -12, -9, -7, -6, 0, 13, 30, 32, 37, 38, 31, 24, 25, 43, + 54, 49, 46, 44, 40, 41, 30, 9, -1, 6, 22, 31, 22, 9, 0, -14, + -23, -29, -29, -28, -35, -39, -39, -39, -33, -25, -30, -44, -49, -45, -45, -35, + -19, 2, 16, 16, 9, 0, 0, 6, 2, -1, 11, 27, 40, 32, 16, -2, + -2, 1, 3, 1, 7, 12, 6, 8, 11, 5, -1, -2, -1, 1, 8, 10, + 5, 4, 14, 17, 6, -1, 0, 4, 4, 17, 23, 19, 25, 20, 5, -8, + -9, -2, -1, -6, -3, 13, 16, 1, -13, -19, -21, -26, -34, -37, -23, -13, + -13, -24, -40, -42, -40, -39, -29, -22, -21, -18, -12, -2, 18, 24, 10, 0, + -6, -4, 15, 33, 34, 34, 44, 41, 31, 33, 44, 43, 31, 22, 20, 17, + 16, 23, 22, 19, 21, 10, -5, -6, -9, -8, -2, -5, -16, -28, -36, -47, + -53, -39, -23, -21, -24, -32, -43, -39, -34, -24, -18, -14, -11, -12, -6, 10, + 29, 41, 40, 27, 14, 10, 4, 1, 3, 2, 9, 19, 21, 9, -10, -16, + -10, 8, 18, 20, 13, -3, -8, -4, -1, 2, 5, 5, -1, 3, 9, 12, + 16, 16, 14, 9, 3, 5, 10, 4, -6, 1, 6, 5, 13, 20, 11, 1, + -7, -21, -30, -25, -12, -9, -13, -19, -24, -29, -34, -30, -32, -39, -33, -24, + -20, -22, -24, -13, 3, 6, 2, 1, 3, 5, 16, 30, 35, 35, 24, 16, + 15, 19, 31, 37, 33, 28, 29, 29, 30, 26, 20, 15, 13, 10, 10, 12, + 9, 7, -3, -21, -39, -44, -43, -42, -34, -26, -23, -18, -12, -18, -32, -36, + -31, -27, -20, -10, -7, -9, -11, -5, 2, 12, 19, 19, 25, 24, 11, 3, + 15, 29, 30, 20, 9, 1, -1, 1, 5, 2, -3, -2, 0, -6, -18, -27, + -20, -3, 8, 13, 15, 11, 7, 10, 18, 16, 10, 6, 3, -1, 1, 11, + 19, 19, 15, 14, 5, -2, -2, -7, -12, -15, -20, -16, -10, -5, 2, 1, + -13, -29, -33, -24, -10, -6, -13, -18, -23, -31, -32, -26, -22, -18, -13, -3, + 2, 3, 7, 8, 10, 19, 27, 32, 33, 33, 35, 38, 43, 41, 29, 9, + -4, -9, 2, 16, 17, 13, 15, 17, 13, 10, 5, -1, -8, -18, -29, -32, + -27, -21, -22, -30, -31, -31, -33, -31, -27, -18, -7, -6, -15, -16, -8, -1, + 4, 12, 18, 22, 20, 16, 11, 10, 14, 18, 16, 15, 14, 9, 6, 4, + 3, 3, 0, -5, -13, -18, -15, -13, -9, -7, -8, -5, -2, -5, -1, 5, + 8, 10, 11, 12, 17, 19, 16, 10, 4, 4, 8, 8, 8, 13, 14, 9, + 3, 0, -1, 0, 0, -7, -19, -24, -20, -15, -12, -15, -21, -23, -24, -26, + -28, -29, -28, -21, -10, -1, 5, 6, -3, -12, -14, -11, -1, 12, 16, 17, + 28, 36, 28, 20, 25, 27, 24, 25, 28, 21, 15, 11, 3, 4, 12, 11, + 0, -7, -5, -1, -1, -5, -8, -11, -17, -23, -22, -19, -21, -20, -20, -22, + -24, -22, -17, -20, -24, -20, -10, 2, 10, 13, 14, 14, 11, 8, 8, 12, + 17, 18, 20, 20, 14, 4, -1, -2, -1, 3, 11, 12, 6, 0, -9, -20, + -25, -18, -9, -8, -13, -18, -19, -14, -6, 0, 4, 11, 19, 22, 20, 19, + 15, 13, 14, 18, 17, 12, 7, 9, 14, 9, -1, -4, -1, -5, -10, -12, + -16, -23, -19, -7, -5, -10, -10, -11, -19, -27, -24, -14, -6, -3, -10, -21, + -24, -15, -6, 0, 9, 15, 12, 8, 6, 9, 9, 11, 20, 26, 31, 35, + 30, 21, 16, 16, 13, 6, 2, 4, 5, 3, -2, -10, -13, -11, -8, -9, + -13, -16, -18, -18, -19, -22, -18, -8, -3, -1, 0, -5, -11, -10, -9, -11, + -9, -2, 2, 4, 10, 15, 18, 19, 21, 21, 22, 22, 15, 4, -4, -8, + -7, -6, -10, -14, -18, -23, -20, -15, -8, -1, 0, -4, -7, -9, -9, -6, + -2, 2, 6, 7, 4, 1, 0, 7, 13, 11, 14, 22, 22, 15, 8, 2, + 4, 10, 16, 17, 13, 10, 9, 6, -3, -13, -23, -26, -21, -17, -14, -12, + -13, -16, -14, -9, -8, -8, -11, -18, -18, -12, -4, 0, 2, 6, 6, -1, + -6, 0, 8, 11, 13, 11, 6, 6, 9, 13, 16, 16, 15, 10, 7, 10, + 10, 4, 0, -2, -3, -1, 2, 2, -1, -5, -13, -21, -27, -30, -26, -16, + -4, 5, 8, 6, 2, -3, -5, -1, 4, 8, 9, 11, 11, 6, 0, 0, + 7, 12, 13, 11, 7, 1, -4, -3, 0, 5, 6, 5, -2, -10, -13, -13, + -10, -5, -4, -9, -18, -28, -31, -24, -14, -10, -4, 2, 5, 4, 2, 4, + 13, 20, 21, 19, 14, 11, 11, 12, 13, 14, 15, 17, 18, 18, 14, 5, + -3, -5, -8, -11, -11, -12, -15, -15, -13, -13, -15, -13, -12, -15, -16, -11, + -7, -6, -4, -1, 4, 6, -1, -10, -11, -7, -4, -1, 4, 9, 11, 12, + 9, 7, 8, 8, 7, 9, 13, 15, 12, 4, 1, 1, -2, -9, -10, -7, + -1, 3, 3, -1, -9, -12, -9, -5, 1, 3, -2, -10, -10, -7, -4, 2, + 8, 6, 4, 6, 5, -1, -1, 7, 17, 20, 17, 16, 19, 16, 7, -3, + -8, -9, -9, -11, -15, -24, -27, -20, -15, -12, -11, -7, -3, -4, -6, -7, + -6, -8, -14, -18, -18, -15, -10, -5, 3, 12, 18, 20, 17, 11, 10, 16, + 21, 22, 23, 23, 22, 17, 9, 0, -3, 2, 10, 15, 16, 11, 2, -9, + -19, -23, -22, -15, -10, -8, -11, -13, -15, -17, -19, -18, -15, -10, -3, 1, + -2, -6, -3, 0, -3, -3, 0, 6, 10, 9, 7, 4, -1, -4, 0, 10, + 17, 16, 11, 5, 0, -1, 2, 5, 1, -6, -10, -10, -8, -6, -4, -2, + -4, -7, -9, -9, -6, 2, 12, 17, 16, 11, 8, 7, 6, 5, 7, 9, + 12, 14, 14, 9, 3, -1, -3, -5, -4, 0, 4, -1, -10, -18, -24, -29, + -28, -20, -14, -13, -12, -8, -5, -5, -9, -13, -14, -11, -10, -9, -4, 1, + 3, 2, 3, 8, 16, 20, 18, 13, 10, 14, 24, 29, 29, 27, 23, 17, + 14, 16, 17, 15, 9, -1, -7, -10, -14, -18, -16, -11, -8, -7, -8, -12, + -18, -26, -29, -26, -19, -11, -5, -3, -3, -2, 0, 2, 0, -3, -3, -2, + -3, -4, -2, -1, 3, 7, 9, 8, 7, 3, 1, 4, 5, 2, 3, 5, + 5, 0, -7, -9, -6, -1, 5, 9, 8, 3, -2, -6, -5, 3, 9, 12, + 11, 8, 4, 3, 4, 6, 11, 13, 8, 1, 0, 4, 9, 13, 12, 5, + 2, 3, 3, 0, -6, -16, -26, -30, -28, -26, -22, -18, -17, -19, -22, -24, + -19, -12, -7, -2, 1, 0, -2, -4, -5, -2, 4, 10, 14, 15, 15, 16, + 16, 17, 19, 22, 26, 25, 19, 13, 10, 7, 9, 11, 10, 7, 4, 1, + -5, -8, -8, -4, 0, 1, -4, -11, -16, -17, -16, -14, -12, -10, -11, -14, + -15, -16, -13, -9, -3, 1, 2, 1, 0, 0, -3, -9, -13, -10, -8, -7, + -4, 0, 3, 6, 9, 9, 5, 3, 3, 5, 8, 12, 12, 6, -1, -2, + 2, 8, 8, 4, -2, -5, -1, 4, 10, 13, 14, 13, 13, 14, 14, 12, + 10, 8, 8, 8, 6, 6, 9, 6, -1, -9, -15, -19, -22, -24, -23, -25, + -25, -23, -20, -19, -19, -21, -20, -20, -21, -19, -11, -2, 2, 1, 0, 3, + 9, 13, 15, 16, 14, 10, 5, 3, 8, 14, 16, 18, 20, 22, 24, 21, + 15, 9, 6, 8, 14, 18, 15, 9, 4, 1, 0, -2, -4, -4, -3, -3, + -4, -7, -11, -13, -12, -11, -15, -19, -22, -25, -25, -21, -14, -11, -15, -19, + -18, -14, -7, -1, 4, 2, -3, -6, -4, 0, 5, 10, 16, 17, 12, 7, + 2, -1, -3, 0, 3, 6, 10, 14, 12, 6, 2, 5, 10, 15, 18, 18, + 16, 14, 11, 6, 4, 3, 1, 1, 2, 6, 9, 9, 3, -2, -3, -4, + -6, -8, -10, -15, -19, -20, -19, -18, -17, -15, -16, -17, -18, -20, -22, -21, + -16, -11, -4, 1, 0, -4, -4, -1, 1, 2, 4, 4, 3, 3, 4, 7, + 11, 16, 21, 20, 15, 11, 9, 12, 16, 21, 24, 23, 21, 17, 13, 11, + 9, 4, 0, 0, 1, 3, 4, 0, -4, -7, -7, -9, -13, -17, -20, -22, + -23, -21, -16, -12, -12, -15, -17, -17, -15, -12, -10, -10, -11, -12, -15, -15, + -10, -4, 0, -1, -1, 1, 4, 7, 13, 19, 22, 23, 21, 19, 18, 17, + 11, 5, 2, 5, 10, 13, 15, 15, 14, 13, 10, 5, 1, 0, 2, 5, + 8, 10, 9, 6, 4, 2, -1, -5, -7, -8, -7, -8, -11, -13, -14, -16, + -19, -21, -22, -22, -24, -23, -20, -17, -16, -16, -15, -16, -16, -15, -13, -11, + -9, -5, 0, 6, 12, 15, 18, 18, 17, 17, 19, 20, 19, 19, 20, 23, + 25, 25, 23, 20, 17, 13, 11, 9, 9, 8, 6, 3, 1, -2, -5, -5, + -2, -1, -3, -7, -6, -3, 0, -2, -9, -21, -29, -32, -32, -30, -27, -27, + -29, -30, -28, -24, -23, -21, -16, -7, 0, 1, 2, 2, 4, 7, 10, 14, + 16, 14, 12, 13, 15, 18, 20, 22, 23, 20, 15, 8, 3, 2, 7, 13, + 15, 13, 7, 2, 0, 0, -1, -2, -1, 1, 2, 1, 0, 2, 3, 4, + 4, 6, 7, 5, 0, -10, -21, -30, -36, -36, -33, -28, -23, -18, -15, -14, + -17, -19, -19, -17, -12, -5, -2, -2, -3, -1, 2, 6, 10, 12, 14, 13, + 12, 13, 18, 25, 29, 28, 24, 19, 14, 10, 6, 6, 9, 12, 13, 15, + 17, 18, 18, 14, 7, 0, -1, 1, 1, -2, -6, -8, -10, -11, -13, -17, + -19, -18, -17, -16, -14, -14, -15, -17, -19, -22, -26, -26, -24, -20, -17, -14, + -13, -12, -10, -7, -4, 1, 5, 7, 9, 10, 13, 15, 17, 18, 21, 24, + 22, 21, 19, 17, 15, 13, 14, 14, 16, 17, 18, 16, 12, 10, 8, 6, + 5, 3, 0, -3, -6, -7, -5, -4, -4, -5, -5, -4, -4, -4, -8, -13, + -19, -24, -27, -28, -27, -25, -25, -27, -27, -25, -19, -14, -8, -3, 1, 6, + 9, 8, 3, -3, -6, -4, -1, 4, 9, 14, 18, 20, 22, 22, 23, 23, + 22, 21, 20, 20, 21, 21, 19, 15, 9, 3, -2, -4, -3, 0, 2, 2, + 2, 3, 3, 1, -4, -10, -15, -19, -19, -16, -11, -7, -7, -9, -13, -17, + -23, -28, -30, -29, -24, -20, -18, -19, -20, -19, -18, -19, -18, -13, -5, 1, + 6, 9, 11, 13, 16, 21, 26, 29, 30, 29, 29, 28, 26, 23, 20, 20, + 21, 21, 20, 18, 15, 9, 2, -4, -6, -5, -3, -3, -4, -6, -7, -9, + -10, -10, -10, -10, -11, -13, -12, -11, -8, -6, -6, -10, -17, -26, -32, -35, + -35, -34, -32, -27, -19, -9, -3, -1, -2, -5, -7, -6, -1, 7, 14, 18, + 21, 23, 25, 26, 26, 23, 20, 20, 23, 24, 24, 21, 19, 14, 8, 2, + -1, 0, 1, 2, 3, 6, 8, 8, 5, 2, -2, -5, -5, -4, -1, 1, + 1, -1, -6, -9, -11, -13, -17, -20, -24, -26, -27, -26, -23, -21, -20, -23, + -26, -27, -26, -24, -20, -15, -9, -2, 4, 8, 10, 13, 16, 19, 21, 23, + 25, 28, 33, 36, 38, 38, 35, 32, 29, 24, 16, 11, 6, 2, -2, -6, + -6, -5, -4, -4, -7, -11, -14, -13, -10, -8, -8, -8, -9, -11, -12, -12, + -11, -11, -12, -14, -17, -19, -19, -18, -18, -20, -22, -23, -21, -18, -14, -11, + -8, -4, -1, 5, 11, 13, 11, 8, 6, 7, 9, 11, 13, 15, 19, 22, + 23, 25, 27, 27, 22, 17, 11, 6, 4, 5, 9, 13, 15, 15, 11, 6, + 0, -4, -7, -8, -6, -3, -2, -3, -6, -9, -13, -18, -22, -23, -20, -15, + -11, -10, -11, -14, -19, -24, -27, -28, -28, -27, -26, -23, -19, -15, -10, -6, + -1, 4, 8, 10, 11, 11, 13, 15, 17, 20, 23, 24, 24, 26, 28, 28, + 28, 27, 26, 24, 22, 20, 16, 13, 10, 8, 6, 3, -3, -9, -15, -17, + -16, -15, -13, -13, -14, -17, -19, -20, -20, -17, -14, -12, -13, -14, -13, -13, + -14, -15, -14, -13, -12, -12, -12, -10, -8, -7, -8, -9, -9, -7, -4, 0, + 3, 6, 8, 10, 12, 14, 18, 22, 25, 26, 27, 28, 28, 27, 24, 20, + 16, 13, 11, 9, 6, 3, 0, -3, -3, -2, 1, 3, 5, 3, 0, -4, + -8, -12, -17, -21, -22, -20, -17, -15, -14, -14, -13, -15, -19, -22, -21, -18, + -14, -13, -15, -16, -17, -17, -19, -19, -16, -11, -4, 1, 6, 10, 13, 17, + 20, 23, 24, 24, 24, 25, 28, 33, 37, 38, 35, 30, 24, 20, 16, 13, + 9, 2, -4, -8, -8, -8, -7, -7, -9, -12, -16, -18, -18, -16, -15, -16, + -16, -16, -13, -10, -10, -11, -13, -15, -15, -15, -15, -16, -17, -16, -14, -13, + -13, -13, -13, -12, -9, -5, -2, 1, 3, 6, 12, 18, 22, 22, 21, 18, + 16, 16, 19, 23, 29, 32, 30, 24, 18, 13, 9, 6, 3, 0, -2, -4, + -6, -8, -10, -11, -10, -6, -3, -2, -3, -5, -5, -6, -6, -7, -6, -5, + -4, -5, -8, -10, -11, -12, -14, -16, -18, -20, -21, -21, -22, -23, -24, -24, + -22, -18, -11, -4, 1, 4, 5, 6, 8, 11, 15, 20, 24, 26, 27, 28, + 31, 32, 31, 30, 28, 27, 24, 20, 17, 14, 12, 9, 3, -3, -9, -12, + -15, -16, -17, -15, -13, -10, -10, -11, -13, -14, -15, -17, -19, -21, -23, -24, + -22, -18, -13, -9, -8, -8, -8, -9, -9, -9, -7, -4, 0, 2, 3, 5, + 5, 3, 3, 4, 5, 6, 7, 10, 14, 17, 20, 20, 20, 21, 22, 20, + 18, 16, 15, 14, 12, 9, 7, 6, 4, 2, -2, -5, -7, -9, -9, -8, + -5, -2, 0, 0, -1, -3, -7, -12, -16, -16, -15, -13, -12, -13, -13, -12, + -11, -11, -12, -15, -19, -23, -24, -22, -19, -16, -13, -10, -5, -1, 3, 6, + 7, 8, 8, 10, 13, 17, 21, 25, 27, 28, 28, 26, 24, 24, 25, 27, + 28, 29, 28, 25, 19, 12, 4, -3, -10, -15, -19, -22, -24, -25, -26, -25, + -23, -21, -20, -18, -17, -16, -14, -12, -11, -12, -14, -14, -13, -13, -15, -16, + -16, -16, -15, -11, -4, 0, -2, 0, 0, 3, 14, 34, 24, -3, -14, -12, + 6, 6, -11, -23, -5, 15, 20, 15, -19, -12, 3, 19, 11, -5, 1, 4, + 7, -13, -3, 5, -13, 0, -2, 8, 0, -6, 16, 23, 13, 6, 2, 14, + 25, 2, 11, 3, -7, -8, -24, -6, -4, -18, 6, 30, 14, 9, 0, 0, + 13, -7, 0, -3, 9, 8, -6, -14, -15, -23, -19, -7, 0, -3, 1, -8, + -10, -10, -17, -12, -7, -10, 1, -12, -13, 0, -15, -20, -25, -16, -6, -7, + -6, -6, -2, -4, -13, -12, -6, -6, -5, 2, 8, -5, -13, -3, -4, -11, + -16, -3, 12, -2, -8, -4, -4, 4, -15, -17, -6, -2, 5, -4, 3, -2, + -10, -4, -5, -7, -8, 4, 17, 1, -3, -14, -4, -2, -7, -4, -6, 10, + 5, -6, -7, -8, 10, -5, -3, 3, -8, 11, 7, -5, -3, -13, -7, 0, + -6, 4, 0, -7, 12, -9, -17, -7, 5, 2, -3, -4, -7, 7, -2, -13, + -5, -2, 5, 4, 0, 7, -3, 4, 1, -2, -4, 6, 8, 8, 0, -2, + 2, 3, 2, 1, -2, 5, 12, 6, 3, 2, -3, 2, 3, 1, 8, 6, + 7, 2, -5, -3, 1, 5, 2, 0, -3, 2, 7, 2, 0, -9, 0, 5, + 1, 3, 1, 4, 6, -5, -3, -2, 2, 6, 4, 6, 1, 2, 4, 4, + -2, 2, 5, 5, 7, 7, 2, 6, 0, 3, 0, -3, 8, 4, 4, 9, + -3, 2, 1, 1, 2, 1, 5, 5, 4, 6, 1, -6, -2, 3, 5, 6, + 4, 3, 4, 1, 2, -4, 0, 6, 2, 2, 4, 3, 5, -3, -2, -5, + -3, 5, 2, 1, 3, 1, -2, -3, -4, -6, 3, 5, 1, -2, 1, 2, + -2, -2, -2, -3, 3, 5, 3, 4, 2, 2, 1, 0, 1, 4, 9, 9, + 5, 2, 1, 6, 4, 4, 5, 5, 7, 8, 4, 5, 1, 2, 3, 1, + 1, 4, 2, 3, 0, -4, -7, -5, 0, -3, -3, -3, -5, 0, -8, -7, + -8, -5, -3, -6, -3, -4, -5, 0, -7, -4, -5, -3, 1, 1, -2, 1, + -2, 2, 0, 0, -2, 3, 5, 4, 5, 4, 2, 4, 2, 4, 5, 6, + 5, 6, 4, 4, 4, 4, 3, 4, 2, 4, 4, 2, -2, -2, 0, -3, + -3, -3, -4, -2, -7, -6, -7, -9, -7, -10, -9, -10, -10, -8, -11, -9, + -9, -12, -10, -13, -12, -7, -8, -6, -6, -9, -6, -5, -3, 0, 0, 1, + 1, 4, 3, 4, 8, 6, 8, 7, 6, 10, 9, 12, 12, 11, 12, 8, + 13, 10, 11, 10, 8, 9, 8, 6, 9, 4, 5, 0, -3, -5, -5, -6, + -7, -9, -12, -15, -17, -21, -18, -22, -21, -23, -25, -24, -27, -27, -26, -30, + -27, -27, -28, -20, -22, -19, -14, -15, -12, -10, -10, -2, 3, 4, 12, 12, + 14, 20, 17, 25, 27, 29, 33, 35, 35, 40, 38, 41, 39, 36, 38, 36, + 36, 38, 31, 33, 25, 21, 14, 8, 1, 2, 0, -3, -5, -15, -23, -28, + -40, -39, -43, -46, -43, -52, -53, -59, -66, -62, -69, -63, -64, -64, -50, -56, + -44, -45, -43, -38, -36, -31, -20, -8, 4, 12, 19, 18, 28, 31, 40, 52, + 57, 68, 73, 73, 77, 73, 81, 79, 82, 82, 77, 82, 77, 75, 69, 59, + 53, 42, 33, 24, 22, 17, 11, 1, -17, -25, -36, -42, -46, -55, -60, -64, + -73, -77, -88, -90, -92, -97, -98, -100, -100, -92, -85, -79, -80, -76, -79, -69, + -56, -50, -32, -24, -15, 0, -2, 11, 15, 29, 45, 55, 67, 72, 82, 88, + 95, 101, 102, 109, 109, 112, 109, 110, 110, 106, 104, 91, 81, 77, 68, 66, + 54, 42, 32, 14, 6, -6, -12, -20, -29, -43, -55, -65, -76, -76, -85, -89, + -97, -105, -107, -114, -115, -117, -117, -113, -112, -104, -101, -91, -85, -84, -70, -72, + -55, -42, -34, -14, -8, 5, 16, 22, 35, 44, 57, 69, 78, 89, 94, 101, + 104, 109, 109, 119, 118, 117, 120, 110, 114, 114, 99, 102, 84, 74, 72, 57, + 52, 43, 32, 22, 10, -7, -20, -28, -34, -47, -54, -60, -67, -71, -80, -87, + -90, -105, -105, -110, -120, -115, -120, -123, -113, -111, -109, -97, -98, -92, -83, -82, + -76, -63, -61, -48, -39, -30, -16, -3, 10, 22, 32, 42, 49, 61, 67, 76, + 84, 91, 101, 105, 115, 116, 117, 125, 115, 119, 116, 106, 111, 102, 97, 92, + 84, 79, 70, 64, 50, 45, 31, 19, 14, -2, -9, -19, -30, -35, -47, -54, + -62, -67, -73, -82, -86, -96, -100, -105, -109, -116, -118, -120, -120, -117, -111, -110, + -97, -96, -90, -84, -78, -73, -64, -55, -50, -39, -25, -20, 1, 11, 19, 37, + 40, 51, 61, 68, 76, 85, 94, 97, 105, 114, 112, 120, 122, 119, 121, 117, + 110, 106, 105, 92, 90, 84, 69, 71, 57, 48, 45, 29, 22, 14, -2, -9, + -22, -31, -40, -47, -59, -62, -68, -76, -80, -87, -97, -96, -111, -111, -116, -124, + -119, -123, -120, -109, -109, -98, -95, -93, -84, -81, -75, -66, -55, -51, -37, -28, + -16, 1, 12, 23, 39, 40, 55, 59, 68, 77, 86, 94, 103, 104, 116, 117, + 118, 125, 122, 117, 120, 107, 108, 104, 95, 92, 85, 72, 70, 60, 48, 43, + 29, 18, 10, -7, -12, -22, -30, -38, -49, -58, -63, -72, -75, -84, -90, -93, + -100, -110, -103, -121, -115, -115, -124, -110, -112, -111, -92, -98, -86, -81, -77, -69, + -61, -53, -48, -34, -27, -13, 1, 9, 28, 37, 45, 58, 59, 76, 78, 85, + 97, 98, 109, 114, 111, 123, 120, 119, 121, 116, 111, 110, 101, 93, 92, 79, + 73, 68, 55, 52, 40, 30, 21, 10, 0, -13, -23, -29, -41, -47, -58, -64, + -69, -75, -84, -89, -93, -103, -105, -110, -120, -115, -117, -128, -105, -114, -109, -88, + -102, -86, -76, -84, -64, -63, -56, -43, -37, -25, -10, 4, 11, 31, 36, 46, + 56, 58, 74, 78, 84, 100, 95, 110, 114, 110, 124, 120, 116, 121, 110, 105, + 108, 97, 96, 91, 79, 75, 66, 57, 51, 38, 29, 17, 5, -3, -13, -20, + -28, -40, -46, -55, -66, -68, -76, -85, -88, -97, -102, -106, -110, -117, -115, -120, + -122, -108, -117, -103, -98, -96, -86, -79, -77, -66, -59, -54, -46, -33, -31, -10, + -2, 11, 27, 36, 47, 58, 62, 74, 78, 86, 94, 96, 106, 109, 115, 120, + 118, 121, 119, 112, 114, 104, 98, 94, 85, 77, 72, 63, 56, 49, 37, 31, + 20, 6, -2, -15, -24, -33, -44, -50, -58, -63, -68, -76, -82, -89, -95, -105, + -105, -116, -118, -117, -126, -114, -111, -118, -92, -105, -92, -83, -88, -72, -71, -65, + -51, -50, -31, -25, -9, 2, 16, 29, 35, 50, 53, 67, 73, 75, 92, 88, + 104, 112, 108, 122, 117, 119, 123, 114, 116, 110, 104, 98, 94, 86, 80, 75, + 63, 59, 47, 36, 29, 13, 9, -5, -16, -21, -36, -40, -50, -61, -61, -73, + -77, -85, -93, -95, -103, -108, -117, -120, -118, -125, -117, -108, -116, -96, -98, -97, + -83, -82, -78, -66, -61, -54, -43, -32, -25, -2, 3, 16, 33, 36, 52, 56, + 66, 75, 78, 94, 91, 103, 113, 108, 122, 119, 119, 121, 116, 112, 110, 106, + 93, 96, 83, 76, 74, 59, 58, 47, 34, 28, 14, 6, -6, -17, -27, -36, + -44, -54, -61, -63, -70, -76, -86, -90, -99, -102, -108, -117, -115, -121, -123, -111, + -120, -102, -100, -101, -84, -91, -76, -74, -70, -54, -56, -41, -30, -20, -3, 8, + 23, 31, 46, 47, 59, 70, 71, 83, 89, 90, 108, 108, 115, 120, 121, 122, + 118, 118, 109, 110, 102, 93, 93, 82, 78, 72, 62, 57, 45, 37, 22, 15, + 4, -10, -18, -30, -36, -42, -54, -57, -63, -68, -77, -86, -91, -102, -103, -108, + -117, -114, -119, -117, -115, -110, -106, -100, -91, -99, -79, -81, -77, -59, -61, -50, + -36, -33, -16, -4, 10, 16, 35, 39, 48, 62, 64, 76, 85, 89, 98, 105, + 110, 113, 120, 119, 118, 123, 112, 111, 110, 100, 98, 93, 82, 78, 70, 58, + 54, 45, 30, 24, 12, 0, -7, -20, -28, -36, -45, -55, -61, -66, -73, -79, + -88, -93, -103, -105, -112, -119, -115, -124, -123, -109, -119, -103, -98, -102, -92, -84, + -83, -75, -62, -59, -50, -34, -34, -12, 1, 7, 26, 33, 42, 50, 62, 67, + 76, 88, 90, 101, 110, 108, 118, 121, 119, 122, 121, 111, 113, 110, 98, 98, + 91, 80, 78, 66, 58, 53, 40, 29, 20, 8, -4, -11, -22, -33, -37, -49, + -57, -61, -68, -77, -81, -90, -96, -101, -110, -112, -116, -120, -116, -121, -119, -104, + -111, -96, -91, -96, -79, -79, -76, -59, -57, -46, -33, -25, -14, 5, 11, 26, + 39, 42, 55, 61, 70, 81, 86, 94, 101, 105, 114, 116, 120, 121, 119, 119, + 115, 111, 107, 102, 94, 90, 82, 73, 68, 59, 50, 41, 28, 20, 7, -4, + -12, -22, -30, -41, -48, -56, -62, -69, -75, -83, -90, -98, -100, -107, -111, -119, + -112, -124, -120, -107, -119, -101, -93, -104, -80, -85, -83, -61, -65, -55, -40, -38, + -25, -7, -3, 13, 29, 34, 45, 57, 59, 74, 79, 87, 98, 98, 108, 111, + 112, 122, 117, 119, 119, 111, 110, 107, 96, 96, 89, 76, 74, 63, 54, 51, + 35, 27, 19, 5, -3, -12, -25, -29, -43, -52, -58, -64, -71, -78, -82, -92, + -98, -101, -108, -110, -114, -120, -119, -118, -115, -110, -106, -95, -97, -82, -84, -76, + -62, -63, -51, -42, -39, -20, -12, 2, 15, 29, 36, 47, 58, 62, 74, 80, + 85, 95, 101, 106, 111, 116, 118, 117, 122, 113, 115, 111, 99, 103, 90, 85, + 80, 68, 63, 56, 46, 36, 28, 17, 5, -5, -19, -25, -35, -43, -52, -58, + -62, -72, -75, -83, -94, -94, -105, -105, -115, -115, -116, -122, -114, -112, -108, -98, + -99, -89, -86, -82, -72, -69, -58, -52, -44, -31, -21, -6, 4, 17, 28, 39, + 48, 53, 66, 72, 80, 88, 92, 104, 108, 113, 116, 119, 121, 116, 119, 112, + 108, 107, 94, 94, 85, 79, 72, 62, 57, 48, 37, 25, 17, 8, -8, -15, + -26, -35, -42, -55, -59, -65, -73, -75, -87, -89, -97, -104, -109, -116, -116, -121, + -120, -120, -109, -108, -103, -90, -97, -78, -78, -77, -60, -64, -50, -41, -34, -16, + -7, 9, 19, 33, 42, 52, 60, 65, 77, 79, 87, 96, 99, 109, 113, 118, + 124, 117, 121, 117, 109, 110, 99, 94, 93, 83, 77, 73, 63, 55, 50, 32, + 26, 18, 0, -6, -20, -29, -34, -49, -53, -57, -63, -71, -76, -83, -91, -97, + -108, -112, -114, -122, -115, -124, -112, -105, -112, -89, -99, -90, -78, -89, -72, -66, + -61, -49, -41, -28, -16, 2, 6, 25, 35, 36, 53, 54, 67, 77, 79, 93, + 97, 105, 112, 111, 122, 118, 119, 117, 112, 109, 108, 99, 95, 92, 82, 76, + 71, 59, 56, 43, 30, 24, 10, 0, -9, -18, -26, -36, -45, -55, -59, -68, + -75, -81, -88, -94, -99, -106, -109, -110, -119, -117, -119, -116, -111, -105, -101, -91, + -92, -83, -75, -75, -61, -52, -52, -35, -29, -18, 0, 9, 22, 36, 41, 51, + 64, 68, 78, 88, 90, 101, 103, 109, 113, 115, 121, 117, 118, 116, 109, 109, + 102, 94, 90, 80, 71, 67, 57, 47, 42, 30, 19, 14, -4, -9, -19, -31, + -36, -50, -55, -61, -68, -74, -79, -87, -93, -101, -107, -107, -115, -118, -118, -123, + -112, -110, -109, -92, -93, -94, -74, -83, -71, -57, -61, -45, -34, -31, -10, 0, + 12, 27, 37, 42, 55, 61, 70, 77, 87, 95, 96, 106, 112, 113, 123, 122, + 117, 122, 112, 109, 110, 96, 96, 92, 76, 74, 68, 55, 50, 40, 28, 20, + 7, -6, -10, -23, -31, -42, -51, -59, -65, -70, -76, -82, -88, -92, -104, -104, + -105, -122, -113, -122, -126, -106, -119, -103, -91, -99, -82, -80, -76, -66, -59, -54, + -46, -34, -30, -9, 1, 13, 33, 34, 51, 57, 63, 76, 77, 91, 95, 95, + 110, 108, 115, 122, 120, 120, 123, 112, 110, 110, 94, 95, 87, 70, 74, 62, + 55, 50, 39, 29, 20, 7, -5, -13, -26, -35, -44, -56, -61, -65, -69, -75, + -83, -86, -98, -104, -104, -121, -115, -119, -128, -110, -117, -116, -92, -100, -90, -78, + -83, -75, -63, -64, -55, -41, -39, -20, -7, 1, 21, 31, 40, 51, 55, 67, + 72, 77, 91, 93, 99, 110, 109, 118, 125, 118, 124, 119, 108, 114, 101, 93, + 96, 81, 75, 73, 59, 57, 48, 35, 27, 15, 1, -7, -20, -29, -37, -49, + -56, -61, -65, -69, -74, -83, -91, -98, -107, -113, -117, -120, -122, -118, -115, -111, + -103, -101, -92, -89, -85, -80, -77, -65, -61, -51, -41, -33, -16, -4, 8, 21, + 34, 40, 49, 57, 63, 73, 82, 89, 98, 104, 109, 117, 118, 123, 122, 119, + 116, 110, 108, 100, 97, 93, 83, 80, 70, 64, 55, 45, 34, 22, 12, -2, + -10, -20, -30, -35, -48, -55, -62, -67, -71, -78, -86, -91, -101, -104, -110, -117, + -117, -120, -123, -111, -111, -110, -90, -99, -90, -76, -85, -71, -58, -63, -45, -37, + -33, -14, 1, 4, 27, 34, 41, 53, 59, 66, 79, 84, 92, 100, 103, 110, + 115, 116, 123, 118, 118, 117, 107, 110, 101, 95, 93, 79, 76, 68, 57, 52, + 43, 30, 23, 11, -3, -8, -20, -30, -34, -48, -55, -60, -69, -74, -81, -89, + -92, -101, -105, -108, -114, -117, -118, -122, -112, -113, -108, -95, -101, -87, -82, -83, + -68, -60, -56, -45, -38, -28, -17, -2, 6, 23, 33, 40, 54, 60, 68, 80, + 85, 94, 96, 103, 109, 110, 119, 118, 118, 121, 113, 112, 110, 100, 98, 90, + 77, 73, 66, 55, 51, 41, 29, 25, 8, 1, -9, -23, -28, -42, -51, -59, + -64, -67, -75, -79, -86, -94, -98, -105, -111, -115, -117, -121, -123, -111, -120, -102, + -95, -100, -79, -84, -81, -61, -69, -55, -46, -42, -27, -14, -3, 11, 30, 35, + 49, 57, 60, 76, 76, 86, 95, 95, 109, 108, 116, 122, 121, 123, 120, 116, + 114, 106, 100, 94, 88, 78, 73, 65, 59, 52, 38, 33, 20, 10, -2, -15, + -22, -32, -42, -51, -58, -62, -67, -77, -80, -86, -94, -100, -106, -113, -115, -119, + -122, -118, -117, -107, -106, -98, -89, -89, -78, -76, -71, -57, -56, -46, -36, -25, + -12, 0, 16, 26, 39, 49, 54, 67, 72, 80, 88, 94, 101, 104, 115, 113, + 121, 125, 116, 123, 116, 110, 109, 98, 93, 88, 78, 69, 65, 56, 47, 42, + 27, 20, 8, -6, -15, -27, -33, -43, -53, -58, -64, -68, -74, -86, -87, -96, + -106, -103, -117, -116, -117, -123, -117, -106, -114, -97, -96, -96, -81, -81, -80, -62, + -64, -49, -45, -34, -19, -8, 4, 17, 28, 40, 47, 54, 66, 73, 79, 93, + 95, 102, 113, 110, 117, 123, 119, 121, 117, 113, 111, 106, 96, 95, 88, 78, + 72, 63, 55, 47, 35, 26, 14, 4, -9, -19, -24, -35, -43, -51, -61, -65, + -72, -79, -88, -88, -99, -107, -107, -120, -114, -120, -122, -113, -116, -102, -106, -95, + -89, -95, -72, -80, -70, -50, -58, -37, -30, -20, -5, 6, 18, 29, 44, 45, + 57, 72, 68, 89, 89, 97, 109, 104, 120, 113, 118, 124, 112, 120, 112, 107, + 106, 96, 91, 87, 78, 66, 65, 52, 40, 39, 17, 17, 4, -13, -13, -30, + -35, -44, -58, -59, -66, -72, -78, -85, -93, -97, -106, -114, -110, -120, -120, -118, + -120, -109, -110, -98, -100, -89, -81, -87, -68, -68, -59, -44, -46, -29, -18, -5, + 5, 22, 32, 39, 54, 56, 68, 79, 79, 94, 98, 102, 110, 112, 117, 119, + 124, 117, 116, 116, 104, 106, 97, 89, 86, 74, 67, 60, 53, 41, 34, 24, + 12, 4, -9, -19, -28, -38, -47, -58, -60, -68, -73, -77, -88, -93, -96, -111, + -109, -115, -124, -118, -122, -120, -107, -109, -102, -91, -95, -82, -78, -78, -60, -59, + -51, -36, -35, -14, -3, 6, 24, 34, 41, 56, 59, 67, 81, 82, 92, 103, + 102, 112, 119, 114, 123, 123, 116, 121, 112, 106, 107, 93, 91, 84, 74, 69, + 61, 52, 43, 32, 21, 13, -2, -10, -22, -31, -38, -51, -56, -59, -69, -71, + -76, -87, -90, -100, -107, -110, -119, -118, -120, -123, -108, -118, -101, -92, -102, -77, + -85, -83, -63, -71, -58, -45, -44, -27, -15, -2, 10, 30, 32, 46, 57, 56, + 74, 73, 84, 93, 95, 109, 108, 117, 117, 124, 119, 119, 119, 112, 109, 100, + 96, 90, 81, 75, 65, 59, 51, 41, 33, 22, 12, 0, -12, -23, -30, -40, + -51, -57, -64, -71, -73, -83, -84, -95, -102, -102, -116, -117, -118, -128, -116, -114, + -116, -102, -99, -95, -86, -80, -80, -71, -58, -61, -46, -38, -30, -10, -4, 12, + 26, 37, 47, 54, 67, 68, 79, 89, 86, 104, 104, 111, 118, 118, 123, 121, + 119, 116, 112, 109, 99, 96, 88, 80, 75, 66, 58, 49, 41, 29, 19, 10, + -5, -10, -25, -35, -39, -53, -58, -64, -69, -75, -81, -87, -100, -99, -112, -116, + -118, -126, -123, -115, -120, -111, -102, -100, -93, -86, -85, -76, -69, -64, -56, -47, + -38, -25, -10, 4, 16, 31, 40, 46, 61, 65, 70, 83, 86, 93, 103, 105, + 114, 125, 118, 124, 125, 112, 120, 111, 98, 103, 91, 86, 83, 71, 66, 61, + 49, 38, 32, 16, 7, -4, -17, -26, -36, -44, -54, -60, -59, -71, -75, -79, + -94, -95, -103, -117, -112, -120, -127, -120, -118, -117, -104, -102, -99, -88, -84, -86, + -73, -70, -64, -51, -47, -37, -17, -10, 7, 19, 32, 40, 52, 56, 67, 73, + 80, 87, 92, 103, 109, 110, 123, 119, 121, 126, 111, 113, 112, 98, 98, 91, + 80, 80, 71, 60, 61, 47, 36, 30, 13, 5, -5, -19, -27, -35, -43, -52, + -58, -62, -71, -76, -84, -96, -100, -105, -118, -115, -121, -123, -121, -114, -117, -110, + -98, -105, -91, -83, -90, -71, -68, -64, -48, -43, -33, -17, -5, 3, 23, 32, + 38, 54, 59, 66, 79, 82, 92, 100, 105, 108, 116, 119, 117, 126, 116, 115, + 118, 106, 105, 99, 91, 85, 78, 67, 60, 54, 41, 33, 24, 11, 0, 3, + 10, 14, -8, 46, 7, -20, -23, -28, 17, 9, 47, -7, -15, -35, -1, -26, + 44, 34, -31, 31, -47, -32, 30, -2, 32, 15, -15, -17, -39, 16, -2, 26, + 23, 3, -43, 11, -37, 14, 37, 7, 4, -21, -30, -9, 14, 18, 38, -13, + -16, -21, -24, 8, 38, 3, 16, -29, -11, -26, 20, 15, 24, -9, 0, -34, + -21, 32, -16, 41, -1, -20, -7, -7, -7, 27, 0, -2, -2, -11, -11, 19, + -16, 32, -19, -4, 11, -40, 49, -13, -12, 12, -32, 12, 17, 1, 23, -34, + -20, 14, -20, 33, 44, -51, 7, -21, -38, 46, 19, 37, -28, -29, -17, -40, + 63, 36, -33, 42, -45, -57, 16, 37, -3, 54, 0, -64, -25, -7, 15, 37, + 34, -2, -65, -12, -3, -7, 76, -2, -6, -28, -22, -30, 40, 11, 12, 21, + -43, -6, -1, -31, 73, -35, 33, -1, -67, 29, -24, 16, 42, 4, -26, 17, + -71, 32, 0, 0, 72, -56, 4, -2, -75, 76, -25, 39, 24, -42, -6, -20, + -31, 56, 1, 3, 49, -63, -12, -16, -10, 49, 12, 29, -32, -59, 35, -39, + 35, 45, -33, -21, 46, -68, 13, 16, 12, 0, 2, 32, -70, 12, 30, -62, + 64, 5, -31, 22, -30, 11, -30, 43, 2, -8, 16, -3, -60, 39, -11, -13, + 63, -32, 8, -6, -45, 39, -38, 30, 49, -89, 96, -84, 0, 43, -51, 52, + -4, -6, 7, -31, -10, 12, -22, 62, 8, -57, 65, -101, 1, 69, -46, 76, + -18, -34, -24, -33, 50, -6, 55, 16, -70, -19, 2, -33, 59, 61, -40, 7, + -44, -33, -7, 61, 31, -15, 5, -32, -70, 47, 34, 8, 22, -16, -44, -47, + 56, -6, 12, 56, -46, -32, -3, 7, -4, 42, 19, -41, -35, 41, -59, 43, + 45, -44, 9, -9, -7, -19, 36, 2, -50, 49, -6, -34, 33, -1, -38, 17, + 44, -33, 5, 28, -68, -13, 62, -25, 15, 45, -57, -32, 23, -14, 37, 11, + 29, -56, -48, 46, -55, 48, 94, -74, 22, -40, -59, 36, 9, 75, -19, -31, + 6, -104, 39, 80, -23, 59, -12, -104, 10, -12, 24, 59, 5, 9, -78, -12, + 24, -47, 116, -6, -51, 34, -71, -26, 55, 3, 11, 38, -31, -9, -45, 21, + -11, 4, 92, -79, 16, -16, -41, 29, 27, 19, -5, -19, -13, -35, 29, 22, + -7, 20, -35, 6, -21, 30, -2, 6, -8, -20, -12, 30, -13, 8, 23, -52, + 21, 8, -16, 40, -20, -7, -15, -38, 62, -33, 48, 5, -66, 28, -25, 15, + 39, 5, -46, 8, -46, 32, 12, 37, -9, -49, 43, -78, 43, 46, -43, 39, + -41, -36, 13, 19, 48, -21, 9, -37, -54, 45, 32, -14, 41, -32, -66, 42, + -8, 37, 12, -10, -12, -74, 71, -30, 16, 65, -64, -1, -13, -12, 17, 24, + 10, -16, -31, -1, -3, 1, 68, -47, -7, -8, -41, 74, -16, 32, -27, -42, + 22, -49, 80, -11, 0, 23, -84, 34, -24, 31, 48, -37, 23, -55, -25, 22, + 14, 22, 59, -78, -11, -1, -45, 90, -35, 32, 0, -75, 63, -65, 34, 52, + -71, 70, -56, -14, 30, -22, 10, 55, -74, 41, -19, -47, 88, -62, 50, -11, + -57, 44, -54, 59, 17, -23, 12, -40, -41, 60, 3, 15, 28, -71, -1, -17, + 11, 61, -28, 47, -59, -48, 35, -18, 51, 27, -20, -35, -36, 14, 6, 44, + 23, -30, -33, -17, -1, 14, 49, -2, -32, -12, -20, 5, 29, 34, -33, 9, + -34, -26, 36, -2, 40, -28, 5, -26, -39, 65, -27, 19, 31, -54, 0, -8, + 12, 2, 30, -5, -25, -22, 24, -29, 26, 52, -57, 7, 5, -56, 46, 1, + 8, 4, -5, 1, -51, 28, 14, -21, 48, -17, -46, 4, 11, -6, 35, 7, + -16, -31, -10, 25, -49, 95, -28, -29, 19, -46, -5, 32, 21, 8, -1, -24, + -36, -17, 59, -7, 33, 10, -76, -14, 19, -1, 56, 16, -23, -64, -8, 7, + 8, 85, 0, -57, -21, -35, -7, 72, 23, 28, -66, -16, -47, 2, 68, 24, + 5, 0, -69, -26, 22, -7, 72, 0, -12, -20, -51, 15, -11, 44, 44, -46, + 36, -59, -38, 32, 19, -3, 71, -45, -28, -29, -17, 36, 8, 79, -47, -53, + 18, -65, 38, 75, -24, 20, -36, -34, -26, 38, 39, -7, -3, 7, -85, 44, + 26, -17, 42, -20, -29, -26, 26, 18, -8, 36, -17, -73, 40, 4, -1, 52, + -16, -47, -15, 14, 4, 29, 30, -41, -44, 15, -2, 16, 60, -26, -54, 17, + -33, 22, 48, -5, -15, -20, -13, -15, 31, 37, -28, 6, -17, -22, -10, 64, + -43, 16, 22, -71, 41, 3, -1, 6, -12, 12, -38, 11, 38, -49, 37, 24, + -64, 27, 18, -73, 81, -33, 14, -3, -32, 43, -60, 53, 24, -76, 70, -29, + -33, 50, -18, -34, 48, -38, 37, -15, -5, 25, -80, 70, -4, -45, 89, -72, + -3, 13, -23, 28, 21, -9, -9, -25, -11, 24, -26, 62, -14, -49, 67, -97, + 57, 12, -23, 46, -46, 9, -20, -4, 25, -1, 5, 18, -31, -25, 38, -43, + 44, 17, -42, 37, -66, 37, -16, 26, 18, -16, -17, -4, -17, 7, 38, -11, + 4, -3, -51, 32, -17, 38, 18, -34, 23, -58, 4, 25, 0, 26, 3, -35, + -11, -10, 16, 24, 8, 4, -33, -30, 22, -2, 14, 52, -61, 10, -23, -4, + 20, 10, 32, -44, -2, 1, -36, 37, 32, -25, 2, 0, -40, 14, 24, -5, + 13, -28, 20, -51, 41, 15, -23, 25, -12, -41, 30, -2, -11, 40, -34, 14, + -24, 3, 22, -31, 44, -22, -31, 57, -55, 28, 0, -9, 1, 11, -10, 8, + -13, 3, -2, -23, 60, -49, 23, 10, -59, 36, -3, -3, 35, -23, 5, -42, + 15, 7, -2, 35, 0, -45, 8, -4, -27, 63, -4, -14, 9, -39, 1, 1, + 27, 19, -27, 24, -49, -6, 34, -5, 10, 19, -32, -20, 14, -12, 16, 26, + -9, -19, -9, -8, 8, 7, 40, -29, -14, -4, -25, 7, 56, -15, 6, -20, + -36, 3, 10, 33, 20, -23, -5, -42, -18, 54, -17, 63, -5, -59, 2, -44, + 12, 57, 17, 15, -33, -44, -16, -17, 65, 40, -9, 10, -72, -51, 39, 10, + 65, 19, -25, -47, -51, 17, 20, 53, 30, -35, -35, -34, -16, 36, 48, 12, + -3, -35, -42, -9, 28, 34, 12, 15, -42, -39, 7, 8, 24, 28, 1, -31, + -36, 9, -1, 28, 29, -14, -34, 14, -43, 23, 34, -7, 24, -44, 10, -28, + -5, 53, -29, 29, -7, -33, 2, -1, 5, 19, 10, -17, 2, -33, 14, 1, + 8, 32, -36, 17, -28, -18, 36, -22, 29, 2, -25, 5, -17, 13, 1, 16, + -1, -10, -12, 3, -9, 10, 19, -22, 16, -3, -20, 24, -22, 15, -3, -14, + 22, -30, 31, -14, -11, 12, -11, 8, 17, -9, -4, -13, -13, 7, 10, 19, + -6, -7, -2, -32, 24, 8, 0, 17, -20, -10, -15, 13, 10, 11, 4, -1, + -40, 19, -4, -6, 42, -31, -1, -5, -12, 19, 6, 7, -5, -26, 10, -12, + 15, 20, -8, -19, 12, -40, 31, 15, -3, 16, -23, -27, 7, -5, 31, 6, + 3, -6, -41, 14, -2, 7, 38, -10, -29, 11, -44, 17, 29, 6, 20, -26, + 1, -45, 9, 31, -18, 40, -1, -47, 8, -10, -4, 29, 33, -25, 1, -31, + -12, -9, 35, 30, -25, 31, -48, -28, 20, 17, 9, 30, -19, -39, -13, 6, + 8, 38, 15, -10, -42, 0, -24, 15, 49, -9, -12, 5, -44, -5, 42, 4, + 6, 8, -27, -29, 5, 24, -2, 10, 28, -56, 1, 23, -29, 29, 15, -19, + -11, 1, -4, -8, 24, 6, -15, 2, 7, -27, 12, 21, -40, 36, -15, -12, + 22, -16, 17, -17, 15, -6, -18, 23, -3, -26, 39, -27, -5, 26, -20, 8, + 5, -11, 7, -21, 19, -11, -8, 35, -25, 2, 18, -35, 9, 16, -21, 29, + -16, 1, -13, -13, 28, -18, 23, 13, -36, 6, -1, -23, 26, 12, -15, 17, + -20, -2, -7, 3, 22, -22, 27, -11, -34, 36, -30, 11, 17, 2, -12, 13, + -22, -11, 11, -5, 26, -17, 26, -25, -32, 44, -47, 39, 25, -31, 16, -35, + -1, -4, 26, 16, 3, -16, -10, -23, -8, 55, -27, 26, 0, -63, 41, -26, + 28, 22, -23, 14, -42, 5, 20, -13, 28, 3, -42, 20, -6, -17, 52, -32, + 6, -2, -37, 42, -27, 29, 15, -51, 40, -38, 2, 33, -19, 6, 11, -43, + 25, 0, -19, 57, -54, 31, -9, -43, 58, -52, 36, 11, -44, 50, -44, 8, + 23, -24, 12, 6, -34, 25, -9, -15, 50, -55, 35, -7, -25, 49, -48, 32, + -23, -18, 37, -30, 28, 8, -27, 7, -2, -19, 22, 10, -11, 10, -27, 4, + -16, 18, 29, -19, 20, -22, -36, 16, -2, 18, 14, 3, -24, -15, -5, 12, + 13, 20, 4, -40, 2, -23, 8, 29, 7, 9, -23, -10, -13, 5, 19, 9, + -3, -14, -7, -19, 21, 6, 5, 10, -20, 0, -14, 12, 0, 2, 5, -13, + 1, -3, 12, -12, 20, -13, -7, 6, -11, 5, 0, 5, -5, -4, 10, -10, + 2, 6, -5, -12, 18, -13, -9, 19, -17, 11, -1, 8, -5, -22, 26, -26, + 1, 29, -17, -7, 16, -22, -8, 23, -3, 4, -3, -2, -15, -20, 42, -21, + 4, 40, -55, 8, 8, -22, 21, 20, -17, 2, -14, -7, -2, 10, 31, -25, + 10, -3, -54, 40, 5, -12, 42, -17, -37, 13, -12, 7, 24, 10, -6, -36, + 12, -9, -25, 74, -24, -19, 38, -64, 5, 25, 0, 16, 1, -9, -25, -23, + 36, -8, 6, 50, -58, -12, 22, -53, 52, 18, -12, 16, -51, 15, -30, 25, + 46, -37, 31, -26, -49, 30, 9, -1, 42, -19, -28, -13, -5, 16, 4, 42, + -18, -40, 20, -30, 1, 49, -4, -15, 0, -21, -19, 21, 26, 0, -9, 9, + -43, -1, 26, -5, 21, -7, -6, -32, 9, 12, -3, 34, -17, -12, -17, -4, + 9, 7, 28, -19, -3, -13, -11, 7, 15, 15, -19, 15, -38, -5, 17, -1, + 29, -20, 15, -39, -11, 41, -33, 45, -8, -21, -11, -3, 7, 0, 28, -7, + -19, -8, 7, -20, 23, 24, -40, 24, -17, -16, 26, -9, 21, -27, 13, -11, + -22, 29, -7, 0, 22, -22, -16, 14, -12, 12, 11, -5, -6, -17, 14, -15, + 9, 30, -28, 5, 1, -26, 8, 18, -7, 1, 6, -12, -15, 9, 13, -13, + 13, 13, -42, 14, 3, -16, 20, 7, -3, -22, 25, -26, 4, 16, -7, 3, + -8, 17, -33, 14, 9, -21, 25, -3, -11, -1, 1, -13, 1, 23, -20, 26, + -18, 0, -18, 3, 24, -25, 36, -15, -29, 22, -22, 3, 24, -5, -1, 0, + -18, 2, -11, 20, 10, -17, 30, -37, -15, 29, -33, 39, 11, -23, 7, -34, + 8, 0, 11, 36, -27, -12, 9, -47, 29, 31, -29, 40, -37, -14, 3, -17, + 45, -11, 8, 12, -60, 20, -2, -2, 41, -12, -18, 3, -37, 27, 12, -4, + 37, -56, 17, -21, -5, 44, -20, 14, -2, -40, 20, 0, 3, 22, -13, -10, + -6, -16, 29, -12, 14, 15, -49, 24, -11, -7, 39, -18, 3, -20, -12, 19, + -10, 32, 2, -34, 10, -13, -13, 37, 1, -7, 3, -33, 4, 2, 18, 25, + -25, 8, -33, -13, 34, -7, 24, 4, -33, -10, -2, 2, 25, 12, -1, -25, + -12, 3, -18, 34, 12, -15, 4, -9, -25, 10, 17, -3, 9, 2, -13, -23, + 9, 8, -13, 37, -10, -15, 1, -13, -1, 0, 31, -15, 0, 5, -29, 6, + 5, 15, -9, 16, -9, -29, 15, -10, 3, 15, 9, -11, -12, 11, -29, 17, + 14, -7, 6, -6, -7, -24, 30, -11, 9, 18, -20, -8, -6, 6, -10, 22, + 10, -29, 14, -13, -8, 13, 17, -13, 2, 1, -24, 5, 5, 12, -10, 15, + -7, -28, 21, -2, -8, 22, -9, -14, -2, 6, -5, 5, 12, -7, -15, 14, + -4, -16, 27, -10, -14, 13, -5, -9, 10, 5, -8, -5, 16, -20, 2, 13, + -14, -3, 17, -18, 2, 10, -12, 9, -6, -2, -16, 13, 10, -15, 33, -24, + -17, 10, -4, 15, 1, 9, -23, -9, 6, -5, 5, 21, -10, -13, 11, -21, + -2, 19, -10, 23, -20, 10, -16, -21, 33, -17, 17, 18, -30, 1, -14, -1, + 20, -2, 18, -15, -24, 6, -5, 6, 36, -26, 6, -18, -23, 34, -12, 25, + 1, -30, -1, -11, 10, 22, -1, 4, -19, -28, 21, -11, 22, 25, -33, 4, + -21, -7, 22, 7, 19, -23, -13, -3, -13, 21, 17, -11, 7, -19, -12, 12, + -10, 30, -13, -5, 4, -30, 27, -9, 17, -3, -25, 13, -23, 13, 27, -15, + -5, 3, -35, 17, 19, -8, 29, -37, 1, -15, -10, 48, -20, 26, -7, -49, + 22, -23, 21, 33, -10, -8, -17, -34, 11, 19, 12, 40, -39, -14, -13, -36, + 64, -4, 20, 9, -55, 3, -24, 21, 31, 10, -1, -22, -30, -7, 12, 18, + 29, -10, -7, -28, -22, 22, 3, 26, 4, -13, -18, -16, 21, -9, 28, -1, + -21, 0, -12, 5, 6, 5, 10, -20, 1, 3, -20, 21, 7, -23, 24, -25, + -6, 21, -13, 25, -19, -8, 2, -14, 20, 13, -23, 25, -31, -7, 24, -16, + 20, 6, -25, 8, -24, 12, 15, -10, 24, -25, -2, 0, -12, 14, 10, -13, + 4, 1, -17, 9, 6, -9, 9, 0, -3, -8, 11, -10, -2, 7, -1, -6, + 6, 1, -12, 1, 18, -31, 23, -2, -21, 21, -6, -8, 15, -14, 4, -6, + -1, 17, -22, 20, -6, -35, 37, -17, -6, 47, -41, 6, -6, -16, 12, 16, + 6, 1, -36, 18, -26, 4, 59, -36, -1, 16, -64, 30, 14, 1, 16, -13, + 0, -35, 17, 13, -8, 12, 14, -45, 11, 12, -24, 27, 12, -27, 10, -6, + -9, 1, 14, -7, -6, 8, -4, -8, 8, 8, -24, 13, 7, -27, 28, -1, + -28, 27, -19, -2, 17, -5, 6, -10, -5, 4, -25, 32, 2, -22, 32, -28, + -20, 35, -20, 16, 7, -18, 1, -22, 20, 0, 2, 20, -15, -25, 24, -25, + 12, 25, -23, 10, -19, -5, 8, 2, 20, -6, -13, 0, -22, 12, 15, -3, + 13, -13, -25, 12, -6, 18, 13, -3, -14, -22, 3, -2, 14, 25, -10, -16, + -5, -13, 2, 22, 9, -2, -11, -12, -20, 15, 20, 1, 14, -19, -17, -9, + 1, 19, 5, 0, 4, -35, 17, -7, 5, 20, -16, 2, -8, -11, 11, -2, + 2, 7, -19, 15, -10, 2, 12, -14, -3, 2, -9, 17, -3, 2, -7, -16, + 10, 2, 9, 10, -14, -9, -6, -11, 21, 5, 4, 6, -24, -5, -4, 6, + 18, 0, 8, -21, -18, 8, -8, 21, 16, -11, -9, -12, -15, 15, 3, 27, + -9, -16, 5, -30, 13, 23, -11, 21, -19, -15, -3, -9, 30, -9, 14, -6, + -22, -5, 15, -11, 23, -1, -14, -4, -9, 8, 4, 1, 20, -34, 9, 1, + -17, 24, -6, 1, -9, 1, -4, 3, 6, 8, -16, 0, 2, -13, 11, 21, + -31, 24, -21, -4, 13, -2, 7, -9, -3, 0, -18, 29, -4, -9, 16, -19, + -13, 25, -5, -1, 15, -24, 4, -15, 22, 4, -11, 20, -21, -25, 39, -23, + 14, 14, -23, 1, -8, 3, 12, -9, 23, -19, -18, 24, -22, 5, 30, -32, + 11, 2, -21, 18, -6, 5, 1, -9, 13, -22, 4, 19, -28, 26, 3, -28, + 21, -4, -25, 32, -15, 5, 0, -2, -4, -9, 15, 0, -13, 21, -14, -20, + 31, -19, 2, 17, -14, -9, 12, -6, 4, -1, 4, -17, -1, 12, -2, 0, + 20, -31, -8, 12, -8, 17, 14, -13, -16, -9, -7, 20, 11, 18, -13, -28, + -3, -12, 13, 40, -12, 4, -20, -32, 8, 17, 14, 21, -10, -28, -18, -2, + 11, 22, 17, 0, -34, -6, -3, -17, 50, 1, -13, 4, -22, -21, 17, 16, + 4, 7, 0, -27, -11, 4, 10, 2, 24, -6, -28, 7, -12, -2, 33, -3, + -6, 2, -37, 3, 9, 7, 24, -4, -14, -6, -24, 25, -1, 11, 16, -36, + -9, 12, -25, 45, 5, -20, 11, -36, 11, 7, 0, 30, -32, -1, 7, -33, + 37, 0, -9, 15, -21, -10, 12, -15, 24, -8, 3, 4, -20, 7, 3, -15, + 28, -14, -7, 13, -23, 2, 11, 0, 4, 7, -9, -16, 1, 7, -7, 19, + -3, -12, -14, 15, -10, 7, 30, -26, -13, 15, -30, 15, 26, -12, -1, -8, + -9, -5, 13, 22, -12, -12, 7, -36, 17, 31, -24, 27, -21, -24, 15, -10, + 26, 4, -12, 4, -36, 13, 14, -5, 27, -14, -22, 7, -12, 6, 23, -13, + 7, -19, -2, 7, -8, 25, -5, -17, 18, -25, 3, 14, -8, 4, 0, -1, + -11, 4, 12, -18, 15, 2, -23, 12, -2, -7, 12, 1, -1, -15, 11, -3, + -17, 41, -24, -7, 13, -25, 3, 22, -9, 15, -12, -9, 0, -17, 32, -5, + -5, 19, -49, 19, 3, -11, 45, -30, 2, -4, -28, 29, 0, 7, 12, -34, + 6, -10, 1, 33, -9, -6, 4, -41, 25, 2, 4, 29, -40, 8, -17, -9, + 42, -16, 16, -10, -33, 11, -7, 22, 12, -6, -6, -25, -4, 18, -3, 25, + -4, -29, 5, -17, 8, 22, 1, 4, -22, 1, -13, 2, 31, -19, 9, 2, + -36, 17, 5, -7, 20, -11, -2, -13, 4, 9, -18, 24, -3, -30, 33, -19, + -11, 31, -21, 6, 0, -5, 3, -10, 17, -7, -19, 30, -24, 0, 26, -23, + 3, 7, -17, 9, -3, 9, -1, -17, 23, -25, -3, 34, -27, 10, 15, -34, + 9, 1, 1, 7, -1, 12, -31, 4, 16, -27, 32, 10, -33, 10, -1, -27, + 29, 9, -9, 0, -1, -16, -6, 24, 2, -17, 23, -20, -24, 33, -11, -2, + 17, -7, -21, 13, 1, -7, 10, 1, -12, -9, 13, -1, -5, 20, -16, -15, + 15, -8, 5, 13, -10, -7, -9, 5, 2, 10, 7, -7, -22, 12, -13, 6, + 26, -14, -6, 0, -17, 3, 16, 6, 0, -11, 3, -26, 13, 15, -6, 7, + 4, -29, 6, 7, -3, 13, 1, -11, -9, 2, -1, 3, 9, -3, -8, 1, + -4, 0, 5, 0, 0, -2, 0, -1, 0, 0, -2, 11, 23, 22, 24, 25, + 20, 21, 15, 40, -1, -24, -42, -5, -19, -11, -8, 4, -46, -31, -14, -33, + -40, -44, -48, -89, -63, -47, -33, -27, -10, -6, 22, 25, 26, 28, 37, 11, + 15, 51, 44, 54, 66, 66, 71, 111, 84, 70, 63, 47, 39, 22, 47, -28, + -79, -111, -90, -91, -112, -81, -87, -49, -46, -5, -24, 26, 24, 47, 29, 23, + 30, 30, 13, -1, 4, -14, 17, 35, 62, 31, 53, 59, 72, 64, 27, 26, + 9, 9, -61, -44, -88, -74, -81, -83, -124, -96, -37, -78, -48, -56, -68, -60, + 7, 44, 39, 54, 77, 102, 110, 108, 89, 101, 100, 105, 64, 22, -1, 44, + 40, -19, -29, -35, -16, -27, -40, -77, -82, -113, -104, -93, -57, -72, -56, -3, + 1, 7, -1, 49, 39, 30, 31, 23, 10, 31, 11, 7, -19, -2, -2, 28, + 62, 92, 75, 33, 34, -20, -47, -61, -85, -105, -93, -119, -112, -54, -70, -67, + -32, -1, 4, 4, 20, 29, 62, 70, 54, 62, 78, 115, 92, 85, 78, 52, + 21, 19, 27, 2, -8, 13, 0, 5, 3, 9, 18, 0, -59, -61, -45, -57, + -65, -76, -89, -102, -48, -24, 17, 6, 26, 33, 35, 26, 41, 63, 20, 12, + 29, 34, 8, 7, 31, 21, 31, 39, 33, -5, -8, -55, -57, -98, -94, -88, + -64, -82, -74, -39, -14, 3, 16, 22, 8, 2, 17, 5, 36, 76, 74, 71, + 57, 73, 62, 47, 30, 32, 19, 4, 7, -14, -18, -2, 17, -5, 13, 22, + 31, 10, 8, -13, -47, -80, -85, -86, -71, -73, -60, -35, -10, 9, 19, 49, + 53, 47, 60, 73, 43, 33, 20, 13, -1, -7, -7, 7, 9, -2, 5, -14, + -40, -69, -61, -66, -67, -84, -58, -58, -33, 2, -7, -5, 12, 32, 18, 25, + 19, 24, 65, 59, 62, 64, 63, 55, 60, 52, 31, 19, -12, -26, -4, -7, + -10, -3, 6, -22, -14, 12, 19, 4, -26, -38, -40, -56, -61, -66, -59, -65, + -51, -20, 29, 40, 51, 52, 62, 61, 53, 26, 20, 6, 8, 6, 9, -14, + -14, -15, -2, -11, -23, -36, -38, -60, -77, -69, -60, -51, -56, -44, -27, 10, + -2, 14, 10, 22, 16, 41, 60, 39, 35, 60, 62, 43, 45, 63, 52, 17, + 12, 15, -1, -2, 0, -38, -48, -32, -22, -7, 3, 13, 10, -2, -1, -8, + -12, -25, -48, -46, -52, -49, -36, -17, 9, 17, 26, 48, 57, 55, 69, 60, + 32, 6, 4, -6, -20, -24, -9, -21, -25, -14, -18, -38, -38, -32, -51, -52, + -60, -34, -6, -6, -16, -11, -2, -1, 17, 19, 3, 11, 25, 31, 41, 39, + 33, 33, 41, 34, 34, 23, 21, 15, 6, -13, -24, -28, -20, -8, -12, -19, + -12, -5, 9, 14, 2, -12, -25, -28, -21, -28, -23, -22, -18, -26, -5, 24, + 45, 46, 47, 39, 33, 36, 42, 29, 7, -5, -10, -21, -29, -39, -39, -31, + -24, -29, -39, -51, -43, -27, -22, -18, -25, -26, -20, 9, 19, 18, 4, -2, + 19, 30, 38, 25, 24, 28, 33, 41, 38, 34, 32, 38, 24, 8, 4, -8, + -11, -15, -25, -31, -25, -20, -22, -15, -11, -9, -12, -17, -20, -20, -15, -6, + -11, -8, 0, 11, 29, 19, 17, 17, 18, 28, 31, 25, 18, 23, 18, 10, + 1, -7, -18, -26, -24, -30, -41, -38, -44, -32, -31, -31, -35, -25, -12, -2, + -8, -11, -13, -13, -2, 8, 15, 19, 29, 35, 37, 39, 43, 42, 40, 35, + 27, 25, 18, 15, 9, 4, -4, -15, -28, -28, -26, -28, -18, -15, -25, -23, + -12, -11, -14, -10, -2, -4, -1, 8, 15, 19, 22, 25, 16, 16, 17, 5, + 7, 13, 18, 13, 9, 6, 6, 4, -4, -21, -31, -28, -37, -39, -34, -38, + -38, -32, -17, -6, -4, -14, -19, -9, 3, -2, 3, 4, 7, 8, 13, 23, + 35, 38, 43, 42, 31, 25, 23, 17, 8, 3, 4, -7, -7, -10, -13, -20, + -19, -28, -33, -30, -23, -18, -13, -17, -12, 3, 14, 23, 31, 27, 23, 21, + 22, 19, 12, 4, 2, 2, -2, 0, 4, 11, 11, 6, 4, -2, -5, -14, + -17, -30, -38, -44, -42, -28, -21, -23, -21, -15, -15, -4, 8, 11, 4, -7, + -15, -7, 5, 10, 21, 26, 28, 27, 34, 37, 36, 28, 19, 10, 11, 8, + -2, -18, -17, -19, -19, -22, -24, -21, -24, -18, -17, -13, -19, -13, -1, 12, + 19, 22, 21, 19, 19, 30, 34, 24, 13, 7, 2, 1, 1, 2, -1, -2, + -6, 0, 0, -2, -15, -21, -17, -21, -28, -32, -31, -31, -32, -27, -24, -17, + -4, 1, -3, -1, 1, 4, 7, 8, 15, 16, 15, 15, 20, 32, 36, 38, + 32, 19, 12, 3, 2, -2, -4, -11, -19, -17, -15, -11, -16, -20, -27, -30, + -28, -22, -13, -6, -2, 2, 12, 23, 29, 45, 44, 36, 32, 21, 16, 14, + 10, 1, -9, -8, -2, -1, -7, -13, -13, -12, -9, -11, -18, -24, -26, -28, + -30, -24, -21, -21, -21, -11, -11, -10, 0, -2, 0, 4, 12, 13, 14, 12, + 17, 22, 28, 30, 28, 20, 16, 13, 8, 2, -2, -6, -15, -14, -18, -15, + -15, -16, -18, -18, -16, -19, -18, -17, -10, 0, -1, 4, 13, 22, 37, 39, + 36, 27, 27, 32, 26, 15, 6, -1, -4, -5, -7, -11, -11, -9, -15, -15, + -14, -18, -21, -19, -17, -21, -19, -15, -15, -10, -15, -14, -12, -11, -6, -2, + 1, -2, 1, 5, 14, 22, 33, 35, 23, 18, 16, 13, 11, 6, 1, -9, + -18, -11, -6, -7, -8, -9, -11, -11, -12, -13, -17, -21, -24, -24, -15, -4, + 7, 12, 17, 25, 30, 28, 31, 32, 31, 27, 22, 15, 12, 3, -2, -8, + -6, -3, -9, -13, -22, -24, -20, -18, -22, -24, -18, -14, -13, -10, -11, -9, + -3, -2, -3, -5, -10, -10, -5, -1, 4, 11, 15, 19, 22, 27, 23, 20, + 16, 14, 5, -3, -11, -15, -16, -12, -12, -11, -5, 1, -3, -10, -13, -15, + -11, -10, -10, -11, -8, -3, 2, 7, 9, 15, 25, 30, 33, 31, 25, 21, + 20, 16, 13, 7, -2, -8, -5, -4, -11, -20, -21, -22, -21, -17, -20, -21, + -22, -19, -19, -11, -4, -2, -2, -2, 2, 5, 2, 0, 0, -3, 1, 8, + 16, 13, 14, 17, 15, 13, 8, 5, -1, -6, -10, -13, -14, -14, -13, -10, + -7, -8, -8, -6, -6, -3, -1, -1, -9, -12, -7, 3, 13, 17, 14, 13, + 17, 22, 23, 24, 18, 15, 18, 18, 18, 15, 8, 0, -5, -8, -11, -15, + -17, -21, -26, -26, -24, -26, -24, -13, -9, -6, -3, -2, 3, 4, 6, 7, + 5, 2, 4, 2, -2, -4, -3, 5, 13, 17, 10, 3, -1, -2, -4, -5, + -11, -14, -13, -11, -8, -8, -8, -6, -3, 0, -1, -5, -5, 0, 4, 3, + 1, 2, 0, 0, 6, 13, 20, 17, 17, 18, 21, 18, 14, 13, 11, 11, + 7, 9, 3, -5, -12, -14, -18, -21, -23, -26, -26, -13, -3, -6, -13, -14, + -5, 5, 8, 3, 0, 1, 3, 6, 4, -1, -1, 1, 3, 7, 5, 3, + 0, 1, -1, 3, 0, -3, -11, -11, -9, -10, -9, -8, -5, -7, -7, -10, + -9, -6, -1, 4, 6, 4, 2, 5, 10, 13, 9, 12, 13, 14, 15, 16, + 13, 12, 10, 13, 14, 13, 8, 2, -1, -4, -6, -9, -15, -20, -21, -19, + -14, -16, -22, -21, -13, -5, -3, -3, -1, 3, 5, 10, 9, 9, 6, 8, + 7, 7, 7, 3, -4, -6, -4, -1, -4, -8, -10, -11, -8, -4, -6, -10, + -7, -8, -11, -11, -8, -5, -4, 0, 3, 3, 8, 10, 10, 12, 12, 11, + 10, 13, 12, 10, 6, 8, 9, 9, 11, 13, 11, 9, 10, 7, 2, -3, + -8, -9, -14, -16, -16, -19, -18, -14, -13, -11, -11, -10, -5, -1, 3, 5, + 2, 2, 9, 14, 11, 9, 10, 7, 2, 0, 2, -2, -9, -13, -15, -18, + -17, -15, -13, -10, -5, -5, -7, -7, -4, -1, 0, -2, -4, -2, 1, 4, + 9, 10, 10, 11, 11, 13, 14, 10, 11, 9, 9, 4, 6, 5, 4, 5, + 7, 8, 10, 9, 4, -4, -8, -9, -10, -11, -12, -14, -15, -17, -15, -9, + -4, -1, -6, -5, 2, 8, 8, 6, 5, 3, 4, 5, 9, 10, 10, 5, + -1, -5, -10, -12, -14, -16, -18, -17, -11, -10, -11, -8, -5, -2, -2, 0, + 3, 4, 5, 3, 2, 3, 5, 9, 12, 12, 11, 10, 12, 14, 12, 8, + 5, 0, -1, 1, 3, 0, 1, 3, 5, 6, 5, 0, -5, -11, -10, -13, + -12, -13, -15, -14, -8, -4, -3, -3, -4, 0, 4, 5, 3, 6, 4, 4, + 7, 10, 9, 9, 8, 5, 5, 2, -4, -10, -15, -17, -20, -22, -22, -19, + -14, -11, -10, -8, -6, 0, 3, 5, 3, 4, 8, 11, 11, 12, 13, 12, + 12, 15, 15, 16, 16, 13, 11, 6, 3, -2, -5, -5, -3, -2, -1, 2, + 0, -3, -4, -5, -7, -10, -12, -11, -12, -11, -8, -4, -2, 0, 1, 2, + 2, 2, 4, 3, 3, 4, 5, 9, 10, 6, 2, 1, 2, 0, -3, -7, + -13, -18, -19, -18, -16, -18, -20, -19, -14, -8, -4, -1, 3, 3, 5, 7, + 9, 9, 10, 12, 13, 13, 13, 13, 16, 15, 13, 9, 6, 3, 2, 1, + 0, -3, -5, -6, -4, -2, -2, -4, -4, -5, -5, -3, -3, -4, -6, -6, + -7, -4, 0, 2, 3, 2, 2, 1, 2, 2, 1, 4, 5, 4, 1, 0, + 2, 2, 0, -2, -6, -8, -6, -7, -9, -11, -15, -18, -19, -18, -18, -17, + -13, -9, -2, 2, 3, 5, 10, 12, 13, 14, 14, 15, 17, 17, 16, 16, + 15, 13, 11, 7, 2, -6, -10, -8, -6, -8, -8, -7, -6, -6, -3, -4, + -6, -5, -3, -2, -2, 0, 1, 0, 2, 2, 3, 2, 3, 2, 3, 3, + 5, 2, 0, 4, 6, 5, -1, -4, -2, -1, -2, -6, -8, -9, -10, -12, + -10, -14, -17, -22, -22, -21, -19, -15, -8, -3, 1, 7, 12, 12, 15, 19, + 22, 21, 18, 16, 16, 16, 13, 12, 6, 3, 3, 2, -3, -6, -7, -12, + -12, -11, -8, -9, -8, -7, -3, 0, 0, 0, 0, -2, -2, 0, 1, 2, + 2, 4, 6, 6, 7, 5, 4, 3, 4, 5, 3, 0, -2, -2, -4, -6, + -10, -8, -8, -10, -11, -12, -12, -12, -13, -16, -16, -16, -14, -11, -8, -4, + -2, 1, 6, 12, 17, 19, 20, 20, 21, 21, 19, 13, 10, 9, 5, 0, + -3, -4, -4, -5, -6, -6, -4, -7, -10, -12, -12, -12, -10, -7, -4, -2, + 4, 6, 8, 7, 7, 7, 7, 8, 8, 7, 5, 6, 6, 4, 1, -1, + -1, 0, -3, -7, -10, -10, -8, -11, -14, -14, -12, -11, -9, -6, -8, -8, + -8, -11, -13, -12, -9, -8, -5, 0, 4, 8, 11, 14, 18, 18, 20, 23, + 23, 20, 14, 9, 4, 0, -3, -6, -8, -8, -8, -8, -9, -10, -11, -10, + -9, -8, -8, -7, -6, -3, 0, 3, 6, 12, 16, 16, 14, 10, 8, 9, + 7, 4, 1, 0, 0, -2, -1, 0, 0, -3, -7, -10, -13, -13, -12, -13, + -15, -14, -13, -9, -6, -5, -5, -7, -8, -9, -7, -6, -5, -7, -5, 1, + 8, 13, 17, 19, 20, 21, 22, 22, 18, 12, 9, 5, -1, -5, -9, -11, + -13, -12, -12, -11, -10, -8, -7, -7, -6, -7, -6, -3, 0, 1, 3, 7, + 10, 11, 12, 15, 15, 14, 9, 6, 3, 1, 0, -2, -2, -2, -3, -6, + -8, -10, -11, -13, -15, -15, -15, -13, -12, -12, -7, -5, -5, -5, -4, -3, + -3, -4, -4, -1, -1, 1, 4, 7, 10, 12, 14, 17, 20, 22, 19, 14, + 8, 5, 2, -2, -5, -10, -14, -13, -11, -10, -10, -10, -10, -8, -6, -3, + -3, -3, -1, -1, 2, 6, 10, 13, 14, 15, 15, 15, 13, 11, 8, 5, + 1, -1, -3, -3, -6, -10, -12, -12, -12, -12, -13, -15, -18, -19, -15, -11, + -6, -4, -3, -4, -4, -2, 1, 4, 2, -1, -2, 1, 4, 6, 8, 7, + 7, 11, 14, 15, 15, 15, 13, 10, 6, 1, -3, -6, -9, -13, -15, -15, + -13, -11, -9, -9, -9, -7, -3, 0, 2, 2, 4, 7, 11, 15, 16, 14, + 11, 12, 13, 15, 13, 9, 4, 1, -1, -4, -6, -8, -11, -15, -17, -17, + -17, -17, -15, -13, -13, -12, -10, -7, -6, -4, 1, 2, 2, 3, 4, 5, + 4, 4, 3, 5, 6, 6, 8, 7, 7, 9, 11, 10, 9, 8, 5, 2, + 0, -2, -6, -10, -13, -13, -14, -14, -13, -11, -9, -4, -1, -1, -1, 2, + 6, 8, 10, 11, 12, 14, 14, 14, 13, 11, 10, 7, 4, 2, 3, 1, + -3, -6, -10, -14, -17, -18, -18, -19, -19, -17, -15, -13, -9, -5, -1, 1, + 0, 1, 3, 5, 6, 6, 6, 7, 8, 9, 8, 4, 1, 0, 2, 4, + 5, 6, 5, 4, 4, 4, 3, 1, -3, -7, -9, -11, -12, -12, -12, -11, + -10, -7, -4, -2, 1, 4, 5, 8, 11, 13, 14, 14, 11, 11, 11, 10, + 10, 9, 6, 5, 3, 1, -2, -5, -10, -14, -16, -17, -18, -19, -20, -19, + -17, -14, -10, -5, -1, 1, 3, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 8, 7, 6, 4, 2, 0, -1, 0, 0, 1, 2, 1, 1, 2, 1, -2, + -5, -8, -9, -10, -11, -12, -12, -10, -7, -4, -1, 2, 8, 11, 13, 15, + 15, 13, 12, 11, 10, 9, 8, 6, 5, 4, 4, 3, 0, -3, -6, -10, + -14, -18, -21, -22, -21, -18, -16, -13, -10, -6, -3, 0, 3, 5, 5, 5, + 6, 7, 8, 8, 8, 7, 8, 7, 6, 5, 4, 1, 0, -2, -4, -4, + -5, -4, -4, -3, -2, -1, -2, -3, -4, -7, -8, -9, -9, -9, -8, -5, + -2, 2, 4, 8, 11, 14, 15, 15, 14, 12, 10, 7, 5, 4, 4, 2, + 1, 1, 2, -1, -3, -7, -10, -15, -18, -18, -18, -18, -17, -15, -11, -7, + -3, 1, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 10, 9, 6, 4, + 2, 0, -3, -4, -6, -7, -7, -6, -5, -3, -2, -2, -2, -2, -3, -4, + -5, -6, -6, -6, -6, -5, -4, -1, 4, 7, 9, 11, 12, 12, 11, 10, + 9, 8, 7, 5, 3, 3, 2, 1, 0, -1, -4, -7, -8, -10, -13, -14, + -15, -15, -15, -14, -11, -9, -6, -3, 0, 2, 4, 5, 6, 7, 8, 9, + 10, 10, 9, 8, 6, 5, 3, 1, -3, -6, -8, -8, -7, -7, -7, -6, + -4, -2, 0, -1, -2, -3, -3, -3, -3, -4, -3, -3, -1, 1, 3, 4, + 6, 7, 8, 9, 10, 10, 9, 7, 6, 6, 4, 3, 2, 1, -1, -2, + -4, -6, -9, -11, -12, -12, -12, -11, -11, -10, -9, -8, -7, -5, -4, -1, + 1, 3, 5, 7, 9, 10, 11, 10, 9, 8, 7, 6, 2, -1, -3, -4, + -6, -7, -7, -7, -7, -6, -5, -5, -4, -3, -3, -4, -4, -4, -3, -2, + 0, 0, 1, 1, 2, 4, 6, 6, 7, 7, 8, 7, 7, 7, 7, 7, + 6, 5, 2, 0, -2, -4, -5, -7, -8, -8, -8, -9, -10, -10, -9, -8, + -7, -7, -7, -5, -3, -2, 0, 1, 2, 4, 6, 9, 10, 11, 12, 10, + 8, 6, 3, 1, -2, -4, -6, -7, -7, -7, -7, -8, -7, -7, -6, -6, + -5, -4, -3, -3, -2, -1, 1, 2, 2, 3, 4, 5, 5, 5, 6, 6, + 6, 5, 5, 6, 6, 6, 4, 3, 2, 1, -1, -3, -4, -6, -8, -9, + -9, -8, -8, -6, -5, -5, -5, -6, -6, -6, -5, -4, -2, 0, 2, 4, + 6, 7, 8, 9, 9, 9, 9, 6, 4, 1, -1, -3, -5, -6, -7, -7, + -7, -6, -6, -6, -6, -6, -5, -4, -3, -3, -2, -1, 1, 3, 4, 5, + 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, + -1, -3, -4, -5, -6, -7, -7, -7, -7, -7, -6, -5, -4, -4, -3, -3, + -3, -3, -2, -1, 0, 1, 3, 5, 7, 8, 8, 8, 7, 6, 4, 2, + 0, -2, -3, -4, -5, -6, -7, -7, -7, -7, -6, -6, -5, -5, -5, -3, + -2, 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 5, 4, 3, 3, 3, + 3, 3, 3, 2, 1, 1, -1, -2, -3, -4, -5, -6, -6, -7, -6, -5, + -4, -3, -3, -3, -3, -3, -2, -1, -1, 0, 1, 1, 1, 2, 3, 5, + 6, 6, 6, 5, 4, 2, 1, 0, -2, -4, -5, -5, -6, -6, -6, -7, + -7, -7, -6, -5, -4, -3, -2, -1, 0, 2, 3, 3, 4, 4, 5, 5, + 5, 4, 4, 4, 4, 3, 3, 2, 1, 1, 0, 0, -1, -1, -2, -3, + -4, -5, -5, -5, -5, -5, -4, -4, -3, -3, -2, -1, -1, -1, -1, 0, + 0, 0, 1, 2, 3, 3, 4, 4, 4, 4, 4, 3, 1, 0, 0, -2, + -3, -4, -5, -5, -6, -6, -6, -5, -4, -4, -4, -3, -2, -2, -1, 0, + 2, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, + 0, -1, -1, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -2, -2, + -2, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 1, 1, 0, 0, -1, -1, -2, -3, -3, -3, -4, -4, -4, -4, -3, + -3, -2, -1, -1, -1, 0, 1, 1, 1, 2, 2, 2, 3, 3, 2, 2, + 1, 1, 1, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -5, -41, -25, -37, -9, 28, 14, 6, 1, + 19, 16, -83, -53, -35, -44, -29, 8, -23, -29, -6, -20, -22, -19, -40, -2, + 14, 34, 78, 59, 73, 93, 73, 83, 124, 94, 87, 61, 98, 80, 29, 27, + 6, 8, -9, -8, -26, -33, -35, -32, -25, -32, -28, -59, -46, -31, -19, -12, + -12, 14, 14, -41, -59, -46, -33, -32, -52, -31, -29, -49, -51, -53, -85, -53, + -60, -100, -85, -84, -66, -37, -26, -11, -8, 22, 41, 33, 39, 27, 29, 75, + 59, 45, 52, 69, 66, 73, 90, 91, 103, 81, 46, 16, -21, -32, -13, -34, + -22, -42, -51, -35, -53, -62, -45, -35, -34, -29, 25, 62, 61, 39, -8, -20, + -5, -7, 2, 28, 1, -24, 8, 29, 11, -9, -54, -34, -35, -57, -41, -63, + -50, -16, -18, 26, 23, -2, 38, 9, 17, 41, 39, 82, 64, 64, 103, 64, + 43, 43, 51, 26, -3, 30, 1, 9, 14, -26, 20, -27, -50, -39, -47, -31, + -23, -33, 25, 56, 51, 20, -19, -60, -41, -27, -10, 3, -36, -30, -22, -46, + -5, -12, -7, -4, -54, 3, -25, -10, -1, -42, -75, -27, -84, -60, -88, -107, + -73, -29, -67, -53, 9, -10, 17, -29, -33, 55, 12, 7, 121, 70, 42, 123, + 96, 127, 74, 28, 51, 21, 60, 23, -10, 25, 103, 113, 65, 45, 15, -1, + 10, 2, -26, 1, -16, 19, 27, -8, -8, -24, -20, -17, -35, -86, -87, -32, + -51, -26, -60, -60, -50, -15, -31, -30, -50, -55, -19, 22, 14, 30, 49, 42, + 15, -11, -57, -15, -29, -65, -37, -56, -29, 15, 70, 69, 36, 24, 19, 21, + 19, 4, 60, 55, 18, -17, 0, -2, -21, 51, 49, -6, 22, 14, -24, -63, + -5, 4, -53, -33, -1, -37, -34, 40, 30, 12, -6, -1, 12, 12, 23, 20, + 43, 34, 11, -26, -40, 25, 56, -1, -41, -50, -37, -10, 20, -58, -65, -43, + -26, 42, 57, 77, 57, 26, -4, -10, -57, -45, -23, -49, -1, -59, -41, -26, + -27, 24, 52, -3, -12, 19, -44, -31, 33, 11, -14, 43, 31, 7, 58, 84, + 45, 35, 18, -5, 6, -21, -6, -20, -7, 41, 53, 29, 25, 55, 68, 37, + -29, -17, -41, -67, -76, -90, -112, -104, -60, -21, 25, 16, -23, -9, 30, 47, + 17, 3, 19, 4, -2, 30, 24, 1, 26, 33, 34, 10, 14, 1, -5, 16, + -2, -60, -32, -51, -48, -38, -34, -42, -20, 16, 17, -16, -32, -6, 4, -39, + -18, 1, -20, -22, 55, 70, 34, 5, -1, 13, 2, 1, 28, 20, -31, -2, + 51, 26, 24, 19, 11, -1, 2, 30, 13, 2, 70, 36, 15, 24, 5, 9, + 14, 48, 43, 8, 2, -10, 18, 33, 22, -27, -19, -17, -22, 11, 19, -5, + 0, -55, -60, -49, -63, -72, -45, -80, -55, -18, -8, 32, 52, 22, 0, -40, + -42, -30, -68, -51, -9, -67, -52, -10, 7, 35, 12, 36, 64, 23, 13, 64, + 39, 32, 73, 3, 6, -10, -6, 16, 18, 53, 51, 21, -20, -15, 13, -3, + 2, -39, -30, -7, -3, 6, 10, -4, -25, -7, -10, -10, -18, -31, -23, -38, + -48, -3, -26, -43, -7, 11, 31, 62, 41, -7, -34, -42, -24, 17, 12, 44, + 25, 24, 18, 11, 32, 51, 46, 46, 51, 33, 24, 32, 30, 40, 8, -30, + -39, -30, -44, -19, -33, -55, -41, -36, -70, -67, -64, -34, -37, -46, 1, 19, + 27, 81, 23, 13, 10, -5, -18, -19, -51, -14, -48, -75, 11, 51, 43, 63, + 37, 20, 19, 4, -23, 27, 47, 71, 29, 16, 15, -17, -11, 32, 40, 22, + 6, 16, -7, 5, 34, 61, 12, -21, -24, -13, -38, -41, -36, -33, 2, 9, + -45, -54, -36, 12, -18, -41, -25, -18, 19, 31, -11, -16, -22, -62, -65, -68, + -42, -4, -48, -49, 4, 38, 65, 47, 12, -20, -20, -8, 3, 32, 69, 84, + 44, 28, 31, 18, 36, 57, 74, 35, 19, 6, 24, 29, 36, 35, 6, -13, + -25, -43, -45, -35, -33, -44, -23, -41, -57, -52, -41, -35, -21, -16, -22, -11, + 33, 42, 14, 19, 16, 0, -6, -34, -17, -37, -25, -7, 6, 48, 47, 3, + -14, -17, -19, -11, -9, -11, 42, 42, 16, 1, 6, 15, 51, 42, 33, 29, + 20, -5, -3, 4, 54, 42, 8, -30, -19, -15, -15, -20, -6, -7, -24, -32, + -24, -17, -1, -16, -18, -36, -55, -38, -2, 8, 16, 7, -21, -35, -56, -67, + -17, -58, -67, -36, 21, 67, 48, 15, 8, 13, -9, -8, -1, 21, 107, 56, + 40, 56, 32, 33, 71, 60, 36, 30, 3, 31, 15, 4, 21, 2, -2, -25, + -30, -26, -13, -9, -26, -20, -34, -34, -51, -28, 6, -9, -24, -49, -67, -54, + -54, -52, -41, -42, -58, -37, 16, 39, 31, 16, 19, 11, -4, -23, -5, 24, + 1, 10, 24, 26, 15, 34, 70, 77, 56, 33, 43, 28, 17, 25, 12, 2, + 0, -12, -15, -2, 10, -19, -28, -45, -41, -28, -17, -3, -2, -9, -3, -25, + -45, -14, 23, 10, -5, -19, -32, -22, -10, -1, -15, -16, -6, 13, 48, 70, + 55, 23, 23, 10, -8, -14, 6, 8, -12, -5, 13, 10, -14, 0, 33, 23, + 18, 43, 21, 26, 33, 13, -14, -7, -3, -31, -29, -5, -5, -25, -27, -35, + -56, -45, -21, -17, -40, -14, 2, -23, -38, -9, 8, -16, -16, -7, -13, -25, + -4, -12, -21, -14, 3, 13, 44, 65, 60, 40, 15, 5, -20, -22, -3, 3, + 20, 39, 39, 9, 6, 21, 48, 24, 25, 25, 11, 0, 4, -5, -31, -34, + -22, -45, -40, -24, -24, -41, -38, -47, -54, -45, -16, -22, -32, -7, 16, -1, + -11, 23, 31, -1, -10, -20, -19, -9, 15, -10, -28, -21, 4, 24, 45, 60, + 56, 46, 30, 26, 23, 36, 48, 33, 46, 40, 34, 19, 12, 23, 43, 37, + 41, 43, 22, 24, 11, -11, -2, -5, 8, -28, -33, -11, -5, -26, -30, -25, + -45, -21, -8, -26, -35, -37, -39, -54, -56, -20, -23, -42, -52, -49, -63, -47, + -31, -29, -16, -21, -7, 14, 26, 48, 32, 12, -10, -22, -24, -6, 0, 33, + 44, 31, 25, 15, 10, 34, 48, 38, 14, 9, 16, 12, -23, -15, -15, -8, + -9, -19, -22, -2, -8, -10, -32, -27, 4, 12, -5, 1, -1, 4, -5, -3, + -5, 10, 37, 18, -8, -19, -3, 0, -10, -5, -31, -32, -29, -2, 18, 32, + 33, 14, -12, -15, 6, 8, 36, 66, 48, 38, 37, 42, 29, 49, 50, 42, + 28, 25, 33, 15, 2, 4, 2, 4, 2, -11, -1, 6, 3, 9, -14, -12, + -5, -12, -33, -36, -29, -26, -38, -44, -42, -38, -38, -52, -67, -70, -50, -32, + -27, -29, -38, -26, -27, 1, 21, 23, 16, -17, -34, -26, -18, -20, 2, 11, + 13, 5, 10, 13, 12, 28, 33, 35, 14, 14, 14, -8, -24, -25, -8, -16, + -23, -14, 12, 8, 21, 25, 13, 25, 29, 25, 6, 3, 36, 26, 34, 11, + 30, 29, 34, 23, 0, 1, 7, 8, 1, -10, -9, -13, 5, 17, 30, 26, + 25, 3, -11, -4, -4, 9, 13, 17, 6, 4, 17, -1, -4, 9, 16, 22, + 3, -2, -4, -16, -28, -22, -13, -34, -37, -31, -9, -7, -12, -16, -26, -12, + -14, -11, -23, -16, -24, -33, -24, -30, -17, -28, -34, -44, -51, -34, -24, -22, + -25, -2, 14, 23, 38, 46, 43, 28, 10, -6, -11, 1, 0, 5, 18, 16, + -3, 12, 27, 23, 32, 48, 42, 34, 21, 21, 10, -3, -10, -10, -20, -38, + -34, -29, -22, -16, -15, -17, -9, 7, 6, 6, -6, 1, 7, 6, 3, 11, + 30, 30, 15, 11, 11, 10, 17, 22, 23, 24, 9, 15, 5, -2, 4, 3, + -17, -21, -4, -21, -6, 8, -9, -1, 0, 8, -7, -18, -16, -3, -14, -13, + -8, -17, -10, -8, -26, -37, -28, -17, -35, -17, -10, 1, -6, 1, 25, 32, + 26, 9, -18, -19, 1, -12, -20, 2, 12, 5, -4, 15, 14, 15, 15, 17, + 14, 2, 6, 3, -18, -21, -9, -1, -15, -11, -15, -22, -1, 3, -7, 0, + 14, 14, -4, -13, 4, 18, 12, 15, 19, 25, 28, 27, 12, 9, 9, -10, + -17, -4, -5, -4, -20, -19, 11, 20, 13, 0, -19, -8, 6, -9, 6, 26, + 18, 14, 17, 22, 24, 18, 21, 37, 20, 7, 11, -8, -11, -4, -3, -8, + -22, -16, -18, -15, -4, -9, -21, -10, 5, -8, -7, -17, -7, -9, -20, -28, + -35, -31, -23, -23, -29, -28, -28, -33, -28, -24, -6, 0, -4, 7, 29, 25, + 15, -6, -19, 1, -2, -22, 4, 10, 1, 9, 10, 13, 4, 6, 21, 15, + 5, 21, 11, -18, -21, -15, -3, -4, -15, -15, -19, 4, 19, 11, 2, 17, + 16, 2, 14, 14, 17, 20, 22, 20, 10, 16, 27, 12, 8, 11, 5, -9, + -10, -6, -1, -7, -12, -3, 3, 8, 9, -5, -3, 6, -5, -6, 23, 14, + 11, 12, 21, 21, 4, 18, 30, 7, 12, 25, 3, -11, -16, -15, -10, -13, + -8, -6, -21, 2, -2, -25, -18, -8, -22, -22, -17, -12, -7, -12, -15, -20, + -41, -28, -24, -23, -12, -12, -15, -10, -7, 2, 1, 6, 18, 29, 23, 21, + 20, 9, -3, -9, -9, -10, -15, -8, -11, -2, 6, 14, 7, 7, 11, 9, + 14, 2, 3, 7, 6, 6, -21, -20, -10, -12, -15, -16, -18, -14, -11, -14, + 0, 0, -5, 3, 14, 12, 9, 0, -11, 5, 5, 12, 11, -1, 5, 3, + 1, 4, -1, -1, 13, 16, 8, 14, 9, -2, -7, -11, -17, -12, -5, -9, + -10, -13, -4, 1, 0, 4, 5, 0, 2, 3, 5, 14, 18, 9, -3, 2, + 15, 14, 6, 2, 1, -1, -5, -6, 0, 0, 0, 7, 20, 22, 23, 13, + 13, 17, 20, 35, 25, 20, 20, 14, 17, 16, 3, 7, 18, 15, 13, 17, + 6, -5, -6, -13, -23, -19, -19, -22, -22, -24, -17, -18, -22, -27, -31, -30, + -29, -30, -33, -36, -34, -37, -47, -38, -24, -28, -27, -31, -30, -28, -26, -20, + -14, -14, -9, 4, 17, 21, 15, 12, 25, 29, 33, 33, 30, 30, 31, 19, + 20, 14, 4, 10, 17, 18, 21, 28, 19, 20, 20, 5, -2, -3, -7, -10, + -2, 1, 4, 6, 4, 5, 3, 2, -1, -4, -7, -10, -3, -6, -16, -5, + -1, -8, -7, -6, -9, -10, -11, -7, -6, -10, -11, 2, 11, 7, 1, 6, + 12, 16, 18, 15, 11, 14, 16, 9, 11, 6, 5, 13, 14, 13, 11, 0, + -11, -4, -4, -8, -7, -5, -6, -3, -1, 2, -1, -6, -7, -9, -9, -9, + -15, -11, -14, -17, -16, -18, -17, -12, -7, -8, -7, -6, -2, -3, -12, -15, + -15, -18, -13, -19, -23, -24, -21, -21, -13, -12, -7, -3, -7, -6, -4, 2, + 1, 1, 3, 9, 23, 28, 23, 17, 24, 27, 22, 19, 16, 19, 10, 9, + 10, 10, 19, 8, 11, 16, 15, 11, 13, 14, 7, 5, -3, -7, -12, -15, + -16, -17, -10, -5, 4, -2, -2, -9, -13, -9, -8, -10, -10, -12, -5, 3, + 7, 3, 9, 3, 4, -1, -2, 2, -4, -9, -4, 0, 4, 4, -6, -3, + 12, 10, 15, 12, 7, 7, 1, -1, 8, 11, 9, 9, 13, 17, 17, 9, + 11, 4, 0, -3, -6, -8, -9, -10, -17, -20, -24, -17, -19, -22, -20, -21, + -15, -16, -19, -23, -21, -28, -26, -15, -14, -4, -1, -6, -3, -1, 4, 9, + 2, 4, 7, 7, 11, 15, 6, 17, 24, 16, 15, 9, 6, 6, 3, 1, + 3, 2, -2, 6, 6, 6, 3, -6, -3, -8, -7, -10, -13, -17, -18, -16, + -19, -13, -9, -3, 4, 10, 7, 7, 12, 11, 13, 10, 6, 1, 2, 4, + 4, 10, 10, 7, 4, 1, 4, -5, -12, -3, 1, 10, 7, 6, 4, 19, + 22, 20, 23, 16, 15, 19, 17, 14, 9, 7, 4, 4, 2, 5, 3, 0, + 0, -7, -7, -8, -7, -14, -15, -18, -25, -21, -21, -16, -13, -14, -17, -18, + -23, -21, -23, -29, -32, -33, -30, -23, -13, -11, -10, -8, -7, -2, 1, -3, + -1, 5, 13, 17, 13, 11, 13, 16, 14, 10, 11, 8, 16, 13, 4, 0, + 7, 13, 14, 15, 15, 17, 17, 9, 8, 9, 9, 2, 5, 11, 14, 7, + 4, 11, 10, 5, 7, 2, -1, -4, -9, -16, -15, -12, -9, -15, -23, -21, + -22, -22, -20, -22, -22, -21, -22, -22, -13, -6, 4, 2, -2, 2, 7, 6, + 10, 8, 9, 12, 21, 16, 11, 7, 11, 13, 11, 10, 11, 13, 9, 6, + 6, 5, 4, -5, 1, 4, 5, -1, -2, 6, 3, 3, -3, -10, -14, -14, + -14, -16, -8, -6, -1, -6, -7, -5, -7, -6, -9, -8, -8, -4, -5, -8, + -6, 3, 12, 4, -2, 3, 1, 1, -1, -4, -4, 5, 6, 1, -4, -3, + 5, 9, 8, 18, 20, 22, 15, 11, 11, 15, 12, 9, 11, 11, 11, 5, + 10, 12, 5, 3, -2, -4, -9, -9, -16, -17, -14, -12, -14, -20, -15, -16, + -17, -17, -19, -20, -19, -15, -17, -15, -13, -2, -3, -13, -8, 0, 4, 7, + 6, 4, 11, 13, 14, 11, 5, 6, 3, -1, -2, 2, 3, -1, -2, -6, + -4, -1, -3, 0, 3, 1, -2, -5, -5, -3, -6, -9, -7, -15, -13, -10, + -8, -4, 1, 9, 7, 2, 8, 8, 9, 12, 14, 7, 12, 12, 12, 8, + 14, 19, 11, 7, 10, 13, 10, 2, -2, -6, -1, 2, 6, 3, 1, 4, + 2, 2, 5, 8, 8, 7, 7, 2, 0, -3, -6, -3, -1, -6, -12, -9, + -6, -7, -9, -10, -14, -16, -12, -12, -11, -13, -16, -16, -20, -18, -14, -10, + -8, -9, -13, -9, -8, -9, -7, -9, -8, -3, -4, -3, -6, 0, 2, 3, + -3, 2, 5, 1, 6, 5, 5, 10, 11, 17, 15, 20, 25, 20, 15, 17, + 13, 12, 11, 7, 4, -1, -2, 6, 7, 7, 9, 10, 7, 9, 7, 5, + 5, 1, -6, -2, -5, -6, -3, -3, -1, -3, -5, -3, -6, -8, -7, -8, + -11, -12, -16, -19, -19, -14, -14, -17, -17, -11, -12, -15, -6, -8, -12, -12, + -9, -7, -6, 2, 9, 6, 8, 11, 13, 15, 14, 11, 7, 3, 3, 4, + 7, 9, 10, 6, 6, 5, 7, 11, 11, 4, 1, 1, -3, -5, -1, -1, + -1, -5, -2, -1, -1, 1, 1, -3, -7, -7, -9, -12, -11, -3, -3, -7, + -6, -6, -5, -5, 0, -3, -4, -2, 2, -1, 0, 6, 7, 7, 4, 3, + 5, -1, 0, -1, -7, -9, -8, -11, -5, 0, -1, 0, 2, 2, 5, 10, + 10, 7, 7, 7, 8, 8, 9, 11, 9, 8, 9, 6, 4, 2, 0, -3, + -5, -8, -8, -12, -8, -1, -4, -4, -5, -7, -9, -6, -5, -6, -8, -6, + -3, -7, 0, 5, 6, 3, 1, 6, 6, 4, 3, 1, -2, -4, -6, -4, + 3, 7, 3, 0, -1, -3, -2, -1, -2, -5, -8, -9, -7, -9, -8, -6, + -9, -7, -9, -7, -6, -7, -6, -7, -7, -7, -7, -8, -2, 1, 2, 4, + 3, 5, 6, 10, 11, 9, 10, 12, 9, 9, 11, 9, 10, 8, 7, 7, + 6, 7, 5, 4, 5, 4, -1, -4, -3, -5, -1, -2, -4, -4, -4, -4, + -2, -2, -3, -4, -2, -1, 0, 1, 8, 8, 4, 4, 4, 2, -2, -3, + -5, -6, -9, -10, -8, -5, 2, 1, -2, -2, -2, -2, -2, -5, -5, -7, + -7, -3, -4, -6, -4, -3, -5, -7, -5, -4, -7, -9, -6, -6, -9, -7, + -6, -2, 3, 3, 4, 5, 3, 4, 5, 2, 0, 2, 3, 2, 5, 7, + 10, 9, 7, 7, 6, 4, 1, -2, -5, -6, -10, -10, -8, 2, 8, 7, + 6, 7, 5, 5, 7, 6, 3, 4, 3, 4, 1, 3, 2, 4, 2, 1, + 1, -1, -3, -3, -4, -6, -9, -9, -9, -7, -6, -5, -5, -4, -5, -2, + -1, -2, -3, -1, -1, -3, -2, 2, 2, 3, 4, 4, 2, 0, -1, -3, + -4, -4, -5, -7, -2, 2, 2, -1, -3, -1, -4, -3, -2, -4, -4, -2, + -1, -2, -4, -2, -2, -1, -2, -2, -2, -3, -2, 0, 2, 0, -2, -2, + 0, 2, 3, 5, 4, 4, 4, 6, 3, 1, 0, 0, 0, 0, 5, 5, + 4, 6, 4, 2, 0, -2, -3, -6, -9, -8, -10, -10, -2, 3, 4, 4, + 4, 5, 4, 4, 5, 4, 4, 4, 4, 2, 3, 2, 2, 2, 1, 1, + 0, -2, -3, -3, -4, -6, -8, -7, -4, -6, -3, -3, -3, -2, 1, 0, + -1, -2, -2, -1, -1, 0, 1, 0, 0, 1, 0, 0, 0, -1, -2, -3, + -3, -4, -5, -4, -3, -3, -3, -3, -3, -3, -2, -1, 0, -1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 2, 3, + 3, 2, 2, 0, -1, -1, -2, -3, -3, -4, -5, -4, 0, 3, 3, 3, + 3, 2, 3, 4, 6, 4, 4, 3, 2, 1, 2, 1, 0, 0, -1, -2, + -3, -3, -2, -2, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, + -2, -3, -2, -3, -2, -2, 0, 0, 0, 0, 0, -1, -1, -2, -2, -3, + -2, -4, -4, -3, 0, -1, 0, 0, 0, 0, 0, 1, 2, 1, 1, 1, + 0, 0, 0, -1, 0, -1, -1, -1, -1, -1, 0, 0, -1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, + 0, 0, -1, -1, -2, -2, -2, -2, -2, -3, -3, -1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, -8, -33, -24, -25, -25, -26, -27, + -32, -28, -36, -31, -36, -22, -34, 11, -74, -14, 94, 41, 28, 33, 30, 40, + 34, 23, 41, 40, 60, 56, 59, 60, 44, 39, 54, 45, 52, 17, 44, 62, + 34, 33, 19, 18, 43, 35, 22, 36, -15, -10, 32, -7, -12, -6, -8, -50, + -47, -44, -4, -25, -48, -76, -58, -75, -96, -85, -118, -114, -63, -106, -103, -83, + -110, -99, -84, -76, -58, -63, -61, -51, -53, -36, -32, -41, -27, -11, 11, 8, + 27, 19, 30, 35, 28, 57, 53, 38, 71, 51, 68, 110, 78, 89, 109, 97, + 82, 94, 115, 114, 79, 70, 79, 94, 85, 76, 84, 95, 83, 82, 55, 54, + 54, 41, 41, 27, 20, 6, -11, -21, -16, -14, -33, -33, -52, -54, -59, -62, + -71, -79, -88, -88, -78, -78, -72, -71, -94, -99, -93, -90, -78, -87, -105, -103, + -79, -62, -71, -78, -63, -61, -66, -49, -23, -10, -11, -24, -20, -4, -22, 9, + 8, 27, 43, 34, 38, 51, 83, 65, 58, 74, 75, 70, 73, 71, 65, 100, + 89, 94, 65, 84, 49, 49, 61, 54, 43, 51, 58, 53, 35, 40, 36, 38, + 34, 23, 14, -12, -10, -1, -1, -11, -12, -19, -33, -66, -52, -42, -37, -55, + -42, -28, -32, -29, -35, -41, -28, -25, -46, -85, -64, -62, -55, -49, -68, -55, + -53, -52, -47, -43, -26, -32, -41, -34, -35, -40, -26, -8, -1, -6, -11, 5, + -2, 8, 3, 8, 6, 4, 20, 29, 43, 24, 33, 20, 30, 24, 39, 38, + 40, 29, 37, 36, 39, 61, 58, 41, 51, 59, 51, 55, 58, 48, 32, 45, + 40, 27, 30, 41, 44, 26, 19, 23, -3, 7, 0, -3, 2, 3, -6, -5, + -14, -6, -10, -27, -45, -47, -41, -38, -50, -51, -46, -43, -45, -65, -65, -80, + -95, -82, -74, -66, -69, -67, -33, -31, -53, -48, -51, -43, -18, -24, -24, -33, + -26, -10, 0, -17, -6, 17, 31, 2, 23, 45, 46, 12, 75, 38, 63, 69, + 31, 38, 80, 57, 48, 59, 81, 74, 32, 52, 72, 24, 60, 44, 55, 40, + 28, 48, 33, 24, 10, -2, 21, 34, 13, 18, 7, -1, -12, -20, -18, -30, + -9, -7, -30, -27, -26, -38, -20, -54, -55, -64, -53, -36, -62, -37, -71, -47, + -42, -71, -45, -55, -50, -54, -56, -36, -37, -54, -36, -12, -38, -33, -26, -7, + -22, -44, -10, 2, 3, 15, 8, 18, 6, 12, 8, 15, 28, 22, 50, 35, + 55, 42, 36, 49, 52, 64, 48, 60, 49, 60, 62, 40, 47, 68, 52, 59, + 61, 44, 53, 44, 35, 31, 31, 47, 22, 6, 4, -7, 5, -4, -21, -13, + -9, -10, -27, -46, -32, -44, -46, -62, -44, -51, -67, -53, -59, -63, -74, -67, + -61, -61, -65, -47, -58, -57, -45, -41, -46, -41, -38, -22, -25, -34, -16, -10, + -18, 0, 1, -6, 5, 17, 15, 10, 23, 38, 28, 28, 54, 40, 19, 55, + 55, 41, 46, 53, 40, 49, 51, 52, 41, 56, 39, 53, 38, 33, 35, 18, + 15, 38, 30, 23, 27, 13, 11, 7, 16, -1, 0, 0, 13, -6, -10, -15, + -10, -10, -24, -20, -16, -38, -36, -21, -40, -32, -42, -38, -52, -53, -41, -48, + -58, -50, -47, -37, -41, -45, -29, -41, -6, -48, -24, -25, -15, -9, -10, -10, + -10, -1, -17, 4, 3, 10, -4, 9, 15, 25, 24, 19, 23, 34, 28, 33, + 37, 38, 26, 36, 47, 35, 46, 45, 28, 35, 32, 32, 24, 21, 26, 23, + 19, 37, 20, 9, 29, -2, 26, 24, 8, 4, 14, 21, 11, -9, -8, 4, + -9, -31, -11, -15, -21, -24, -29, -22, -33, -26, -29, -48, -32, -44, -28, -22, + -35, -30, -38, -31, -46, -44, -36, -27, -23, -29, -24, -11, -20, -28, -13, -34, + -19, -1, 7, -3, -1, 6, -3, 5, 4, 8, 17, 26, 19, 33, 27, 16, + 35, 14, 36, 39, 22, 32, 31, 19, 32, 23, 29, 21, 30, 29, 23, 31, + 13, 24, 17, 11, 26, 18, 12, 5, 23, 16, 9, 15, -10, 3, 18, -15, + -4, -4, 6, -14, -15, -5, -34, -11, -20, -18, -8, -17, -29, -30, -29, -19, + -34, -35, -20, -36, -20, -16, -21, -38, -16, -30, -24, -25, -19, -18, -15, -7, + -5, -5, -10, -23, -3, -14, 0, -1, -12, -9, 7, 7, 2, 12, 5, 7, + 19, 10, 21, 21, 27, 30, 22, 18, 34, 22, 11, 26, 24, 20, 21, 25, + 29, 22, 27, 27, 20, 10, 20, 16, 22, 15, 16, 16, 5, 19, 10, 3, + 22, -5, -5, -7, -16, -4, -11, -22, -7, -16, -11, -23, -16, -30, -24, -28, + -20, -29, -24, -32, -22, -22, -30, -17, -23, -28, -22, -20, -21, -21, -17, -30, + -15, -14, -20, -9, 3, 6, 5, -20, 10, 13, -2, 11, 8, -1, 7, 16, + 5, 22, 23, 13, 22, 13, 22, 25, 15, 16, 11, 15, 13, 7, 12, 19, + 18, 20, 12, 23, 11, 6, 10, 1, 11, 19, 5, 20, 0, 11, 11, 1, + 14, 15, -3, -1, -7, 6, -6, -9, -9, 4, -3, -10, -20, -14, -9, -14, + -7, -10, -5, -4, -29, -14, -12, -26, -21, -27, -18, -10, -19, -27, -18, -8, + -25, -8, -13, -15, -14, -15, 5, -13, -7, -11, -4, -12, 0, 15, 5, 4, + 1, 11, 6, 4, 3, 6, 21, 19, 8, 15, 13, 6, 14, 16, 18, 17, + 20, 15, 11, 15, 24, 13, 11, 19, 7, 17, 14, 6, 17, 7, 7, 6, + 6, 5, 11, 0, 6, 0, -6, 5, 1, -11, -6, -1, -8, -9, -15, -7, + -4, -16, -17, -13, -13, -17, -14, -12, -12, -28, -13, -19, -25, -31, -24, -17, + -17, -16, -7, -15, -12, -8, -15, -8, -16, -10, -4, -1, -2, 3, 5, 2, + -2, 5, 3, 6, 10, 8, 11, 14, 14, 13, 15, 22, 16, 14, 18, 13, + 17, 19, 16, 10, 17, 8, 17, 14, 3, 14, 7, 10, 10, 7, 6, 6, + -1, 6, 1, 0, 12, -6, 6, 12, -4, -5, -4, -2, -2, -1, -2, -8, + -11, -9, -11, -11, -18, -6, -5, -16, -9, -14, -10, -13, -10, -11, -15, -14, + -14, -12, -17, -17, -17, -7, -11, -14, -15, -12, -6, -15, -5, -13, -9, 0, + 12, -2, -2, 6, 2, -7, 4, 10, 2, 9, 8, 7, 4, 5, 11, 15, + 11, 10, 18, 9, 13, 13, 13, 21, 11, 18, 19, 13, 14, 16, 6, 8, + 1, 19, 11, 10, 11, 1, 3, -1, -1, 5, -11, 5, -1, -5, -3, -13, + -10, -6, -7, -5, -15, -10, -11, -18, -8, -16, -20, -18, -9, -12, -17, -21, + -21, -13, -21, -8, -10, -10, -5, -16, -7, 2, -6, -6, -9, -7, -2, -9, + -5, 6, -7, 1, 3, -1, 2, 1, 2, 9, 8, 5, 15, 12, 1, 11, + 9, 8, 10, 15, 14, 5, 13, 17, 14, 15, 10, 7, 16, 5, 5, 5, + 8, 9, 10, 10, 7, 0, 4, 6, 9, -10, -4, 5, 2, -1, 0, -3, + -4, -5, -10, -5, -8, -9, -10, -3, -13, -6, -9, -20, -15, -11, -18, -14, + -10, -12, -20, -14, -14, -7, -12, -21, -14, -9, -8, -11, -5, -2, -7, -4, + 4, -2, -3, -1, 0, -1, 8, 6, 9, 7, 10, 6, 3, 4, 7, 10, + 11, 6, 9, 17, 11, 9, 7, -2, 16, 13, 12, 18, 5, 16, 9, 4, + 9, 6, 8, 9, 4, 4, 3, -2, -3, 2, -6, -3, 1, -7, -6, -3, + -6, -14, -8, -9, -4, -13, -9, -8, -16, -10, -12, -13, -11, -7, -8, -12, + -9, -8, -7, -11, -4, -8, -7, -8, -3, -13, -10, -3, 6, -5, -5, 0, + -5, -3, 6, -2, -2, 4, -2, 6, 2, -2, 5, 5, -2, 5, 15, 13, + 4, 6, 6, 14, 9, 4, 8, 7, 3, 11, 12, 2, 10, 7, 10, 8, + 4, 6, 2, 0, 3, 2, 4, 2, -6, -2, 2, -4, 3, -5, -6, -5, + -5, -5, -4, -8, -7, -4, -4, -7, -8, -7, -13, -10, -10, -11, -9, -8, + -8, -7, -11, -7, -3, -9, -6, -7, -3, -4, -5, 3, -3, -1, -2, -4, + 1, 4, 0, 3, 0, 5, 2, 0, 5, 4, 1, 3, 1, 0, 1, 7, + 3, 0, 4, 3, 6, 5, 0, 9, 5, 7, 6, 3, 6, 2, 3, 5, + -4, 9, 0, 4, 10, 0, 5, 1, -2, 4, -3, -3, -2, 0, 2, -7, + 3, -10, -1, -6, -9, -2, -4, -10, -3, -7, -6, -4, -10, -6, -6, -11, + -6, 0, -6, -8, -4, -1, -9, -10, 0, -6, -7, -2, -7, 1, -5, -5, + -1, 1, -6, 2, 0, -3, -1, 7, -4, 0, 7, 0, 8, 2, 3, 4, + 4, 2, 5, -1, 6, 7, 5, 6, 4, 2, 4, 6, 8, 6, 3, 1, + 8, 9, 2, -1, 4, 3, 4, 3, -3, 7, 4, 3, -2, 2, -4, -6, + -2, -5, -2, -3, 0, -5, -6, -13, -5, -6, -11, -9, -10, -5, -4, -9, + -9, -7, -7, -8, -8, -6, -5, -7, -5, -1, -3, -4, -2, -2, 2, -3, + 1, 2, -3, 1, 2, 1, 0, 1, 5, 0, 2, 5, 2, 0, 4, 1, + 7, 3, 2, 6, 0, 5, 7, 5, 5, 1, 3, 3, 5, 10, 3, 4, + 8, 2, 7, 3, -2, 3, 0, -1, -1, 1, 0, 1, -3, -2, -5, -4, + -3, -1, -7, -8, -4, -4, -10, -2, -8, -8, -8, -8, -9, -6, -8, -9, + -4, -2, -7, -5, -2, -7, -6, -9, -2, 0, -4, 4, -6, -3, -4, -1, + 2, 1, 2, 9, 0, 3, 0, 6, 4, 0, 5, 6, 2, 7, 7, 5, + 7, 6, 8, 6, 6, 5, 5, 1, 6, 5, -1, 3, 4, -1, 4, 1, + 4, 3, -5, 0, 4, 1, 4, -2, -3, -4, 0, -4, -8, -2, -5, -4, + -8, -6, -5, -3, -3, -7, -9, -6, -10, -10, -6, -6, -5, -4, -7, -6, + -4, -10, -3, -10, 0, -2, -2, -6, -1, 3, -3, -3, 1, 2, 1, 4, + 3, 4, 3, 4, 1, 2, 6, 5, 5, 5, 7, 9, 1, 5, 4, 4, + 7, 2, 9, 2, 4, 8, 2, 5, 6, 3, -2, -2, -1, -2, -1, 1, + -2, -4, 1, -6, -2, -5, -3, -5, -5, -6, -4, -3, -4, -10, -4, -3, + -8, -4, 0, -3, -5, -6, -6, -3, -1, -7, -3, 1, -1, -4, -2, 1, + -2, 0, -1, -2, 0, 0, 5, -2, 0, 3, 3, 1, 5, 2, 4, 1, + 4, 1, 2, 3, 3, 3, 4, 3, 3, 5, 1, 4, 2, 3, 1, 2, + 0, 2, 1, -2, -2, -1, 0, -2, -1, -1, -3, -5, -2, 0, -5, -1, + 0, -5, -2, -2, -2, -3, -3, -1, -4, -1, -2, -4, -2, -1, -2, -1, + 0, -3, -1, -1, 0, 1, -1, -1, 3, -4, -2, -2, 4, -2, -1, -1, + -1, 0, 0, -1, -1, -1, -1, 2, 0, -1, 2, -1, 0, -1, 2, 0, + 3, 5, -2, 1, 2, 0, 5, 0, -3, 4, -3, 1, 2, 0, 4, -1, + -2, 1, 0, 0, 0, -1, 1, -2, 0, 1, 1, 0, -5, 1, -2, -1, + 0, -2, -3, -1, -3, 0, -2, -3, -4, 1, -2, -3, -2, -2, -1, -1, + -2, -1, -4, -5, 2, -4, 0, 1, -1, 2, -2, -1, 0, 0, 1, -3, + 3, 2, 0, -2, 2, 1, 2, -2, 5, 3, -2, -2, -1, 1, 0, 0, + 1, 3, 2, 0, 0, -1, -2, 1, 1, 2, 1, 1, -1, 0, -1, -1, + -1, -3, 1, 1, 2, -2, -1, 0, 0, -2, 0, -1, -1, 2, -2, 1, + -1, 0, 0, -1, -1, -2, 0, -1, 1, -1, -1, 2, -2, 0, -1, -1, + 2, -1, 0, -3, -1, 0, 0, 0, -3, -3, -2, 0, 0, -1, -1, 0, + -4, 2, 0, -2, 0, 1, -3, -1, 2, 1, 0, -1, 0, 0, -1, 0, + 2, -1, -1, 0, 0, -2, 1, 1, 0, 1, 0, 2, -3, -2, 2, -1, + -1, 2, -2, 1, 1, 0, 0, 1, 1, 0, -4, 3, -1, 2, 0, 2, + -1, -2, 0, 1, 1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, + -1, 1, 0, -5, 0, -1, -1, -1, 1, -1, 1, -1, 1, 0, -2, 0, + -2, 1, -1, 1, 0, -1, -2, 0, -1, 0, 0, 2, 0, 0, 0, 1, + 0, 0, 2, 0, -1, 0, 0, 0, 2, -1, 1, 1, -1, -1, 0, 0, + 1, 1, 0, 0, 0, 0, -1, 0, 0, -2, 0, 0, -1, 1, -2, -1, + -1, -1, -2, -1, -2, 1, -1, 0, -2, -2, 1, -2, -1, 1, 0, 1, + 1, -1, -1, 0, -1, 0, 0, 0, -2, 0, -1, 0, 0, -1, -2, -2, + -2, 1, -1, 0, 0, -1, 1, 1, -2, -1, -2, -1, 1, -1, -1, -2, + -2, 0, 0, 1, -1, -1, -1, -1, -2, 2, 0, 0, 1, 1, 1, -2, + 0, -1, 0, -1, -1, 2, 0, -1, -1, -1, 1, -1, 2, 0, -1, 1, + 1, 0, 1, 0, -1, -1, -1, -1, -3, 0, 0, -1, 1, 0, 0, -2, + -2, -2, 0, -1, 0, 0, -1, 0, -1, -2, -1, -2, 0, -2, 0, 0, + -1, -2, 1, -2, 0, -1, -2, 2, 0, -1, 2, -1, 1, -1, 0, 0, + -1, 0, 0, 0, -1, 0, 1, 0, 0, 1, 0, -1, -1, 0, -2, -1, + 0, 0, 1, 0, 0, 0, 0, -1, -1, 1, -1, -2, -1, 0, 0, -2, + 0, -1, 0, 0, 0, 1, 0, 0, -1, 1, 0, -1, 0, 1, -1, 0, + -1, -2, 0, -1, 0, -1, -1, -1, 0, -1, 0, 0, 0, -1, -1, 0, + -2, 0, 0, 0, -2, -2, 0, -2, -1, -1, -1, -2, 0, -1, -1, -1, + 0, 0, -1, -1, 0, 1, -1, -1, 0, -1, 0, 0, 1, 1, 0, 0, + -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, 0, 0, -1, 0, + 0, -1, -1, 0, -1, -1, 0, -1, 0, -1, -1, 0, -2, -1, 0, -1, + -1, -1, -1, 0, -1, 0, 0, 0, 0, -1, 1, 0, 0, 0, -1, -1, + 0, -1, -1, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, -1, + 0, -2, 0, -1, -1, -1, 0, -1, -1, 0, -1, 0, 0, 0, -2, -1, + 0, -1, -1, 0, 1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, 0, + 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, + -1, 0, 0, -1, -1, -1, 0, 0, -1, -1, 0, -1, 0, 0, 0, -1, + 0, -1, -1, 0, -2, -1, -1, -1, 0, -1, 0, -1, -1, 0, 0, -1, + 0, -1, 0, -1, -1, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, + 0, -1, -1, 0, 0, 0, -1, 0, -1, 0, 1, -1, 0, 0, 0, 0, + 0, -1, 0, 0, 0, -1, 0, 0, -1, -1, 0, 0, 0, -1, 0, 1, + -1, -1, -1, 0, 0, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, + 0, -1, -1, 0, -1, -1, 0, -1, 0, -1, -1, -1, -1, 0, -1, -1, + -1, -1, -1, -1, -1, 0, -1, 0, -1, 0, 0, -1, -1, 0, -1, 0, + -1, 0, 0, -1, 0, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, + 0, -1, 0, -1, 0, 0, 0, -1, -1, 0, 0, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 0, 0, -1, -1, -1, 0, 0, 0, -1, 0, -1, -1, + 0, -1, 0, 0, -1, -1, -1, -1, -1, 0, 0, -1, 0, 0, -1, 0, + 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, + -1, 0, 0, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, -1, -1, + 0, -1, -1, 0, -1, -1, 0, 0, -1, -1, -1, -1, 0, -1, -1, 0, + 0, -1, 0, 0, 0, -1, -1, 0, -1, -1, -1, 0, 0, -1, -1, -1, + -1, -1, 0, -1, 0, 0, -1, -1, 0, 0, -1, 0, 0, -1, -1, -1, + 0, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, 0, -1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + 0, 0, 0, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 0, -4, 11, 6, 16, 10, -16, -48, + -44, 2, 67, 42, -17, -51, 15, 71, 12, -22, -14, -44, -35, 11, 17, -18, + 2, -15, 19, 12, -1, -44, -15, 50, 45, -25, -61, 17, 10, -10, 31, 18, + -72, -27, 57, 26, -13, -17, -2, 6, -1, -23, -54, 17, 39, 8, 30, 28, + -6, -71, -5, 33, 27, -5, 17, 10, -23, -6, 12, -26, -6, -7, -9, -14, + 11, 37, 41, 8, -33, -14, 8, -31, -38, 13, 9, 15, 35, 33, 11, 17, + -41, -48, -33, 29, 25, 16, -9, -9, -17, -19, -29, 43, 64, -2, -55, -42, + -1, -21, -4, 29, 34, -25, -67, -29, 1, 51, 49, 25, -6, -15, -48, -76, + -3, 60, 78, 33, 19, 13, -38, -35, -35, -2, 62, 19, -4, -12, -4, -4, + -32, -30, 8, 68, -43, -66, -28, 55, 51, 20, -28, -29, -19, 20, -2, 8, + 21, -15, -43, 24, 22, -7, -2, 35, 15, -2, -24, -12, 3, 31, 13, -15, + -20, -17, -17, 26, -26, 24, -3, 7, 21, 26, -3, -17, -26, -50, -26, 33, + 58, 49, -22, -67, -17, 24, 7, -57, 5, 42, -11, -3, 32, -3, 7, 13, + -11, -9, 27, 17, 1, -5, -9, -18, -19, -3, -23, -5, 7, -8, 9, 13, + 12, -5, 7, -37, 22, 26, 21, 24, -20, -35, 23, 24, -35, -15, 46, -38, + -48, -14, -4, 0, -22, 3, 43, 38, -1, -14, -8, -5, -14, 1, 21, 23, + 29, -19, -47, -42, -49, -10, 66, 77, 48, -29, -32, 1, -11, 8, 17, -17, + 3, 43, 33, -22, -19, -41, 29, 22, -42, 9, 63, 28, -23, -59, -65, 7, + 53, -22, -10, -27, -30, 36, 48, -4, -6, -22, -16, 10, 14, -7, 22, 50, + -4, -25, -41, -55, -62, 23, 68, -16, -31, 49, 57, 21, -38, 14, 12, -43, + -49, -16, 28, 7, -12, -50, -17, 49, 65, 18, 1, -8, 28, 2, -27, -13, + 12, -11, -52, 4, 31, -32, -39, 15, 8, -19, 6, 25, -1, -23, 13, 34, + 59, 36, -16, -5, -7, -28, -30, 1, -14, -42, 10, 43, 26, -25, -37, -61, + 1, 63, 62, 1, -36, -24, 38, -7, -26, 27, 10, 4, 2, -19, -22, -27, + -24, 0, 33, -8, -57, -12, 62, 77, 51, -10, -42, -27, -28, -31, -3, 5, + 21, 10, 15, -27, -18, -18, -10, 3, 17, 19, 18, -16, -20, 25, -3, -19, + -5, 32, 17, -3, -32, -8, 2, -11, -24, -17, -11, 3, 42, 15, -12, -2, + 26, 9, -4, -30, -3, 16, 7, 13, 34, 40, 114, 11, -104, -71, 7, -14, + -34, -26, 35, 45, 47, 7, -7, -16, 11, -6, -29, -32, 1, 24, 32, 10, + 29, -10, -74, -80, -20, 18, 9, 18, 61, 38, -27, -44, 13, 16, -26, 20, + 69, 14, -14, -46, -7, -6, -35, 0, 9, 5, 58, 71, -36, -78, -15, 43, + 34, -61, -101, -27, 45, 26, -10, 23, 69, 69, 5, -72, -62, 19, 16, -37, + -60, 37, 60, 10, -49, -10, -2, -1, 43, 44, 10, -50, -5, 19, 8, -43, + -58, -17, 32, 28, 4, -1, -18, -10, 13, 8, 1, 1, 22, -3, -4, 9, + -8, -9, 17, 3, -15, -8, 14, 11, -14, -11, -5, 13, -24, -34, -1, -16, + -4, 32, 35, -32, 9, 22, 12, -27, -16, 14, 15, 0, -2, -12, -31, -24, + 14, 48, 10, -14, -7, -22, 4, -8, -14, 19, 21, -21, -25, -12, 19, 24, + 19, 27, -3, -15, -16, 10, 21, -14, 3, 8, 3, -11, -33, -16, 7, 5, + -8, 2, -3, 12, 5, -34, -19, -6, 26, 19, 0, -4, -12, 5, 12, 20, + 16, 19, 18, -13, -42, -26, -1, 0, -18, -16, 10, 27, 23, -5, -7, 9, + -8, 7, 22, 10, -28, -51, -26, 13, 44, 17, 16, 25, 14, -32, -45, -36, + -40, -3, 22, 41, 34, -12, -35, -31, 18, 3, 31, 28, 4, -21, 2, -14, + -24, -23, 19, -6, -7, -10, -1, -13, -13, 21, 52, 28, 7, 1, -25, -36, + 2, 34, 10, -37, -31, -13, 19, 11, -4, -20, 15, -5, -18, 40, -13, 15, + -36, 14, 18, 17, -21, 6, -39, 21, 7, -26, 8, -33, 24, 30, 32, -11, + -26, -47, -39, 62, 10, 11, 5, -17, -21, 10, 0, 18, 15, -22, 7, 13, + 14, -8, -9, 30, 33, -34, -41, -32, 37, 24, -19, -15, 1, 2, 10, 10, + -27, -46, -14, -9, 9, 47, 1, -22, -18, 5, 37, 29, -3, -19, -19, -18, + 8, 17, 1, -11, -6, -20, 27, 37, -2, -28, -34, -3, 22, 54, 34, -31, + -43, -28, -30, -33, 26, 49, 45, 43, -15, -58, -13, -2, -27, -7, 41, 11, + 19, -50, -74, -28, 31, 75, 39, -45, -7, 99, 44, -83, -47, 45, -1, -30, + 23, 29, -55, -30, 31, 28, -19, 2, -44, -46, -49, 30, 22, 58, 31, -50, + -20, 9, -38, -53, 49, 37, -9, 13, -25, -18, 18, -27, -7, 17, 3, 24, + 57, 26, -51, -52, -54, -43, 53, 85, 31, -36, -44, 7, 13, 19, -23, -33, + 36, 47, -38, -11, 37, -19, -6, 18, 17, 2, 31, 54, -29, -72, -80, -1, + 27, 52, 10, -29, -40, -48, -72, 24, 108, 66, -44, -76, -32, -24, 21, 69, + 54, 24, -2, -8, -28, -44, -50, 34, 95, 45, -40, -72, -32, 6, 28, -1, + 18, -7, 27, 1, -14, 21, -8, -51, -62, -24, 64, 56, 12, 19, -36, -22, + 10, 20, -10, -1, -5, -51, 36, 72, -42, -51, 70, 45, -48, -27, 54, 19, + -46, 8, 0, -46, 10, 37, 35, -21, -32, -22, -44, -82, -33, 59, 105, 48, + -32, -36, -31, 18, 60, -12, -49, 10, 89, 28, 12, 8, -45, -21, -6, -16, + -32, -17, -18, 3, 29, -3, 0, -20, -51, -31, 24, 52, 1, -17, -20, 1, + 35, 15, 5, 35, 27, 18, -19, 8, -71, -74, -8, 88, 57, -45, -37, 17, + 51, -1, -13, -4, 3, -13, -24, -7, 30, -7, -25, -1, 16, -8, -43, -70, + 11, 85, 77, 12, -62, -57, 35, 53, -33, -96, 8, 82, 21, -38, 25, 39, + -1, -27, -14, 18, -16, -45, -24, 42, 7, -9, 22, 32, -39, -5, -8, -49, + -17, 60, 88, 21, -93, -20, 82, 31, -26, -63, -17, 52, -28, -25, 13, -2, + -32, -46, 55, 56, -37, 6, -57, -33, 65, 63, 5, -25, -31, 69, 86, -32, + -34, -56, -23, -47, 14, 44, -23, 19, 6, 60, -27, -69, -37, 20, -14, -5, + 50, 44, 15, 13, -23, -60, -46, 23, 40, -5, -25, 6, 46, -4, -10, -27, + -12, 28, 45, 10, -13, -33, -19, -39, 42, 32, -23, -25, 24, -17, 13, 25, + 13, -32, 13, 48, 4, -93, -5, 40, -7, 37, -39, -37, 41, 1, -13, -33, + 43, -53, 106, 8, -57, -93, 55, 40, 56, -24, -4, -19, 7, -23, -65, -18, + 34, -30, 7, 66, 92, 3, -43, -37, -23, 12, -7, -17, 14, -15, -9, -18, + 18, 51, -1, -57, -17, 23, 19, 15, -40, -1, 0, -8, 39, -13, -43, 72, + 57, -1, -54, -17, 32, -19, 11, 0, 36, 25, -23, -86, 21, -3, 14, -17, + 76, 37, 23, 2, -23, -54, -42, -80, 61, 60, 63, -12, -57, -44, 15, 35, + 26, 11, -44, -22, 8, 33, -24, -17, 21, 38, -25, -39, 16, 43, -36, -28, + 54, 10, -52, -18, -34, -14, 76, 60, 24, -32, -19, 16, -13, -68, -5, 30, + -13, -23, -14, 61, 24, 35, 39, 4, -50, -58, -39, 0, 43, 43, 21, 24, + -20, -46, -36, 38, 8, -67, -8, 61, 38, 10, -12, 5, -4, -16, -47, -5, + -18, -20, 37, 41, 24, 4, 7, -19, 11, -52, 0, 17, 20, -30, -33, -16, + 60, 34, -15, -46, -77, 14, 29, 26, 21, 25, 8, 7, 36, 23, -39, -16, + 21, 11, -23, 11, -4, -6, -35, 13, -8, -49, -17, 44, 19, -25, -17, 9, + -5, -5, -1, -31, 11, 15, 17, -8, -31, -51, 12, 54, 85, 32, 4, -58, + -35, -31, 0, 10, 21, -20, -20, -29, 15, 26, -7, 8, 4, 0, 30, 2, + -26, 2, 19, 15, -18, -13, -20, -19, 47, 33, -6, -51, -30, -12, 12, 30, + 34, 31, 4, -45, -81, -7, -22, 1, 73, 98, 24, -67, -13, 19, -32, -86, + 6, 94, 4, -47, 21, -11, -50, 22, -3, -2, 50, 20, -37, -59, 35, 28, + -16, -36, -30, -11, 4, 69, 98, -65, -84, 73, 27, -90, -17, 84, 10, -51, + -14, 40, -24, -11, 16, -34, -26, 38, -43, -34, 58, 85, -33, -51, 17, 7, + 4, 52, 25, -35, 0, 44, -21, -47, 40, 44, -69, -65, 37, 35, -21, 4, + 32, -60, -75, 21, 64, 60, -6, -11, 6, 2, -41, -34, 19, 31, 9, 7, + -1, 11, 6, -11, -26, -23, 16, 35, -39, -68, 6, 56, -3, -42, 29, 28, + 3, 28, 14, -37, -16, 11, -8, -18, 15, -1, -8, 43, -20, -67, -12, 34, + 7, -12, -9, 5, -4, 7, -12, 27, -3, -68, 26, 96, 30, -33, -28, -25, + 19, 27, -33, -48, -3, 37, -1, -35, -11, 5, 42, 36, 6, -48, -38, 26, + 54, -23, -41, 52, 44, -32, -22, 28, -23, -32, 12, 41, -16, -6, -6, -17, + -18, -14, -12, -5, 18, 52, 45, -10, -16, 29, 11, -36, -26, 7, 36, 12, + -57, -48, 48, 70, 16, 21, -13, -46, -33, -62, -63, -21, 94, 94, 20, -110, + -47, 41, 67, -16, -57, -40, 85, 71, 7, -39, 15, -29, -50, -41, 18, -40, + -42, 38, 69, 21, -8, -58, -19, 23, 24, -20, -10, 11, 41, 7, -6, -30, + -23, 2, 16, 57, 38, -11, -50, 36, -16, -51, -51, 81, 24, -68, -84, 39, + 112, 62, -79, -104, 24, 102, 15, -38, 20, 22, -49, -91, 15, 51, 30, -1, + -15, -30, -12, 17, 42, -17, -48, 0, 49, 35, 2, -19, -16, -30, 9, 17, + -12, -4, -15, 5, 34, -1, -56, -64, 7, 48, 54, -16, -51, 20, 62, -17, + -27, -9, -10, -29, -1, 35, 44, -20, -23, -2, -12, -4, 31, 24, -24, -14, + 2, -28, -27, 49, 61, -54, -61, 6, 23, -20, 2, 41, 26, 2, 15, -5, + 6, -16, -36, -16, 2, -54, -53, -18, 62, 64, 10, -3, 91, 39, -54, -103, + -5, 16, -31, -28, 75, 105, -32, -114, -52, 68, 32, -52, -19, 25, 54, 61, + 14, -40, 12, 1, -56, -31, 74, 40, -73, -66, 0, 49, 36, 24, -20, 0, + 13, -40, -99, -11, 55, 31, -33, 39, 24, 3, -18, 7, 10, 4, -29, 17, + 19, 27, -30, -41, 9, 33, -24, -25, 30, 28, -34, -57, 8, -7, -46, 5, + 48, -22, -6, 57, 58, -31, -72, -2, 72, 44, -53, -42, 41, 1, -54, 30, + 54, -6, -79, -14, 33, -6, -22, 14, 10, -5, -8, 13, 23, 21, -47, -74, + 22, 24, -10, -7, 39, 2, 12, -7, -2, 4, 33, -20, -33, 18, 22, -88, + -71, 26, 81, 14, -37, 3, -24, 6, -8, 11, 40, 18, -7, -17, 20, -8, + -15, -41, -11, 27, 52, -27, -46, 33, 21, 46, -30, -13, 26, -91, -106, -47, + 54, 109, 67, -87, -90, 38, 92, 31, -10, -69, -73, -27, -6, 24, -6, 20, + 30, 45, 33, -13, -25, 10, 57, -16, -32, 0, -14, -55, -20, 4, 7, -4, + 3, 18, -11, 34, 11, -45, -45, -125, -38, -2, 19, 72, 82, 99, 98, 35, + -51, -81, -53, 3, -39, 23, -4, -58, -63, -24, 40, 84, 48, -7, -18, -2, + -8, -20, -10, 3, 21, 17, -39, -66, -20, -2, 37, 30, 39, 34, -5, -41, + -26, 33, 40, 18, -2, 11, 13, -20, -60, -21, 33, -25, -35, 30, 65, 22, + 13, -15, 2, 16, 11, -68, -18, 74, 10, -74, -34, -39, -17, 8, 59, 39, + -22, -38, -8, 9, 30, 23, 11, -3, -12, 10, -1, 59, 9, -28, -72, -27, + 32, 68, -11, -3, 27, 4, -33, -39, 7, -1, -5, -7, 26, -14, -26, -40, + -12, 5, 5, 1, -12, 64, 63, -41, -56, 10, 26, 40, -26, -44, -42, 25, + -6, 3, -1, 10, 9, -1, 9, 1, -28, 10, 24, 26, -33, -36, 46, 20, + -43, -52, -35, 22, 53, 30, -6, 18, -16, -49, -36, 45, 10, 21, 7, 9, + -33, -50, 21, 73, 33, -42, -46, 42, -12, -18, 5, -50, -25, 68, 55, -31, + -79, -7, 77, 25, -6, 29, 78, 24, -87, -41, -30, -41, -23, 75, 35, -32, + -65, -7, -13, 3, 41, 34, -24, -33, 25, 14, -52, -28, 19, 76, 45, -45, + -47, -5, 24, 9, -14, -41, -5, 49, 22, 10, -31, -35, -1, -6, 3, 10, + -1, -12, -20, -51, 9, 79, 53, -36, -38, -13, -14, -15, 50, 50, -36, -33, + 0, 5, 22, 23, 24, -51, -81, -27, 56, 42, -10, -16, 0, 0, -5, 16, + 12, -19, 11, 10, -15, -1, -32, -17, 1, 11, 62, -16, -21, 9, 21, -29, + -50, 16, 82, 17, -35, -4, 11, 3, 8, 8, -9, -13, 10, -39, -63, -19, + 54, 58, -16, -25, 18, 38, -8, -50, -54, -17, 18, 47, 17, -33, -45, 0, + 52, 57, -5, -34, -17, 32, 10, -28, -10, -21, -3, -9, -20, 20, 47, 22, + 5, -4, -15, -37, -22, -28, 9, 37, -18, -13, 3, 15, -33, -47, 20, 73, + 0, -36, 33, 60, -11, -77, -13, 42, 13, -20, 9, 47, 22, -27, 29, 6, + -71, -78, -20, 21, 4, 27, 23, 19, 31, 45, -29, -54, -10, 37, -78, -46, + -14, 67, 108, 57, 12, -62, -108, -15, 116, 56, -58, -110, -33, 33, 30, -39, + -26, 11, 29, 22, 8, 52, 76, 31, 0, -31, -50, -10, 59, 54, -13, -84, + -65, -60, 0, 35, 105, 61, -30, -117, -62, 35, 88, 57, 48, -38, -85, 41, + 12, -21, -6, 7, 15, 73, -30, -72, -37, 25, 0, -5, 65, 76, -90, -78, + 24, 47, 2, -14, 40, 83, 0, -32, -46, -62, -26, 50, 37, -4, -44, -40, + 55, 31, -38, -13, -17, -30, -4, 7, 68, 39, 1, -23, -38, -30, 6, -35, + 14, 52, -9, -62, -47, 45, 44, 11, -17, -9, 6, 16, 34, -3, -32, -21, + -33, -3, 21, 26, -39, 11, 65, 33, 19, -1, -49, -85, -97, 66, 58, -93, + -15, 15, 5, 81, 76, 29, -2, -52, -51, -30, 65, 38, -45, -14, 1, 28, + 22, 43, 19, -59, -109, -29, 29, -14, -22, -41, 0, 54, 76, 16, 8, 23, + 15, -47, -39, -8, 5, 36, -6, -3, -4, 13, 13, 21, -47, -53, -6, -9, + -27, -44, 8, 86, 64, 12, -5, -32, -10, -20, -27, -23, 8, 30, 1, 16, + 42, -35, -8, 4, -39, -11, -62, -29, 108, 87, -20, -104, -18, -55, 8, 47, + -16, 29, 38, 4, -44, -39, -20, 38, -13, 23, 82, 30, -67, -93, 26, 79, + 20, -79, -74, -23, 33, 59, 80, 39, -42, -100, 0, 19, 38, 9, -55, 9, + -15, 22, 68, -17, -55, -23, 1, 87, 19, -56, -60, 32, 37, 38, -67, -33, + -1, 31, 24, 15, -30, -5, -36, -29, -27, 8, 27, -9, 12, 29, 38, 33, + 0, -39, -18, 6, 19, 18, 8, 1, -33, 9, -1, 2, -29, -66, 0, 41, + 6, -50, -13, 9, 73, -28, -47, -21, 30, 68, 31, 32, 29, -46, -14, 13, + -44, -75, -3, 62, 55, 9, -49, -1, 54, 19, -6, 7, 16, 38, 13, -26, + -55, -76, -23, 16, 21, -33, -22, 16, 61, 25, -14, -35, 12, 23, -7, -17, + -32, -10, -16, -1, 7, 18, -1, 19, -2, -1, 21, -14, 1, -44, -44, -23, + -29, -1, 28, -28, 47, 64, 12, -4, -15, -37, -7, 24, 50, 6, -15, -26, + -5, 20, 12, -25, -21, -2, -18, -23, 9, 16, 24, 36, -30, -35, -12, 32, + 19, -13, 19, -6, 2, -2, -22, -11, 14, 50, 10, -21, -55, -14, 23, 6, + 6, -6, -26, -25, -8, 25, 14, 24, 14, -13, 18, 11, 23, -34, -49, -45, + 6, 39, 37, 3, 0, -29, 8, 26, -6, -7, -21, 2, -11, 6, 16, -1, + -17, 6, 32, -4, -54, -9, 22, -14, 6, 27, -1, -2, 34, 33, 8, 1, + -8, -14, -32, 23, -22, -23, -29, -12, 5, 25, 22, -4, 14, 5, 24, -39, + -29, 17, -21, -80, -60, -9, 78, 99, 81, -41, -53, 22, 11, -69, -22, -2, + 70, 80, 18, -56, -54, -79, -27, 56, 46, 28, -1, 12, -37, -76, 23, 64, + -4, -5, 4, 0, -2, -5, 10, -4, -9, 5, 3, 3, -2, 6, -2, -1, + 0, 2, 0, 1, -2, 2, -3, -2, 0, 1, -1, 0, 0, -1, -1, -1, + 0, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, -5, -6, -5, -5, + -3, 0, -1, -3, -1, 7, 16, 20, 8, -8, -24, -35, -39, -36, -35, -42, + -47, -35, -14, 0, 8, 17, 28, 45, 60, 65, 64, 66, 67, 60, 50, 39, + 26, 14, 5, -14, -40, -54, -56, -56, -55, -47, -36, -20, 1, 13, 15, 16, + 12, 2, -10, -20, -33, -43, -42, -38, -43, -40, -28, -17, -7, 6, 21, 34, + 48, 60, 63, 64, 66, 61, 54, 51, 41, 23, 10, 1, -18, -37, -46, -54, + -63, -60, -46, -30, -13, 5, 15, 16, 17, 11, -2, -11, -21, -34, -44, -45, + -43, -42, -33, -21, -17, -10, 5, 23, 39, 54, 62, 61, 62, 63, 59, 53, + 47, 38, 23, 10, -5, -23, -36, -42, -51, -61, -61, -48, -26, -2, 14, 16, + 13, 13, 9, -1, -14, -27, -36, -42, -44, -48, -44, -31, -17, -10, -8, 1, + 21, 47, 65, 67, 58, 54, 58, 61, 54, 41, 31, 23, 11, -9, -30, -41, + -44, -45, -54, -61, -52, -21, 11, 25, 19, 8, 4, 7, 2, -15, -33, -39, + -39, -44, -51, -48, -34, -12, -2, -4, -2, 19, 54, 74, 72, 58, 47, 51, + 59, 54, 40, 26, 20, 7, -16, -37, -46, -44, -42, -51, -58, -47, -15, 19, + 31, 25, 9, -1, -1, -4, -15, -30, -37, -41, -51, -55, -48, -28, -11, -4, + -2, 6, 28, 58, 73, 74, 63, 50, 45, 46, 49, 42, 31, 19, -6, -30, + -43, -44, -42, -51, -54, -49, -33, -3, 18, 30, 31, 17, 2, -13, -15, -15, + -25, -31, -45, -62, -60, -45, -24, -16, -10, 6, 20, 40, 58, 68, 74, 69, + 55, 41, 37, 44, 43, 34, 15, -17, -41, -48, -46, -51, -59, -51, -34, -16, + 3, 17, 29, 33, 23, 2, -15, -18, -18, -22, -31, -50, -64, -61, -42, -30, + -24, -8, 13, 35, 50, 57, 65, 70, 70, 58, 42, 40, 41, 40, 32, 6, + -23, -45, -53, -55, -64, -60, -45, -24, -1, 10, 19, 27, 28, 23, 4, -9, + -17, -22, -23, -36, -53, -61, -60, -47, -36, -22, -3, 19, 44, 56, 60, 65, + 65, 65, 60, 52, 45, 39, 37, 23, -2, -26, -49, -63, -66, -63, -55, -42, + -16, 3, 14, 25, 25, 22, 19, 11, -2, -17, -20, -29, -44, -50, -58, -64, + -53, -32, -13, 0, 25, 45, 53, 65, 68, 61, 60, 63, 60, 47, 42, 33, + 7, -10, -26, -56, -73, -68, -57, -53, -37, -12, -1, 14, 32, 26, 16, 17, + 16, 1, -12, -19, -38, -52, -47, -55, -65, -50, -23, -9, 4, 27, 40, 48, + 68, 72, 59, 58, 67, 64, 52, 42, 21, -5, -16, -31, -60, -73, -62, -54, + -49, -34, -17, -4, 17, 32, 24, 13, 18, 20, 6, -11, -29, -46, -48, -46, + -54, -59, -41, -17, -5, 6, 20, 35, 54, 71, 68, 55, 60, 74, 71, 53, + 27, 5, -6, -16, -35, -62, -70, -57, -49, -45, -40, -25, 4, 25, 29, 15, + 7, 23, 27, 10, -20, -46, -47, -41, -39, -47, -55, -34, -11, -1, 4, 11, + 38, 67, 72, 62, 48, 61, 83, 76, 49, 9, -9, -7, -15, -31, -59, -70, + -55, -48, -46, -43, -21, 16, 29, 22, 6, 1, 25, 32, 10, -28, -57, -47, + -34, -30, -38, -49, -33, -12, -4, 3, 17, 50, 72, 68, 55, 44, 61, 86, + 77, 41, -2, -16, -10, -13, -28, -56, -69, -58, -52, -47, -35, -7, 22, 25, + 13, -4, -2, 25, 33, 7, -35, -58, -46, -29, -22, -32, -44, -34, -16, -5, + 8, 30, 59, 72, 65, 46, 39, 62, 87, 76, 33, -8, -20, -13, -10, -28, + -57, -70, -62, -51, -42, -24, 3, 23, 23, 4, -15, -4, 25, 34, 3, -38, + -55, -45, -23, -17, -32, -43, -34, -15, -1, 14, 41, 64, 73, 59, 35, 35, + 64, 89, 73, 26, -11, -23, -14, -11, -33, -60, -69, -59, -48, -39, -14, 11, + 25, 17, -11, -24, -3, 30, 35, -3, -40, -54, -41, -18, -19, -36, -41, -28, + -10, 0, 21, 51, 70, 71, 47, 24, 36, 72, 93, 65, 17, -14, -22, -13, + -17, -43, -62, -63, -52, -48, -36, -5, 19, 26, 5, -26, -27, 5, 40, 31, + -12, -42, -50, -34, -20, -28, -37, -33, -17, -8, -1, 29, 61, 75, 64, 31, + 19, 44, 85, 93, 51, 9, -15, -18, -16, -30, -50, -57, -52, -48, -52, -32, + 3, 25, 20, -10, -34, -21, 19, 42, 20, -17, -40, -43, -35, -30, -32, -32, + -21, -12, -12, 3, 37, 67, 72, 50, 25, 24, 57, 92, 81, 42, 6, -12, + -18, -25, -39, -53, -52, -44, -49, -51, -28, 6, 25, 13, -17, -32, -11, 29, + 39, 8, -24, -38, -37, -33, -36, -39, -30, -10, -3, -9, 3, 38, 68, 71, + 46, 23, 32, 68, 92, 71, 31, 5, -7, -16, -31, -50, -55, -45, -37, -49, + -53, -27, 8, 23, 8, -20, -24, 3, 34, 28, -6, -28, -32, -30, -35, -46, + -43, -23, 0, 0, -10, 5, 41, 67, 65, 42, 30, 47, 77, 83, 52, 23, + 10, 2, -16, -43, -60, -55, -38, -36, -53, -53, -25, 8, 19, 3, -14, -8, + 17, 29, 9, -17, -24, -22, -26, -43, -53, -42, -14, 4, -3, -9, 10, 44, + 63, 58, 43, 43, 63, 77, 64, 38, 24, 20, 7, -23, -52, -62, -49, -38, + -45, -57, -49, -19, 6, 11, 2, -1, 12, 22, 13, -7, -18, -15, -17, -32, + -50, -52, -32, -11, -4, -8, -3, 21, 44, 55, 53, 52, 63, 70, 64, 49, + 35, 34, 24, 0, -29, -53, -54, -50, -51, -56, -57, -37, -17, -2, 7, 9, + 20, 21, 12, 1, -13, -11, -13, -24, -36, -49, -40, -30, -22, -12, -9, 10, + 25, 38, 51, 57, 70, 71, 62, 57, 44, 42, 34, 15, -4, -30, -42, -53, + -65, -61, -61, -49, -35, -22, -2, 10, 25, 27, 15, 11, -1, -8, -14, -22, + -27, -37, -37, -37, -40, -26, -14, -2, 10, 24, 42, 54, 68, 73, 65, 65, + 60, 49, 36, 27, 15, -7, -25, -43, -63, -69, -65, -61, -54, -36, -13, 3, + 18, 26, 23, 20, 16, 1, -16, -21, -20, -31, -37, -38, -40, -38, -25, -15, + -7, 11, 34, 48, 56, 66, 71, 72, 73, 61, 43, 34, 29, 11, -14, -31, + -46, -63, -69, -72, -69, -53, -28, -7, 3, 16, 27, 30, 28, 15, -3, -14, + -19, -25, -39, -42, -37, -38, -35, -30, -19, -2, 18, 39, 47, 56, 69, 75, + 78, 71, 60, 49, 35, 22, -1, -20, -32, -50, -65, -76, -75, -63, -49, -27, + -9, 6, 22, 28, 31, 27, 16, 6, -13, -26, -36, -43, -41, -42, -42, -36, + -27, -10, 2, 18, 38, 52, 64, 70, 73, 79, 76, 70, 50, 27, 11, -5, + -21, -41, -62, -69, -72, -68, -61, -50, -26, -4, 13, 21, 23, 32, 35, 27, + 6, -21, -33, -37, -42, -48, -53, -45, -31, -19, -8, 3, 23, 45, 59, 65, + 65, 73, 88, 88, 69, 40, 19, 10, -6, -30, -54, -69, -69, -68, -67, -59, + -43, -18, 2, 10, 15, 22, 39, 46, 27, -3, -28, -34, -37, -48, -56, -60, + -48, -29, -16, -1, 14, 35, 52, 58, 60, 64, 80, 96, 88, 64, 34, 16, + 6, -11, -36, -62, -77, -75, -68, -58, -47, -33, -14, -1, 7, 15, 28, 43, + 44, 24, -6, -30, -38, -40, -49, -63, -68, -56, -30, -5, 15, 27, 40, 51, + 59, 63, 72, 84, 91, 83, 60, 32, 12, 1, -14, -45, -73, -84, -78, -62, + -46, -36, -28, -17, 0, 11, 20, 31, 38, 35, 20, -6, -28, -40, -46, -58, + -72, -71, -52, -26, 4, 26, 37, 45, 54, 64, 69, 74, 81, 80, 73, 59, + 35, 13, -5, -28, -54, -75, -79, -74, -63, -43, -30, -21, -11, 0, 14, 23, + 29, 33, 23, 14, -2, -25, -41, -58, -69, -71, -64, -43, -24, 3, 33, 47, + 56, 60, 64, 73, 74, 75, 73, 62, 56, 38, 13, -12, -42, -57, -69, -77, + -71, -63, -44, -25, -15, -3, 2, 13, 26, 23, 24, 19, 8, -2, -24, -44, + -64, -74, -64, -60, -45, -16, 9, 34, 53, 63, 68, 66, 75, 73, 63, 66, + 62, 49, 34, 11, -17, -43, -54, -66, -82, -72, -52, -43, -28, -10, 0, 4, + 18, 27, 16, 13, 20, 8, -11, -26, -47, -66, -63, -59, -63, -47, -7, 20, + 34, 56, 69, 65, 73, 81, 67, 54, 61, 63, 44, 25, 6, -23, -37, -44, + -69, -85, -69, -48, -39, -26, -7, -4, 5, 27, 25, 9, 10, 15, 5, -17, + -34, -52, -62, -54, -54, -60, -40, -5, 21, 41, 59, 67, 66, 78, 81, 64, + 53, 58, 56, 39, 18, -3, -24, -34, -45, -64, -76, -67, -51, -37, -21, -8, + -3, 11, 22, 20, 11, 9, 11, -4, -23, -38, -56, -57, -53, -50, -42, -31, + -5, 21, 41, 63, 67, 72, 77, 69, 67, 58, 56, 49, 28, 16, -8, -28, + -35, -50, -53, -62, -65, -53, -44, -20, -2, 2, 14, 10, 14, 17, 7, 5, + -13, -27, -37, -60, -58, -55, -42, -22, -18, -2, 13, 36, 69, 73, 76, 71, + 62, 70, 60, 53, 42, 23, 16, -13, -35, -45, -51, -40, -46, -58, -60, -52, + -17, 4, 8, 11, 5, 14, 15, 4, -4, -20, -23, -37, -62, -67, -59, -27, + -2, -3, -3, 3, 36, 70, 77, 75, 66, 67, 70, 57, 46, 32, 29, 19, + -17, -49, -62, -46, -25, -33, -54, -68, -51, -15, 4, 8, 6, 11, 18, 8, + -7, -19, -16, -12, -35, -68, -83, -56, -9, 13, 7, -7, 4, 40, 66, 73, + 69, 73, 80, 69, 46, 27, 31, 42, 24, -23, -68, -69, -36, -14, -25, -57, + -66, -43, -16, -3, -2, 11, 28, 23, -2, -31, -29, -4, -1, -34, -83, -89, + -45, 3, 22, 6, -3, 16, 41, 56, 55, 68, 93, 93, 65, 23, 12, 38, + 53, 27, -38, -80, -64, -29, -12, -31, -54, -49, -34, -22, -24, -11, 28, 47, + 25, -24, -51, -27, 5, 5, -43, -90, -79, -34, 6, 11, 4, 17, 31, 39, + 34, 38, 79, 114, 105, 50, 3, 12, 44, 56, 16, -49, -72, -54, -28, -29, + -44, -37, -27, -28, -41, -45, -5, 46, 61, 17, -44, -53, -20, 7, -6, -53, + -78, -62, -27, -7, -6, 14, 41, 45, 26, 11, 38, 93, 127, 101, 34, 1, + 20, 48, 42, -1, -41, -53, -45, -40, -51, -44, -18, -9, -34, -61, -47, 7, + 57, 58, 2, -46, -43, -14, -5, -27, -52, -58, -46, -31, -26, -12, 28, 59, + 45, 10, 6, 50, 104, 124, 87, 30, 11, 30, 40, 19, -9, -26, -35, -44, + -58, -62, -38, -4, -6, -46, -67, -37, 21, 56, 43, -4, -37, -30, -15, -25, + -40, -44, -38, -38, -43, -38, -9, 40, 64, 37, 5, 14, 65, 106, 107, 75, + 36, 26, 34, 24, 4, -8, -10, -24, -53, -70, -64, -30, 0, -16, -53, -61, + -22, 28, 43, 29, -2, -21, -20, -26, -39, -43, -34, -26, -43, -54, -40, 0, + 46, 56, 30, 12, 30, 75, 97, 90, 69, 47, 38, 29, 13, 2, 0, -1, + -27, -61, -71, -55, -25, -14, -32, -50, -41, -6, 22, 25, 17, 4, -8, -19, + -31, -38, -35, -28, -35, -53, -54, -29, 7, 31, 32, 23, 28, 51, 72, 78, + 72, 65, 55, 42, 30, 19, 15, 11, -8, -36, -58, -58, -42, -35, -35, -43, + -40, -18, 0, 12, 14, 11, 9, -4, -15, -25, -31, -28, -36, -49, -53, -45, + -18, 1, 12, 19, 23, 43, 58, 64, 68, 64, 64, 57, 46, 40, 28, 22, + 9, -17, -35, -48, -47, -44, -47, -45, -44, -31, -12, -2, 7, 10, 9, 7, + -2, -8, -19, -28, -32, -44, -51, -48, -37, -21, -9, 5, 16, 26, 43, 55, + 60, 64, 63, 61, 58, 55, 48, 34, 21, 6, -13, -27, -39, -49, -53, -50, + -46, -41, -32, -16, -3, 5, 11, 9, 6, 5, -4, -17, -32, -40, -42, -44, + -42, -40, -32, -12, 5, 17, 24, 35, 50, 58, 64, 64, 60, 65, 61, 50, + 34, 18, 10, -2, -18, -38, -58, -56, -49, -45, -41, -38, -22, -4, 8, 14, + 8, 11, 10, -5, -20, -38, -41, -36, -37, -40, -48, -37, -12, 4, 14, 19, + 27, 46, 59, 66, 63, 62, 70, 64, 50, 34, 22, 17, 8, -11, -38, -59, + -57, -50, -49, -47, -43, -28, -6, 10, 16, 10, 14, 8, 1, -5, -5, -4, + -5, 5, 2, 2, 1, -1, 0, 1, 0, 2, 0, 0, -2, -1, -1, 2, + 1, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + -1, 0, 1, 0, 0, 0, 1, 0, 1, 0, -3, -10, -11, -8, -13, -25, + -21, -10, 0, 2, 18, 41, 44, 42, 66, 62, 28, 10, 17, 17, -16, -10, + 25, 28, 29, 34, 47, 34, -7, 7, 25, -12, -43, -44, -40, -61, -85, -78, + -55, -42, -33, -10, 17, 31, 43, 59, 51, 25, 25, 40, 27, -1, 2, 25, + 30, 15, 12, 27, 26, 13, 16, 9, -24, -43, -37, -49, -83, -92, -62, -40, + -42, -36, 1, 33, 34, 45, 61, 46, 27, 32, 33, 10, -6, 15, 38, 26, + 4, 15, 35, 19, 7, 17, 3, -26, -41, -50, -67, -91, -82, -48, -40, -46, + -24, 18, 33, 32, 54, 62, 46, 30, 22, 20, 7, 4, 28, 33, 15, 10, + 22, 25, 9, 13, 18, -2, -29, -54, -65, -74, -86, -68, -49, -46, -32, -8, + 17, 29, 45, 65, 60, 43, 23, 13, 17, 12, 18, 28, 22, 19, 16, 13, + 14, 16, 24, 13, -13, -40, -66, -72, -75, -74, -64, -55, -36, -20, -9, 15, + 43, 63, 65, 51, 37, 17, 9, 19, 23, 21, 19, 24, 21, 3, 4, 24, + 31, 18, -2, -20, -49, -77, -74, -65, -71, -69, -47, -27, -27, -10, 38, 66, + 59, 52, 51, 34, 4, 11, 36, 26, 12, 22, 26, 2, -11, 25, 45, 18, + 0, -1, -23, -72, -83, -55, -65, -83, -61, -34, -37, -36, 23, 71, 55, 43, + 60, 55, 11, 1, 40, 37, 8, 16, 31, 6, -22, 14, 55, 27, -3, 8, + 2, -52, -83, -57, -56, -89, -79, -43, -43, -55, -4, 66, 61, 35, 56, 68, + 31, 4, 32, 46, 13, 7, 31, 16, -24, -4, 50, 42, 2, 7, 16, -25, + -67, -60, -54, -86, -95, -55, -44, -63, -32, 40, 62, 40, 47, 67, 48, 22, + 32, 42, 18, 4, 25, 25, -15, -16, 29, 44, 21, 11, 15, -5, -39, -49, + -59, -85, -96, -72, -52, -62, -50, 7, 45, 49, 50, 56, 56, 43, 42, 39, + 19, 9, 16, 21, 1, -16, 9, 32, 31, 24, 14, 5, -14, -34, -52, -81, + -94, -85, -71, -62, -55, -21, 21, 41, 53, 55, 55, 57, 51, 44, 26, 13, + 15, 11, 3, -3, 0, 19, 27, 29, 26, 11, 0, -16, -41, -70, -90, -88, + -85, -80, -57, -34, -3, 26, 42, 57, 57, 60, 64, 50, 33, 20, 17, 9, + -6, -1, 6, 10, 23, 26, 28, 22, 10, 1, -27, -60, -78, -87, -90, -94, + -74, -42, -20, 10, 34, 44, 57, 65, 71, 58, 35, 30, 23, 8, -5, -7, + 4, 7, 19, 33, 23, 19, 24, 17, -13, -53, -65, -75, -96, -98, -83, -61, + -40, -7, 32, 38, 38, 66, 83, 65, 36, 36, 37, 8, -7, 1, 0, -5, + 11, 39, 34, 10, 21, 36, 4, -45, -59, -59, -89, -106, -84, -67, -62, -32, + 21, 41, 30, 47, 85, 80, 41, 34, 45, 20, -8, 0, 9, -7, -6, 31, + 45, 21, 12, 32, 25, -27, -55, -52, -76, -104, -95, -70, -64, -57, -7, 33, + 34, 38, 67, 84, 57, 35, 46, 29, -1, -4, 7, 7, -8, 12, 41, 31, + 21, 24, 25, -5, -43, -45, -65, -98, -98, -82, -62, -58, -35, 13, 27, 38, + 59, 70, 67, 45, 49, 39, 2, -3, 2, 9, 9, 6, 30, 30, 24, 31, + 20, 3, -26, -37, -48, -91, -100, -88, -75, -53, -41, -9, 12, 23, 55, 65, + 61, 54, 51, 51, 14, -6, 1, 1, 15, 18, 26, 29, 16, 30, 28, 4, + -14, -29, -36, -71, -100, -93, -87, -64, -38, -16, 2, 6, 33, 61, 59, 56, + 54, 55, 32, 1, -3, -4, 5, 25, 36, 36, 17, 14, 25, 14, -4, -19, + -30, -53, -84, -94, -95, -82, -49, -16, 4, 2, 10, 37, 56, 61, 58, 54, + 42, 19, 3, -9, -8, 14, 41, 53, 32, 10, 7, 10, 10, -7, -25, -43, + -65, -81, -97, -99, -72, -29, 9, 11, 3, 10, 33, 61, 65, 55, 46, 30, + 19, 0, -17, -5, 29, 62, 57, 24, -1, -6, 10, 8, -16, -35, -54, -64, + -80, -105, -99, -57, -2, 26, 13, -2, 6, 42, 67, 60, 49, 36, 31, 22, + -10, -24, 1, 49, 77, 53, 9, -14, -4, 10, -4, -26, -47, -56, -58, -89, + -115, -93, -34, 23, 33, 6, -6, 16, 50, 62, 53, 39, 34, 40, 16, -24, + -26, 15, 71, 82, 38, -5, -13, -1, 3, -13, -39, -53, -48, -61, -103, -119, + -80, -6, 42, 27, -1, 2, 26, 51, 56, 43, 33, 43, 42, 4, -34, -23, + 37, 87, 70, 20, -6, -10, -3, -5, -27, -49, -48, -44, -72, -115, -118, -56, + 22, 43, 17, 3, 12, 33, 51, 45, 34, 38, 51, 38, -11, -42, -9, 59, + 86, 53, 13, -5, -5, -3, -19, -42, -50, -43, -45, -85, -127, -105, -28, 34, + 37, 15, 8, 23, 41, 42, 34, 33, 45, 55, 26, -27, -38, 12, 69, 77, + 40, 9, 1, 0, -13, -33, -48, -49, -39, -55, -102, -124, -83, -8, 37, 31, + 14, 19, 35, 39, 34, 30, 35, 51, 50, 9, -31, -25, 27, 72, 65, 30, + 12, 9, -2, -23, -42, -52, -46, -43, -71, -109, -112, -63, 7, 36, 25, 20, + 33, 42, 35, 29, 29, 40, 52, 35, -2, -28, -12, 40, 69, 51, 26, 18, + 13, -8, -33, -48, -50, -46, -57, -84, -107, -98, -43, 14, 29, 24, 30, 44, + 43, 30, 26, 34, 44, 40, 19, -8, -20, 4, 46, 59, 42, 29, 25, 10, + -18, -40, -46, -47, -57, -73, -91, -100, -78, -30, 13, 25, 30, 44, 48, 39, + 29, 31, 41, 35, 23, 9, -9, -5, 16, 43, 52, 40, 37, 25, 0, -23, + -41, -43, -54, -74, -82, -93, -86, -60, -26, 12, 26, 41, 53, 44, 40, 33, + 36, 38, 19, 12, 2, -3, 9, 18, 40, 48, 42, 41, 16, -6, -23, -41, + -45, -68, -84, -86, -90, -71, -52, -22, 15, 32, 52, 54, 45, 45, 36, 36, + 25, 6, 6, 0, 5, 15, 21, 41, 46, 46, 37, 10, -7, -24, -42, -57, + -81, -88, -88, -83, -62, -43, -14, 16, 41, 59, 55, 48, 48, 40, 27, 10, + 2, 2, 0, 8, 22, 30, 36, 45, 50, 32, 5, -9, -23, -48, -75, -86, + -86, -88, -81, -54, -26, -11, 16, 52, 65, 55, 50, 53, 39, 9, -2, 4, + 2, -4, 11, 36, 34, 27, 47, 51, 26, 0, -9, -23, -63, -91, -85, -81, + -89, -79, -38, -13, -11, 23, 62, 67, 55, 52, 56, 29, -8, -7, 7, 0, + -5, 19, 44, 30, 28, 49, 46, 21, -2, -10, -32, -79, -96, -83, -81, -87, + -67, -27, -11, 0, 36, 65, 67, 58, 54, 48, 14, -15, -7, 3, 1, 6, + 26, 35, 30, 38, 46, 37, 18, -2, -18, -48, -85, -96, -89, -81, -70, -52, + -30, -8, 20, 48, 63, 66, 59, 50, 33, 6, -14, -15, -2, 13, 20, 21, + 25, 36, 45, 42, 31, 12, -10, -31, -56, -84, -103, -96, -70, -50, -43, -31, + 0, 35, 58, 68, 65, 51, 37, 26, 8, -19, -25, 2, 27, 27, 17, 20, + 36, 45, 45, 29, 0, -27, -41, -55, -87, -111, -93, -57, -37, -33, -23, 5, + 41, 70, 77, 59, 36, 26, 24, 4, -24, -22, 7, 31, 33, 19, 14, 29, + 49, 50, 22, -16, -39, -48, -63, -92, -104, -86, -51, -25, -19, -16, 10, 53, + 82, 74, 47, 26, 19, 16, -1, -18, -16, 7, 35, 37, 18, 10, 31, 55, + 41, 4, -25, -45, -57, -73, -90, -95, -82, -42, -9, -8, -11, 20, 71, 84, + 57, 39, 27, 13, 2, -6, -9, -12, 8, 45, 41, 8, 5, 42, 56, 20, + -10, -24, -50, -73, -83, -83, -87, -76, -25, 10, -5, -9, 39, 84, 71, 44, + 38, 26, 2, -9, -2, -4, -11, 17, 52, 36, 0, 11, 50, 43, 3, -19, + -31, -57, -84, -84, -77, -82, -59, -9, 14, 1, 7, 55, 81, 61, 38, 29, + 20, -2, -10, -1, -4, 0, 26, 42, 30, 8, 20, 41, 28, -4, -31, -46, + -64, -84, -82, -79, -66, -37, -7, 15, 18, 30, 58, 68, 57, 33, 17, 9, + 0, -3, -7, 0, 15, 23, 31, 29, 23, 24, 22, 14, -12, -43, -63, -72, + -73, -83, -75, -47, -26, -2, 20, 37, 48, 50, 57, 52, 30, 6, -1, 11, + 0, -9, 7, 16, 24, 28, 32, 33, 15, 7, 2, -21, -55, -79, -66, -67, + -81, -63, -38, -12, 9, 29, 53, 48, 42, 51, 47, 22, -6, 5, 18, -4, + -7, 6, 22, 28, 26, 39, 28, 2, -2, -8, -35, -73, -76, -56, -67, -77, + -55, -20, 4, 16, 40, 54, 42, 41, 51, 37, 7, 0, 17, 13, -12, -9, + 20, 31, 25, 29, 33, 15, -5, -8, -22, -57, -74, -62, -57, -74, -71, -33, + 0, 11, 26, 44, 45, 41, 47, 45, 22, 3, 12, 19, 0, -15, 4, 30, + 32, 27, 26, 17, 3, -4, -14, -44, -69, -66, -56, -63, -74, -52, -11, 12, + 21, 29, 35, 41, 49, 51, 31, 9, 11, 19, 11, -8, -7, 20, 36, 34, + 22, 10, 6, 5, -4, -33, -64, -66, -58, -58, -67, -63, -29, 4, 20, 21, + 21, 35, 52, 57, 39, 12, 10, 18, 16, 3, -7, 8, 31, 39, 25, 5, + 3, 10, 5, -22, -58, -67, -58, -56, -60, -64, -45, -11, 15, 19, 12, 24, + 50, 62, 46, 17, 9, 18, 20, 12, 0, 2, 21, 37, 31, 7, 0, 11, + 14, -12, -51, -66, -58, -53, -54, -59, -54, -29, 3, 16, 9, 17, 44, 62, + 51, 22, 8, 17, 24, 21, 9, 1, 11, 30, 31, 14, 3, 11, 16, -4, + -43, -65, -58, -49, -50, -53, -55, -43, -16, 5, 10, 16, 38, 59, 54, 26, + 7, 18, 29, 24, 18, 8, 5, 16, 27, 23, 11, 14, 18, -1, -36, -63, + -56, -43, -48, -47, -49, -52, -36, -12, 8, 17, 35, 55, 50, 28, 9, 17, + 33, 25, 24, 20, 5, 4, 15, 27, 23, 20, 22, 0, -32, -58, -55, -40, + -47, -44, -39, -52, -54, -34, -2, 19, 35, 53, 46, 27, 12, 18, 34, 26, + 26, 33, 13, -6, 0, 22, 34, 32, 28, 3, -31, -53, -51, -39, -47, -45, + -30, -45, -66, -56, -19, 15, 38, 52, 43, 22, 13, 22, 35, 26, 26, 41, + 25, -7, -13, 10, 35, 46, 39, 10, -29, -50, -46, -37, -47, -46, -27, -35, + -65, -72, -42, 2, 38, 55, 43, 19, 11, 24, 36, 27, 26, 43, 37, 2, + -19, -6, 25, 53, 56, 20, -24, -46, -43, -36, -46, -48, -29, -28, -56, -77, + -64, -22, 31, 61, 45, 16, 10, 23, 35, 30, 26, 41, 42, 16, -14, -21, + 7, 51, 70, 36, -15, -38, -40, -35, -42, -49, -35, -29, -44, -71, -81, -49, + 14, 60, 50, 18, 10, 21, 34, 34, 26, 37, 43, 30, 0, -27, -13, 37, + 74, 54, 2, -29, -35, -32, -37, -49, -42, -32, -36, -57, -85, -73, -12, 46, + 57, 27, 9, 17, 32, 38, 28, 30, 41, 39, 18, -20, -27, 15, 62, 68, + 26, -17, -30, -28, -29, -45, -51, -40, -34, -45, -77, -86, -42, 18, 54, 43, + 14, 12, 29, 42, 34, 25, 33, 41, 30, -2, -24, -5, 36, 65, 50, 3, + -24, -24, -19, -33, -54, -52, -42, -45, -61, -75, -58, -15, 32, 48, 25, 10, + 24, 45, 45, 27, 26, 32, 28, 13, -4, -6, 14, 44, 55, 24, -11, -18, + -12, -20, -46, -57, -53, -54, -57, -63, -57, -33, 4, 35, 32, 16, 22, 40, + 49, 36, 26, 28, 23, 17, 8, 1, 10, 27, 43, 33, 5, -6, -8, -14, + -33, -53, -57, -61, -62, -61, -59, -38, -10, 15, 26, 20, 26, 40, 44, 41, + 30, 27, 25, 18, 12, 3, 9, 26, 33, 28, 13, 5, 5, -8, -25, -45, + -57, -60, -64, -66, -65, -49, -17, 6, 13, 16, 26, 43, 47, 39, 32, 27, + 27, 25, 13, 3, 6, 22, 35, 26, 13, 10, 12, 5, -17, -40, -54, -58, + -58, -68, -74, -61, -31, -1, 9, 10, 23, 40, 50, 45, 31, 24, 27, 31, + 20, 3, 2, 17, 32, 31, 16, 12, 15, 12, -4, -31, -51, -55, -54, -62, + -76, -73, -47, -17, 2, 8, 19, 37, 51, 50, 34, 24, 26, 31, 25, 9, + 4, 13, 26, 34, 25, 9, 13, 20, -2, -33, -44, -43, -58, -78, -77, -59, + -44, -33, -10, 17, 6, 12, -9, 32, 13, 4, -4, 6, -9, 27, 8, 2, + -1, -3, -2, 3, -4, -3, 2, 0, -2, 1, -2, 1, -4, 2, 1, 0, + -2, -1, -3, 2, 0, -1, -2, -2, -2, -1, -2, -2, -1, -2, -2, -2, + -2, -1, -2, -1, 0, -1, -2, -2, -2, -1, 0, -2, -2, -2, -2, -1, + -1, -2, -1, -2, -2, -2, -3, -1, -1, 0, 0, -1, -3, -2, 1, 3, + 0, 0, -2, -8, -21, -17, -2, 12, 20, 19, 6, -13, -28, -73, -67, -64, + -58, -39, -11, 19, 38, 60, 96, 80, 38, 12, 6, -20, -65, -83, -65, -61, + -56, -17, 22, 35, 49, 74, 94, 55, 16, 20, -5, -52, -89, -81, -53, -65, + -36, 21, 37, 48, 51, 85, 82, 25, 23, 9, -36, -80, -105, -58, -57, -54, + 7, 36, 54, 44, 58, 97, 48, 26, 16, -21, -61, -115, -83, -45, -57, -12, + 23, 57, 54, 36, 86, 77, 37, 21, -16, -40, -103, -110, -54, -46, -24, 6, + 43, 68, 36, 62, 86, 60, 30, -12, -34, -80, -119, -76, -44, -24, -5, 24, + 64, 51, 50, 76, 72, 48, 0, -34, -68, -106, -94, -56, -26, -7, 11, 45, + 59, 58, 66, 71, 60, 23, -27, -68, -93, -93, -72, -37, -8, 10, 25, 50, + 70, 68, 62, 62, 45, -10, -70, -88, -83, -79, -57, -15, 15, 13, 31, 73, + 80, 59, 53, 61, 15, -67, -89, -73, -75, -75, -33, 21, 11, 10, 66, 92, + 65, 42, 63, 42, -56, -92, -66, -66, -84, -57, 16, 19, -5, 50, 98, 76, + 39, 56, 60, -35, -95, -64, -53, -84, -79, 0, 28, -8, 29, 96, 89, 42, + 46, 69, -10, -90, -69, -41, -74, -95, -25, 28, -1, 13, 81, 101, 53, 37, + 69, 11, -77, -75, -38, -53, -103, -55, 22, 8, 6, 61, 104, 75, 29, 59, + 31, -61, -76, -43, -36, -91, -88, 6, 17, 1, 46, 96, 94, 34, 40, 48, + -40, -80, -47, -27, -69, -107, -27, 26, 4, 29, 87, 105, 51, 24, 46, -10, + -76, -58, -21, -49, -107, -62, 17, 16, 17, 70, 110, 67, 22, 38, 10, -60, + -71, -24, -28, -97, -85, -6, 25, 18, 50, 106, 84, 28, 31, 16, -38, -71, + -38, -17, -78, -94, -30, 15, 30, 41, 86, 92, 44, 31, 15, -25, -54, -53, + -26, -57, -88, -51, -2, 33, 45, 68, 88, 59, 35, 17, -15, -42, -55, -41, + -48, -73, -60, -19, 24, 50, 61, 74, 67, 46, 21, -8, -32, -48, -54, -53, + -57, -57, -34, 9, 50, 63, 59, 65, 58, 29, -1, -24, -38, -62, -67, -48, + -47, -40, -8, 43, 68, 48, 58, 66, 38, 6, -19, -26, -62, -85, -45, -35, + -39, -21, 28, 72, 41, 47, 74, 45, 15, -14, -17, -53, -102, -50, -24, -36, + -26, 10, 69, 42, 32, 81, 52, 21, -4, -15, -39, -109, -64, -12, -35, -26, + -1, 54, 47, 21, 79, 65, 20, 7, -12, -33, -100, -82, -8, -27, -32, -2, + 36, 47, 21, 66, 77, 25, 12, -2, -36, -88, -87, -18, -16, -36, -8, 27, + 36, 30, 56, 77, 39, 12, 6, -33, -84, -79, -30, -11, -29, -20, 19, 27, + 31, 58, 66, 50, 21, 5, -25, -81, -75, -32, -17, -17, -27, 2, 24, 28, + 61, 61, 48, 35, 4, -22, -71, -77, -31, -19, -12, -23, -18, 16, 29, 59, + 65, 45, 41, 10, -23, -59, -76, -37, -14, -11, -18, -29, -2, 29, 57, 68, + 51, 37, 16, -21, -55, -67, -44, -12, -5, -21, -29, -19, 19, 59, 68, 61, + 36, 14, -12, -55, -61, -44, -16, 3, -21, -29, -25, 0, 55, 72, 69, 43, + 8, -6, -49, -63, -39, -18, 5, -15, -31, -26, -18, 39, 78, 75, 53, 8, + -8, -40, -67, -37, -15, 2, -8, -30, -26, -29, 16, 79, 84, 59, 14, -11, + -33, -66, -42, -9, -2, -6, -23, -26, -33, -7, 66, 94, 67, 22, -9, -32, + -62, -48, -8, 0, -9, -16, -20, -35, -24, 46, 96, 78, 31, -2, -29, -59, + -51, -13, 1, -10, -13, -9, -31, -35, 23, 86, 88, 42, 5, -22, -57, -53, + -18, -3, -10, -13, 0, -19, -44, 2, 69, 90, 57, 12, -13, -50, -57, -21, + -9, -13, -13, 1, -3, -41, -17, 51, 82, 69, 23, -9, -37, -57, -25, -12, + -22, -15, 0, 10, -25, -32, 32, 69, 71, 37, -4, -25, -48, -30, -12, -32, + -23, -3, 14, -2, -33, 11, 56, 63, 49, 3, -18, -32, -31, -13, -37, -38, + -9, 11, 17, -16, -6, 41, 53, 51, 11, -17, -15, -23, -14, -35, -54, -22, + 4, 26, 10, -10, 26, 43, 46, 19, -19, -6, -5, -10, -30, -65, -42, -9, + 24, 35, 3, 12, 32, 37, 24, -20, -8, 14, 2, -23, -68, -62, -26, 10, + 50, 28, 11, 22, 27, 24, -19, -19, 24, 21, -8, -63, -78, -45, -11, 47, + 53, 23, 21, 19, 22, -17, -34, 21, 40, 15, -48, -89, -65, -34, 30, 68, + 44, 27, 16, 16, -11, -47, 3, 49, 39, -22, -89, -82, -55, 3, 68, 61, + 44, 21, 11, -6, -53, -21, 45, 56, 11, -74, -96, -72, -26, 52, 73, 60, + 39, 10, -3, -48, -44, 27, 61, 42, -43, -101, -88, -52, 27, 73, 70, 59, + 21, -1, -40, -60, 2, 52, 60, -4, -90, -100, -74, -2, 62, 72, 76, 42, + 5, -30, -66, -22, 34, 63, 33, -62, -104, -92, -31, 44, 68, 84, 66, 21, + -21, -64, -41, 13, 54, 55, -26, -94, -104, -57, 20, 56, 82, 84, 43, -6, + -57, -54, -10, 36, 60, 7, -70, -107, -78, -6, 40, 73, 92, 66, 12, -45, + -57, -27, 16, 52, 29, -41, -96, -90, -32, 20, 60, 91, 83, 34, -27, -52, + -37, -3, 34, 36, -15, -77, -91, -52, -1, 43, 83, 93, 53, -5, -42, -40, + -17, 14, 32, 1, -54, -81, -65, -21, 23, 71, 96, 67, 16, -25, -37, -24, + -5, 21, 6, -36, -64, -69, -37, 3, 54, 93, 73, 35, -6, -28, -25, -19, + 8, 4, -27, -46, -65, -46, -14, 34, 86, 73, 49, 15, -17, -19, -28, -4, + -3, -28, -32, -56, -48, -24, 15, 74, 67, 55, 36, -2, -10, -28, -14, -9, + -36, -25, -42, -50, -29, 1, 60, 59, 50, 55, 16, -3, -22, -20, -14, -46, + -29, -28, -48, -33, -5, 47, 50, 40, 64, 40, 4, -14, -17, -19, -53, -40, + -18, -40, -41, -6, 39, 39, 28, 61, 62, 17, -10, -7, -21, -59, -53, -20, + -28, -47, -11, 38, 29, 15, 52, 77, 36, -6, 1, -12, -63, -66, -25, -20, + -46, -19, 37, 28, 0, 38, 83, 54, 5, 5, -2, -57, -81, -34, -15, -44, + -22, 29, 31, -4, 16, 85, 68, 17, 15, 1, -44, -87, -54, -8, -42, -27, + 25, 24, 2, 0, 69, 88, 24, 25, 11, -42, -76, -75, -14, -25, -40, 23, + 18, -3, 3, 42, 96, 45, 22, 29, -39, -70, -75, -40, -8, -39, 7, 24, + -17, 8, 33, 79, 76, 22, 35, -21, -75, -64, -60, -15, -17, -14, 21, -21, + -4, 40, 59, 88, 45, 24, -3, -71, -61, -59, -38, 1, -14, 0, -17, -18, + 41, 54, 82, 74, 22, -3, -53, -61, -53, -54, -2, 3, -19, -25, -22, 30, + 57, 73, 92, 38, -15, -40, -51, -50, -58, -17, 17, -23, -44, -22, 19, 55, + 72, 97, 60, -22, -40, -35, -45, -55, -32, 14, -17, -60, -26, 11, 46, 75, + 97, 78, -17, -46, -23, -38, -45, -37, -1, -14, -66, -31, 3, 34, 80, 98, + 85, -4, -47, -19, -33, -33, -30, -20, -25, -63, -34, -4, 18, 79, 104, 84, + 9, -38, -18, -29, -27, -14, -30, -46, -63, -32, -5, 3, 68, 111, 84, 18, + -23, -12, -25, -28, -2, -25, -67, -75, -29, 1, -6, 46, 112, 91, 22, -11, + 0, -18, -33, -1, -9, -76, -96, -34, 9, -8, 22, 101, 102, 27, -2, 14, + -7, -36, -9, 4, -68, -114, -48, 13, -3, 5, 80, 109, 40, 4, 26, 6, + -33, -18, 6, -52, -120, -67, 7, 4, -1, 55, 103, 58, 14, 31, 17, -21, + -24, -4, -39, -110, -84, -10, 6, 2, 34, 87, 71, 29, 36, 25, -7, -23, + -16, -33, -96, -90, -29, -1, 6, 22, 68, 75, 45, 45, 31, 4, -15, -24, + -37, -84, -87, -43, -15, 3, 18, 53, 68, 57, 58, 38, 11, -7, -22, -45, + -81, -79, -48, -29, -10, 17, 45, 57, 61, 71, 50, 17, 0, -15, -49, -85, + -74, -45, -40, -25, 10, 42, 49, 55, 82, 65, 22, 7, -9, -43, -89, -80, + -34, -47, -40, -1, 35, 52, 43, 85, 84, 25, 17, -4, -38, -85, -92, -28, + -44, -55, -9, 21, 53, 42, 75, 100, 35, 22, 6, -38, -74, -99, -38, -34, + -65, -18, 12, 42, 51, 63, 102, 52, 25, 21, -36, -70, -90, -56, -30, -64, + -30, 7, 27, 55, 63, 90, 69, 33, 26, -26, -69, -79, -66, -43, -54, -37, + -1, 17, 49, 69, 79, 72, 50, 30, -15, -61, -75, -68, -58, -52, -33, -12, + 9, 42, 69, 78, 64, 60, 42, -9, -49, -71, -69, -68, -61, -25, -17, -1, + 38, 64, 77, 59, 62, 58, -3, -37, -62, -72, -72, -73, -24, -12, -11, 35, + 55, 73, 59, 58, 69, 8, -29, -48, -75, -76, -82, -31, -4, -14, 28, 49, + 63, 61, 54, 73, 22, -21, -36, -71, -82, -88, -42, 0, -9, 21, 43, 53, + 57, 56, 73, 33, -12, -25, -62, -89, -95, -49, -2, -2, 18, 37, 43, 49, + 60, 75, 38, -2, -16, -49, -89, -105, -54, -7, 1, 19, 31, 37, 38, 59, + 81, 39, 4, -7, -35, -83, -115, -62, -10, 0, 20, 27, 32, 30, 53, 87, + 43, 4, 0, -24, -70, -118, -75, -12, -2, 19, 24, 27, 27, 45, 89, 52, + 4, 1, -14, -55, -113, -87, -18, -3, 13, 20, 24, 28, 41, 85, 60, 7, + -3, -9, -40, -100, -91, -28, -4, 7, 10, 21, 30, 43, 82, 62, 13, -8, + -11, -26, -85, -87, -36, -10, 2, -4, 14, 35, 47, 81, 62, 18, -9, -21, + -20, -65, -78, -38, -19, -4, -16, 0, 39, 54, 85, 65, 20, -7, -31, -24, + -47, -62, -33, -26, -15, -25, -19, 35, 63, 90, 73, 22, -3, -39, -39, -35, + -43, -20, -26, -30, -34, -36, 24, 71, 94, 85, 29, -3, -40, -58, -34, -24, + -4, -16, -46, -47, -47, 6, 73, 100, 97, 42, -4, -39, -73, -45, -8, 12, + 0, -51, -64, -56, -13, 66, 104, 106, 64, 2, -40, -82, -63, -3, 27, 18, + -43, -82, -68, -28, 51, 104, 112, 86, 19, -42, -86, -81, -10, 40, 34, -26, + -90, -86, -41, 31, 98, 116, 104, 46, -38, -92, -95, -25, 46, 48, -6, -84, + -105, -55, 13, 84, 117, 114, 76, -20, -95, -105, -45, 41, 54, 8, -65, -112, + -70, -1, 65, 109, 115, 100, 14, -85, -106, -62, 21, 50, 13, -44, -104, -84, + -14, 45, 98, 112, 111, 53, -62, -105, -75, -3, 44, 12, -31, -85, -93, -27, + 27, 82, 110, 110, 81, -27, -95, -81, -27, 31, 11, -31, -66, -90, -39, 12, + 61, 106, 107, 94, 12, -73, -79, -48, 11, 13, -32, -57, -78, -46, -1, 38, + 97, 109, 96, 43, -41, -69, -62, -13, 13, -30, -58, -68, -46, -11, 17, 81, + 112, 97, 59, -7, -51, -67, -37, 6, -23, -62, -67, -42, -14, 2, 60, 110, + 99, 65, 20, -24, -63, -56, -7, -15, -63, -75, -40, -12, -8, 39, 102, 103, + 67, 35, 6, -48, -68, -25, -11, -56, -85, -46, -7, -10, 22, 86, 107, 72, + 41, 29, -25, -70, -42, -14, -42, -91, -62, -5, -6, 9, 67, 105, 84, 40, + 40, 3, -64, -56, -23, -30, -83, -85, -12, 3, 1, 50, 97, 96, 44, 36, + 28, -45, -69, -33, -22, -67, -101, -34, 13, 2, 31, 88, 104, 56, 28, 37, + -16, -71, -51, -18, -49, -103, -62, 9, 14, 18, 70, 109, 68, 26, 36, 6, + -58, -68, -23, -28, -97, -84, -7, 23, 19, 50, 106, 84, 28, 31, -21, -26, + -18, -30, -24, -77, -76, -48, -46, 31, 0, -1, 0, 0, 2, 0, 1, -2, + 1, 0, -6, -7, -5, -3, 0, -3, -4, -2, 2, 0, -8, -11, -14, -10, + -8, -4, 6, 13, 14, 9, 2, -6, -10, -9, -6, 9, 17, 15, 8, 0, + 1, -4, -12, -19, -14, -8, -4, 3, 6, -2, -4, -6, -7, -10, -8, -12, + -11, 3, 23, 27, 11, 4, -3, -5, 0, -9, -3, 6, 11, 19, 4, -8, + -17, -20, -21, -3, 5, 8, 2, 3, 5, 2, -3, -3, -12, 4, 1, 3, + -7, 0, 5, 6, 0, -7, -8, -5, -7, -5, -3, 4, 9, 5, -5, -5, + -5, -17, -7, 3, 17, 15, 7, -2, -5, -3, 3, -8, -5, -3, 3, 8, + 12, 5, -10, -27, -20, 1, 5, -4, -9, -17, 4, 10, 9, -2, -12, -16, + -12, -2, 8, 16, 13, 11, 16, 19, 10, -2, -16, -21, -11, 14, 15, 21, + 11, 6, -10, -8, -11, -24, -35, -31, -13, 9, 24, 17, -2, -11, -20, -11, + -19, -7, 3, 8, 22, 21, 21, 2, -7, -10, 12, 24, 18, -3, -19, -6, + 0, -5, -18, -17, 6, 12, 7, -16, -20, -22, -27, -19, -14, 12, 14, 3, + 0, 2, 8, -3, -5, -3, 21, 29, 17, 6, -8, 3, 3, 10, 10, 3, + 12, 4, -9, -18, -20, -20, -9, 6, 3, -9, -7, -14, -9, -8, -9, -23, + -19, 7, 17, 20, 9, 8, 5, 9, 18, 9, 8, -10, -10, -4, 9, 25, + -6, -19, -19, -5, -4, -7, -7, -17, -15, -7, -4, 0, 2, -2, -17, -4, + 14, 23, 15, 2, -7, -5, 9, 11, 1, 0, -3, 0, 0, 15, 14, -4, + -15, -20, -26, -22, -13, 0, 6, 12, 5, -10, 2, 8, -2, -18, -8, 6, + 20, 28, 23, 0, -16, -7, 9, 7, 10, -12, -21, -19, 7, 12, 4, -17, + -28, -24, -3, 14, 4, -19, -18, -9, 11, 22, 16, -13, -23, -15, 18, 32, + 32, 17, -4, 1, 14, 11, 1, -20, -19, -3, 9, 13, -4, -13, -16, -18, + -23, -12, -17, -16, -20, -15, -14, -4, 8, 12, 0, 8, 5, 12, 17, 26, + 25, 14, 10, 11, 11, 18, 15, 4, -9, -13, -8, -9, -14, -20, -28, -32, + -12, -9, -16, -17, -24, -18, -12, 5, 10, 4, 6, 8, 18, 35, 31, 17, + 1, 12, 21, 33, 18, 6, -10, -11, -4, -9, -13, -19, -24, -24, -24, -18, + -20, -18, -20, -13, -15, -10, -9, -5, 8, 10, 13, 23, 26, 29, 14, 13, + 13, 13, 16, 25, 19, 17, 4, -15, -18, -15, -14, -17, -34, -23, -16, -12, + -16, -26, -33, -23, -15, -4, 4, 10, 16, 19, 22, 29, 28, 7, 1, 2, + 18, 26, 30, 21, 9, 3, -4, -10, -16, -29, -31, -27, -4, -9, -11, -28, + -23, -17, -15, -13, -11, 4, 11, 9, 13, 16, 25, 18, 8, 10, 18, 17, + 8, 18, 17, 11, -5, -19, -17, -12, -19, -38, -27, -8, 0, -3, -14, -19, + -20, -14, -10, -13, -3, 6, 12, 26, 38, 34, 14, 2, -2, 11, 19, 14, + 8, 5, 16, 9, -7, -19, -24, -29, -36, -26, -13, -12, -22, -28, -20, 5, + -3, -10, -19, 7, 20, 18, 17, 24, 25, 14, 18, 19, 29, 21, 11, 10, + 9, 13, -13, -29, -27, -20, -24, -30, -22, -12, -7, -15, -22, -21, -13, -14, + -20, -8, 12, 26, 25, 21, 33, 27, 25, 16, 13, 16, 16, -2, 2, 11, + 9, -2, -17, -18, -16, -25, -25, -26, -27, -30, -35, -30, -12, -6, -6, -6, + -5, 19, 19, 11, 15, 17, 24, 23, 34, 28, 23, 13, 2, 9, 18, 16, + -14, -18, -12, -7, -9, -31, -37, -33, -24, -14, -24, -20, -16, -21, -15, -7, + 5, 9, 15, 20, 28, 38, 29, 21, 15, 22, 17, 4, 12, 6, 12, -4, + -9, -15, -16, -19, -40, -38, -34, -23, -18, -17, -8, -10, -3, -7, 1, 3, + 4, 11, 13, 36, 41, 36, 24, 9, 17, 20, 21, 14, -5, -9, -11, -8, + -19, -14, -24, -30, -23, -18, -25, -30, -24, -17, -20, -9, -3, 6, 8, 22, + 23, 20, 27, 18, 10, 10, 14, 18, 14, 23, 17, 6, 5, -4, -8, -26, + -19, -24, -25, -24, -21, -27, -28, -15, -19, -16, -9, 0, 7, 9, 17, 14, + 15, 24, 30, 29, 29, 32, 16, 10, 8, 0, -3, -10, -7, -17, -22, -25, + -30, -36, -32, -25, -26, -22, -12, -16, -11, -3, 5, 7, 13, 21, 21, 26, + 32, 28, 26, 28, 31, 17, 15, 15, 5, -4, -14, -18, -28, -25, -24, -28, + -32, -33, -32, -29, -18, -17, -20, -10, -4, 6, 6, 18, 22, 22, 37, 38, + 31, 27, 26, 23, 22, 23, 12, 4, -5, -2, -11, -19, -25, -35, -35, -36, + -36, -43, -32, -24, -20, -12, -7, -3, -7, 3, 13, 23, 29, 35, 37, 35, + 42, 33, 26, 22, 17, 12, 6, 4, -9, -23, -28, -34, -34, -33, -31, -40, + -36, -27, -25, -22, -30, -20, -11, 2, 12, 22, 22, 26, 28, 35, 47, 44, + 27, 29, 29, 29, 19, 2, 1, -9, -15, -21, -34, -35, -34, -40, -44, -42, + -34, -31, -26, -21, -9, -12, -3, 10, 17, 29, 26, 27, 34, 48, 50, 34, + 33, 25, 21, 16, 8, 3, -8, -11, -25, -30, -37, -37, -42, -51, -34, -28, + -21, -26, -25, -19, -13, 4, 9, 17, 29, 41, 33, 33, 44, 45, 32, 31, + 28, 22, 16, 5, -10, -13, -16, -23, -38, -39, -39, -45, -54, -40, -32, -24, + -22, -17, -14, 0, 6, 9, 18, 41, 43, 34, 32, 40, 40, 31, 30, 27, + 22, 19, 14, -2, -16, -21, -34, -48, -45, -41, -41, -41, -45, -38, -25, -21, + -17, -20, -7, 11, 17, 19, 36, 40, 42, 44, 47, 46, 39, 33, 26, 15, + 11, 8, -5, -19, -24, -29, -40, -44, -48, -44, -37, -37, -43, -43, -26, -19, + -14, -2, 13, 23, 31, 36, 36, 43, 41, 47, 46, 44, 40, 24, 15, 14, + 3, -12, -21, -23, -30, -36, -47, -51, -50, -47, -44, -46, -31, -19, -16, -11, + 2, 16, 20, 25, 29, 40, 53, 51, 49, 45, 41, 35, 25, 18, 7, 5, + -12, -18, -23, -34, -39, -56, -58, -54, -49, -50, -45, -35, -26, -12, -5, 6, + 17, 29, 41, 42, 47, 50, 46, 49, 50, 50, 39, 30, 16, 2, -8, -15, + -21, -30, -41, -49, -50, -46, -57, -63, -57, -41, -29, -24, -12, -3, 5, 12, + 22, 33, 41, 50, 51, 53, 57, 55, 46, 36, 29, 16, 2, -4, -11, -21, + -33, -40, -49, -47, -53, -60, -58, -51, -42, -34, -23, -13, -2, 5, 17, 27, + 39, 49, 48, 51, 56, 54, 58, 44, 37, 28, 18, 4, -3, -15, -29, -39, + -49, -49, -51, -62, -65, -64, -47, -42, -36, -26, -14, -5, 10, 24, 32, 45, + 50, 49, 62, 65, 63, 47, 42, 41, 36, 23, 7, -7, -22, -31, -41, -53, + -58, -62, -59, -62, -56, -54, -50, -44, -32, -16, 0, 11, 25, 35, 50, 54, + 55, 56, 66, 65, 62, 54, 45, 36, 23, 14, -4, -22, -44, -55, -52, -62, + -61, -66, -70, -68, -60, -54, -45, -29, -15, 4, 21, 34, 36, 44, 54, 62, + 70, 73, 68, 67, 59, 50, 37, 21, -5, -12, -25, -39, -48, -53, -63, -76, + -73, -71, -71, -67, -57, -45, -29, -12, 2, 13, 30, 42, 51, 61, 76, 71, + 63, 66, 71, 60, 50, 40, 23, -2, -9, -20, -41, -54, -59, -72, -79, -71, + -64, -73, -68, -60, -51, -36, -13, 2, 13, 27, 47, 54, 71, 78, 71, 60, + 72, 74, 65, 54, 39, 28, 7, -6, -23, -50, -59, -64, -69, -75, -70, -78, + -74, -73, -64, -52, -37, -13, 6, 18, 40, 51, 58, 64, 78, 79, 75, 68, + 64, 68, 57, 45, 21, 4, -16, -34, -50, -65, -75, -83, -80, -71, -69, -68, + -73, -63, -57, -36, -16, 6, 26, 45, 60, 70, 71, 79, 79, 81, 78, 80, + 64, 55, 36, 16, -4, -23, -38, -54, -63, -69, -81, -85, -87, -76, -72, -66, + -61, -52, -30, -12, 12, 24, 44, 55, 69, 78, 85, 84, 74, 70, 71, 71, + 62, 41, 17, -11, -25, -42, -55, -66, -75, -87, -87, -81, -74, -76, -76, -63, + -48, -32, -13, 7, 30, 51, 64, 76, 80, 82, 83, 81, 80, 82, 70, 61, + 42, 19, 0, -28, -49, -61, -72, -78, -87, -90, -89, -88, -87, -82, -69, -54, + -33, -13, 15, 36, 58, 68, 79, 90, 96, 90, 84, 86, 89, 79, 62, 38, + 22, -3, -29, -55, -69, -81, -89, -94, -94, -94, -94, -89, -74, -62, -52, -35, + -18, 14, 39, 54, 65, 76, 87, 98, 95, 94, 90, 82, 75, 69, 47, 26, + -6, -33, -57, -72, -82, -88, -97, -90, -91, -88, -83, -80, -75, -59, -33, -9, + 20, 42, 58, 68, 82, 90, 94, 93, 94, 88, 85, 77, 65, 43, 16, -10, + -37, -60, -71, -84, -89, -95, -97, -102, -95, -84, -80, -72, -57, -26, -4, 19, + 42, 62, 80, 89, 94, 97, 100, 99, 90, 83, 71, 65, 39, 14, -9, -43, + -65, -83, -90, -95, -98, -96, -100, -96, -88, -76, -66, -51, -24, -12, 21, 45, + 70, 85, 93, 95, 97, 101, 105, 92, 84, 69, 58, 35, 16, -14, -44, -68, + -86, -88, -96, -101, -101, -102, -97, -90, -74, -69, -50, -19, 9, 35, 56, 76, + 84, 92, 98, 96, 99, 97, 93, 84, 77, 59, 24, 2, -30, -52, -76, -87, + -93, -98, -100, -102, -100, -96, -89, -81, -73, -46, -18, 12, 36, 62, 82, 88, + 96, 104, 107, 105, 102, 92, 84, 77, 53, 26, -6, -35, -57, -75, -81, -92, + -103, -114, -111, -108, -98, -88, -83, -67, -35, -7, 20, 39, 60, 70, 89, 106, + 116, 107, 103, 99, 86, 90, 82, 53, 18, -13, -31, -52, -73, -92, -102, -106, + -104, -97, -106, -99, -101, -92, -72, -42, -5, 16, 38, 66, 86, 101, 99, 101, + 95, 112, 107, 99, 95, 81, 53, 16, -3, -29, -60, -81, -102, -98, -102, -102, + -112, -114, -101, -104, -88, -69, -34, -8, 14, 41, 67, 92, 94, 99, 103, 104, + 115, 109, 103, 90, 78, 52, 22, 0, -39, -65, -92, -95, -91, -103, -104, -118, + -110, -102, -93, -84, -71, -36, -15, 19, 52, 81, 94, 89, 98, 103, 115, 117, + 102, 92, 83, 80, 49, 23, -11, -43, -67, -90, -93, -102, -105, -110, -118, -104, + -100, -89, -83, -64, -36, -7, 28, 50, 74, 88, 95, 104, 103, 115, 107, 106, + 97, 87, 74, 50, 20, -17, -47, -75, -89, -93, -101, -102, -115, -117, -106, -97, + -88, -90, -73, -38, 2, 36, 60, 75, 84, 96, 104, 115, 115, 102, 98, 96, + 96, 84, 52, 10, -12, -32, -53, -71, -87, -101, -109, -112, -109, -106, -105, -102, + -92, -74, -48, -19, 7, 33, 56, 76, 91, 101, 108, 111, 111, 108, 103, 96, + 85, 63, 33, 1, -27, -51, -73, -90, -102, -109, -112, -110, -107, -103, -100, -93, + -76, -50, -19, 10, 36, 58, 76, 91, 101, 108, 111, 111, 108, 103, 96, 85, + 63, 33, 1, -27, -51, -73, -90, -102, -109, -112, -110, -107, -103, -100, -93, -76, + -50, -19, 10, 36, 58, 76, -1, -2, -15, 21, -17, 23, -30, 1, 34, -34, + 6, 5, -15, 19, 1, -25, 6, 20, -2, -28, 15, 10, -15, 0, -7, 10, + 7, -5, -9, -6, 19, -3, -21, 3, 20, -4, -20, 1, 16, -3, -8, -2, + 5, 1, -8, -6, 3, 9, 2, -13, -4, 15, -7, -9, 0, 3, 6, -7, + -7, 5, 8, -8, -4, 0, 1, 1, -6, -4, 7, 2, -2, -7, 0, 4, + -3, -4, 0, 2, 0, -2, -4, 1, 4, -2, -4, -3, 1, 3, -5, -4, + 4, 3, -6, -5, 4, -1, -2, -3, 0, 3, -3, -1, -4, 3, 3, -5, + -3, 1, 1, -2, -3, 1, 2, -2, -4, 0, 0, 0, -1, -3, 1, 1, + -3, -2, 1, 0, -2, -2, 0, 0, -2, -1, 0, -1, 1, -2, -2, 1, + 0, -2, 0, -1, 0, -1, -1, -1, 0, 0, -1, -3, 1, 1, -2, -2, + 0, 1, -1, -2, -1, 0, 0, 0, -2, -1, 1, 0, -3, 0, 2, -1, + -2, 0, 0, 0, -2, 0, -1, 0, -1, -1, 1, 0, -1, 0, -1, 1, + 0, -13, 5, 7, -11, 24, -50, 41, 4, -29, 14, -11, 8, 11, -15, -12, + 15, 18, -21, -14, 22, -2, -11, -3, -3, 18, -3, -5, -14, 9, 22, -24, + -16, 23, 12, -23, -8, 9, 10, -4, -8, -3, 11, -4, -14, 0, 8, 8, + -5, -14, 8, 10, -12, -4, -2, 10, 0, -11, -3, 11, 0, -7, -2, -1, + 7, -6, -8, 3, 6, 0, -3, -8, 7, 2, -7, -2, 2, 1, -2, -4, + -1, 3, 3, -4, -5, 1, 3, -3, -6, 2, 5, -1, -7, -1, 3, -1, + -4, -3, 5, 0, -3, -2, -1, 4, -1, -5, -1, 3, -1, -4, -1, 3, + 1, -4, -2, 1, 0, -2, -3, 0, 2, -1, -4, 1, 1, -1, -2, -2, + 1, -1, -3, 0, 0, 0, -1, -2, 0, 0, -2, -1, 0, -1, 0, -2, + -1, 0, -1, 0, -1, -2, 2, -1, -2, -1, 0, 1, -2, 0, -1, -1, + 0, -1, -2, 0, 1, -1, -3, 0, 1, -1, -3, 0, 1, -2, -1, 0, + 0, -1, -1, 0, -1, -1, -1, -1, 0, 0, -1, -1, 0, 0, -2, 0, + 0, 0, 0, -2, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, + -1, 0, 0, -1, 0, -1, 1, 0, 0, 0, 1, -1, -1, 0, 0, 0, + 1, -2, 4, -3, 3, -40, 71, -73, 67, -27, -68, 127, -80, 3, 5, 1, + 17, -14, 1, -30, 53, -3, -42, 15, 19, -9, -17, -1, 13, 16, -17, 4, + -32, 43, 15, -68, 18, 54, -38, -7, -1, 11, 7, -3, -18, 5, 25, -27, + -9, 9, 19, -6, -12, -8, 20, -1, -15, -1, 1, 17, -10, -16, 12, 12, + -13, 0, -6, 10, 2, -16, -1, 14, -4, 4, -11, -2, 12, -6, -8, 4, + 4, -2, -4, 1, -2, 4, 3, -7, -5, 8, 0, -10, 1, 4, 2, -4, + -6, 4, 1, -1, -7, 1, 8, -9, 2, -5, 3, 3, -4, -3, 0, 3, + -3, -5, 4, 3, -3, -4, 0, 2, 0, -3, -4, 5, 0, -5, -1, 2, + 0, -3, 0, -1, 2, -2, -4, 3, 0, -1, -2, -1, 2, -2, -2, 1, + -1, 0, -1, -3, 1, 1, -2, 1, -3, 1, 1, -3, -1, 1, 0, -1, + -2, 1, -1, -1, 1, -2, 1, -1, -1, -1, -1, 0, 1, -3, 0, 0, + 1, -4, 0, 1, -2, 0, -2, 0, 0, 0, -2, 1, -1, 0, -2, 0, + 2, -2, -1, 0, -1, 2, -2, -1, 1, -2, 0, -1, 1, -1, -1, -1, + 1, -2, 1, -1, -1, 2, -3, 0, 0, -1, 1, -1, 0, 1, 0, -2, + 0, -1, 1, -2, 0, 0, -1, 1, 0, -2, 0, 1, -2, 1, 0, 0, + -1, 0, 1, -1, -1, -1, 1, 1, -1, 0, 0, 0, -1, 1, 0, -1, + 1, 0, 0, 1, 0, -1, 1, 0, 3, -40, 58, -39, 12, 42, -117, 108, + 1, -66, 22, 17, 0, -9, 10, -39, 42, 4, -23, -12, 28, 3, -34, 9, + 17, 3, -9, 10, -29, 13, 53, -79, 3, 64, -26, -24, 16, -9, 14, 2, + -8, -15, 31, -9, -30, 11, 29, -15, -7, 0, 3, 6, -4, -9, -6, 22, + 1, -24, 9, 11, -8, 0, -2, 2, 8, -12, -6, 10, 2, 2, -9, -4, + 11, -2, -10, 3, 2, 3, -5, -1, 1, -1, 6, -4, -8, 9, 2, -8, + -3, 6, 3, -4, -3, -1, 6, -2, -8, 0, 9, -4, -3, -2, 2, 4, + -4, -1, -1, 4, -2, -6, 4, 2, -1, -4, 0, 1, 2, -3, -5, 3, + 3, -3, -4, 3, 0, -1, 0, -2, 2, 0, -3, 0, 3, 0, -3, -1, + 2, 0, -3, 1, 0, -1, 2, -2, -2, 2, -1, 0, -1, -1, 1, -1, + -2, 0, 0, 1, -3, 1, 0, -1, 1, -2, -1, 2, -2, -1, 0, -1, + 2, -3, -1, 1, 1, -2, -2, 2, 1, -2, -1, 0, 0, 1, -3, 1, + 0, 0, 0, -2, 3, 0, -2, 0, 0, 1, 0, -1, 1, -2, 0, 0, + 0, -1, 1, 0, 0, 0, -1, 1, -1, 1, 0, -1, 1, -2, 0, 1, + 1, 0, 1, -2, 1, 0, 1, 0, 0, 3, -1, 0, 1, 0, 0, 3, + -29, 35, -12, -16, 56, -88, 39, 62, -79, 5, 29, 1, -13, 12, -29, 26, + 17, -28, -3, 12, 5, -11, -19, 28, 1, -5, 9, -21, -7, 60, -56, -20, + 57, -10, -27, 21, -21, 16, 12, -12, -21, 24, 6, -29, 4, 19, 2, -7, + -5, -3, 7, 6, -11, -9, 11, 13, -18, -4, 13, 1, -3, -6, -1, 10, + -8, -6, 5, 3, 5, -3, -11, 4, 9, -11, 0, 4, 3, -4, -1, 0, + 0, 7, 0, -14, 7, 5, -7, -4, 4, 5, -1, -4, -4, 4, 1, -4, + -4, 7, -1, -1, -3, 0, 5, -1, -4, -1, 2, 0, -3, 1, 1, 2, + -2, -4, 1, 2, 0, -5, 2, 3, -2, -2, 1, 1, -2, 2, -3, 0, + 0, -1, -1, 0, 1, 0, -3, 0, 0, -1, 1, -1, -2, 1, -1, 0, + -2, 2, 1, -2, -1, 1, 0, -1, -1, 0, 1, -1, 0, -2, 1, 1, + -1, 0, -1, -1, 0, 0, -1, -1, 0, -1, -1, 2, -2, -1, 1, 0, + 0, -1, -1, 1, 0, -1, 1, -1, 0, 1, -3, 1, 1, -1, -1, 0, + 1, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, 0, 2, -2, 0, 1, + 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, -1, -1, -7, -9, 35, -52, + 59, -33, -32, 64, -15, -41, 19, 22, -20, 9, -11, -3, 33, -27, 2, 7, + -9, 19, -37, 24, 7, -11, 11, -1, -30, 37, 8, -57, 36, 19, -33, 14, + 0, -17, 26, 1, -20, -5, 26, -18, -13, 14, 7, -6, 4, -9, -4, 11, + 3, -14, -7, 20, 0, -18, 10, 1, 4, -5, -7, 6, 0, -3, -2, -2, + 8, 5, -11, -6, 10, -1, -10, 6, -2, -1, 1, -3, 0, 3, 5, -9, + -5, 9, -3, -4, 1, 1, 3, -1, -4, -1, 2, -2, -5, 5, -3, 0, + 1, -5, 4, 2, -3, -3, 0, 0, -2, 1, 0, -2, 3, -2, -5, 2, + 2, -2, -4, 3, 0, -2, 1, -2, -2, 5, -2, -6, 1, 2, -1, -1, + 0, 1, -1, -2, -1, -1, 2, 0, -4, 0, 1, 0, -3, 0, 2, 0, + -3, 0, 0, 1, -1, -1, 1, 0, -1, -2, 1, 0, 0, -1, 0, -2, + 1, 0, -1, 1, -1, 0, -2, 1, 1, -2, -1, 2, -2, 1, -3, 1, + 1, -1, 0, 0, -1, 1, 0, -2, 2, -1, -1, 0, 0, 1, 0, 1, + 0, -2, 1, 0, 0, -1, 1, 0, 0, 0, 0, -3, -20, 45, -56, 40, + -5, -34, 27, 24, -42, -1, 29, -14, -4, 2, -7, 24, -20, -1, 18, -25, + 25, -29, 9, 21, -26, 14, 4, -20, 7, 27, -42, 5, 31, -24, -2, 19, + -30, 21, 8, -11, -17, 20, 1, -22, 11, 7, -7, 6, -5, -7, 3, 11, + -6, -18, 11, 16, -20, 1, 5, 2, -3, -3, 0, -3, 4, -1, -7, 2, + 10, -9, -8, 7, 2, -9, 5, -1, -5, 2, 1, -3, -2, 9, -5, -8, + 4, 1, -5, 0, 1, 2, -1, 0, -5, 4, -1, -5, 4, -3, 1, 1, + -5, 3, 0, 0, -3, 0, -1, -2, 1, 2, -5, 2, 1, -5, -2, 3, + -1, -5, 2, 1, -4, 2, -1, -4, 2, 3, -7, -1, 2, 0, -2, 1, + 0, -2, -1, 0, -3, 1, 2, -3, -2, 3, 0, -3, -1, 1, 0, -1, + -2, -1, 1, 0, 0, -1, 0, 0, -2, 0, 0, 1, -2, 2, -3, 1, + 0, 0, -2, 1, 0, -1, 0, 0, -1, -1, 2, -3, 0, 0, -1, 0, + 0, -1, 1, 0, -4, -13, 32, -41, 31, -10, -10, 4, 22, -25, -8, 21, + -3, -14, 5, 1, 12, -23, 8, 18, -31, 25, -26, 10, 17, -23, 8, 5, + -9, 0, 16, -25, 2, 23, -22, -2, 22, -30, 15, 7, -6, -13, 12, 1, + -17, 9, 5, -6, 4, -3, -7, 5, 7, -6, -13, 7, 10, -11, 0, 0, + 4, -3, -3, 2, -7, 4, 2, -5, 0, 6, -3, -8, 4, 2, -8, 7, + 0, -8, -1, 6, 0, -8, 6, 0, -5, 1, 0, -5, 3, 2, -3, -2, + 4, -5, -1, -1, -2, 3, -4, 1, -1, -3, 3, -1, -2, -2, 1, -2, + -2, 1, 1, -4, 1, 2, -5, -3, 5, -3, -4, 4, -1, -4, 2, -1, + -4, 3, 1, -5, -2, 2, 0, -2, 2, -1, -4, 3, -1, -3, 0, 1, + -2, -2, 1, -1, -1, -1, 0, 0, -1, -1, -1, 0, -1, 1, -1, -1, + 0, -2, 1, 0, -1, -1, 0, -1, -1, -1, 2, -2, -1, 1, -1, -2, + 1, -1, -1, 1, -2, 1, -7, -3, 15, -23, 20, -16, 9, -12, 16, -12, + -8, 11, 5, -18, 6, 8, 0, -18, 16, 4, -19, 16, -17, 10, 5, -8, + -2, 9, -5, -4, 10, -17, 5, 13, -18, 2, 12, -17, 10, 0, -2, -8, + 7, -4, -7, 6, 1, -3, 1, 3, -9, -2, 10, -7, -8, 4, 6, -6, + 1, 0, 0, -2, 1, -1, -8, 6, 1, -5, 2, 4, -2, -4, 1, 1, + -7, 5, -1, -4, -2, 4, 0, -4, 4, -3, -4, 1, 0, -3, 0, 2, + -1, -2, 2, -2, -1, -3, 0, 3, -4, 3, -3, 0, 2, 0, -3, -1, + 1, -3, -1, 2, 0, -1, 0, 0, -3, 0, 1, -4, -1, 2, 0, -2, + 0, 1, -3, 1, 1, -3, -2, 2, -1, -1, 2, -1, -2, 1, 0, -1, + -1, -1, -3, -8, -16, -20, -7, 14, 20, 19, 18, 16, 11, 3, -9, -21, + -36, -43, -39, -24, 6, 38, 57, 55, 26, 0, -7, -10, -13, -12, -11, -29, + -56, -59, -37, 0, 43, 74, 87, 75, 37, -2, -31, -51, -59, -45, -15, -16, + -34, -20, -10, -5, 29, 61, 72, 51, 18, -2, -21, -39, -35, -24, 1, 0, + -31, -29, -23, -44, -13, 48, 82, 79, 46, 16, -4, -44, -58, -26, 3, 6, + -38, -52, -24, -42, -35, 47, 95, 88, 55, 19, 12, -22, -72, -38, 4, 3, + -31, -67, -29, -24, -60, 23, 112, 111, 72, 22, 7, -20, -90, -73, -1, 19, + -4, -57, -36, 3, -54, -32, 98, 125, 71, 14, 14, 0, -82, -106, 0, 42, + 10, -48, -32, -2, -54, -63, 72, 125, 82, 24, 14, -8, -57, -104, -22, 52, + 34, -34, -46, -16, -35, -83, 32, 127, 99, 26, 19, 4, -55, -110, -48, 45, + 36, -12, -26, -22, -41, -64, -7, 107, 113, 56, 6, 4, -41, -92, -74, 35, + 57, 12, -41, -21, -39, -67, -40, 86, 114, 71, 10, 22, -31, -83, -83, 16, + 46, 34, -28, -18, -42, -58, -60, 55, 108, 97, 3, 21, -8, -77, -102, 10, + 45, 42, -26, -2, -27, -68, -73, 45, 83, 92, 29, 25, -8, -56, -104, -13, + 35, 52, -6, -7, -22, -46, -91, 10, 80, 95, 35, 26, 8, -38, -106, -34, + 34, 42, 5, 1, -23, -39, -73, -28, 61, 89, 60, 20, 2, -7, -73, -86, + 24, 52, 26, -12, -11, -19, -58, -86, 46, 91, 62, 17, 22, -15, -39, -106, + 8, 55, 45, -13, -6, -30, -21, -102, 4, 82, 87, 7, 28, -3, -9, -115, + -32, 50, 63, -23, 8, -19, -18, -94, -28, 61, 96, 14, 39, -4, 1, -85, + -60, 23, 79, -3, 2, -20, -10, -82, -65, 25, 108, 28, 31, 19, 9, -65, + -74, -5, 78, 16, -3, -9, -14, -65, -76, -3, 93, 60, 29, 22, 13, -43, + -90, -30, 61, 49, -9, -1, 4, -52, -98, -16, 68, 72, 21, 38, 15, -31, + -94, -34, 32, 67, 5, 9, 0, -28, -111, -33, 40, 85, 24, 37, 23, -6, + -104, -44, 13, 69, 9, 14, 8, -11, -110, -53, 20, 80, 32, 48, 30, 5, + -87, -66, -7, 63, 33, 12, 2, 5, -86, -94, -2, 79, 46, 26, 44, 22, + -59, -88, -19, 54, 48, 13, 14, 4, -51, -112, -37, 67, 71, 21, 38, 29, + -29, -104, -50, 44, 63, 11, 10, 14, -24, -103, -67, 49, 88, 20, 27, 43, + -10, -90, -79, 24, 69, 21, 7, 18, -8, -82, -103, 17, 94, 38, 10, 54, + 12, -70, -97, 1, 68, 37, -4, 27, -6, -56, -104, -21, 82, 67, -3, 46, + 23, -37, -108, -31, 57, 58, -13, 29, 11, -32, -106, -50, 53, 92, -6, 38, + 38, -15, -105, -54, 34, 79, -12, 20, 22, -11, -98, -70, 22, 99, 4, 16, + 48, 14, -99, -75, 15, 82, 2, 0, 44, 8, -93, -80, 0, 84, 29, -3, + 57, 32, -79, -94, 1, 66, 27, -19, 49, 29, -73, -109, -7, 54, 52, -17, + 62, 53, -46, -113, -4, 43, 51, -30, 46, 37, -42, -128, -23, 26, 69, -18, + 51, 59, -2, -122, -30, 24, 66, -27, 31, 51, 1, -128, -48, 13, 71, -11, + 33, 66, 22, -110, -57, 8, 68, -9, 12, 53, 28, -104, -87, -4, 67, 8, + 8, 72, 53, -80, -91, -4, 59, 10, -13, 63, 44, -81, -109, -19, 46, 33, + -6, 76, 57, -43, -104, -24, 36, 42, -26, 55, 51, -34, -126, -39, 19, 58, + -21, 68, 71, -8, -114, -32, 2, 62, -24, 52, 54, -4, -120, -53, -22, 71, + -8, 49, 62, 31, -102, -52, -25, 70, -5, 24, 55, 35, -109, -69, -40, 59, + 16, 25, 65, 55, -80, -70, -37, 47, 23, 7, 48, 51, -73, -97, -48, 30, + 46, 6, 57, 74, -37, -98, -34, 21, 48, -10, 44, 58, -34, -123, -46, -2, + 61, 2, 50, 69, 10, -110, -40, -5, 59, -9, 31, 53, 19, -126, -59, -20, + 62, 8, 32, 64, 49, -105, -59, -16, 58, 2, 17, 50, 45, -102, -83, -31, + 46, 24, 15, 53, 69, -65, -86, -24, 42, 25, -4, 45, 64, -58, -112, -37, + 30, 41, -6, 51, 75, -24, -105, -32, 26, 41, -19, 39, 62, -14, -117, -51, + 7, 54, -13, 35, 78, 19, -105, -47, 9, 58, -19, 21, 69, 18, -113, -66, + -10, 52, -10, 14, 75, 42, -83, -60, -5, 52, 0, -3, 69, 43, -83, -83, + -21, 35, 17, -13, 72, 57, -54, -82, -10, 29, 28, -29, 65, 52, -45, -98, + -21, 1, 40, -30, 64, 63, -7, -94, -9, 1, 51, -36, 51, 54, -8, -115, + -23, -22, 47, -30, 48, 65, 24, -90, -13, -15, 46, -26, 30, 55, 21, -100, + -37, -26, 31, -10, 24, 65, 41, -71, -35, -10, 25, -2, 4, 58, 32, -69, + -61, -16, 2, 8, 1, 67, 42, -33, -56, -1, -1, 20, -13, 59, 33, -28, + -82, -10, -20, 22, -15, 64, 40, -1, -70, 0, -17, 29, -22, 53, 33, 1, + -84, -15, -29, 22, -19, 53, 43, 22, -64, -7, -19, 25, -18, 37, 38, 16, + -73, -30, -33, 11, -14, 32, 50, 31, -45, -17, -15, 16, -4, 16, 43, 23, + -49, -43, -30, -2, -1, 8, 52, 36, -25, -32, -13, -1, 11, -1, 42, 30, + -25, -49, -25, -18, 10, -7, 44, 40, -2, -34, -11, -15, 21, -6, 29, 33, + -5, -54, -29, -30, 13, -6, 29, 46, 15, -32, -10, -18, 16, -1, 13, 36, + 9, -45, -30, -32, 0, 1, 12, 43, 28, -23, -16, -16, 6, 9, 2, 33, + 22, -33, -34, -27, -11, 2, 1, 35, 36, -14, -16, -11, -5, 8, 3, 24, + 32, -19, -30, -29, -17, -4, 1, 20, 43, -5, -14, -13, -4, 0, 7, 11, + 39, -9, -23, -28, -17, -16, 1, 9, 44, 3, -7, -15, -4, -4, 7, 5, + 38, 3, -20, -30, -19, -19, -8, 0, 40, 17, -6, -7, -3, -2, -1, 4, + 32, 16, -20, -21, -26, -17, -18, -3, 28, 32, -7, -1, -9, 4, -9, 3, + 22, 34, -19, -14, -27, -13, -27, -10, 16, 44, -8, 5, -6, 3, -12, 1, + 13, 40, -12, -11, -25, -17, -27, -15, 5, 45, 4, 2, 0, 0, -9, -5, + 6, 38, 2, -17, -14, -20, -24, -23, 0, 38, 19, -4, 11, -4, -7, -10, + 4, 27, 20, -20, -9, -23, -22, -30, -6, 26, 35, -8, 12, 2, -4, -15, + 2, 20, 32, -16, -7, -15, -22, -37, -14, 18, 39, -3, 5, 8, -5, -18, + -2, 18, 34, -4, -14, -4, -21, -35, -25, 15, 36, 8, -4, 21, -5, -17, + -14, 23, 26, 9, -22, 4, -25, -32, -40, 14, 27, 24, -12, 30, 1, -8, + -26, 24, 21, 19, -28, 9, -20, -28, -51, 7, 23, 30, -15, 27, 9, -7, + -32, 16, 25, 23, -21, 4, -8, -27, -50, -10, 25, 29, -9, 13, 24, -7, + -28, -3, 34, 20, -12, -9, 10, -31, -43, -29, 30, 23, 2, -3, 38, -9, + -19, -19, 39, 18, -1, -20, 25, -29, -36, -42, 26, 17, 12, -14, 43, -3, + -15, -29, 35, 19, 6, -28, 27, -18, -36, -48, 16, 17, 15, -15, 39, 12, + -13, -29, 24, 24, 9, -25, 19, -1, -39, -50, 1, 18, 11, -11, 25, 26, + -14, -26, 12, 32, 10, -17, 6, 17, -33, -48, -14, 20, 6, -7, 11, 36, + -9, -26, -1, 34, 11, -9, -4, 25, -25, -49, -26, 19, 4, -4, 5, 41, + 3, -21, -8, 31, 12, -7, -11, 23, -13, -47, -37, 13, 6, -3, 1, 40, + 14, -17, -14, 26, 16, -2, -12, 20, -3, -40, -44, 2, 6, -2, -4, 35, + 24, -9, -19, 19, 17, 2, -13, 16, 5, -29, -48, -7, 4, 3, -7, 28, + 28, 2, -21, 13, 14, 9, -14, 11, 9, -15, -49, -17, -3, 6, -11, 20, + 30, 14, -23, 7, 12, 14, -11, 6, 10, -4, -46, -24, -10, 6, -8, 11, + 29, 24, -15, 0, 11, 14, -4, -2, 11, 3, -37, -36, -13, -3, -2, 2, + 28, 27, -2, -10, 14, 9, 7, -8, 13, 3, -21, -42, -14, -14, 4, -6, + 24, 24, 13, -16, 12, 3, 14, -8, 12, 4, -7, -44, -18, -20, 5, -6, + 18, 22, 23, -13, 6, 2, 13, -4, 5, 5, 1, -36, -26, -20, -1, -1, + 10, 23, 25, -3, -4, 5, 9, 5, -2, 8, 1, -24, -36, -18, -10, 4, + 1, 24, 23, 11, -9, 8, 4, 12, -7, 9, 1, -12, -40, -19, -16, 4, + -4, 21, 21, 16, -9, 6, 2, 13, -4, 6, 6, -4, -33, -24, -18, -2, + -2, 10, 21, 18, 0, -3, 3, 8, 6, -1, 8, 0, -18, -31, -19, -10, + 1, 0, 19, 20, 13, -5, 4, 5, 12, -4, 5, 2, -7, -34, -24, -17, + 1, -4, 13, 20, 21, -3, 2, 5, 14, 0, 2, 4, 0, -26, -28, -20, + -6, -4, 4, 18, 23, 6, -3, 5, 9, 7, -1, 6, 3, -14, -33, -22, + -14, -1, -1, 16, 22, 17, -4, 4, 4, 10, -2, 4, 3, -4, -30, -25, + -19, -2, -2, 11, 20, 23, 0, 0, 2, 10, 3, 1, 4, 1, -23, -30, + -22, -8, -1, 4, 19, 23, 10, -3, 4, 6, 8, -2, 5, 2, -13, -33, + -23, -15, 0, -1, 16, 21, 16, -3, 3, 4, 11, 0, 5, 6, -3, -27, + -25, -19, -4, -2, 9, 19, 19, 2, -3, 2, 8, 6, -1, 8, 0, 0, + 2, 33, 42, 58, 71, 79, 85, 88, 91, 94, 79, 95, 82, 106, 86, 105, + 47, 16, -6, 13, 44, 31, -15, -38, -36, 20, 70, 41, 48, 58, 24, -57, + -127, -119, -102, -126, -128, -111, -78, -82, -88, -87, -60, -66, -98, -104, -99, -97, + -99, -104, -101, -88, -87, -91, -61, -27, -34, -54, -55, -45, -24, -10, -5, -4, + 5, 34, 63, 101, 94, 78, 52, 51, 52, 74, 81, 77, 59, 46, 17, 7, + 39, 53, 47, 42, 66, 83, 73, 52, 28, 22, 11, 8, 11, 0, -15, -23, + -15, -14, -6, 16, 46, 62, 71, 76, 90, 102, 103, 103, 101, 100, 90, 75, + 63, 67, 49, 37, 28, 12, 5, 6, 15, 15, 8, -7, -12, -4, -10, -28, + -24, -17, -25, -50, -64, -81, -103, -116, -116, -113, -95, -72, -54, -41, -47, -65, + -65, -50, -33, -24, -7, 11, 8, -4, -13, -28, -51, -75, -90, -91, -90, -90, + -87, -88, -83, -84, -82, -81, -81, -76, -65, -71, -85, -84, -79, -83, -81, -77, + -72, -70, -65, -66, -66, -65, -66, -68, -61, -56, -51, -36, -13, -3, -5, -8, + -12, -12, 3, 16, 21, 31, 50, 69, 77, 82, 90, 102, 110, 114, 116, 117, + 118, 119, 116, 112, 109, 105, 98, 99, 103, 102, 91, 73, 64, 63, 61, 57, + 51, 40, 24, 35, 57, 75, 84, 79, 65, 37, 4, -26, -45, -57, -54, -46, + -45, -54, -67, -67, -48, -16, 15, 35, 44, 45, 44, 45, 46, 38, 23, 2, + -15, -34, -52, -60, -70, -77, -80, -79, -74, -77, -84, -86, -80, -72, -68, -72, + -80, -87, -92, -96, -101, -104, -104, -101, -93, -90, -89, -86, -85, -84, -83, -82, + -81, -79, -77, -76, -73, -71, -66, -62, -55, -39, -31, -27, -25, -31, -37, -46, + -51, -53, -54, -48, -45, -38, -20, 3, 24, 35, 39, 32, 16, 5, 3, 0, + -6, -13, -13, -11, -2, 14, 28, 40, 50, 53, 50, 55, 64, 74, 90, 105, + 108, 112, 106, 104, 109, 112, 123, 127, 127, 127, 127, 127, 127, 118, 113, 107, + 110, 114, 111, 104, 101, 101, 102, 103, 99, 99, 89, 73, 53, 35, 20, 0, + -22, -43, -63, -77, -82, -76, -65, -48, -36, -29, -24, -25, -29, -37, -40, -49, + -59, -67, -73, -76, -78, -79, -75, -73, -74, -75, -68, -52, -44, -30, -19, -9, + -6, -9, -13, -24, -33, -35, -31, -30, -35, -40, -44, -45, -51, -53, -54, -50, + -50, -47, -42, -50, -55, -54, -56, -56, -54, -54, -49, -48, -41, -32, -28, -18, + -13, -5, 6, 18, 33, 49, 60, 71, 78, 88, 95, 97, 93, 88, 91, 93, + 97, 98, 97, 94, 91, 85, 81, 72, 70, 66, 61, 60, 64, 66, 74, 83, + 92, 102, 108, 109, 107, 102, 97, 95, 91, 87, 80, 74, 67, 62, 61, 58, + 61, 61, 57, 53, 43, 35, 27, 25, 24, 20, 20, 22, 27, 34, 36, 32, + 21, 8, -3, -10, -16, -18, -16, -16, -19, -15, -11, -11, -12, -20, -34, -45, + -59, -72, -80, -89, -94, -95, -102, -111, -114, -111, -111, -108, -106, -104, -101, -98, + -93, -90, -86, -86, -83, -82, -81, -79, -76, -73, -70, -72, -78, -81, -79, -79, + -72, -60, -43, -31, -25, -27, -34, -37, -40, -42, -41, -39, -36, -34, -25, -12, + -4, 5, 12, 16, 17, 15, 13, 6, -4, -7, -8, -6, -1, 4, 7, 9, + 12, 16, 19, 19, 22, 28, 29, 28, 29, 30, 34, 40, 49, 57, 71, 78, + 85, 92, 96, 95, 89, 85, 86, 93, 99, 104, 102, 100, 94, 85, 77, 73, + 69, 66, 63, 60, 60, 59, 57, 52, 47, 41, 31, 18, 6, -3, -7, -11, + -12, -14, -18, -22, -23, -22, -24, -30, -37, -41, -44, -50, -56, -64, -67, -65, + -62, -58, -58, -58, -59, -61, -62, -66, -72, -78, -79, -77, -73, -68, -64, -61, + -56, -53, -54, -52, -52, -57, -63, -69, -70, -68, -65, -62, -59, -57, -56, -58, + -60, -61, -63, -64, -62, -61, -60, -58, -54, -49, -45, -42, -39, -36, -32, -28, + -22, -13, -7, -3, 2, 13, 28, 41, 52, 64, 71, 73, 73, 70, 64, 61, + 60, 64, 66, 65, 66, 64, 61, 60, 62, 65, 64, 66, 67, 67, 68, 66, + 64, 66, 68, 73, 76, 74, 72, 66, 58, 52, 46, 42, 38, 38, 41, 47, + 52, 52, 48, 45, 42, 40, 38, 34, 29, 27, 26, 28, 29, 28, 29, 30, + 31, 28, 24, 21, 19, 17, 14, 10, 6, 3, -4, -9, -15, -19, -26, -33, + -40, -49, -55, -60, -65, -70, -73, -72, -72, -71, -70, -71, -75, -78, -81, -83, + -86, -86, -85, -84, -82, -80, -77, -72, -69, -66, -63, -61, -61, -61, -61, -61, + -60, -58, -53, -48, -42, -36, -30, -28, -30, -32, -33, -32, -31, -28, -22, -18, + -10, -5, 0, 3, 6, 11, 16, 19, 22, 24, 26, 27, 29, 34, 40, 46, + 48, 48, 48, 45, 40, 36, 33, 31, 33, 35, 40, 48, 55, 62, 68, 73, + 76, 78, 78, 77, 79, 82, 85, 87, 87, 87, 86, 86, 86, 83, 78, 71, + 63, 55, 48, 44, 39, 36, 36, 36, 35, 32, 28, 24, 18, 13, 9, 6, + 4, 1, -2, -5, -11, -17, -20, -21, -20, -21, -24, -28, -32, -34, -33, -33, + -35, -37, -40, -43, -47, -52, -58, -63, -69, -74, -77, -80, -81, -82, -81, -80, + -77, -74, -69, -62, -54, -48, -48, -51, -54, -57, -57, -57, -56, -55, -55, -56, + -57, -56, -55, -54, -54, -54, -54, -52, -49, -45, -41, -38, -34, -31, -29, -27, + -24, -20, -17, -11, -7, -3, 0, 5, 10, 16, 22, 27, 31, 34, 38, 42, + 44, 45, 48, 50, 52, 57, 61, 64, 64, 65, 65, 63, 60, 57, 55, 55, + 58, 61, 63, 65, 67, 69, 71, 74, 77, 79, 79, 77, 74, 71, 68, 66, + 63, 60, 57, 55, 51, 46, 40, 36, 30, 25, 20, 17, 16, 17, 16, 14, + 12, 10, 7, 3, -1, -5, -11, -15, -17, -18, -18, -19, -21, -25, -29, -32, + -33, -33, -36, -39, -43, -46, -50, -53, -56, -58, -59, -60, -61, -62, -63, -65, + -66, -67, -68, -70, -72, -72, -70, -67, -63, -61, -60, -60, -58, -56, -54, -53, + -52, -52, -52, -51, -50, -49, -47, -45, -43, -40, -37, -35, -34, -32, -29, -25, + -21, -18, -14, -9, -4, 0, 4, 7, 11, 15, 18, 21, 25, 28, 33, 37, + 41, 44, 46, 47, 47, 46, 46, 45, 43, 42, 42, 43, 46, 48, 49, 50, + 52, 55, 59, 62, 65, 66, 67, 68, 69, 69, 70, 72, 74, 74, 73, 72, + 71, 69, 65, 61, 57, 53, 50, 46, 43, 38, 35, 32, 28, 23, 19, 17, + 17, 15, 13, 11, 9, 5, 1, -3, -6, -9, -12, -14, -17, -19, -23, -27, + -31, -35, -38, -40, -43, -46, -48, -52, -55, -57, -61, -64, -66, -67, -68, -69, + -70, -70, -70, -69, -69, -70, -71, -70, -66, -62, -59, -55, -52, -50, -46, -43, + -41, -38, -36, -35, -35, -34, -33, -33, -33, -33, -31, -30, -28, -26, -25, -24, + -21, -20, -20, -19, -19, -18, -17, -16, -15, -13, -11, -8, -3, 2, 9, 15, + 21, 27, 33, 38, 41, 45, 48, 51, 53, 55, 56, 56, 56, 56, 56, 56, + 56, 55, 57, 58, 60, 61, 62, 62, 64, 66, 68, 69, 71, 72, 73, 74, + 72, 70, 67, 63, 60, 57, 54, 50, 46, 41, 36, 31, 27, 23, 19, 16, + 14, 12, 11, 9, 8, 5, 2, -1, -4, -8, -10, -15, -18, -19, -20, -22, + -22, -23, -23, -24, -26, -29, -31, -33, -35, -36, -37, -38, -41, -44, -46, -48, + -50, -52, -54, -56, -59, -61, -63, -63, -64, -65, -64, -63, -62, -61, -60, -59, + -58, -57, -58, -57, -57, -55, -53, -50, -49, -47, -46, -43, -40, -37, -33, -31, + -28, -26, -23, -20, -16, -14, -12, -9, -5, -2, 1, 5, 9, 13, 17, 21, + 24, 26, 29, 32, 35, 37, 37, 38, 39, 41, 43, 44, 45, 46, 48, 50, + 51, 53, 52, 52, 50, 48, 47, 46, 46, 46, 46, 47, 48, 49, 51, 54, + 56, 58, 60, 61, 62, 62, 62, 61, 59, 57, 55, 54, 53, 52, 51, 49, + 46, 41, 36, 31, 27, 22, 18, 14, 11, 9, 6, 3, 0, -2, -5, -8, + -11, -16, -20, -25, -28, -31, -34, -37, -39, -41, -41, -42, -42, -42, -43, -45, + -46, -47, -49, -50, -52, -54, -56, -57, -58, -60, -61, -63, -64, -64, -64, -63, + -63, -61, -59, -58, -57, -55, -54, -53, -52, -52, -51, -50, -49, -47, -46, -45, + -44, -42, -40, -38, -35, -32, -30, -28, -25, -22, -19, -17, -15, -12, -9, -5, + -1, 3, 7, 11, 15, 19, 23, 25, 27, 30, 34, 36, 37, 38, 39, 40, + 42, 44, 45, 46, 47, 49, 50, 52, 53, 52, 51, 49, 47, 47, 46, 46, + 46, 47, 47, 48, 50, 52, 55, 57, 59, 61, 62, 62, 62, 61, 60, 58, + 56, 54, 54, 53, 51, 50, 47, 44, 39, 34, 29, 25, 20, 16, 13, 10, + 7, 4, 2, -1, -3, -6, -9, -14, -18, -22, -26, -30, -33, -35, -38, -40, + -41, -41, -42, -42, -43, -44, -46, -47, -48, -49, -51, -53, -55, -56, -57, -59, + -60, -62, -63, -64, -64, -63, -63, -62, -60, -59, -57, -56, -55, -53, -52, -52, + -51, -51, -50, -48, -46, -45, -44, -43, -41, -39, -36, -34, -31, -29, -26, -24, + -21, -16, -1, -2, -1, -3, 1, -2, -2, -4, 2, 6, 2, -2, -2, 0, + 7, 8, 4, -2, -2, 6, 5, 6, 0, -2, 5, 12, 10, 0, -5, -3, + 5, 10, 9, -7, -8, -7, 5, 8, 3, -9, -13, -5, 3, 5, -5, -9, + -4, 0, 6, 0, -4, -11, -7, 3, 4, 0, -5, 0, -1, 5, 1, 4, + -6, -5, -3, 12, 9, -2, -10, 4, 11, 8, -4, -5, -9, -6, 1, 19, + 13, -2, -22, 4, 9, 6, -26, -4, 3, 12, -9, 0, 2, 0, -15, 4, + 8, -8, -20, 0, 15, 8, -13, -2, -4, -4, -2, 12, 3, -14, -18, 1, + 21, 13, -9, -25, -8, 17, 15, 5, -14, -17, 5, 19, 13, -15, -17, -3, + 10, 20, 10, -27, -19, 5, 11, 12, 3, -13, -17, -1, 6, -3, -2, 1, + -1, -11, -17, 7, 7, -7, -7, -13, 9, 0, -5, 9, -5, -9, 6, 5, + -2, -16, -5, 15, 17, -10, -20, 1, 11, 14, -1, 1, 10, -11, -8, -1, + 18, 13, -2, -12, 1, -16, -2, 34, 27, -28, -42, -3, 42, 26, -14, -39, + -19, 7, 26, 25, -16, -55, -26, 32, 57, 4, -69, -48, 6, 75, 29, -51, + -67, -32, 51, 56, 7, -57, -75, 14, 63, 43, -29, -82, -27, 31, 56, 28, + -43, -81, -31, 59, 85, 1, -100, -59, 8, 102, 41, -42, -92, -52, 72, 79, + 29, -103, -85, -1, 117, 49, -54, -113, 7, 24, 94, -28, -39, -84, 39, 28, + 61, -44, -28, -67, 61, 23, 35, -40, -23, -37, 6, 38, 69, -42, -61, -53, + 58, 86, 2, -93, -24, 19, 72, 17, -19, -87, 45, 10, 64, -13, -45, -57, + 38, 48, 36, -51, -35, -37, 46, 26, 37, -73, -28, -12, 44, 22, 27, -84, + -22, 6, 70, 17, -24, -82, -7, 26, 79, 9, -63, -78, 6, 90, 68, -55, + -118, -3, 92, 62, -10, -73, -50, 14, 110, 15, -5, -118, 5, 69, 53, 22, + -81, -45, 29, 47, 80, -69, -28, -52, 58, 66, -1, -25, -59, -22, 107, 2, + 43, -108, -13, 20, 59, 56, -58, -66, -7, 34, 114, -42, -63, -50, 42, 69, + 44, -63, -37, -50, 114, 27, 18, -49, -81, 20, 74, 51, -14, -102, -4, 40, + 70, 38, -64, -73, 11, 60, 76, -41, -30, -78, 42, 46, 68, -63, -48, -56, + 89, 43, 28, -100, -53, 41, 60, 11, -6, -76, -16, 44, 52, 9, -67, -48, + 10, 69, 30, -1, -84, -4, 36, 72, -23, -22, -27, -33, 55, 74, -11, -86, + -1, 27, 36, 31, -7, -101, 49, 5, 66, -7, -46, -39, 9, 64, 44, -63, + -33, -22, 55, 23, 43, -79, -24, 5, 29, 54, -14, -59, -53, 63, 32, 20, + -34, -32, -36, 93, -2, 20, -35, -38, 18, 51, 61, -94, 15, -14, 17, 69, + 5, -87, 16, 28, 34, 1, 34, -57, -53, 118, -22, 34, -10, -71, 23, 70, + 25, -29, -7, -19, -3, 117, -33, -12, -21, -19, 43, 84, -38, -57, 33, 0, + 32, 41, -7, -103, 85, 2, 2, 58, -14, -103, 103, 7, -17, 34, -32, -59, + 71, 51, -78, 76, -65, -30, 63, 48, -66, 9, -11, -28, 52, 50, -72, -37, + 73, -61, 75, 7, -51, -44, 73, -3, -11, 40, -78, 7, 63, -15, -16, 30, + -53, 12, 38, 12, -42, 39, -63, 47, 23, 0, -23, -11, 8, -25, 60, -37, + -15, -3, -9, 12, 27, -14, -40, 22, 12, 14, 15, -31, -14, 15, 23, -12, + 14, -31, 19, 13, 32, -39, 27, -51, 43, 8, 0, 5, -26, 16, 4, 19, + -24, 17, -18, 6, -2, 49, -67, 39, -1, -30, 46, -13, -16, -9, 21, -17, + 27, 2, -34, 19, -3, 24, 8, -38, 13, -10, 22, 15, -34, 2, 4, -10, + 18, 14, -15, -15, 26, -12, 28, -21, 0, -6, 0, 7, 0, -15, 6, -2, + -18, 9, 8, -18, -15, 59, -94, 81, -40, -24, 14, -18, 25, -15, 4, -21, + -9, 24, -20, 3, 3, -52, 56, -29, 4, 5, -51, 45, -50, 73, -75, 13, + 17, -48, 38, -10, -16, 5, 4, -22, 3, 17, -27, -23, 42, -30, -5, 41, + -53, 10, 23, -28, 1, 29, -47, 9, 13, -3, -18, 9, -13, -11, 18, 12, + -53, 28, 1, -41, 41, 7, -61, 32, 0, -34, 16, 9, -74, 45, -23, -33, + 22, 39, -104, 49, 23, -96, 83, 5, -46, 36, -4, -45, 54, -25, -26, 21, + 2, -39, 51, -25, -25, 43, -22, -25, 30, -2, -32, 39, 14, -69, 42, 22, + -78, 60, 23, -83, 33, 44, -74, 19, 69, -113, 43, 53, -88, 51, 17, -74, + 42, 1, -38, 4, 39, -67, 12, 35, -39, -23, 73, -82, -5, 67, -71, -5, + 42, -36, -48, 78, -64, -4, 40, -48, -7, 50, -80, 17, 31, -56, 9, 6, + -18, -36, 43, -37, -29, 47, -47, -18, 33, -29, -27, 40, -30, -37, 51, -46, + -25, 61, -66, 7, 28, -48, 30, -15, -8, -6, 17, -14, -9, 26, -23, 4, + 9, -15, 12, -9, 16, -22, 7, 22, -51, 59, -29, -23, 54, -49, 6, 20, + -19, -11, 17, -3, -30, 32, -27, -5, 16, -28, 4, 4, -27, 32, -46, 27, + -18, -8, 11, -25, 18, -6, -17, 10, 1, -18, 24, -33, 10, 8, -12, -10, + 21, -19, 0, 8, -18, 14, 11, -44, 39, -22, -4, -6, 11, -15, -13, 17, + -17, -6, 13, -22, -1, 7, -5, -8, 0, 4, -24, 29, -23, 0, 20, -25, + -8, 30, -34, 31, -29, 11, -9, 21, -15, -1, 10, -9, -11, 32, -23, -2, + -14, 27, -19, 10, -4, -23, 14, 13, -45, 48, -44, 11, -4, -7, -3, 4, + -2, -34, -8, 37, -41, 20, -24, -4, -10, 2, 4, 12, -28, -30, 9, 32, + -16, 6, -46, -23, 60, 0, -22, -3, -23, -15, 48, 12, -34, -17, -18, 10, + 46, -1, -56, -8, 12, 9, 18, 13, -72, -3, 26, 9, 28, -14, -89, 15, + 67, -18, 1, -19, -52, 45, 26, -8, -5, -25, -25, 36, 38, -13, -36, -18, + -6, 55, 23, -51, -14, 4, 6, 25, 24, -41, -44, 38, 19, 10, 10, -59, + -14, 42, 1, 6, -8, -43, -1, 43, 10, -30, -10, -36, 18, 35, -20, -14, + -11, -19, 9, 20, -5, -22, -9, -6, 13, 26, -30, -23, 4, 1, 20, 9, + -20, -22, 3, -1, 17, 28, -26, -25, 16, -2, -4, 12, -10, -16, 24, -2, + -18, 17, -27, -1, 36, -6, -7, -4, -26, 6, 29, -3, -17, -6, -4, 18, + 18, -26, -10, -4, 6, 30, -1, -6, -24, 0, 24, 12, 2, -16, -25, 13, + 32, -3, -4, -3, -24, 15, 16, -7, 8, -20, -13, 36, 9, -24, -11, -10, + 10, 20, -1, -13, -10, -9, 20, 17, -12, -9, -15, 9, 20, -11, -14, -6, + 5, 10, 6, 5, -7, -11, 7, 19, 1, 3, -11, -10, 24, 14, -16, 2, + -9, 11, 14, 7, -1, -11, -4, 15, 24, 3, -24, -4, 4, 15, 13, -3, + -15, 0, 15, 8, 2, 0, -19, 16, 12, -1, 7, -13, -2, 18, 3, -3, + 5, -9, -10, 12, 9, -2, 8, -9, 4, 9, 6, 1, -8, 10, 4, -2, + 11, -14, 3, 5, 1, 9, 4, -15, 0, 10, 1, 5, -4, -10, 3, 7, + -1, 8, -13, 1, 4, 10, 6, -9, -3, 1, 6, 14, -3, -4, 4, -10, + 10, 13, -1, -4, 5, -3, 10, 13, -13, 4, 7, 1, 8, -1, 1, 4, + 5, 4, 11, -5, -2, 1, 8, 6, 1, 3, -1, -5, 11, 3, -3, 4, + -5, -1, 17, -4, -2, 6, -10, 10, 10, -4, 2, 3, -10, 10, 5, -2, + -2, -1, 4, 3, -1, -2, -4, 1, 6, -4, 6, -4, -10, 8, 2, -4, + 6, -4, -4, 12, -2, 2, 6, -9, 3, 2, 0, 7, -5, -3, 3, 2, + 4, -4, -2, 7, 3, 5, 9, -3, 1, 12, -3, 7, 6, -9, 4, 9, + -4, 12, 1, -7, 9, 2, 1, 10, -3, 1, 0, 0, 8, 0, -1, 5, + -2, 8, 1, -3, 10, 2, 0, 11, -4, -1, 6, -3, 2, 3, -5, 4, + 0, -5, 5, -3, 1, 3, 0, 4, -3, -3, 4, -2, -2, 5, -2, -1, + 6, -5, 2, 3, -4, 4, -2, -3, 11, -8, 0, 5, -1, 1, 0, -3, + 4, 2, 2, 6, -2, 4, 5, -3, 4, 7, -4, 11, -1, 0, 3, 0, + 3, 7, -2, 5, 1, 0, 6, 3, 2, 4, -1, 2, 6, 0, 3, 5, + -4, 6, 0, 2, 7, -4, -1, 2, -2, 7, 1, -1, 1, -2, 2, 4, + -5, 0, 4, -1, 2, -1, -2, 1, -2, 3, 2, -3, 3, -1, -4, 5, + -2, -2, 3, 0, -1, 2, -5, 2, 1, -4, 0, 1, -3, 5, -2, 2, + 2, -3, 1, 3, -2, 3, 1, -2, 4, 1, 2, 5, -2, 3, 1, 2, + 5, 0, -1, 4, 0, 1, 4, 2, 4, 4, -2, 0, 2, 3, 5, 0, + 0, 0, 1, 5, -2, -3, 4, 0, 1, 2, -2, -4, -4, -5, -6, -7, + -8, -9, -10, -11, -12, -13, -13, -14, -16, -18, -21, -25, -29, -34, -36, -38, + -39, -40, -42, -44, -47, -50, -53, -56, -58, -59, -58, -55, -50, -44, -38, -31, + -24, -18, -13, -9, -6, -3, 0, 3, 6, 9, 13, 17, 21, 27, 33, 42, + 53, 63, 74, 83, 91, 98, 104, 108, 111, 113, 115, 118, 119, 121, 123, 125, + 126, 127, 127, 127, 127, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, + 126, 125, 123, 121, 118, 114, 111, 107, 104, 101, 100, 99, 98, 98, 98, 98, + 98, 99, 98, 98, 97, 95, 92, 88, 81, 73, 63, 54, 46, 39, 33, 29, + 27, 25, 24, 22, 20, 18, 14, 10, 5, 0, -5, -8, -8, -7, -3, 2, + 8, 14, 19, 23, 26, 28, 29, 30, 31, 32, 32, 31, 30, 28, 24, 20, + 14, 9, 4, -1, -4, -7, -9, -10, -12, -13, -15, -17, -19, -22, -24, -25, + -25, -23, -21, -19, -17, -15, -15, -14, -15, -15, -16, -17, -17, -17, -16, -16, + -16, -17, -19, -22, -25, -30, -35, -39, -44, -47, -50, -53, -56, -58, -61, -63, + -64, -65, -65, -63, -60, -55, -49, -43, -38, -34, -32, -31, -31, -32, -33, -35, + -36, -37, -37, -36, -35, -34, -34, -34, -36, -39, -43, -49, -55, -61, -67, -72, + -77, -81, -85, -88, -90, -92, -94, -94, -95, -94, -94, -94, -94, -95, -96, -98, + -100, -102, -104, -105, -107, -108, -108, -109, -110, -110, -110, -109, -109, -109, -108, -108, + -109, -109, -109, -109, -108, -108, -107, -106, -106, -105, -105, -105, -105, -105, -105, -104, + -103, -101, -98, -93, -88, -82, -76, -70, -64, -58, -52, -47, -42, -38, -34, -31, + -29, -27, -25, -22, -18, -13, -7, -1, 6, 13, 20, 26, 32, 37, 41, 45, + 48, 51, 55, 58, 63, 68, 73, 77, 82, 85, 89, 91, 94, 96, 97, 98, + 99, 99, 99, 100, 100, 100, 101, 101, 101, 101, 101, 101, 99, 97, 95, 93, + 90, 87, 84, 81, 77, 73, 67, 60, 51, 40, 29, 17, 6, -5, -14, -23, + -31, -38, -45, -52, -58, -65, -70, -75, -80, -84, -87, -90, -92, -94, -95, -96, + -97, -98, -100, -101, -102, -102, -103, -103, -104, -104, -103, -102, -100, -97, -93, -89, + -86, -82, -79, -77, -75, -72, -70, -67, -63, -59, -53, -47, -40, -33, -26, -20, + -14, -9, -6, -3, 0, 3, 6, 9, 13, 17, 21, 26, 31, 37, 44, 51, + 58, 64, 70, 75, 79, 83, 86, 88, 90, 92, 93, 95, 96, 97, 98, 100, + 100, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 102, 102, + 102, 101, 100, 98, 96, 94, 92, 90, 89, 88, 88, 87, 87, 87, 87, 87, + 86, 85, 84, 82, 79, 76, 72, 67, 61, 55, 49, 43, 39, 35, 32, 30, + 29, 27, 25, 24, 21, 18, 15, 12, 8, 5, 3, 3, 4, 6, 9, 12, + 15, 18, 21, 23, 25, 27, 28, 30, 31, 31, 31, 30, 28, 25, 22, 18, + 14, 10, 7, 5, 3, 1, 0, -2, -4, -6, -9, -11, -14, -16, -17, -17, + -16, -14, -12, -11, -9, -9, -9, -10, -11, -12, -13, -14, -15, -15, -16, -16, + -17, -19, -22, -26, -30, -34, -38, -42, -45, -48, -50, -52, -53, -54, -55, -56, + -56, -55, -53, -50, -46, -42, -38, -35, -32, -31, -30, -31, -31, -33, -34, -35, + -36, -36, -36, -35, -35, -35, -36, -38, -41, -45, -49, -54, -59, -64, -68, -73, + -76, -80, -83, -86, -88, -89, -90, -91, -91, -91, -92, -92, -93, -95, -96, -98, + -100, -101, -102, -103, -104, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -104, -104, -103, -102, -102, -101, -100, -100, -100, -99, -99, -99, -98, -96, + -94, -91, -86, -82, -76, -71, -65, -59, -53, -48, -42, -37, -32, -28, -25, -22, + -19, -16, -13, -8, -3, 3, 9, 16, 22, 28, 35, 40, 45, 49, 53, 56, + 60, 63, 67, 71, 76, 80, 85, 88, 92, 94, 97, 99, 100, 102, 103, 103, + 104, 104, 104, 104, 105, 105, 105, 105, 105, 104, 103, 101, 99, 97, 94, 91, + 87, 84, 80, 76, 71, 65, 57, 48, 39, 28, 18, 8, -2, -11, -19, -27, + -34, -41, -47, -54, -60, -65, -70, -75, -79, -82, -85, -87, -89, -91, -92, -94, + -95, -96, -97, -98, -99, -100, -100, -100, -100, -100, -98, -96, -94, -90, -87, -84, + -81, -78, -76, -73, -71, -68, -65, -61, -57, -52, -46, -40, -33, -27, -21, -15, + -11, -7, -4, 0, 3, 7, 11, 15, 20, 24, 29, 35, 41, 48, 54, 61, + 67, 72, 77, 81, 85, 88, 90, 92, 94, 95, 97, 98, 99, 101, 102, 103, + 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, + 104, 103, 101, 99, 98, 96, 95, 93, 93, 92, 92, 91, 91, 90, 90, 88, + 87, 86, 84, 81, 78, 74, 69, 64, 59, 54, 49, 45, 42, 39, 37, 35, + 33, 31, 29, 27, 24, 21, 18, 15, 13, 11, 11, 12, 13, 15, 17, 20, + 22, 24, 25, 27, 28, 29, 30, 31, 31, 31, 30, 28, 26, 23, 20, 17, + 14, 11, 9, 8, 6, 5, 3, 1, -1, -4, -6, -8, -10, -11, -11, -11, + -10, -9, -8, -8, -8, -9, -10, -11, -13, -14, -15, -16, -17, -17, -18, -20, + -22, -25, -28, -31, -35, -38, -41, -44, -46, -47, -49, -50, -51, -52, -52, -52, + -51, -49, -47, -44, -40, -38, -35, -33, -33, -32, -33, -33, -34, -35, -36, -37, + -38, -38, -38, -38, -39, -40, -42, -45, -49, -53, -57, -61, -65, -69, -73, -76, + -79, -82, -85, -87, -88, -89, -90, -91, -91, -92, -93, -94, -95, -97, -98, -99, + -100, -101, -102, -103, -103, -104, -104, -104, -104, -104, -104, -104, -104, -104, -103, -103, + -103, -102, -102, -101, -100, -99, -99, -98, -97, -97, -96, -96, -95, -94, -92, -89, + -86, -82, -77, -72, -67, -61, -56, -50, -45, -39, -34, -29, -25, -21, -18, -14, + -11, -5, 4, 8, 14, 19, 25, 31, 37, 42, 47, 52, 57, 61, 65, 69, + 72, 76, 79, 83, 86, 89, 92, 95, 97, 99, 101, 102, 104, 104, 105, 106, + 106, 106, 106, 106, 106, 105, 104, 104, 103, 101, 99, 97, 95, 92, 89, 85, + 81, 77, 73, 68, 62, 57, 50, 43, 35, 28, 19, 12, 4, -4, -11, -18, + -25, -32, -38, -44, -50, -55, -61, -65, -69, -73, -77, -80, -82, -85, -87, -89, + -91, -92, -93, -95, -95, -96, -97, -97, -97, -96, -96, -95, -93, -92, -90, -88, + -86, -84, -82, -79, -77, -74, -71, -68, -64, -60, -55, -51, -46, -41, -36, -31, + -26, -21, -16, -11, -7, -2, 3, 8, 14, 19, 25, 30, 36, 42, 47, 53, + 58, 63, 68, 72, 76, 79, 82, 85, 87, 89, 91, 93, 95, 96, 98, 99, + 101, 102, 103, 103, 104, 105, 105, 105, 106, 106, 106, 106, 106, 106, 106, 105, + 105, 105, 104, 103, 103, 102, 101, 100, 99, 99, 98, 97, 96, 95, 93, 92, + 91, 89, 87, 85, 82, 79, 76, 73, 70, 67, 63, 60, 58, 55, 53, 50, + 48, 46, 44, 41, 39, 37, 34, 32, 31, 29, 28, 28, 27, 28, 28, 28, + 28, 29, 29, 29, 29, 30, 30, 30, 29, 29, 28, 27, 26, 25, 23, 22, + 20, 19, 17, 16, 15, 13, 12, 10, 8, 6, 4, 2, 1, -1, -2, -4, + -5, -6, -7, -9, -10, -12, -13, -15, -17, -19, -21, -22, -24, -26, -27, -29, + -31, -32, -34, -36, -38, -40, -42, -43, -45, -46, -47, -47, -48, -48, -49, -49, + -48, -48, -47, -46, -45, -44, -44, -43, -43, -43, -44, -44, -45, -46, -47, -48, + -49, -50, -51, -52, -53, -55, -57, -59, -61, -64, -67, -70, -72, -75, -78, -80, + -82, -84, -86, -88, -90, -91, -92, -94, -95, -96, -97, -98, -98, -99, -100, -101, + -101, -101, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -101, -101, -100, -100, + -99, -98, -97, -96, -95, -94, -93, -92, -91, -89, -88, -87, -85, -83, -81, -78, + -75, -71, -67, -63, -58, -54, -49, -44, -39, -33, -28, -23, -18, -13, -8, -3, + 2, 7, 13, 18, 23, 29, 35, 40, 45, 51, 55, 60, 64, 68, 71, 75, + 78, 82, 85, 88, 91, 93, 96, 98, 100, 101, 103, 104, 105, 105, 106, 106, + 106, 106, 105, 105, 104, 104, 103, 101, 100, 98, 95, 93, 90, 86, 83, 79, + 75, 70, 65, 60, 54, 47, 40, 33, 25, 18, 10, 2, -5, -12, -19, -26, + -32, -38, -44, -50, -55, -60, -65, -69, -73, -76, -79, -82, -84, -87, -89, -90, + -92, -93, -94, -95, -96, -96, -96, -96, -96, -95, -94, -93, -91, -90, -88, -86, + -84, -81, -79, -76, -74, -70, -67, -63, -59, -54, -49, -44, -39, -34, -29, -24, + -19, -14, -10, -5, -2, -1, 3, -2, 1, -3, 4, -2, 0, 0, 8, 0, + 10, -9, -7, -128, -72, 13, -44, -13, -18, 4, -4, 12, 3, 31, 4, 66, + 74, 38, 38, 36, 30, 25, 22, 18, 13, 7, 5, 2, 1, -5, -7, -9, + -9, -11, -14, -12, -14, -12, -16, -13, -16, -13, -14, -16, -11, -14, -10, -13, + -11, -13, -8, -8, -6, -6, -5, 0, -6, -3, -3, 3, -4, 6, -13, 17, + -5, -5, 15, -1, -23, 6, 23, 28, 35, 13, 41, -3, 24, 25, -4, 6, + 30, 4, 18, 10, -32, -64, -120, -64, -91, -76, -33, -45, -58, 2, 1, -19, + -14, 18, 48, 50, 59, 51, 53, 47, 46, 41, 37, 35, 26, 28, 19, 21, + 10, 13, 9, 3, 5, -4, 2, -5, -3, -8, -5, -8, -8, -10, -9, -10, + -10, -12, -7, -17, -8, -11, -14, -5, -15, -5, -4, -10, -13, 11, -22, 3, + -3, -4, -5, -11, 13, 2, -16, -9, -5, -12, 27, 15, 17, 21, 20, 20, + 8, 14, 13, 0, 10, 35, 10, -1, -12, -52, -89, -78, -58, -85, -74, -51, + -25, -25, -28, -30, -14, 12, 29, 44, 44, 51, 46, 50, 49, 43, 38, 36, + 32, 29, 23, 19, 17, 14, 10, 6, 6, 2, 4, -8, 3, -7, -3, -6, + -7, -11, -4, -12, -7, -6, -20, 1, -15, -14, -8, -7, -10, -10, -10, 2, + -14, -12, 7, -10, -8, -5, -6, 1, 6, -2, -12, -19, -3, 3, 2, 19, + 19, 14, 19, 24, 13, 5, 12, 12, 13, 21, 29, 5, -18, -43, -48, -64, + -82, -82, -71, -44, -37, -37, -40, -33, -23, 5, 20, 33, 38, 45, 48, 51, + 46, 44, 41, 38, 36, 27, 26, 24, 19, 13, 16, 5, 11, 4, -1, 3, + -4, -3, 1, -9, -7, -2, -9, -6, -13, -4, -6, -17, -8, -6, -15, -10, + -5, -10, -8, -10, -5, -7, -5, -2, -14, -10, 3, 5, -4, -3, -10, -17, + -10, 3, 4, 5, 18, 18, 18, 16, 16, 10, 5, 11, 23, 26, 22, 7, + -9, -16, -37, -62, -80, -76, -65, -46, -43, -43, -51, -41, -24, -4, 11, 24, + 32, 41, 47, 43, 49, 45, 41, 40, 33, 31, 31, 20, 23, 18, 11, 16, + 9, 5, 3, 2, 5, -2, -7, 2, -4, -10, -3, -5, -8, -10, -7, -8, + -14, -10, -8, -11, -9, -6, -14, -10, -2, -3, -12, -10, -7, -9, 0, 6, + -1, -11, -12, -11, -10, -7, 4, 7, 12, 17, 20, 18, 13, 6, 8, 19, + 22, 24, 17, 14, 5, -8, -29, -54, -77, -71, -55, -50, -44, -54, -57, -39, + -32, -15, 3, 15, 31, 34, 39, 47, 45, 44, 44, 37, 37, 33, 28, 27, + 18, 20, 21, 10, 7, 10, 7, 1, 2, 2, 0, -5, 0, -2, -7, -3, + -5, -8, -8, -5, -13, -13, -5, -6, -14, -11, -8, -8, -5, -5, -9, -17, + -10, -2, 0, -2, -1, -9, -12, -14, -12, -6, -1, 3, 11, 19, 19, 14, + 7, 9, 13, 17, 23, 22, 19, 21, 12, 2, -21, -55, -65, -59, -52, -47, + -56, -56, -50, -53, -38, -22, -7, 10, 18, 29, 36, 40, 45, 43, 38, 41, + 40, 32, 27, 26, 26, 19, 17, 17, 12, 9, 9, 6, 2, 4, 4, -1, + -2, 2, -3, -3, 0, -2, -8, -9, -7, -7, -7, -6, -8, -12, -6, -4, + -7, -12, -13, -10, -5, -2, -2, -3, -8, -12, -15, -16, -14, -13, -7, 2, + 8, 11, 8, 4, 5, 8, 13, 20, 22, 23, 24, 23, 19, 6, -13, -23, + -29, -32, -37, -42, -46, -53, -57, -53, -49, -39, -25, -12, -1, 10, 21, 28, + 32, 35, 36, 34, 34, 32, 28, 25, 24, 21, 18, 19, 16, 10, 7, 8, + 9, 8, 6, 5, 2, 3, 6, 7, 5, 2, -2, -4, -3, -1, -3, -4, + -3, -1, -3, -8, -13, -14, -11, -4, -1, -2, -4, -6, -11, -16, -19, -21, + -21, -17, -9, -3, 0, 0, -3, -5, -2, 4, 11, 18, 23, 25, 26, 24, + 17, 10, 5, -1, -7, -12, -20, -29, -37, -44, -51, -55, -54, -47, -39, -28, + -16, -4, 9, 18, 23, 27, 31, 31, 30, 30, 28, 23, 20, 22, 23, 20, + 14, 10, 9, 9, 10, 9, 6, 4, 4, 6, 9, 10, 7, 2, 0, 1, + -1, -2, -2, -1, 1, 2, -2, -10, -14, -11, -8, -5, -2, -1, -3, -6, + -9, -14, -20, -23, -23, -18, -11, -5, -3, -4, -6, -8, -4, 2, 7, 14, + 21, 25, 25, 23, 19, 13, 8, 4, -1, -9, -15, -23, -31, -39, -48, -53, + -51, -48, -44, -34, -20, -8, 3, 12, 20, 24, 27, 30, 31, 29, 24, 22, + 22, 23, 22, 18, 13, 10, 10, 11, 11, 9, 5, 3, 5, 10, 11, 9, + 7, 5, 4, 2, 0, -3, -1, 3, 5, 2, -3, -8, -11, -10, -7, -5, + -3, -2, -2, -4, -7, -14, -20, -24, -24, -19, -12, -6, -6, -8, -8, -8, + -7, -2, 5, 12, 19, 23, 24, 22, 20, 16, 12, 7, 1, -5, -10, -17, + -27, -36, -42, -47, -52, -51, -45, -36, -26, -12, 0, 9, 15, 21, 27, 30, + 29, 26, 23, 22, 23, 23, 21, 17, 12, 9, 10, 12, 10, 6, 3, 4, + 7, 10, 11, 9, 8, 9, 7, 2, -1, 0, 2, 6, 6, 3, -2, -7, + -9, -8, -6, -4, -3, -1, -1, -2, -6, -13, -21, -26, -24, -18, -13, -10, + -9, -10, -11, -11, -10, -5, 3, 10, 17, 21, 22, 22, 21, 19, 14, 8, + 5, 1, -7, -14, -21, -29, -38, -45, -49, -50, -48, -40, -28, -16, -6, 3, + 11, 19, 26, 27, 26, 24, 22, 22, 24, 24, 20, 14, 11, 11, 12, 11, + 8, 4, 3, 6, 8, 9, 9, 10, 11, 10, 6, 2, 0, 2, 5, 8, + 7, 3, -2, -5, -6, -7, -6, -4, -3, -1, 1, 1, -5, -13, -21, -24, + -23, -18, -14, -12, -11, -12, -13, -14, -13, -8, 0, 8, 14, 17, 21, 22, + 21, 18, 15, 12, 8, 2, -3, -9, -16, -24, -32, -40, -47, -51, -49, -41, + -30, -21, -12, -1, 9, 17, 23, 25, 24, 21, 21, 24, 24, 22, 17, 12, + 11, 13, 12, 8, 4, 3, 4, 6, 7, 7, 9, 11, 12, 10, 6, 3, + 3, 6, 9, 10, 8, 5, 1, -2, -3, -3, -2, -1, 1, 3, 3, 1, + -5, -12, -18, -20, -20, -18, -16, -16, -16, -17, -19, -20, -17, -11, -5, 1, + 8, 13, 17, 18, 18, 17, 16, 14, 11, 7, 2, -3, -8, -14, -22, -34, + -43, -46, -42, -35, -28, -20, -11, -2, 7, 15, 19, 19, 19, 19, 20, 20, + 17, 14, 11, 10, 9, 7, 1, -4, -6, -4, 0, 2, 4, 6, 7, 8, + 9, 8, 7, 7, 10, 13, 15, 15, 13, 9, 6, 3, 2, 4, 7, 9, + 11, 11, 7, 1, -5, -10, -13, -14, -14, -14, -16, -19, -23, -26, -28, -27, + -23, -18, -13, -7, -1, 6, 11, 14, 15, 14, 14, 15, 15, 12, 7, 2, + -1, -4, -11, -22, -34, -41, -40, -34, -26, -19, -12, -4, 4, 10, 14, 17, + 17, 18, 19, 18, 15, 12, 10, 9, 8, 6, 0, -6, -11, -10, -6, -1, + 3, 5, 6, 6, 6, 7, 7, 8, 10, 13, 16, 18, 17, 13, 9, 5, + 3, 4, 7, 11, 13, 14, 11, 5, -2, -7, -11, -12, -12, -13, -14, -17, + -22, -26, -28, -29, -27, -22, -17, -11, -5, 1, 7, 12, 14, 14, 13, 14, + 15, 14, 11, 5, 0, -2, -6, -15, -27, -37, -42, -38, -31, -24, -17, -9, + -1, 6, 12, 15, 17, 18, 19, 19, 17, 13, 11, 9, 9, 8, 4, -2, + -8, -11, -9, -4, 1, 4, 5, 6, 6, 6, 7, 7, 9, 11, 14, 17, + 18, 16, 12, 8, 4, 3, 5, 9, 12, 14, 13, 9, 2, -4, -9, -12, + -13, -12, -13, -15, -19, -23, -27, -29, -28, -25, -20, -15, -9, -3, 3, 9, + 13, 15, 14, 13, 15, 15, 13, 9, 3, -1, -3, -9, -19, -31, -40, -41, + -36, -28, -21, -14, -6, 2, 9, 13, 16, 17, 18, 19, 18, 16, 12, 10, + 9, 9, 7, 2, -4, -10, -11, -8, -2, 2, 5, 5, 6, 6, 7, 7, + 8, 9, 12, 16, 18, 17, 14, 10, 6, 4, 4, 6, 10, 13, 14, 12, + 7, 0, -6, -10, -12, -13, -13, -14, -16, -21, -25, -28, -29, -28, -24, -18, + -13, -7, -1, 6, 11, 14, 15, 13, 14, 15, 15, 12, 7, 2, -1, -5, + -12, -23, -35, -41, -40, -34, -26, -19, -12, -3, 4, 10, 14, 17, 18, 18, + 19, 18, 14, 11, 9, 9, 8, 6, 0, -7, -11, -10, -6, 0, 2, -1, + -2, -9, -24, 4, -3, 3, -3, 10, 7, 4, 13, -4, 1, 3, 3, 0, + 2, 8, -9, -9, 2, 1, -1, 7, 17, 21, 37, 25, 13, 14, -2, 15, + 20, 5, 0, -3, -7, -27, -14, -18, -19, -29, -20, -4, -18, -32, -30, -30, + -29, -32, -22, -26, -19, -19, -1, -6, 4, 7, 5, 2, 0, -8, -16, -12, + -13, -17, -17, 19, 20, 24, 16, 8, -4, 8, 0, 13, 28, 33, 16, 11, + 5, -3, -1, 4, 12, 12, 40, 20, 11, 4, 5, 8, -1, 2, 5, 5, + 22, 13, 21, 8, 9, 18, 20, 13, 20, 26, 11, 24, 17, 10, 27, 30, + 22, 28, 30, 41, 47, 57, 36, 36, 20, -16, 4, 6, -19, -21, -41, -39, + -33, -38, -41, -46, -42, -36, -18, -37, -65, -75, -77, -78, -62, -63, -62, -68, + -63, -63, -44, -50, -30, -41, -43, -26, -34, -35, -36, -45, -49, -27, 1, -6, + -4, -7, -20, -16, -20, -21, -13, 2, -6, -1, -12, 0, -1, 15, 19, 20, + 26, 37, 40, 46, 37, 50, 35, 34, 41, 43, 51, 54, 55, 50, 56, 47, + 59, 51, 51, 75, 67, 66, 71, 59, 60, 72, 75, 72, 80, 79, 82, 98, + 99, 87, 93, 62, 49, 58, 41, 42, 28, 5, -6, -6, -18, -24, -23, -30, + -25, -20, -38, -60, -75, -77, -80, -75, -71, -75, -70, -73, -69, -76, -60, -66, + -71, -66, -57, -62, -61, -61, -87, -90, -69, -63, -46, -31, -35, -47, -42, -53, + -63, -53, -45, -33, -36, -39, -37, -43, -39, -34, -30, -19, -9, 2, -9, -1, + -3, 1, -3, 5, 7, 15, 24, 22, 23, 20, 32, 43, 33, 48, 63, 67, + 70, 68, 52, 59, 73, 73, 77, 85, 73, 81, 103, 98, 116, 115, 87, 80, + 76, 72, 69, 60, 37, 27, 29, 12, 19, 4, -12, 1, 3, -3, -31, -42, + -57, -67, -67, -61, -61, -61, -48, -58, -51, -41, -46, -48, -40, -35, -33, -26, + -36, -67, -68, -65, -59, -47, -28, -34, -37, -36, -52, -61, -61, -47, -34, -39, + -39, -42, -42, -48, -36, -38, -37, -20, -19, -16, -16, -18, -20, -22, -26, -22, + -16, -15, 1, -4, -6, 10, 12, 13, 22, 32, 41, 54, 52, 44, 54, 66, + 61, 78, 81, 71, 87, 89, 99, 119, 107, 91, 77, 76, 69, 76, 68, 47, + 49, 35, 33, 37, 22, 14, 24, 37, 26, 13, -10, -26, -41, -43, -34, -40, + -34, -33, -43, -39, -25, -27, -27, -18, -25, -15, -1, -10, -29, -42, -39, -39, + -19, -7, -10, -10, -11, -20, -35, -44, -33, -30, -28, -36, -34, -47, -41, -36, + -46, -42, -34, -27, -29, -25, -34, -30, -32, -40, -36, -36, -31, -16, -25, -25, + -15, -21, -14, -9, -11, 1, 17, 15, 9, 25, 20, 25, 46, 39, 46, 50, + 51, 68, 85, 87, 72, 65, 52, 50, 59, 44, 42, 29, 23, 22, 23, 11, + -5, 8, 14, 19, 8, -6, -23, -38, -43, -42, -48, -41, -34, -42, -38, -19, + -23, -16, -15, -19, -10, 8, 8, -9, -18, -27, -30, -10, -4, 7, 6, 15, + 8, -8, -17, -15, -8, -11, -3, -15, -17, -14, -16, -27, -30, -26, -22, -19, + -21, -22, -19, -30, -27, -26, -36, -22, -9, -13, -10, -10, -8, -9, -6, -12, + -1, 16, 6, 11, 16, 6, 19, 24, 27, 38, 38, 38, 48, 71, 72, 78, + 66, 51, 54, 52, 49, 42, 32, 21, 25, 26, 13, 1, -1, 10, 15, 8, + 1, -22, -38, -47, -56, -58, -46, -43, -46, -33, -25, -17, -11, -9, -19, -9, + 16, 18, 12, 1, -17, -18, -9, 3, 9, 17, 24, 26, 9, -4, -1, -6, + 2, 9, 0, -2, 2, -3, -13, -16, -15, -8, -8, -8, -1, -6, -17, -11, + -22, -24, -16, -12, -9, -9, -9, -9, -6, -8, -16, 2, 6, 2, 13, 9, + 7, 10, 17, 19, 30, 31, 22, 37, 49, 61, 70, 56, 43, 37, 36, 31, + 32, 15, 4, 11, 9, 4, -14, -16, -7, -5, -1, -8, -28, -46, -56, -75, + -74, -67, -70, -67, -62, -55, -47, -36, -32, -42, -28, -9, 1, 4, -4, -17, + -30, -18, -12, -2, 4, 15, 21, 7, 1, -7, -6, -1, 7, 0, 0, 3, + -3, -8, -15, -18, -6, -9, -6, 5, -2, -2, 0, -7, -12, -7, -3, 2, + 7, 3, 4, 14, 2, 1, 12, 11, 17, 20, 19, 16, 19, 20, 24, 39, + 36, 37, 42, 55, 71, 84, 76, 63, 56, 47, 49, 46, 29, 18, 14, 18, + 11, -5, -11, -8, -3, 4, 4, -16, -27, -44, -60, -64, -59, -62, -62, -55, + -55, -47, -28, -32, -35, -29, -15, -3, 4, 3, -15, -25, -24, -13, -11, -3, + 10, 14, 12, 4, -5, -9, -1, 2, -1, 1, 1, -1, -7, -17, -16, -12, + -17, -8, 0, -1, -1, -2, -8, -13, -9, -9, 0, 9, 1, 14, 16, 6, + 7, 10, 12, 18, 26, 20, 22, 22, 16, 25, 32, 36, 34, 36, 43, 60, + 75, 72, 67, 52, 44, 50, 45, 38, 17, 14, 17, 11, -2, -9, -14, -10, + 0, -4, -12, -24, -41, -59, -67, -63, -70, -69, -62, -70, -55, -40, -38, -42, + -38, -29, -16, -3, -3, -9, -29, -31, -25, -26, -20, -7, 0, 2, -1, -14, + -18, -14, -14, -12, -10, -10, -4, -13, -21, -19, -22, -24, -16, -10, -6, -2, + -2, -10, -12, -15, -17, -4, -4, -5, 7, 9, 3, 4, 7, 5, 18, 23, + 22, 28, 25, 22, 27, 34, 39, 43, 38, 41, 62, 71, 79, 78, 62, 55, + 55, 57, 49, 31, 23, 30, 21, 15, 7, -5, 1, 8, 9, 8, -3, -16, + -39, -46, -50, -60, -55, -58, -62, -53, -36, -33, -34, -34, -29, -18, -6, 5, + -2, -17, -23, -22, -24, -17, -8, 1, 9, 10, -4, -7, -8, -9, -6, -9, + -6, 0, -11, -14, -14, -21, -24, -21, -16, -10, 1, -3, -3, -5, -14, -11, + -7, -7, -5, 6, 9, 4, 8, 1, 3, 11, 16, 20, 26, 24, 20, 25, + 29, 36, 41, 32, 40, 51, 64, 77, 78, 67, 55, 54, 57, 53, 33, 27, + 25, 22, 20, 9, -3, -3, 3, 7, 6, 4, -16, -32, -42, -55, -60, -61, + -64, -70, -62, -49, -39, -41, -40, -37, -33, -18, -5, -8, -16, -24, -29, -31, + -28, -24, -15, -1, 1, -7, -11, -14, -13, -14, -18, -11, -8, -14, -16, -16, + -25, -31, -29, -31, -20, -12, -13, -6, -11, -19, -19, -14, -17, -12, -1, 2, + 6, 7, 2, 4, 8, 11, 18, 24, 21, 22, 19, 21, 33, 33, 32, 32, + 40, 55, 71, 76, 72, 58, 55, 62, 56, 42, 34, 28, 29, 26, 17, 4, + 2, 6, 4, 13, 12, -4, -18, -30, -45, -50, -51, -59, -63, -61, -47, -37, + -33, -32, -34, -32, -19, -4, -3, -5, -13, -21, -23, -22, -24, -13, 1, 5, + 5, -3, -6, -1, -7, -9, -2, 1, -2, -2, -4, -13, -16, -22, -22, -15, + -10, -4, 2, -1, -11, -8, -7, -12, -6, 1, 6, 12, 11, 8, 9, 9, + 9, 20, 23, 26, 25, 20, 24, 32, 34, 35, 33, 35, 49, 63, 74, 74, + 58, 55, 60, 54, 45, 33, 27, 25, 26, 19, 6, 4, 1, 1, 9, 12, + -1, -10, -26, -43, -50, -54, -61, -70, -69, -61, -50, -43, -40, -44, -44, -34, + -18, -12, -9, -15, -24, -25, -28, -31, -22, -12, -2, 1, -8, -8, -5, -12, + -14, -8, -8, -8, -5, -9, -11, -18, -27, -26, -22, -19, -12, -1, -4, -9, + -8, -11, -14, -12, -8, 0, 7, 5, 5, 6, 0, 3, 8, 13, 20, 18, + 13, 15, 22, 27, 29, 25, 26, 36, 51, 70, 71, 59, 56, 57, 55, 47, + 37, 25, 24, 27, 17, 9, 3, -2, -2, 8, 9, 6, -2, -16, -34, -44, + -47, -54, -63, -66, -63, -55, -44, -39, -42, -44, -35, -23, -11, -4, -10, -16, + -17, -23, -25, -22, -13, 1, 6, 1, 1, 4, -2, -4, 1, -1, 4, 3, + 2, 2, -3, -12, -15, -14, -15, -7, 3, 5, 3, 2, 1, -2, -4, -4, + 3, 9, 10, 13, 11, 9, 8, 9, 15, 22, 22, 20, 19, 21, 27, 30, + 28, 28, 28, 42, 61, 69, 65, 60, 60, 58, 55, 47, 35, 30, 30, 24, + 18, 10, 0, -1, 2, 6, 7, 3, -8, -24, -36, -43, -50, -59, -65, -66, + -62, -52, -43, -43, -44, -41, -35, -21, -12, -12, -13, -17, -23, -26, -30, -24, + -12, -4, -5, -3, -2, -5, -6, -6, -5, -3, -2, -1, 2, 2, -5, -3, + 2, 8, 17, 26, 32, 42, 50, 56, 68, 73, 64, 63, 65, 48, 56, 71, + 48, 49, 50, 26, 30, 30, 16, 25, 21, -2, 0, -13, -15, -2, -19, -17, + -16, -50, -49, -49, -81, -85, -88, -108, -112, -116, -127, -126, -113, -113, -106, -79, + -65, -48, -17, 5, 20, 41, 58, 63, 69, 59, 28, 17, 0, -32, -41, -52, + -69, -63, -61, -59, -41, -26, -19, 6, 28, 33, 52, 67, 70, 81, 87, 84, + 90, 93, 84, 72, 69, 60, 45, 56, 57, 40, 46, 39, 25, 29, 25, 16, + 21, 12, -1, -3, -11, -8, -5, -16, -12, -21, -41, -38, -48, -68, -70, -77, + -91, -93, -98, -106, -103, -93, -92, -82, -60, -47, -30, -4, 13, 27, 44, 56, + 60, 62, 47, 23, 13, -8, -32, -40, -54, -64, -59, -59, -53, -36, -26, -14, + 12, 27, 36, 56, 66, 72, 84, 86, 86, 93, 92, 82, 73, 70, 57, 49, + 59, 52, 43, 47, 37, 29, 30, 24, 18, 18, 7, -2, -6, -11, -7, -10, + -16, -14, -29, -42, -42, -57, -71, -73, -83, -93, -96, -102, -107, -101, -93, -90, + -75, -55, -41, -22, 3, 19, 33, 50, 59, 61, 60, 41, 21, 10, -14, -33, + -43, -57, -63, -60, -61, -51, -36, -27, -9, 15, 26, 40, 59, 66, 74, 85, + 85, 88, 94, 90, 80, 75, 69, 56, 54, 60, 50, 47, 46, 36, 31, 30, + 23, 19, 15, 4, -3, -7, -10, -9, -14, -17, -19, -35, -44, -47, -63, -73, + -77, -88, -96, -98, -104, -107, -99, -92, -86, -69, -50, -35, -14, 9, 24, 38, + 54, 60, 61, 56, 36, 19, 4, -20, -35, -46, -60, -62, -61, -60, -48, -35, + -25, -3, 17, 27, 45, 60, 66, 77, 85, 86, 91, 94, 88, 80, 75, 67, + 56, 58, 59, 50, 49, 45, 36, 33, 30, 23, 19, 13, 2, -5, -8, -10, + -11, -16, -18, -25, -40, -45, -53, -68, -76, -81, -91, -97, -100, -106, -106, -97, + -90, -81, -63, -44, -28, -6, 15, 28, 44, 57, 61, 61, 52, 31, 16, -1, + -24, -37, -50, -61, -62, -62, -59, -46, -35, -22, 1, 18, 30, 48, 61, 68, + 79, 85, 87, 92, 93, 86, 80, 75, 66, 58, 60, 58, 51, 50, 44, 37, + 33, 29, 23, 17, 10, 0, -6, -9, -10, -14, -18, -21, -31, -43, -48, -59, + -72, -78, -85, -94, -99, -102, -107, -104, -95, -88, -76, -56, -39, -22, 2, 20, + 33, 49, 59, 61, 60, 47, 27, 12, -7, -27, -40, -53, -62, -62, -63, -57, + -44, -34, -18, 5, 19, 33, 51, 61, 70, 81, 85, 88, 94, 92, 85, 80, + 74, 65, 60, 62, 57, 52, 50, 43, 37, 33, 28, 22, 15, 8, -2, -7, + -10, -12, -16, -20, -24, -36, -46, -52, -64, -75, -81, -89, -97, -100, -104, -107, + -102, -93, -85, -70, -50, -33, -14, 8, 25, 38, 53, 61, 61, 58, 42, 24, + 8, -12, -30, -43, -56, -62, -63, -63, -54, -43, -32, -13, 7, 20, 37, 53, + 62, 72, 82, 85, 89, 94, 90, 84, 80, 73, 64, 62, 62, 56, 53, 49, + 43, 37, 33, 27, 20, 14, 5, -3, -8, -11, -13, -18, -22, -28, -40, -49, + -57, -69, -78, -84, -92, -99, -102, -105, -106, -99, -90, -81, -64, -44, -27, -7, + 14, 29, 43, 56, 61, 61, 54, 37, 20, 4, -17, -33, -46, -58, -62, -64, + -62, -52, -42, -29, -9, 9, 23, 40, 55, 64, 74, 83, 86, 91, 93, 89, + 84, 80, 72, 65, 64, 62, 56, 53, 49, 42, 37, 33, 26, 19, 12, 3, + -5, -8, -12, -16, -20, -24, -33, -44, -52, -61, -73, -80, -87, -95, -100, -103, + -106, -104, -96, -88, -76, -57, -38, -21, 0, 20, 33, 47, 59, 62, 60, 51, + 33, 17, -1, -21, -36, -49, -59, -63, -64, -61, -51, -40, -25, -5, 11, 26, + 43, 56, 65, 76, 83, 87, 92, 93, 88, 84, 79, 71, 65, 65, 61, 56, + 53, 48, 42, 37, 32, 25, 17, 10, 1, -6, -10, -13, -18, -22, -27, -37, + -48, -55, -65, -76, -83, -90, -97, -101, -104, -106, -102, -94, -84, -71, -51, -33, + -15, 7, 24, 38, 51, 60, 62, 59, 46, 29, 13, -6, -25, -39, -52, -60, + -63, -64, -59, -49, -38, -21, -1, 14, 29, 46, 57, 67, 78, 84, 88, 92, + 92, 87, 83, 78, 70, 66, 65, 61, 57, 53, 48, 42, 37, 31, 23, 15, + 7, -1, -7, -11, -15, -20, -24, -31, -41, -51, -59, -69, -79, -85, -93, -99, + -102, -105, -106, -100, -91, -80, -65, -45, -27, -8, 13, 29, 42, 55, 61, 61, + 56, 42, 25, 8, -11, -28, -42, -54, -61, -64, -64, -57, -47, -35, -17, 1, + 16, 33, 48, 59, 69, 79, 84, 89, 93, 91, 87, 83, 77, 70, 67, 65, + 60, 57, 53, 47, 41, 36, 29, 21, 14, 5, -3, -8, -12, -17, -22, -27, + -35, -45, -54, -63, -73, -81, -88, -95, -100, -103, -105, -104, -97, -88, -76, -58, + -39, -21, -1, 18, 33, 46, 58, 62, 61, 53, 38, 21, 4, -15, -31, -45, + -56, -62, -65, -64, -56, -46, -32, -13, 4, 19, 36, 50, 61, 71, 80, 85, + 90, 92, 90, 86, 82, 76, 70, 68, 65, 60, 57, 52, 46, 41, 35, 27, + 19, 12, 3, -5, -9, -14, -19, -24, -29, -38, -48, -57, -66, -76, -84, -91, + -97, -101, -104, -105, -102, -94, -84, -71, -52, -33, -15, 5, 23, 37, 50, 60, + 62, 60, 50, 34, 17, -1, -19, -35, -48, -58, -63, -65, -62, -54, -43, -28, + -10, 7, 22, 39, 52, 62, 73, 81, 86, 91, 92, 89, 86, 82, 75, 70, + 68, 64, 60, 57, 52, 46, 40, 34, 26, 17, 9, 1, -6, -11, -15, -21, + -26, -32, -42, -52, -60, -70, -79, -86, -93, -99, -102, -104, -105, -100, -91, -80, + -65, -46, -27, -9, 11, 28, 42, 54, 61, 62, 58, 46, 30, 13, -6, -23, + -38, -51, -60, -64, -65, -61, -52, -41, -25, -6, 9, 26, 42, 54, 64, 75, + 82, 87, 91, 91, 89, 85, 81, 74, 71, 68, 64, 60, 56, 51, 45, 39, + 32, 24, 16, 7, -1, -7, -12, -17, -23, -28, -36, -45, -55, -64, -73, -82, + -88, -95, -100, -103, -105, -104, -97, -88, -76, -59, -40, -22, -2, 17, 32, 45, + 57, 62, 62, 56, 42, 26, 9, -10, -27, -41, -53, -61, -65, -65, -60, -50, + -38, -21, -3, 12, 29, 44, 55, 66, 76, 82, 88, 91, 91, 88, 85, 80, + 74, 71, 68, 63, 60, 56, 50, 44, 38, 30, 22, 14, 5, -3, -9, -14, + -19, -25, -31, -39, -49, -58, -67, -77, -84, -91, -97, -101, -103, -105, -102, -95, + -84, -71, -53, -34, -16, 4, 22, 37, 49, 59, 63, 61, 53, 38, 22, 4, + -14, -30, -44, -56, -62, -66, -65, -58, -48, -35, -17, -1, 15, 32, 46, 57, + 68, 77, 83, 88, 91, 90, 88, 84, 79, 74, 71, 67, 63, 60, 55, 49, + 43, 37, 28, 20, 12, 3, -5, -10, -15, -21, -27, -33, -43, -52, -61, -70, + -79, -86, -93, -98, -102, -104, -104, -100, -92, -81, -66, -47, -28, -10, 10, 27, + 40, 53, 61, 63, 59, 49, 34, 18, -1, -18, -34, -47, -58, -63, -66, -64, + -56, -46, -31, -14, 2, 18, 35, 48, 59, 70, 78, 84, 89, 91, 90, 87, + 83, 78, 74, 71, 67, 63, 59, 54, 49, 42, 35, 27, 18, 9, 1, -6, + -12, -17, -23, -29, -36, -46, -55, -64, -73, -82, -89, -95, -100, -102, -104, -103, + -97, -88, -76, -60, -41, -23, -4, 15, 31, 44, 55, 62, 62, 57, 46, 30, + 13, -5, -22, -37, -50, -59, -64, -66, -62, -55, -43, -28, -11, 5, 22, 37, + 50, 61, 71, 79, 85, 89, 91, 89, 87, 82, 77, 73, 70, 66, 63, 59, + 53, 47, 41, 33, 24, 16, 7, -1, -8, -14, -19, -25, -32, -40, -49, -58, + -67, -76, -84, -91, -96, -101, -103, -104, -102, -95, -85, -72, -55, -37, -18, 1, + 19, 34, 47, 57, 62, 62, 56, 43, 28, 10, -8, -25, -39, -52, -60, -65, + -66, -62, -53, -42, -25, -9, 8, 24, 39, 51, 62, 72, 80, 86, 90, 90, + 89, 86, 82, 77, 73, 70, 66, 62, 58, 53, 47, 40, 33, 24, 15, 6, + -2, -8, -14, -19, -25, -32, -40, -49, -58, -67, -72, -103, -18, -76, 0, 0, + 0, 0, 1, 2, 3, 5, 6, 0, -7, -8, -15, -9, 10, 8, 17, 33, + 14, 5, 38, 44, 31, 63, 70, 51, 73, 82, 68, 85, 100, 96, 97, 103, + 115, 114, 112, 127, 122, 110, 116, 113, 109, 120, 120, 118, 113, 91, 93, 109, + 97, 98, 115, 110, 109, 120, 112, 94, 75, 63, 69, 72, 64, 64, 59, 45, + 39, 36, 35, 42, 42, 24, 5, 2, 3, 4, 7, 9, 11, 14, 17, 19, + 14, -3, -20, -26, -30, -26, -24, -31, -32, -34, -40, -39, -33, -34, -45, -56, + -60, -66, -64, -55, -60, -62, -56, -59, -58, -50, -56, -70, -73, -76, -86, -77, + -70, -80, -76, -71, -77, -71, -66, -76, -85, -82, -90, -95, -80, -82, -92, -85, + -86, -94, -85, -79, -86, -92, -90, -94, -101, -92, -85, -90, -84, -77, -78, -74, + -73, -85, -86, -85, -95, -85, -77, -90, -88, -83, -94, -93, -83, -81, -81, -86, + -89, -89, -94, -88, -77, -77, -71, -59, -58, -59, -63, -72, -74, -77, -73, -61, + -67, -72, -67, -73, -80, -74, -68, -60, -56, -65, -70, -67, -72, -66, -52, -49, + -40, -27, -27, -32, -39, -47, -50, -42, -30, -31, -34, -32, -38, -46, -46, -43, + -35, -20, -16, -24, -30, -30, -31, -24, -13, -6, 4, 13, 11, 3, -5, -9, + -2, 12, 15, 15, 16, 9, 3, -2, -5, -1, 12, 24, 30, 29, 20, 17, + 22, 25, 30, 41, 47, 49, 46, 37, 32, 41, 52, 54, 60, 61, 52, 48, + 45, 36, 35, 43, 51, 60, 67, 69, 60, 57, 63, 63, 64, 73, 75, 72, + 69, 63, 67, 78, 78, 82, 89, 80, 73, 76, 67, 60, 64, 67, 73, 79, + 83, 88, 82, 75, 80, 81, 77, 83, 83, 76, 74, 77, 83, 85, 86, 94, + 89, 80, 82, 78, 69, 68, 68, 69, 78, 80, 81, 90, 83, 73, 79, 77, + 70, 73, 70, 62, 65, 73, 75, 76, 84, 82, 70, 71, 69, 59, 57, 54, + 48, 53, 63, 64, 68, 76, 66, 57, 58, 51, 42, 40, 33, 28, 37, 46, + 49, 55, 56, 42, 37, 37, 27, 22, 20, 10, 4, 8, 15, 24, 30, 31, + 24, 14, 8, -3, -14, -21, -26, -26, -15, -4, -1, -4, -13, -21, -26, -34, + -39, -42, -50, -57, -63, -66, -60, -47, -43, -48, -51, -57, -66, -75, -82, -88, + -91, -88, -78, -74, -81, -86, -85, -92, -101, -100, -102, -109, -109, -110, -112, -113, + -115, -109, -106, -113, -113, -107, -110, -110, -106, -108, -112, -109, -110, -114, -111, -98, + -95, -98, -93, -93, -98, -94, -89, -81, -69, -65, -71, -73, -73, -77, -73, -62, + -56, -48, -40, -41, -45, -47, -47, -37, -20, -11, -4, 5, 4, 3, 6, 9, + 16, 30, 39, 47, 51, 44, 40, 45, 47, 50, 59, 64, 66, 68, 65, 65, + 75, 80, 78, 87, 95, 91, 93, 98, 96, 98, 104, 100, 96, 99, 104, 101, + 100, 106, 107, 105, 108, 109, 109, 110, 111, 110, 101, 87, 82, 84, 81, 82, + 88, 89, 90, 91, 85, 71, 57, 49, 48, 51, 52, 55, 59, 58, 58, 60, + 61, 61, 57, 42, 24, 14, 7, 5, 9, 11, 15, 20, 21, 19, 11, -3, + -18, -27, -33, -31, -25, -24, -21, -16, -16, -14, -11, -17, -29, -40, -49, -59, + -61, -55, -54, -52, -45, -42, -41, -41, -48, -59, -65, -72, -81, -79, -72, -73, + -69, -62, -61, -59, -60, -69, -76, -79, -87, -92, -84, -81, -82, -76, -72, -71, + -67, -66, -72, -79, -81, -87, -94, -92, -87, -86, -82, -76, -75, -75, -78, -85, + -87, -91, -96, -91, -82, -83, -80, -74, -74, -71, -64, -64, -68, -73, -77, -81, + -87, -88, -82, -79, -76, -70, -69, -72, -76, -80, -84, -87, -82, -71, -67, -64, + -58, -57, -55, -49, -43, -39, -40, -47, -54, -58, -64, -66, -61, -58, -54, -49, + -50, -55, -59, -63, -65, -58, -45, -38, -32, -25, -24, -23, -18, -13, -5, 3, + 4, -2, -11, -17, -23, -26, -23, -20, -18, -15, -18, -24, -28, -28, -21, -7, + 3, 11, 18, 20, 19, 22, 24, 30, 40, 47, 51, 49, 40, 32, 28, 24, + 23, 25, 25, 23, 20, 15, 15, 23, 34, 43, 51, 59, 59, 58, 59, 58, + 60, 67, 73, 78, 84, 85, 78, 71, 68, 63, 60, 60, 57, 53, 50, 50, + 56, 65, 70, 76, 84, 84, 81, 81, 79, 76, 79, 84, 87, 91, 96, 98, + 94, 88, 85, 81, 76, 73, 70, 66, 66, 70, 76, 80, 84, 91, 92, 87, + 86, 83, 78, 76, 78, 81, 85, 88, 91, 96, 93, 86, 83, 78, 71, 68, + 64, 61, 64, 71, 74, 78, 84, 86, 80, 76, 72, 64, 59, 56, 55, 59, + 66, 69, 74, 79, 76, 69, 64, 57, 48, 43, 39, 39, 45, 52, 56, 62, + 63, 55, 47, 41, 31, 21, 15, 8, 5, 9, 16, 24, 31, 35, 33, 26, + 19, 10, 0, -6, -9, -7, -7, -13, -17, -22, -26, -31, -34, -37, -40, -42, + -44, -46, -48, -50, -51, -54, -56, -58, -61, -64, -67, -70, -74, -78, -82, -86, + -90, -93, -97, -99, -102, -104, -106, -108, -109, -110, -111, -112, -113, -113, -114, -114, + -115, -115, -115, -115, -115, -114, -113, -111, -109, -107, -104, -100, -97, -93, -90, -87, + -84, -82, -80, -78, -76, -74, -73, -71, -69, -67, -65, -61, -58, -53, -48, -42, + -35, -28, -21, -13, -6, 1, 8, 15, 21, 26, 31, 35, 38, 41, 44, 46, + 48, 50, 52, 55, 58, 61, 64, 68, 72, 76, 80, 83, 87, 90, 92, 94, + 96, 98, 99, 100, 101, 102, 102, 103, 103, 103, 103, 104, 103, 103, 103, 102, + 101, 99, 97, 94, 92, 88, 85, 81, 78, 74, 71, 67, 64, 61, 58, 55, + 53, 51, 49, 47, 46, 44, 42, 40, 37, 34, 30, 26, 22, 17, 12, 8, + 3, -1, -5, -9, -13, -16, -20, -23, -26, -29, -31, -33, -35, -37, -38, -40, + -42, -44, -46, -48, -51, -54, -56, -59, -61, -64, -65, -67, -69, -70, -72, -74, + -75, -77, -78, -80, -81, -82, -83, -84, -85, -86, -86, -87, -88, -89, -90, -90, + -91, -92, -92, -92, -92, -92, -92, -91, -91, -92, -92, -92, -93, -93, -94, -94, + -94, -95, -95, -95, -95, -95, -95, -95, -95, -95, -94, -93, -92, -91, -90, -89, + -87, -86, -85, -85, -85, -84, -84, -85, -85, -85, -85, -85, -85, -85, -85, -85, + -84, -83, -82, -81, -79, -77, -75, -73, -70, -68, -65, -63, -62, -60, -59, -59, + -59, -59, -59, -59, -59, -60, -59, -59, -59, -58, -57, -55, -53, -50, -47, -44, + -40, -36, -32, -29, -25, -22, -20, -18, -17, -16, -15, -15, -16, -16, -16, -16, + -16, -16, -15, -13, -11, -9, -6, -2, 2, 6, 10, 15, 19, 22, 26, 29, + 31, 33, 35, 36, 36, 36, 36, 35, 35, 35, 35, 35, 36, 38, 40, 42, + 45, 48, 52, 55, 58, 61, 64, 67, 70, 72, 73, 74, 75, 76, 76, 76, + 75, 75, 74, 74, 74, 74, 74, 75, 77, 78, 80, 82, 83, 85, 87, 89, + 90, 91, 92, 93, 94, 94, 94, 94, 94, 93, 93, 92, 91, 91, 90, 90, + 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, + 93, 93, 92, 92, 91, 90, 89, 88, 87, 87, 86, 86, 85, 85, 85, 84, + 84, 83, 83, 82, 81, 80, 79, 78, 77, 77, 76, 75, 74, 72, 71, 70, + 68, 67, 65, 64, 63, 61, 60, 58, 57, 55, 53, 50, 48, 45, 43, 40, + 38, 36, 34, 32, 30, 29, 27, 25, 23, 21, 19, 17, 14, 12, 9, 6, + 3, 0, -4, -8, -12, -17, -21, -25, -29, -33, -36, -39, -42, -45, -47, -49, + -51, -53, -55, -58, -60, -63, -65, -68, -71, -74, -77, -81, -84, -87, -91, -94, + -97, -99, -102, -104, -105, -107, -108, -109, -110, -111, -111, -112, -112, -113, -113, -113, + -113, -113, -113, -112, -111, -109, -107, -105, -102, -99, -96, -93, -90, -87, -84, -82, + -79, -77, -75, -73, -70, -69, -66, -64, -60, -58, -53, -49, -44, -39, -32, -27, + -19, -14, -8, -3, 3, 11, 22, 10, 8, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 5, 6, 6, 6, 6, + 6, 6, 7, 5, 7, 5, 6, 4, 6, 4, 4, 4, 4, 3, 3, 2, + 3, 1, 3, -2, 2, 0, 0, 0, 0, -2, -1, -2, -3, -3, 0, -5, + -1, -2, -2, -2, -1, 0, -3, -1, -1, 0, 1, -1, 0, -1, 0, 0, + 1, 0, 0, 1, -1, 1, -1, 1, -2, -1, -3, 0, -2, -1, -2, -2, + -2, -3, -2, -3, -4, -5, -6, -5, -9, -8, -9, -9, -9, -11, -10, -13, + -14, -14, -15, -16, -15, -17, -19, -19, -21, -18, -21, -20, -22, -20, -24, -21, + -22, -19, -20, -21, -17, -19, -16, -17, -15, -17, -13, -11, -10, -7, -5, -3, + 2, 6, 4, 8, 9, 18, 14, 31, 25, 24, 25, 24, 21, 13, 15, 15, + 11, 9, 1, 4, -20, -18, -38, -44, -57, -57, -55, -55, -52, -55, -46, -47, + -40, -32, -26, -19, -16, -2, 3, 13, 19, 28, 30, 37, 40, 44, 39, 38, + 35, 34, 37, 41, 48, 51, 53, 58, 61, 70, 74, 76, 76, 80, 81, 86, + 83, 83, 78, 78, 73, 69, 65, 55, 47, 40, 36, 29, 23, 16, 14, 8, + -2, -4, -11, -11, -19, -22, -26, -25, -34, -39, -40, -41, -45, -49, -51, -57, + -56, -58, -59, -66, -70, -70, -72, -65, -64, -59, -53, -49, -45, -34, -29, -21, + -15, -10, -6, -6, -3, -4, 2, 3, 3, 3, -1, -3, -11, -11, -13, -16, + -22, -24, -27, -32, -34, -37, -35, -31, -30, -26, -25, -22, -21, -15, -13, -15, + -10, -12, -12, -7, 2, 15, 22, 27, 24, 28, 22, 22, 21, 22, 17, 13, + 14, 9, 5, 2, -8, -12, -16, -14, -17, -17, -17, -17, -14, -8, -3, -3, + 0, 5, 3, 5, 6, 3, -2, -6, -9, -11, -13, -18, -19, -29, -42, -61, + -72, -79, -81, -83, -82, -79, -76, -65, -54, -42, -33, -24, -14, 0, 18, 33, + 48, 62, 75, 87, 93, 99, 100, 102, 102, 104, 102, 100, 100, 96, 93, 95, + 96, 105, 109, 112, 111, 110, 106, 106, 104, 102, 97, 93, 85, 80, 71, 60, + 48, 36, 26, 12, 0, -5, -13, -21, -28, -31, -36, -42, -49, -53, -56, -59, + -61, -63, -64, -64, -63, -67, -70, -77, -75, -77, -78, -79, -80, -81, -80, -75, + -69, -64, -57, -50, -43, -35, -26, -16, -6, 6, 13, 17, 22, 26, 25, 27, + 27, 26, 23, 19, 11, 5, -5, -12, -19, -24, -31, -37, -42, -45, -50, -49, + -48, -47, -43, -41, -38, -38, -37, -35, -35, -37, -42, -40, -33, -27, -20, -12, + -11, -13, -10, -9, -10, -10, -10, -13, -11, -9, -8, -11, -13, -16, -18, -17, + -15, -15, -14, -12, -8, -3, 3, 8, 16, 22, 25, 31, 34, 36, 36, 34, + 31, 25, 23, 24, 26, 23, 13, -1, -16, -29, -38, -45, -51, -56, -57, -54, + -48, -39, -34, -29, -20, -10, 0, 13, 27, 39, 54, 68, 79, 87, 92, 94, + 96, 94, 92, 89, 87, 82, 76, 72, 71, 74, 76, 81, 83, 83, 84, 84, + 85, 85, 82, 81, 82, 80, 75, 71, 66, 57, 46, 34, 24, 15, 5, -2, + -8, -13, -19, -26, -31, -37, -41, -44, -48, -53, -54, -53, -54, -54, -57, -61, + -64, -67, -70, -72, -75, -77, -79, -79, -76, -73, -70, -63, -58, -53, -47, -38, + -29, -21, -13, -6, 0, 4, 7, 7, 8, 8, 6, 5, -1, -8, -15, -22, + -30, -36, -41, -47, -51, -54, -56, -58, -59, -56, -50, -45, -42, -37, -31, -26, + -23, -23, -23, -24, -21, -14, -6, 2, 8, 12, 15, 18, 21, 20, 20, 20, + 20, 21, 23, 22, 18, 13, 10, 8, 6, 5, 4, 3, 2, 2, 4, 7, + 10, 13, 18, 22, 24, 26, 28, 27, 21, 14, 8, 5, 4, 2, -3, -12, + -24, -37, -50, -59, -67, -76, -80, -79, -75, -69, -61, -55, -47, -38, -27, -15, + -2, 11, 27, 43, 58, 71, 82, 90, 94, 96, 98, 98, 98, 95, 89, 84, + 81, 79, 81, 85, 88, 89, 91, 92, 92, 90, 89, 89, 88, 85, 82, 79, + 75, 67, 58, 48, 37, 25, 14, 4, -4, -10, -17, -24, -31, -37, -42, -47, + -51, -56, -59, -59, -59, -59, -61, -63, -65, -67, -70, -72, -74, -76, -78, -78, + -78, -75, -70, -66, -61, -56, -50, -41, -33, -23, -14, -6, 2, 10, 16, 19, + 21, 23, 24, 24, 22, 19, 13, 7, 0, -6, -14, -20, -25, -27, -32, -37, + -39, -39, -38, -36, -33, -30, -27, -22, -19, -19, -20, -23, -24, -22, -18, -13, + -8, -4, 0, 2, 5, 6, 5, 3, 2, 4, 6, 6, 5, 1, -2, -6, + -8, -9, -10, -11, -13, -12, -12, -11, -9, -4, 0, 4, 8, 13, 18, 20, + 19, 14, 10, 6, 4, 4, 4, 0, -8, -17, -28, -38, -49, -60, -68, -72, + -72, -70, -65, -59, -54, -46, -37, -27, -17, -5, 8, 22, 37, 51, 66, 77, + 84, 88, 91, 93, 94, 94, 91, 85, 79, 75, 74, 76, 77, 80, 83, 85, + 85, 85, 86, 86, 85, 85, 85, 83, 81, 77, 70, 64, 55, 44, 32, 22, + 13, 6, -1, -9, -16, -22, -27, -32, -38, -43, -46, -47, -47, -47, -48, -49, + -49, -50, -52, -54, -56, -59, -62, -64, -66, -65, -64, -61, -59, -56, -53, -48, + -41, -33, -25, -17, -10, -2, 4, 9, 13, 15, 16, 17, 17, 15, 11, 7, + 1, -7, -15, -22, -27, -33, -38, -43, -47, -49, -50, -50, -49, -46, -42, -37, + -31, -28, -28, -29, -30, -29, -26, -22, -17, -13, -8, -3, 2, 6, 7, 6, + 5, 6, 8, 10, 12, 11, 8, 5, 3, 1, -1, -2, -3, -4, -6, -7, + -6, -3, 0, 1, 5, 10, 16, 20, 21, 19, 15, 10, 8, 6, 6, 4, + 0, -5, -12, -22, -33, -45, -57, -65, -70, -72, -70, -68, -64, -58, -51, -44, + -36, -24, -13, -2, 11, 27, 43, 58, 70, 78, 83, 88, 92, 96, 97, 93, + 89, 85, 81, 80, 81, 83, 86, 88, 90, 91, 91, 91, 91, 91, 91, 91, + 89, 86, 83, 79, 72, 63, 52, 41, 30, 21, 13, 4, -5, -11, -17, -23, + -31, -38, -44, -47, -49, -50, -52, -54, -55, -57, -57, -58, -60, -63, -66, -69, + -72, -74, -73, -72, -70, -69, -67, -64, -59, -53, -45, -37, -30, -22, -14, -7, + -2, 3, 8, 10, 12, 12, 13, 12, 8, 3, -4, -10, -16, -21, -27, -33, + -37, -41, -44, -46, -48, -48, -45, -48, -43, -37, -33, -31, -32, -33, -32, -29, + -26, -22, -18, -12, -5, 1, 6, 9, 9, 9, 9, 11, 14, 16, 16, 14, + 12, 8, 5, 3, 2, 1, -1, -3, -4, -4, -2, -1, 2, 5, 11, 18, + 24, 27, 27, 24, 20, 17, 15, 13, 11, 9, 5, -1, -10, -22, -35, -49, + -61, -70, -75, -77, -76, -73, -69, -63, -56, -47, -36, -25, -13, 0, 16, 34, + 52, 67, 79, 88, 95, 101, 106, 109, 108, 105, 100, 95, 92, 90, 91, 93, + 96, 99, 100, 101, 101, 101, 101, 101, 101, 100, 97, 95, 91, 85, 78, 67, + 55, 43, 31, 21, 11, 1, -7, -14, -21, -29, -37, -45, -51, -54, -56, -58, + -60, -62, -64, -65, -66, -67, -69, -72, -76, -80, -82, -84, -83, -82, -80, -79, + -77, -73, -67, -60, -51, -42, -34, -25, -16, -8, -2, 4, 9, 12, 13, 14, + 14, 13, 9, 3, -5, -12, -18, -25, -31, -37, -42, -47, -50, -53, -54, -53, + -48, -41, -36, -32, -31, -31, -32, -31, -28, -25, -22, -17, -12, -5, 1, 1, + -2, -1, -9, -9, -6, 5, 6, -1, -10, 8, 24, 11, -2, -14, -9, -15, + -13, 5, 14, 12, -6, -1, -12, 1, -9, 12, 12, 10, 5, -19, -11, -13, + -2, 8, 5, 1, -2, -3, 9, -6, 6, 5, 6, -3, -17, -7, 3, 2, + -1, 0, 7, -7, 5, 4, 6, -18, -24, 6, 20, -1, -4, -1, 10, 3, + -10, 8, 7, -11, -17, -15, 5, 18, 4, 1, 8, -16, -4, 0, 11, 9, + -10, -15, 0, -22, -12, 19, 34, 16, -9, -16, -7, -12, -10, 13, 23, -1, + -10, -2, -3, -11, 13, 7, -6, -9, 3, 11, -10, -18, 12, 22, 7, -27, + -29, -4, 20, 20, 10, 8, -16, -26, -6, 22, 21, 7, 15, 8, -50, -50, + -7, 35, 22, -13, 32, 41, -33, -46, -10, 23, -7, -25, 23, 21, -38, -36, + 14, 44, 2, 2, 34, -14, -51, -29, 11, 19, 7, 22, 13, -23, -21, -8, + -9, 1, 14, 26, 26, -8, -34, -33, 4, 1, -6, -2, 16, -7, -23, 12, + 27, 5, 6, 6, 0, -8, 0, -1, -17, -13, -12, 3, 9, 4, 11, 23, + 36, 0, -43, -16, 4, -21, -26, 27, 16, -25, 3, 65, 4, -34, 24, -10, + -38, -14, 13, 4, -15, 36, 44, -42, -51, 20, -5, -6, 68, 20, -18, -39, + -11, 9, 17, 6, -33, -20, -13, 48, 30, 22, -4, -9, -53, -20, 32, 32, + -16, 17, -11, -36, -8, -5, 39, 28, 33, 21, -64, -48, 3, -22, 15, 62, + -26, 0, 3, 5, 73, -14, -48, -20, -59, 4, 70, 60, -7, -2, -88, -22, + -17, 39, 17, 33, -3, 15, 28, -47, -80, -37, 5, 7, 104, 16, -99, -92, + -36, 109, 78, 26, -15, -92, -21, 62, 48, -51, -81, -25, 55, 63, 35, 21, + -115, -54, 101, 73, -41, -110, -66, 50, 107, 45, -8, -109, -38, 12, 102, 3, + 17, -45, -2, -36, 39, 46, -12, -28, -27, -17, 17, -18, 82, -5, -3, -25, + -5, -14, 15, 9, -3, -17, -6, 2, 7, -36, -13, 6, 21, -23, -20, 16, + -18, 3, -2, 26, 0, 13, -23, -2, -19, -28, -18, 15, 12, 22, -4, 23, + -17, -22, -9, -18, -4, 11, 13, 0, 34, -16, -20, 26, 23, 15, -4, -25, + 7, 8, -9, 8, 44, 1, -40, 17, -32, 9, -30, -52, 52, 3, 2, -21, + 83, 58, -14, -46, -61, -12, -67, -20, 64, 72, 57, -10, 5, 1, -77, 31, + -47, -39, 12, 22, 57, 28, 0, 9, -76, 15, -74, 33, -12, 39, 114, -35, + -36, -38, -23, 27, -21, 14, 56, 47, 6, -72, -61, -4, 18, -4, 19, 13, + 45, 71, 48, -1, -125, -52, -56, -20, -18, -12, 51, 78, 68, -46, 32, -40, + -29, -28, -81, -25, 75, 42, 58, -38, 1, -29, -34, 31, -36, -14, 10, 64, + 37, 2, -31, -72, -17, -33, 30, -52, -54, 25, 43, 70, 81, -9, -73, 4, + -65, 15, -28, 25, 0, 28, 19, 51, -26, 6, 0, -37, -15, -22, -20, -16, + -5, 50, 56, 67, 25, 16, -35, -29, -14, -39, 19, -24, -52, -13, -32, -10, + 39, 33, 59, 6, 37, 55, 11, -9, -35, -15, -57, -56, -36, -34, 19, 19, + 6, 20, 17, -11, 5, 26, 19, 16, 7, -20, -26, -55, -62, -36, -18, 19, + 37, 47, 25, -6, -14, 1, -4, -13, 12, 23, 34, 38, 41, 33, 31, -10, + -56, -52, -49, -31, -40, -21, -12, 0, 5, 12, 22, 22, 21, 31, 12, 2, + -8, -4, -18, -7, 3, 1, -1, 11, 12, 18, 17, 9, -2, -12, -13, -11, + -1, 8, 3, 3, 2, 5, -5, -16, -15, -13, -8, -12, -9, -2, -1, 2, + 7, 10, 7, 11, 14, 7, -1, -4, 5, -3, -2, 0, -6, -10, -1, -5, + 3, 9, 0, -8, -9, -6, -6, 0, 6, 3, 6, 7, 10, 0, -8, -3, + -5, -1, -8, -7, -4, -3, -3, 0, -1, -6, 2, 7, 7, 5, 4, 10, + 5, 8, -1, -11, -15, -11, -15, -10, -1, -8, -12, -5, 1, 3, 6, 8, + 11, 18, 22, 26, 10, -10, -1, -15, -3, -21, -16, -14, -12, -7, -8, -18, + -20, -11, 9, 20, 27, 26, 11, 1, 21, 6, 3, -9, -15, -9, -20, 3, + 5, 21, 14, 6, 11, -21, -22, -6, -21, -23, -18, 11, 6, 5, 21, 9, + 23, 16, -3, -30, -7, -27, -4, 5, 18, 22, 16, 2, 7, -1, -2, -10, + -14, -10, -17, -10, -15, -16, 3, 12, 30, 18, -1, -6, -15, -3, 5, 11, + -18, -2, 8, 21, 11, -13, -4, -30, -7, 0, 12, 25, -3, 17, 14, -20, + -6, -27, -41, -11, -12, 23, -8, 13, 24, 18, 27, -11, -8, -12, -2, 17, + 23, 13, -20, -21, -2, -21, -34, -46, -23, 28, 48, 9, -10, 8, 29, 27, + 5, -29, -12, 13, -5, -2, -35, 1, 3, 24, 13, 17, -18, -30, -21, 14, + -1, 6, -8, 48, 45, -7, -34, -49, -32, -6, -26, 20, 29, 76, 30, -21, + -66, -36, -15, 40, -5, 29, 3, 10, -39, -25, -2, 24, 19, 19, -4, -8, + 3, -22, -23, -18, 13, 17, -3, -25, 23, 66, 26, -18, -27, -34, -30, -30, + 36, 25, 28, -22, -17, -7, -22, 21, 18, 42, 8, -25, -28, -31, -10, 15, + 18, 0, -1, -5, 16, -12, 13, 13, 12, -8, -37, -9, 13, -5, 8, -3, + 13, -8, 4, 24, -16, -43, -18, 26, 26, -11, -9, 19, 9, -15, 9, 15, + -12, -31, -27, 8, 29, 5, 7, 17, -33, -14, 14, 23, -1, -18, -18, -4, + -35, -17, 47, 71, -16, -20, -11, -16, -25, 6, 37, 14, -18, 1, -8, -14, + 10, 14, 2, -20, 0, 20, -10, -25, 14, 32, 7, -39, -38, -3, 34, 25, + 13, 3, -24, -34, 5, 38, 18, 7, 29, -30, -74, -41, 36, 40, -12, 26, + 55, -17, -59, -26, 28, -2, -31, 24, 25, -44, -39, 21, 44, -1, 10, 33, + -34, -50, -12, 18, 13, 20, 17, -6, -31, -10, -6, -1, 7, 12, 14, 6, + -16, -24, 6, 9, -16, -16, 6, 2, -10, 13, 12, -10, 0, 11, 11, 10, + -3, -22, -22, -12, -7, 19, 17, -2, -12, 6, 16, 7, -11, -1, -20, -22, + -8, 26, 16, -3, 12, 1, -33, 2, 30, -23, -5, 28, -17, -19, 21, 9, + -28, -14, 25, -1, 4, 24, 0, -26, -9, 7, 2, -2, 20, -10, -11, 5, + -3, -4, 8, -9, 14, 18, 25, -22, -15, -22, -3, -12, 27, 30, 15, -11, + -26, -4, 15, -7, -14, 23, -23, -4, 34, -2, -38, 14, -11, -24, 16, 34, + 11, -13, 3, -3, -19, -34, 0, -3, 24, 43, 1, -12, -38, -25, -11, 23, + 35, 12, -28, -25, -16, 7, 22, 1, -10, 8, 8, -3, 6, -24, -20, -13, + 9, 31, 12, -16, 7, -29, 5, 8, -28, 3, 4, 12, 26, -9, -15, -5, + -20, 9, 21, 0, 1, -9, 0, 8, -3, -7, -9, -3, 22, 8, 3, -11, + -9, -11, 3, 15, 9, -10, 1, -3, -3, -2, -5, 9, 0, 12, 7, -15, + -7, 0, -8, 5, 9, -5, 7, -7, 10, 4, -11, -2, -8, -4, 9, 9, + 0, -2, -11, -3, -4, 3, 4, 3, -2, 3, 3, -8, -9, -2, 0, 3, + 5, -1, -10, -7, 2, 8, 3, 0, -5, -5, 2, 4, -2, -5, -3, 2, + 3, 0, 2, -5, -3, 3, 2, -2, -4, -2, 1, 2, 1, 0, 0, 0, + 0, -1, -7, -9, -5, 0, 2, 2, 5, 6, 0, -11, -13, -5, 3, 1, + 0, 0, 1, -3, -9, -6, -1, 5, 3, -3, -5, -3, -1, -4, -3, -1, + 2, -2, -9, -7, -2, -5, -18, -31, -36, -36, -41, -38, -29, -21, -27, -31, + -26, -4, 37, 65, 67, 44, 22, 10, 2, -4, 8, 32, 44, 38, 24, 17, + 9, 4, 3, 12, 26, 32, 32, 23, 16, 7, 1, -7, -13, -8, 1, -5, + -39, -72, -79, -64, -49, -40, -24, -1, 12, 0, -25, -44, -43, -30, -14, 1, + 13, 13, 4, 4, 16, 34, 46, 55, 65, 73, 67, 53, 54, 58, 62, 60, + 51, 38, 33, 20, -7, -27, -40, -46, -55, -58, -41, -9, 7, 8, 2, -26, + -49, -71, -92, -101, -93, -80, -70, -71, -73, -65, -67, -69, -61, -42, -15, 15, + 18, -5, -33, -54, -54, -40, -18, 2, 21, 21, 3, -28, -52, -33, 9, 35, + 33, 30, 34, 45, 46, 43, 54, 63, 65, 61, 56, 43, 45, 59, 77, 96, + 104, 112, 115, 100, 78, 53, 22, -3, -6, 5, 24, 37, 38, 35, 25, 3, + -19, -38, -51, -46, -33, -34, -42, -47, -48, -38, -27, -30, -40, -48, -45, -30, + -24, -38, -44, -43, -47, -34, -13, 7, 27, 30, 9, -18, -38, -22, 19, 47, + 70, 83, 68, 28, -13, -41, -41, -19, -1, 10, 8, 4, 4, -7, -12, 6, + 32, 42, 31, 0, -39, -71, -99, -115, -111, -85, -56, -46, -61, -74, -66, -45, + -22, 4, 21, 27, 25, 1, -30, -51, -37, 4, 37, 40, 26, 17, 12, 12, + 5, 1, 2, 12, 29, 43, 44, 45, 54, 45, 28, 10, 13, 26, 32, 43, + 59, 67, 62, 60, 66, 72, 61, 34, 11, 0, 1, -6, -18, -12, 19, 47, + 51, 32, 9, -8, -22, -26, -27, -30, -29, -12, 7, 18, 13, -1, -11, -11, + 5, 16, 14, 11, 5, -19, -47, -54, -29, 13, 37, 42, 33, 9, -17, -31, + -21, 14, 61, 81, 68, 39, 4, -26, -46, -38, -17, -1, 1, -4, -14, -25, + -23, -4, 24, 43, 49, 37, 4, -48, -97, -123, -116, -89, -66, -65, -73, -67, + -64, -66, -69, -46, 3, 36, 27, -3, -25, -39, -38, -39, -36, -24, -9, 5, + 13, 13, 4, -1, -13, -15, 0, 22, 47, 65, 76, 67, 35, 3, -4, 6, + 27, 47, 58, 68, 72, 73, 72, 66, 59, 62, 61, 49, 28, -5, -30, -27, + 9, 40, 51, 46, 40, 28, 1, -30, -56, -57, -41, -13, 5, 12, 7, -11, + -38, -54, -40, -16, 12, 23, 13, -16, -49, -62, -55, -29, 4, 38, 45, 28, + -5, -36, -36, -5, 39, 68, 77, 73, 55, 8, -35, -46, -29, -15, -15, -16, + -12, -9, -23, -30, -18, 16, 48, 51, 24, -18, -45, -72, -96, -111, -101, -80, + -67, -71, -79, -77, -70, -46, -22, -7, -4, -5, -4, -2, -15, -37, -43, -42, + -27, -5, 9, 27, 38, 27, 4, -14, -15, 6, 30, 61, 93, 90, 52, 16, + 2, 1, 5, 11, 34, 64, 79, 71, 48, 35, 43, 61, 59, 46, 27, 1, + -22, -33, -25, -9, 15, 37, 56, 54, 28, -10, -44, -58, -49, -27, -8, 20, + 29, 0, -42, -66, -60, -34, -7, 16, 30, 15, -20, -50, -64, -49, -11, 21, + 34, 34, 17, -7, -31, -29, 3, 43, 69, 78, 73, 45, 10, -20, -32, -33, + -26, -12, -6, -18, -41, -44, -27, -6, 10, 17, 19, 18, -4, -49, -87, -108, + -100, -84, -87, -93, -83, -67, -54, -45, -45, -35, -23, -13, 6, 17, 14, 1, + -22, -40, -35, -18, 2, 28, 57, 63, 33, -7, -21, -4, 23, 57, 89, 102, + 94, 68, 37, 8, -4, 4, 37, 71, 88, 79, 54, 46, 55, 62, 55, 53, + 54, 46, 20, -14, -40, -41, -16, 15, 44, 60, 59, 30, -21, -61, -70, -54, + -26, 10, 29, 19, -16, -49, -63, -58, -33, 4, 29, 26, -1, -33, -49, -50, + -34, -9, 16, 34, 34, 9, -20, -25, -9, 13, 29, 54, 87, 91, 56, 11, + -12, -11, -12, -20, -22, -17, -11, -12, -22, -25, -15, 3, 19, 19, 9, -11, + -38, -62, -76, -92, -107, -109, -95, -68, -53, -49, -49, -58, -63, -48, -25, -5, + 12, 12, -7, -36, -56, -56, -32, 8, 50, 64, 36, 6, -10, -15, -11, 9, + 47, 94, 118, 100, 58, 14, -3, 3, 19, 44, 72, 83, 78, 75, 66, 53, + 45, 52, 66, 70, 52, 22, -8, -36, -36, -14, 21, 63, 84, 63, 14, -29, + -55, -54, -42, -12, 28, 40, 14, -24, -52, -58, -42, -22, 6, 19, 16, -5, + -34, -49, -43, -24, -12, 2, 14, 22, 10, -10, -20, -16, 3, 28, 60, 72, + 61, 42, 25, 1, -26, -44, -46, -31, -25, -26, -32, -30, -24, -12, -12, -15, + 0, 6, -3, -23, -47, -79, -112, -128, -115, -84, -61, -45, -42, -51, -64, -68, + -61, -33, 9, 29, 12, -28, -54, -64, -56, -30, 9, 36, 41, 34, 10, -18, + -38, -29, 13, 70, 105, 106, 79, 48, 31, 12, -1, 12, 51, 78, 89, 87, + 75, 66, 49, 44, 56, 73, 79, 66, 23, -23, -42, -39, -9, 31, 65, 75, + 52, 7, -32, -54, -57, -30, 3, 24, 19, 2, -18, -39, -50, -39, -10, 8, + 10, -2, -12, -18, -21, -29, -33, -16, 11, 28, 17, 1, -4, 3, -3, -6, + 13, 42, 64, 67, 56, 29, 2, -21, -36, -42, -40, -25, -15, -10, -7, -10, + -27, -38, -24, 2, 19, 14, -6, -44, -86, -115, -121, -109, -81, -45, -27, -36, + -58, -76, -81, -53, -13, 11, 8, -11, -24, -40, -58, -62, -30, 11, 42, 44, + 17, -15, -36, -38, -22, 15, 53, 84, 88, 73, 52, 19, -6, -9, 13, 44, + 71, 88, 93, 79, 54, 42, 46, 67, 82, 79, 54, 20, -10, -28, -27, 0, + 46, 70, 61, 29, 2, -18, -38, -45, -23, 7, 16, 10, -8, -22, -26, -30, + -32, -23, -13, -2, 6, -6, -15, -16, -18, -20, -9, 0, 2, 11, 19, 17, + -2, -21, -12, 14, 33, 50, 65, 61, 43, 19, -17, -44, -50, -42, -21, 1, + 11, 1, -31, -56, -45, -22, -1, 17, 18, -4, -44, -95, -126, -123, -95, -56, + -36, -41, -51, -59, -68, -60, -38, -15, 5, 14, 7, -17, -47, -61, -37, 1, + 27, 33, 24, 7, -13, -30, -43, -26, 13, 47, 70, 74, 68, 48, 12, -19, + -14, 14, 46, 74, 81, 75, 64, 52, 48, 56, 67, 82, 78, 44, 9, -12, + -20, -8, 18, 41, 57, 46, 23, 0, -23, -33, -21, -10, -10, -2, 3, 5, + -2, -19, -33, -32, -24, -16, -11, -14, -6, 7, -2, -20, -25, -16, -6, 6, + 17, 27, 22, 2, -10, -11, 0, 24, 51, 68, 79, 65, 25, -19, -49, -48, + -30, -9, 8, 10, -12, -40, -57, -57, -34, -1, 25, 24, -7, -56, -95, -111, + -102, -84, -69, -57, -44, -42, -59, -74, -71, -47, -17, 0, 3, -6, -21, -37, + -38, -27, -6, 15, 23, 22, 12, -4, -23, -32, -26, 1, 36, 63, 82, 78, + 46, 12, -1, 2, 20, 41, 64, 81, 79, 66, 59, 61, 67, 75, 76, 66, + 49, 27, 5, -7, 2, 24, 41, 44, 38, 28, 13, -5, -19, -21, -17, -11, + -2, 4, 4, -2, -14, -28, -32, -27, -21, -16, -13, -1, 6, -4, -21, -25, + -17, -7, 6, 0, 0, -4, -4, -5, -8, -4, 3, 8, 6, 1, 1, 2, + 3, 3, -2, -7, -11, -10, -5, -2, 4, 6, 0, -2, -5, -4, -4, -9, + -9, -7, -11, -11, -10, -7, 4, 0, -4, -4, -1, 4, 0, -4, -3, -5, + -6, -5, -4, 4, -1, 2, 11, 5, -13, -20, -30, -49, -50, -34, -22, -33, + -27, -20, -17, 0, 34, 70, 73, 42, 3, -26, -37, -25, -1, 25, 48, 71, + 75, 44, 22, 45, 69, 57, 44, 52, 58, 24, -23, -41, -50, -58, -67, -82, + -66, -29, -29, -41, -34, -19, -4, -4, -1, 20, 50, 56, 35, 12, 4, -8, + -15, 4, 28, 44, 46, 34, 17, 2, 0, 11, 28, 42, 22, -28, -51, -45, + -34, -39, -37, -19, -17, -30, -32, -18, -4, 9, 19, 38, 35, 3, -24, -35, + -40, -23, -11, -25, -47, -52, -51, -58, -61, -52, -47, -37, -17, -5, -5, -16, + -31, -24, -11, -1, -3, -23, -40, -48, -40, -12, 15, 25, 17, -5, -2, 14, + 21, 15, -12, -26, -18, -2, 28, 48, 55, 52, 42, 35, 35, 42, 38, 36, + 40, 53, 55, 52, 44, 36, 49, 57, 56, 57, 55, 50, 39, 27, 31, 30, + 15, 11, 12, 6, 4, 14, 28, 23, 1, -6, -17, -35, -44, -41, -33, -22, + -9, -6, -12, -15, -13, -27, -29, -7, 14, -5, -55, -71, -49, -33, -37, -46, + -33, -18, -43, -89, -96, -65, -23, 2, 8, 20, 24, -11, -50, -51, -12, 15, + 4, 1, 20, 47, 53, 43, 52, 77, 98, 114, 110, 100, 88, 53, 10, -29, + -55, -71, -83, -77, -58, -55, -57, -52, -48, -47, -46, -12, 34, 59, 52, 25, + -10, -33, -21, 18, 49, 54, 46, 18, 13, 30, 41, 48, 54, 53, 44, 24, + 1, -13, -25, -43, -38, -28, -35, -55, -71, -64, -40, -13, 10, 24, 38, 41, + 21, -1, -11, 1, 15, 7, -6, -13, -39, -57, -64, -51, -20, -12, -24, -37, + -30, -4, 17, 21, 12, -7, -16, -15, -7, 6, 1, -20, -34, -30, -1, 32, + 44, 36, 22, 25, 21, 6, 1, -2, -13, -5, 19, 28, 24, 12, 11, 16, + 19, 38, 54, 49, 38, 28, 28, 39, 52, 49, 32, 25, 33, 45, 49, 39, + 40, 46, 20, -9, -6, 6, 1, -22, -29, 10, 48, 33, -17, -51, -55, -44, + -49, -50, -36, -33, -57, -84, -71, -21, 11, 13, 4, -1, -8, -32, -45, -32, + -10, 2, -13, -37, -39, -42, -57, -65, -63, -36, -11, 10, 33, 22, -12, -34, + -28, -12, 2, 8, 6, -2, -4, 0, 10, 22, 36, 57, 82, 104, 122, 127, + 109, 70, 17, -28, -45, -36, -20, -33, -68, -102, -114, -103, -76, -45, -20, -7, + -11, -10, -2, 6, 0, -14, -5, 30, 48, 29, 3, -8, 10, 39, 67, 86, + 83, 59, 32, 17, 32, 46, 40, 11, -29, -48, -57, -68, -69, -57, -43, -26, + -13, -2, 1, 1, 3, 4, 8, 21, 20, 11, 3, -2, -6, -26, -39, -33, + -34, -36, -28, -23, -27, -28, -17, -1, 0, -6, -10, -9, -7, -12, -26, -44, + -54, -38, -16, 0, 18, 27, 17, -3, -18, -3, 19, 11, -9, -7, 10, 14, + 5, 5, 18, 29, 29, 12, 16, 38, 43, 14, 2, 24, 55, 59, 33, 17, + 24, 44, 65, 75, 77, 55, 15, -16, -20, 6, 31, 27, 17, 18, 19, 17, + 7, 0, -5, -20, -22, -25, -49, -69, -73, -58, -45, -29, -4, 9, -1, -23, + -51, -52, -24, -2, 11, 12, -16, -51, -75, -77, -67, -59, -59, -54, -35, -15, + -9, -9, -9, -7, -8, -12, -1, 15, 22, 10, -14, -34, -28, -14, 11, 64, + 113, 127, 117, 97, 87, 84, 68, 50, 37, 36, 24, -15, -58, -78, -84, -71, + -40, -14, -12, -34, -48, -41, -14, 20, 37, 35, 16, -6, 1, 14, 15, 20, + 23, 24, 38, 58, 69, 57, 40, 54, 73, 75, 65, 40, -3, -49, -68, -56, + -42, -42, -53, -59, -44, -23, -9, -3, -11, -18, -13, -11, -5, 3, 13, 4, + -25, -39, -22, -14, -16, -27, -38, -37, -42, -55, -51, -21, 8, 10, -8, -12, + -4, -10, -39, -55, -38, -13, -4, -11, -15, -3, 15, 12, 2, 11, 28, 34, + 15, -5, 3, 11, 6, 12, 25, 25, 13, 10, 15, 27, 48, 55, 38, 23, + 17, 23, 32, 23, 32, 57, 75, 75, 52, 22, 10, 5, 12, 28, 33, 23, + 2, -14, -4, 19, 30, 25, 15, 1, -27, -64, -78, -67, -49, -45, -48, -42, + -31, -25, -40, -50, -39, -18, -4, 13, 19, 12, -10, -43, -59, -53, -47, -54, + -61, -51, -20, -2, -12, -23, -25, -18, 5, 33, 51, 45, 16, -16, -46, -53, + -38, -6, 33, 57, 74, 81, 75, 77, 89, 105, 114, 110, 83, 39, -6, -25, + -28, -39, -48, -52, -55, -59, -67, -67, -57, -42, -23, -3, 10, 3, -19, -33, + -30, -8, 20, 23, 2, -18, -17, 12, 40, 58, 65, 65, 66, 71, 64, 54, + 38, 1, -41, -62, -47, -26, -31, -49, -55, -42, -21, -17, -19, -10, -2, -3, + -10, -13, 2, 13, -10, -38, -27, 3, 8, -18, -46, -61, -65, -53, -36, -18, + -5, -6, -14, -22, -18, -12, -19, -29, -28, -21, -10, -15, -24, -18, -4, 16, + 23, 17, 14, 10, 9, 13, 15, 28, 35, 19, 4, 2, -2, 9, 34, 62, + 66, 43, 13, -2, 15, 42, 50, 48, 51, 56, 56, 45, 44, 45, 48, 40, + 33, 31, 27, 10, -10, -4, 16, 41, 52, 48, 31, -1, -36, -56, -50, -27, + -14, -25, -43, -60, -67, -47, -31, -38, -47, -40, -17, 13, 32, 28, -10, -50, + -68, -62, -40, -21, -20, -33, -58, -72, -63, -45, -28, -11, 18, 48, 42, 15, + -14, -43, -54, -40, -15, 4, 2, -5, 0, 20, 55, 91, 113, 120, 109, 89, + 77, 63, 43, 26, 20, 12, -13, -47, -69, -68, -53, -49, -49, -36, -28, -27, + -27, -28, -12, 5, 1, -9, -2, 14, 10, -25, -39, -6, 21, 35, 41, 53, + 73, 82, 74, 64, 54, 39, 9, -23, -37, -30, -22, -30, -52, -62, -54, -32, + -9, 2, 5, -3, -17, -25, -17, -1, 13, 8, -7, -12, -7, -7, -21, -40, + -51, -51, -38, -21, -16, -22, -29, -33, -23, -10, -2, -9, -24, -33, -33, -29, + -21, -8, 3, 2, -10, -18, -11, 8, 26, 32, 27, 21, 14, 7, 1, 3, + 12, 22, 35, 45, 43, 29, 13, 10, 20, 37, 54, 59, 45, 28, 28, 37, + 48, 55, 60, 60, 43, 17, 0, -3, 9, 24, 31, 31, 28, 28, 26, 14, + -5, -22, -31, -30, -21, -7, -8, -34, -63, -82, -80, -63, -45, -28, -14, -5, + 3, 2, -11, -27, -39, -33, -11, 2, -8, -39, -73, -95, -91, -54, -8, 19, + 16, 4, 5, 14, 14, 2, -8, -14, -19, -33, -45, -38, -19, 2, 21, 54, + 93, 106, 90, 74, 80, 97, 98, 76, 52, 34, 10, -18, -37, -36, -27, -35, + -52, -62, -56, -44, -39, -37, -29, -17, -8, -2, 3, 4, -4, -16, -27, -32, + -19, 1, 19, 41, 60, 70, 71, 67, 64, 61, 53, 38, 14, -8, -21, -29, + -34, -38, -39, -29, -15, 0, 5, -5, -19, -25, -16, 5, 19, 17, 6, -3, + -7, 0, -1, 1, -2, -5, 0, 0, 2, 0, -3, -2, 0, 1, 0, -2, + -2, -2, 0, 3, 3, -2, -5, -1, -1, -1, -4, 3, 9, 1, -1, -2, + -11, -7, 1, 9, 11, 8, -4, -11, -12, -9, -4, 18, 15, 14, 1, -22, + -29, -14, 3, 30, 29, 14, -2, -35, -43, -11, 13, 36, 42, 15, -16, -49, + -44, -10, 28, 47, 38, 11, -25, -66, -39, 4, 36, 58, 33, -3, -44, -65, + -29, 19, 52, 54, 23, -13, -59, -65, -15, 32, 69, 49, 8, -30, -74, -51, + 3, 43, 71, 40, -5, -48, -77, -31, 16, 57, 67, 24, -15, -67, -72, -12, + 36, 66, 59, 5, -31, -80, -51, 3, 49, 75, 37, -2, -59, -81, -28, 20, + 67, 66, 22, -23, -76, -65, -10, 41, 78, 48, 4, -36, -85, -47, 6, 59, + 80, 31, -8, -69, -82, -22, 29, 73, 63, 17, -31, -81, -63, -1, 47, 79, + 47, 3, -56, -90, -40, 19, 75, 73, 28, -25, -86, -74, -10, 48, 85, 56, + 6, -51, -93, -48, 11, 67, 86, 33, -11, -78, -87, -29, 36, 89, 66, 13, + -38, -91, -60, 2, 50, 83, 48, 0, -56, -90, -41, 16, 71, 78, 30, -17, + -80, -75, -20, 31, 82, 62, 15, -32, -85, -66, -7, 48, 84, 50, 4, -53, + -87, -44, 8, 62, 78, 35, -8, -65, -83, -30, 23, 70, 71, 24, -20, -76, + -75, -12, 32, 73, 62, 15, -30, -85, -62, -2, 41, 76, 51, 9, -39, -86, + -52, 1, 45, 79, 46, 8, -49, -89, -46, 3, 54, 80, 43, 7, -55, -83, + -50, 0, 53, 76, 54, 11, -52, -83, -55, 0, 40, 67, 58, 22, -32, -79, + -67, -11, 28, 63, 52, 37, -9, -70, -63, -28, 10, 42, 49, 53, 8, -46, + -64, -41, 1, 22, 38, 51, 39, -16, -63, -46, -23, 5, 33, 38, 48, 14, + -42, -57, -29, -5, 22, 37, 40, 28, -23, -53, -39, -10, 14, 30, 40, 31, + -1, -48, -40, -18, 11, 19, 31, 26, 14, -20, -50, -25, -5, 11, 31, 30, + 14, 0, -35, -39, -4, -1, 19, 27, 17, 9, -10, -39, -21, -8, 9, 24, + 26, 13, -5, -19, -30, -12, -1, 17, 25, 16, 3, -19, -26, -13, -6, 17, + 22, 20, 5, -16, -32, -19, -1, 23, 27, 23, 4, -30, -33, -23, -1, 35, + 35, 24, -2, -41, -45, -21, 9, 45, 41, 22, -12, -50, -46, -18, 28, 55, + 45, 10, -27, -78, -42, 0, 53, 66, 32, -1, -61, -74, -28, 27, 64, 64, + 24, -28, -80, -66, -15, 53, 84, 48, 5, -59, -94, -41, 17, 75, 80, 26, + -21, -91, -79, -12, 48, 87, 55, 10, -58, -96, -46, 9, 80, 81, 30, -23, + -84, -80, -15, 49, 90, 49, 9, -57, -95, -45, 17, 76, 79, 26, -20, -91, + -75, -18, 52, 90, 52, 6, -59, -92, -41, 15, 68, 80, 31, -21, -87, -76, + -13, 45, 87, 49, 11, -60, -94, -35, 14, 80, 68, 22, -23, -89, -66, -7, + 47, 93, 44, -8, -61, -95, -31, 24, 86, 75, 10, -35, -96, -66, -1, 61, + 100, 44, -12, -77, -105, -33, 32, 97, 92, 16, -44, -111, -90, -5, 65, 121, + 65, -3, -80, -123, -59, 17, 98, 111, 46, -25, -112, -109, -33, 42, 112, 90, + 30, -55, -115, -84, -17, 66, 105, 71, 13, -73, -113, -61, 0, 77, 96, 56, + 4, -80, -108, -50, 8, 78, 93, 47, 3, -88, -98, -40, 7, 65, 76, 53, + 18, -71, -90, -44, 0, 39, 57, 43, 34, -19, -69, -54, -19, 18, 32, 31, + 34, 7, -40, -36, -21, -1, 12, 12, 25, 27, -9, -32, -14, -14, 2, 0, + 1, 20, 19, -2, -13, -11, -18, -12, -2, 18, 24, 12, -2, -14, -19, -19, + -12, 18, 24, 22, -2, -15, -32, -20, 3, 22, 26, 17, -13, -31, -27, -13, + 17, 33, 32, 5, -29, -47, -29, 2, 33, 42, 32, -6, -53, -52, -24, 22, + 51, 41, 27, -32, -74, -45, 0, 45, 59, 33, -1, -62, -66, -31, 26, 73, + 49, 17, -42, -80, -42, -8, 63, 72, 28, -10, -75, -72, -23, 32, 88, 47, + 13, -56, -93, -38, 10, 76, 69, 26, -20, -96, -66, -10, 48, 90, 47, 0, + -69, -103, -29, 25, 87, 73, 18, -35, -104, -68, -2, 61, 93, 47, -5, -83, + -98, -31, 30, 92, 68, 17, -39, -97, -63, -5, 64, 88, 35, -9, -74, -86, + -22, 31, 85, 54, 13, -44, -93, -46, 9, 65, 75, 23, -17, -75, -78, -15, + 39, 84, 54, 3, -52, -96, -46, 12, 71, 90, 29, -18, -89, -87, -26, 36, + 86, 72, 26, -37, -106, -77, -12, 45, 99, 68, 22, -46, -108, -73, -10, 43, + 87, 69, 19, -27, -92, -79, -12, 27, 63, 57, 26, 4, -53, -75, -35, 12, + 33, 37, 31, 26, -9, -53, -39, -16, 6, 20, 23, 22, 13, -8, -22, -23, + -18, -3, 9, 25, 19, 4, -8, -20, -17, -10, 6, 16, 17, 13, -8, -34, + -21, -6, 17, 33, 23, 6, -32, -51, -23, 11, 36, 46, 31, -11, -46, -65, + -31, 15, 59, 55, 28, -20, -73, -64, -26, 42, 78, 51, 14, -53, -85, -48, + -4, 70, 80, 38, -16, -80, -76, -32, 39, 90, 58, 19, -59, -99, -50, 14, + 71, 75, 36, -21, -94, -70, -23, 51, 88, 53, 9, -68, -97, -40, 16, 83, + 73, 29, -33, -100, -61, -13, 58, 87, 41, 0, -74, -81, -35, 24, 87, 55, + 20, -41, -88, -58, 0, 69, 73, 34, -5, -86, -75, -20, 38, 79, 49, 13, + -48, -90, -39, 2, 71, 68, 31, -16, -84, -67, -15, 38, 79, 42, 12, -50, + -85, -37, 2, 62, 71, 34, -5, -83, -75, -24, 27, 82, 51, 27, -30, -88, + -54, -15, 44, 73, 50, 16, -49, -81, -47, -6, 38, 58, 50, 27, -31, -69, + -52, -13, 15, 36, 45, 33, -5, -41, -44, -23, 2, 14, 27, 33, 10, -25, + -20, -18, -6, 1, -1, 17, 22, 3, -13, -10, -17, -13, -6, 13, 24, 15, + 1, -11, -19, -19, -16, 12, 24, 24, 3, -12, -29, -26, -1, 18, 27, 19, + -4, -31, -28, -19, 11, 30, 35, 12, -21, -46, -35, -6, 28, 42, 36, 5, + -46, -57, -31, 10, 50, 43, 33, -16, -71, -55, -9, 35, 62, 38, 10, -51, + -71, -40, 11, 69, 58, 24, -26, -81, -50, -18, 48, 79, 37, 1, -62, -81, + -32, 16, 84, 59, 20, -37, -96, -50, -2, 63, 78, 33, -4, -85, -80, -20, + 33, 88, 59, 10, -50, -107, -47, 14, 75, 85, 27, -19, -95, -83, -15, 47, + 94, 60, 8, -66, -105, -46, 15, 83, 81, 26, -23, -91, -76, -18, 48, 92, + 47, 1, -59, -94, -36, 18, 78, 66, 19, -27, -91, -60, -3, 53, 80, 35, + -8, -62, -86, -28, 27, 79, 66, 13, -38, -94, -62, 1, 56, 95, 42, -6, + -75, -96, -39, 22, 80, 80, 36, -20, -97, -92, -24, 30, 93, 79, 32, -27, + -102, -87, -22, 31, 81, 79, 29, -14, -81, -91, -25, 19, 56, 63, 31, 11, + -39, -77, -47, 3, 31, 37, 33, 27, 3, -48, -46, -20, 0, 18, 22, 23, + 16, -3, -20, -19, -15, -4, 2, 8, 5, 0, 0, 0, 0, 2, 2, 5, + 9, 12, 14, 12, 7, 6, 4, 0, -1, -1, 1, -2, -2, -11, -17, -32, + -41, -49, -55, -58, -61, -61, -65, -61, -57, -47, -37, -27, -22, -15, -5, 6, + 12, 16, 21, 27, 28, 32, 33, 35, 41, 44, 45, 47, 50, 54, 57, 56, + 53, 53, 54, 50, 50, 52, 54, 56, 52, 53, 54, 50, 49, 46, 43, 38, + 33, 27, 19, 8, 2, -11, -20, -27, -29, -30, -32, -35, -42, -52, -57, -57, + -59, -48, -40, -27, -13, 4, 13, 20, 18, 14, 11, 7, 3, -1, -3, -10, + -11, -20, -28, -46, -60, -72, -82, -92, -97, -97, -97, -94, -90, -81, -71, -61, + -55, -55, -53, -47, -38, -29, -23, -11, -6, -3, 1, 2, 5, 6, 3, 3, + 5, 15, 24, 28, 30, 30, 35, 37, 36, 39, 39, 44, 47, 48, 56, 62, + 73, 84, 91, 96, 95, 91, 85, 76, 72, 63, 55, 47, 44, 43, 41, 38, + 31, 19, 7, 0, -9, -7, -4, 8, 22, 40, 54, 67, 71, 70, 64, 56, + 45, 32, 24, 15, 12, 3, -3, -21, -42, -66, -84, -102, -117, -124, -128, -127, + -124, -118, -107, -96, -86, -86, -88, -86, -80, -70, -63, -50, -40, -33, -25, -23, + -20, -18, -18, -21, -25, -22, -14, -8, -3, -3, -1, 1, 0, 1, -3, -1, + 2, 4, 13, 24, 35, 49, 59, 67, 70, 69, 68, 59, 54, 46, 40, 31, + 29, 27, 25, 23, 20, 12, -1, -9, -19, -22, -21, -11, 3, 23, 41, 60, + 71, 76, 73, 71, 65, 56, 50, 44, 42, 35, 33, 24, 9, -13, -31, -48, + -65, -76, -83, -83, -82, -77, -69, -59, -46, -40, -40, -41, -38, -30, -24, -13, + -2, 8, 17, 22, 24, 25, 23, 20, 13, 9, 11, 15, 19, 16, 12, 9, + 4, 1, -6, -10, -11, -14, -12, -5, 3, 15, 26, 35, 40, 41, 41, 35, + 28, 19, 12, 3, -2, -6, -7, -10, -13, -19, -31, -39, -50, -56, -58, -52, + -41, -22, -3, 18, 34, 46, 48, 47, 45, 38, 32, 26, 24, 20, 19, 15, + 5, -14, -32, -49, -65, -79, -88, -91, -91, -88, -82, -75, -63, -52, -47, -46, + -46, -38, -31, -21, -8, 4, 17, 26, 31, 36, 39, 42, 40, 35, 36, 39, + 47, 48, 45, 43, 38, 36, 30, 24, 22, 19, 18, 23, 29, 40, 50, 61, + 68, 72, 74, 71, 66, 57, 50, 40, 32, 24, 21, 16, 12, 7, -3, -14, + -26, -38, -45, -46, -43, -31, -16, 3, 18, 33, 39, 39, 36, 31, 22, 13, + 8, 3, -1, -4, -9, -24, -42, -60, -77, -94, -107, -115, -119, -120, -116, -112, + -103, -91, -81, -78, -80, -75, -69, -61, -51, -39, -25, -13, -5, 2, 8, 14, + 17, 16, 15, 16, 24, 31, 32, 32, 29, 29, 27, 22, 21, 20, 19, 22, + 26, 35, 46, 59, 70, 77, 83, 85, 84, 79, 74, 66, 59, 50, 46, 41, + 38, 35, 29, 21, 11, 0, -9, -14, -16, -11, 0, 16, 30, 48, 58, 62, + 61, 58, 51, 40, 31, 25, 19, 15, 13, 4, -11, -28, -44, -61, -76, -87, + -95, -100, -100, -99, -95, -86, -75, -68, -69, -68, -67, -62, -56, -49, -38, -27, + -19, -13, -9, -3, 2, 1, -1, -3, 0, 7, 10, 10, 6, 5, 4, 0, + -4, -5, -7, -7, -7, -2, 5, 16, 27, 36, 44, 49, 52, 50, 46, 40, + 35, 26, 22, 18, 15, 15, 13, 9, 4, -5, -14, -19, -23, -21, -14, 0, + 15, 33, 49, 60, 63, 63, 61, 53, 44, 38, 32, 27, 27, 23, 14, 0, + -14, -29, -44, -58, -67, -74, -76, -76, -73, -67, -55, -45, -41, -41, -41, -39, + -35, -30, -23, -12, -3, 4, 9, 14, 20, 21, 20, 17, 15, 19, 24, 26, + 24, 21, 20, 18, 12, 9, 6, 3, 0, 1, 4, 11, 21, 30, 38, 43, + 47, 48, 45, 38, 32, 23, 15, 9, 5, 3, 1, -2, -5, -13, -22, -30, + -37, -41, -40, -30, -18, -3, 15, 30, 38, 41, 41, 37, 27, 19, 12, 6, + 3, 2, -2, -13, -25, -39, -53, -67, -78, -88, -92, -92, -91, -86, -77, -63, + -54, -50, -48, -47, -43, -38, -32, -23, -11, -1, 6, 11, 19, 25, 27, 26, + 24, 26, 31, 36, 38, 36, 37, 37, 34, 32, 29, 27, 24, 22, 23, 27, + 35, 45, 53, 61, 67, 70, 71, 66, 60, 51, 42, 34, 28, 24, 21, 18, + 16, 11, 2, -8, -16, -24, -28, -25, -17, -5, 10, 26, 39, 45, 47, 45, + 37, 27, 18, 9, 3, 0, -2, -10, -22, -36, -51, -67, -81, -93, -102, -107, + -108, -107, -102, -90, -78, -71, -67, -66, -63, -59, -56, -49, -39, -28, -19, -13, + -6, 1, 7, 8, 6, 5, 8, 14, 19, 19, 19, 20, 20, 19, 16, 15, + 13, 12, 11, 13, 20, 30, 39, 49, 57, 63, 68, 68, 65, 58, 51, 43, + 37, 32, 29, 27, 26, 24, 19, 11, 2, -5, -12, -14, -9, 0, 13, 30, + 46, 56, 62, 65, 61, 53, 44, 35, 26, 22, 20, 15, 6, -6, -20, -36, + -51, -66, -78, -87, -91, -92, -92, -85, -74, -65, -58, -56, -55, -52, -50, -46, + -40, -30, -20, -14, -8, -2, 5, 7, 6, 3, 2, 5, 10, 11, 10, 9, + 9, 8, 5, 2, 0, -2, -5, -5, -3, 5, 14, 23, 32, 39, 46, 50, + 49, 45, 38, 31, 24, 17, 14, 11, 10, 9, 7, 2, -5, -12, -20, -25, + -25, -19, -8, 7, 24, 40, 50, 58, 60, 56, 49, 41, 31, 24, 22, 20, + 15, 6, -5, -19, -34, -48, -61, -72, -79, -83, -85, -81, -72, -62, -52, -47, + -44, -41, -39, -35, -31, -24, -13, -5, 1, 7, 14, 20, 22, 21, 19, 18, + 22, 25, 25, 24, 23, 23, 20, 17, 15, 12, 10, 7, 5, 9, 16, 24, + 33, 40, 47, 53, 56, 54, 48, 41, 33, 25, 20, 15, 11, 9, 8, 5, + -2, -10, -19, -27, -32, -31, -25, -15, 0, 17, 30, 40, 46, 46, 42, 35, + 25, 15, 10, 9, 5, -2, -11, -23, -37, -52, -65, -79, -89, -95, -99, -100, + -95, -85, -74, -65, -60, -55, -52, -48, -44, -40, -29, -18, -10, -4, 4, 12, + 18, 20, 19, 17, 20, 24, 27, 27, 26, 26, 25, 23, 21, 19, 17, 15, + 12, 13, 17, 25, 34, 41, 49, 57, 62, 65, 63, 57, 51, 42, 35, 30, + 25, 22, 21, 19, 15, 8, 0, -9, -17, -21, -20, -14, -3, 13, 26, 38, + 48, 53, 52, 47, 39, 28, 19, 15, 13, 8, 0, -10, -22, -37, -51, -65, + -79, -88, -95, -100, -99, -94, -84, -74, -67, -61, -58, -55, -51, -49, -43, -33, + -23, -17, -10, -2, 6, 10, 11, 9, 9, 12, 15, 17, 16, 16, 16, 14, + 12, 11, 9, 8, 5, 3, 4, 10, 18, 26, 34, 42, 50, 57, 59, 57, + 52, 45, 38, 32, 27, 23, 21, 20, 19, 14, 8, 1, -9, 2, 5, 7, + 8, -1, 6, 15, 1, 20, 28, 1, 37, 41, 31, 29, 27, 61, 40, -12, + 38, 52, -16, -20, -1, -23, -48, -56, -63, -61, -77, -100, -88, -76, -103, -113, + -98, -103, -118, -120, -108, -107, -104, -110, -118, -104, -109, -128, -107, -83, -106, -86, + -94, -100, -77, -113, -88, -43, -77, -46, -44, -69, -34, -54, -39, 4, -30, 11, + 18, -25, 20, 16, 10, 52, 35, 52, 74, 33, 55, 74, 59, 70, 81, 85, + 91, 81, 72, 89, 94, 82, 80, 99, 100, 85, 86, 91, 100, 91, 81, 91, + 102, 83, 74, 92, 95, 63, 62, 75, 71, 63, 39, 54, 74, 15, 1, 31, + 6, -5, -13, -20, -8, -44, -59, -38, -69, -73, -67, -86, -90, -68, -73, -77, + -49, -82, -70, -43, -76, -27, 0, -29, 22, 25, -5, 44, 45, 29, 66, 71, + 49, 84, 92, 73, 92, 74, 72, 91, 37, 48, 99, 47, 31, 44, 36, 33, + -5, -11, 26, 6, -33, -22, -6, -32, -55, -44, -45, -52, -63, -73, -55, -51, + -77, -79, -61, -73, -91, -83, -70, -77, -74, -82, -85, -68, -88, -98, -57, -67, + -77, -58, -75, -66, -64, -78, -33, -37, -50, -19, -47, -38, -23, -41, 3, 6, + -7, 30, 0, -4, 24, 15, 31, 45, 44, 66, 44, 34, 58, 54, 59, 67, + 71, 87, 78, 60, 73, 84, 78, 76, 86, 95, 89, 76, 85, 94, 89, 73, + 82, 99, 85, 66, 75, 93, 75, 50, 56, 69, 59, 31, 31, 61, 29, -15, + 15, 5, -15, -14, -36, -25, -29, -69, -55, -53, -82, -78, -76, -95, -88, -69, + -80, -65, -63, -86, -58, -67, -59, -12, -28, -9, 29, -8, 13, 44, 22, 44, + 68, 53, 62, 91, 74, 81, 89, 64, 84, 78, 35, 78, 86, 44, 43, 47, + 45, 22, -5, 17, 21, -16, -24, -14, -14, -34, -50, -40, -36, -63, -71, -58, + -60, -69, -78, -78, -67, -81, -98, -78, -71, -89, -85, -84, -86, -82, -99, -82, + -60, -76, -75, -74, -76, -71, -86, -68, -37, -51, -34, -41, -57, -37, -51, -31, + -7, -17, -3, 1, 7, 22, 31, 46, 57, 41, 43, 56, 63, 62, 68, 85, + 86, 80, 84, 92, 96, 93, 93, 104, 105, 96, 99, 108, 106, 102, 98, 102, + 111, 99, 87, 106, 110, 85, 80, 88, 89, 79, 68, 70, 81, 48, 25, 39, + 32, 18, 9, 12, 0, -29, -31, -38, -60, -52, -63, -79, -71, -66, -62, -59, + -62, -74, -72, -73, -81, -43, -21, -28, 8, 10, -10, 16, 28, 27, 42, 50, + 47, 66, 76, 68, 81, 73, 67, 72, 39, 40, 67, 41, 23, 25, 22, 12, + -16, -22, -5, -27, -51, -44, -45, -57, -68, -73, -71, -74, -91, -89, -84, -90, + -97, -98, -98, -102, -105, -108, -103, -97, -105, -109, -101, -107, -113, -106, -92, -87, + -90, -92, -92, -92, -100, -92, -57, -56, -54, -40, -59, -58, -54, -61, -23, -9, + -12, 16, 0, -14, 4, 5, 17, 32, 41, 57, 55, 43, 54, 66, 67, 68, + 84, 89, 87, 87, 91, 98, 100, 96, 104, 109, 105, 103, 108, 111, 109, 105, + 105, 113, 111, 99, 102, 115, 104, 88, 90, 97, 93, 80, 75, 86, 75, 37, + 40, 43, 33, 20, 20, -14, -26, -36, -53, -52, -65, -75, -75, -69, -69, -69, + -74, -77, -76, -74, -59, -34, -26, -9, 9, 5, 13, 32, 39, 42, 53, 58, + 61, 73, 77, 77, 73, 61, 57, 46, 29, 37, 37, 17, 6, 2, -10, -27, + -38, -41, -46, -58, -68, -69, -75, -85, -89, -92, -97, -101, -103, -106, -107, -108, + -112, -111, -112, -115, -115, -115, -113, -111, -116, -115, -112, -116, -117, -110, -101, -98, + -101, -101, -98, -101, -101, -86, -69, -65, -59, -57, -62, -58, -54, -39, -19, -12, + 1, 7, -1, 5, 16, 24, 36, 46, 58, 64, 61, 64, 74, 79, 81, 90, + 96, 97, 100, 100, 104, 108, 107, 111, 114, 113, 115, 115, 115, 118, 117, 116, + 118, 119, 116, 115, 116, 117, 111, 104, 105, 107, 99, 93, 95, 91, 71, 57, + 53, 47, 38, 29, 23, 14, -11, -28, -38, -49, -58, -67, -73, -80, -84, -84, + -83, -82, -80, -78, -74, -67, -56, -42, -29, -16, -4, 7, 18, 29, 40, 49, + 57, 64, 70, 74, 78, 79, 77, 72, 67, 60, 53, 48, 42, 33, 23, 14, + 4, -6, -16, -24, -32, -40, -48, -55, -61, -68, -74, -78, -83, -87, -91, -94, + -96, -99, -101, -103, -104, -106, -107, -107, -107, -107, -107, -108, -107, -107, -107, -105, + -101, -98, -96, -94, -93, -91, -87, -82, -74, -67, -62, -57, -54, -49, -43, -35, + -25, -16, -7, -1, 4, 10, 17, 25, 33, 41, 49, 55, 59, 63, 69, 74, + 78, 83, 88, 91, 93, 96, 98, 100, 102, 104, 106, 107, 107, 108, 108, 109, + 109, 108, 108, 108, 107, 105, 104, 102, 99, 94, 91, 87, 83, 78, 73, 66, + 56, 46, 37, 28, 19, 9, 0, -11, -23, -35, -45, -55, -64, -71, -78, -83, + -85, -84, -83, -81, -79, -75, -70, -61, -49, -36, -23, -10, 2, 12, 24, 35, + 45, 53, 61, 67, 72, 76, 79, 78, 75, 70, 65, 58, 52, 46, 39, 29, + 20, 11, 1, -9, -18, -26, -34, -42, -50, -56, -63, -69, -74, -79, -83, -88, + -91, -94, -96, -98, -101, -102, -104, -105, -106, -106, -106, -106, -106, -106, -106, -106, + -105, -102, -98, -96, -94, -92, -90, -88, -84, -77, -70, -64, -59, -55, -51, -45, + -38, -29, -20, -11, -4, 2, 7, 13, 21, 29, 37, 44, 51, 56, 60, 65, + 70, 75, 80, 84, 88, 91, 93, 96, 98, 100, 102, 104, 105, 106, 107, 107, + 108, 108, 107, 107, 107, 106, 104, 103, 101, 99, 95, 91, 87, 83, 78, 73, + 67, 59, 49, 39, 30, 21, 12, 3, -8, -19, -31, -41, -51, -60, -68, -75, + -81, -84, -85, -84, -82, -80, -77, -73, -65, -55, -42, -29, -16, -4, 7, 18, + 29, 40, 49, 57, 64, 70, 74, 78, 79, 77, 73, 68, 62, 56, 50, 44, + 36, 26, 17, 7, -3, -12, -20, -28, -36, -44, -51, -58, -64, -70, -75, -79, + -84, -88, -91, -93, -96, -98, -100, -102, -103, -105, -105, -105, -105, -105, -105, -105, + -105, -104, -102, -99, -96, -94, -92, -90, -88, -85, -79, -72, -66, -61, -56, -52, + -47, -41, -33, -24, -15, -8, -1, 4, 10, 17, 24, 32, 40, 47, 53, 57, + 62, 67, 72, 77, 81, 85, 89, 91, 94, 96, 98, 100, 102, 104, 105, 105, + 106, 106, 107, 106, 106, 106, 105, 104, 102, 101, 99, 95, 91, 87, 83, 79, + 74, 68, 61, 52, 42, 33, 24, 15, 5, -5, -15, -27, -38, -48, -57, -66, + -72, -79, -83, -85, -85, -83, -81, -79, -75, -69, -60, -48, -35, -23, -10, 2, + 13, 24, 35, 45, 54, 61, 67, 72, 77, 78, 79, 76, 72, 66, 60, 54, + 49, 41, 32, 23, 12, 3, -4, -17, -15, 1, -1, 0, 0, 1, 3, 5, + 9, 13, 18, 24, 32, 38, 32, 18, -9, -48, -73, -41, 2, -3, -24, -34, + -44, -72, -111, -124, -62, 40, 40, -51, -35, 45, 46, -22, -79, 35, 78, -47, + -98, -88, -69, -57, -44, -31, -17, -9, -3, 6, 41, 85, 43, -91, -128, -65, + -25, -21, -19, -12, 2, 16, 29, 39, 49, 48, 10, -69, -47, 50, 8, -52, + -44, 5, 21, -40, -42, 33, 79, 66, 38, 24, 25, 26, 18, 21, 70, 117, + 98, 28, -1, 20, 22, 0, 1, 9, -10, -49, -33, 39, 68, 39, -5, -17, + -58, -76, 78, 104, 17, 6, -23, -43, -13, 58, 85, 43, 21, 35, 46, 31, + 22, 35, 14, -48, -74, -38, 6, 10, -8, -17, -24, -37, -60, -69, -41, 15, + 27, -21, -26, 18, 28, -1, -41, 5, 51, -9, -51, -48, -38, -31, -24, -16, + -8, -2, 1, 6, 23, 52, 41, -39, -83, -50, -19, -13, -12, -8, 1, 10, + 20, 27, 34, 35, 15, -40, -46, 27, 16, -35, -38, -6, 19, -18, -35, 17, + 61, 55, 33, 21, 22, 25, 21, 18, 52, 98, 92, 31, -5, 9, 17, -1, + -2, 7, -7, -47, -43, 24, 62, 39, -3, -20, -48, -88, 46, 113, 25, 4, + -20, -45, -25, 42, 82, 47, 19, 28, 42, 32, 18, 30, 19, -39, -77, -51, + -4, 10, -6, -18, -25, -37, -57, -70, -50, 4, 26, -15, -33, 9, 27, 6, + -38, -12, 50, 6, -47, -50, -40, -32, -25, -17, -10, -3, 0, 4, 17, 45, + 47, -23, -82, -60, -24, -14, -13, -10, -2, 7, 16, 24, 30, 33, 18, -32, + -56, 13, 23, -31, -41, -15, 19, -6, -35, 4, 52, 55, 35, 21, 22, 25, + 22, 15, 41, 89, 94, 38, -5, 4, 16, 2, -2, 7, -4, -41, -48, 12, + 58, 43, 2, -20, -38, -89, 14, 118, 38, 3, -15, -43, -32, 28, 78, 53, + 19, 24, 40, 34, 18, 26, 23, -28, -75, -61, -14, 10, -2, -16, -24, -34, + -53, -68, -55, -7, 25, -8, -36, 1, 27, 12, -31, -26, 45, 22, -39, -50, + -41, -32, -25, -17, -10, -4, 0, 3, 13, 38, 51, -5, -77, -69, -31, -15, + -14, -11, -4, 5, 13, 21, 27, 31, 20, -24, -61, -3, 28, -23, -43, -23, + 15, 5, -32, -6, 43, 53, 36, 22, 21, 26, 24, 14, 32, 79, 95, 46, + -3, 0, 15, 5, -1, 7, -1, -36, -52, 2, 53, 46, 7, -18, -30, -84, + -15, 114, 55, 4, -10, -40, -37, 15, 72, 59, 22, 20, 36, 36, 19, 23, + 26, -18, -70, -68, -25, 7, 2, -13, -22, -32, -49, -65, -59, -16, 22, -1, + -36, -8, 25, 17, -22, -35, 34, 36, -29, -48, -42, -32, -25, -18, -10, -4, + 0, 3, 10, 32, 52, 11, -67, -76, -38, -16, -13, -11, -6, 3, 11, 19, + 25, 30, 22, -15, -62, -19, 30, -14, -43, -30, 9, 13, -25, -15, 33, 51, + 37, 23, 21, 26, 26, 15, 24, 68, 94, 54, 0, -3, 13, 8, 1, 8, + 2, -30, -53, -8, 47, 49, 13, -16, -25, -75, -41, 102, 73, 6, -5, -36, + -40, 2, 65, 64, 25, 18, 33, 37, 21, 21, 27, -8, -63, -73, -36, 2, + 5, -10, -21, -30, -45, -62, -61, -25, 17, 5, -35, -17, 21, 21, -13, -39, + 20, 46, -16, -46, -42, -32, -25, -17, -10, -4, 0, 3, 8, 27, 50, 25, + -54, -81, -46, -19, -13, -12, -7, 1, 9, 17, 23, 28, 23, -8, -59, -35, + 27, -5, -42, -35, 2, 20, -16, -20, 24, 47, 38, 24, 21, 27, 28, 17, + 18, 58, 91, 62, 5, -6, 10, 10, 3, 9, 5, -24, -52, -17, 40, 50, + 18, -13, -22, -64, -60, 83, 90, 12, -3, -31, -41, -8, 55, 67, 30, 17, + 30, 37, 24, 19, 27, 1, -54, -75, -46, -4, 7, -7, -18, -28, -41, -58, + -61, -32, 11, 10, -31, -24, 17, 23, -4, -39, 5, 52, -2, -42, -42, -32, + -25, -17, -10, -4, 0, 3, 6, 22, 47, 35, -38, -82, -55, -23, -13, -12, + -8, -1, 7, 15, 21, 26, 23, -1, -53, -48, 20, 5, -39, -39, -6, 22, + -5, -22, 14, 43, 38, 25, 21, 27, 29, 19, 15, 47, 86, 68, 12, -7, + 7, 11, 4, 10, 7, -18, -50, -25, 33, 51, 24, -10, -20, -52, -72, 58, + 103, 21, -1, -26, -41, -17, 44, 67, 35, 16, 27, 36, 26, 18, 25, 8, + -45, -76, -55, -13, 7, -3, -16, -26, -38, -55, -61, -38, 4, 13, -26, -30, + 11, 25, 4, -36, -10, 51, 14, -37, -42, -33, -24, -17, -10, -4, 1, 3, + 6, 18, 42, 42, -22, -80, -63, -28, -14, -12, -9, -3, 5, 12, 19, 24, + 23, 3, -46, -58, 9, 14, -34, -41, -14, 21, 6, -21, 4, 36, 38, 26, + 21, 26, 30, 22, 13, 37, 78, 73, 20, -7, 4, 11, 6, 10, 10, -11, + -45, -33, 22, 49, 29, -4, -18, -40, -75, 23, 108, 40, 1, -18, -39, -26, + 28, 65, 42, 17, 22, 34, 29, 18, 23, 15, -30, -71, -65, -27, 3, 2, + -11, -22, -34, -49, -58, -45, -7, 13, -16, -35, -1, 24, 13, -23, -26, 37, + 36, -20, -39, -34, -24, -17, -10, -4, 1, 3, 5, 12, 33, 46, 6, -64, + -75, -40, -17, -12, -10, -5, 2, 9, 15, 20, 22, 10, -30, -65, -18, 20, + -19, -42, -27, 11, 21, -8, -8, 22, 34, 27, 22, 26, 31, 27, 14, 22, + 60, 75, 34, -4, -2, 8, 8, 11, 14, -2, -36, -42, 6, 44, 36, 4, + -15, -26, -66, -24, 95, 71, 8, -10, -33, -32, 7, 56, 51, 21, 17, 29, + 32, 20, 19, 20, -12, -59, -72, -45, -8, 5, -5, -17, -28, -42, -54, -50, + -21, 9, -5, -36, -16, 19, 21, -7, -34, 12, 51, 4, -33, -34, -25, -17, + -10, -4, 1, 4, 5, 9, 23, 44, 29, -39, -79, -55, -24, -13, -10, -7, + -1, 6, 12, 16, 20, 14, -15, -62, -46, 16, -2, -39, -36, -2, 29, 9, + -12, 8, 28, 27, 23, 25, 31, 31, 17, 13, 43, 72, 46, 2, -5, 5, + 8, 11, 16, 5, -26, -44, -8, 36, 40, 12, -12, -19, -52, -53, 67, 94, + 20, -5, -27, -35, -7, 45, 55, 27, 15, 25, 32, 23, 17, 21, 0, -47, + -73, -57, -19, 4, 0, -13, -24, -37, -50, -51, -29, 3, 1, -32, -26, 12, + 23, 3, -32, -6, 52, 22, -26, -34, -25, -17, -10, -4, 1, 5, 6, 8, + 18, 39, 38, -21, -76, -64, -30, -14, -10, -8, -2, 4, 10, 15, 18, 14, + -9, -56, -57, 7, 7, -35, -39, -10, 27, 18, -10, 2, 23, 26, 23, 24, + 31, 32, 20, 11, 35, 67, 51, 7, -6, 3, 8, 11, 17, 8, -20, -44, + -15, 31, 41, 16, -9, -17, -43, -61, 44, 102, 31, -2, -23, -35, -15, 36, + 56, 32, 0, -27, 1, -1, -1, 3, -4, -2, 1, -1, -2, 2, 3, -6, + 1, 2, -6, 2, 2, -4, -1, 2, -5, 1, 4, -4, 0, -1, 0, -1, + -2, 2, 2, -6, 0, 4, -3, -3, 4, -2, -3, -2, 0, 1, 1, -2, + -2, 3, -8, 27, -42, 11, 21, -35, 34, -25, 12, 9, -24, 14, 13, -38, + 53, -42, -3, 46, -73, 55, -16, -9, 28, -49, 38, -12, -21, 49, -51, 20, + 32, -73, 64, -28, -7, 32, -50, 42, -11, -30, 49, -21, -31, 46, -25, -7, + 20, -22, 18, -16, -10, 21, -23, 5, 28, -35, 8, 0, 8, -26, 19, 6, + -11, -20, 64, -46, -18, 51, -73, 119, -117, 46, 36, -80, 67, -46, 22, 0, + -24, 56, -59, 14, 26, -40, 24, -9, 20, -20, -15, 43, -26, -11, 9, 14, + -3, -31, 6, 54, -62, 3, 67, -78, 20, 21, -25, 31, -41, 18, 27, -53, + 32, 15, -48, 37, -11, 4, -12, -3, 31, -24, -21, 42, -10, -45, 55, -32, + 34, -43, -14, 86, -78, 8, 39, -35, -2, 13, 2, 5, -11, -4, 7, 5, + -31, 37, -4, -28, 28, -9, -11, 10, -1, 4, -18, 17, -9, -13, 24, -18, + 20, -18, -30, 59, -25, -29, 48, -15, -29, 23, 4, -3, -18, 14, 6, -8, + -19, 19, 8, -13, 0, 13, -18, 4, 1, 0, 0, 10, -14, -12, 39, -46, + 23, 9, -22, 23, -20, -22, 63, -42, -28, 77, -66, 12, 38, -56, 31, 27, + -77, 66, -11, -39, 59, -33, -41, 92, -54, -50, 96, -36, -46, 46, -17, 31, + -43, -28, 98, -57, -50, 84, -22, -44, 39, -8, 17, -28, -13, 63, -67, 16, + 10, 3, -15, -4, 36, -34, -1, 26, -27, -2, 13, 7, -22, 0, 27, -11, + -19, 6, 26, -42, 14, 18, -7, -14, -10, 37, -14, -24, 25, -4, -5, -10, + 3, 35, -39, -7, 31, -8, -23, 15, 4, -1, -25, 28, 7, -35, 34, -16, + -1, 9, -35, 45, -22, -17, 48, -52, 24, 22, -65, 48, 7, -45, 47, -19, + -33, 71, -70, 46, -7, -52, 68, -25, -35, 48, -13, -17, 14, 2, -12, 8, + -10, 1, 22, -32, 4, 34, -26, -18, 29, -7, -19, 15, -7, 15, -8, -29, + 50, -22, -35, 53, -19, -37, 47, -9, -40, 41, 1, -27, 7, 3, 0, 0, + -7, 13, -7, -21, 26, 14, -44, 11, 40, -51, 10, 26, -28, 16, -13, -3, + 31, -42, 11, 34, -52, 11, 34, -43, 10, 29, -19, -21, 27, -10, -5, 10, + -14, 11, 3, -35, 43, 3, -52, 37, 22, -66, 49, -12, -19, 50, -58, 16, + 42, -70, 50, -2, -42, 60, -69, 43, 11, -57, 54, -8, -31, 23, -8, -7, + 24, -32, 11, 21, -51, 60, -44, -6, 68, -87, 33, 45, -79, 50, -7, -13, + 21, -40, 31, 12, -41, 18, 24, -39, 15, 7, -17, 25, -20, -12, 43, -47, + 17, 6, -16, 10, 4, -11, -1, 14, -10, -7, 6, 9, -23, 9, 3, 13, + -30, 16, 16, -33, 17, 4, -17, 23, -29, 3, 54, -86, 50, 11, -41, 30, + -23, 15, 18, -60, 56, 7, -65, 49, -4, -12, 1, -6, 19, -4, -33, 35, + -10, -12, 13, -2, -2, -2, 2, -10, 16, -8, -11, 19, -6, -19, 24, -14, + 9, 3, -24, 24, -6, -13, 19, -11, -6, 6, -9, 16, -8, -10, 14, -10, + -1, -5, 16, -8, -25, 37, -11, -27, 37, -14, -13, 19, -17, 14, -5, -15, + 26, -27, 10, 11, -23, 22, -5, -19, 25, -7, -28, 44, -35, 0, 25, -31, + 31, -10, -26, 46, -41, 2, 33, -40, 24, 8, -43, 44, -12, -25, 37, -25, + -6, 29, -27, 5, 24, -40, 24, -1, -25, 23, -1, -6, -2, -1, 14, -24, + 8, 13, -11, 0, -13, 16, 15, -56, 43, 12, -35, 14, -9, 18, -10, -19, + 28, -3, -27, 23, -2, -14, 27, -35, 10, 35, -68, 44, 7, -43, 46, -21, + -25, 56, -35, -21, 51, -33, -8, 28, -27, 19, -2, -26, 36, -26, 3, 13, + -12, 6, -10, 8, -14, 15, -12, 0, 13, -9, -16, 32, -27, 3, 23, -49, + 49, -17, -31, 63, -64, 25, 36, -76, 61, -11, -47, 75, -54, -9, 69, -81, + 32, 29, -63, 46, -7, -26, 39, -31, 6, 18, -26, 13, -5, 5, -5, -2, + 5, -12, 17, -17, -2, 22, -25, 1, 20, -19, 3, 6, -6, 3, -9, 10, + -6, -3, 7, -7, -3, 12, -5, -5, -11, 24, -7, -23, 24, 0, -14, 0, + 12, -10, -2, 5, 0, 1, -10, 10, -2, -17, 26, -11, -16, 28, -22, 6, + 4, -17, 30, -27, -7, 46, -54, 15, 29, -42, 25, -4, -15, 26, -29, 11, + 15, -28, 19, -7, 1, 8, -20, 14, 1, -15, 11, -2, -2, 0, -10, 15, + -5, -12, 15, -1, -15, 12, 4, -15, 9, -1, -9, 9, -5, -6, 13, -12, + 1, 6, -6, -3, 6, -4, 0, -6, 11, -9, -2, 13, -12, -2, -1, 8, + -11, 4, 2, -6, 4, -4, 4, 0, -13, 15, 0, -21, 23, -5, -15, 15, + -2, -9, 6, -2, -4, 2, 3, -1, -7, 7, -2, -9, 6, 2, -9, 4, + 5, -12, 10, -9, 4, 5, -16, 12, -2, -13, 20, -13, -4, 17, -23, 14, + 2, -20, 22, -13, -3, 15, -22, 12, 4, -18, 17, -7, -7, 13, -14, 6, + 4, -10, 9, -5, -6, 7, 0, -7, 8, -4, -1, 0, -6, 4, 7, -14, + 2, 13, -16, 3, 10, -15, 7, -1, -10, 14, -10, -2, 11, -9, -4, 7, + -6, 3, -3, -5, 9, -6, -3, 5, 1, -7, 3, -2, 0, -2, 0, 4, + -3, -2, 4, -6, 4, -2, -2, 0, 1, 0, -7, 7, -2, -7, 9, -7, + -4, 11, -15, 11, -2, -9, 9, -4, -3, 2, 3, -7, 5, 0, -5, 6, + -7, 1, 7, -10, -2, 13, -9, -4, 8, -4, -2, -1, 1, 1, -7, 4, + 5, -8, 0, 6, -6, 0, 3, -4, 0, 1, -2, 2, -4, -4, 8, -7, + -1, 6, -9, 8, -3, -6, 12, -12, 1, 10, -11, 1, 5, -6, 3, -2, + -3, 7, -10, 2, 7, -12, 5, 2, -5, 3, -5, 0, 6, -10, 3, 4, + -8, 2, 2, -3, 3, -8, 8, 2, -14, 10, 3, -12, 8, 2, -11, 8, + -2, -6, 9, -7, -4, 10, -9, -1, 7, -7, 1, 3, -8, 8, -2, -8, + 10, -3, -5, 5, -6, 3, 1, -8, 10, -5, -5, 7, -4, -2, 2, -3, + 1, -1, -3, 4, -3, 0, 0, 0, 0, -4, 3, -2, -3, 3, -5, 3, + 0, -7, 5, 1, -8, 5, 1, -6, 6, -5, 0, 3, -7, 3, 2, -6, + 3, 2, -6, 3, 1, -3, -2, 5, -4, -1, 3, -4, 0, 0, -3, 5, + -5, -3, 7, -5, -3, 6, -4, 0, -1, -3, 3, -2, -1, 2, -1, -2, + 1, -2, 1, -1, -7, 8, -1, 5, -7, 13, -22, 8, -7, 8, -110, -28, + 24, 54, 36, 2, 60, -45, 57, 42, -43, 20, 41, -66, 24, -11, 18, -18, + -38, -63, -36, 30, -11, 33, 25, 30, 18, 11, -18, -5, 5, -46, 40, 1, + -13, -18, -20, -31, 20, 10, 29, -7, -18, 40, -29, -17, 42, -19, 6, -4, + 6, -8, 10, -26, -5, 3, 1, -17, 6, 0, 19, -1, 8, 0, -6, -10, + -1, -12, -1, 1, -3, 8, -7, 4, 11, 4, 14, -13, 16, -19, -4, -13, + -13, -14, 6, 4, -1, 4, 11, -1, 11, -1, 1, -4, -1, -15, 6, -9, + 1, -1, 0, 3, 1, -8, 3, -1, -1, 2, -2, 2, -2, 1, -5, -7, + 3, -3, 6, -3, 4, -1, 0, -4, 2, -7, 3, -6, -1, -1, 4, 0, + 3, -2, 2, -5, 5, -8, -3, -3, 2, -5, 7, -1, 4, -2, 4, -10, + 6, -6, -1, -4, 5, -13, 7, -6, 5, -8, 17, -20, 14, -6, 9, -40, + 71, -127, 9, -73, 127, 76, -28, 74, -32, 8, -62, -49, -38, 40, -68, 22, + -12, 68, 10, 39, -10, 0, 35, -23, 0, -59, -15, -7, -3, -23, 1, -20, + 37, 27, 2, 30, -2, 17, 2, -5, -7, -27, -29, 16, -3, -11, 1, -16, + -5, -8, -10, 7, 32, 9, 5, -4, 16, 5, -8, -17, -16, 5, -13, 8, + 11, 15, -10, -9, 0, -1, 2, 7, -3, -23, 9, 2, 3, 1, -13, -1, + -6, 11, -6, 8, 1, 12, -12, 9, -14, 8, -1, 0, -3, -13, 4, -7, + -4, 8, 5, -5, -7, 4, -2, -3, 2, 3, -6, 8, -3, 1, -3, -2, + 2, -6, 2, -4, -3, -4, 3, 1, 0, 0, 1, -1, -1, 2, -2, 0, + -4, -2, 1, 2, 0, -3, 1, -3, 0, -1, -3, -6, 2, -2, 3, -4, + 10, -8, 9, -5, 12, -19, 46, 37, -128, 60, -90, 102, -65, 40, -57, 39, + -6, 23, -8, 19, 24, 15, -17, -47, -27, -36, -16, 21, 3, 23, 14, 50, + -8, 19, 25, 7, -9, -28, -63, -37, 0, -42, 54, -17, 68, -3, 30, -12, + -4, 11, -15, 9, -25, -15, -2, -27, -25, 38, -8, -13, 33, 24, 12, -38, + 39, -12, -3, -17, -44, 38, 2, 27, 3, -5, -4, -13, -30, -56, -4, 11, + 1, 9, 17, 46, 25, -14, 6, -3, -7, -21, 2, 16, -5, -22, 2, -2, + 6, -12, -25, -15, 10, 9, 8, 11, 43, 8, -5, -22, -16, 14, -31, 16, + 7, -7, -26, -20, -2, 9, 11, 26, 7, 6, -20, -13, 0, 4, 17, -17, + -18, 10, 2, -10, 27, -8, 24, -23, -14, 1, 0, 13, -19, 14, 10, -16, + 16, -4, -20, 20, -33, 2, 2, 24, 21, -3, -26, -24, -18, -18, 10, 10, + 24, 18, 2, 9, -24, 16, -14, -8, 9, -5, -14, 8, -5, 30, -11, 11, + -13, -15, -12, 7, 4, -13, -13, 13, -13, 12, 23, 9, 0, 14, -10, -9, + -35, -2, -21, 12, -1, 17, 19, 11, -4, 0, -18, -24, 11, -10, 1, 11, + 12, -13, -16, 10, -23, 21, 9, -9, 3, 12, -6, 3, -5, 12, 0, -2, + 0, -19, -9, 5, -11, -7, 10, 1, -3, 9, 18, -6, 0, -1, 1, -13, + 2, 1, -3, -8, 17, -4, -9, 18, -15, 8, -1, -11, -5, -14, 11, -5, + -7, 12, 16, -7, 7, -3, -11, -5, -6, 1, 4, -3, -3, 15, 5, 0, + 3, 6, -16, 4, -14, -6, -9, -4, 2, 11, 11, 7, -2, 4, -12, -7, + -14, -6, -7, 9, 4, 7, -2, 6, 5, 6, -4, -3, -4, 7, -7, -11, + -9, 0, -3, 7, -2, -2, 3, 13, -4, -6, -15, 9, -7, -1, 4, 6, + 5, 8, -6, -8, 0, -11, -4, 6, -8, 4, 3, 5, 13, -4, -9, -3, + 4, -3, -3, 4, -1, -12, 6, -14, 2, 3, 15, 2, 6, -7, -8, 3, + 1, -2, 3, -3, -12, -6, -14, 7, -2, 13, 6, 10, 6, 0, -2, -10, + -12, -8, -6, -7, -6, 6, 4, -2, 5, 2, 0, -1, 3, -11, 4, 0, + 20, -8, -2, 0, -1, -3, 7, -3, -4, -2, -6, -10, -10, -8, 1, 2, + 5, 8, 2, 5, 8, 3, 4, 3, -2, -15, 0, -1, -7, -2, -5, -10, + 10, -1, 5, 3, 5, -1, -2, -8, -5, -9, 1, -8, 6, 5, 4, 1, + 1, 2, 3, -2, 4, -7, 1, -7, -9, -2, 0, 2, 3, 6, -8, 8, + 3, 0, -2, -9, -3, -2, 0, 3, -1, -2, -3, 7, -3, 10, -8, 1, + -12, 3, -7, 2, -3, 7, 4, 4, 0, 0, -6, -1, -5, -3, -4, -7, + 0, 5, 7, 0, 2, -3, 10, -1, 3, -7, -5, -4, -9, -3, -7, 5, + -4, 9, 2, 1, 4, 5, 0, -5, 1, -8, 4, -9, 5, -5, 0, 3, + -2, -1, 1, 1, -7, 7, 0, 3, -5, 0, -3, -1, -1, -5, -1, 1, + -1, 1, -1, 0, 2, 0, 2, -7, -7, 4, -1, 0, 3, 4, -1, -3, + -4, -6, 3, -2, 4, -1, 5, -2, -1, -5, -2, -4, 1, 3, 2, 2, + 0, -3, 1, 1, -3, -3, -1, 1, -3, -2, -1, -2, -3, -1, 0, 4, + 3, 5, 2, 1, -4, -9, -3, -7, 1, -2, 7, -2, 3, 3, 3, 1, + 0, -1, -6, -7, -6, -4, -1, 1, 0, 5, 2, -2, 2, -3, -1, 3, + -1, 1, -4, -4, -5, 0, -7, 2, -4, 3, 4, 1, 2, -1, -1, -2, + -2, 0, -1, 1, -1, -1, -3, 1, 1, 3, -3, -1, 1, 1, -2, -3, + -8, -5, 0, -1, 5, 2, 3, 1, -2, -1, -1, -3, 1, 1, -2, -3, + -3, -1, 0, -1, 1, 2, 2, 5, 0, -1, -2, -1, -2, 0, -4, 0, + -5, -1, -1, 0, 1, 5, 4, -2, -1, -2, 0, -6, -1, 0, 1, -1, + -2, 1, 0, 0, 3, 1, -2, 1, -2, -4, -1, 0, -1, -1, -4, -2, + -4, 2, -1, 1, 0, 3, 2, 0, 4, -1, 4, -6, 2, -4, -3, -5, + -4, -3, 0, 2, 0, 1, 4, 2, 2, -2, -2, -5, -6, -5, -3, -2, + 1, -1, 0, 0, 2, 2, 2, 0, 4, -2, 3, 2, -1, -2, -3, -3, + -3, -5, -5, -5, -1, -1, 0, 2, 2, 4, 1, 2, 1, 2, -1, -1, + -3, -4, -5, -3, -2, -2, -1, 1, 4, 2, 2, 2, 1, -1, -2, -6, + -2, -3, 2, -1, 1, -2, 0, 2, 1, 2, -2, 1, 0, -2, -2, -3, + 0, -2, -1, -1, 0, -2, -2, 1, 0, 2, -1, 1, -1, 0, -1, -1, + 0, -1, 0, -2, 2, 0, 2, 2, 5, 3, 6, 8, 12, 13, -6, -110, + -7, 51, -99, -128, 10, -28, -39, 25, -33, -27, 41, 34, -5, 17, 23, 25, + 24, 23, 20, 24, 25, 24, 21, 20, 23, 23, 16, 20, 9, 20, 18, 10, + 14, 5, 14, 11, 7, 5, 3, 10, 2, 7, -4, 0, 3, 0, -3, -5, + -6, -1, -12, -4, -17, -10, 9, -42, -40, 65, 40, -58, 29, 72, 39, 50, + 31, -1, 30, 25, -7, -4, -33, -47, -29, -49, -74, -69, -71, -79, -61, -51, + -57, -53, -34, -20, -22, -16, -10, -6, -2, 1, 3, 4, 8, 8, 12, 10, + 9, 14, 13, 12, 12, 13, 12, 12, 14, 12, 12, 12, 12, 13, 12, 9, + 11, 11, 11, 7, 8, 7, 8, 9, 2, 5, 8, -6, 2, 17, -17, -20, + 18, 5, -15, 15, 27, 21, 37, 44, 41, 46, 38, 26, 32, 26, -4, -15, + -6, -20, -44, -50, -54, -60, -59, -58, -58, -54, -46, -38, -32, -26, -19, -14, + -9, -5, -1, 2, 5, 7, 8, 10, 11, 12, 13, 13, 14, 14, 14, 13, + 13, 14, 15, 14, 11, 13, 14, 13, 12, 10, 12, 12, 10, 10, 8, 6, + 11, 9, -1, 5, 11, -1, -6, 1, -1, -4, 0, -1, 0, 14, 25, 24, + 28, 37, 38, 38, 38, 31, 22, 14, 4, -5, -15, -26, -38, -47, -52, -54, + -56, -57, -55, -51, -45, -39, -34, -28, -22, -17, -13, -8, -3, -1, 2, 5, + 7, 8, 10, 11, 12, 13, 13, 13, 13, 14, 14, 13, 13, 14, 13, 12, + 13, 13, 12, 11, 12, 11, 9, 11, 9, 6, 7, 8, 5, 3, 2, 0, + 0, 0, -2, -3, 0, 3, 6, 11, 18, 23, 27, 31, 34, 35, 32, 27, + 21, 14, 5, -5, -15, -26, -35, -43, -48, -52, -53, -53, -52, -49, -44, -40, + -35, -29, -24, -19, -14, -10, -6, -3, 1, 3, 5, 7, 9, 10, 11, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 12, 11, 13, 11, 10, + 10, 9, 9, 8, 7, 7, 5, 4, 3, 2, 0, -1, -1, 0, 2, 4, + 8, 12, 17, 22, 25, 28, 30, 30, 28, 24, 19, 12, 3, -5, -14, -23, + -31, -37, -43, -46, -46, -48, -47, -43, -41, -38, -33, -29, -25, -21, -16, -12, + -8, -5, -2, 0, 3, 5, 7, 9, 10, 11, 12, 12, 13, 14, 13, 13, + 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, 7, 7, 6, + 5, 4, 4, 3, 3, 3, 3, 5, 6, 8, 10, 12, 14, 17, 18, 19, + 20, 19, 17, 14, 10, 5, 0, -6, -11, -17, -22, -26, -29, -32, -34, -34, + -35, -34, -32, -31, -28, -26, -23, -20, -17, -14, -11, -8, -5, -3, 0, 2, + 4, 6, 7, 8, 9, 10, 11, 11, 12, 12, 12, 12, 11, 11, 11, 10, + 10, 9, 9, 8, 8, 7, 7, 6, 5, 5, 5, 4, 4, 5, 5, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 12, 10, 8, 5, 2, + -2, -6, -10, -14, -18, -21, -24, -26, -28, -29, -29, -30, -29, -28, -27, -25, + -23, -20, -18, -15, -12, -10, -7, -4, -2, 0, 2, 4, 6, 7, 9, 10, + 10, 11, 11, 12, 12, 12, 12, 11, 11, 11, 10, 10, 9, 9, 8, 8, + 7, 7, 6, 6, 5, 5, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, + 12, 13, 13, 13, 12, 11, 10, 8, 5, 2, -1, -5, -9, -13, -16, -19, + -22, -24, -26, -27, -28, -28, -28, -27, -26, -24, -22, -20, -18, -15, -13, -10, + -7, -5, -2, 0, 2, 4, 5, 7, 8, 9, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, + 5, 5, 6, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 12, 11, 10, + 9, 7, 5, 2, -1, -5, -8, -12, -15, -18, -21, -23, -25, -26, -27, -27, + -27, -26, -25, -24, -22, -20, -18, -16, -13, -11, -8, -6, -3, -1, 1, 3, + 4, 6, 7, 8, 9, 10, 10, 10, 11, 11, 11, 10, 10, 10, 10, 9, + 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, 5, 5, 6, 6, 6, 7, + 8, 9, 9, 10, 11, 11, 11, 11, 11, 10, 9, 7, 4, 2, -1, -4, + -7, -11, -14, -17, -19, -21, -23, -24, -25, -26, -26, -25, -24, -23, -22, -20, + -18, -16, -13, -11, -9, -6, -4, -2, 0, 2, 4, 5, 7, 8, 9, 9, + 10, 10, 11, 11, 11, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 7, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, + 11, 11, 10, 10, 8, 7, 5, 2, -1, -3, -7, -10, -13, -15, -18, -20, + -22, -23, -24, -25, -25, -24, -24, -23, -21, -20, -18, -16, -14, -11, -9, -7, + -5, -2, 0, 1, 3, 5, 6, 7, 8, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 9, 9, 8, 8, 8, 7, 7, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 9, 9, 8, 7, 6, 4, + 2, 0, -2, -5, -7, -10, -12, -15, -17, -18, -20, -21, -21, -22, -22, -21, + -21, -20, -18, -17, -15, -13, -12, -10, -8, -6, -4, -2, 0, 1, 3, 4, + 5, 6, 7, 8, 8, 8, 9, 9, 9, 9, 9, 8, 8, 8, 8, 7, + 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 7, 6, 5, 4, 3, 1, -1, -3, -5, -7, -9, -10, + -12, -14, -15, -16, -17, -18, -18, -18, -18, -17, -17, -16, -15, -13, -12, -11, + -9, -7, -6, -4, -3, -1, 0, 1, 3, 4, 5, 5, 6, 7, 7, 7, + 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, + 4, 3, 2, 0, -1, -3, -5, -7, -9, -10, -12, -13, -15, -16, -17, -17, + -18, -18, -18, -17, -17, -16, -15, -14, -12, -11, -9, -8, -6, -5, -3, -2, + -1, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 6, 6, 5, 4, 3, 2, 0, -1, -3, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, + 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 10, + 11, 12, 12, 13, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 26, + 27, 29, 29, 29, 28, 28, 28, 29, 30, 31, 31, 31, 31, 28, 19, -8, + -41, -53, -57, -59, -60, -62, -62, -63, -64, -65, -65, -66, -67, -69, -69, -69, + -72, -74, -73, -74, -76, -78, -79, -81, -82, -82, -83, -81, -83, -85, -81, -81, + -88, -90, -80, -64, -47, -32, -23, -18, -15, -13, -12, -12, -12, -13, -13, -13, + -13, -13, -12, -12, -11, -9, -7, -6, -4, -2, -1, 0, 1, 2, 4, 5, + 7, 10, 12, 14, 16, 18, 19, 18, 19, 21, 19, 20, 22, 22, 22, 25, + 27, 28, 29, 29, 29, 29, 29, 30, 31, 31, 31, 33, 34, 34, 35, 34, + 33, 31, 30, 29, 26, 25, 26, 25, 22, 22, 21, 20, 20, 19, 19, 19, + 18, 18, 18, 17, 17, 17, 17, 16, 16, 16, 15, 13, 13, 14, 14, 15, + 13, 12, 13, 13, 11, 12, 14, 14, 16, 17, 15, 16, 19, 19, 19, 19, + 21, 19, 17, 18, 19, 18, 15, 15, 17, 18, 18, 13, 11, 14, 15, 14, + 11, 6, 5, 10, 13, 17, 18, 11, 2, -2, -2, -3, 2, 14, 24, 30, + 37, 47, 52, 52, 56, 63, 65, 65, 63, 65, 72, 75, 73, 71, 73, 77, + 82, 82, 77, 77, 82, 90, 99, 104, 99, 89, 84, 86, 94, 106, 119, 127, + 126, 117, 104, 87, 64, 42, 24, 10, -2, -15, -22, -25, -27, -30, -35, -37, + -36, -34, -33, -36, -40, -42, -44, -43, -44, -48, -53, -57, -59, -57, -53, -52, + -53, -57, -62, -68, -73, -75, -75, -71, -63, -56, -48, -40, -34, -29, -26, -23, + -22, -21, -19, -19, -20, -21, -22, -22, -22, -22, -22, -21, -21, -21, -20, -19, + -19, -18, -18, -17, -17, -16, -14, -14, -13, -11, -9, -9, -9, -9, -9, -8, + -8, -8, -8, -8, -7, -6, -7, -6, -4, -3, -2, -2, -3, -4, -3, -3, + -2, -1, 0, 0, -1, -1, 0, -1, -1, -1, -3, -5, -5, -8, -10, -10, + -9, -9, -10, -11, -11, -11, -11, -11, -10, -9, -10, -10, -10, -11, -12, -12, + -13, -12, -11, -12, -14, -14, -11, -10, -12, -11, -11, -12, -12, -11, -11, -13, + -12, -9, -6, -6, -7, -7, -6, -5, -4, -4, -5, -8, -12, -11, -8, -4, + -3, -5, -6, -7, -9, -12, -13, -8, -3, -2, -4, -8, -11, -14, -15, -17, + -19, -19, -15, -8, -1, 2, 4, 8, 12, 17, 23, 26, 25, 24, 25, 30, + 36, 40, 39, 36, 33, 32, 33, 37, 43, 49, 53, 53, 49, 45, 43, 43, + 46, 52, 60, 67, 76, 82, 82, 78, 69, 58, 47, 37, 26, 14, 2, -9, + -16, -21, -24, -28, -32, -35, -37, -38, -37, -36, -36, -36, -39, -43, -46, -49, + -51, -49, -47, -46, -45, -45, -48, -52, -58, -62, -65, -66, -65, -62, -58, -54, + -50, -45, -39, -34, -30, -28, -25, -23, -21, -20, -20, -20, -20, -19, -18, -19, + -20, -18, -17, -18, -17, -17, -18, -17, -16, -15, -15, -13, -12, -10, -10, -10, + -9, -8, -7, -6, -4, -4, -5, -6, -5, -4, -4, -3, -2, -2, -1, -1, + -1, 0, 2, 3, 2, 2, 3, 2, 1, 2, 4, 5, 5, 4, 4, 4, + 3, 2, 2, 1, 0, 0, -1, -4, -5, -4, -2, -2, -3, -3, -3, -2, + -1, -2, -3, -2, -3, -4, -4, -3, -4, -6, -7, -4, 0, 0, -2, -4, + -4, -3, -2, -2, -3, -4, -4, -3, -2, -1, 3, 6, 8, 6, 3, 0, + 0, 2, 4, 5, 4, 3, 2, 2, 2, 1, 0, -1, 2, 7, 11, 9, + 6, 2, -1, -3, -3, -5, -7, -8, -6, -3, 2, 8, 13, 17, 18, 18, + 19, 23, 28, 34, 40, 42, 42, 40, 39, 39, 40, 42, 46, 50, 55, 59, + 59, 55, 51, 48, 48, 51, 57, 63, 70, 76, 82, 86, 88, 89, 86, 80, + 71, 61, 51, 43, 34, 25, 18, 10, 2, -5, -9, -12, -13, -12, -12, -13, + -14, -17, -22, -26, -29, -28, -27, -25, -24, -24, -25, -27, -31, -35, -40, -43, + -46, -47, -49, -49, -46, -43, -40, -36, -32, -28, -24, -21, -18, -16, -14, -13, + -13, -12, -11, -11, -12, -11, -10, -9, -11, -11, -11, -12, -12, -12, -10, -10, + -10, -10, -9, -8, -7, -6, -5, -4, -4, -4, -4, -4, -3, -2, -2, -1, + -2, -3, -2, -1, 0, 0, 1, 2, 3, 2, 1, 1, 2, 3, 3, 4, + 5, 4, 4, 5, 6, 7, 6, 4, 3, 3, 3, 2, -1, -3, -3, -1, + -1, -2, -3, -3, -2, -1, 1, 0, -1, -1, -2, -5, -6, -5, -4, -4, + -4, -4, -6, -6, -4, -1, 0, -2, -6, -9, -10, -8, -5, -4, -3, -3, + -1, 1, 1, -1, -3, -4, -2, 0, 2, 2, 0, -3, -6, -7, -6, -4, + -3, -2, -1, -1, -1, 0, 1, 0, -3, -9, -14, -18, -18, -15, -12, -9, + -8, -7, -5, -3, -2, 0, 5, 11, 17, 22, 25, 24, 23, 21, 20, 22, + 27, 32, 37, 40, 41, 40, 39, 37, 35, 34, 34, 35, 39, 45, 52, 59, + 66, 71, 73, 75, 74, 71, 65, 60, 55, 48, 39, 28, 17, 7, -1, -7, + -11, -13, -13, -14, -17, -21, -24, -28, -31, -32, -32, -32, -32, -31, -29, -29, + -30, -33, -36, -40, -44, -47, -50, -52, -54, -55, -54, -52, -49, -47, -43, -39, + -35, -31, -28, -26, -24, -22, -21, -19, -18, -17, -17, -16, -15, -16, -18, -17, + -16, -16, -17, -18, -18, -17, -16, -16, -14, -13, -13, -12, -12, -12, -11, -10, + -10, -9, -7, -8, -9, -10, -10, -8, -6, -5, -6, -6, -5, -3, -3, -4, + -4, -4, -3, -2, -2, -1, -1, -1, 0, 2, 3, 3, 3, 2, 1, 0, + -1, -1, -1, -2, -3, -5, -5, -4, -2, -3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 3, 2, 0, + -1, 1, 2, 1, -1, -1, 2, 2, 0, 1, 2, 2, -1, -4, -10, -21, + -30, -36, -41, -44, -40, -30, -18, -10, -8, -11, -13, -8, 3, 18, 32, 41, + 44, 45, 48, 49, 43, 32, 23, 14, 7, 8, 16, 27, 35, 37, 30, 18, + 9, 5, 3, 2, 1, 1, -1, -6, -11, -12, -6, -2, -5, -11, -18, -28, + -39, -47, -55, -69, -86, -99, -102, -92, -70, -46, -28, -15, -3, 7, 17, 26, + 28, 24, 23, 30, 42, 53, 57, 50, 36, 21, 5, -5, -4, 6, 20, 31, + 35, 34, 29, 26, 27, 37, 56, 76, 85, 80, 71, 63, 55, 47, 34, 13, + -13, -32, -39, -40, -46, -65, -93, -117, -128, -128, -126, -120, -110, -96, -78, -58, + -36, -14, 3, 10, 20, 41, 60, 68, 63, 54, 45, 39, 36, 32, 28, 29, + 35, 41, 47, 46, 41, 39, 43, 53, 68, 80, 78, 64, 46, 28, 13, 3, + -9, -35, -64, -80, -82, -74, -66, -71, -91, -111, -121, -118, -105, -86, -68, -57, + -49, -37, -22, -7, 5, 14, 26, 42, 55, 56, 46, 35, 25, 14, 6, 2, + 1, 3, 11, 22, 32, 40, 43, 42, 46, 60, 77, 88, 90, 78, 54, 30, + 14, 2, -15, -37, -62, -82, -90, -89, -86, -90, -99, -107, -109, -101, -81, -54, + -29, -14, -5, 7, 24, 40, 49, 56, 68, 83, 92, 92, 87, 74, 54, 32, + 12, -5, -19, -25, -24, -18, -7, 1, -1, -6, -4, 13, 41, 69, 84, 80, + 63, 44, 32, 29, 25, 11, -10, -25, -31, -35, -40, -48, -65, -87, -104, -109, + -102, -87, -69, -58, -54, -42, -21, 0, 13, 29, 51, 71, 84, 89, 86, 75, + 54, 33, 14, -3, -19, -29, -27, -22, -18, -11, -8, -16, -26, -19, 2, 24, + 40, 48, 42, 27, 21, 29, 34, 24, 7, -5, -14, -23, -28, -32, -45, -67, + -82, -85, -78, -63, -46, -34, -29, -24, -13, 0, 12, 25, 44, 65, 79, 85, + 86, 78, 60, 41, 27, 12, -5, -15, -15, -14, -13, -8, -7, -17, -27, -23, + -3, 23, 44, 51, 43, 25, 12, 11, 14, 8, -3, -10, -15, -22, -28, -30, + -36, -55, -73, -78, -74, -71, -63, -51, -43, -39, -34, -25, -18, -9, 8, 28, + 46, 56, 61, 62, 58, 47, 36, 28, 20, 12, 11, 16, 19, 20, 21, 15, + 0, -6, 10, 37, 57, 63, 55, 36, 15, 2, -3, -9, -19, -27, -34, -43, + -49, -49, -52, -66, -82, -86, -81, -77, -71, -61, -51, -47, -43, -35, -22, -12, + 2, 24, 47, 58, 63, 67, 66, 58, 51, 45, 34, 18, 9, 7, 7, 7, + 8, 1, -14, -24, -12, 18, 47, 64, 68, 63, 53, 42, 37, 38, 36, 29, + 21, 16, 11, 5, -2, -17, -36, -49, -52, -56, -62, -63, -61, -61, -63, -60, + -56, -49, -37, -19, 2, 17, 25, 30, 34, 37, 37, 37, 34, 25, 15, 11, + 13, 14, 14, 8, -7, -21, -16, 9, 37, 53, 60, 61, 53, 40, 33, 34, + 32, 22, 14, 12, 10, 6, -2, -15, -32, -48, -57, -60, -63, -67, -66, -63, + -63, -65, -64, -58, -49, -34, -13, 6, 16, 21, 28, 34, 38, 41, 43, 36, + 25, 19, 21, 26, 27, 20, 4, -11, -11, 7, 31, 53, 66, 70, 66, 57, + 49, 47, 44, 33, 21, 17, 16, 10, 1, -9, -26, -46, -60, -67, -76, -84, + -84, -80, -78, -79, -78, -73, -65, -52, -32, -11, 4, 10, 17, 25, 32, 36, + 40, 37, 24, 13, 15, 23, 23, 11, -5, -19, -25, -16, 9, 38, 59, 70, + 72, 67, 63, 63, 60, 50, 39, 32, 28, 22, 14, 3, -14, -34, -53, -65, + -76, -87, -94, -93, -91, -94, -96, -93, -86, -76, -56, -30, -9, 4, 16, 29, + 40, 51, 63, 65, 52, 39, 39, 45, 42, 29, 11, -7, -22, -24, -8, 19, + 42, 54, 60, 63, 61, 58, 57, 53, 43, 36, 36, 34, 28, 21, 11, -5, + -24, -39, -52, -65, -75, -77, -75, -75, -78, -80, -78, -73, -61, -43, -23, -9, + 1, 10, 23, 39, 52, 56, 47, 36, 35, 41, 42, 33, 17, -2, -24, -35, + -26, -3, 18, 32, 42, 50, 52, 53, 52, 47, 38, 31, 30, 31, 29, 26, + 22, 14, -1, -18, -33, -46, -58, -65, -65, -65, -71, -79, -81, -79, -75, -62, + -42, -27, -21, -14, 1, 19, 34, 40, 36, 29, 27, 31, 38, 39, 29, 9, + -12, -27, -28, -14, 8, 25, 37, 50, 62, 67, 66, 62, 53, 42, 36, 37, + 36, 32, 30, 25, 12, -7, -24, -39, -54, -65, -67, -67, -72, -78, -81, -82, + -81, -70, -51, -35, -29, -23, -7, 15, 30, 37, 40, 35, 25, 25, 36, 41, + 33, 15, -6, -26, -36, -27, -9, 7, 20, 35, 50, 58, 59, 58, 52, 43, + 37, 37, 37, 36, 34, 31, 24, 8, -11, -29, -44, -57, -67, -70, -73, -79, + -86, -92, -93, -87, -72, -59, -53, -46, -29, -9, 7, 20, 28, 26, 19, 17, + 27, 38, 38, 26, 7, -12, -25, -26, -15, 1, 14, 28, 47, 61, 67, 68, + 68, 63, 54, 51, 53, 51, 49, 49, 47, 34, 14, -5, -22, -39, -56, -65, + -67, -73, -86, -96, -97, -92, -86, -77, -69, -61, -49, -28, -6, 10, 22, 27, + 25, 24, 33, 49, 56, 48, 32, 13, -5, -15, -12, -2, 7, 18, 35, 50, + 59, 63, 65, 61, 53, 48, 46, 44, 43, 46, 49, 43, 27, 10, -6, -25, + -45, -53, -53, -60, -75, -87, -90, -90, -88, -81, -75, -72, -65, -48, -25, -6, + 5, 10, 13, 18, 31, 49, 60, 58, 44, 28, 12, -1, -7, -7, -1, 8, + 23, 41, 54, 61, 65, 66, 63, 56, 48, 43, 41, 42, 44, 43, 37, 25, + 8, -12, -32, -44, -49, -53, -64, -80, -91, -95, -93, -89, -85, -82, -78, -68, + -50, -27, -6, 0, -1, 0, 0, 0, 1, 2, 3, 6, 9, 13, 17, 19, + 13, -4, -15, -10, 4, 19, 26, 15, -9, -16, 6, -2, -18, 38, 64, 21, + -48, 30, 82, -23, -63, -50, -26, -7, 12, 26, 47, 83, 100, 3, -108, -87, + -30, -6, 5, 18, 33, 46, 47, 21, -52, -46, 48, 3, -54, -32, 22, 25, + -7, 12, 9, -18, -33, -24, 2, 44, 88, 92, 10, -28, -1, 1, 20, 42, + 1, -17, 53, 72, 12, -16, -74, -31, 127, 52, 1, -35, -46, 13, 39, -13, + -13, 13, 12, 11, 8, -57, -80, -44, -5, 14, 18, 6, -13, -26, -11, -8, + -24, 3, 30, 14, -28, -12, 41, -2, -37, -35, -23, -12, -1, 6, 17, 34, + 53, 19, -55, -67, -32, -13, -5, 2, 12, 19, 24, 14, -24, -47, 12, 11, + -36, -35, -1, 18, -3, 0, 5, -13, -25, -22, -5, 19, 53, 69, 21, -28, + -10, -5, 6, 28, 8, -25, 23, 57, 17, -17, -49, -63, 84, 70, 3, -23, + -50, -6, 36, -2, -20, 8, 14, 9, 13, -37, -82, -58, -19, 8, 17, 10, + -9, -26, -19, -7, -24, -9, 25, 22, -17, -28, 33, 16, -32, -37, -27, -15, + -4, 4, 13, 27, 48, 35, -35, -72, -43, -17, -7, -1, 9, 16, 23, 17, + -12, -51, -7, 21, -27, -40, -12, 19, 6, -3, 5, -9, -22, -23, -8, 11, + 42, 68, 38, -23, -16, -6, 3, 25, 19, -24, 8, 54, 31, -13, -33, -76, + 46, 95, 13, -13, -48, -20, 32, 13, -22, 2, 15, 10, 15, -17, -77, -67, + -31, 3, 17, 15, -3, -21, -23, -7, -20, -18, 18, 27, -4, -34, 17, 33, + -21, -36, -29, -16, -6, 4, 11, 23, 42, 47, -12, -69, -54, -22, -8, -2, + 7, 15, 22, 20, -2, -46, -27, 23, -13, -41, -22, 15, 16, -2, 4, -5, + -18, -21, -10, 5, 32, 64, 53, -12, -21, -6, 0, 21, 27, -16, -6, 48, + 42, -6, -22, -71, 2, 106, 31, -6, -41, -32, 22, 25, -18, -4, 15, 12, + 14, -1, -64, -74, -42, -5, 16, 19, 4, -16, -25, -10, -14, -23, 9, 29, + 9, -31, -2, 42, -5, -33, -30, -18, -8, 3, 9, 19, 36, 51, 10, -58, + -63, -29, -11, -2, 4, 13, 20, 21, 6, -35, -44, 16, 1, -38, -30, 7, + 23, 3, 2, -2, -16, -20, -12, 2, 23, 56, 62, 3, -24, -7, -2, 17, + 30, -5, -17, 37, 49, 4, -17, -57, -37, 99, 55, 0, -31, -41, 9, 33, + -10, -11, 13, 14, 12, 9, -47, -78, -53, -15, 12, 20, 9, -10, -24, -14, + -11, -25, -2, 27, 18, -21, -20, 39, 13, -29, -31, -20, -9, 1, 8, 17, + 30, 49, 29, -41, -70, -39, -15, -4, 2, 11, 17, 21, 11, -22, -52, 0, + 14, -31, -36, -4, 25, 11, 1, -1, -13, -19, -13, 0, 15, 45, 65, 20, + -24, -10, -4, 12, 30, 8, -22, 24, 52, 17, -14, -39, -61, 71, 81, 8, + -21, -44, -5, 34, 2, -16, 9, 16, 11, 14, -29, -76, -62, -27, 6, 20, + 15, -4, -21, -19, -9, -23, -12, 22, 25, -8, -30, 26, 30, -20, -31, -23, + -11, -1, 8, 14, 25, 44, 42, -19, -69, -50, -20, -6, 1, 9, 15, 20, + 15, -11, -51, -19, 20, -20, -39, -15, 23, 20, 2, 0, -11, -17, -14, -2, + 9, 35, 63, 37, -19, -14, -5, 8, 28, 18, -22, 9, 50, 28, -11, -26, + -68, 32, 100, 22, -13, -43, -18, 30, 15, -17, 4, 16, 12, 15, -12, -69, + -69, -39, -2, 18, 19, 2, -17, -22, -10, -19, -20, 15, 27, 4, -31, 7, + 41, -7, -30, -25, -13, -3, 6, 12, 22, 38, 48, 3, -61, -60, -27, -9, + 0, 7, 13, 19, 17, -2, -44, -37, 18, -7, -39, -24, 15, 28, 7, 0, + -9, -16, -14, -3, 6, 25, 57, 49, -9, -18, -7, 3, 25, 26, -15, -4, + 45, 38, -5, -18, -61, -8, 103, 42, -6, -37, -30, 21, 25, -13, -3, 16, + 13, 14, 2, -56, -73, -49, -12, 15, 21, 8, -11, -23, -13, -15, -24, 4, + 28, 14, -25, -12, 42, 9, -26, -26, -15, -5, 5, 11, 19, 32, 48, 22, + -46, -67, -36, -12, -2, 4, 12, 17, 18, 4, -33, -50, 6, 6, -35, -31, + 4, 31, 14, 0, -8, -15, -14, -4, 4, 17, 48, 57, 4, -21, -8, -1, + 21, 30, -5, -15, 36, 44, 5, -14, -46, -40, 88, 67, 2, -29, -37, 9, + 31, -6, -9, 14, 15, 13, 11, -40, -74, -58, -24, 9, 22, 13, -6, -21, + -17, -13, -25, -6, 25, 21, -13, -25, 33, 26, -19, -27, -18, -6, 3, 10, + 16, 27, 45, 36, -26, -69, -46, -17, -4, 2, 10, 15, 18, 9, -22, -55, + -11, 15, -26, -36, -8, 30, 23, 2, -6, -14, -14, -6, 4, 11, 37, 59, + 19, -20, -10, -4, 16, 31, 7, -20, 23, 47, 15, -13, -32, -58, 58, 88, + 13, -21, -40, -5, 32, 4, -13, 10, 17, 12, 14, -23, -70, -65, -35, 1, + 20, 17, 0, -18, -20, -12, -23, -16, 19, 25, -1, -30, 16, 39, -8, -26, + -20, -8, 1, 9, 14, 23, 39, 44, -5, -63, -57, -24, -7, 1, 8, 13, + 17, 12, -12, -52, -30, 17, -15, -38, -18, 23, 32, 7, -6, -13, -14, -7, + 3, 8, 27, 55, 33, -16, -13, -6, 10, 30, 17, -20, 10, 46, 25, -9, + -21, -60, 19, 100, 31, -13, -39, -17, 27, 15, -13, 4, 17, 13, 15, -8, + -61, -69, -46, -10, 17, 21, 6, -13, -22, -13, -20, -22, 10, 27, 9, -27, + -4, 44, 6, -24, -22, -11, -1, 8, 13, 20, 33, 46, 14, -50, -65, -33, + -11, 0, 5, 12, 15, 14, -4, -43, -46, 10, -2, -36, -27, 13, 36, 15, + -4, -13, -14, -8, 3, 7, 18, 49, 43, -7, -16, -7, 5, 27, 24, -14, + -3, 42, 33, -3, -16, -51, -17, 97, 51, -3, -38, -5, -13, 1, -7, 5, + -22, -32, -35, -32, -43, -35, -55, -42, -66, -48, -80, -57, -17, -128, -59, -76, + 0, -26, 1, -33, 21, 3, 16, 15, 26, 43, 28, 66, 6, 97, 40, 103, + 67, 101, 102, 98, 94, 21, 98, 90, 57, 78, 89, 81, 61, -6, 54, 4, + 62, 19, 27, 34, 12, 16, 14, -17, 19, -5, -2, -13, -38, -24, -3, -33, + -14, -11, -16, 0, -13, 7, -26, -13, -16, 6, -57, -23, -28, -13, -9, -34, + -32, -20, -87, -62, -28, -38, -75, -37, -27, -41, -71, -48, -30, -44, -83, -67, + -52, -48, -45, -46, -45, -63, -47, -40, -32, -45, -24, -32, -43, -21, -17, 0, + 21, 26, 43, 51, 62, 47, 41, 55, 57, 68, 34, 53, 63, 62, 71, 60, + 61, 56, 53, 56, 54, 38, 50, 58, 50, 40, 28, 54, 39, 41, 38, 22, + 32, 20, -3, 19, -1, -7, -6, -16, -16, -14, -27, -29, -46, -66, -61, -51, + -54, -61, -41, -50, -47, -52, -55, -45, -44, -28, -58, -56, -31, -37, -36, -32, + -18, -16, -34, -29, -9, -21, -20, -30, -22, -17, -19, -8, -12, -14, -6, -14, + -6, -11, -2, 4, -6, 9, 8, 17, 23, 13, 31, 13, 24, 30, 28, 29, + 30, 43, 34, 37, 52, 42, 44, 50, 67, 59, 49, 54, 48, 43, 51, 45, + 42, 62, 47, 39, 37, 36, 24, 28, 13, 3, 9, -11, -3, -9, -14, -18, + -34, -27, -29, -39, -42, -38, -46, -37, -46, -43, -41, -35, -38, -31, -38, -34, + -39, -39, -34, -48, -44, -47, -49, -54, -52, -44, -53, -37, -47, -38, -31, -38, + -27, -19, -19, -15, -16, 0, 0, 2, 7, 13, 29, 22, 32, 32, 39, 47, + 41, 40, 55, 48, 41, 44, 57, 43, 36, 47, 43, 42, 37, 32, 32, 27, + 33, 36, 30, 23, 25, 25, 22, 18, 22, 20, 16, 8, 6, 12, 7, 0, + 1, 3, -5, -14, -9, -7, -8, -19, -15, -16, -23, -21, -21, -32, -31, -29, + -26, -27, -29, -33, -26, -29, -30, -39, -28, -41, -43, -35, -34, -32, -29, -28, + -28, -25, -27, -24, -27, -27, -27, -22, -23, -17, -9, -10, -14, -10, -8, -4, + -2, -1, -3, 5, 4, 10, 11, 7, 13, 11, 14, 27, 22, 22, 22, 27, + 36, 34, 36, 37, 45, 44, 47, 48, 51, 49, 52, 51, 52, 48, 50, 47, + 48, 42, 40, 29, 33, 24, 22, 12, 5, 0, -3, -5, -9, -21, -21, -25, + -19, -28, -28, -30, -33, -39, -42, -42, -46, -46, -45, -42, -43, -47, -47, -36, + -32, -30, -34, -31, -22, -29, -29, -30, -26, -28, -30, -21, -26, -27, -21, -19, + -16, -11, -12, -8, -2, 1, -4, 1, 0, 1, 9, 8, 7, 12, 10, 13, + 20, 17, 18, 21, 26, 29, 30, 30, 29, 34, 33, 34, 33, 30, 32, 33, + 28, 33, 29, 35, 32, 31, 30, 31, 30, 25, 27, 24, 21, 21, 20, 16, + 17, 12, 6, 4, -3, 1, -6, -7, -11, -13, -11, -10, -8, -13, -12, -9, + -17, -14, -19, -24, -22, -24, -30, -32, -30, -33, -37, -39, -40, -42, -39, -41, + -39, -40, -41, -35, -35, -35, -37, -36, -33, -30, -25, -25, -19, -16, -16, -10, + -6, -7, -4, -2, 1, 3, 6, 10, 9, 15, 17, 18, 17, 13, 19, 18, + 17, 19, 20, 24, 24, 27, 27, 29, 30, 26, 28, 28, 27, 28, 26, 25, + 24, 25, 20, 19, 17, 18, 15, 12, 13, 10, 6, 8, 6, 3, 4, 3, + 0, -3, 0, -1, -2, -5, -4, -5, -4, -5, -6, -8, -9, -9, -12, -11, + -16, -16, -15, -15, -13, -17, -16, -17, -17, -21, -20, -25, -24, -24, -24, -26, + -30, -30, -27, -30, -26, -26, -27, -27, -25, -24, -19, -20, -17, -13, -12, -8, + -8, -8, -6, -5, -2, -1, 0, 3, 8, 10, 12, 16, 18, 24, 25, 25, + 28, 30, 28, 32, 33, 31, 32, 31, 35, 33, 31, 31, 27, 28, 26, 23, + 23, 20, 22, 18, 16, 13, 11, 9, 5, 4, -2, -2, -3, -8, -9, -11, + -12, -13, -15, -15, -15, -15, -15, -14, -12, -12, -13, -13, -8, -11, -10, -12, + -10, -12, -12, -8, -8, -9, -9, -9, -8, -9, -10, -11, -11, -10, -13, -14, + -13, -16, -16, -17, -17, -18, -19, -18, -17, -16, -16, -15, -15, -13, -12, -10, + -12, -10, -9, -8, -6, -6, -3, 0, 0, 1, 2, 2, 3, 4, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 12, 13, 14, 14, 15, 15, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 14, 13, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -1, -2, -3, -4, -5, + -5, -6, -7, -7, -8, -9, -9, -10, -11, -11, -12, -12, -13, -13, -13, -13, + -14, -14, -14, -15, -15, -15, -15, -15, -15, -16, -16, -16, -15, -15, -15, -14, + -13, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -2, -1, 0, 1, 2, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 16, 16, 15, 15, + 14, 14, 13, 12, 11, 10, 9, 7, 6, 5, 3, 1, 0, -2, -4, -5, + -7, -9, -10, -11, -13, -14, -15, -15, -16, -17, -17, -18, -18, -18, -18, -18, + -18, -18, -18, -18, -18, -18, -18, -17, -17, -16, -16, -15, -14, -14, -13, -12, + -11, -10, -9, -8, -7, -6, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 9, 10, 11, 11, 12, 13, 13, 13, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 12, 12, + 11, 10, 9, 8, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, 0, + 0, -1, 2, 1, 0, 1, 4, 2, 2, 2, 5, 2, 5, 5, 8, 4, + 13, 15, 19, -62, -65, 56, -18, -128, -39, 15, -57, -10, 19, -22, -11, 36, + 30, 5, 19, 25, 17, 21, 21, 16, 21, 18, 17, 17, 15, 14, 13, 12, + 10, 6, 8, 6, 6, -1, 1, -4, 7, -10, -36, 35, 64, -25, -18, 83, + 50, 22, 39, 21, 19, -4, -20, 28, 0, -88, -55, -5, -55, -83, -64, -58, + -77, -61, -22, -39, -57, -15, 2, -14, -9, -1, 1, 1, 2, 9, 5, 6, + 11, 9, 9, 10, 11, 12, 12, 10, 9, 9, 13, 7, 3, 14, 4, -3, + 2, 2, 17, 40, 12, 14, 55, 58, 44, 39, 38, 37, 6, 4, 31, -6, + -50, -25, -15, -49, -52, -41, -60, -68, -32, -25, -47, -36, -9, -5, -7, -3, + 3, 4, 6, 8, 11, 9, 10, 14, 14, 11, 13, 15, 14, 13, 14, 12, + 11, 12, 12, 8, 8, 3, 4, 5, -1, 8, 32, 21, 14, 43, 50, 39, + 47, 39, 20, 23, 16, 5, -9, -23, -26, -34, -48, -37, -48, -71, -56, -34, + -43, -49, -36, -20, -14, -13, -9, -4, -1, 1, 3, 6, 6, 6, 9, 10, + 8, 10, 11, 11, 11, 11, 10, 10, 10, 10, 6, 6, 4, 3, 6, -3, + 2, 25, 23, 16, 34, 38, 43, 51, 31, 19, 38, 22, -10, -7, 0, -25, + -45, -34, -32, -54, -62, -47, -39, -45, -47, -36, -24, -19, -16, -11, -6, -3, + 0, 2, 4, 6, 7, 8, 10, 11, 9, 11, 12, 11, 11, 12, 11, 10, + 10, 8, 7, 6, 3, 5, 4, 0, 13, 28, 23, 19, 36, 50, 42, 30, + 31, 39, 24, -6, -2, 7, -21, -40, -27, -34, -51, -51, -44, -42, -45, -45, + -37, -27, -22, -18, -13, -9, -6, -2, 1, 2, 5, 7, 7, 9, 11, 10, + 10, 12, 12, 11, 12, 11, 10, 10, 9, 7, 7, 4, 5, 7, 1, 7, + 27, 24, 15, 34, 47, 37, 32, 36, 36, 26, 4, -1, 4, -13, -30, -27, + -34, -47, -46, -42, -43, -45, -44, -38, -31, -25, -21, -17, -12, -8, -5, -1, + 1, 3, 5, 6, 8, 9, 10, 10, 10, 11, 11, 11, 11, 11, 10, 9, + 7, 7, 6, 3, 6, 5, 6, 17, 23, 19, 29, 40, 35, 33, 36, 34, + 26, 14, 3, 0, -6, -18, -26, -32, -39, -40, -38, -39, -41, -40, -36, -31, + -27, -23, -19, -15, -12, -8, -4, -2, 0, 3, 4, 5, 7, 8, 9, 9, + 9, 10, 10, 10, 10, 10, 9, 8, 8, 8, 7, 8, 10, 11, 14, 19, + 22, 25, 28, 29, 29, 29, 27, 21, 14, 7, -1, -5, -11, -19, -26, -29, + -31, -32, -33, -34, -33, -32, -29, -26, -24, -21, -18, -15, -12, -9, -6, -4, + -2, 0, 2, 3, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, + 10, 10, 11, 12, 14, 16, 18, 20, 22, 23, 24, 24, 23, 20, 17, 12, + 7, 2, -3, -8, -13, -17, -21, -23, -25, -26, -27, -27, -27, -26, -25, -23, + -21, -19, -17, -14, -12, -9, -7, -5, -3, -1, 1, 2, 4, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, 15, 16, 18, 19, 21, + 22, 22, 22, 21, 19, 17, 13, 9, 4, 0, -5, -10, -14, -18, -21, -23, + -25, -26, -26, -26, -26, -25, -23, -22, -20, -18, -15, -13, -11, -9, -6, -4, + -2, 0, 1, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 11, + 12, 13, 14, 15, 17, 18, 20, 21, 21, 21, 21, 19, 17, 14, 11, 7, + 2, -3, -7, -11, -15, -19, -21, -23, -25, -25, -26, -25, -25, -24, -22, -21, + -19, -17, -15, -12, -10, -8, -6, -4, -2, 0, 1, 3, 4, 5, 6, 6, + 7, 8, 8, 9, 9, 10, 11, 11, 12, 13, 15, 16, 17, 19, 20, 20, + 21, 20, 19, 18, 15, 12, 8, 4, 0, -4, -9, -13, -16, -19, -21, -23, + -24, -25, -25, -25, -24, -23, -21, -20, -18, -16, -14, -12, -9, -7, -5, -3, + -2, 0, 1, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 12, + 13, 14, 15, 17, 18, 19, 20, 20, 20, 19, 18, 16, 13, 10, 6, 2, + -2, -6, -10, -13, -16, -19, -21, -23, -24, -24, -24, -24, -23, -22, -20, -19, + -17, -15, -13, -11, -8, -6, -5, -3, -1, 0, 2, 3, 4, 5, 6, 7, + 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, + 19, 18, 16, 14, 11, 8, 4, 0, -3, -7, -11, -14, -17, -19, -21, -22, + -23, -23, -23, -23, -22, -21, -19, -18, -16, -14, -12, -10, -8, -6, -4, -2, + -1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 19, 18, 17, 15, 12, 9, 6, 3, -1, + -5, -9, -12, -15, -17, -19, -21, -22, -23, -23, -23, -22, -21, -20, -18, -17, + -15, -13, -11, -9, -7, -6, -4, -2, -1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 18, 18, 18, 17, + 16, 14, 12, 10, 7, 4, 0, -3, -6, -9, -12, -15, -17, -18, -20, -20, + -21, -21, -21, -20, -19, -18, -17, -15, -14, -12, -10, -9, -7, -5, -4, -2, + -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, + 15, 15, 16, 16, 16, 16, 16, 15, 14, 12, 11, 8, 6, 3, 0, -3, + -6, -9, -12, 1, -1, 2, -1, 4, 2, 8, 5, 10, -5, 0, 5, 17, + -11, 0, 19, -17, 26, 65, 15, 29, 3, 35, 67, 50, 88, 59, 117, 28, + -6, -16, 29, 63, 62, -40, 59, 22, -95, -49, -55, 19, 36, -15, 26, -117, + 60, 8, -101, -115, 23, 60, -32, -106, -84, -88, -127, -99, -117, -110, -56, -42, + -53, -79, -44, 43, 10, -11, 72, 22, 61, 10, -92, -106, -111, -35, -68, -128, + -67, -36, -118, -97, -96, -4, 75, 70, 113, 36, 73, 115, 37, 6, 79, 97, + 89, -8, -38, -8, -72, -8, -29, -35, 73, 98, 66, 12, 40, 113, 106, 87, + 126, 112, 127, 87, -3, -21, -23, 40, 14, -68, -20, 21, -57, -67, -67, -4, + 69, 53, 90, 17, 36, 78, -7, -54, -2, 32, 21, -71, -109, -89, -124, -103, + -114, -113, -37, -4, -30, -88, -83, 15, 13, -35, 42, 28, 33, 14, -90, -92, + -104, -37, -34, -115, -73, -9, -75, -89, -85, -29, 67, 51, 97, 55, 47, 115, + 46, -9, 42, 90, 96, 26, -36, 11, -43, -25, -6, -37, 59, 104, 88, 31, + 22, 96, 116, 69, 110, 119, 119, 109, 11, -15, -26, 18, 37, -45, -32, 34, + -13, -62, -62, -30, 61, 47, 75, 46, 14, 72, 14, -58, -35, 16, 30, -38, + -109, -78, -109, -116, -102, -123, -57, -2, -11, -58, -95, -18, 22, -41, -3, 36, + 20, 31, -69, -94, -100, -72, -21, -91, -92, -9, -33, -82, -81, -57, 48, 52, + 70, 81, 35, 97, 69, -10, 8, 66, 94, 55, -27, 4, -5, -40, -1, -33, + 30, 102, 101, 61, 19, 70, 121, 72, 77, 123, 112, 121, 36, -13, -21, -10, + 38, -18, -43, 27, 25, -40, -59, -45, 40, 54, 52, 68, 15, 56, 35, -48, + -58, -12, 25, -10, -98, -84, -83, -122, -101, -123, -81, -8, -3, -28, -85, -47, + 20, -28, -39, 23, 18, 31, -38, -99, -92, -97, -35, -66, -102, -26, -3, -60, + -77, -69, 18, 59, 47, 87, 46, 73, 86, 3, -13, 34, 80, 70, -8, -12, + 19, -32, -12, -21, 3, 91, 105, 87, 34, 51, 114, 89, 53, 106, 115, 119, + 65, -10, -13, -25, 20, 4, -45, 9, 44, -8, -49, -51, 14, 61, 39, 68, + 34, 39, 51, -30, -67, -41, 7, 5, -76, -96, -65, -111, -110, -115, -103, -20, + -1, -9, -58, -65, 8, -9, -55, -6, 17, 24, -11, -94, -89, -102, -64, -50, + -101, -51, 6, -30, -66, -71, -12, 59, 40, 72, 67, 58, 91, 24, -21, 6, + 56, 74, 14, -22, 23, -8, -24, -14, -13, 71, 106, 101, 62, 42, 101, 105, + 49, 76, 114, 114, 87, 3, -12, -23, -6, 13, -37, -11, 45, 24, -29, -49, + -8, 57, 40, 53, 54, 32, 56, -6, -65, -61, -21, 6, -52, -101, -65, -85, + -115, -109, -116, -42, 0, -1, -27, -65, -12, 7, -51, -37, 7, 17, 6, -76, + -95, -94, -91, -52, -90, -76, -2, -4, -46, -66, -35, 46, 46, 49, 78, 57, + 85, 50, -17, -13, 26, 64, 34, -22, 9, 18, -22, -14, -18, 42, 103, 105, + 88, 50, 83, 114, 63, 49, 96, 110, 99, 26, -14, -15, -23, 6, -24, -29, + 33, 45, 0, -38, -23, 44, 50, 37, 60, 38, 52, 21, -54, -70, -48, -7, + -31, -95, -78, -63, -104, -108, -117, -69, -4, -1, -5, -47, -30, 13, -33, -58, + -14, 8, 11, -50, -99, -87, -101, -70, -77, -92, -22, 10, -22, -52, -46, 23, + 55, 36, 70, 66, 74, 69, -2, -23, 1, 43, 43, -11, -8, 29, -4, -17, + -16, 18, 91, 105, 102, 71, 72, 112, 83, 40, 70, 101, 102, 50, -10, -10, + -24, -10, -13, -36, 14, 52, 27, -18, -28, 26, 58, 33, 51, 49, 46, 40, + -34, -70, -66, -31, -22, -81, -92, -56, -83, -105, -112, -91, -17, 0, 2, -22, + -37, 7, -12, -61, -39, -5, 7, -27, -93, -90, -96, -90, -72, -95, -48, 9, + -1, -33, -46, 0, 55, 37, 50, 72, 68, 77, 20, -25, -15, 17, 40, 3, + -20, 22, 19, -12, -14, 2, 70, 105, 106, 92, 72, 104, 100, 48, 46, 83, + 98, 70, 3, -12, -16, -23, -11, -34, -8, 46, 47, 11, -21, 8, 57, 41, + 36, 53, 45, 48, -6, -64, -72, -57, -28, -61, -98, -65, -60, -94, -105, -103, + -41, 1, 0, -1, -29, -6, 5, -48, -60, -26, -3, -12, -74, -97, -86, -100, + -80, -89, -74, -6, 13, -10, -35, -18, 41, 48, 33, 64, 68, 75, 46, -15, + -25, -7, 24, 16, -20, 4, 33, 5, -11, -5, 43, 98, 105, 105, 85, 93, + 110, 67, 35, 59, 87, 81, 25, -13, -9, -23, -18, -27, -25, 30, 55, 37, + -1, -3, 46, 53, 29, 44, 47, 48, 20, -48, -72, -72, -47, -48, -93, -82, + -51, -73, -96, -102, -66, -6, 0, 5, -10, -16, 10, -26, -66, -49, -20, -10, + -51, -98, -86, -93, -93, -85, -88, -32, 14, 8, -16, -23, 22, 54, 32, 45, + 67, 70, 61, 4, -27, -21, 2, 17, -13, -13, 29, 26, -1, -5, 23, 83, + 104, 106, 100, 90, 110, 87, 40, 38, 68, 80, 45, -6, -9, -14, -24, -23, + -32, 8, 52, 53, 25, 1, 31, 60, 35, 30, 45, 45, 36, -24, -68, -76, + -67, -49, -80, -94, -57, -54, -81, -95, -82, -23, 2, 1, 4, -12, 4, -5, + -57, -65, -40, -20, -36, -87, -94, -83, -97, -87, -90, -57, 2, 18, 2, -12, + 8, 10, -20, 30, 25, 21, 14, 4, 15, -48, -33, 11, -70, 54, -5, -21, + -8, -3, 73, -52, 65, -55, 80, -28, -67, -3, -13, 21, -49, -2, 11, 36, + 59, -60, 34, -28, 21, -25, -45, 54, 5, 0, -19, -12, 20, 54, -51, -23, + 22, 36, -59, -20, 8, 28, -9, -54, 127, -44, 69, -128, 5, 69, -8, -98, + 45, 69, 20, -97, 23, -7, 121, -81, -2, -21, 51, -67, -14, -24, 127, -60, + 45, -116, 127, -29, -93, -23, 107, -5, -21, -62, 37, 41, 29, -74, -63, 103, + 24, -59, -44, 62, 43, -28, -46, 7, 72, 19, -70, -47, 42, 53, -68, -13, + 37, 59, -38, -60, 39, 66, 27, -128, 36, 77, 15, -74, -15, 75, 38, -49, + -11, -39, 16, -8, -30, 35, 41, -1, -2, 17, -68, 99, -97, 60, -49, 32, + -44, -29, 82, -26, 39, -35, 10, 38, -20, -21, -92, 83, -24, 13, 31, -33, + 22, 45, -31, -24, 9, -24, -32, 42, -17, 34, 7, -27, 6, 61, -9, -34, + -5, -8, -17, -6, -34, 17, 43, -9, 35, -34, 16, 27, -24, -17, -17, 5, + -17, 42, -31, 22, 17, -26, -22, 32, 41, -27, -25, -10, -5, 16, -2, 13, + -1, 48, -33, -27, 6, 16, 13, -37, -11, 18, 25, -42, -11, 46, -7, -15, + 9, 15, 4, -3, -36, -24, 31, -8, 14, 12, 27, -19, -17, -14, -7, 42, + -5, -15, 5, 1, -15, 14, 43, -19, 1, -25, -35, 16, 16, 29, -12, 8, + -14, 1, 21, -8, -12, -22, -4, 24, 26, -16, -22, 37, 3, -41, 7, 4, + 3, 30, 4, -27, 11, -6, -26, 33, 23, -23, -14, -20, -7, -4, 36, 0, + 18, 10, -27, 1, 1, 16, -1, -4, -44, -5, 17, 9, 13, -4, -3, 31, + 24, -14, -26, 9, -27, -28, 19, 22, 32, -11, -15, 5, 15, -23, -21, 16, + 14, 18, -11, -26, 13, 10, -12, -12, 11, 14, -6, -13, -3, 6, -6, 3, + 12, 32, 14, -22, -45, -10, 37, 11, -50, -11, 50, 22, -13, -4, -4, 15, + -16, -33, 7, 34, -9, -14, -1, 21, 15, -14, -12, -6, 7, 8, 2, 0, + -5, 6, 15, 4, -9, 13, 3, -51, -18, 27, 10, 5, -11, 6, -1, 5, + 22, 2, -14, -39, -12, 19, 17, 4, 11, 5, -25, 2, 23, 8, 2, -3, + -39, -22, 4, 18, 6, 14, 25, 20, -17, -20, 17, 7, -43, -38, -18, 17, + 24, -6, 30, 44, 6, -36, -20, 7, 24, 1, -69, -25, 47, 15, -4, 35, + 19, -18, -22, -12, 20, 39, -36, -49, 9, 28, -16, 9, 34, 36, -22, -69, + -16, 39, 7, -28, -3, 33, -18, -7, 18, 53, 24, -37, -61, -10, 38, 2, + -24, -11, 12, 17, 0, 28, 50, -5, -59, -57, 22, 14, -15, -5, 22, 9, + -20, 19, 33, 31, -33, -62, -13, -2, 45, -9, -4, -3, 19, 8, -8, 40, + 8, -16, -44, -19, 16, 3, 23, -32, 22, 5, -9, 5, 26, 21, -27, -18, + -45, 3, 15, 0, 7, 7, 7, 13, 18, -10, 3, -5, -30, -30, -3, 9, + 31, 17, -10, 19, 28, -33, -20, 31, 14, -67, -27, 13, 20, 29, 1, -2, + 24, -3, -26, -12, 32, -7, -31, -17, 5, 22, 11, -6, 6, 7, 2, 7, + 5, -12, -22, -17, -24, 22, 47, 1, 2, 10, 5, -29, -5, 13, 1, -30, + -28, -5, 23, 25, 6, 5, 1, 7, 0, 5, 3, -33, -37, -6, 19, 20, + 26, -1, -15, 21, 9, -14, -13, 0, -11, -24, -9, 9, 23, 1, 1, 32, + 11, -25, -18, 5, -5, -6, -9, -10, 2, 18, 4, 12, 6, -2, -8, 2, + 2, -7, 2, -22, -5, 17, 25, 15, -5, -1, -24, -8, -10, -5, 12, 7, + -4, -10, 4, 8, 22, 11, -1, -12, -31, -17, 6, 12, 11, 5, -3, -1, + 22, 0, -4, 3, -18, -17, -3, 16, 9, 2, -5, 0, 4, -9, 18, 17, + -22, -19, -8, -6, 21, 11, -6, -16, 33, 13, -15, -3, -15, 1, -3, -10, + -7, 8, 17, -11, 9, 19, 0, 5, 0, -18, -13, 2, -20, 10, 29, -11, + -13, 5, 11, 16, 4, -25, -21, 13, -5, 1, 3, -1, 6, 13, -7, -1, + 17, -6, -6, -9, -6, -3, -1, 1, 18, 11, -22, 2, 18, -2, -15, 1, + 5, -12, -10, -7, 9, 26, 10, -11, 5, 0, -7, -3, -11, -9, -3, 2, + -10, 19, 28, -3, -3, -4, 9, -14, -5, -7, 8, -3, -27, 5, 37, 11, + -2, 3, -27, -15, 12, -2, 14, 2, -8, -16, 22, 11, -1, 10, -17, -8, + -5, -23, 2, 29, 8, -21, 8, 12, 6, 8, -17, 3, -2, -12, -27, 16, + 25, -5, -7, 2, 19, 1, -15, 7, 2, -5, -34, 2, 18, 17, -10, 2, + 18, -1, -12, -10, 5, 1, -16, -9, 12, 21, 4, -10, 2, 12, 1, -19, + -11, 20, 5, -14, -21, 5, 17, -5, 3, 17, 4, -25, -5, 5, 4, 0, + -5, 2, 2, -1, 1, 13, 0, -11, -8, 3, 2, -1, -3, -3, 11, 8, + -6, 2, 7, 4, -5, -23, -2, 14, -1, -15, -2, 15, 10, 1, -4, 16, + 1, -24, -12, 8, 8, -20, -2, 14, 13, 10, 2, 2, -9, -6, -9, -3, + 5, 7, -3, -9, 0, 2, 8, 3, -1, 2, -4, 0, -1, -1, -1, -2, + -8, -14, -19, -28, -51, -53, -49, -48, -49, -44, -37, -30, -23, -14, -8, -11, + -5, 3, 11, 2, 0, 8, 19, 10, 1, 6, 18, 15, 4, 4, 17, 19, + 13, 9, 20, 27, 26, 26, 33, 42, 45, 53, 59, 68, 69, 83, 89, 92, + 85, 88, 91, 80, 56, 37, 29, 9, -25, -54, -65, -74, -94, -113, -112, -103, + -101, -103, -93, -79, -66, -62, -50, -41, -33, -27, -17, -11, -12, -8, 0, 7, + -1, -2, 5, 15, 8, -1, 3, 15, 13, 2, 2, 12, 17, 12, 8, 15, + 23, 24, 25, 29, 38, 42, 50, 56, 65, 68, 78, 87, 91, 87, 87, 91, + 84, 64, 43, 33, 16, -14, -44, -60, -70, -87, -107, -111, -105, -101, -103, -96, + -84, -70, -64, -55, -45, -36, -30, -22, -14, -14, -11, -4, 4, 0, -3, 1, + 11, 8, -1, 0, 10, 12, 3, 0, 9, 15, 11, 7, 14, 22, 23, 24, + 28, 37, 42, 49, 55, 64, 67, 78, 87, 91, 88, 88, 93, 86, 67, 47, + 36, 20, -10, -40, -56, -67, -84, -104, -109, -105, -101, -103, -96, -85, -71, -65, + -56, -46, -38, -31, -23, -16, -15, -12, -6, 2, -1, -5, 0, 9, 6, -1, + -1, 8, 11, 3, 0, 8, 14, 11, 7, 13, 21, 23, 23, 27, 37, 41, + 48, 54, 63, 67, 77, 86, 91, 89, 89, 93, 87, 70, 51, 39, 23, -6, + -36, -53, -64, -81, -101, -107, -103, -100, -102, -96, -85, -72, -66, -57, -47, -39, + -32, -25, -17, -16, -13, -7, 0, -3, -5, -1, 7, 6, -2, -2, 7, 9, + 2, -1, 7, 13, 10, 7, 12, 20, 22, 23, 27, 36, 41, 48, 54, 63, + 68, 77, 87, 91, 91, 91, 95, 89, 73, 54, 43, 27, -1, -31, -49, -61, + -78, -98, -105, -102, -99, -101, -96, -85, -73, -66, -58, -48, -40, -33, -26, -19, + -17, -14, -9, -2, -4, -6, -3, 5, 4, -3, -3, 5, 8, 1, -1, 6, + 12, 10, 7, 11, 20, 22, 23, 27, 35, 41, 47, 54, 62, 68, 76, 86, + 91, 91, 92, 96, 91, 76, 58, 46, 30, 3, -27, -45, -57, -75, -94, -103, + -100, -98, -100, -96, -85, -74, -67, -59, -49, -41, -34, -28, -20, -19, -15, -10, + -3, -5, -7, -4, 3, 3, -4, -4, 4, 7, 1, -2, 5, 11, 9, 6, + 11, 19, 21, 22, 26, 35, 40, 46, 53, 61, 67, 76, 86, 91, 92, 93, + 97, 93, 78, 61, 49, 33, 7, -22, -41, -54, -72, -91, -100, -99, -97, -100, + -96, -86, -74, -67, -60, -51, -42, -35, -29, -22, -20, -17, -11, -5, -6, -8, + -5, 2, 1, -5, -5, 2, 5, 0, -3, 3, 10, 8, 5, 10, 18, 21, + 21, 25, 34, 39, 45, 52, 61, 67, 75, 85, 91, 92, 94, 97, 94, 81, + 64, 52, 37, 11, -18, -37, -51, -69, -88, -98, -98, -96, -99, -95, -86, -75, + -68, -61, -52, -44, -36, -30, -23, -21, -17, -13, -6, -7, -9, -6, 0, 0, + -5, -5, 1, 4, -1, -3, 2, 8, 8, 5, 10, 17, 20, 21, 25, 33, + 39, 45, 51, 60, 66, 75, 85, 91, 93, 94, 98, 95, 83, 67, 55, 40, + 15, -14, -33, -48, -66, -85, -96, -96, -95, -98, -95, -86, -75, -69, -62, -53, + -45, -38, -32, -25, -22, -19, -14, -8, -9, -10, -8, -2, -1, -6, -7, -1, + 2, -2, -4, 1, 7, 6, 5, 8, 16, 19, 20, 24, 32, 38, 44, 50, + 59, 66, 74, 84, 91, 93, 95, 99, 97, 85, 70, 58, 43, 18, -10, -30, + -45, -63, -82, -93, -95, -94, -97, -95, -87, -76, -70, -63, -54, -46, -39, -33, + -26, -23, -20, -16, -10, -10, -12, -9, -3, -3, -7, -8, -2, 1, -2, -5, + 0, 6, 6, 4, 8, 15, 18, 20, 23, 31, 37, 43, 50, 58, 65, 74, + 83, 91, 93, 96, 100, 98, 87, 72, 61, 46, 22, -6, -27, -42, -60, -79, + -91, -94, -93, -97, -95, -87, -77, -70, -64, -55, -47, -40, -34, -28, -25, -22, + -17, -12, -11, -13, -11, -5, -4, -8, -9, -3, 0, -4, -6, -1, 5, 5, + 3, 7, 14, 18, 19, 23, 30, 36, 42, 49, 57, 65, 73, 83, 90, 94, + 96, 100, 99, 89, 75, 63, 49, 25, -2, -23, -38, -56, -76, -88, -92, -92, + -95, -94, -87, -77, -71, -65, -57, -48, -41, -36, -29, -26, -23, -19, -13, -12, + -14, -12, -7, -6, -9, -10, -5, -1, -4, -7, -2, 2, 5, 4, 6, 12, + 18, 20, 24, 30, 38, 45, 52, 61, 70, 79, 89, 99, 106, 109, 113, 115, + 109, 96, 81, 66, 44, 16, -12, -32, -52, -74, -92, -101, -104, -107, -108, -103, + -94, -85, -78, -70, -60, -52, -45, -38, -33, -29, -25, -19, -16, -17, -16, -12, + -9, -10, -12, -9, -5, -5, -7, -5, 0, 3, 3, 5, 11, 17, 20, 23, + 29, 37, 44, 51, 59, 69, 78, 88, 98, 105, 110, 114, 116, 110, 98, 84, + 69, 48, 20, -7, -29, -49, -71, -89, -99, -102, -105, -107, -103, -94, -86, -79, + -71, -62, -54, -47, -40, -34, -30, -26, -21, -18, -18, -17, -14, -10, -12, -14, + -11, -5, -10, 43, -94, 44, -13, 27, -98, 1, 9, 77, 63, 4, 8, -128, + 63, -73, 78, -116, 127, -14, 111, -87, -67, -43, -45, 38, 53, 99, -37, 14, + -51, -58, -23, -32, 34, 27, 75, 9, 51, -104, -71, -33, 27, 67, 0, -1, + 25, 0, -35, 1, -70, 28, -4, 109, 3, 5, -42, -7, 42, -15, 37, -62, + 67, -14, 48, -85, -46, -94, 37, 35, 23, 15, -79, 35, -50, 91, -64, 40, + -69, 46, 20, 43, -21, -51, 8, -1, 95, -47, 69, -104, 98, -44, 74, -61, + -14, -19, 7, 52, -40, 8, -89, 58, -53, 106, -106, 42, -82, 61, -1, -8, + -10, -59, 53, -18, 85, -83, 63, -73, 89, -32, 50, -62, 10, 13, 20, 62, + -81, 41, -84, 88, -32, 41, -78, 27, -30, 51, -6, -42, 6, -49, 74, -41, + 41, -89, 27, -33, 57, 0, -16, -8, -4, 45, 8, 20, -63, 36, -29, 75, + -23, -17, -23, -14, 45, -7, 17, -56, 20, -12, 45, -16, -13, -31, 6, 31, + -7, 17, -81, 40, -35, 73, -34, 0, -31, 10, 35, -4, 19, -60, 44, -30, + 83, -66, 41, -87, 59, -6, 23, -4, -59, 34, -33, 77, -70, 49, -89, 88, + -45, 63, -62, 4, -20, 18, 46, -49, 45, -101, 91, -56, 78, -79, 35, -51, + 67, -12, -2, -14, -49, 66, -35, 72, -87, 51, -74, 83, -38, 29, -36, -10, + 23, 3, 30, -59, 27, -59, 91, -44, 41, -63, 12, 2, 23, 8, -36, 14, + -35, 66, -38, 32, -59, 25, -11, 40, -6, -25, -2, -24, 55, -25, 29, -58, + 30, -17, 41, -18, -17, -3, -13, 50, -25, 26, -63, 35, -23, 50, -22, -5, + -18, 0, 33, -19, 22, -67, 57, -39, 63, -45, 6, -27, 13, 23, -6, 15, + -55, 44, -42, 70, -59, 36, -60, 56, -13, 15, -9, -50, 49, -38, 72, -63, + 37, -65, 67, -48, 55, -51, 10, 2, -5, 45, -61, 46, -83, 91, -58, 72, + -69, 23, -27, 35, -8, -3, -2, -33, 66, -61, 79, -100, 67, -60, 66, -26, + 13, -21, -13, 23, -11, 29, -49, 40, -53, 80, -67, 52, -63, 28, 6, -1, + 23, -45, 25, -30, 42, -25, 22, -42, 33, -26, 39, -26, -9, 10, -28, 61, + -50, 33, -43, 18, 2, 6, 4, -18, 4, -8, 24, -21, 22, -49, 50, -40, + 52, -35, -10, 17, -34, 64, -53, 38, -47, 37, -28, 40, -47, 33, -32, 28, + 3, -20, 30, -69, 79, -75, 88, -72, 39, -34, 22, -7, 9, -18, 1, 19, + -27, 58, -89, 81, -90, 89, -58, 42, -27, -5, 16, -21, 29, -34, 28, -37, + 59, -65, 72, -90, 69, -45, 31, 6, -36, 40, -53, 56, -47, 39, -42, 40, + -38, 50, -52, 34, -31, 7, 32, -47, 62, -79, 66, -51, 41, -27, 12, -10, + 12, -5, 3, -5, -18, 33, -44, 70, -75, 60, -52, 27, 4, -19, 22, -29, + 27, -15, 18, -31, 26, -36, 50, -41, 35, -31, 3, 19, -37, 55, -62, 51, + -38, 25, -11, 1, -13, 12, -7, 13, 4, -33, 38, -56, 72, -64, 52, -43, + 20, 6, -20, 25, -40, 34, -25, 38, -41, 43, -68, 68, -59, 53, -28, -7, + 27, -45, 63, -70, 56, -60, 59, -41, 48, -56, 39, -43, 35, -3, -19, 40, + -70, 85, -81, 76, -75, 48, -36, 41, -20, 12, -23, 0, 16, -23, 51, -76, + 78, -82, 80, -57, 29, -23, 3, 14, -2, 9, -29, 17, -31, 55, -51, 53, + -66, 49, -27, 17, 3, -35, 36, -33, 44, -27, 11, -30, 24, -18, 37, -29, + 4, -3, -15, 45, -47, 42, -57, 46, -19, 18, -11, -20, 10, -3, 24, -18, + 14, -46, 52, -50, 64, -57, 25, -14, 1, 33, -42, 30, -52, 50, -28, 47, + -54, 32, -49, 53, -25, 14, -4, -34, 57, -54, 69, -78, 46, -45, 52, -21, + 21, -37, 7, 1, 3, 29, -57, 56, -74, 90, -66, 47, -51, 16, 6, 10, + 10, -29, 9, -32, 58, -47, 59, -84, 65, -49, 52, -24, -18, 14, -30, 61, + -39, 31, -57, 39, -38, 67, -56, 37, -46, 26, 10, -15, 18, -49, 45, -27, + 42, -37, 11, -24, 30, -15, 21, -34, 15, -5, 11, 5, -24, 11, -16, 30, + -16, 6, -20, 7, 3, 11, -9, -5, -6, 4, 16, -15, 9, -29, 22, -6, + 14, -6, -16, 9, -12, 28, -22, 15, -27, 22, -11, 21, -23, 5, -10, 8, + 17, -22, 19, -42, 41, -31, 39, -37, 20, -20, 19, -3, -7, 2, -17, 27, + -20, 30, -43, 30, -34, 38, -24, 13, -13, -1, 16, -16, 19, -36, 28, -21, + 30, -22, 7, -17, 11, 2, 1, 1, -19, 22, -21, 32, -34, 18, -21, 17, + 6, -8, 5, -25, 21, -13, 24, -24, 12, -22, 24, -11, 10, -14, -7, 15, + -11, 28, -36, 21, -30, 30, -10, 10, -13, -5, 6, -2, 14, -22, 15, -25, + 33, -22, 23, -31, 11, -6, 8, 11, -21, 14, -28, 32, -23, 25, -31, 19, + -15, 19, -7, -7, 1, -13, 26, -19, 24, -37, 25, -24, 30, -18, 6, -9, + -2, 17, -16, 17, -34, 27, -19, 28, -21, 6, -15, 10, 4, 0, 2, -20, + 22, -19, -21, 0, -3, -3, 2, 1, -1, 2, -2, -1, 4, 3, -3, -15, + -21, -20, -23, -42, -45, -31, -27, -17, -8, 9, 29, 41, 44, 33, 20, 13, + 6, 12, 16, 25, 43, 44, 33, 33, 35, 15, -5, -3, 8, 16, 8, -10, + -6, 8, 4, -4, 1, -18, -38, -43, -51, -54, -55, -71, -85, -68, -58, -61, + -50, -33, -27, -15, -5, 22, 67, 100, 109, 114, 110, 91, 69, 50, 37, 35, + 46, 48, 37, 36, 14, -24, -38, -42, -38, -38, -59, -91, -86, -57, -44, -32, + -15, -26, -44, -30, -30, -30, -16, -31, -50, -34, -43, -59, -49, -44, -52, -62, + -69, -50, -4, 47, 83, 105, 120, 111, 88, 72, 55, 57, 76, 69, 59, 55, + 41, 10, -18, -32, -28, -19, -36, -68, -76, -72, -71, -46, -35, -47, -43, -43, + -61, -48, -28, -25, -22, -19, -23, -15, -7, 3, 4, -8, -28, -37, -5, 42, + 72, 107, 127, 122, 117, 90, 48, 37, 48, 51, 54, 56, 43, 24, -8, -37, + -33, -11, -28, -55, -61, -75, -75, -51, -58, -55, -33, -33, -41, -35, -30, -21, + -16, -17, -24, -26, -20, -18, -17, -12, -36, -72, -65, -45, -6, 53, 88, 106, + 119, 107, 71, 52, 50, 59, 75, 87, 85, 76, 43, -1, -7, 9, -1, -13, + -34, -69, -80, -74, -80, -73, -65, -67, -65, -56, -44, -33, -23, -18, -24, -25, + -16, -20, -9, -1, -21, -38, -55, -64, -40, 3, 39, 82, 113, 114, 95, 71, + 54, 56, 68, 76, 87, 94, 57, 10, -9, -17, -17, -15, -35, -60, -75, -89, + -92, -85, -76, -71, -74, -70, -53, -41, -20, -9, -9, 4, 4, 10, 33, 38, + 25, 15, -17, -43, -33, -15, 3, 40, 77, 94, 91, 69, 37, 31, 33, 37, + 68, 96, 82, 53, 25, 8, 22, 28, 9, -9, -27, -46, -56, -65, -62, -61, + -60, -51, -51, -39, -25, -23, -11, -3, -15, -10, 5, 12, 20, 18, -11, -41, + -52, -47, -34, -2, 33, 65, 82, 70, 51, 45, 28, 21, 49, 74, 86, 74, + 33, 5, 10, 14, 7, -10, -28, -45, -67, -68, -73, -76, -66, -66, -65, -46, + -39, -31, -9, -3, -6, 1, 8, 22, 41, 49, 33, 8, -16, -34, -30, -17, + 7, 49, 73, 64, 63, 50, 19, 5, 13, 32, 62, 65, 37, 8, -5, 4, + -1, -8, -15, -36, -50, -57, -71, -65, -53, -58, -49, -37, -40, -28, -10, -3, + 0, 2, -2, 5, 30, 41, 36, 22, -7, -33, -39, -46, -30, 15, 44, 56, + 72, 65, 44, 21, 2, 15, 42, 59, 49, 18, 2, -3, -4, 0, -10, -25, + -34, -52, -65, -59, -56, -50, -37, -33, -33, -25, -12, -2, 10, 12, 3, 6, + 27, 42, 52, 43, 16, -3, -24, -48, -41, -11, 16, 48, 67, 78, 75, 49, + 21, 13, 36, 64, 63, 47, 25, -1, -2, 2, -12, -18, -28, -53, -65, -71, + -76, -70, -55, -53, -49, -41, -35, -24, -1, 5, 1, 4, 8, 28, 51, 43, + 26, 18, -14, -42, -51, -49, -23, 5, 31, 55, 67, 58, 26, -2, 11, 35, + 49, 55, 35, 8, 3, -2, -5, -6, -13, -30, -38, -49, -61, -56, -45, -43, + -36, -31, -37, -25, -7, 1, 6, 1, -10, 11, 33, 29, 27, 17, -6, -34, + -58, -67, -57, -34, -4, 21, 50, 63, 37, 11, 8, 17, 45, 63, 55, 39, + 26, 12, 11, 10, -1, -11, -19, -35, -51, -52, -52, -45, -35, -36, -41, -31, + -24, -9, 9, -3, -12, 2, 19, 33, 40, 37, 25, -3, -30, -51, -59, -42, + -24, -3, 38, 58, 51, 32, 8, 2, 25, 45, 50, 49, 35, 18, 16, 19, + 10, 9, 4, -13, -27, -36, -45, -36, -24, -32, -29, -31, -33, -10, 6, 1, + -4, -6, 4, 19, 30, 37, 30, 12, -13, -48, -59, -57, -56, -35, 2, 31, + 48, 41, 12, -2, 7, 25, 41, 52, 44, 29, 25, 22, 18, 20, 15, 1, + -6, -26, -38, -28, -26, -21, -17, -31, -33, -19, -4, 0, -8, -16, -15, -11, + 9, 19, 22, 24, -2, -34, -49, -61, -70, -57, -32, 4, 38, 46, 26, 5, + -1, 7, 29, 45, 44, 38, 32, 23, 27, 30, 23, 24, 14, -8, -16, -24, + -24, -12, -10, -19, -27, -26, -9, -2, -4, -6, -16, -14, -2, 8, 23, 34, + 17, -6, -26, -47, -61, -62, -50, -18, 26, 50, 48, 31, 12, 6, 24, 40, + 44, 51, 40, 29, 34, 28, 27, 32, 20, 7, -5, -23, -26, -19, -9, -12, + -25, -25, -17, -8, 1, -4, -13, -12, -16, -9, 13, 26, 23, 8, -13, -37, + -55, -71, -78, -59, -18, 16, 35, 34, 8, -3, 4, 13, 31, 40, 34, 34, + 29, 23, 30, 31, 27, 21, 7, -6, -21, -21, -10, -10, -19, -24, -28, -17, + -6, -8, -9, -9, -19, -21, -5, 12, 23, 22, 5, -16, -34, -55, -80, -78, + -56, -22, 18, 33, 24, 14, 3, 7, 25, 31, 37, 41, 33, 29, 29, 32, + 33, 30, 24, 7, -16, -22, -18, -15, -14, -24, -31, -22, -13, -12, -8, -6, + -18, -27, -22, -6, -5, -1, -1, -1, 1, 2, 7, 13, 19, 10, -12, -31, + -13, 17, 29, -4, -29, 24, 53, 18, 92, 15, -15, 23, 13, -35, -52, 127, + 9, 3, -9, 31, -63, -64, -5, -50, 14, 33, -29, -42, 0, 43, 39, -15, + -59, -45, 3, 33, 12, -35, -10, 51, 18, 49, 55, -28, 16, 4, 3, -64, + 54, 53, -12, 0, 5, -4, -72, -7, -31, -14, 26, -2, -37, -14, 17, 35, + 4, -33, -45, -12, 15, 21, -16, -23, 22, 28, 12, 55, -7, -2, 7, 7, + -34, -10, 65, -4, 1, -5, 14, -46, -28, -9, -29, 13, 13, -23, -23, 4, + 27, 18, -17, -39, -25, 5, 20, 0, -26, 1, 34, 7, 41, 24, -20, 11, + 1, -6, -45, 53, 22, -6, -4, 9, -17, -52, -4, -30, -6, 20, -9, -29, + -8, 18, 27, -2, -33, -36, -6, 16, 13, -20, -16, 27, 19, 18, 49, -17, + 3, 2, 6, -42, 9, 55, -9, 1, -3, 9, -54, -19, -16, -24, 16, 7, + -27, -19, 8, 28, 12, -22, -40, -20, 8, 19, -7, -25, 9, 31, 7, 48, + 9, -14, 9, 2, -17, -35, 62, 9, -2, -6, 13, -30, -44, -4, -31, 2, + 18, -15, -27, -3, 22, 24, -8, -36, -32, -2, 17, 8, -23, -9, 31, 13, + 28, 40, -21, 8, 1, 3, -47, 29, 43, -9, 0, 1, 1, -57, -11, -22, + -17, 19, 2, -28, -14, 12, 29, 7, -27, -39, -14, 11, 17, -13, -22, 17, + 27, 10, 51, -4, -7, 7, 5, -27, -19, 64, -1, 1, -6, 14, -41, -34, + -8, -30, 8, 15, -20, -24, 2, 25, 20, -14, -38, -27, 2, 18, 2, -25, + -1, 33, 9, 37, 29, -21, 11, 0, -3, -46, 46, 29, -7, -2, 7, -9, + -54, -6, -27, -10, 20, -4, -28, -9, 16, 28, 1, -30, -37, -8, 14, 14, + -18, -17, 25, 22, 16, 50, -13, 1, 4, 5, -37, 0, 59, -7, 2, -4, + 12, -49, -24, -13, -26, 13, 11, -23, -19, 6, 27, 15, -19, -39, -21, 6, + 18, -4, -24, 7, 32, 8, 45, 15, -16, 10, 2, -12, -39, 58, 16, -3, + -5, 11, -22, -48, -4, -30, -2, 19, -10, -26, -4, 20, 25, -5, -34, -33, + -4, 16, 10, -21, -11, 30, 16, 25, 43, -19, 7, 1, 4, -44, 20, 49, + -8, 1, -1, 6, -54, -15, -19, -20, 17, 6, -26, -15, 10, 29, 9, -23, + -39, -16, 9, 17, -10, -22, 15, 29, 10, 50, 2, -10, 8, 3, -22, -26, + 63, 5, 0, -6, 14, -34, -39, -6, -30, 4, 17, -15, -24, 0, 24, 22, + -11, -36, -28, 1, 17, 5, -23, -3, 32, 12, 34, 33, -21, 10, 0, 0, + -46, 39, 36, -7, -1, 4, -3, -54, -9, -24, -14, 19, 0, -26, -10, 14, + 28, 4, -27, -37, -11, 12, 15, -15, -18, 22, 24, 14, 50, -9, -2, 5, + 5, -32, -8, 61, -3, 2, -5, 14, -44, -29, -10, -27, 10, 13, -20, -20, + 4, 26, 17, -16, -37, -23, 4, 18, -1, -23, 5, 32, 9, 42, 20, -18, + 11, 1, -7, -41, 53, 22, -4, -3, 9, -14, -50, -6, -27, -7, 19, -6, + -26, -5, 18, 26, -2, -31, -34, -6, 14, 11, -19, -12, 28, 19, 22, 45, + -17, 4, 2, 5, -40, 11, 54, -6, 2, -3, 10, -51, -20, -16, -23, 14, + 9, -23, -15, 8, 28, 12, -20, -38, -18, 7, 17, -7, -22, 13, 30, 10, + 47, 7, -12, 9, 2, -17, -31, 61, 10, 0, -5, 13, -26, -43, -6, -29, + 0, 18, -11, -23, -1, 22, 23, -8, -34, -30, -1, 15, 7, -22, -5, 31, + 14, 30, 37, -20, 9, 0, 2, -44, 30, 42, -7, 1, 2, 2, -53, -12, + -21, -17, 17, 4, -25, -11, 12, 28, 6, -25, -37, -13, 10, 15, -13, -18, + 20, 26, 13, 49, -5, -5, 6, 4, -27, -16, 62, 1, 2, -5, 14, -38, + -34, -9, -28, 6, 15, -16, -20, 3, 25, 19, -13, -36, -25, 2, 16, 1, + -23, 3, 32, 11, 38, 25, -19, 11, 0, -4, -43, 46, 29, -4, -2, 7, + -8, -51, -8, -25, -10, 18, -2, -25, -7, 16, 27, 0, -28, -35, -8, 12, + 12, -17, -13, 26, 21, 19, 46, -14, 2, 3, 4, -36, 2, 57, -4, 3, + -4, 12, -46, -25, -13, -25, 11, 12, -20, -16, 7, 27, 14, -18, -37, -20, + 5, 16, -5, -21, 10, 31, 10, 45, 12, -14, 10, 1, -12, -36, 57, 16, + -1, -4, 11, -20, -46, -6, -28, -4, 18, -8, -23, -3, 20, 24, -5, -32, + -31, -4, 13, 8, -20, -6, 29, 17, 27, 39, -19, 7, 0, 3, -42, 21, + 47, -6, 2, 0, 7, -51, -17, -18, -20, 15, 7, -23, -12, 10, 28, 8, + -22, -37, -15, 8, 15, -10, -19, 18, 27, 13, 47, 0, -8, 8, 3, -24, + -20, 52, -36, -2, 0, -2, 3, 5, -4, -28, 22, -43, 36, -13, -127, -43, + 2, -18, 126, 78, -127, -48, 68, -74, -67, 33, 62, 83, 42, -32, -46, -70, + -26, 115, 21, -66, 72, 52, -27, 44, 50, 50, 61, 28, -12, 3, -59, 49, + 3, -19, 39, 94, 16, 31, 6, 29, 3, -100, -1, -4, -60, 19, 7, -29, + -28, -38, -3, -47, -20, -21, -1, 5, -55, -12, -55, -39, 26, 47, -22, -9, + -41, -21, -19, -37, 0, 45, -56, 24, 75, -50, -9, 31, 28, 26, 13, -3, + -15, -27, 1, 1, -31, -10, 38, -1, 7, 43, 19, 21, 41, 33, 9, -17, + -3, -42, -76, -30, -8, -9, -1, 21, 22, 38, 32, 22, 0, -18, -32, -58, + -12, 5, -48, -13, 64, 29, -2, 2, 19, 43, 25, -19, -39, -69, -92, -15, + 23, 30, 30, 51, 37, 35, 37, 30, -27, -63, 5, -30, -56, -16, 26, 52, + 20, 14, 59, 27, -9, 22, -4, -20, -37, -17, -34, -34, -1, 35, 26, 31, + 5, -16, 4, 33, 22, 8, 5, -28, -41, -20, -10, -6, -2, -16, 12, 31, + -23, 7, -2, -39, -28, -13, 8, 5, 16, -4, -6, -18, -24, -27, -50, -6, + 5, 12, 0, -2, -14, -23, 5, -28, -10, 2, 28, 15, 2, 22, 27, 41, + 31, 2, 12, 31, 5, 12, -6, 15, 40, 34, 18, 26, 26, 12, 34, 23, + 34, 30, 22, 10, -26, -22, 1, 0, -1, 12, -4, -21, -5, -5, -20, -31, + -25, -24, -42, -44, -41, -41, -37, -29, -28, -29, -40, -17, -21, -38, -42, -38, + -40, -36, -13, -14, -8, -15, -7, -6, 5, 12, -1, -17, -1, 9, 2, 16, + 30, 27, 37, 36, 38, 36, 36, 19, 45, 45, 33, 26, 33, 28, 36, 31, + 17, 12, 22, 11, 11, 17, 5, -13, 6, 10, 2, -6, 2, 9, 15, -6, + -8, -23, -44, -3, -11, -35, -25, -35, -23, -21, 0, -11, -21, -17, 11, -6, + -11, -17, -33, -16, -16, -4, -7, -7, -9, -4, 1, 1, -3, 6, 7, 4, + -17, -11, -6, -4, 1, 3, 6, 4, 5, -4, 17, 7, 3, 9, -20, 0, + -7, -3, -5, 4, 9, 16, 2, 3, 8, 15, 15, 1, -3, 8, -1, 5, + 14, 7, 4, 8, -8, 2, -3, 5, 11, 5, 3, -4, 10, 17, 13, -11, + -5, 1, -3, 0, -6, -12, 2, -3, 13, -5, -25, -15, -7, 4, 1, -8, + -4, -12, -16, 3, 9, -6, 3, -21, -4, 4, -14, 1, -1, -2, 3, -8, + -5, 0, 7, -2, -3, -1, 3, -9, 5, -4, -17, -1, 9, 3, 7, 1, + -4, -3, 5, 2, -7, -9, 12, -6, -14, -16, 2, -1, 16, 2, 2, 7, + -6, -26, 3, -2, -4, -2, 10, 3, -7, 3, 8, 9, 5, 4, 1, -5, + -5, 11, 8, 7, 11, 12, -1, -5, -16, 13, 7, 2, 11, 4, -4, 9, + -8, -8, 14, 11, -8, 0, -1, -5, -2, -1, -10, -5, -9, -9, -16, -12, + -8, -16, 5, -10, -4, -11, -3, 1, 0, -3, -5, -13, -9, -2, -8, 5, + -9, -7, -2, 2, -11, -7, 13, 8, -3, 2, 7, -2, -1, 5, 0, 11, + 6, 13, 15, 1, -4, 9, 5, 3, 8, -3, -4, 16, 4, 11, 9, 0, + 8, 1, -6, -5, -18, 3, 7, -18, -4, 0, -3, -3, -6, -4, -5, -5, + -10, -2, -9, -5, -2, -4, -11, -2, 1, -5, -2, 11, -6, -9, 1, 4, + -6, -1, -5, 1, 2, 9, 5, 0, 4, 4, -2, 7, 0, -10, 5, 2, + -3, 0, -6, 7, -4, -3, 6, -1, -6, -1, -1, 2, -2, -6, -3, 0, + 8, -6, 4, -1, -5, -3, 3, 1, -5, -6, -2, -3, 5, 6, 0, 7, + -3, 3, -1, 0, -2, 9, 1, 1, -3, 4, 5, -5, 2, -2, 2, -11, + -2, -4, 11, 4, 5, 0, -5, -12, -6, -5, -5, 3, -2, -2, 2, 2, + 1, 0, -1, -8, -5, -5, -3, 2, -1, 3, -1, 3, 0, -1, 0, -1, + 1, 1, -4, -4, 2, -2, 1, -6, 1, 2, 4, 2, 2, -5, -1, 6, + -3, -1, -4, 11, 3, -9, -2, -6, -3, 2, 4, 2, 1, 2, 4, 3, + -6, -4, -3, -2, 0, 2, -2, 5, 2, -1, 3, -9, -3, -3, -4, -4, + -1, 0, -2, 7, 3, 1, 1, -2, -4, -2, -3, -2, -4, 2, 4, -1, + 2, 3, 0, 3, -1, 0, -2, -2, -3, 1, -1, -4, 5, -1, 5, 0, + -3, -2, -1, -4, 3, -1, -3, -2, -2, -1, 0, 0, 1, -1, 0, -2, + -2, 0, -3, -1, 0, 0, 1, 1, -2, -1, 1, -3, 1, 2, 0, -1, + 0, -1, 1, 5, -2, 1, -3, -3, -1, -3, 0, 1, 3, 2, -1, -1, + -2, -2, -1, 1, 0, -1, -2, -2, -2, -3, -3, -3, -2, -2, -2, -2, + -2, -2, -2, -1, 0, 1, 1, -2, -2, 0, 0, 2, -3, -16, -22, -20, + -28, -35, -31, -17, 19, 33, 36, 33, 34, 40, 36, 25, 18, 20, 18, 14, + 17, 12, 14, 10, -24, -36, -27, -38, -55, -69, -66, -47, -33, -13, 3, 5, + 10, 22, 25, 15, 28, 43, 41, 51, 56, 58, 58, 31, -18, -52, -64, -71, + -92, -105, -98, -77, -50, -17, 23, 59, 85, 99, 94, 76, 55, 14, -9, -5, + -7, -18, -17, -35, -53, -53, -33, -23, -33, -36, -15, 17, 32, 24, 12, 19, + 37, 54, 49, 38, 21, -14, -44, -30, -22, -15, 5, 8, -1, -26, -42, -46, + -49, -51, -37, -17, 1, -4, -19, -4, 45, 84, 91, 79, 57, 3, -30, -29, + -35, -25, -8, -6, -26, -61, -75, -73, -77, -72, -54, -19, 9, 6, -10, 3, + 47, 85, 92, 103, 92, 45, 21, 6, 4, 16, 27, 27, -1, -48, -69, -78, + -80, -84, -72, -33, -10, -24, -41, -20, 40, 82, 99, 123, 102, 69, 49, 30, + 27, 34, 42, 41, -2, -58, -96, -108, -103, -106, -83, -37, -10, -18, -38, -18, + 40, 65, 92, 110, 84, 44, 1, -26, -23, -7, 21, 32, 7, -39, -78, -84, + -79, -82, -61, -19, 5, -14, -52, -25, 25, 59, 102, 127, 116, 86, 40, 13, + 4, 9, 27, 29, 4, -47, -88, -94, -87, -83, -56, -18, 15, -13, -49, -30, + -2, 29, 69, 87, 80, 50, 9, -15, -27, -10, 18, 44, 36, -9, -45, -53, + -53, -46, -33, 6, 31, -8, -36, -28, -11, 21, 54, 76, 76, 44, 4, -33, + -53, -45, -18, 13, 10, -35, -62, -70, -61, -44, -19, 38, 63, 30, 9, 4, + 9, 35, 60, 81, 75, 51, 14, -25, -44, -37, -9, 29, 24, -11, -41, -59, + -51, -54, -33, 23, 35, 6, -13, -28, -18, 8, 43, 73, 76, 63, 33, -1, + -21, -22, 10, 43, 35, 5, -32, -47, -51, -68, -44, 6, 14, 0, -21, -34, + -25, 0, 37, 65, 73, 64, 35, 5, -22, -25, 11, 40, 39, 13, -20, -28, + -42, -64, -32, 6, 15, -1, -25, -39, -39, -16, 19, 44, 58, 53, 27, -2, + -39, -38, -2, 30, 40, 13, -16, -19, -45, -60, -29, 6, 17, 1, -21, -40, + -44, -24, 9, 38, 58, 51, 38, 8, -31, -29, 0, 34, 44, 9, -11, -23, + -58, -69, -42, -6, 9, 0, -16, -33, -36, -12, 19, 55, 72, 68, 58, 18, + -22, -25, -6, 29, 31, 2, -5, -23, -57, -69, -45, -8, 12, 10, 0, -22, + -24, -7, 20, 52, 61, 65, 59, 21, -15, -28, -11, 26, 20, 2, -2, -22, + -56, -71, -49, -14, 3, 8, -5, -26, -28, -19, 14, 42, 54, 71, 67, 38, + 8, -11, 16, 47, 37, 26, 18, -10, -51, -74, -59, -35, -19, -12, -24, -37, + -44, -34, 0, 24, 44, 67, 64, 43, 3, -18, 11, 35, 28, 22, 18, -4, + -47, -68, -55, -34, -11, -7, -15, -27, -43, -32, -1, 18, 42, 58, 60, 43, + -8, -29, -6, 11, 7, 4, 4, -17, -59, -75, -66, -41, -13, -3, 1, -11, + -29, -19, 1, 19, 42, 53, 64, 45, -8, -28, -9, 7, 4, 4, 9, -13, + -51, -71, -69, -43, -19, -7, 3, -11, -25, -17, -2, 23, 43, 60, 78, 55, + 1, -19, -5, 8, 3, 7, 13, -8, -41, -66, -67, -40, -19, 3, 16, 1, + -7, -5, 10, 34, 46, 67, 87, 62, 11, -13, -1, 8, 4, 15, 20, 1, + -33, -64, -65, -48, -30, -2, 6, -5, -14, -18, 1, 21, 32, 62, 86, 66, + 20, -3, 6, 7, 5, 16, 20, 7, -29, -62, -65, -59, -39, -13, -5, -8, + -22, -27, -6, 7, 17, 49, 74, 58, 14, -5, -2, -4, -3, 7, 14, 6, + -32, -59, -66, -63, -40, -16, -2, -2, -19, -20, -1, 6, 18, 49, 77, 62, + 21, 3, -1, -5, -2, 5, 18, 10, -26, -50, -65, -64, -43, -24, -5, -6, + -24, -23, -8, -2, 10, 45, 75, 60, 25, 6, -4, -4, -5, 3, 20, 8, + -20, -43, -60, -58, -45, -24, 1, -1, -15, -12, -1, 3, 16, 53, 83, 70, + 42, 19, 9, 7, 3, 16, 29, 17, -7, -35, -55, -56, -49, -24, 2, -1, + -11, -7, 3, 4, 16, 55, 83, 75, 50, 25, 15, 6, 0, 13, 21, 13, + -9, -40, -58, -66, -62, -35, -11, -11, -18, -13, -3, -7, 9, 49, 75, 74, + 51, 28, 19, 5, 1, 13, 20, 16, -3, -28, -48, -62, -61, -37, -16, -13, + -20, -15, -12, -19, -5, 21, 50, 61, 47, 28, 15, -1, -6, 0, 9, 14, + 1, -19, -37, -55, -56, -38, -16, -11, -13, -9, -9, -16, -8, 18, 48, 59, + 44, 28, 9, 15, -3, 2, -5, 3, 3, 4, 1, 7, -2, 7, -4, 2, + -124, -37, 33, -48, 7, -27, 8, -14, 77, 26, -9, 26, 7, 20, 10, 13, + 8, 9, 7, 4, 5, 2, 3, 2, 1, -1, 0, -3, -2, -5, 1, -10, + 11, 70, -6, 21, 5, 27, -2, 41, -15, -61, -66, -128, 0, -48, -21, -46, + -6, -55, 23, 53, -6, 11, 2, 14, 11, 10, 11, 8, 9, 9, 8, 5, + 8, 5, 6, 5, 6, 2, 7, -4, 6, 5, -23, 62, 29, 24, 8, 33, + 4, 32, 36, -30, -16, -124, -58, -39, -18, -51, -3, -43, -40, 53, 19, 12, + 4, 9, 12, 13, 10, 11, 9, 8, 11, 6, 5, 8, 6, 3, 9, 1, + 7, 2, -5, 22, -33, 20, 37, 35, 7, 29, 14, 8, 52, -5, 17, -64, + -84, -70, -15, -55, -23, -12, -72, 1, 28, 16, 8, 6, 7, 12, 10, 8, + 11, 6, 8, 10, 5, 4, 10, 1, 8, 4, 2, 10, -15, 26, -16, -9, + 14, 42, 17, 19, 29, -3, 42, 14, 28, -8, -45, -92, -37, -41, -54, 0, + -53, -48, 2, 18, 10, 8, 4, 8, 12, 8, 10, 10, 6, 9, 10, 2, + 10, 5, 3, 9, -2, 18, -16, 17, 3, -9, -12, 26, 28, 13, 35, 3, + 27, 19, 31, 17, 4, -60, -67, -33, -66, -22, -22, -58, -38, 2, 11, 9, + 7, 4, 9, 10, 8, 10, 9, 5, 12, 5, 5, 9, 2, 11, -5, 21, + -8, 4, 10, 5, -17, -1, 28, 11, 34, 13, 20, 17, 28, 24, 27, -6, + -61, -41, -57, -51, -17, -36, -56, -32, -1, 7, 8, 5, 6, 8, 10, 8, + 12, 6, 9, 9, 5, 9, 1, 15, -7, 15, 5, -2, 4, 14, -3, -18, + 15, 8, 28, 21, 20, 16, 23, 23, 29, 30, -20, -38, -45, -63, -38, -23, + -43, -53, -29, -5, 5, 5, 5, 5, 9, 7, 11, 8, 8, 10, 5, 12, + -2, 16, -1, 4, 11, 4, -3, 8, 15, -16, 0, 1, 16, 23, 23, 17, + 20, 21, 21, 39, 19, -14, -28, -52, -58, -33, -28, -47, -50, -30, -6, 2, + 5, 4, 6, 6, 9, 10, 7, 12, 3, 15, 0, 10, 8, 1, 6, 11, + 2, -4, 20, -1, -6, -5, 4, 15, 24, 20, 18, 23, 15, 30, 38, 13, + -6, -27, -56, -52, -30, -34, -48, -50, -28, -8, 2, 3, 5, 5, 6, 11, + 5, 13, 3, 12, 6, 5, 10, 5, 2, 7, 13, -8, 10, 11, 0, -6, + -4, 3, 17, 23, 16, 24, 18, 17, 36, 32, 13, -1, -30, -57, -45, -31, + -36, -51, -49, -28, -7, -1, 3, 6, 2, 11, 5, 12, 6, 9, 10, 5, + 8, 8, 5, -1, 16, 1, -1, 11, 9, -1, -5, -5, 4, 20, 17, 20, + 24, 14, 23, 37, 29, 16, 2, -33, -53, -42, -30, -39, -52, -49, -27, -9, + -3, 5, 0, 8, 5, 10, 8, 6, 10, 6, 7, 6, 11, -3, 8, 11, + 0, 2, 11, 8, -1, -5, -7, 9, 18, 16, 24, 20, 14, 27, 35, 27, + 21, 1, -33, -50, -38, -32, -42, -53, -48, -25, -14, -1, -2, 4, 3, 6, + 9, 5, 9, 7, 7, 4, 12, 4, 1, 10, 6, 2, 6, 10, 4, 0, + -6, -2, 11, 14, 18, 22, 17, 20, 32, 34, 28, 20, 0, -26, -36, -34, + -37, -45, -54, -44, -30, -13, -8, -3, 1, 2, 6, 4, 7, 8, 8, 2, + 8, 10, 1, 4, 6, 5, 5, 9, 6, 1, -3, -5, 3, 10, 14, 18, + 18, 17, 26, 35, 35, 29, 17, -1, -17, -24, -32, -41, -50, -51, -44, -28, + -18, -12, -5, -2, 2, 3, 3, 6, 9, 4, 3, 9, 6, 2, 2, 4, + 5, 9, 10, 4, -2, -5, -1, 5, 10, 14, 16, 15, 19, 30, 38, 37, + 29, 15, 1, -5, -14, -31, -43, -50, -52, -42, -29, -22, -16, -9, -3, 0, + 0, 2, 6, 6, 2, 4, 7, 6, 2, 1, 2, 6, 11, 10, 2, -5, + -4, 0, 5, 10, 14, 15, 14, 21, 32, 39, 38, 29, 14, 4, 0, -3, + -19, -32, -40, -43, -41, -36, -31, -25, -19, -12, -9, -8, -6, -1, 2, 2, + 0, -3, -4, -1, 3, 6, 6, 2, -3, -6, -2, 2, 2, 1, 2, 7, + 16, 25, 32, 35, 35, 36, 36, 33, 24, 11, -3, -18, -32, -40, -42, -40, + -36, -30, -25, -18, -12, -9, -8, -5, -1, 2, 2, 0, -3, -4, -1, 3, + 7, 6, 2, -4, -5, -2, 2, 2, 1, 2, 8, 17, 25, 32, 35, 36, + 36, 36, 32, 23, 10, -4, -20, -33, -41, -42, -40, -35, -30, -24, -18, -12, + -9, -8, -5, -1, 3, 2, -1, -4, -4, -1, 4, 7, 6, 1, -4, -5, + -2, -1, 3, 1, 3, 5, 3, -3, -1, -1, 1, -15, 1, 1, -5, -7, + 7, -2, -4, 3, -2, -5, -1, -3, -3, -1, 6, 3, 2, 3, -26, -117, + 35, -8, -19, 24, 58, -7, -6, 25, -9, 7, 4, 10, 2, 7, 6, 6, + 0, 6, -2, -1, -3, -3, 8, 71, 0, 17, 27, 20, -102, -115, 39, -32, + -18, -5, 58, -15, -12, 13, -10, -4, 1, 2, 1, 0, 6, 2, 1, 2, + 0, -4, 0, -5, 2, 67, 9, 14, 28, 29, -72, -126, 27, -25, -19, -14, + 58, -6, -11, 13, -5, -3, 3, 3, 4, 1, 8, 3, 3, 3, 3, -2, + 2, -3, -3, 62, 17, 14, 27, 35, -45, -128, 11, -19, -20, -22, 53, 1, + -12, 11, -3, -4, 2, 3, 4, 1, 7, 3, 3, 3, 3, -2, 2, -2, + -9, 57, 22, 14, 25, 37, -23, -125, -8, -15, -20, -30, 46, 9, -12, 10, + -2, -3, 0, 3, 3, 1, 6, 4, 2, 3, 2, -2, 1, 0, -16, 50, + 26, 13, 22, 37, -2, -117, -27, -13, -18, -36, 36, 16, -13, 9, -2, -2, + -2, 3, 2, 2, 4, 5, 1, 4, 2, -1, 0, 4, -20, 43, 29, 15, + 20, 36, 14, -102, -43, -15, -16, -40, 26, 22, -12, 8, -2, -2, -3, 3, + 1, 3, 2, 6, 1, 5, 1, 0, -1, 7, -23, 35, 31, 18, 18, 33, + 27, -83, -57, -20, -14, -42, 14, 26, -9, 7, -2, 0, -5, 3, 1, 4, + 1, 7, 0, 5, 1, 1, -2, 10, -24, 26, 31, 20, 17, 30, 36, -62, + -65, -27, -12, -43, 2, 28, -7, 6, -2, 0, -5, 3, 0, 4, 0, 7, + 0, 5, 1, 2, -4, 11, -23, 17, 32, 22, 16, 27, 42, -44, -67, -36, + -9, -42, -8, 28, -3, 5, -1, 1, -5, 2, 0, 4, 1, 7, 1, 5, + 1, 3, -5, 13, -22, 10, 31, 23, 17, 22, 45, -25, -66, -45, -8, -40, + -18, 27, 0, 5, -1, 1, -5, 1, 0, 4, 0, 6, 2, 4, 2, 3, + -6, 14, -19, 2, 29, 25, 19, 19, 47, -10, -60, -54, -10, -37, -27, 24, + 4, 4, 0, 1, -5, 0, 0, 3, 1, 5, 2, 4, 2, 4, -7, 15, + -16, -4, 27, 25, 21, 15, 48, 4, -51, -61, -12, -33, -34, 19, 7, 4, + 1, 0, -4, -1, 0, 3, 2, 5, 3, 3, 3, 5, -8, 15, -11, -10, + 24, 25, 23, 12, 45, 15, -39, -66, -18, -28, -40, 12, 10, 4, 2, 1, + -3, -2, 0, 2, 2, 4, 3, 3, 3, 5, -8, 13, -6, -14, 19, 25, + 25, 10, 43, 24, -25, -67, -25, -24, -45, 4, 11, 5, 3, 0, -2, -3, + -1, 1, 2, 3, 3, 3, 2, 6, -9, 11, -2, -17, 15, 24, 27, 9, + 39, 31, -13, -66, -33, -19, -48, -3, 11, 5, 3, 1, -2, -3, -1, 1, + 2, 4, 3, 3, 2, 8, -9, 9, 3, -18, 10, 22, 29, 9, 35, 35, + 0, -61, -41, -17, -49, -11, 10, 6, 3, 2, -2, -3, -2, 1, 1, 4, + 3, 5, 1, 9, -9, 7, 6, -18, 5, 20, 29, 10, 32, 38, 11, -47, + -45, -18, -47, -20, 5, 6, 4, 2, -1, -3, -2, 0, 1, 5, 1, 6, + 1, 7, -7, 6, 6, -16, 1, 16, 27, 11, 29, 40, 20, -30, -43, -23, + -46, -28, -2, 4, 4, 2, -1, -3, -2, -1, 0, 6, -1, 7, 2, 5, + -6, 5, 6, -15, -3, 13, 25, 12, 26, 41, 26, -14, -36, -26, -44, -35, + -11, 1, 4, 2, 0, -4, -3, -3, -1, 7, -2, 7, 4, 4, -6, 4, + 7, -13, -6, 10, 23, 12, 24, 42, 31, 0, -24, -28, -42, -40, -19, -4, + 4, 2, 1, -4, -3, -4, -3, 8, -3, 6, 6, 3, -6, 4, 7, -11, + -8, 7, 20, 12, 21, 41, 34, -2, -31, -34, -29, -21, -12, -3, -4, -10, + -7, -5, -6, -4, 5, 8, -3, -1, 7, -1, -11, -7, 0, 1, 6, 16, + 28, 33, 33, 30, 13, -1, -26, -35, -30, -24, -14, -5, -4, -11, -7, -5, + -6, -6, 3, 8, -2, -2, 7, 1, -11, -9, -1, 0, 4, 14, 26, 32, + 33, 32, 17, 3, -22, -34, -31, -25, -16, -6, -3, -10, -8, -5, -6, -7, + 2, 9, 0, -3, 6, 3, -9, -10, -2, 0, 3, 12, 24, 32, -1, 0, + -3, -1, -8, -5, -16, -5, -14, -4, -13, -5, -1, -7, 16, -17, 28, -16, + 47, 1, 70, 35, 97, 71, 98, 66, 32, -5, -71, -69, -122, -69, -105, -33, + -67, -6, -35, 2, -12, -2, 4, -12, 16, -19, 29, -16, 44, 2, 66, 37, + 92, 76, 95, 74, 33, 5, -69, -63, -122, -69, -106, -36, -66, -11, -33, -3, + -9, -7, 7, -16, 18, -22, 29, -17, 42, 3, 61, 40, 86, 81, 91, 82, + 34, 15, -67, -57, -122, -69, -105, -40, -64, -17, -29, -9, -6, -12, 10, -20, + 20, -23, 28, -17, 39, 4, 56, 42, 80, 85, 88, 89, 35, 24, -63, -53, + -119, -70, -104, -45, -62, -22, -26, -14, -2, -16, 12, -23, 20, -25, 27, -16, + 35, 7, 51, 45, 74, 89, 85, 96, 38, 32, -58, -49, -116, -72, -102, -50, + -60, -27, -24, -19, 0, -20, 14, -24, 20, -24, 24, -14, 31, 10, 45, 48, + 69, 92, 82, 102, 40, 39, -53, -45, -112, -74, -100, -55, -57, -33, -21, -24, + 3, -24, 15, -26, 19, -24, 22, -12, 27, 12, 40, 50, 63, 95, 80, 106, + 43, 45, -47, -42, -107, -76, -97, -60, -55, -38, -18, -28, 4, -26, 15, -27, + 18, -23, 19, -10, 23, 15, 35, 53, 59, 97, 78, 110, 47, 50, -39, -39, + -102, -79, -94, -65, -52, -43, -16, -32, 5, -28, 14, -27, 16, -21, 15, -7, + 18, 18, 30, 55, 54, 98, 76, 113, 51, 55, -32, -37, -96, -81, -91, -70, + -50, -48, -15, -35, 6, -30, 13, -26, 13, -19, 11, -5, 13, 20, 25, 56, + 50, 99, 75, 115, 56, 59, -24, -35, -90, -83, -88, -75, -48, -52, -14, -38, + 5, -30, 11, -25, 10, -17, 7, -2, 9, 22, 21, 57, 47, 99, 75, 116, + 61, 62, -15, -33, -82, -86, -84, -80, -47, -56, -14, -39, 4, -30, 9, -24, + 6, -15, 3, 1, 5, 24, 17, 57, 44, 98, 75, 116, 66, 65, -6, -31, + -75, -88, -81, -83, -46, -59, -14, -41, 3, -30, 6, -22, 3, -12, -1, 3, + 1, 26, 13, 57, 41, 96, 75, 115, 72, 68, 2, -29, -69, -89, -78, -87, + -45, -62, -15, -42, 0, -29, 3, -20, -1, -10, -5, 5, -2, 26, 11, 56, + 40, 94, 76, 114, 77, 69, 12, -28, -61, -91, -75, -89, -45, -64, -16, -42, + -2, -28, 0, -18, -5, -8, -9, 7, -6, 27, 8, 55, 38, 91, 77, 112, + 82, 71, 20, -25, -55, -91, -73, -91, -46, -65, -18, -42, -5, -26, -4, -15, + -10, -5, -13, 9, -9, 27, 7, 53, 37, 88, 78, 110, 87, 72, 29, -23, + -48, -90, -71, -93, -47, -66, -21, -41, -9, -24, -8, -13, -13, -3, -16, 9, + -11, 27, 5, 51, 37, 84, 79, 108, 93, 74, 37, -20, -42, -90, -70, -94, + -49, -66, -24, -40, -12, -23, -12, -12, -16, -2, -18, 10, -12, 25, 5, 48, + 37, 80, 81, 105, 98, 75, 45, -16, -36, -88, -68, -94, -51, -66, -28, -39, + -16, -21, -15, -10, -19, -1, -21, 10, -13, 24, 4, 45, 37, 76, 82, 102, + 102, 76, 52, -13, -30, -85, -67, -94, -54, -66, -31, -38, -20, -19, -19, -9, + -22, 0, -22, 9, -14, 22, 4, 41, 37, 71, 83, 99, 105, 77, 59, -8, + -25, -82, -67, -93, -56, -65, -35, -37, -23, -18, -22, -7, -25, 0, -24, 8, + -14, 20, 5, 37, 38, 67, 84, 96, 108, 79, 65, -3, -20, -79, -66, -92, + -59, -65, -39, -36, -27, -17, -25, -7, -27, -1, -24, 6, -14, 17, 6, 34, + 39, 63, 84, 93, 111, 80, 71, 1, -15, -75, -66, -90, -62, -64, -43, -35, + -31, -16, -28, -6, -28, -1, -25, 5, -14, 14, 6, 30, 39, 58, 85, 90, + 113, 82, 76, 7, -11, -70, -66, -88, -66, -62, -46, -34, -34, -15, -30, -7, + -30, -2, -25, 2, -13, 11, 7, 26, 40, 53, 84, 87, 115, 84, 81, 13, + -7, -65, -66, -85, -68, -61, -50, -33, -37, -15, -32, -7, -30, -4, -25, 0, + -12, 7, 9, 19, 37, 52, 80, 97, 118, 113, 98, 54, 7, -41, -72, -87, + -87, -75, -65, -47, -42, -29, -30, -22, -24, -19, -19, -14, -9, -2, 8, 17, + 36, 50, 77, 95, 117, 115, 101, 60, 13, -35, -69, -85, -88, -75, -66, -49, + -44, -31, -31, -23, -25, -20, -20, -15, -9, -2, -1, 0, 0, 0, 0, -1, + -1, -1, 3, 9, 14, 14, 10, -3, -17, -13, 1, 1, 23, 33, -14, -55, + -59, -80, -75, -35, -7, 51, 40, -29, -35, -53, -128, -31, 111, 72, 46, 55, + -19, -73, -23, 14, 64, 104, 87, 105, 68, -54, -76, -1, -18, 12, 92, 23, + -79, -93, -105, -119, -64, -20, 39, 70, 2, -45, -52, -107, -82, 73, 106, 56, + 53, 12, -57, -37, 14, 52, 105, 101, 94, 85, -5, -75, -25, -1, -8, 59, + 52, -45, -89, -94, -117, -90, -42, 1, 53, 29, -29, -45, -79, -104, 3, 99, + 78, 63, 42, -25, -49, -7, 30, 83, 112, 103, 99, 40, -54, -58, -11, -7, + 36, 68, -4, -80, -98, -114, -106, -57, -15, 33, 42, -10, -46, -66, -97, -45, + 68, 90, 67, 53, 4, -40, -20, 18, 60, 103, 107, 100, 69, -15, -62, -31, + -9, 15, 60, 31, -50, -90, -108, -115, -79, -33, 11, 42, 15, -33, -58, -87, + -75, 21, 87, 79, 63, 27, -26, -33, 1, 40, 88, 111, 105, 85, 20, -50, + -49, -17, 5, 46, 49, -17, -77, -102, -115, -95, -49, -7, 31, 28, -15, -50, + -76, -84, -21, 64, 84, 71, 45, -4, -32, -13, 22, 66, 103, 108, 95, 50, + -23, -56, -32, -5, 30, 55, 14, -53, -92, -111, -107, -68, -24, 16, 34, 4, + -37, -66, -85, -53, 32, 81, 77, 58, 17, -25, -24, 6, 46, 89, 108, 101, + 71, 6, -49, -45, -16, 15, 49, 36, -26, -77, -103, -110, -85, -41, 0, 30, + 20, -21, -55, -79, -72, -5, 65, 81, 67, 36, -10, -28, -8, 27, 71, 102, + 104, 85, 34, -31, -51, -29, 1, 37, 48, 2, -57, -93, -109, -97, -58, -16, + 20, 28, -4, -42, -70, -79, -36, 39, 78, 74, 51, 9, -24, -18, 11, 51, + 91, 105, 94, 57, -6, -48, -41, -12, 22, 48, 26, -33, -79, -103, -104, -74, + -32, 6, 28, 12, -27, -60, -78, -59, 8, 66, 78, 62, 27, -13, -24, -3, + 33, 74, 100, 99, 74, 20, -35, -48, -25, 8, 40, 40, -7, -61, -94, -106, + -88, -49, -9, 21, 21, -11, -47, -72, -71, -22, 45, 76, 71, 43, 2, -22, + -13, 16, 56, 91, 101, 85, 43, -15, -47, -36, -6, 28, 45, 16, -38, -80, + -102, -97, -65, -24, 11, 25, 4, -33, -63, -75, -46, 18, 66, 75, 56, 19, + -15, -20, 2, 38, 77, 98, 93, 62, 8, -38, -44, -20, 14, 41, 32, -15, + -64, -94, -101, -79, -40, -2, 22, 15, -17, -52, -72, -61, -9, 49, 74, 66, + 36, -2, -21, -9, 22, 61, 91, 96, 76, 31, -22, -45, -32, 0, 32, 40, + 7, -43, -82, -99, -89, -56, -17, 14, 21, -2, -38, -65, -69, -33, 26, 66, + 71, 50, 13, -16, -16, 7, 43, 79, 95, 85, 50, -2, -40, -40, -14, 20, + 40, 24, -22, -66, -93, -95, -70, -32, 3, 21, 9, -23, -55, -70, -51, 1, + 52, 71, 60, 28, -6, -19, -4, 27, 64, 90, 91, 66, 19, -27, -43, -26, + 6, 34, 35, -1, -48, -83, -96, -81, -47, -10, 16, 17, -9, -43, -66, -62, + -22, 33, 66, 67, 43, 7, -16, -13, 12, 48, 80, 91, 77, 39, -10, -40, + -36, -8, 24, 38, 17, -28, -69, -92, -89, -62, -25, 7, 19, 4, -29, -58, + -67, -42, 10, 55, 70, 55, 22, -9, -17, 0, 33, 68, 90, 86, 57, 10, + -31, -41, -21, 12, 36, 30, -8, -53, -85, -94, -75, -41, -5, 17, 13, -15, + -48, -67, -57, -13, 39, 68, 64, 37, 3, -16, -9, 18, 54, 84, 91, 72, + 30, -17, -41, -33, -2, 28, 37, 10, -35, -74, -94, -86, -56, -19, 10, 17, + -2, -36, -63, -66, -34, 19, 60, 70, 51, 17, -11, -15, 5, 39, 74, 92, + 83, 49, 1, -36, -40, -16, 18, 37, 24, -17, -61, -90, -93, -70, -34, 1, + 18, 8, -22, -55, -69, -50, -2, 47, 70, 61, 31, -3, -17, -5, 26, 62, + 88, 90, 65, 19, -25, -42, -27, 5, 33, 33, 1, -45, -81, -95, -81, -48, + -11, 14, 15, -10, -43, -66, -61, -22, 31, 65, 68, 43, 9, -14, -11, 12, + 49, 80, 92, 76, 38, -10, -39, -36, -8, 24, 38, 16, -27, -70, -92, -89, + -61, -25, 7, 17, 3, -31, -59, -68, -39, 8, 55, 55, 19, 0, -9, -10, + -14, -13, -21, -30, -32, -44, -49, -57, -65, -72, -83, -98, -104, -117, -123, -128, + -127, -128, -128, -128, -128, -127, -128, -120, -117, -109, -100, -90, -83, -72, -66, -55, + -50, -33, -42, -18, -29, -18, 15, -6, 11, 7, 19, 3, 38, 5, 48, 44, + 64, 57, 97, 82, 111, 104, 110, 107, 120, 116, 125, 126, 126, 126, 126, 127, + 117, 125, 123, 100, 127, 101, 124, 102, 121, 109, 126, 96, 125, 116, 127, 90, + 119, 87, 127, 90, 118, 95, 123, 93, 106, 90, 100, 104, 74, 84, 73, 97, + 72, 71, 57, 66, 80, 36, 59, 38, 55, 35, 57, -6, 64, 10, 25, 19, + 19, -22, 65, -26, 14, 2, -17, -12, 22, -40, -3, -31, -24, -38, -1, -56, + -6, -48, -36, -54, -19, -56, -33, -49, -69, -49, -52, -53, -60, -61, -84, -76, + -85, -96, -95, -95, -114, -93, -117, -104, -93, -101, -98, -100, -101, -96, -78, -95, + -71, -70, -72, -52, -63, -70, -43, -77, -41, -48, -65, -53, -53, -59, -42, -56, + -37, -64, -54, -52, -50, -54, -56, -54, -55, -62, -51, -47, -44, -67, -60, -63, + -56, -64, -53, -48, -61, -53, -58, -38, -48, -32, -38, -34, -28, -26, -23, -25, + -22, -6, -7, -12, -1, 5, 6, 6, -7, 22, -4, 27, 15, 18, 24, 37, + 30, 47, 24, 53, 29, 63, 29, 46, 46, 51, 52, 53, 36, 54, 65, 55, + 33, 64, 36, 69, 54, 26, 62, 66, 36, 68, 30, 47, 54, 58, 20, 55, + 31, 40, 50, 35, 19, 56, 33, 25, 46, 18, 22, 42, 21, 25, 32, 19, + 19, 26, 18, 23, 29, 24, 7, 27, 6, 33, 8, 17, -2, 14, 3, 23, + 14, 7, 5, -9, -13, -10, -23, -12, -16, -27, -8, -18, -15, -3, -18, -24, + -5, -23, -9, 0, -11, 4, -1, 4, 2, 5, -2, 3, -1, -7, 4, -11, + 1, -12, -4, -7, -10, -11, -11, -16, -23, -15, -20, -22, -23, -20, -30, -23, + -31, -25, -32, -35, -41, -34, -44, -39, -34, -49, -33, -30, -36, -29, -33, -14, + -24, -32, -18, -15, -7, -9, -11, 5, -14, 27, -11, 16, -10, 13, -9, 23, + -10, 19, 10, 18, 11, 29, 1, 47, 27, -4, 45, 3, 43, 40, 14, 13, + 57, 16, 34, 27, 22, 30, 32, 14, 24, 27, 20, 20, 17, 4, 20, 20, + 8, 8, 0, 10, -3, 17, -8, -1, -4, 1, 0, 6, -7, -3, -3, -13, + -5, -6, -18, -5, -28, -12, -13, -5, -11, -5, -28, -7, -15, -10, -6, -28, + -16, -12, -17, -8, -10, -19, -10, -24, -30, -32, -26, -31, -36, -32, -33, -27, + -25, -26, -26, -25, -25, -23, -16, -22, -10, -11, -7, -7, 4, -10, 10, -9, + 11, -8, 4, -6, 4, -8, 3, -4, 2, -3, -5, -3, -11, -8, -6, -12, + -11, -7, -24, -4, -17, -9, -18, -28, -16, -29, -23, -38, -24, -34, -22, -38, + -18, -27, -10, -22, -19, -21, -2, -23, 10, -19, 0, 4, 16, 7, 0, 3, + 17, 14, 26, 8, 25, 27, 30, 25, 38, 31, 49, 37, 42, 45, 48, 55, + 63, 46, 54, 54, 56, 59, 56, 47, 50, 53, 47, 50, 44, 42, 35, 40, + 31, 37, 35, 27, 20, 23, 19, 26, 24, 18, 11, 14, 18, 24, 18, 12, + 10, 3, 12, 2, 9, 4, 0, 0, 3, -4, 11, 1, 1, -1, -5, -7, + 1, -6, -1, 2, -4, 1, -1, -7, -9, -11, -21, -19, -20, -28, -27, -22, + -29, -24, -26, -32, -22, -25, -31, -24, -19, -22, -11, -19, -15, -4, -5, -4, + 0, -6, -6, 2, -9, -5, -5, -9, -10, -7, -18, -8, -14, -14, -19, -29, + -25, -16, -25, -30, -30, -30, -21, -29, -38, -37, -36, -41, -44, -53, -48, -43, + -44, -55, -46, -40, -33, -36, -40, -40, -28, -25, -24, -23, -17, -15, 1, -3, + -1, 5, 2, 9, 1, 4, 12, 13, 14, 15, 9, 21, 26, 32, 31, 28, + 28, 41, 38, 49, 45, 46, 53, 56, 57, 57, 57, 58, 55, 48, 56, 56, + 56, 45, 39, 41, 41, 44, 42, 25, 28, 27, 24, 28, 21, 14, 17, 8, + 15, 22, 13, 15, 16, 3, 11, 10, 4, 6, 4, -8, 0, -2, -2, -3, + -2, 1, 3, -3, -3, -6, -8, -5, 4, 3, 2, -4, -2, -1, 5, 3, + -2, -2, -2, 3, 7, -2, -26, -37, -34, -30, -13, -14, -21, -24, -27, -24, + -13, -7, -15, 6, 3, -30, -50, -48, -47, -41, -26, -8, 28, 43, 38, 57, + 63, 56, 75, 118, 127, 117, 99, 86, 85, 66, 46, 59, 80, 69, 43, 27, + -6, -47, -74, -80, -71, -57, -40, -44, -56, -78, -88, -78, -59, -52, -51, -56, + -57, -47, -36, -36, -39, -39, -32, -17, 6, 24, 33, 10, -14, -14, -2, -11, + -20, -15, -24, -28, -28, -25, -28, -54, -73, -65, -43, -18, 6, 27, 21, 23, + 17, 22, 18, 16, 31, 50, 45, 25, 22, 8, -20, -17, 8, 29, 10, -22, + -41, -45, -51, -53, -31, -18, -23, -7, 37, 54, 38, 36, 60, 100, 119, 120, + 122, 125, 110, 88, 94, 99, 90, 85, 82, 54, 26, -5, -49, -83, -85, -67, + -36, -14, -30, -55, -76, -86, -65, -41, -45, -60, -53, -43, -35, -34, -41, -43, + -45, -35, 10, 40, 32, 3, -3, -14, -30, -38, -33, -23, -29, -26, -18, -10, + -17, -37, -46, -58, -61, -45, -17, -4, -2, 19, 31, 27, 13, 22, 38, 49, + 59, 69, 60, 23, -13, -11, 13, 24, 19, 24, 8, -30, -58, -58, -66, -85, + -90, -61, -19, -1, -11, -5, 25, 42, 61, 92, 109, 106, 110, 104, 93, 93, + 89, 82, 86, 81, 71, 51, 13, -40, -74, -87, -73, -35, -24, -50, -71, -73, + -53, -50, -58, -68, -60, -61, -54, -30, -25, -40, -52, -25, 13, 32, 45, 49, + 44, 28, 22, 29, 32, 20, 3, 7, 6, 0, -1, -4, -30, -63, -69, -62, + -57, -49, -25, 2, 17, 24, 27, 30, 10, 4, 38, 77, 66, 32, 13, 7, + 0, 9, 31, 43, 23, -11, -25, -23, -46, -83, -87, -63, -42, -19, -6, -3, + 6, 27, 49, 81, 108, 121, 123, 124, 115, 110, 98, 80, 78, 77, 77, 69, + 54, 8, -56, -99, -92, -53, -46, -64, -75, -73, -70, -75, -62, -67, -86, -88, + -54, -28, -33, -46, -50, -40, -24, -3, 29, 51, 48, 34, 44, 44, 30, 18, + 13, -3, -15, -7, -1, -10, -36, -56, -65, -79, -100, -91, -64, -52, -40, -5, + 20, 9, -14, -9, 21, 49, 59, 58, 49, 25, -1, 11, 39, 39, 22, 19, + 20, 8, -19, -49, -72, -69, -58, -43, -27, -24, -13, -5, 12, 38, 74, 97, + 110, 124, 126, 126, 114, 105, 100, 87, 91, 108, 115, 73, 5, -41, -49, -49, + -53, -45, -49, -69, -77, -60, -51, -71, -94, -96, -68, -49, -46, -44, -45, -60, + -60, -27, 0, 11, 26, 37, 37, 37, 40, 42, 34, 8, -1, 14, 15, -5, + -12, -18, -44, -75, -85, -88, -98, -99, -76, -36, -12, -19, -24, -11, -9, 1, + 36, 71, 58, 29, 13, 17, 33, 33, 30, 35, 44, 44, 27, -3, -39, -51, + -61, -55, -41, -31, -25, -29, -21, -1, 23, 46, 76, 102, 109, 110, 116, 118, + 92, 61, 76, 112, 120, 93, 57, 14, -28, -54, -50, -46, -60, -83, -82, -64, + -62, -82, -89, -93, -101, -88, -59, -52, -64, -75, -76, -63, -50, -30, -1, 9, + 8, 11, 32, 44, 36, 29, 32, 27, 20, 22, 28, 24, 0, -21, -30, -45, + -78, -97, -83, -66, -50, -32, -17, -16, -23, -20, 4, 38, 51, 47, 37, 28, + 29, 27, 27, 31, 42, 54, 55, 43, 20, -5, -29, -40, -37, -30, -27, -23, + -15, -12, -11, 8, 43, 67, 78, 100, 122, 126, 107, 84, 81, 92, 106, 115, + 110, 79, 31, -3, -13, -26, -47, -56, -56, -58, -58, -56, -59, -72, -86, -84, + -66, -57, -56, -56, -60, -74, -74, -51, -32, -24, -14, 3, 14, 15, 19, 28, + 33, 19, 11, 22, 29, 18, 8, 9, 0, 0, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, + -1, -1, -1, -1, -1, -1, -1, 0, -1, -3, -2, -1, 0, 2, -4, -13, + -21, -23, -19, -8, 7, 17, 23, 26, 33, 38, 32, 17, -5, -17, -24, -20, + -6, -3, -16, -29, -26, -17, -5, -1, 2, 7, 11, 17, 15, 9, 9, 3, + 10, 15, 9, -14, -33, -27, -18, -6, -7, -10, -6, 0, 12, 15, 29, 38, + 36, 32, 11, 0, -30, -45, -50, -39, -23, -27, -24, -15, 6, 25, 37, 51, + 46, 40, 0, -19, -22, -34, -30, -40, -45, -51, -34, -1, 25, 48, 40, 43, + 51, 64, 58, 5, -22, -49, -63, -69, -68, -58, -54, -16, 13, 44, 66, 61, + 68, 72, 86, 47, -17, -56, -82, -88, -93, -72, -58, -40, 4, 45, 94, 98, + 84, 65, 68, 71, 15, -46, -88, -90, -88, -85, -62, -56, -34, -4, 41, 80, + 82, 74, 54, 70, 66, 25, -29, -70, -74, -90, -87, -79, -73, -46, -10, 54, + 90, 103, 88, 76, 90, 69, 25, -38, -76, -96, -119, -111, -103, -81, -57, -12, + 50, 90, 113, 98, 100, 112, 103, 60, -11, -54, -95, -121, -124, -119, -95, -71, + -10, 53, 103, 116, 93, 91, 89, 80, 31, -28, -67, -108, -122, -128, -110, -87, + -53, 8, 60, 107, 107, 89, 83, 83, 76, 27, -14, -52, -84, -99, -103, -82, + -72, -40, 4, 53, 92, 92, 88, 85, 97, 87, 42, 3, -45, -74, -106, -111, + -105, -101, -70, -30, 27, 65, 77, 83, 87, 106, 90, 58, 16, -30, -67, -101, + -100, -101, -93, -68, -27, 29, 60, 77, 79, 93, 111, 96, 71, 24, -21, -73, + -109, -118, -127, -118, -98, -50, 6, 43, 65, 70, 99, 115, 108, 82, 40, -1, + -53, -80, -94, -105, -101, -82, -31, 18, 56, 66, 72, 95, 103, 97, 64, 29, + -15, -63, -85, -102, -105, -104, -81, -35, 13, 53, 58, 69, 86, 97, 94, 67, + 39, -12, -54, -80, -97, -102, -103, -77, -38, 9, 40, 45, 60, 77, 95, 88, + 70, 41, -8, -46, -74, -87, -99, -100, -78, -42, 10, 37, 50, 66, 89, 110, + 103, 91, 57, 9, -33, -68, -86, -105, -105, -89, -51, -2, 23, 40, 53, 80, + 99, 98, 89, 53, 8, -37, -68, -90, -107, -106, -94, -51, -5, 25, 43, 58, + 86, 95, 98, 86, 52, 9, -36, -64, -92, -105, -108, -95, -53, -11, 22, 37, + 57, 81, 90, 96, 82, 52, 6, -34, -64, -92, -104, -113, -97, -59, -18, 15, + 31, 58, 79, 92, 98, 87, 57, 9, -29, -63, -87, -100, -109, -91, -58, -13, + 16, 36, 62, 78, 93, 96, 88, 56, 12, -25, -62, -83, -101, -106, -89, -57, + -15, 6, 30, 52, 71, 87, 94, 89, 55, 18, -21, -55, -76, -96, -100, -88, + -53, -16, 6, 31, 53, 76, 93, 105, 98, 64, 26, -18, -52, -78, -99, -105, + -95, -59, -26, 0, 24, 45, 66, 81, 97, 88, 62, 28, -12, -40, -67, -84, + -95, -83, -50, -21, 4, 24, 47, 64, 81, 96, 85, 63, 26, -11, -41, -69, + -88, -102, -91, -64, -36, -12, 10, 34, 51, 74, 87, 81, 62, 26, -7, -40, + -63, -83, -95, -83, -58, -31, -10, 14, 34, 51, 75, 85, 82, 61, 30, -3, + -34, -57, -81, -92, -83, -60, -36, -15, 11, 27, 47, 69, 80, 79, 59, 30, + -5, -33, -57, -82, -93, -84, -61, -38, -15, 10, 25, 48, 68, 80, 77, 58, + 29, -4, -30, -56, -80, -89, -78, -54, -34, -8, 10, 0, 0, 1, 0, -2, + -2, -5, -8, -3, 3, -4, -10, 2, 8, 3, 4, 5, -3, -9, 10, 26, + 26, 12, -4, -40, -64, -50, 1, 55, 69, 28, -23, -65, -83, -52, 13, 67, + 67, 39, 16, -15, -48, -38, 10, 53, 44, 5, -5, -14, -43, -35, 16, 54, + 37, -1, -26, -53, -82, -37, 35, 67, 44, 2, -10, -20, -39, -19, 27, 55, + 42, 3, -26, -67, -107, -62, 43, 110, 102, 43, -18, -63, -91, -35, 73, 120, + 77, -6, -72, -113, -109, -36, 53, 78, 50, 0, -46, -72, -71, -20, 67, 112, + 100, 44, -24, -88, -123, -84, 5, 71, 97, 66, 7, -53, -100, -80, -1, 83, + 127, 108, 38, -57, -121, -119, -57, 24, 84, 97, 62, -4, -77, -97, -46, 32, + 101, 108, 56, -20, -103, -119, -69, 18, 105, 126, 90, 6, -92, -126, -90, -3, + 85, 108, 75, 0, -86, -117, -85, -6, 76, 115, 101, 30, -68, -118, -105, -33, + 57, 105, 102, 41, -46, -104, -112, -59, 25, 95, 121, 81, -5, -88, -126, -94, + -12, 63, 101, 76, 7, -67, -107, -73, 11, 94, 127, 102, 21, -74, -124, -95, + -21, 57, 101, 82, 21, -48, -89, -59, 6, 67, 95, 60, -11, -82, -115, -81, + -13, 52, 84, 52, -9, -68, -96, -56, 9, 66, 93, 63, 10, -52, -86, -54, + 1, 60, 96, 70, 19, -44, -80, -51, 0, 55, 94, 69, 20, -42, -88, -76, + -40, 24, 79, 72, 34, -28, -75, -63, -23, 35, 71, 48, 4, -57, -95, -67, + -10, 62, 103, 75, 18, -61, -110, -86, -22, 61, 110, 90, 37, -45, -100, -87, + -39, 34, 81, 70, 33, -39, -88, -76, -24, 54, 94, 76, 32, -46, -100, -92, + -42, 35, 73, 62, 26, -46, -97, -93, -44, 36, 81, 75, 35, -38, -87, -81, + -26, 58, 99, 85, 37, -44, -101, -103, -46, 47, 98, 97, 56, -27, -90, -99, + -49, 37, 88, 95, 62, -12, -74, -93, -51, 27, 69, 71, 35, -30, -78, -87, + -38, 41, 84, 90, 57, -11, -71, -96, -56, 21, 69, 86, 60, -4, -67, -97, + -61, 12, 65, 88, 65, 3, -61, -94, -60, 14, 71, 96, 68, 3, -66, -104, + -70, 3, 59, 84, 59, -1, -67, -107, -76, -3, 59, 89, 64, 3, -67, -111, + -82, -9, 57, 92, 76, 26, -43, -93, -71, -9, 50, 80, 64, 16, -51, -100, + -79, -17, 49, 88, 77, 30, -41, -95, -79, -17, 49, 87, 77, 34, -36, -92, + -78, -19, 44, 82, 73, 33, -37, -95, -84, -23, 47, 89, 83, 43, -30, -92, + -83, -28, 39, 79, 74, 40, -28, -87, -82, -31, 34, 71, 67, 35, -31, -88, + -85, -36, 28, 68, 69, 44, -20, -79, -83, -43, 19, 59, 64, 41, -25, -89, + -100, -61, 9, 60, 76, 57, -10, -75, -90, -51, 22, 74, 88, 66, 1, -61, + -78, -42, 25, 71, 84, 63, -1, -67, -90, -59, 8, 59, 81, 68, 8, -56, + -85, -62, 1, 50, 74, 63, 7, -53, -84, -60, 5, 55, 80, 70, 17, -43, + -76, -55, 4, 49, 73, 65, 17, -41, -77, -62, -9, 38, 68, 64, 17, -43, + -84, -73, -22, 23, 56, 57, 18, -36, -77, -68, -23, 20, 51, 52, 16, -36, + -77, -70, -26, 18, 54, 59, 28, -22, -64, -59, -20, 21, 56, 63, 36, -12, + -55, -52, -16, 25, 58, 63, 35, -14, -59, -57, -22, 18, 51, 57, 31, -16, + -58, -58, -27, 10, 43, 51, 30, -16, -59, -60, -28, 12, 48, 57, 35, -13, + -59, -64, -35, 7, 47, 63, 47, 1, -46, -55, -32, 7, 47, 0, 0, -1, + -1, -4, 1, -1, -3, -13, -8, -14, -3, -2, -2, 1, 8, 5, 7, -21, + -13, -2, -6, -8, -22, -6, 5, 11, 34, 41, 33, 13, 28, 33, 48, 35, + 21, -3, -26, -18, -10, 3, 7, 22, 21, 63, 40, 41, 43, 4, -8, -43, + -63, -77, -77, -59, -18, 3, 2, -21, -46, -74, -90, -108, -101, -94, -89, -84, + -85, -77, -59, -50, -33, -7, 18, 37, 47, 64, 101, 127, 125, 127, 126, 126, + 126, 122, 100, 87, 62, 37, 28, 27, 25, 27, 34, 25, -4, -45, -85, -123, + -128, -126, -128, -127, -123, -92, -73, -55, -45, -37, -33, -32, -33, -43, -53, -55, + -43, -20, 3, 20, 34, 42, 49, 55, 63, 74, 84, 93, 101, 107, 112, 117, + 109, 92, 63, 33, 8, -13, -25, -29, -30, -27, -27, -32, -46, -63, -82, -98, + -109, -116, -121, -118, -104, -80, -49, -12, 21, 45, 58, 64, 66, 66, 61, 51, + 44, 37, 32, 32, 33, 33, 28, 23, 15, 8, 3, 2, 9, 16, 20, 24, + 23, 14, -1, -20, -37, -48, -53, -52, -47, -38, -26, -13, -5, -1, -4, -10, + -22, -34, -43, -48, -46, -34, -16, 5, 25, 45, 65, 78, 84, 83, 71, 55, + 39, 24, 9, -3, -12, -23, -34, -45, -57, -65, -71, -71, -63, -49, -34, -21, + -11, -2, 2, 8, 11, 12, 14, 14, 20, 28, 38, 50, 58, 63, 61, 56, + 46, 33, 17, -1, -19, -34, -45, -48, -44, -32, -19, -5, 5, 7, 4, -2, + -7, -11, -15, -18, -21, -23, -26, -28, -30, -31, -29, -26, -20, -12, -1, 11, + 21, 32, 42, 51, 55, 55, 52, 46, 41, 37, 32, 30, 28, 27, 24, 19, + 12, -1, -21, -45, -67, -89, -103, -107, -101, -90, -70, -51, -33, -18, -2, 11, + 23, 33, 39, 44, 49, 52, 57, 59, 59, 56, 52, 48, 41, 35, 28, 20, + 15, 11, 4, 0, -5, -11, -18, -25, -34, -42, -47, -48, -46, -40, -33, -27, + -24, -21, -24, -32, -42, -51, -56, -58, -56, -47, -35, -18, 2, 24, 48, 70, + 88, 99, 104, 102, 97, 89, 79, 69, 59, 49, 37, 27, 14, 0, -14, -29, + -44, -58, -71, -81, -87, -88, -88, -85, -81, -77, -72, -63, -51, -37, -21, -5, + 12, 29, 43, 53, 59, 61, 57, 48, 36, 24, 13, 8, 8, 15, 25, 38, + 48, 54, 54, 50, 43, 33, 22, 11, 3, -6, -15, -25, -35, -46, -54, -61, + -65, -68, -69, -69, -68, -64, -59, -52, -43, -32, -20, -7, 6, 19, 31, 42, + 51, 58, 62, 64, 62, 58, 52, 44, 35, 26, 17, 9, 1, -5, -10, -15, + -18, -19, -20, -19, -18, -16, -15, -14, -14, -15, -16, -17, -18, -19, -19, -19, + -19, -18, -16, -14, -11, -9, -6, -3, 0, 3, 6, 10, 14, 18, 22, 27, + 32, 35, 37, 37, 35, 30, 23, 14, 4, -6, -15, -24, -31, -36, -39, -40, + -39, -37, -32, -26, -19, -10, -1, 8, 17, 24, 29, 32, 33, 32, 29, 25, + 20, 15, 11, 7, 3, -1, -5, -9, -14, -19, -24, -28, -31, -32, -31, -27, + -23, -16, -10, -3, 2, 7, 10, 12, 13, 13, 13, 12, 10, 8, 7, 5, + 5, 5, 5, 6, 8, 10, 13, 17, 20, 23, 25, 26, 25, 21, 16, 9, + 1, -7, -16, -24, -31, -37, -42, -47, -49, -51, -52, -51, -48, -43, -37, -30, + -20, -7, 6, 19, -1, -4, -4, 0, -1, -4, -3, 4, 4, -2, -3, 2, + 1, -4, 0, 5, 0, -4, 2, -10, -26, -29, -34, -49, -61, -44, -21, -8, + -3, -3, 1, 20, 32, 38, 32, 12, -4, 1, 14, 28, 51, 68, 78, 80, + 72, 38, 1, -6, 16, 23, 2, -14, -15, -20, -33, -62, -65, -37, -18, -27, + -29, -26, -45, -38, 8, 52, 55, 31, 26, 16, 17, 45, 80, 87, 77, 62, + 54, 24, -23, -50, -43, -28, -47, -72, -86, -86, -87, -61, -35, -38, -57, -69, + -55, -27, 1, 4, 22, 45, 54, 31, 0, -7, -5, -3, 0, -9, -21, -20, + -15, -27, -31, -10, 5, 9, 3, -21, -67, -83, -46, -3, 8, 18, 22, 4, + -3, 5, 35, 52, 67, 72, 83, 89, 71, 37, 19, 25, 8, -11, -37, -58, + -80, -85, -68, -33, -24, -57, -60, -34, -16, -14, 17, 73, 96, 77, 48, 17, + -7, -9, 4, -1, -3, 6, 3, -12, -10, 19, 33, 33, 41, 35, -29, -70, + -64, -38, -18, 3, 17, -5, -26, -35, -5, 31, 63, 73, 86, 94, 80, 64, + 50, 46, 37, 28, -2, -32, -65, -91, -84, -63, -59, -82, -97, -80, -66, -65, + -43, 8, 49, 60, 61, 42, 27, 23, 23, 14, 15, 18, 10, -12, -17, -9, + -13, 8, 35, 42, 2, -41, -76, -87, -67, -46, -31, -32, -45, -72, -53, -5, + 32, 46, 72, 92, 96, 92, 77, 75, 73, 61, 44, 12, -32, -68, -72, -54, + -58, -75, -85, -67, -57, -61, -60, -46, -11, 24, 35, 22, 15, 6, -1, -13, + 8, 23, 8, -1, -1, -6, -8, 35, 71, 86, 79, 50, -11, -46, -38, -31, + -29, -21, -30, -64, -68, -43, -12, 10, 28, 62, 89, 88, 84, 85, 90, 89, + 95, 83, 28, -32, -53, -36, -44, -62, -64, -55, -59, -54, -52, -48, -23, 19, + 48, 37, 39, 42, 31, 12, 19, 20, 5, 4, 1, -23, -40, -14, 14, 42, + 68, 64, 14, -33, -53, -52, -32, -18, -24, -43, -67, -62, -36, -18, -1, 25, + 54, 57, 58, 56, 54, 50, 66, 80, 44, -21, -50, -40, -52, -69, -77, -60, + -56, -54, -53, -62, -49, -9, 28, 41, 58, 58, 47, 43, 49, 41, 34, 37, + 18, -19, -44, -47, -36, 1, 35, 38, 19, -20, -62, -71, -59, -36, -34, -47, + -63, -63, -50, -38, -17, 7, 37, 56, 74, 80, 73, 61, 87, 116, 99, 47, + -7, -26, -22, -20, -32, -57, -72, -76, -76, -71, -47, -9, 13, 24, 29, 29, + 25, 27, 52, 68, 62, 9, -38, -67, -66, -39, -11, -4, -24, -37, -47, -51, + -49, -44, -55, -39, -6, -17, -52, -54, -19, 1, 15, 24, 31, 41, 55, 71, + 79, 89, 111, 115, 88, 54, 22, -2, -8, -5, -7, -27, -49, -57, -69, -72, + -64, -30, -3, 17, 31, 37, 29, 14, 39, 67, 73, 47, 10, -40, -72, -58, + -23, -12, -19, -19, -39, -49, -42, -46, -62, -44, -8, -11, -36, -51, -39, -15, + 0, 13, 21, 25, 40, 55, 63, 73, 95, 115, 115, 85, 53, 20, 2, -1, + -2, -10, -32, -48, -64, -73, -77, -62, -33, -9, 16, 33, 31, 18, 17, 44, + 67, 70, 49, 6, -45, -69, -53, -24, -13, -19, -24, -40, -47, -45, -50, -62, + -43, -10, -13, -37, -51, -39, -15, 0, -3, -1, 1, -1, -6, -6, -4, -1, + -2, -6, -8, -7, -4, -5, -10, -14, -16, -16, -16, -17, -18, -18, -17, -15, + -15, -16, -15, -13, -10, -9, -9, -11, -13, -14, -11, -9, -8, -9, -7, -3, + -2, -5, -8, -6, 1, 5, 4, 1, 0, 1, 4, 4, 4, 5, 7, 9, + 9, 8, 8, 9, 10, 9, 5, 2, 3, 5, 7, 7, 9, 11, 11, 12, + 14, 14, 12, 8, 7, 8, 5, 1, 3, 8, 9, 9, 10, 14, 16, 15, + 14, 12, 11, 9, 7, 3, -2, -3, 3, 5, 0, -5, -1, -1, -6, -10, + -16, -23, -28, -29, -32, -39, -36, -23, -16, -19, -19, -10, -7, -12, -11, -5, + -6, -11, -13, -11, -9, -8, -2, 6, 8, 8, 9, 6, 2, 4, 8, 9, + 4, 4, 12, 18, 17, 14, 17, 20, 20, 16, 9, 7, 7, 5, 3, 4, + 1, -2, 0, 3, 2, -1, 1, 3, 3, 1, 2, 2, 0, 3, 6, 9, + 8, 0, -5, -3, 7, 12, 8, -2, -2, 9, 10, 2, -3, 2, 5, 1, + -3, -5, -6, -2, -3, -11, -20, -26, -28, -30, -32, -37, -43, -45, -43, -40, + -42, -41, -31, -22, -20, -18, -16, -16, -19, -15, -8, -3, -3, 3, 17, 26, + 22, 16, 18, 23, 27, 26, 23, 17, 15, 21, 25, 24, 25, 31, 36, 32, + 29, 23, 17, 15, 11, 5, 1, 4, 6, 8, 6, 7, 8, 10, 14, 18, + 22, 20, 17, 14, 15, 13, 10, 15, 15, 12, 9, 10, 15, 14, 9, 3, + 6, 10, 5, -3, -9, -16, -16, -10, -11, -20, -24, -18, -20, -32, -42, -48, + -55, -70, -84, -95, -100, -92, -75, -65, -68, -67, -56, -55, -51, -41, -33, -37, + -42, -38, -33, -31, -26, -6, 19, 30, 25, 25, 28, 30, 27, 19, 16, 18, + 31, 44, 46, 48, 56, 71, 77, 74, 66, 54, 47, 37, 19, 3, 2, 3, + 3, 4, 13, 20, 21, 25, 24, 25, 19, 18, 19, 19, 14, 6, 17, 14, + 1, 3, 12, 27, 29, 25, 13, 14, 24, 22, 6, -7, -7, 0, 11, 12, + 1, 0, 10, 8, -13, -32, -46, -52, -57, -70, -88, -106, -101, -81, -74, -82, + -75, -49, -37, -42, -44, -42, -46, -51, -47, -40, -32, -27, -6, 3, 16, 32, + 29, 25, 24, 30, 54, 69, 74, 78, 90, 108, 118, 124, 117, 107, 102, 93, + 76, 61, 50, 41, 35, 31, 26, 13, 4, 0, -1, 0, -6, -12, -10, -8, + -4, 0, -3, -20, -31, -27, -18, -16, -22, -29, -28, -9, 0, -3, -1, 2, + 11, 20, 24, 18, 22, 34, 32, 16, -1, -18, -34, -46, -55, -67, -91, -102, + -91, -72, -73, -81, -68, -55, -55, -65, -74, -79, -87, -87, -83, -81, -77, -60, + -25, 4, 4, -3, 0, 13, 29, 29, 24, 23, 29, 51, 67, 72, 77, 88, + 105, 114, 122, 116, 106, 100, 93, 77, 63, 51, 42, 36, 31, 27, 15, 5, + 0, -1, 0, -4, -10, -9, -7, -3, 2, -1, -16, -28, -26, -16, -13, -18, + -25, -25, -8, 2, 1, 2, 5, 13, 21, 26, 20, 23, 35, 35, 20, 3, + -14, -32, -45, -54, -67, -91, -102, -90, -72, -75, -82, -68, -56, -56, -66, -75, + -81, -88, -88, -83, -82, -77, -59, -22, 4, 1, -1, -2, -3, -3, -1, -1, + -6, -8, -9, -12, -5, 6, 15, 21, 22, 21, 9, -8, -16, -23, -32, -22, + 4, 27, 32, 17, -2, -21, -34, -37, -30, -24, -3, 24, 47, 58, 50, 23, + -12, -41, -52, -47, -33, -2, 28, 48, 45, 28, 0, -36, -58, -53, -34, -4, + 26, 52, 75, 73, 45, -5, -66, -101, -90, -61, -14, 23, 59, 87, 89, 63, + 10, -46, -79, -80, -55, -23, -3, 27, 58, 62, 41, -6, -66, -92, -77, -29, + 19, 41, 65, 74, 69, 42, -9, -73, -109, -107, -67, -17, 23, 70, 104, 111, + 83, 21, -56, -104, -109, -62, -21, 4, 34, 68, 89, 75, 19, -46, -89, -85, + -38, -1, 23, 45, 64, 74, 62, 8, -53, -98, -93, -47, -9, 16, 36, 62, + 86, 78, 13, -67, -121, -109, -56, -9, 25, 58, 89, 109, 81, 8, -70, -119, + -106, -56, -7, 32, 63, 90, 108, 74, -3, -89, -128, -118, -70, -22, 23, 62, + 101, 126, 98, 26, -64, -117, -110, -72, -32, 6, 44, 93, 124, 100, 28, -63, + -116, -110, -71, -26, 16, 54, 101, 121, 92, 13, -86, -128, -120, -79, -28, 15, + 60, 111, 127, 95, 11, -83, -127, -116, -80, -29, 15, 67, 117, 127, 100, 17, + -75, -118, -108, -75, -31, 7, 60, 109, 123, 87, 3, -83, -118, -106, -67, -23, + 13, 62, 106, 119, 85, 3, -77, -106, -95, -61, -27, 2, 52, 103, 124, 97, + 19, -61, -95, -92, -63, -34, -4, 45, 94, 116, 87, 8, -63, -91, -85, -58, + -36, -9, 36, 81, 104, 76, 2, -60, -87, -77, -52, -32, -2, 48, 97, 119, + 86, 7, -59, -90, -85, -65, -50, -22, 26, 78, 107, 79, 11, -49, -78, -73, + -58, -46, -18, 31, 85, 112, 75, 1, -59, -84, -73, -55, -40, -12, 30, 80, + 106, 74, 10, -46, -70, -62, -49, -39, -13, 31, 86, 110, 74, 8, -49, -70, + -59, -46, -33, -6, 38, 92, 111, 76, 13, -42, -62, -56, -51, -44, -23, 19, + 75, 97, 67, 8, -44, -63, -58, -56, -48, -26, 19, 75, 94, 64, 8, -40, + -55, -50, -49, -42, -25, 18, 69, 85, 57, 4, -41, -54, -51, -50, -45, -28, + 18, 71, 88, 60, 8, -35, -46, -47, -48, -46, -30, 16, 66, 84, 59, 9, + -30, -41, -43, -42, -40, -22, 25, 73, 88, 60, 8, -30, -42, -46, -45, -42, + -21, 28, 74, 83, 52, -1, -36, -46, -45, -40, -37, -17, 26, 66, 73, 41, + -10, -42, -54, -53, -48, -43, -19, 27, 68, 76, 44, -4, -34, -44, -41, -37, + -33, -10, 34, 71, 75, 40, -7, -36, -47, -43, -39, -35, -9, 35, 72, 75, + 39, -7, -38, -49, -45, -43, -38, -11, 33, 68, 70, 36, -4, -31, -39, -36, + -35, -31, -5, 36, 69, 69, 35, -4, -31, -38, -35, -37, -33, -8, 31, 64, + 63, 31, -7, -34, -42, -40, -43, -38, -12, 28, 61, 59, 27, -10, -34, -40, + -38, -41, -35, -9, 31, 63, 60, 29, -6, -31, -37, -38, -42, -35, -10, 29, + 60, 56, 27, -8, -30, -33, -34, -38, -32, -10, 28, 56, 51, 23, -9, -29, + -32, -34, -38, -33, -10, 29, 55, 50, 23, -9, -28, -30, -33, -37, -32, -8, + 32, 56, 52, 23, 23, 0, -2, 0, -2, -6, -6, -6, -5, -2, -1, 5, + 15, 20, 11, 12, 12, 6, 0, -8, -19, -12, -4, -19, -19, -4, 4, -7, + -3, 5, 8, 11, 14, 9, 9, 8, -4, -11, -6, -8, -16, -14, -7, -1, + -3, 1, 10, 13, 24, 28, 12, 10, 14, 11, -14, -29, -19, -12, -21, -25, + -16, 2, 0, -11, -7, 7, 10, 0, 0, 5, 11, 6, 10, 21, 13, 7, + 14, 4, -4, -9, -5, -11, -16, -7, -3, 3, 15, -2, 2, 17, 6, -19, + -16, 3, 3, -14, -10, 7, 7, 4, 8, 11, 4, -5, -12, -9, -6, -14, + -13, -17, -13, -8, 5, 9, 3, 10, 12, 24, 28, 26, 35, 20, -3, 24, + 23, -19, -31, -23, -23, -38, -34, -18, -10, -8, -6, -4, -1, 5, -4, -8, + 2, 15, 12, 26, 56, 37, 10, 25, 25, -4, -21, -24, -23, -26, -30, -27, + -8, 10, -5, 3, 30, 6, -26, -7, 13, -2, -19, -2, 11, 3, 14, 21, + 8, 12, 5, -19, -26, -12, 9, 1, -8, -8, 20, 27, 17, 16, 15, 0, + 23, 39, 11, -4, -13, -21, -21, -32, -36, -27, -20, -24, -10, -4, 5, 14, + 4, -11, -10, 7, -8, -7, 7, 7, 2, 15, 29, 55, 26, 4, 22, 37, + 32, 14, 10, 18, 7, -1, -28, -49, -24, -14, -41, -53, -37, -28, -27, -15, + 1, 2, 14, 14, 13, 3, 0, 1, 18, 9, 7, 11, 23, 23, 25, 16, + -7, 1, 13, 26, 26, 9, 13, 28, 28, 1, -29, -29, -26, -27, -43, -43, + -31, -12, -26, -15, 6, 16, 6, 22, 11, -4, 0, 3, 0, -4, -20, -9, + 15, 23, 19, 7, 25, 19, 42, 63, 40, 13, 22, 24, 1, -41, -60, -55, + -63, -69, -61, -31, -7, 10, 8, 0, 7, 4, 4, 20, 5, -4, 9, 27, + 31, 27, 23, 13, 19, 12, 2, 4, 15, 20, 35, 19, 16, 26, 3, -30, + -48, -31, -40, -60, -59, -47, -13, -3, 12, 22, 11, 7, 9, 8, 3, -10, + -34, -5, 6, 24, 38, 19, 13, 21, 40, 15, 2, 27, 26, 16, 44, 47, + -7, -43, -41, -29, -44, -80, -81, -58, -26, -17, 3, 16, 30, 19, 10, 25, + 16, 6, -12, -3, 13, 30, 38, 20, 17, 22, 25, 18, 13, 16, -3, 1, + 32, 44, -11, -48, -51, -34, -38, -49, -64, -70, -23, -10, -14, -1, 20, 18, + 20, 21, 11, 3, -8, -3, 13, 14, 22, 18, 32, 37, 30, 25, 16, 27, + 27, 18, 37, 52, 12, -26, -56, -57, -46, -71, -92, -86, -50, -21, -10, 8, + 15, 15, 18, 28, 17, 1, 1, 2, 13, 13, 23, 23, 21, 29, 31, 29, + 15, 20, 33, 32, 29, 46, 21, -31, -49, -53, -51, -66, -82, -76, -54, -32, + -10, 12, 19, 29, 18, 3, 0, 16, 20, 29, 31, 20, 25, 31, 43, 41, + 34, 44, 27, 29, 65, 54, -15, -70, -79, -63, -86, -114, -114, -79, -26, -2, + 6, 18, 19, 10, 19, 26, 15, 5, 0, 16, 23, 29, 30, 21, 25, 28, + 37, 37, 38, 44, 32, 29, 66, 65, -7, -67, -74, -59, -82, -114, -117, -85, + -31, -2, 11, 20, 18, 9, 20, 30, 15, 5, 0, 0, 1, 1, 2, 3, + 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 7, 7, 7, 7, 7, 6, + 4, 3, 2, 0, -1, -2, -3, -5, -6, -8, -9, -9, -11, -12, -14, -15, + -17, -17, -17, -18, -19, -19, -19, -18, -17, -16, -15, -13, -11, -8, -7, -6, + -5, -3, -1, 0, 0, 1, 3, 5, 8, 10, 12, 14, 17, 19, 21, 23, + 26, 27, 28, 28, 28, 26, 25, 24, 23, 23, 21, 19, 18, 16, 15, 14, + 13, 12, 11, 11, 11, 10, 8, 6, 5, 5, 4, 2, 0, -2, -4, -5, + -7, -10, -11, -12, -13, -14, -15, -15, -15, -15, -15, -16, -17, -18, -18, -19, + -21, -23, -25, -27, -28, -29, -29, -30, -30, -29, -27, -25, -23, -22, -20, -18, + -16, -14, -13, -12, -11, -11, -10, -9, -8, -6, -5, -4, -3, -1, 1, 3, + 4, 6, 7, 8, 8, 9, 10, 11, 12, 13, 13, 13, 13, 15, 18, 21, + 23, 24, 25, 25, 28, 31, 33, 34, 34, 32, 31, 31, 31, 30, 27, 22, + 16, 12, 10, 9, 7, 3, -5, -13, -19, -22, -22, -23, -25, -28, -31, -33, + -33, -32, -32, -31, -32, -33, -32, -29, -25, -21, -19, -19, -19, -19, -18, -15, + -9, -3, 2, 6, 9, 12, 16, 21, 27, 32, 37, 39, 40, 40, 39, 39, + 40, 41, 40, 38, 35, 34, 34, 33, 29, 22, 16, 11, 10, 11, 12, 12, + 10, 8, 7, 5, 3, 2, 0, -6, -12, -19, -23, -23, -22, -23, -26, -30, + -33, -33, -33, -34, -35, -37, -40, -45, -50, -53, -52, -48, -42, -37, -32, -27, + -22, -20, -18, -16, -16, -18, -21, -26, -30, -33, -34, -35, -36, -38, -40, -41, + -41, -38, -36, -36, -38, -41, -40, -38, -34, -30, -27, -25, -22, -20, -16, -15, + -16, -17, -18, -16, -13, -10, -7, -4, -2, 1, 6, 11, 16, 21, 24, 25, + 26, 24, 22, 19, 18, 19, 22, 24, 26, 30, 33, 38, 44, 50, 56, 61, + 63, 68, 72, 74, 73, 68, 64, 57, 50, 47, 46, 44, 37, 21, 3, -11, + -20, -23, -25, -30, -33, -36, -36, -34, -31, -27, -22, -21, -22, -21, -18, -21, + -24, -27, -31, -33, -32, -27, -21, -14, -13, -17, -17, -10, 0, 10, 15, 16, + 14, 8, 6, 10, 16, 25, 34, 39, 43, 47, 53, 62, 72, 82, 89, 92, + 90, 84, 79, 77, 77, 76, 67, 54, 42, 33, 26, 18, 5, -11, -27, -41, + -53, -65, -73, -77, -79, -81, -86, -93, -102, -110, -116, -118, -120, -124, -127, -128, + -128, -126, -122, -116, -107, -96, -85, -78, -72, -64, -54, -45, -39, -40, -46, -49, + -49, -47, -45, -44, -45, -45, -44, -42, -38, -33, -29, -26, -23, -20, -18, -14, + -11, -8, -5, -2, 2, 7, 11, 10, 8, 7, 9, 16, 22, 26, 28, 31, + 34, 39, 44, 49, 53, 57, 60, 62, 63, 63, 65, 66, 63, 57, 51, 46, + 46, 50, 53, 54, 55, 54, 55, 57, 63, 69, 73, 75, 73, 69, 66, 64, + 65, 63, 55, 43, 30, 18, 11, 3, -6, -15, -23, -29, -32, -32, -28, -22, + -16, -13, -16, -16, -11, -2, 9, 15, 1, 0, 0, 0, -1, 0, -3, 0, + -1, 0, -18, 21, -22, 23, -41, 20, 84, -39, 50, -61, 26, -126, -19, -37, + 15, 2, 70, -33, 127, -55, 117, -73, 15, -45, -50, 8, -11, 23, 33, 1, + 26, -67, 26, -25, 14, -45, 57, -124, 12, -4, -23, 107, -54, 127, -49, 43, + 27, -59, -30, 15, -128, 5, -128, 86, -39, 82, 12, 62, 9, 51, -59, 53, + -95, 67, -92, 68, -28, 94, 21, 47, -11, -1, -41, 0, -25, -9, 18, -68, + 15, -27, 49, -27, 103, -4, 3, -36, 58, -98, 56, -116, -31, -123, 25, -58, + 89, -21, 110, -25, 73, -28, 39, -21, 35, -40, 37, -20, 50, 55, 51, 6, + 1, -47, -11, -32, -23, 38, -67, 3, -54, 34, -55, 79, 1, 32, -61, 89, + -86, 53, -67, -10, -128, -6, -68, 51, -4, 82, 15, 83, -16, 63, -24, 55, + -29, 8, 0, 6, 11, 54, 14, 16, -39, -9, -12, -47, 37, -40, -22, -60, + 21, -76, 51, -17, 74, -63, 98, -36, 44, -33, 24, -113, -37, -89, 20, -30, + 67, 18, 87, 0, 67, -6, 38, 1, -2, -18, -5, -20, 32, 17, 21, -8, + -30, 15, -47, 11, -17, 11, -97, 43, -87, 27, -36, 91, -41, 66, 3, 44, + -28, 55, -74, -37, -92, -21, -37, 33, -1, 75, 22, 36, 14, 26, 8, 8, + -12, -7, -21, -1, 27, 11, 21, -30, 21, -37, -3, -13, 23, -27, -32, -10, + -23, -44, 56, -1, 43, -12, 76, -29, 48, -9, -25, -71, -70, -48, -20, 2, + 9, 56, 8, 56, -10, 52, -12, 31, -29, 27, -60, 62, -42, 83, -45, 30, + -24, 4, -26, 33, -23, 5, -18, -25, -53, -7, -6, -6, 19, 16, 31, 3, + 58, -14, 0, -64, -33, -58, -8, -43, 42, -18, 57, -9, 54, 1, 47, -3, + 36, -18, 3, 4, 6, 2, -17, 8, -14, -27, 35, 2, -3, 1, -8, -43, + -34, -1, -22, 12, 2, 37, -6, 53, 14, 16, -43, -22, -75, -2, -67, 23, + -24, 39, -3, 39, 6, 44, 9, 37, 5, 1, 3, 5, 12, -18, 0, 0, + -31, 5, 23, 1, -3, 10, -20, -48, -6, -30, 7, -18, 35, -4, 32, 21, + 39, -26, -1, -75, -9, -65, -3, -28, 20, -5, 32, 5, 36, 20, 30, 30, + 3, 10, -1, 16, -10, -7, -1, -17, -23, 18, 14, -3, 8, 9, -45, -14, + -35, -1, -27, 18, -2, 29, 1, 61, -14, 20, -56, -19, -51, -22, -38, 9, + -14, 22, 5, 24, 27, 23, 41, 13, 20, -7, 23, -2, -8, -2, -9, -26, + -6, 14, 11, -11, 37, -33, -12, -38, -6, -33, 7, -14, 30, -12, 55, 4, + 33, -32, -14, -45, -22, -43, -7, -15, 18, 18, 33, 17, 41, 22, 15, 14, + 8, -24, -16, -18, -16, -7, 6, 16, -2, 8, -14, -6, -23, 0, -22, 1, + -23, 21, 4, 24, -1, 9, -9, -11, -14, -13, -16, -14, -15, -12, -16, -5, + 8, 28, 25, 28, 34, 27, 15, 16, 2, -20, -22, -20, -15, -8, 10, 11, + 7, -3, -5, -16, -10, -13, -5, -16, -5, 4, 17, 13, 6, 1, -9, -1, + -2, -3, -4, -4, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -6, + -6, -6, -6, -6, -5, -3, -3, -5, -5, -5, -7, -8, -5, 4, 5, 13, + 12, -12, -5, 10, 5, 4, 0, 3, 26, 33, 10, -15, -69, -89, -25, 25, + 58, 70, 22, -41, -62, -31, 18, 17, -17, -12, -9, 20, 99, 96, 0, -88, + -123, -69, 61, 116, 54, -11, -45, -28, 40, 38, -42, -59, -53, -31, 63, 78, + -9, -65, -83, -59, 48, 110, 50, -11, -51, -54, 41, 96, 9, -87, -119, -77, + 42, 118, 67, -18, -57, -46, 24, 89, 81, 22, -43, -77, -65, -41, -23, -3, + 4, 8, -13, -54, -52, -21, 30, 89, 86, 8, -49, -76, -56, 30, 55, 52, + 47, -7, -45, -49, -48, -10, 68, 74, 43, 22, -27, -25, 12, 20, -5, -43, + -69, -46, 21, 53, 51, 38, -8, -32, 6, 20, -1, -19, -56, -67, -26, 27, + 76, 95, 23, -64, -60, -15, 33, 39, -8, -37, -24, -7, 7, 4, -25, -23, + -10, -14, -7, -5, -12, 2, 28, 31, 37, 21, -18, -16, -4, -22, -37, -46, + -56, -8, 58, 64, 53, 31, -9, -9, -2, -57, -85, -52, -13, 59, 92, 21, + -42, -47, -33, 27, 75, 27, -22, -38, -44, 18, 77, 32, -21, -46, -50, 34, + 89, 22, -37, -60, -56, 31, 95, 36, -27, -57, -82, -15, 53, 15, -13, -25, + -44, 14, 66, 14, -32, -53, -62, 25, 96, 50, 3, -32, -56, 25, 98, 51, + -9, -56, -78, 7, 92, 71, 28, -31, -92, -42, 28, 20, 24, 8, -34, 22, + 70, 18, -17, -53, -88, -20, 39, 7, -2, -8, -28, 35, 80, 19, -23, -55, + -93, -22, 63, 54, 47, 19, -52, -35, 2, -36, -32, -18, -49, -9, 41, 15, + 26, 34, -22, -6, 31, 1, 8, 9, -43, -15, 30, -3, -1, -7, -73, -48, + 6, -14, 5, 13, -47, -30, 12, -13, 6, 18, -37, -13, 39, 27, 45, 38, + -37, -32, 12, 3, 32, 46, -10, 6, 48, 16, 15, 15, -32, -2, 47, 24, + 26, 18, -51, -51, -15, -29, -1, 19, -28, -15, 21, 2, 18, 22, -34, -24, + 13, -3, 15, 14, -45, -34, 7, 10, 38, 31, -34, -30, 4, 5, 43, 61, + 13, 4, 6, -22, 4, 24, -13, -13, -10, -34, 0, 23, -16, -16, -13, -42, + -18, -4, -36, -17, 5, -10, 14, 22, -21, -22, -16, -37, -6, 20, -2, 17, + 36, 19, 43, 43, -9, -15, -12, -29, 6, 31, 6, 10, 7, -23, -2, 9, + -23, -15, -10, -26, 3, 20, -5, 1, 0, -22, 5, 22, -6, -8, -16, -37, + -5, 20, 2, 11, 6, -19, 11, 33, 12, 20, 16, -7, 20, 35, 11, 11, + -3, -28, 2, 19, -1, 3, -6, -29, -5, 2, -25, -17, -12, -16, 22, 34, + 3, -4, -21, -36, 4, 26, 8, -1, -30, -54, -23, -3, -11, 0, -12, -27, + 7, 24, 13, 19, -1, -21, 10, 27, 14, 17, 0, -14, 18, 33, 19, 14, + -17, -41, -10, 9, 2, 7, -14, -30, 4, 20, 9, 9, -15, -35, -3, 16, + 9, 0, -1, -2, -3, 4, 7, 4, -2, -3, 0, 3, -1, -1, 4, 5, + -2, -13, -9, 1, 4, 2, 1, 2, 2, -2, -8, -4, 0, 4, 4, -3, + -4, -3, 1, 2, -1, 3, 14, 1, -7, -12, -4, -2, 1, 1, 9, 5, + -6, -5, -2, -1, -1, 1, 14, 6, -6, -7, 3, 8, -2, -4, 13, 12, + -10, -17, -10, -5, -4, 2, 3, 7, -6, -6, -1, -1, -4, 1, 11, 6, + -6, -9, 10, 11, 3, 1, 14, 15, -12, -20, -12, -9, -15, -1, 7, 2, + -16, -7, 6, 0, -2, 10, 26, 17, -6, -11, 24, 21, 1, 0, 18, 15, + -17, -31, -28, -23, -14, 0, -4, 0, -16, -8, 8, -4, -3, 7, 15, 5, + -3, -3, 26, 25, 12, 8, 28, 17, -15, -28, -18, -17, -18, -7, -3, -7, + -20, 0, 7, 1, -9, 6, 9, -4, -9, 2, 15, 24, 34, 31, 10, -4, + -15, -29, -17, -21, -41, -40, -5, 19, -20, 3, 11, 33, 28, 21, 18, 15, + 16, 3, -1, 18, 17, 15, 1, -15, -10, -5, -14, -42, -48, -43, -26, 4, + -29, -14, -9, 32, 20, 12, 15, 21, 39, 24, 8, 26, 33, 6, -3, 0, + 1, -7, -16, -41, -44, -51, -34, -3, -6, -6, -19, 26, 10, 15, 35, 46, + 32, 20, 16, 23, 38, 15, -4, -10, 17, -6, -41, -48, -53, -70, -52, -9, + -9, -22, -15, 19, 24, 22, 30, 49, 34, 10, 1, 15, 33, 15, 1, 17, + 46, 12, -38, -59, -50, -57, -46, -13, -16, -30, -24, 26, 37, 33, 30, 45, + 40, 2, -11, 17, 41, 24, -4, 16, 48, 15, -38, -67, -64, -65, -46, -18, + -18, -35, -32, 35, 39, 37, 21, 45, 42, -2, -19, 14, 37, 22, 7, 24, + 40, 13, -42, -68, -63, -63, -38, -6, -12, -34, -25, 39, 43, 39, 17, 47, + 45, 3, -19, 21, 45, 25, 2, 21, 31, 0, -45, -71, -78, -83, -48, 2, + 7, -27, -32, 34, 45, 49, 23, 44, 36, 5, -5, 38, 60, 27, -13, 21, + 42, -13, -69, -81, -86, -79, -38, -9, -11, -41, -36, 38, 56, 45, 10, 43, + 43, 10, -6, 36, 57, 41, 10, 36, 46, -16, -67, -66, -71, -80, -44, -8, + -5, -29, -27, 30, 43, 46, 20, 52, 39, -9, -21, 40, 68, 42, -1, 20, + 32, -14, -70, -86, -94, -90, -45, -2, 0, -31, -17, 36, 47, 46, 18, 44, + 29, -2, -11, 46, 74, 51, 14, 36, 46, -15, -78, -87, -91, -89, -46, -12, + -11, -28, -5, 41, 46, 40, 17, 51, 33, -6, -13, 49, 75, 52, 15, 30, + 34, -21, -79, -88, -93, -88, -42, -9, -4, -25, -3, 36, 40, 34, 16, 44, + 23, -8, -10, 52, 83, 55, 17, 38, 31, -31, -82, -91, -93, -82, -39, -16, + -10, -25, 5, 33, 42, 32, 20, 54, 25, -9, -3, 59, 85, 63, 24, 37, + 24, -39, -86, -92, -97, -80, -34, -17, -15, -24, 10, 35, 45, 32, 16, 45, + 12, -23, -2, 62, 78, 53, 21, 37, 26, -39, -91, -95, -96, -77, -29, -16, + -16, -25, 10, -1, 0, 3, 21, -26, 18, -30, 32, -19, -15, -27, 2, 0, + 103, -84, -53, -52, 79, 51, 36, -69, -31, 48, 71, 33, -74, -64, 10, 51, + 49, -68, -91, -16, 30, 33, -31, -58, -42, 14, 24, -25, 23, -71, 79, -22, + 123, -74, 28, 28, 115, 99, -7, 9, -15, 72, 1, 16, -47, -5, -71, -18, + -75, -26, -71, -28, -56, -24, -57, -19, -33, -5, 7, -3, 14, -8, 82, 100, + 23, -32, -15, 80, 98, 68, -30, -21, 24, 71, 28, -41, -96, -22, 32, 37, + -57, -110, -67, 28, 35, -22, -112, -79, 13, 70, 27, -55, -63, 31, 95, 86, + -4, -40, 29, 110, 110, 28, -50, -12, 66, 80, 14, -87, -81, -7, 36, -5, + -95, -118, -42, 26, 8, -69, -121, -48, 37, 60, -6, -68, -29, 67, 104, 61, + -24, -17, 70, 123, 92, -5, -43, 23, 82, 67, -28, -96, -54, 18, 30, -39, + -115, -96, -7, 25, -13, -99, -101, -13, 52, 42, -35, -62, 9, 88, 93, 28, + -32, 15, 97, 118, 58, -29, -24, 51, 82, 39, -61, -88, -26, 28, 9, -70, + -117, -63, 7, 14, -46, -109, -71, 15, 55, 16, -51, -42, 43, 94, 75, 2, + -21, 48, 107, 101, 23, -36, 4, 65, 70, 1, -81, -69, -3, 26, -19, -94, + -106, -32, 14, -3, -74, -103, -37, 34, 46, -10, -56, -12, 66, 91, 49, -15, + 1, 74, 111, 76, -4, -28, 31, 72, 50, -33, -85, -43, 11, 15, -46, -106, + -80, -11, 13, -26, -92, -84, -8, 44, 29, -30, -48, 19, 80, 81, 26, -18, + 27, 91, 103, 49, -22, -10, 48, 68, 22, -60, -75, -22, 17, -5, -71, -105, + -54, 3, 3, -49, -98, -58, 14, 44, 11, -44, -27, 45, 85, 65, 5, -8, + 53, 100, 87, 21, -26, 11, 60, 56, -6, -74, -58, -4, 13, -25, -90, -91, + -29, 7, -12, -72, -90, -29, 32, 37, -10, -46, -2, 66, 83, 47, -8, 10, + 74, 101, 68, -3, -19, 31, 62, 38, -36, -77, -40, 6, 4, -49, -100, -72, + -12, 3, -31, -86, -73, -4, 37, 25, -28, -36, 25, 75, 74, 25, -9, 34, + 88, 94, 43, -16, -4, 47, 58, 15, -57, -69, -22, 6, -12, -73, -96, -50, + -4, -7, -53, -89, -49, 13, 36, 5, -37, -17, 47, 77, 59, 9, 2, 58, + 92, 79, 19, -17, 16, 54, 45, -13, -69, -52, -8, 3, -33, -85, -82, -29, + -2, -20, -68, -79, -23, 24, 29, -11, -34, 7, 61, 73, 41, 0, 22, 73, + 90, 58, 1, -9, 32, 52, 26, -36, -69, -35, -3, -7, -53, -90, -63, -16, + -7, -36, -78, -60, -4, 29, 16, -22, -23, 29, 68, 64, 26, 2, 42, 80, + 81, 38, -8, 5, 42, 44, 4, -53, -57, -21, -2, -22, -69, -83, -43, -10, + -15, -51, -77, -38, 11, 27, 3, -27, -5, 46, 68, 52, 13, 15, 58, 83, + 68, 19, -8, 21, 46, 32, -16, -60, -44, -12, -6, -36, -76, -74, -34, -10, + -20, -57, -73, -33, 12, 27, 3, -1, -6, -11, -3, 4, 0, -7, -8, 1, + 21, 14, 28, 33, 25, -1, 7, 4, -13, -21, -44, -29, -17, -31, -32, 2, + 0, -20, 4, 3, 4, 0, -2, -5, -4, -14, 3, 14, 9, 28, 34, 54, + 43, 54, 39, 19, 17, -1, 5, -23, -31, -25, -35, -46, -60, -29, -29, -13, + -37, -22, -16, -20, -27, -21, -6, -16, 8, -5, 15, 26, 69, 65, 74, 85, + 81, 76, 51, 22, -10, -10, -19, -3, -39, -73, -55, -36, -18, -45, -49, -45, + -52, -47, -74, -73, -56, -31, -15, -16, -5, 18, 65, 86, 108, 94, 97, 90, + 79, 54, 30, 19, 10, 25, -16, -34, -37, -9, -16, -35, -44, -60, -60, -50, + -62, -70, -66, -44, -34, -34, -29, -10, 23, 61, 85, 79, 75, 70, 61, 41, + 31, 7, 8, 3, -22, -42, -28, 0, -13, -29, -39, -52, -56, -55, -58, -60, + -57, -41, -35, -37, -19, 5, 35, 71, 87, 85, 97, 112, 97, 71, 56, 52, + 53, 43, 18, -7, -3, 10, 0, -17, -39, -55, -58, -64, -80, -106, -121, -112, + -110, -113, -105, -82, -51, -8, 16, 20, 45, 66, 66, 49, 46, 59, 75, 78, + 63, 62, 74, 80, 80, 69, 51, 27, 11, 0, -14, -40, -53, -48, -55, -68, + -71, -56, -34, -1, 14, 24, 49, 62, 59, 42, 34, 43, 47, 43, 26, 30, + 33, 38, 26, 4, -17, -41, -66, -81, -92, -112, -120, -115, -116, -128, -125, -103, + -71, -36, -11, 9, 33, 56, 59, 54, 61, 67, 77, 77, 77, 79, 74, 75, + 73, 55, 30, 10, -21, -38, -46, -61, -70, -67, -70, -81, -77, -64, -45, -23, + -4, 10, 30, 44, 44, 39, 42, 48, 51, 50, 51, 58, 58, 65, 65, 47, + 29, 12, -14, -31, -41, -53, -63, -60, -62, -64, -58, -44, -26, -11, 1, 10, + 20, 22, 17, 9, 5, 6, 6, 2, 4, 10, 10, 17, 19, 9, 7, -1, + -14, -18, -13, -14, -9, 1, 7, 12, 17, 23, 31, 35, 36, 35, 38, 31, + 21, 16, 3, 0, -8, -11, -11, -13, -19, -20, -23, -34, -39, -51, -69, -78, + -81, -83, -83, -78, -70, -60, -47, -34, -19, 2, 20, 39, 57, 60, 66, 67, + 63, 61, 53, 50, 51, 47, 37, 32, 23, 13, 6, -3, -17, -23, -28, -34, + -37, -35, -27, -15, -2, 4, 12, 23, 30, 44, 47, 43, 41, 35, 29, 22, + 15, 13, 14, 7, -1, -5, -11, -19, -20, -25, -37, -43, -41, -43, -47, -47, + -40, -29, -17, -7, 5, 13, 23, 38, 44, 37, 34, 31, 23, 17, 6, 1, + -2, -10, -20, -25, -35, -45, -50, -54, -64, -68, -65, -66, -65, -59, -47, -30, + -19, -7, 5, 14, 28, 48, 62, 66, 72, 75, 78, 76, 67, 60, 56, 46, + 32, 20, 9, -2, -10, -21, -35, -43, -44, -49, -56, -57, -51, -38, -25, -13, + -2, 9, 25, 42, 56, 59, 64, 65, 67, 65, 57, 52, 49, 41, 28, 18, + 8, -2, -10, 0, 8, 13, 21, 20, 20, 17, 10, 8, -2, -6, -17, -21, + -29, -23, -25, -14, -7, -2, 7, 10, 20, 21, 22, 23, 19, 14, 9, -2, + -6, -18, -20, -28, -25, -23, -18, -10, -3, 5, 9, 22, 17, 28, 22, 21, + 17, 11, 2, -8, -18, -23, -27, -26, -24, -19, -13, -6, 3, 9, 17, 20, + 28, 24, 25, 21, 13, 6, -5, -14, -21, -29, -29, -30, -23, -19, -7, -1, + 10, 18, 25, 29, 27, 28, 20, 17, 5, -7, -13, -26, -29, -30, -30, -27, + -20, -12, 0, 11, 19, 25, 27, 30, 26, 28, 19, 11, -2, -12, -24, -30, + -35, -34, -30, -24, -14, -2, 9, 18, 23, 28, 26, 33, 31, 29, 24, 12, + 5, -12, -23, -30, -37, -36, -36, -26, -19, -5, 5, 19, 22, 32, 32, 36, + 35, 26, 21, 3, -6, -22, -34, -41, -44, -38, -31, -18, -6, 6, 15, 23, + 32, 33, 39, 34, 31, 23, 10, -2, -21, -32, -44, -47, -45, -37, -23, -12, + 6, 13, 28, 30, 38, 40, 40, 38, 23, 17, -6, -15, -35, -42, -50, -49, + -41, -31, -14, 0, 14, 26, 35, 42, 45, 45, 40, 27, 18, -4, -14, -33, + -42, -54, -52, -47, -36, -21, -5, 13, 24, 39, 43, 52, 47, 42, 36, 20, + 7, -15, -32, -45, -55, -56, -54, -43, -27, -8, 12, 26, 38, 45, 50, 51, + 48, 40, 27, 9, -11, -30, -46, -58, -62, -58, -49, -31, -11, 9, 24, 41, + 45, 54, 53, 54, 45, 30, 14, -10, -27, -48, -58, -67, -64, -56, -35, -15, + 6, 24, 37, 45, 54, 56, 56, 49, 39, 18, 0, -26, -45, -60, -74, -70, + -63, -41, -23, 4, 21, 39, 48, 53, 61, 58, 59, 43, 29, 3, -20, -46, + -64, -77, -77, -69, -50, -27, 0, 20, 36, 49, 56, 64, 64, 63, 51, 34, + 6, -17, -46, -65, -79, -83, -76, -58, -33, -6, 17, 38, 49, 60, 67, 68, + 66, 53, 37, 13, -13, -38, -65, -79, -90, -82, -68, -41, -15, 14, 36, 52, + 63, 70, 73, 69, 62, 44, 19, -8, -38, -63, -83, -93, -90, -77, -49, -20, + 12, 34, 54, 65, 72, 75, 76, 65, 51, 26, -1, -33, -62, -86, -98, -96, + -86, -58, -29, 6, 32, 54, 66, 73, 79, 76, 73, 58, 36, 4, -27, -60, + -85, -101, -104, -92, -70, -36, -1, 31, 53, 70, 75, 81, 80, 78, 65, 41, + 15, -24, -56, -84, -105, -109, -101, -79, -46, -7, 25, 56, 65, 77, 82, 85, + 83, 69, 51, 19, -14, -50, -83, -103, -115, -107, -88, -55, -17, 21, 50, 67, + 81, 86, 89, 85, 79, 55, 28, -8, -46, -77, -103, -116, -117, -97, -67, -25, + 1, 39, 66, 81, 92, 96, 97, 90, 73, 45, 11, -27, -64, -97, -120, -128, + -117, -89, -49, -5, 35, 65, 81, 93, 98, 99, 91, 75, 46, 12, -27, 28, + -9, -42, -57, -50, -18, 33, 77, 77, 17, -64, -96, -55, 22, 73, 68, 17, + -43, -77, -67, -15, 59, 102, 79, 12, -48, -71, -57, -28, -3, 11, 10, -3, + -17, -4, 44, 88, 79, 10, -69, -103, -74, -6, 54, 75, 53, -4, -63, -80, + -38, 32, 73, 59, 7, -43, -67, -57, -18, 33, 71, 71, 24, -31, -47, -17, + 20, 23, -14, -58, -73, -47, 10, 73, 110, 93, 20, -62, -97, -68, -6, 43, + 54, 28, -13, -51, -65, -35, 26, 74, 69, 12, -50, -68, -37, 9, 37, 37, + 16, -12, -26, -7, 36, 65, 45, -19, -87, -112, -75, -7, 58, 97, 92, 41, + -30, -75, -62, -3, 49, 52, 7, -44, -63, -45, -6, 37, 60, 42, -5, -42, + -41, -3, 38, 41, 8, -33, -51, -38, 3, 54, 90, 79, 12, -76, -127, -106, + -29, 47, 78, 63, 23, -19, -36, -16, 24, 50, 35, -15, -59, -64, -27, 17, + 40, 35, 11, -20, -39, -26, 19, 63, 67, 14, -61, -97, -72, -5, 64, 101, + 87, 26, -49, -96, -86, -32, 24, 40, 17, -11, -17, -3, 24, 51, 55, 29, + -20, -66, -69, -23, 35, 55, 25, -26, -59, -55, -14, 44, 86, 80, 23, -56, + -105, -87, -19, 48, 79, 67, 27, -18, -46, -43, -14, 17, 16, -20, -54, -47, + 3, 59, 83, 66, 18, -35, -64, -54, -8, 44, 59, 18, -48, -87, -72, -16, + 49, 88, 84, 37, -31, -81, -79, -26, 33, 52, 29, -5, -19, -6, 20, 34, + 27, -5, -51, -84, -71, -9, 62, 95, 71, 12, -40, -58, -37, 8, 52, 63, + 22, -53, -103, -88, -23, 47, 80, 64, 24, -14, -33, -28, -3, 21, 18, -15, + -45, -39, 5, 57, 78, 54, -1, -60, -97, -89, -29, 50, 92, 67, 0, -53, + -57, -13, 38, 64, 52, 10, -44, -82, -76, -26, 28, 49, 32, 1, -14, -1, + 24, 40, 38, 9, -43, -87, -79, -13, 69, 110, 80, 4, -65, -90, -69, -21, + 32, 58, 39, -9, -48, -45, 0, 52, 69, 46, 5, -34, -57, -50, -14, 23, + 28, -8, -48, -48, 4, 71, 99, 69, 3, -63, -99, -88, -30, 46, 92, 78, + 16, -45, -66, -44, -6, 25, 34, 16, -24, -55, -43, 10, 67, 80, 37, -22, + -48, -29, 7, 30, 27, -5, -51, -84, -73, -11, 71, 116, 95, 27, -43, -84, + -84, -43, 18, 63, 60, 10, -44, -53, -9, 41, 49, 14, -31, -57, -50, -15, + 29, 61, 57, 14, -37, -51, -14, 38, 63, 47, -1, -61, -106, -105, -47, 44, + 115, 113, 42, -36, -64, -42, -2, 23, 20, -3, -28, -39, -21, 24, 64, 59, + 7, -48, -67, -47, -7, 36, 59, 47, 2, -55, -77, -31, 55, 111, 89, 7, + -75, -113, -96, -42, 21, 62, 64, 28, -13, -18, 17, 45, 28, -2, -7, -6, + -7, -7, -8, -8, -8, -8, -7, -6, -5, -4, -3, -3, -2, -2, -1, 0, + 1, 2, 4, 5, 6, 8, 9, 10, 11, 12, 13, 13, 14, 15, 16, 17, + 17, 17, 17, 17, 16, 16, 15, 15, 14, 14, 13, 12, 10, 10, 9, 8, + 7, 6, 5, 5, 4, 3, 2, 1, 0, -2, -3, -4, -5, -6, -7, -8, + -9, -10, -11, -12, -13, -13, -14, -14, -14, -14, -14, -15, -15, -15, -15, -16, + -16, -14, -14, -12, -10, -13, -10, -13, -7, -3, -5, -1, -1, -5, -5, 8, + 13, 10, 10, 15, 16, 17, 30, 34, 19, 17, 22, 29, 27, 22, 16, 1, + -3, 8, 18, 11, 6, 8, 8, 1, 6, 18, 5, -8, -4, 4, 5, 3, + 5, -3, -6, 12, 30, 23, 9, 5, 6, 9, 15, 27, 20, 2, 0, 10, + 17, 8, -1, -4, -8, -8, -3, -7, -19, -28, -24, -22, -31, -42, -47, -50, + -50, -42, -35, -35, -43, -41, -31, -27, -23, -17, -9, -7, 3, 26, 37, 38, + 37, 41, 39, 39, 49, 55, 50, 46, 53, 58, 51, 44, 36, 24, 9, 5, + 2, -12, -25, -28, -26, -33, -42, -44, -55, -66, -69, -62, -60, -65, -57, -42, + -33, -26, -15, -5, -6, 0, 15, 29, 34, 41, 55, 61, 62, 68, 71, 62, + 49, 49, 49, 39, 29, 24, 14, -2, -10, -16, -34, -56, -67, -70, -77, -83, + -85, -88, -93, -92, -79, -74, -78, -74, -61, -49, -41, -23, -9, -2, 11, 35, + 54, 56, 58, 64, 69, 73, 81, 91, 86, 77, 78, 77, 67, 50, 39, 24, + 6, -4, -10, -22, -41, -49, -52, -62, -73, -81, -87, -98, -97, -83, -74, -70, + -63, -46, -33, -23, -6, 9, 18, 26, 48, 69, 77, 85, 97, 106, 107, 111, + 114, 104, 89, 83, 84, 75, 60, 50, 34, 13, -5, -16, -34, -59, -74, -80, + -86, -95, -97, -96, -104, -104, -95, -86, -86, -82, -66, -49, -32, -11, 12, 26, + 36, 55, 73, 81, 84, 94, 104, 107, 114, 120, 116, 102, 92, 88, 73, 54, + 37, 21, 0, -16, -23, -37, -58, -76, -85, -94, -108, -114, -116, -120, -119, -106, + -89, -84, -78, -64, -49, -37, -21, 1, 13, 25, 46, 71, 88, 95, 105, 113, + 112, 113, 116, 112, 97, 91, 91, 83, 68, 51, 35, 11, -10, -23, -38, -60, + -80, -86, -93, -102, -107, -110, -116, -121, -114, -102, -98, -93, -77, -55, -38, -18, + 1, 13, 25, 46, 71, 88, 95, 105, 113, 112, 113, 116, 112, 97, 91, 91, + 83, 68, 51, 35, 11, -10, -23, -38, -60, -80, -86, -93, -102, -107, -110, -116, + -121, -114, -102, -98, -93, -77, -55, -38, -18, 1, -3, -7, -8, -3, 1, 0, + 3, -5, -9, -14, -15, -4, 0, 7, 12, 12, 11, 18, 16, 14, 14, 11, + 20, 14, 19, 7, 12, 8, 13, 8, 7, 9, 0, 9, -7, -4, -5, -8, + -7, -9, -7, -2, -7, -4, 1, 1, 0, -2, 3, 2, 1, 2, 1, -2, + -3, -7, -2, -2, -2, -5, -4, -4, -4, 3, 6, 8, 3, 0, -3, -2, + 3, 4, 3, 2, 2, -2, 1, 0, 2, 3, 9, 8, 2, -3, -4, -2, + 1, 4, 0, -2, 3, 1, 7, 1, -4, 0, 2, 3, 1, 1, 2, -5, + 3, -3, -4, -3, -8, 2, -7, 1, -3, -2, -5, -8, -7, -8, -7, -5, + -7, -4, -8, -10, -7, -8, -7, -5, 0, -2, 0, -2, -3, -3, -2, 0, + 1, 0, 1, 0, -3, -3, -5, -5, -9, -9, -13, -16, -21, -26, -25, -25, + -16, -16, -12, -13, -15, -9, 3, 25, 44, 66, 68, 66, 49, 17, 13, 18, + 41, 51, 40, 35, 25, 23, -2, -16, -28, -8, -4, -12, -18, -34, -29, -31, + -28, -18, -4, 2, 16, 13, 20, 9, 4, 2, -3, -4, -9, -9, -9, -8, + -9, -10, -13, -14, -15, -13, -4, 7, 13, 19, 18, 16, 9, 7, 4, 6, + 8, 7, 7, 3, -3, -15, -19, -24, -21, -16, -9, 0, 3, 7, 4, 4, + -3, -2, 6, 13, 20, 14, 16, 14, 11, 7, 0, -4, -3, -3, -7, -12, + -12, -9, -5, -5, -7, -9, -4, -2, -2, -2, -4, -9, -10, -13, -13, -14, + -15, -13, -9, -8, -9, -9, -7, -4, 2, 2, 6, 9, 8, 11, 9, 11, + 9, 8, 6, 0, -7, -13, -21, -29, -36, -45, -53, -63, -72, -73, -61, -41, + 0, 52, 98, 109, 81, 64, 54, 78, 77, 45, 39, 44, 25, 19, 6, -8, + 25, 30, 44, 62, 46, -20, -85, -89, -88, -47, -29, -30, 2, 11, 8, 12, + 24, 33, 29, 25, 22, 1, -15, -34, -37, -36, -41, -36, -28, -15, 2, 9, + 11, 14, 12, 8, 12, 17, 18, 19, 23, 20, 20, 20, 8, -5, -14, -15, + -15, -13, -13, -18, -19, -24, -29, -32, -31, -23, -12, -2, 12, 20, 23, 24, + 25, 20, 22, 18, 16, 14, 9, 7, 2, 1, -9, -10, -19, -15, -12, -13, + -8, -5, -4, -4, -7, -10, -12, -12, -16, -14, -8, -9, -13, -14, -18, -15, + -10, -5, -3, 3, 4, 6, 11, 13, 13, 16, 16, 16, 12, 6, -3, -10, + -16, -21, -28, -37, -48, -61, -77, -88, -87, -68, -34, 28, 92, 127, 99, 64, + 50, 72, 92, 55, 43, 51, 41, 32, 4, -8, -7, -17, -23, -31, -33, -35, + -32, -28, -23, -18, -12, -8, -4, -2, 0, 1, 2, 2, 3, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 4, 6, 7, 7, 7, 8, 9, 9, 8, + 8, 9, 11, 14, 18, 22, 27, 32, 33, 30, 21, 6, -12, -30, -45, -54, + -56, -51, -41, -29, -17, -9, -3, 0, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 3, 3, 3, 3, 3, 2, 3, 4, 5, 8, 9, 10, 9, 8, 7, + 7, 8, 10, 15, 20, 25, 30, 35, 39, 39, 32, 19, 0, -22, -42, -56, + -62, -61, -53, -40, -27, -15, -7, -3, -1, 0, 0, 0, 0, 2, 3, 4, + 5, 5, 5, 4, 2, 0, -1, 0, 2, 5, 8, 9, 10, 10, 9, 9, + 8, 9, 10, 14, 19, 24, 28, 32, 34, 38, 36, 29, 17, -5, -28, -49, + -61, -65, -61, -52, -39, -25, -14, -7, -3, -2, -1, -2, -1, 0, 2, 4, + 6, 7, 7, 5, 3, 0, -1, -1, 0, 3, 7, 11, 13, 14, 13, 12, + 10, 8, 8, 9, 12, 17, 22, 26, 29, 31, 33, 31, 26, 18, 3, -16, + -35, -50, -59, -61, -56, -46, -35, -23, -14, -6, -2, 0, 1, 2, 3, 4, + 4, 5, 5, 5, 4, 2, 1, -1, -1, 0, 2, 5, 9, 12, 13, 13, + 12, 11, 9, 7, 7, 8, 11, 15, 20, 24, 29, 33, 35, 34, 30, 21, + 4, -16, -37, -55, -66, -68, -63, -50, -35, -21, -9, -1, 4, 5, 5, 4, + 4, 3, 3, 3, 3, 2, 2, 1, 0, -1, -1, 1, 6, 10, 13, 15, + 15, 13, 11, 8, 5, 4, 4, 7, 11, 17, 22, 27, 32, 36, 39, 39, + 36, 24, 6, -20, -48, -70, -81, -79, -67, -48, -29, -12, -1, 5, 7, 7, + 4, 2, 1, 1, 2, 2, 3, 2, 2, -1, -2, -3, -3, -1, 3, 8, + 13, 16, 17, 16, 12, 8, 3, -1, -3, -2, 2, 11, 21, 29, 36, 38, + 39, 42, 48, 57, 52, 23, -27, -76, -107, -113, -98, -71, -42, -18, -1, 8, + 12, 13, 10, 7, 3, 1, 1, 2, 3, 2, 1, 0, -2, -3, -3, -1, + 2, 8, 13, 17, 18, 17, 12, 7, 1, -3, -4, -3, 20, 30, 38, 41, + 39, 38, 46, 65, 75, 45, -23, -89, -126, -127, -101, -64, -31, -7, 5, 11, + 13, 14, 13, 9, 4, 1, 0, 1, 2, 1, -1, -3, -4, -4, -2, 2, + 6, 10, 14, 18, 18, 15, 9, 1, -6, -10, -13, -10, -4, 7, 20, 0, + 14, 19, 23, 26, 28, 28, 26, 23, 18, 11, 3, -4, -10, -16, -21, -23, + -24, -22, -20, -16, -12, -8, -3, 3, 8, 13, 19, 23, 26, 27, 26, 23, + 17, 10, 4, -3, -9, -15, -20, -24, -25, -25, -22, -17, -11, -3, 3, 9, + 14, 18, 20, 22, 23, 23, 21, 17, 13, 6, 1, -6, -11, -15, -18, -20, + -19, -19, -17, -16, -13, -11, -8, -5, -1, 2, 5, 7, 9, 9, 8, 6, + 3, 0, -3, -7, -10, -14, -17, -19, -19, -18, -16, -12, -7, -2, 3, 8, + 13, 16, 18, 19, 17, 14, 8, -1, -11, -21, -31, -38, -41, -40, -34, -25, + -12, 2, 17, 32, 45, 56, 62, 65, 63, 58, 49, 38, 25, 10, -6, -18, + -28, -37, -44, -51, -59, -64, -64, -56, -40, -17, 7, 29, 46, 56, 58, 59, + 56, 51, 45, 33, 19, 4, -13, -26, -39, -49, -56, -59, -55, -46, -34, -19, + -4, 10, 21, 30, 40, 46, 51, 52, 49, 43, 31, 18, 5, -8, -16, -21, + -23, -26, -29, -35, -39, -42, -40, -34, -22, -11, 2, 11, 18, 21, 24, 23, + 22, 19, 14, 7, -3, -13, -21, -30, -39, -46, -50, -52, -49, -42, -31, -17, + -3, 12, 26, 39, 49, 57, 60, 58, 51, 39, 22, 1, -23, -47, -68, -82, + -89, -88, -77, -60, -37, -11, 16, 43, 65, 83, 94, 100, 101, 96, 87, 71, + 51, 29, 4, -18, -38, -58, -75, -91, -104, -109, -105, -87, -61, -27, 8, 39, + 67, 87, 97, 97, 88, 71, 54, 36, 16, -2, -23, -42, -57, -70, -75, -75, + -71, -60, -43, -23, -1, 18, 31, 47, 57, 66, 71, 68, 61, 49, 32, 17, + 1, -11, -22, -33, -41, -47, -54, -59, -63, -62, -57, -46, -30, -12, 1, 17, + 30, 41, 49, 50, 47, 40, 29, 17, 3, -14, -30, -46, -60, -70, -76, -77, + -73, -63, -48, -28, -4, 20, 44, 65, 81, 91, 93, 88, 77, 60, 37, 11, + -19, -49, -76, -97, -109, -110, -100, -81, -56, -25, 7, 38, 67, 91, 109, 121, + 127, 126, 116, 96, 68, 38, 8, -18, -43, -68, -90, -110, -124, -127, -116, -91, + -59, -22, 14, 47, 77, 98, 107, 105, 93, 74, 54, 33, 13, -6, -26, -45, + -60, -71, -78, -79, -74, -61, -42, -21, 1, 18, 33, 49, 60, 68, 73, 70, + 62, 48, 32, 15, 0, -13, -24, -34, -42, -48, -55, -61, -65, -65, -60, -48, + -32, -15, 2, 19, 32, 43, 50, 51, 47, 40, 28, 16, 1, -14, 2, -2, + 2, -5, -3, -1, 0, -4, -4, -6, -4, -6, -4, -4, -7, -6, -7, -6, + -1, 0, 3, 13, 14, 16, 12, 13, 2, 1, 0, -1, -1, -1, -2, -2, + -2, -3, -3, -4, -8, -4, -4, -5, -5, -5, -7, -9, -12, -8, -14, -11, + -14, -18, -8, 1, 31, 71, 68, 24, -5, -11, -7, -5, -5, -5, -3, -2, + -5, -5, -9, -8, -7, -7, -9, -12, -11, -17, -14, -16, -15, -20, -26, -30, + -27, -15, 16, 51, 87, 101, 70, 8, -18, -11, -14, -7, -7, -1, -2, -5, + -7, -12, -14, -10, -10, -13, -14, -13, -16, -16, -17, -18, -35, -31, -30, -34, + -9, 16, 56, 84, 89, 60, 30, 5, -7, -5, -8, -3, -4, -4, -6, -12, + -14, -13, -10, -12, -12, -9, -10, -8, -12, -13, -15, -19, -23, -26, -33, -29, + -28, -9, 12, 43, 71, 88, 72, 48, 29, -2, -16, -19, -12, -12, -12, -7, + -11, -10, -10, -10, -11, -13, -15, -18, -19, -17, -16, -15, -13, -12, -13, -9, + -13, -17, -21, -18, 2, 34, 59, 87, 92, 98, 38, -30, -24, -27, -18, -16, + -11, -11, -13, -15, -12, -14, -15, -18, -17, -20, -18, -15, -10, -7, -3, -1, + 2, -8, -11, -22, -22, -20, 7, 31, 61, 97, 106, 43, -23, -28, -25, -20, + -12, -7, -5, -7, -10, -13, -13, -13, -11, -14, -15, -15, -12, -8, -7, -4, + -2, -4, -10, -15, -19, -26, -10, 12, 42, 72, 101, 90, 20, -25, -27, -22, + -18, -10, -6, -9, -11, -16, -17, -16, -14, -10, -8, -9, -9, -9, -9, -9, + -8, -5, -3, -6, -10, -17, -24, -21, 4, 30, 61, 84, 96, 79, -16, -38, + -27, -26, -17, -12, -8, -12, -13, -14, -14, -11, -8, -4, -4, -7, -9, -8, + -10, -12, -8, -5, -4, -7, -10, -18, -24, -11, 14, 42, 70, 79, 93, 36, + -32, -26, -28, -19, -15, -9, -9, -13, -16, -14, -12, -8, -5, -3, -7, -9, + -9, -9, -11, -8, -5, -1, -6, -9, -15, -24, -23, 6, 28, 63, 86, 127, + 37, -45, -27, -28, -26, -19, -4, -5, -8, -11, -12, -14, -12, -8, -4, -8, + -8, -10, -8, -13, -8, -8, -3, -8, -8, -16, -23, -17, 7, 34, 69, 83, + 113, 37, -50, -28, -25, -22, -16, 0, -3, -8, -12, -12, -14, -14, -10, -5, + -7, -6, -9, -9, -13, -9, -10, -7, -9, -9, -15, -20, -14, 8, 33, 64, + 81, 90, 57, -29, -28, 0, -4, 10, 10, 11, -15, 4, -1, 3, -11, 11, + 2, -12, 3, 18, -10, -62, 89, -16, -95, 118, -128, 122, -128, 112, -100, 109, + -121, 120, -104, 58, 10, -88, 127, -102, 6, 98, -126, 35, 89, -111, -7, 112, + -53, -94, 92, 64, -106, -53, 109, 52, -100, -75, 86, 95, -45, -119, -12, 111, + 74, -58, -118, -27, 97, 100, -4, -107, -95, 17, 109, 92, -4, -99, -109, -26, + 78, 115, 66, -27, -104, -109, -41, 55, 112, 98, 32, -53, -109, -105, -44, 41, + 102, 109, 67, -4, -74, -112, -102, -47, 27, 88, 112, 93, 45, -19, -78, -110, + -105, -65, -4, 59, 101, 110, 87, 43, -13, -67, -103, -111, -89, -44, 13, 65, + 100, 109, 93, 59, 14, -36, -78, -104, -108, -90, -53, -6, 43, 83, 104, 106, + 88, 57, 17, -27, -66, -95, -108, -102, -80, -44, -2, 41, 77, 99, 106, 98, + 77, 46, 10, -29, -64, -91, -105, -105, -91, -64, -29, 10, 48, 78, 98, 105, + 100, 84, 59, 30, -3, -36, -65, -88, -101, -105, -99, -83, -60, -32, -1, 30, + 58, 80, 96, 103, 102, 94, 80, 62, 40, 16, -10, -35, -58, -78, -92, -101, + -104, -100, -91, -77, -58, -36, -13, 12, 36, 57, 75, 89, 98, 102, 102, 97, + 88, 76, 61, 44, 25, 5, -15, -35, -54, -70, -84, -94, -101, -104, -103, -98, + -89, -77, -63, -46, -27, -8, 12, 31, 49, 65, 79, 90, 97, 102, 104, 102, + 97, 90, 81, 70, 57, 42, 27, 10, -7, -24, -40, -56, -70, -81, -91, -99, + -103, -105, -105, -101, -95, -87, -76, -63, -49, -34, -18, -1, 16, 32, 48, 62, + 74, 85, 93, 100, 104, 105, 105, 102, 97, 90, 82, 72, 61, 48, 35, 21, + 6, -9, -24, -38, -52, -65, -76, -86, -94, -101, -105, -108, -108, -106, -102, -96, + -87, -78, -66, -54, -40, -26, -11, 4, 19, 34, 48, 61, 73, 83, 92, 99, + 104, 107, 108, 108, 105, 101, 96, 89, 80, 70, 60, 48, 36, 22, 9, -5, + -19, -33, -46, -58, -69, -80, -89, -96, -102, -107, -109, -110, -110, -107, -102, -97, + -89, -80, -70, -59, -47, -33, -20, -6, 7, 19, 30, 41, 50, 58, 65, 71, + 75, 78, 79, 80, 79, 77, 74, 70, 65, 60, 54, 48, 42, 36, 29, 22, + 16, 10, 4, -2, -7, -12, -16, -19, -22, -24, -26, -27, -27, -27, -26, -25, + -23, -22, -19, -17, -14, -12, -10, -1, -1, -4, -9, -9, -7, -6, -7, -3, + 4, 8, 10, 11, 13, 10, 4, -3, -10, -15, -13, -9, -10, -11, -5, 4, + 12, 14, 12, 13, 14, 9, 1, -8, -15, -21, -23, -22, -13, -3, 7, 17, + 24, 27, 19, 11, 16, 15, -5, -24, -29, -23, -27, -32, -21, 5, 18, 20, + 21, 24, 24, 15, 11, 8, -6, -30, -31, -19, -17, -24, -14, 2, 17, 15, + 12, 17, 16, 19, 8, -5, -2, -1, -17, -17, -3, 6, 5, -4, 0, 1, + -12, -9, 9, 11, -4, -14, -8, 9, -2, -21, -14, 4, 9, 9, 11, 18, + 21, 10, 8, 16, 10, 26, 35, 6, -14, -28, -25, -24, -55, -65, -33, -17, + 1, -6, -6, 8, 23, 33, 49, 37, 19, 16, 11, 24, 42, 17, -37, -36, + 3, 7, -23, -36, -9, 9, -12, -20, -8, -2, -4, -23, -17, -6, 0, 10, + 24, 24, 40, 46, 33, 39, 26, 5, 6, 9, -12, -26, -33, -42, -61, -52, + -43, -37, -21, -4, 7, 13, 28, 36, 31, 24, 1, -1, 20, 24, 23, 21, + 26, 27, 8, -32, -44, -3, 28, -1, -36, -30, -6, 13, -12, -34, -18, -6, + 9, 21, 25, 16, 10, 38, 62, 46, 17, -11, -7, 10, -8, -44, -53, -33, + -35, -38, -29, -27, -16, 0, 1, 9, 37, 50, 36, 2, -20, -12, 15, 21, + 24, 32, 29, 20, 23, 12, -8, -3, 4, -10, -5, 2, -19, -63, -70, -21, + 20, 41, 23, 33, 57, 61, 42, 21, 15, 10, -45, -82, -60, -29, -44, -77, + -50, -7, 4, -4, 10, 32, 56, 42, 1, -10, -18, 2, 22, 28, 33, 42, + 47, 43, 47, 11, -23, 0, 10, -40, -81, -70, -28, -29, -68, -29, 19, 6, + 7, 21, 40, 41, 32, 22, 28, 47, 69, 66, 35, 21, 15, -3, -20, -34, + -24, -6, -19, -59, -47, -42, -35, -28, 15, 45, 51, 66, 78, 83, 37, 1, + 13, 7, -51, -81, -92, -83, -87, -74, -58, -73, -51, 12, 35, 26, 35, 47, + 69, 70, 63, 65, 49, 47, 68, 73, 52, 33, 15, -12, -30, -50, -51, -46, + -45, -60, -50, -50, -50, -54, -24, 38, 78, 90, 106, 99, 40, -6, -11, -46, + -110, -127, -107, -76, -67, -53, -41, -41, -23, 14, 33, 27, 34, 49, 70, 71, + 66, 65, 51, 51, 69, 72, 52, 32, 10, -12, 0, -5, -2, -5, 2, -29, + 22, 0, -27, 67, -59, 45, -13, -37, 28, 65, -4, 6, 60, 5, 58, 44, + 60, 27, 43, 96, 71, 81, 48, 96, 70, 23, 90, 66, 80, 88, 40, 20, + 61, 64, 12, 36, 24, 4, 7, 5, -27, -38, -26, -33, -49, -50, -70, -69, + -93, -92, -94, -104, -104, -101, -110, -107, -111, -111, -126, -87, -119, -100, -94, -112, + -93, -93, -80, -81, -76, -58, -56, -70, -30, -21, -42, -13, -3, 2, 8, 20, + 28, 41, 45, 59, 62, 69, 84, 85, 90, 103, 109, 111, 118, 121, 121, 123, + 121, 122, 121, 122, 121, 122, 121, 121, 120, 121, 120, 121, 120, 121, 120, 120, + 119, 120, 119, 120, 118, 105, 106, 110, 83, 89, 92, 75, 67, 61, 57, 47, + 40, 33, 24, 17, 10, 3, -2, -10, -20, -31, -31, -37, -49, -50, -63, -66, + -69, -74, -79, -91, -89, -92, -95, -102, -106, -104, -107, -113, -113, -110, -113, -116, + -114, -115, -114, -115, -114, -113, -114, -113, -114, -113, -112, -113, -109, -105, -111, -106, + -107, -103, -100, -103, -99, -97, -98, -99, -92, -92, -93, -92, -92, -90, -88, -90, + -88, -86, -89, -85, -85, -87, -85, -85, -82, -83, -82, -80, -78, -79, -76, -74, + -73, -73, -69, -68, -66, -64, -65, -62, -58, -56, -56, -52, -50, -47, -43, -42, + -39, -35, -33, -31, -27, -23, -21, -16, -16, -8, -7, -3, 1, 0, 10, 15, + 15, 19, 26, 29, 30, 38, 41, 42, 47, 54, 54, 57, 63, 68, 69, 72, + 77, 78, 80, 85, 84, 86, 87, 86, 87, 86, 85, 86, 85, 84, 85, 84, + 83, 84, 83, 82, 82, 83, 82, 81, 82, 81, 80, 81, 80, 79, 80, 79, + 79, 78, 79, 78, 78, 77, 74, 70, 66, 64, 61, 55, 52, 49, 45, 40, + 35, 32, 29, 24, 19, 15, 12, 8, 4, 0, -4, -8, -11, -15, -17, -20, + -25, -26, -29, -32, -34, -37, -39, -41, -43, -45, -46, -48, -49, -50, -50, -52, + -52, -53, -52, -53, -54, -53, -53, -52, -52, -51, -50, -50, -49, -48, -48, -46, + -45, -44, -42, -41, -40, -39, -37, -35, -34, -32, -30, -28, -27, -24, -23, -22, + -20, -19, -17, -15, -14, -13, -12, -10, -9, -8, -8, -6, -6, -5, -4, -4, + -3, -3, -2, -2, -1, -2, -1, -2, -1, -1, 0, -1, -1, 1, 0, 0, + -3, -1, 1, -4, -4, -3, -2, -5, -3, 0, -1, -1, -3, -1, 0, 2, + 0, -2, -5, 5, 4, 1, 7, 2, 2, 1, 8, 1, 6, 2, -4, 2, + 1, -4, 6, -8, -3, -7, -2, -6, -1, -9, 1, -2, -4, 1, 2, 1, + -2, 8, 2, 0, 14, 9, 10, 5, 3, 5, 6, 4, 3, -8, -2, -4, + -10, -1, -5, -3, -4, -6, -13, -5, -4, -4, -3, 2, -13, -6, 3, 6, + 6, 7, 1, 1, 6, 6, 16, 13, 9, 10, 9, 2, 7, 10, 4, -4, + -3, -17, -7, -6, -6, -10, -17, -17, -10, -11, -9, -5, -6, -8, 2, 1, + 8, 19, 15, 18, 24, 19, 16, 17, 19, 11, 7, 1, -5, -8, -9, -15, + -8, -9, -14, -20, -19, -9, -18, -10, -13, -23, -13, -12, -7, 0, -1, 5, + 16, 12, 28, 30, 32, 34, 34, 19, 24, 23, 16, 11, 5, -7, -19, -17, + -16, -21, -26, -23, -32, -31, -30, -25, -26, -24, -19, -13, -9, -1, 0, 4, + 6, 13, 15, 19, 17, 13, 8, 8, 8, 7, 0, -4, -8, -10, -7, -5, + -6, -6, -9, -12, -8, -10, -9, -9, -11, -13, -12, -9, -4, -1, 4, 9, + 19, 27, 31, 26, 16, 14, 16, 16, 12, 1, -8, -14, -11, -9, -6, -11, + -11, -12, -14, -10, -11, -13, -15, -19, -23, -19, -14, -8, -5, -1, 8, 34, + 62, 59, 12, 14, 32, 22, 6, 20, 6, -9, -54, -16, -1, -19, 7, -15, + -13, -12, -14, -15, -14, -22, -24, -30, -30, -20, -12, -6, 3, 26, 66, 88, + 39, 0, 47, 36, -2, 26, -23, 21, 13, -6, -60, -42, 6, -22, 4, -18, + -16, -4, -16, -19, -24, -39, -31, -25, -32, -26, -11, 12, 55, 104, 75, 10, + 35, 62, 9, 26, -16, -8, 19, 3, -9, -61, -46, 2, -26, -7, -16, -10, + 2, -7, -22, -23, -38, -40, -37, -44, -33, -8, 37, 101, 124, 36, -5, 89, + 20, 38, 5, -26, 3, 1, 5, -28, -65, -21, 1, -22, -12, -26, 1, -7, + -10, -24, -26, -33, -37, -48, -50, -36, 5, 63, 122, 109, 7, 35, 84, 5, + 59, -36, -4, -11, -1, -5, -40, -55, -4, -15, -21, -16, -22, 5, -10, -17, + -20, -27, -23, -44, -54, -62, -23, 29, 114, 127, 51, 7, -2, -4, -2, 4, + 11, 14, 10, 2, -7, -9, -9, -15, -16, -7, 3, 2, -10, -21, -17, 6, + 10, -8, -28, -11, 45, 66, 64, 47, 36, 49, 49, 27, 9, -12, -18, -25, + -30, -11, 0, -5, 0, -1, -18, -36, -33, -18, -10, -13, -31, -26, -25, -17, + 4, 28, 70, 89, 48, 9, -32, -58, -56, -70, -57, -17, -38, -48, -35, -32, + -7, 35, 38, 53, 62, 44, 33, 27, -6, -35, -52, -65, -54, -40, -43, -30, + -25, 2, 63, 54, 34, 17, 34, 70, 60, 8, -15, -3, 0, 39, 55, 35, + 39, 60, 75, 36, 20, -7, -25, -66, -110, -89, -89, -71, -36, -12, 9, 31, + 41, 54, 46, 45, 59, 41, 22, 3, -69, -110, -126, -116, -64, -15, 9, 29, + 33, 30, 56, 42, 12, 23, 6, -27, -36, -21, -22, -32, -21, -30, -29, -5, + 9, 16, 22, -9, -12, 31, 24, -17, -41, -23, 32, 32, 26, 34, 64, 66, + 109, 104, 51, 5, 12, 16, -36, -58, -59, -66, -63, -82, -64, -23, -9, 11, + 16, 20, 19, 13, 12, 33, 37, 41, 46, 28, 7, -58, -93, -79, -64, -33, + -1, 22, -4, 2, 19, 4, -7, -3, -3, 5, 1, -10, -3, 12, -6, -38, + -29, -17, -5, 11, 2, -33, -20, 44, 42, 20, -30, -24, 9, 44, 38, 20, + 36, 71, 61, 86, 72, 25, -8, 10, 17, -35, -54, -63, -67, -70, -78, -58, + -16, -7, 19, 22, 20, 21, 29, 21, 16, 35, 36, 16, -8, -27, -61, -58, + -67, -43, 3, 35, 38, -2, -2, 10, -9, -29, -14, -5, -1, -5, 2, 12, + -6, -32, -23, -22, -16, -5, 3, -9, -29, 27, 56, 39, 11, -27, -28, 23, + 34, 28, 18, 20, 62, 82, 71, 74, 24, -4, 16, 18, -39, -54, -65, -61, + -52, -64, -49, -11, -4, 12, 17, 16, 25, 24, 6, 23, 36, 18, 18, -1, + -42, -50, -90, -43, 3, 35, 38, -2, -2, 10, -9, -29, -14, -5, -1, -5, + 2, 12, -6, -32, -23, -22, -16, -5, 3, -9, -29, 27, 56, 39, 11, -27, + -28, 23, 34, 28, 18, 20, 62, 82, 71, 74, 24, -4, 16, 18, -39, -54, + -65, -61, -52, -64, -49, -11, -4, 12, 17, 16, 25, 24, 6, 23, 36, 18, + 18, -1, -42, -50, -90, -43, 0, 1, 6, -11, 19, -25, 24, -15, 11, -6, + 1, 9, -6, -3, 11, -18, 28, -23, 8, 6, -2, -1, 0, -5, 18, -23, + 24, -28, 27, -12, -1, -2, 6, 4, -14, 19, -29, 42, -40, 22, -6, -3, + 14, -16, 4, 8, -9, 13, -22, 17, 5, -24, 37, -34, 20, -4, -11, 19, + -20, 21, -16, 1, 17, -17, 5, -9, 25, -31, 31, -40, 32, -11, -7, 4, + -4, 13, -23, 29, -40, 51, -49, 20, 3, -20, 38, -47, 34, -21, 14, -9, + 4, -13, 20, -29, 37, -57, 59, -48, 23, -5, -7, 5, -6, -5, 13, -17, + 9, -4, -12, 22, -19, -8, 10, -5, -7, 8, -18, 19, -13, 5, -12, 6, + -10, 18, -40, 66, -91, 82, -56, 17, 19, -51, 56, -45, 30, -19, 5, -6, + 7, -9, -4, -2, -5, 13, -19, 1, 20, -28, 13, -6, 0, -17, 33, -48, + 38, -16, -20, 53, -75, 75, -61, 30, -12, -9, 2, 5, -9, -7, 15, -17, + 9, 4, -46, 70, -85, 86, -67, 29, 18, -60, 76, -70, 29, -8, -1, 1, + 14, -58, 93, -118, 127, -125, 85, -36, -2, 17, -39, 46, -61, 70, -99, 122, + -120, 56, 15, -85, 116, -101, 30, 43, -108, 127, -122, 72, -38, -3, 20, -31, + 29, -37, 42, -50, 63, -72, 40, -7, -46, 66, -82, 53, -25, 1, 1, -1, + -3, 3, -24, 24, -34, 27, -24, 36, -49, 37, -38, 35, -42, 13, -4, -14, + 14, -29, 42, -58, 58, -60, 41, -39, 27, -35, 27, -32, 25, -37, 43, -50, + 32, -20, -4, 4, -14, 16, -43, 66, -93, 79, -58, 27, -11, -21, 34, -40, + 24, -7, -25, 31, -29, 19, -18, -2, 1, -6, 4, -31, 47, -63, 62, -64, + 32, 2, -29, 23, -21, 19, -41, 59, -76, 62, -52, 26, -11, -1, -10, 6, + -10, -7, 17, -42, 34, -12, -34, 73, -106, 92, -61, 26, -24, 8, -7, -2, + 3, -24, 31, -44, 27, -9, -22, 38, -43, 15, -4, -3, -2, -12, 5, 1, + -7, 7, -25, 17, -17, 4, -15, 27, -40, 34, -18, 6, -13, 12, -3, -9, + -6, 8, -18, 18, -36, 54, -55, 30, -25, 26, -41, 38, -49, 48, -38, 8, + 16, -40, 47, -52, 34, -12, -4, 2, -13, 0, 1, 6, -11, 19, -25, 24, + -15, 11, -6, 1, 9, -6, -3, 11, -18, 28, -23, 8, 6, -2, -1, 0, + -5, 18, -23, 24, -28, 27, -12, -1, -2, 6, 4, -14, 19, -29, 42, -40, + 22, -6, -3, 14, -16, 4, 8, -9, 13, -22, 17, 5, -24, 37, -34, 20, + -4, -11, 19, -20, 21, -16, 1, 17, -17, 5, -9, 25, -31, 31, -40, 32, + -11, -7, 4, -4, 13, -23, 29, -40, 51, -49, 20, 3, -20, 38, -47, 34, + -21, 14, -9, 4, -13, 20, -29, 37, -57, 59, -48, 23, -5, -7, 5, -6, + -5, 13, -17, 9, -4, -12, 22, -19, -8, 10, -5, -7, 8, -18, 19, -13, + 5, -12, 6, -10, 18, -40, 66, -91, 82, -56, 17, 19, -51, 56, -45, 30, + -19, 5, -6, 7, -9, -4, -2, -5, 13, -19, 1, 20, -28, 13, -6, 0, + -17, 33, -48, 38, -16, -20, 53, -75, 75, -61, 30, -12, -9, 2, 5, -9, + -7, 15, -17, 9, 4, -46, 70, -85, 86, -67, 29, 18, -60, 76, -70, 29, + -8, -1, 1, 14, -58, 93, -118, 127, -125, 85, -36, -2, 17, -39, 46, -61, + 70, -99, 122, -120, 56, 15, -85, 116, -101, 30, 43, -108, 127, -122, 72, -38, + -3, 20, -31, 29, -37, 42, -50, 63, -72, 40, -7, -46, 66, -82, 53, -25, + 1, 1, -1, -3, 3, -24, 24, -34, 27, -24, 36, -49, 37, -38, 35, -42, + 13, -4, -14, 14, -29, 42, -58, 58, -60, 41, -39, 27, -35, 27, -32, 25, + -37, 43, -50, 32, -20, -4, 4, -14, 16, -43, 66, -93, 79, -58, 27, -11, + -21, 34, -40, 24, -7, -25, 31, -29, 19, -18, -2, 1, -6, 4, -31, 47, + -63, 62, -64, 32, 2, -29, 23, -21, 19, -41, 59, -76, 62, -52, 26, -11, + -1, -10, 6, -10, -7, 17, -42, 34, -12, -34, 73, -106, 92, -61, 26, -24, + 8, -7, -2, 3, -24, 31, -44, 27, -9, -22, 38, -43, 15, -4, -3, -2, + -12, 5, 1, -7, 7, -25, 17, -17, 4, -15, 27, -40, 34, -18, 6, -13, + 12, -3, -9, -6, 8, -18, 18, -36, 54, -55, 30, -25, 26, -41, 38, -49, + 48, -38, 8, 16, -40, 47, -52, 34, -12, -4, 2, -13, -1, -2, -1, -4, + -3, -25, -41, 8, 16, 27, 2, 16, 1, 13, 21, -8, -6, -29, 17, 8, + 8, 20, -13, 5, 4, 25, 17, 30, 22, 14, 15, 19, 7, 51, -16, -15, + -32, -13, 12, -8, -17, -49, -27, -29, -29, -52, -66, -55, -32, -20, -41, -21, + -36, -11, -16, 22, 3, 19, 0, -6, -10, 0, -38, -17, -35, -19, -27, 0, + -35, -27, -9, -17, -14, -2, 20, 50, 63, 57, 49, 70, 70, 97, 81, 68, + 52, 78, 93, 98, 102, 56, 34, 20, 53, 60, 45, 24, -18, 21, -10, 0, + -38, -79, -38, -37, -13, -27, -41, -50, -51, 14, 10, 16, -21, -13, -22, -20, + -48, -53, -55, -66, -76, -65, -91, -105, -92, -87, -101, -79, -56, -34, -7, -4, + 7, 20, 15, 26, 29, 32, -8, 36, 47, 50, 66, 29, 18, -33, -11, -4, + -10, -24, -42, -31, -22, 2, -23, -75, -34, -36, 5, 1, 1, -17, -47, 20, + 43, 68, 28, 30, 9, 29, 7, -9, -5, -32, -46, -36, -15, -40, -35, -15, + -26, -21, 2, 21, 49, 62, 83, 87, 106, 77, 97, 94, 67, 60, 85, 79, + 110, 80, 61, 1, 8, 16, 50, 36, 2, -22, 4, -2, 21, -35, -33, -19, + 4, 24, 19, 10, -58, -23, 18, 45, 34, 8, -12, -6, -5, -48, -51, -75, + -72, -77, -37, -65, -80, -57, -66, -68, -38, -38, 2, 10, 38, 31, 58, 22, + 39, 37, 27, -9, 23, 9, 35, 18, 15, -31, -50, -44, -5, 6, -10, -63, + -41, -56, -15, -41, -71, -45, -37, 7, -6, 5, -56, -71, -6, 21, 41, 8, + -13, -14, -40, -30, -41, -40, -56, -31, -31, -9, -15, -5, 10, 42, 27, 73, + 82, 73, 73, 79, 70, 38, 28, 31, 23, 45, 42, 44, 30, -40, 8, 28, + 52, 30, -18, -29, -40, -14, -45, -50, -55, -68, -39, -6, -29, -45, -59, -32, + 4, 31, 23, 16, 20, 11, -1, 1, -28, -45, -53, -56, -67, -60, -55, -40, + -31, -25, -16, 11, 20, 36, 67, 70, 75, 77, 81, 65, 46, 38, 34, 39, + 51, 44, 57, 7, -4, 13, 37, 46, 19, -8, -29, -1, -9, -21, -32, -43, + -55, -58, -40, -8, 15, 29, 38, 44, 59, 63, 51, 20, -20, -47, -61, -58, + -48, -42, -43, -35, -15, 15, 41, 55, 61, 62, 70, 67, 45, 11, -31, -62, + -80, -78, -71, -62, -54, -39, -15, 18, 50, 68, 79, 83, 92, 88, 57, 16, + -31, -71, -94, -95, -90, -83, -71, -55, -28, 7, 49, 77, 93, 100, 109, 107, + 78, 36, -20, -71, -99, -104, -100, -92, -83, -69, -43, -5, 42, 79, 100, 108, + 114, 112, 90, 51, -9, -65, -100, -110, -105, -95, -87, -76, -52, -11, 35, 75, + 100, 107, 111, 106, 90, 52, -4, -60, -97, -109, -99, -87, -80, -65, -35, 5, + 43, 75, 91, 95, 93, 87, 71, 31, -19, -64, -93, -99, -88, -76, -66, -44, + -9, 28, 59, 79, 84, 80, 71, 59, 35, -5, -45, -76, -96, -95, -77, -59, + -39, -9, 28, 61, 86, 98, 93, 74, 52, 28, -6, -43, -72, -94, -108, -99, + -77, -52, -20, 19, 56, 84, 106, 115, 106, 79, 45, 3, -40, -74, -93, -108, + -112, -100, -79, -46, -1, 45, 78, 100, 113, 118, 108, 81, 39, -19, -67, -93, + -103, -108, -104, -94, -74, -32, 19, 61, 88, 102, 108, 109, 100, 73, 21, -44, + -87, -102, -104, -97, -90, -78, -49, 0, 46, 78, 90, 92, 89, 87, 77, 43, + -15, -72, -101, -104, -93, -79, -69, -47, -3, 47, 84, 96, 89, 74, 65, 58, + 37, -7, -61, -99, -110, -101, -82, -62, -38, 2, 49, 92, 112, 106, 82, 59, + 41, 18, -19, -61, -95, -111, -110, -98, -74, -39, 6, 54, 99, 122, 123, 104, + 79, 50, 12, -32, -72, -100, -111, -110, -106, -90, -54, -4, 49, 99, 123, 126, + 113, 95, 69, 24, -27, -72, -102, -114, -109, -104, -94, -64, -16, 36, 87, 116, + 121, 111, 97, 76, 36, -15, -61, -94, -110, -108, -98, -86, -60, -19, 29, 77, + 104, 109, 99, 86, 67, 35, -7, -47, -82, -98, -101, -92, -77, -48, -14, 25, + 67, 92, 95, 83, 66, 45, 18, -9, -37, -62, -77, -81, -78, -54, -16, 0, + 0, 0, 12, -10, 16, -14, -18, 17, -31, -2, 3, -19, -8, 17, 28, 37, + 31, -1, -25, -16, -47, -13, -43, -22, 6, 34, 41, 49, 41, 27, 6, -33, + -62, -54, -59, -32, -13, 29, 53, 73, 60, 54, 16, -19, -58, -77, -89, -42, + -46, 17, 55, 78, 86, 81, 33, -3, -35, -84, -110, -75, -70, 0, 39, 78, + 92, 105, 70, 13, -15, -82, -107, -103, -84, -41, 20, 81, 85, 127, 86, 39, + -4, -63, -103, -99, -107, -69, 2, 68, 82, 127, 84, 58, 28, -44, -88, -104, + -108, -83, -13, 29, 69, 116, 87, 77, 40, -16, -65, -89, -104, -89, -40, -1, + 47, 96, 90, 85, 52, 9, -38, -62, -96, -95, -62, -22, 21, 73, 78, 86, + 65, 35, -15, -41, -80, -92, -69, -48, 1, 43, 65, 80, 73, 49, 8, -23, + -59, -75, -74, -60, -22, 17, 49, 69, 65, 60, 25, -1, -36, -59, -70, -61, + -40, -9, 30, 52, 57, 63, 37, 17, -12, -41, -61, -57, -50, -30, 9, 30, + 49, 60, 47, 28, 6, -20, -49, -51, -53, -42, -11, 13, 34, 53, 50, 34, + 18, -3, -35, -39, -52, -49, -23, 0, 18, 41, 47, 36, 31, 10, -21, -28, + -43, -49, -31, -13, 2, 28, 39, 35, 38, 19, -7, -18, -33, -42, -36, -26, + -12, 19, 30, 34, 36, 22, 6, -5, -25, -38, -36, -29, -17, 8, 19, 26, + 35, 28, 12, 3, -17, -30, -29, -29, -22, -3, 9, 19, 33, 26, 14, 8, + -9, -18, -22, -28, -25, -9, 3, 15, 22, 20, 18, 12, 1, -11, -22, -24, + -21, -13, -3, 8, 11, 20, 21, 12, 5, -6, -19, -16, -17, -17, -7, 3, + 8, 20, 17, 7, 7, -2, -11, -13, -16, -17, -5, 2, 5, 12, 13, 8, + 6, 3, -9, -11, -9, -14, -5, 1, -3, 6, 11, 6, 7, 2, -6, -4, + -4, -10, -6, -3, -4, 5, 8, 2, 5, 4, -2, 0, -3, -9, -4, -3, + -3, 2, 3, 0, 6, 4, 0, -1, -2, -2, 0, 0, 0, 12, -10, 16, + -14, -18, 17, -31, -2, 3, -19, -8, 17, 28, 37, 31, -1, -25, -16, -47, + -13, -43, -22, 6, 34, 41, 49, 41, 27, 6, -33, -62, -54, -59, -32, -13, + 29, 53, 73, 60, 54, 16, -19, -58, -77, -89, -42, -46, 17, 55, 78, 86, + 81, 33, -3, -35, -84, -110, -75, -70, 0, 39, 78, 92, 105, 70, 13, -15, + -82, -107, -103, -84, -41, 20, 81, 85, 127, 86, 39, -4, -63, -103, -99, -107, + -69, 2, 68, 82, 127, 84, 58, 28, -44, -88, -104, -108, -83, -13, 29, 69, + 116, 87, 77, 40, -16, -65, -89, -104, -89, -40, -1, 47, 96, 90, 85, 52, + 9, -38, -62, -96, -95, -62, -22, 21, 73, 78, 86, 65, 35, -15, -41, -80, + -92, -69, -48, 1, 43, 65, 80, 73, 49, 8, -23, -59, -75, -74, -60, -22, + 17, 49, 69, 65, 60, 25, -1, -36, -59, -70, -61, -40, -9, 30, 52, 57, + 63, 37, 17, -12, -41, -61, -57, -50, -30, 9, 30, 49, 60, 47, 28, 6, + -20, -49, -51, -53, -42, -11, 13, 34, 53, 50, 34, 18, -3, -35, -39, -52, + -49, -23, 0, 18, 41, 47, 36, 31, 10, -21, -28, -43, -49, -31, -13, 2, + 28, 39, 35, 38, 19, -7, -18, -33, -42, -36, -26, -12, 19, 30, 34, 36, + 22, 6, -5, -25, -38, -36, -29, -17, 8, 19, 26, 35, 28, 12, 3, -17, + -30, -29, -29, -22, -3, 9, 19, 33, 26, 14, 8, -9, -18, -22, -28, -25, + -9, 3, 15, 22, 20, 18, 12, 1, -11, -22, -24, -21, -13, -3, 8, 11, + 20, 21, 12, 5, -6, -19, -16, -17, -17, -7, 3, 8, 20, 17, 7, 7, + -2, -11, -13, -16, -17, -5, 2, 5, 12, 13, 8, 6, 3, -9, -11, -9, + -14, -5, 1, -3, 6, 11, 6, 7, 2, -6, -4, -4, -10, -6, -3, -4, + 5, 8, 2, 5, 4, -2, 0, -3, -9, -4, -3, -3, 2, 3, 0, 6, + 4, 0, -1, -2, -2, 0, -1, -1, -3, -7, -14, -23, -32, -45, -55, -66, + -74, -83, -88, -80, -77, -71, -64, -54, -46, -37, -31, -25, -19, -12, -6, -1, + 4, 8, 12, 17, 21, 23, 25, 25, 27, 29, 32, 35, 36, 34, 32, 31, + 32, 35, 37, 37, 35, 31, 29, 29, 31, 33, 34, 32, 29, 26, 25, 27, + 30, 32, 31, 29, 27, 27, 29, 31, 34, 35, 35, 35, 36, 38, 41, 43, + 45, 47, 49, 52, 55, 57, 59, 61, 63, 66, 69, 70, 70, 68, 66, 63, + 61, 58, 54, 47, 36, 24, 11, 1, -9, -20, -33, -48, -64, -78, -89, -97, + -103, -110, -116, -123, -128, -128, -126, -121, -116, -112, -107, -102, -95, -88, -78, -69, + -61, -54, -47, -41, -34, -27, -21, -16, -12, -7, -2, 2, 5, 6, 8, 10, + 13, 16, 19, 19, 19, 17, 18, 19, 22, 24, 24, 22, 19, 18, 19, 21, + 23, 24, 22, 19, 17, 18, 20, 22, 24, 24, 22, 21, 22, 24, 27, 29, + 30, 30, 31, 32, 35, 37, 40, 42, 45, 47, 50, 53, 56, 58, 60, 62, + 66, 68, 70, 69, 68, 65, 63, 61, 59, 54, 46, 36, 24, 13, -1, -14, + -28, -43, -57, -68, -78, -86, -94, -102, -109, -114, -117, -117, -115, -112, -109, -106, + -101, -96, -89, -81, -73, -67, -59, -53, -46, -40, -34, -28, -23, -18, -13, -9, + -5, -2, 0, 2, 5, 7, 10, 12, 14, 15, 15, 15, 16, 18, 19, 20, + 20, 19, 18, 18, 19, 21, 22, 22, 21, 20, 19, 21, 23, 24, 25, 25, + 25, 25, 26, 29, 31, 33, 34, 35, 36, 38, 40, 43, 46, 48, 51, 53, + 56, 59, 62, 65, 68, 71, 74, 77, 78, 79, 78, 77, 76, 74, 71, 66, + 58, 49, 39, 28, 17, 6, -6, -20, -35, -50, -64, -75, -85, -94, -102, -110, + -117, -122, -124, -123, -121, -118, -114, -110, -106, -99, -92, -84, -76, -69, -61, -55, + -48, -41, -34, -29, -23, -18, -13, -9, -5, -2, 0, -1, -1, 0, 2, 0, + 3, 2, 2, 4, 5, 4, 4, 4, 4, 5, 3, 4, 3, 1, 2, 0, + 0, -1, -3, -4, -2, -3, -5, -3, -4, -5, -5, -4, -3, -3, -6, -5, + -4, -2, -5, -5, -2, -3, -3, -3, 1, 4, 4, 8, 8, 8, 13, 12, + 13, 14, 12, 9, 8, 6, 6, 3, -2, -2, -5, -5, -4, -5, -11, -16, + -12, -7, -3, -5, -10, -11, -6, -2, -2, -1, -4, -6, -6, -7, -8, -5, + -2, 2, 5, 6, 8, 8, 9, 13, 16, 16, 14, 11, 7, 5, 4, 2, + 0, -2, -3, -3, 0, -3, -13, -28, -11, 7, -1, -15, -1, -5, -18, -10, + 6, 11, -11, -1, -10, -14, -13, -13, -4, 4, 6, 14, 13, 10, 10, 15, + 17, 24, 24, 13, 12, 10, 1, 0, 2, -4, 0, -6, 2, 7, -22, -68, + 2, 35, -40, 14, -24, -3, -10, -9, -20, -3, 28, 2, -9, -12, -28, -19, + -4, -1, 15, 17, 17, 16, 12, 16, 22, 25, 28, 6, 17, 9, -1, -2, + -3, 2, 12, -6, 6, -5, -35, -89, 32, 28, -39, 20, -36, 9, -20, -9, + -34, 3, 34, 8, -16, -11, -37, -15, -3, 0, 26, 18, 13, 15, 13, 25, + 27, 29, 20, 3, 21, 2, -2, 0, -8, 11, 16, -1, 8, -21, -76, -81, + 87, -25, 4, -4, -23, 6, -26, -20, -35, 23, 28, 0, -18, -16, -43, 2, + -9, 17, 25, 15, 9, 18, 17, 37, 28, 35, 3, 14, 12, -5, -1, -1, + -5, 27, 0, 16, -11, -49, -128, 36, 40, -36, 35, -41, 21, -27, -14, -45, + 4, 24, 20, -23, -6, -41, -9, -1, 6, 23, 19, 5, 15, 14, 33, 35, + 40, 16, 5, 16, -3, -5, 4, -12, 24, 10, 18, 1, -38, -128, -21, 72, + -50, 42, -38, 19, -16, -16, -43, -10, 21, 24, -22, -11, -30, -15, 6, 4, + 22, 18, 6, 11, 13, 27, 39, 42, 22, 4, -3, -2, -2, -5, -3, -5, + -3, -2, -6, -5, -5, -6, -5, -3, -5, -3, -5, -4, -6, -3, -1, -2, + -1, 0, -2, 1, 2, 1, 4, 4, 5, 5, 5, 8, 10, 11, 9, 10, + 11, 8, 5, 10, 7, 5, 5, 0, -3, 1, 0, -5, -2, -8, -9, -7, + -7, -5, -9, -11, -9, -8, -8, -7, -9, -7, -6, -7, -5, -6, -5, -3, + -3, -3, -4, -4, -2, 0, 1, 2, 5, 9, 12, 16, 19, 22, 22, 24, + 22, 22, 19, 13, 11, 7, 7, 4, -2, -7, -9, -9, -8, -10, -14, -14, + -15, -15, -13, -14, -17, -18, -14, -12, -12, -8, -9, -7, -6, -6, -6, -8, + -9, -9, -11, -13, -11, -6, -1, 3, 9, 20, 27, 33, 37, 46, 46, 42, + 37, 28, 21, 14, 11, 10, 14, 20, -2, -40, -47, -22, -5, -4, -1, 4, + -15, -53, -56, -7, -33, -14, -2, -19, -7, -8, -15, -6, -9, -8, -3, -9, + -15, -18, -26, -19, -6, -5, -6, 0, 12, 22, 29, 30, 28, 32, 29, 21, + 15, 13, 5, 5, 3, 19, 30, 3, -68, -26, 2, -17, 17, -12, 15, -1, + -12, -48, -43, -19, -1, 3, 6, -8, -4, -10, -10, -4, 0, -6, -1, -7, + -9, -17, -12, -6, -9, -14, -5, 14, 33, 33, 41, 32, 41, 35, 20, 10, + 8, 4, 10, -2, 36, 40, 3, -110, -8, -7, -6, 16, -18, 27, -2, -4, + -56, -57, -33, 16, -2, 12, -11, -5, -17, -9, -5, 10, -6, 0, -12, -11, + -20, -10, -8, -12, -17, -3, 17, 38, 34, 45, 36, 51, 37, 18, 4, -3, + 3, 8, 8, 54, 48, -34, -128, 28, -33, 28, -13, 1, 21, 3, -20, -59, + -65, -10, 17, -1, 7, -17, -10, -19, -8, 5, 11, -4, -2, -16, -17, -20, + -9, -11, -18, -11, 3, 31, 36, 41, 41, 44, 53, 30, 10, 1, -13, 12, + -5, 42, 63, 43, -127, -55, 19, -27, 28, -1, 0, 3, 5, 8, 12, 14, + 15, 15, 14, 12, 8, 5, 1, -3, -9, -14, -17, -19, -18, -16, -12, -8, + -5, -4, -2, -1, -1, -2, -3, -4, -3, -2, -1, -1, 0, 0, 0, 2, + 8, 12, 16, 19, 23, 26, 34, 40, 39, 28, 11, -8, -26, -36, -40, -39, + -35, -27, -19, -10, -5, -6, -10, -12, -15, -14, -12, -9, -5, -3, -1, 1, + 6, 8, 7, 7, 7, 8, 13, 20, 28, 35, 43, 48, 55, 57, 51, 32, + 3, -29, -56, -68, -67, -60, -46, -31, -17, -7, -4, -7, -11, -15, -16, -15, + -10, -5, -1, 1, 3, 5, 7, 9, 11, 12, 12, 10, 13, 19, 26, 36, + 43, 51, 58, 65, 61, 40, 6, -30, -60, -75, -73, -64, -49, -32, -16, -5, + -1, -4, -11, -18, -23, -23, -19, -12, -5, 2, 8, 12, 13, 11, 9, 8, + 8, 10, 15, 21, 27, 32, 37, 42, 49, 55, 63, 55, 32, -3, -39, -66, + -79, -73, -56, -39, -24, -12, -7, -7, -12, -19, -24, -24, -21, -14, -6, 3, + 8, 11, 12, 11, 10, 10, 10, 11, 14, 17, 21, 27, 33, 41, 49, 56, + 63, 66, 49, 15, -27, -61, -82, -85, -73, -52, -33, -18, -9, -5, -7, -12, + -18, -21, -20, -15, -9, -1, 4, 8, 12, 15, 15, 14, 11, 8, 7, 10, + 15, 22, 32, 45, 59, 72, 86, 95, 75, 22, -40, -93, -119, -120, -97, -64, + -32, -9, 5, 9, 5, -3, -14, -21, -23, -20, -13, -5, 4, 12, 17, 18, + 15, 10, 7, 4, 3, 6, 9, 15, 21, 30, 40, 56, 77, 99, 99, 54, + -19, -86, -123, -127, -103, -66, -27, 1, 16, 18, 11, -1, -12, -21, -23, -21, + -16, -8, 1, 9, 16, 19, 16, 11, 8, 5, 5, 7, 9, 14, 19, 27, + 35, 49, 68, 90, 101, 73, 6, -66, -114, -128, -113, -78, -39, -6, 13, 19, + 11, -1, 0, 10, 30, 35, 40, 39, 37, 28, 18, 6, -9, -20, -30, -35, + -33, -30, -28, -23, -24, -23, -19, -20, -15, -11, -8, -3, 0, 1, 0, -2, + -4, -1, 0, 10, 15, 21, 27, 25, 25, 22, 13, 10, -5, -9, -15, -19, + -17, -17, -12, -7, 0, 4, 10, 8, 5, -5, -13, -23, -31, -30, -24, -13, + 11, 36, 62, 81, 83, 78, 54, 35, 19, -11, -29, -49, -57, -47, -35, -20, + -19, -26, -27, -33, -30, -26, -22, -11, -8, 3, 11, 6, 0, -16, -23, -23, + -11, 9, 23, 35, 45, 51, 46, 49, 26, 12, -13, -26, -37, -45, -31, -35, + -17, -4, 8, 23, 24, 23, 9, -10, -22, -37, -40, -38, -33, -12, 22, 67, + 100, 119, 111, 79, 50, 10, -12, -32, -52, -69, -62, -38, -14, -9, -21, -42, + -60, -50, -39, -19, -4, -1, 3, 15, 19, 2, -16, -43, -57, -48, -21, 19, + 38, 63, 66, 69, 74, 59, 39, 4, -33, -52, -67, -58, -39, -25, 2, 10, + 32, 35, 36, 18, -7, -25, -37, -31, -28, -23, -10, 11, 53, 101, 121, 123, + 92, 48, 11, -24, -42, -60, -66, -67, -48, -20, 2, -16, -41, -67, -87, -62, + -44, -10, 8, 19, 30, 34, 35, 4, -36, -66, -78, -75, -27, 22, 49, 83, + 91, 97, 90, 69, 39, -18, -61, -104, -98, -75, -32, 19, 47, 68, 70, 56, + 16, -33, -77, -89, -76, -47, 7, 35, 64, 100, 123, 125, 107, 60, 5, -39, + -76, -94, -101, -93, -69, -36, -3, 17, 10, -15, -56, -80, -86, -69, -40, -7, + 25, 49, 66, 72, 54, 19, -19, -55, -77, -67, -40, 4, 45, 76, 96, 100, + 92, 67, 32, -11, -56, -88, -91, -73, -33, 9, 41, 61, 65, 52, 17, -28, + -67, -80, -68, -36, 6, 47, 82, 114, 126, 114, 74, 18, -32, -73, -93, -101, + -93, -70, -36, -3, 17, 10, -15, 0, -1, -2, -2, 0, 2, 3, 6, 7, + 6, 6, 3, 2, -1, -4, -8, -12, -14, -13, -13, -11, -5, -1, 5, 10, + 14, 17, 19, 18, 15, 12, 7, 3, 1, -2, -4, -4, -7, -11, -13, -16, + -16, -12, -9, -6, -3, -1, -1, -1, -4, -8, -11, -15, -16, -15, -10, -2, + 7, 18, 25, 28, 28, 24, 16, 10, 4, -2, -5, -5, -4, -4, -1, 0, + 0, 1, 1, 0, -1, -3, -6, -11, -11, -14, -16, -17, -19, -19, -16, -10, + -2, 8, 19, 27, 33, 35, 32, 26, 21, 14, 7, 0, -6, -11, -18, -25, + -31, -32, -27, -19, -9, 1, 10, 15, 14, 10, 0, -13, -28, -38, -42, -40, + -26, -4, 17, 40, 58, 66, 62, 51, 35, 17, 3, -8, -16, -18, -18, -15, + -13, -15, -17, -17, -15, -13, -11, -12, -3, -2, 1, -3, -15, -28, -36, -42, + -40, -28, -11, 14, 45, 63, 70, 69, 56, 44, 36, 21, 3, -12, -18, -26, + -37, -47, -58, -55, -41, -20, 4, 22, 34, 43, 37, 22, -7, -43, -71, -88, + -86, -64, -31, 7, 56, 99, 115, 106, 85, 48, 17, 1, -14, -28, -33, -20, + -11, -12, -18, -37, -44, -41, -29, -23, -7, 15, 31, 40, 33, 8, -27, -56, + -73, -74, -63, -33, 4, 50, 93, 101, 91, 79, 56, 43, 24, 5, -17, -32, + -31, -43, -56, -63, -72, -57, -32, 3, 26, 46, 62, 63, 45, 9, -39, -85, + -112, -106, -84, -49, 6, 60, 104, 127, 115, 83, 46, 16, -1, -16, -21, -26, + -16, -2, -8, -25, -47, -67, -62, -49, -26, 2, 34, 60, 74, 65, 33, -21, + -71, -98, -92, -77, -36, 21, 69, 106, 112, 88, 58, 29, 9, -8, -18, -24, + -17, -4, -10, -26, -47, -67, -62, -49, -26, 2, 34, 60, 74, 65, 33, 17, + 16, -38, 9, 40, -58, 27, 43, -80, 52, -2, -54, 64, -27, -17, 32, 4, + -49, 53, -22, -47, 90, -73, 17, 42, -45, 8, 23, -41, -1, 58, -74, 40, + 25, -66, 56, -19, -45, 58, -9, -39, 45, 3, -48, 55, -41, -27, 78, -66, + 13, 40, -38, 0, 29, -51, 12, 57, -79, 38, 31, -64, 40, -4, -47, 63, + -16, -40, 55, -16, -32, 45, -31, -29, 76, -64, 0, 58, -49, 4, 31, -52, + 31, 5, -35, 45, -21, 4, -5, 3, -17, -7, 55, -72, 43, 35, -88, 80, + -57, 3, 45, -62, 53, -14, -2, -17, 46, -77, 42, 23, -61, 75, -54, 39, + -40, 31, -42, 25, 11, -48, 93, -97, 62, -27, -13, 7, 0, 30, -59, 82, + -74, 28, 10, -53, 65, -47, 46, -41, 40, -48, 7, 45, -95, 127, -99, 43, + -9, -25, 40, -58, 84, -84, 78, -66, 11, 50, -96, 111, -85, 51, -26, -14, + 36, -60, 91, -84, 58, -26, -22, 56, -87, 98, -71, 47, -25, -11, 44, -84, + 103, -92, 69, -32, -3, 25, -59, 87, -90, 70, -45, 17, 16, -57, 81, -73, + 50, -33, 14, 0, -35, 75, -84, 69, -42, 8, 11, -46, 74, -69, 57, -47, + 36, -26, -20, 69, -89, 83, -58, 37, -24, -7, 41, -58, 54, -53, 53, -42, + 14, 28, -54, 52, -55, 46, -41, 22, 30, -57, 58, -64, 56, -54, 26, 31, + -55, 63, -73, 66, -68, 49, -3, -38, 61, -71, 75, -87, 69, -15, -27, 37, + -55, 74, -84, 73, -34, -5, 26, -59, 74, -85, 84, -33, -12, 30, -57, 65, + -85, 86, -40, 9, 15, -50, 69, -94, 93, -53, 15, 11, -38, 58, -86, 96, + -64, 11, 21, -30, 17, -3, -3, 0, 0, -3, -4, -4, -3, -4, -4, -5, + -6, -6, -8, -5, -6, -3, 0, 2, 4, 7, 8, 12, 12, 14, 13, 13, + 12, 8, 7, 2, 2, -4, -6, -10, -11, -12, -12, -14, -10, -9, -3, -3, + 2, 3, 3, 2, 1, 1, -3, -3, -4, -3, -3, -3, -4, 0, -3, -3, + -3, 0, -3, 0, -3, 0, 1, 0, 0, 0, 0, 0, -3, 1, -3, 1, + -3, 2, 1, 0, 0, -3, -4, -5, -9, -10, -15, -16, -17, -17, -14, -10, + -3, 4, 9, 14, 19, 24, 25, 26, 28, 30, 34, 42, 31, 9, -31, -39, + -23, -15, -17, -23, -30, -23, -12, -10, 4, 9, 19, 13, 14, 6, 0, -9, + -11, -12, -9, -8, 0, 0, 2, 1, 1, -3, -3, -5, -3, -5, -3, -4, + 0, -3, -4, -4, -3, -5, -3, -5, -3, 0, 3, 2, 7, 7, 7, 3, + 0, -14, -17, -26, -26, -28, -21, -17, -11, -10, 2, 6, 19, 18, 32, 32, + 60, 69, 98, 60, 7, -58, -8, -8, -14, -39, -30, -14, -47, -21, -45, -3, + 7, 20, 14, 31, 12, 10, -15, -5, -23, -14, -15, -4, -8, 2, 1, 7, + -3, 2, -8, -4, -6, -6, -3, 0, -6, -6, -8, -10, -11, -12, -9, -9, + -4, -3, 0, 8, 10, 12, 15, 13, 4, -10, -15, -30, -32, -30, -23, -22, + -19, -14, -4, 3, 10, 14, 26, 40, 70, 102, 127, 62, -17, -39, 9, -25, + -9, -87, -12, -16, 0, -30, -27, -19, -9, 6, 18, 21, 19, 6, 0, -9, + -17, -14, -16, -8, -6, 0, 4, 4, -5, -4, -11, -3, -6, 2, 2, 0, + -6, 0, -2, -4, -8, -14, -21, -25, -28, -32, -36, -40, -44, -48, -51, -55, + -59, -63, -67, -71, -74, -78, -82, -86, -90, -94, -98, -101, -84, -60, -38, -15, + 8, 28, 27, 23, 19, 16, 11, 21, 46, 68, 93, 109, 106, 102, 98, 95, + 91, 87, 83, 79, 75, 71, 67, 64, 60, 56, 52, 49, 45, 41, 37, 33, + 30, 26, 22, 18, 15, 11, 7, 3, -1, -5, -9, -13, -17, -20, -24, -28, + -32, -35, -39, -43, -47, -51, -54, -58, -62, -66, -69, -73, -77, -81, -85, -89, + -93, -97, -100, -105, -95, -70, -48, -23, -7, -10, -14, -17, -22, -18, 4, 26, + 50, 72, 96, 107, 103, 100, 96, 92, 88, 84, 80, 76, 72, 68, 64, 61, + 57, 53, 49, 46, 42, 38, 34, 30, 26, 23, 19, 15, 11, 8, 4, 0, + -4, -8, -11, -15, -19, -23, -27, -30, -35, -38, -43, -46, -51, -54, -58, -61, + -66, -56, -31, -9, 16, 33, 30, 26, 22, 18, 15, 11, 7, 3, -1, -5, + -9, -13, -16, -20, -24, -28, -32, -36, -40, -43, -48, -51, -55, -59, -63, -50, + -26, -4, 20, 42, 64, 67, 62, 59, 55, 51, 47, 43, 39, 35, 31, 27, + 23, 20, 16, 12, 8, 4, 0, -4, -7, -11, -15, -19, -22, -27, -17, 8, + 30, 55, 72, 69, 65, 61, 57, 54, 50, 46, 42, 38, 34, 30, 26, 22, + 18, 15, 11, 7, 3, 0, -4, -8, -12, -15, -19, -23, -27, -31, -35, -38, + -42, -46, -50, -54, -57, -61, -65, -69, -73, -77, -81, -85, -89, -92, -96, -100, + -100, -79, -64, -47, -31, -15, 0, 0, -4, -3, -6, -8, 6, 10, -8, -13, + 22, 55, 15, -58, -102, -88, -25, 51, 77, 79, 82, 19, -45, -107, -128, -88, + 19, 81, 86, 71, 35, -16, -50, -73, -55, -27, -14, 7, 77, 89, 31, -22, + -27, -61, -86, -34, 40, 55, 67, 80, 57, -1, -48, -60, -41, -46, -31, 28, + 62, 47, 43, 33, -5, -34, -45, -52, -33, 26, 66, 70, 41, 17, -34, -79, + -93, -41, -6, 22, 53, 93, 62, 17, -20, -66, -118, -88, -4, 45, 60, 69, + 67, 2, -72, -109, -95, -78, -7, 67, 101, 78, 69, 19, -56, -110, -89, -64, + -19, 45, 100, 86, 36, -11, -65, -107, -108, -41, 24, 69, 93, 111, 56, -15, + -70, -81, -88, -38, 30, 88, 90, 83, 43, -24, -81, -82, -57, -24, 38, 100, + 115, 70, 26, -25, -75, -108, -66, -20, 29, 71, 105, 67, 7, -46, -67, -83, + -60, 0, 58, 82, 81, 57, -9, -72, -99, -78, -60, -8, 54, 95, 69, 44, + 0, -51, -92, -69, -26, 18, 53, 81, 63, 6, -44, -74, -88, -79, -19, 40, + 75, 75, 72, 18, -42, -80, -74, -69, -25, 32, 76, 66, 39, 5, -41, -82, + -76, -34, 3, 42, 79, 88, 38, -12, -49, -74, -92, -48, 8, 51, 70, 83, + 50, -7, -58, -68, -65, -43, 13, 70, 82, 62, 34, -17, -72, -94, -65, -28, + 17, 69, 101, 71, 25, -21, -60, -88, -66, -13, 37, 62, 82, 68, 11, -47, + -73, -79, -66, -15, 49, 82, 76, 57, 11, -51, -88, -78, -48, -9, 49, 0, + 0, 0, 0, 0, 0, -3, -5, -5, -7, -6, -2, 5, 16, 24, 21, 17, + 12, 3, -10, -31, -44, -47, -42, -28, -2, 26, 29, 36, 35, 1, -26, -39, + -52, -53, -38, -10, -32, -41, -7, 2, 22, 65, 89, 74, 15, -16, -24, 12, + 62, 39, 6, -12, -3, 47, 48, 21, 109, 127, 119, 53, -9, 19, 9, -50, + -55, -43, -71, -46, -5, -2, -20, -12, -9, 12, -27, -66, -50, -8, -19, -58, + -22, -8, -19, -34, -42, 10, 32, -4, 4, 46, 96, 34, -51, -10, -8, -93, + -70, -58, -46, -16, -32, -30, 6, 7, -41, -29, 3, 25, 73, 67, 45, 37, + 30, 83, 0, -31, -4, -50, -28, -41, -75, -110, -53, -13, -3, 22, 14, 14, + 13, 7, 9, 38, 47, 39, 17, -8, 90, 75, -5, -29, -46, -54, -102, -66, + -35, -27, -29, -21, 32, 5, 1, 1, -2, 16, 16, 19, 30, 50, 89, 41, + 6, 40, -10, -15, -41, -46, -43, -77, -100, -100, -48, -37, -26, -4, -9, 0, + 13, 36, 70, 75, 59, 34, 12, -13, -27, 37, 71, 48, 53, 37, 7, 8, + 34, 48, 40, 31, 25, 2, -20, -15, -5, 12, -11, -49, -20, 15, -13, -42, + -29, 16, -6, -58, -28, 17, 12, -20, -11, 16, -3, -37, -14, 3, -32, -10, + 40, 54, 53, 27, -3, -5, -34, -47, -49, -90, -68, -36, -32, -31, -16, 26, + 3, 0, -2, -2, 15, 16, 19, 30, 51, 88, 40, 6, 39, -10, 3, -2, + 11, -7, 23, 19, 74, 39, 32, -13, -21, -7, -39, -44, -128, -58, -21, 52, + -86, -74, -94, 75, 61, 72, -38, 13, 59, 116, 71, -9, -33, -12, 68, -2, + -35, -128, -42, -43, 39, -78, -57, -81, 56, 59, 63, -13, 7, 69, 98, 87, + -13, -9, -24, 70, -11, -23, -128, -42, -48, 28, -68, -61, -69, 34, 64, 46, + 8, -5, 79, 82, 100, -17, 5, -29, 69, -13, -21, -122, -49, -43, 11, -55, + -72, -54, 13, 73, 30, 23, -16, 87, 72, 107, -17, 10, -26, 64, -6, -26, + -109, -61, -31, -6, -40, -86, -41, -4, 80, 17, 31, -22, 88, 70, 106, -10, + 6, -16, 53, 7, -37, -93, -76, -17, -21, -28, -99, -33, -15, 83, 12, 31, + -21, 83, 76, 98, 2, -4, -1, 41, 24, -49, -77, -89, -6, -31, -20, -106, + -32, -19, 79, 14, 23, -15, 71, 87, 87, 17, -16, 13, 30, 39, -57, -67, + -97, -1, -34, -19, -106, -38, -16, 69, 23, 11, -5, 56, 100, 75, 32, -28, + 25, 22, 50, -59, -62, -98, -2, -30, -24, -100, -52, -9, 55, 36, -4, 5, + 41, 112, 67, 43, -34, 30, 21, 55, -53, -65, -93, -11, -18, -34, -88, -69, + 0, 41, 48, -17, 12, 29, 118, 65, 49, -34, 28, 27, 53, -42, -72, -83, + -23, -6, -44, -77, -85, 5, -69, 1, -12, -29, -28, -13, 1, 9, -4, -27, + -18, -5, 11, 65, 87, 54, 59, 66, 30, 12, 8, -6, -7, 4, -7, -39, + -59, -63, -48, -23, -13, -6, 22, 61, 68, 15, -59, -87, -41, 3, 5, -10, + -17, -17, -20, -23, -20, -28, -17, -3, -10, -29, 23, 11, 25, 52, 56, 62, + 80, 54, 22, -15, -31, -38, -5, 11, -9, -7, -36, -44, -6, 52, 127, 26, + -68, -125, -105, 22, 15, -27, -27, 13, 25, 69, 28, -42, -77, -57, -70, 15, + 44, 14, 26, 57, 69, 43, 33, 41, 33, 32, 25, -50, -98, -100, -38, 24, + 7, -35, -38, -2, 76, 64, 15, -79, -93, -50, -12, 27, 45, 32, -4, 23, + 6, -36, -47, -33, -52, -15, 37, 78, 49, 40, 17, 14, 14, 70, 81, 60, + -3, -4, -12, -42, -50, -28, -20, 5, 9, 27, 46, -13, -69, -99, -88, -47, + 5, -4, -10, 17, 39, -12, -8, -21, -16, 22, 9, -9, 1, 15, 15, 33, + 29, 17, 11, 38, 72, 29, -8, -36, -27, -42, 17, -40, 25, 25, 8, -3, + 14, 15, 2, 43, 33, -2, -19, -24, -8, 2, -69, -114, -94, -77, -87, 22, + 27, 19, 24, 57, 121, 94, 40, -27, -29, 4, 28, -12, 5, -21, -28, -18, + 0, -9, 1, 36, 22, 7, 6, 12, 7, 8, 55, 6, -2, -7, -13, -12, + -12, -8, -5, -5, -1, -4, -4, -3, -1, 5, 11, 15, 18, 16, 11, 5, + -5, -12, -16, -17, -14, -10, -7, -3, -2, -3, -3, -5, -3, 2, 9, 18, + 22, 23, 18, 11, -2, -14, -20, -22, -18, -12, -8, -5, -3, -5, -6, -6, + -5, 1, 11, 22, 30, 31, 24, 15, -1, -12, -20, -23, -19, -13, -8, -3, + -3, -2, -6, -8, -9, -5, 6, 21, 32, 35, 29, 19, 1, -15, -27, -29, + -25, -15, -9, -4, -1, -2, -7, -14, -15, -10, 4, 24, 42, 48, 43, 26, + 4, -20, -36, -38, -30, -17, -7, -3, 0, -1, -4, -16, -24, -19, -3, 26, + 49, 61, 60, 40, 9, -23, -45, -52, -39, -22, -5, -2, 1, 3, -2, -18, + -32, -30, -10, 22, 55, 77, 78, 52, 15, -22, -51, -66, -52, -29, -5, 0, + 2, 9, 6, -15, -37, -42, -22, 10, 55, 89, 99, 71, 22, -20, -58, -79, + -68, -35, -8, 6, 1, 12, 13, -9, -37, -50, -35, 0, 46, 93, 116, 90, + 33, -15, -60, -89, -84, -44, -9, 10, 3, 13, 19, -3, -35, -53, -43, -12, + 34, 91, 127, 109, 46, -9, -57, -95, -96, -57, -13, 11, 7, 10, 25, 2, + -2, -35, 0, 2, 7, 12, -7, -79, -68, 2, -6, -5, 19, 40, 33, 55, + 56, 17, 32, 32, 2, -20, 5, 51, 27, -21, -13, -11, -17, -20, -6, -63, + -125, -116, -86, -59, -34, 11, 23, 20, 39, 66, 50, 47, 54, 46, 11, -4, + 44, 67, 30, 11, 16, 6, -2, 7, -4, -77, -114, -107, -70, -50, -20, 29, + 26, 12, 48, 69, 44, 47, 49, 28, -8, 9, 53, 49, 15, 9, 8, -3, + -11, 7, -33, -107, -123, -101, -62, -49, -5, 25, 6, 13, 55, 49, 32, 40, + 39, 7, -17, 18, 49, 32, 7, 8, 1, -12, -3, 7, -62, -113, -109, -74, + -50, -31, 23, 32, 13, 40, 69, 48, 46, 54, 42, 2, 1, 42, 52, 25, + 10, 11, 0, -11, 10, -10, -90, -115, -101, -64, -52, -15, 29, 16, 10, 51, + 59, 41, 46, 49, 25, -9, 15, 48, 42, 15, 10, 7, -9, -7, 16, -43, + -107, -113, -89, -60, -47, 4, 27, 4, 19, 58, 47, 38, 46, 43, 6, -9, + 28, 47, 29, 10, 11, 2, -14, 5, 5, -73, -111, -106, -73, -56, -29, 24, + 22, 6, 40, 61, 43, 43, 52, 37, -3, 6, 41, 47, 23, 12, 11, 0, + -14, 1, 3, 5, 5, 6, 8, 6, 4, 0, -4, -5, -6, -9, -9, -11, + -11, -12, -13, -13, -13, -12, -11, -9, -5, -2, -1, 1, 4, 6, 9, 11, + 12, 12, 11, 8, 5, 2, -2, -2, -2, -2, 0, -1, -1, -2, -5, -5, + -5, -1, 4, 10, 17, 20, 22, 19, 15, 7, -1, -9, -15, -19, -21, -21, + -18, -16, -13, -11, -12, -15, -19, -23, -24, -20, -13, -3, 9, 20, 34, 44, + 50, 46, 35, 21, 7, -4, -14, -20, -19, -13, -8, 2, 0, -5, -15, -28, + -32, -29, -14, 0, 11, 27, 42, 58, 59, 45, 22, 4, -15, -26, -37, -43, + -42, -37, -17, 1, 18, 23, 8, -5, -29, -47, -47, -43, -25, -5, 20, 52, + 80, 92, 76, 43, 9, -20, -35, -38, -46, -41, -29, -12, 19, 35, 22, 4, + -34, -53, -58, -40, -26, -16, 14, 47, 88, 108, 90, 50, 16, -9, -36, -51, + -64, -64, -52, -33, -1, 32, 40, 24, 3, -29, -62, -58, -65, -52, -18, 23, + 68, 114, 127, 95, 41, 1, -36, -54, -56, -68, -55, -35, -17, 19, 42, 29, + 13, -16, -46, -60, -54, -56, -47, -11, 29, 72, 116, 127, 94, 41, -3, 0, + 16, 39, 54, 46, 18, 7, -15, -36, -9, -6, -16, -5, -15, -30, -23, -35, + -20, 22, 3, -19, -20, -13, -9, 19, 23, 10, 12, 35, 66, 54, 4, -43, + -58, -15, -10, 16, 55, 18, -39, -38, -30, 2, 9, 27, 51, -32, -60, -72, + -4, 32, 71, 19, -8, 56, -2, -42, 10, 21, -6, 31, -9, -70, 8, -6, + -19, -93, -20, -5, -31, 10, 5, 56, 24, -45, 11, 66, 48, 61, 89, 49, + -57, -6, -20, -69, -104, -83, -50, 32, 10, -16, -87, -78, 30, 127, 63, -17, + -91, -2, -12, 45, 83, 30, 56, 54, 42, 7, 79, -26, -52, -64, -97, 12, + -3, -107, -99, -39, 34, 86, 19, -25, 25, 90, -8, -38, 65, 36, 10, 30, + 36, 19, -6, 38, -47, -101, -52, -45, 30, -9, -106, 18, -10, -37, 16, 100, + -94, -111, -25, -35, -12, -8, -9, 51, 24, -5, -70, -52, -52, -19, -11, 48, + 93, 61, 17, 113, 125, 73, -16, -30, -57, -78, -116, -55, -38, -10, -5, -4, + 38, 31, -3, -46, -46, -50, -20, -10, 52, 84, 48, 14, 115, 119, 64, -16, + -1, 4, 0, -9, -11, -1, 6, 2, -2, 4, -6, -10, -2, 11, 14, 3, + -10, -15, -1, 17, 4, 6, 4, -12, -18, 6, 10, 4, 6, -8, -36, 2, + 3, 3, 5, 15, -20, -17, 9, 8, 11, 17, -8, -26, 18, 2, 5, 5, + 13, -24, -8, -2, 2, 5, 7, -21, -18, 13, 5, -5, 17, 7, -14, -13, + -12, 0, 14, 3, -12, -26, 13, 3, 10, 18, 12, -15, -14, -1, 3, 19, + 0, -10, -29, 11, 4, 17, 15, 12, -24, -20, 6, 9, 22, -3, -13, -15, + 9, 1, 7, 6, 18, -19, -26, -18, 2, 22, 0, -25, -20, 15, 8, -4, + 8, 31, -12, -20, -15, 9, 33, 9, -29, -2, 27, 7, -11, 8, 20, -20, + -41, -10, 15, 35, 15, -21, 11, 49, 6, -6, 4, 3, -48, -76, -35, 14, + 37, 22, -24, 29, 68, 20, 3, 7, -5, -68, -90, -59, 19, 36, 28, -13, + 59, 93, 30, 2, 18, -25, -88, -105, -81, 13, 26, 30, -4, 88, 109, 33, + 0, 22, -30, -88, -112, -76, 17, 31, 18, 5, 94, 114, 30, -4, 0, 4, + -30, -1, 0, -2, -2, -2, -1, 4, 11, 18, 30, 7, -64, -60, -30, -7, + 0, 2, 22, 67, 117, 23, -128, -74, -30, -5, -2, 1, 19, 62, 116, 38, + -123, -82, -31, -8, -1, -1, 16, 57, 114, 52, -117, -88, -33, -10, -2, -3, + 14, 52, 112, 64, -108, -96, -35, -13, -2, -4, 12, 49, 108, 77, -99, -102, + -37, -15, -2, -5, 10, 43, 104, 86, -87, -109, -40, -18, -2, -6, 8, 40, + 100, 95, -73, -115, -42, -21, -2, -8, 7, 35, 95, 102, -59, -120, -45, -24, + -2, -8, 5, 32, 90, 109, -44, -124, -49, -26, -3, -9, 3, 28, 85, 114, + -29, -126, -53, -28, -4, -9, 2, 25, 81, 116, -13, -127, -58, -29, -6, -9, + 0, 22, 75, 119, 3, -126, -63, -31, -7, -9, -2, 19, 70, 120, 18, -124, + -69, -32, -9, -9, -3, 16, 65, 119, 34, -63, -107, -58, -23, -11, -7, 7, + 46, 107, 89, -52, -109, -62, -25, -12, -8, 5, 42, 104, 97, -41, -87, -70, + -36, -18, -11, 0, 30, 85, 100, -2, -87, -5, 11, -23, -10, -3, -20, -3, + -17, -24, -33, -26, -1, -13, -12, -6, -9, 6, 25, 19, -7, -1, 22, -6, + -20, 13, 6, -12, 26, 48, 0, -7, 34, 23, 4, 32, 23, -41, -11, 49, + -3, -30, 35, 45, -14, -2, 62, 18, -44, -2, 26, -4, -28, -6, 16, 2, + -9, -9, 2, 18, 24, 9, -25, -57, -36, 30, 38, -21, -63, -37, 9, 37, + 40, 0, -56, -56, 3, 39, 20, -23, -52, -58, -46, 8, 67, 56, -18, -61, + -18, 36, 70, 95, 73, -35, -128, -127, -73, -17, 32, 48, 29, 28, 60, 106, + 113, 91, 36, -26, -67, -90, -91, -71, -44, -25, -13, 9, 36, 51, 69, 70, + 32, -40, -92, -99, -70, -25, 12, 29, 21, 3, -9, 10, 21, 12, -11, -22, + -27, -44, -23, 10, 30, 25, 24, 39, 18, 3, 8, 19, -1, -19, -8, 6, + 5, 13, 50, 43, 37, 36, 40, 37, 4, 12, -10, -33, -31, -25, -1, 1, + 7, 14, 10, -4, -11, -10, -6, -19, -42, -28, -54, -51, -18, -5, 3, 2, + -10, -10, 10, 28, 27, 16, 5, -5, -24, -26, -7, -14, -25, -16, 53, 33, + -49, -30, 53, 50, -24, -34, 40, 82, -118, -23, 120, -56, -70, -72, 106, -10, + -48, 3, 87, 28, -126, -16, 81, 4, -84, -51, 38, 62, -32, 36, 84, -12, + -41, 72, -42, -60, -64, 4, 77, -24, -79, -9, 122, 6, -94, 52, 43, 35, + 13, -62, -7, -89, 24, -30, 16, 29, 56, -59, 83, 42, 31, 36, -76, -2, + -128, -2, 45, 27, -104, -31, 66, 21, 19, 36, 121, 11, -76, -26, -93, 34, + 24, -34, -65, -53, 53, 17, 73, 46, 75, -9, -64, -21, -103, 41, 51, -41, + -83, -43, 108, 6, -11, 28, 127, 2, -84, -38, -72, 39, 17, -23, -15, -67, + 37, 6, 29, 64, 79, 17, -39, -39, -120, 55, 23, -17, -62, -51, 81, 23, + 20, 24, 99, -38, -99, 4, 17, -66, -41, -33, 63, 62, 16, 53, 91, 56, + -65, -36, -99, -38, 14, -47, -29, -38, 35, 83, 9, 48, 83, 62, -45, -31, + -103, -49, 14, 2, 6, -33, 33, -4, -1, 34, -93, 60, -49, 68, -21, 41, + -38, -38, 27, -87, 127, -34, 38, -3, -34, -2, -85, 79, -24, 4, 75, -23, + 11, -70, 1, -6, -6, 63, -48, 76, -71, 2, -7, -15, 46, -32, 48, -25, + -5, 10, -31, 18, -23, 5, 6, 17, 11, 3, 24, -46, -21, -1, -5, 31, + 1, 36, -23, -11, -4, -29, 14, -5, 29, 9, -2, -2, -20, -2, -15, 13, + 7, 4, 15, -11, 4, -13, -1, 1, -13, 15, -6, 9, 9, -2, -4, -11, + -2, -11, 7, 12, 9, 5, -6, -6, -16, -2, 3, 6, 13, 1, 7, -14, + -3, -11, -1, 8, 0, 18, -3, -3, -6, -13, 0, 4, 2, 9, 2, 2, + -6, -4, -1, -8, 2, 4, 2, 7, -4, 2, 1, -7, -3, -2, 0, 2, + 8, -2, 2, -1, -7, -3, -1, 3, 4, 3, 3, -3, -4, -4, 0, 2, + 1, 5, -1, -2, 1, -4, -1, 1, 0, 2, -5, -8, -3, -3, -9, -2, + -2, 5, 10, 16, 11, 5, -3, -5, -1, -4, -6, -7, -15, -18, -27, -31, + -21, -11, 22, 56, 90, 66, -17, -25, -25, 0, -12, -15, -25, -32, -39, -37, + -26, 6, 33, 65, 69, 44, -1, -13, -12, 1, 0, -9, -14, -22, -40, -44, + -42, -23, 8, 39, 60, 84, 57, -16, -25, -19, 2, -8, -11, -18, -32, -51, + -45, -32, -6, 28, 54, 85, 96, -5, -29, -23, -7, -10, -17, -16, -28, -53, + -44, -40, -7, 22, 52, 82, 112, 17, -37, -25, -20, -11, -18, -10, -23, -33, + -51, -40, -23, 10, 45, 65, 96, 64, -21, -35, -34, -19, -20, -13, -5, -14, + -35, -41, -39, -17, 9, 45, 58, 82, 98, -2, -57, -47, -23, -12, -11, -2, + -18, -28, -39, -36, -24, -1, 26, 57, 84, 121, 23, -65, -50, -40, -12, -11, + -4, -14, -20, -34, -32, -27, -5, 19, 56, 80, 127, 15, -66, -50, -2, -5, + -5, 2, 10, 8, -7, -16, -9, 6, 17, 8, -19, -20, 14, 38, 34, 20, + -5, 1, 50, 37, -50, -54, -66, -32, 32, -3, -13, -18, -17, 46, 89, -17, + -62, 45, 127, 57, -57, -67, -109, -11, 88, -31, -90, -88, -27, 63, 97, -27, + -105, -44, 65, 110, 60, -12, -30, -27, 17, 49, -2, -39, -6, 30, -16, -36, + -43, 32, 67, -54, -58, -38, -21, 47, 95, 76, -33, -78, -62, 10, 107, 24, + -106, -107, 12, 52, 27, 78, 8, -75, 25, 6, -26, 59, 32, -17, -7, -19, + 11, 32, -51, -52, 41, -9, -13, 94, 2, -65, 5, -46, -86, 34, 62, 85, + 29, -93, -89, -29, 44, 35, -31, -33, -19, 56, 127, 7, -9, -62, -52, 23, + 46, 44, -56, -16, -55, -46, 22, 83, -13, -42, -7, 13, 81, 49, 3, -9, + -30, -47, -30, 3, 23, 6, -7, -20, -44, 10, 96, -13, 0, 16, 31, 47, + 61, 75, 87, 98, 107, 115, 121, 125, 127, 127, 125, 121, 116, 108, 99, 88, + 75, 62, 47, 32, 16, 0, -16, -31, -47, -61, -75, -87, -98, -108, -116, -122, + -126, -128, -128, -126, -123, -117, -109, -100, -89, -77, -64, -49, -34, -18, -2, 14, + 29, 45, 59, 73, 86, 97, 106, 114, 121, 125, 127, 127, 126, 122, 116, 109, + 100, 89, 77, 63, 49, 34, 18, 2, -14, -30, -45, -60, -73, -86, -97, -107, + -115, -121, -126, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, -36, -20, + -4, 12, 28, 43, 58, 72, 84, 96, 106, 114, 120, 124, 127, 127, 126, 122, + 117, 109, 100, 90, 78, 64, 50, 35, 19, 3, -13, -29, -44, -59, -73, -85, + -97, -107, -115, -121, -125, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, + -36, -20, -4, 12, 2, 5, 5, 0, -16, -9, -2, -19, 4, 18, 6, 10, + -16, -21, 22, -2, 3, -7, 21, 43, -57, -37, 46, -39, -31, 78, 23, -23, + -10, -10, -7, -52, 44, 50, -44, 9, -9, -46, 47, 12, -75, 40, 45, 32, + -10, -25, -15, -45, 24, 44, -40, -10, 18, -48, -29, 63, 44, -30, -1, 83, + -45, -94, 96, 0, -103, 21, 29, -42, 21, 80, -25, -15, 26, 39, -79, -18, + 73, -111, -45, 61, 29, 55, -22, -77, 40, 9, -72, 78, 35, -1, -1, -69, + 12, -50, -42, 123, 45, -7, -39, -86, 3, 51, 30, 28, -4, -33, -41, -66, + 54, -8, -30, 127, -7, -30, -32, -39, 48, -65, 20, 121, -33, -14, -53, -32, + 46, -24, 36, 98, -49, -39, -61, 1, 49, -54, 65, 59, -83, -11, -49, 32, + 39, -72, 113, 59, -83, -11, -49, 32, 39, -72, 113, 59, -2, -4, -4, -7, + -8, -8, -7, -4, -3, -2, 1, 4, 6, 6, 6, 4, 2, 0, -2, -3, + -4, -7, -7, -5, -3, 0, 4, 9, 11, 11, 9, 7, 4, 1, -3, -7, + -9, -12, -13, -16, -19, -19, -13, -2, 9, 17, 19, 20, 18, 13, 8, 3, + 0, -2, -3, -8, -14, -21, -25, -21, -9, 4, 15, 23, 28, 25, 20, 9, + -7, -21, -14, 3, 3, -18, -38, -49, -32, -7, 8, 14, 26, 37, 42, 37, + 26, 7, -18, -27, -5, 8, -7, -24, -34, -40, -32, -19, 1, 17, 42, 56, + 58, 40, -19, -81, 1, 67, 0, -60, -49, -27, -24, 0, -18, -24, -8, 37, + 67, 70, 59, 34, -42, -81, 7, 51, -12, -54, -37, -14, -25, -14, -16, -24, + 4, 55, 75, 102, 52, -102, -104, 90, 30, -48, -76, 1, -14, 0, -2, -2, + -3, -5, -7, -8, -8, -7, -6, -4, -2, 0, 1, 3, 4, 6, 6, 6, + 6, 5, 4, 3, 1, 0, 0, -3, -4, -7, -10, -11, -11, -8, -6, 1, + 5, 6, 8, 11, 11, 8, 5, 5, 2, 1, 0, 0, -2, 1, -4, -16, + -36, -27, -5, 6, -3, -6, 0, -6, 2, 27, 24, 19, 16, 9, 3, 0, + -4, 2, 1, 9, 19, -14, -79, -32, 22, -4, -22, -14, 25, 8, -11, 13, + 28, 16, 19, 16, 1, -2, -4, -3, -6, 28, 38, -59, -111, 25, 16, -16, + -40, 16, 24, -20, 4, 24, 29, 17, 27, 13, 1, -10, -6, -10, -8, 43, + 61, -68, -128, 28, 12, -15, -39, 12, 21, -28, 12, 37, 25, 12, 27, 11, + 0, -16, -2, -12, -11, 52, 67, -68, 35, 54, 47, 4, -60, -92, -68, -27, + 0, -2, -18, -20, -6, 2, -8, -15, -11, -3, 3, -7, -11, -6, -2, 7, + 15, 18, 19, 22, 27, 40, 40, 29, 20, 24, 28, 34, 30, 25, 32, 20, + 14, 9, 16, 19, 17, 6, -1, 3, -6, -14, -23, -18, -7, 1, -18, -18, + -24, -25, -24, -35, -35, -35, -21, -12, -14, -21, -17, -29, -24, -31, -34, -9, + -11, -9, -3, -7, -7, 6, -17, -22, 7, 16, 14, -4, -11, 10, 33, 24, + 21, 27, 3, -19, -25, -18, 17, 50, 48, 49, 61, 31, -48, -103, -73, 9, + 56, 70, 82, 109, 127, 71, -46, -127, -96, -30, -4, 9, 47, 103, 117, 60, + -39, -110, -119, -94, -64, -40, -4, 35, -8, -14, -9, -5, -4, -3, 6, 18, + 19, 6, -14, -20, -12, -3, -3, -6, 2, 21, 28, 13, -16, -26, -14, -6, + -6, -7, 1, 27, 36, 18, -15, -27, -15, -3, -2, -10, -6, 25, 41, 22, + -17, -34, -18, -4, -3, -16, -12, 29, 56, 31, -24, -44, -20, -4, -1, -19, + -22, 31, 73, 47, -27, -62, -25, -2, 4, -21, -36, 26, 91, 61, -27, -79, + -33, 0, 10, -18, -49, 14, 106, 82, -24, -94, -40, 8, 14, -12, -59, 1, + 112, 105, -19, -106, -51, 12, 16, -4, -63, -13, 110, 127, -12, -114, -51, 0, + -1, -4, -8, -11, -8, -2, 0, 7, 14, 21, 46, 92, 120, 76, -36, -121, + -119, -73, -31, -7, 3, 2, -4, -6, 2, 22, 60, 106, 116, 43, -72, -128, + -105, -57, -21, -3, 3, -1, -6, -5, 7, 33, 76, 117, 102, 5, -100, -127, + -89, -43, -13, 0, 2, -3, -7, -2, 14, 46, 92, 122, 79, -34, -118, -118, + -72, -31, -8, 1, 0, -5, -7, 2, 23, 61, 107, 118, 46, -69, -126, -104, + -56, -21, -4, 1, 0, -4, -5, 0, 16, 48, 87, 103, 60, -25, -87, -94, + -58, -20, -4, -11, 12, 24, 31, -36, 29, -9, 2, -38, -5, -5, -10, -33, + -10, -24, -20, -39, -36, -18, -38, -58, -5, -22, -15, -15, 90, -42, -3, -8, + 25, 6, 28, 25, 17, 25, -16, 28, 80, 22, 12, -6, 35, 22, 8, -7, + 28, 29, -19, 7, 8, -1, -29, -23, 10, -23, -13, -26, -17, -20, -33, -41, + -19, -28, -64, -13, -21, -13, -29, 54, 25, -20, -36, 42, -4, 13, 52, -8, + 47, -14, 9, 42, 88, -12, 20, -5, 43, 22, -11, 127, 127, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, -128, 1, 4, 7, 10, 12, 16, 19, 22, 25, 28, 31, 35, 38, 42, + 45, 49, 51, 56, 58, 63, 65, 70, 73, 78, 80, 85, 87, 93, 95, 100, + 102, 108, 109, 117, 114, 127, 85, -63, -60, -64, -60, -62, -59, -61, -59, -61, + -58, -60, -58, -59, -58, -58, -57, -57, -55, -55, -54, -54, -52, -51, -50, -49, + -47, -46, -44, -43, -41, -40, -37, -36, -34, -32, -30, -28, -25, -24, -21, -19, + -16, -14, -11, -9, -6, 1, 1, 4, 7, 10, 12, 16, 19, 22, 25, 28, + 31, 35, 38, 42, 45, 49, 51, 56, 58, 63, 65, 70, 73, 78, 80, 85, + 87, 93, 95, 100, 102, 108, 109, 117, 114, 127, 85, -63, -60, -64, -60, -62, + -59, -61, -59, -61, -58, -60, -58, -59, -58, -58, -57, -57, -55, -55, -54, -54, + -52, -51, -50, -49, -47, -46, -44, -43, -41, -40, -37, -36, -34, -32, -30, -28, + -25, -24, -21, -19, -16, -14, -11, -9, -6, 1, -3, -19, -24, -14, -8, -19, + -12, -10, -5, -12, -50, -19, 23, 35, 4, -20, -7, -26, 9, 40, 69, 16, + -88, -69, -38, -32, -27, 41, 65, 55, 18, -40, -38, -20, 66, 127, 121, 57, + -23, -55, -48, 13, 53, 31, -20, -38, -13, 10, 8, 0, 12, 17, 13, 2, + -1, -3, -3, 6, 13, 7, -17, -24, -12, 4, 3, -10, -20, -32, -22, -18, + -12, -3, 6, 16, 22, 29, 30, 27, 20, 11, 0, -7, -12, -11, -5, 0, + -3, -14, -20, -16, -9, -9, -17, -25, -29, -31, -33, -35, -33, -29, -25, -22, + -20, -17, -14, -13, -12, -11, -9, -10, -13, -15, -11, -5, 3, 9, 10, 9, + 9, 12, 18, 30, 50, 80, 119, 127, 102, 82, 77, 60, 37, 5, -34, -70, + -84, -83, -74, -60, -46, -29, -12, -2, 6, -23, 28, -20, 50, 50, -14, 14, + -28, -2, 28, 52, -25, -13, -52, 43, -41, -9, -26, 36, -25, -20, -17, 3, + -11, 38, 30, -61, 12, -6, 5, 45, 41, -4, 4, -20, -12, 45, 33, -11, + -29, -44, 27, -17, -36, -1, 17, -11, -31, -12, 4, -10, 37, 20, -39, -23, + 0, -104, -55, -11, 24, 33, 30, 7, -15, -31, -30, -25, -23, -20, -9, 10, + 31, 59, 91, 111, 115, 92, 51, 7, -33, -64, -81, -81, -71, -51, -22, 16, + 52, 74, 82, 81, 68, 38, 0, -40, -81, -112, -124, -102, -57, -11, 0, 7, + -23, -58, -85, -100, -104, -100, -92, -81, -69, -57, -45, -33, -22, -11, -1, 8, + 18, 27, 37, 49, 62, 79, 99, 118, 124, 111, 84, 53, 26, 5, -8, -14, + -15, -12, -6, 2, 12, 21, 28, 26, 9, -22, -58, -20, 7, 10, 21, -14, + 9, 22, 57, 62, 127, 56, 28, 26, -28, 10, -81, -31, -81, -35, -19, -55, + -27, -4, -4, 23, 49, 88, 85, 22, 1, 0, -3, 18, -22, -12, -39, -14, + -47, -67, -53, -53, -33, -20, 8, -22, 25, 30, 6, -19, -62, -19, 10, 83, + 57, -67, -88, -52, 63, 127, 42, -63, -121, -70, 82, 111, 46, -43, -114, -35, + 45, 73, 39, -19, -54, -41, 9, 49, 24, -16, -14, -9, -6, 10, 8, -22, + 25, 30, 6, -19, -62, -19, 10, 83, 57, -67, -88, -52, 63, 127, 42, -63, + -121, -70, 82, 111, 46, -43, -114, -35, 45, 73, 39, -19, -54, -41, 9, 49, + 24, -16, -14, -9, -6, 10, 8, -22, 25, 30, 6, -19, -62, -19, 10, 83, + 57, -67, -88, -52, 63, 127, 42, -63, -121, -70, 82, 111, 46, -43, -114, -35, + 45, 73, 39, -19, -54, -41, 9, 49, 24, -16, -14, -9, -6, 10, -18, -15, + 80, 127, 20, 18, 72, 60, -36, 22, 33, -73, -105, -27, 29, 25, 8, 43, + 23, -22, -35, -14, -8, -34, -25, -5, -18, -46, -13, -28, -3, -19, -10, -28, + -10, 17, -18, 96, 127, 123, 127, 126, 126, 95, 61, 22, -17, -56, -95, -118, + -123, -128, -128, -128, -128, -128, -128, -128, -128, -124, -93, -55, -17, 25, 62, 100, + 107, 119, 119, 127, 41, -4, -4, -10, -27, -62, -102, -128, -117, -85, -76, -49, + -25, -7, 15, 24, 14, 0, -9, -12, -3, 33, 81, 105, 111, 101, 80, 62, + 45, 30, 16, 8, 1, -4, 126, 86, -44, -68, -88, -63, 4, 84, 127, 14, + -29, -51, -127, -47, 58, 87, 82, 24, -17, -112, -113, 18, 46, 72, 102, 19, + -72, -118, -51, 9, 27, 126, 19, -53, -114, -108, 15, 122, 111, 21, -71, -70, + 5, 59, 83, 23, -72, -84, -49, 12, 37, 38, -28, -65, -26, 7, -2, 11, + 5, 23, 68, 19, 27, -54, 15, -24, -31, 46, 71, 81, -24, -33, -87, -41, + -71, -61, -70, -36, -44, -3, 12, -25, -20, 20, 68, 85, 127, 15, 50, -5, + 27, 51, 82, 106, 127, 118, 101, 92, 74, 52, 39, 37, 14, -41, -105, -108, + -94, -119, -124, -93, -57, -40, -37, -45, -51, -41, -5, 51, 127, 127, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127 +}; + +const EAS_U32 eas_sampleLengths[] = +{ + 16820, 16708, 16592, 11754, 10954, 10295, 9922, 7489, + 5779, 5462, 4452, 3779, 3115, 3093, 3057, 3024, + 2818, 2776, 2171, 2168, 2052, 1902, 1835, 1614, + 1603, 1528, 1517, 1480, 1455, 1424, 1387, 1302, + 1262, 1254, 1230, 1227, 1185, 1181, 1178, 1168, + 1132, 1120, 1034, 1033, 1018, 994, 964, 926, + 907, 886, 881, 866, 830, 817, 816, 813, + 749, 748, 739, 720, 652, 610, 610, 583, + 564, 561, 556, 549, 542, 535, 530, 530, + 516, 508, 492, 478, 461, 448, 437, 431, + 423, 418, 403, 402, 400, 394, 387, 387, + 367, 357, 347, 347, 341, 336, 334, 329, + 325, 312, 294, 284, 277, 265, 255, 233, + 230, 213, 207, 205, 194, 193, 184, 181, + 181, 167, 164, 158, 152, 152, 145, 139, + 128, 103, 100, 88, 87, 84, 84, 72, + 71, 55, 46, 45, 43, 40, 40, 40, + 37, 35, 32, 32, 30, 29, 27, 23, + 22, 21, 21, 21, 21, 20 +}; + +const EAS_U32 eas_sampleOffsets[] = +{ + 0x00000000, 0x000041b4, 0x000082f8, 0x0000c3c8, 0x0000f1b2, 0x00011c7c, 0x000144b3, 0x00016b75, + 0x000188b6, 0x00019f49, 0x0001b49f, 0x0001c603, 0x0001d4c6, 0x0001e0f1, 0x0001ed06, 0x0001f8f7, + 0x000204c7, 0x00020fc9, 0x00021aa1, 0x0002231c, 0x00022b94, 0x00023398, 0x00023b06, 0x00024231, + 0x0002487f, 0x00024ec2, 0x000254ba, 0x00025aa7, 0x0002606f, 0x0002661e, 0x00026bae, 0x00027119, + 0x0002762f, 0x00027b1d, 0x00028003, 0x000284d1, 0x0002899c, 0x00028e3d, 0x000292da, 0x00029774, + 0x00029c04, 0x0002a070, 0x0002a4d0, 0x0002a8da, 0x0002ace3, 0x0002b0dd, 0x0002b4bf, 0x0002b883, + 0x0002bc21, 0x0002bfac, 0x0002c322, 0x0002c693, 0x0002c9f5, 0x0002cd33, 0x0002d064, 0x0002d394, + 0x0002d6c1, 0x0002d9ae, 0x0002dc9a, 0x0002df7d, 0x0002e24d, 0x0002e4d9, 0x0002e73b, 0x0002e99d, + 0x0002ebe4, 0x0002ee18, 0x0002f049, 0x0002f275, 0x0002f49a, 0x0002f6b8, 0x0002f8cf, 0x0002fae1, + 0x0002fcf3, 0x0002fef7, 0x000300f3, 0x000302df, 0x000304bd, 0x0003068a, 0x0003084a, 0x000309ff, + 0x00030bae, 0x00030d55, 0x00030ef7, 0x0003108a, 0x0003121c, 0x000313ac, 0x00031536, 0x000316b9, + 0x0003183c, 0x000319ab, 0x00031b10, 0x00031c6b, 0x00031dc6, 0x00031f1b, 0x0003206b, 0x000321b9, + 0x00032302, 0x00032447, 0x0003257f, 0x000326a5, 0x000327c1, 0x000328d6, 0x000329df, 0x00032ade, + 0x00032bc7, 0x00032cad, 0x00032d82, 0x00032e51, 0x00032f1e, 0x00032fe0, 0x000330a1, 0x00033159, + 0x0003320e, 0x000332c3, 0x0003336a, 0x0003340e, 0x000334ac, 0x00033544, 0x000335dc, 0x0003366d, + 0x000336f8, 0x00033778, 0x000337df, 0x00033843, 0x0003389b, 0x000338f2, 0x00033946, 0x0003399a, + 0x000339e2, 0x00033a29, 0x00033a60, 0x00033a8e, 0x00033abb, 0x00033ae6, 0x00033b0e, 0x00033b36, + 0x00033b5e, 0x00033b83, 0x00033ba6, 0x00033bc6, 0x00033be6, 0x00033c04, 0x00033c21, 0x00033c3c, + 0x00033c53, 0x00033c69, 0x00033c7e, 0x00033c93, 0x00033ca8, 0x00033cbd +}; + +/*---------------------------------------------------------------------------- + * S_EAS + *---------------------------------------------------------------------------- +*/ +const S_EAS easSoundLib = +{ + 0x01534145, + 0x0010ac44, + eas_banks, + eas_programs, + eas_regions, + eas_articulations, + eas_sampleLengths, + eas_sampleOffsets, + eas_samples, + 0, + 1, + 1, + 377, + 185, + 150, + 0 +}; /* end S_EAS */ + +/*---------------------------------------------------------------------------- + * Statistics + * + * Number of banks: 1 + * Number of programs: 1 + * Number of regions: 377 + * Number of articulations: 185 + * Number of samples: 150 + * Size of sample pool: 212050 + *---------------------------------------------------------------------------- +*/ +/* end wt_200k_G_MAC.c */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib/libarm-wt-22k.a b/code/embeddedaudiosynthesis/arm-wt-22k/lib/libarm-wt-22k.a new file mode 100755 index 0000000..b130714 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/lib/libarm-wt-22k.a differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_filter_gnu.s b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_filter_gnu.s new file mode 100755 index 0000000..871cd7d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_filter_gnu.s @@ -0,0 +1,134 @@ +@*********************************************************** +@ Function: WT_VoiceFilter +@ Processor: ARM +@ Description: +@ Implements a 2-pole low-pass filter with resonanance +@ +@ Usage: +@ void WT_VoiceFilter( +@ S_FILTER CONTROL *pFilter, +@ S_WT_FRAME *pWTFrame); +@ +@ Copyright 2005 Sonic Network, Inc. +@**************************************************************** +@ Revision Control: +@ $Revision: 496 $ +@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $ +@**************************************************************** +@ +@ where: +@ S_FILTER_CONTROL *pFilter +@ PASSED IN: r0 +@ +@ S_WT_FRAME *pWTFrame +@ PASSED IN: r1 +@**************************************************************** + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + + .global WT_VoiceFilter + + +@ Register usage +@ -------------- +pFilter .req r0 +pWTFrame .req r1 +pBuffer .req r2 +numSamples .req r3 + +z1 .req r4 +z2 .req r5 +b1 .req r6 +b2 .req r7 +K .req r8 + +tmp0 .req r1 @ reuse register +tmp1 .req r9 +tmp2 .req r10 + + +@SaveRegs RLIST {r4-r10, lr} +@RestoreRegs RLIST {r4-r10, pc} + + + .func WT_VoiceFilter +WT_VoiceFilter: + + STMFD sp!, {r4-r10, lr} + +@ +@ Setup passed parameters in their destination registers +@---------------------------------------------------------------- + + LDR pBuffer, [pWTFrame, #m_pAudioBuffer] + LDR numSamples, [pWTFrame, #m_numSamples] + + @load state variables from pFilter structure + LDRSH z1, [pFilter, #m_z1] + LDRSH z2, [pFilter, #m_z2] + + @load coefficients from pWTFrame structure + LDR K, [pWTFrame, #m_k] + LDR b1, [pWTFrame, #m_b1] + LDR b2, [pWTFrame, #m_b2] + + RSB b1, b1, #0 @ b1 = -b1 + RSB b2, b2, #0 @ b2 = -b2 + MOV b2, b2, ASR #1 @ b2 = b2 >> 1 + MOV K, K, ASR #1 @ K = K >> 1 + +@ +@ Start processing +@---------------------------------------------------------------- + + LDRSH tmp0, [pBuffer] @ fetch sample + +FilterLoop: + SMULBB tmp2, z1, b1 @ tmp2 = z1 * -b1 + SMLABB tmp2, z2, b2, tmp2 @ tmp2 = (-b1 * z1) + (-b2 * z2) + + MOV z2, z1 @ delay line + + SMLABB tmp0, tmp0, K, tmp2 @ tmp1 = (K * x[n]) + (-b1 * z1) + (-b2 * z2) + + LDRSH tmp1, [pBuffer, #NEXT_OUTPUT_PCM] @ fetch next sample + + MOV z1, tmp0, ASR #14 @ shift result to low word + STRH z1, [pBuffer], #NEXT_OUTPUT_PCM @ write back to buffer + + SMULBB tmp2, z1, b1 @ tmp2 = z1 * -b1 + + SUBS numSamples, numSamples, #2 @ unroll loop once + + SMLABB tmp2, z2, b2, tmp2 @ tmp2 = (-b1 * z1) + (-b2 * z2) + + SMLABB tmp1, tmp1, K, tmp2 @ tmp1 = (K * x[n]) + (-b1 * z1) + (-b2 * z2) + + MOV z2, z1 @ delay line + + MOV z1, tmp1, ASR #14 @ shift result to low word + + LDRGTSH tmp0, [pBuffer, #NEXT_OUTPUT_PCM] @ fetch next sample + + STRH z1, [pBuffer], #NEXT_OUTPUT_PCM @ write back to buffer + + BGT FilterLoop +@ save z terms +@---------------------------------------------------------------- + + STRH z1, [pFilter, #m_z1] + STRH z2, [pFilter, #m_z2] + +@ Return to calling function +@---------------------------------------------------------------- + + LDMFD sp!,{r4-r10, lr} + BX lr + + .endfunc + .end + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s new file mode 100755 index 0000000..847a7f0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_interpolate_loop_gnu.s @@ -0,0 +1,131 @@ +@*********************************************************** +@ Function: WT_Interpolate +@ Processor: ARM-E +@ Description: the main synthesis function when fetching +@ wavetable samples. +@ C-callable. +@ +@ Usage: +@ void WT_Interpolate( +@ S_WT_VOICE *pWTVoice, +@ S_WT_FRAME *pWTFrame); +@ +@ Copyright Sonic Network Inc. 2004 +@**************************************************************** +@ Revision Control: +@ $Revision: 496 $ +@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $ +@**************************************************************** +@ +@ where: +@ S_WT_VOICE *pWTVoice +@ PASSED IN: r0 +@ +@ S_WT_FRAME *pWTFrame; +@ PASSED IN: r1 +@**************************************************************** + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + .global WT_Interpolate + + +@ Register usage +@ -------------- +pWTVoice .req r0 +pWTFrame .req r1 + +numSamples .req r2 +phaseIncrement .req r3 +pOutputBuffer .req r4 + +tmp0 .req r1 @reuse register +tmp1 .req r5 +tmp2 .req r6 + +pLoopEnd .req r7 +pLoopStart .req r8 + +pPhaseAccum .req r9 +phaseFrac .req r10 +phaseFracMask .req r11 + +@SaveRegs RLIST {r4-r11,lr} +@RestoreRegs RLIST {r4-r11,pc} + + .func WT_Interpolate +WT_Interpolate: + + STMFD sp!,{r4-r11,lr} + +@ +@ Fetch parameters from structures +@---------------------------------------------------------------- + + LDR pOutputBuffer, [pWTFrame, #m_pAudioBuffer] + LDR numSamples, [pWTFrame, #m_numSamples] + + LDR phaseIncrement, [pWTFrame, #m_phaseIncrement] + LDR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] + LDR phaseFrac, [pWTVoice, #m_phaseFrac] + LDR phaseFracMask,=PHASE_FRAC_MASK + + LDR pLoopStart, [pWTVoice, #m_pLoopStart] + LDR pLoopEnd, [pWTVoice, #m_pLoopEnd] + ADD pLoopEnd, pLoopEnd, #1 @ need loop end to equal last sample + 1 + +InterpolationLoop: + SUBS tmp0, pPhaseAccum, pLoopEnd @ check for loop end + ADDGE pPhaseAccum, pLoopStart, tmp0 @ loop back to start + + .ifdef SAMPLES_8_BIT + LDRSB tmp0, [pPhaseAccum] @ tmp0 = x0 + LDRSB tmp1, [pPhaseAccum, #1] @ tmp1 = x1 + .else + LDRSH tmp0, [pPhaseAccum] @ tmp0 = x0 + LDRSH tmp1, [pPhaseAccum, #2] @ tmp1 = x1 + .endif + + ADD tmp2, phaseIncrement, phaseFrac @ increment pointer here to avoid pipeline stall + + SUB tmp1, tmp1, tmp0 @ tmp1 = x1 - x0 + SMULBB tmp1, phaseFrac, tmp1 @ tmp1 = phaseFrac * tmp2 + +@ This section performs a gain adjustment of -12dB for 16-bit samples +@ or +36dB for 8-bit samples. For a high quality synthesizer, the output +@ can be set to full scale, however if the filter is used, it can overflow +@ with certain coefficients and signal sources. In this case, either a +@ saturation operation should take in the filter before scaling back to +@ 16 bits or the signal path should be increased to 18 bits or more. + + .ifdef SAMPLES_8_BIT + MOV tmp0, tmp0, LSL #6 @ boost 8-bit signal by 36dB + .else + MOV tmp0, tmp0, ASR #2 @ reduce 16-bit signal by 12dB + .endif + + ADD tmp1, tmp0, tmp1, ASR #(NUM_EG1_FRAC_BITS-6) @ tmp1 = tmp0 + (tmp1 >> (15-6)) + @ = x0 + f * (x1 - x0) == interpolated result + + STRH tmp1, [pOutputBuffer], #NEXT_OUTPUT_PCM @ *pOutputBuffer++ = interpolated result + +@ carry overflow from fraction to integer portion + ADD pPhaseAccum, pPhaseAccum, tmp2, LSR #(NUM_PHASE_FRAC_BITS - NEXT_INPUT_PCM_SHIFT) + AND phaseFrac, tmp2, phaseFracMask @ nphaseFrac = frac part + + SUBS numSamples, numSamples, #1 + BGT InterpolationLoop + +@ update and store phase + STR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] + STR phaseFrac, [pWTVoice, #m_phaseFrac] + + LDMFD sp!,{r4-r11,lr} + BX lr + + .endfunc + .end + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_interpolate_noloop_gnu.s b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_interpolate_noloop_gnu.s new file mode 100755 index 0000000..6343762 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_interpolate_noloop_gnu.s @@ -0,0 +1,130 @@ +@*********************************************************** +@ Function: WT_InterpolateNoLoop +@ Processor: ARM-E +@ Description: the main synthesis function when fetching +@ wavetable samples. +@ C-callable. +@ +@ Usage: +@ void WT_InterpolateNoLoop( +@ S_WT_VOICE *pWTVoice, +@ S_WT_FRAME *pWTFrame); +@ +@ Copyright Sonic Network Inc. 2004 +@**************************************************************** +@ Revision Control: +@ $Revision: 496 $ +@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $ +@**************************************************************** +@ +@ where: +@ S_WT_VOICE *pWTVoice +@ PASSED IN: r0 +@ +@ S_WT_FRAME *pWTFrame; +@ PASSED IN: r1 +@**************************************************************** + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + + .global WT_InterpolateNoLoop + + +@ Register usage +@ -------------- +pWTVoice .req r0 +pWTFrame .req r1 +pOutputBuffer .req r2 +numSamples .req r3 + +phaseIncrement .req r4 +pPhaseAccum .req r5 +phaseFrac .req r6 +phaseFracMask .req r7 + +tmp0 .req r1 @ reuse register +tmp1 .req r8 +tmp2 .req r9 + + +@SaveRegs RLIST {r4-r9,lr} +@RestoreRegs RLIST {r4-r9,pc} + + .func WT_InterpolateNoLoop +WT_InterpolateNoLoop: + + STMFD sp!, {r4-r9,lr} + +@ +@ Fetch parameters from structures +@---------------------------------------------------------------- + + LDR pOutputBuffer, [pWTFrame, #m_pAudioBuffer] + LDR numSamples, [pWTFrame, #m_numSamples] + + LDR phaseIncrement, [pWTFrame, #m_phaseIncrement] + LDR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] + LDR phaseFrac, [pWTVoice, #m_phaseFrac] + LDR phaseFracMask,=PHASE_FRAC_MASK + +InterpolationLoop: + + .ifdef SAMPLES_8_BIT + LDRSB tmp0, [pPhaseAccum] @ tmp0 = x0 + LDRSB tmp1, [pPhaseAccum, #1] @ tmp1 = x1 + .else + LDRSH tmp0, [pPhaseAccum] @ tmp0 = x0 + LDRSH tmp1, [pPhaseAccum, #2] @ tmp1 = x1 + .endif + + ADD tmp2, phaseIncrement, phaseFrac @ increment pointer here to avoid pipeline stall + + SUB tmp1, tmp1, tmp0 @ tmp1 = x1 - x0 + SMULBB tmp1, phaseFrac, tmp1 @ tmp1 = phaseFrac * tmp2 + +@ This section performs a gain adjustment of -12dB for 16-bit samples +@ or +36dB for 8-bit samples. For a high quality synthesizer, the output +@ can be set to full scale, however if the filter is used, it can overflow +@ with certain coefficients and signal sources. In this case, either a +@ saturation operation should take in the filter before scaling back to +@ 16 bits or the signal path should be increased to 18 bits or more. + + .ifdef SAMPLES_8_BIT + MOV tmp0, tmp0, LSL #6 @ boost 8-bit signal by 36dB + .else + MOV tmp0, tmp0, ASR #2 @ reduce 16-bit signal by 12dB + .endif + + ADD tmp1, tmp0, tmp1, ASR #(NUM_EG1_FRAC_BITS-6) @ tmp1 = tmp0 + (tmp1 >> (15-6)) + @ = x0 + f * (x1 - x0) == interpolated result + + STRH tmp1, [pOutputBuffer], #NEXT_OUTPUT_PCM @ *pOutputBuffer++ = interpolated result + +@ carry overflow from fraction to integer portion + ADD pPhaseAccum, pPhaseAccum, tmp2, LSR #(NUM_PHASE_FRAC_BITS - NEXT_INPUT_PCM_SHIFT) + AND phaseFrac, tmp2, phaseFracMask @ nphaseFrac = frac part + + SUBS numSamples, numSamples, #1 + BGT InterpolationLoop + +@ Clean up and store any changes that were caused during the loop +@---------------------------------------------------------------- + + @ update and store phase + STR pPhaseAccum, [pWTVoice, #m_pPhaseAccum] + STR phaseFrac, [pWTVoice, #m_phaseFrac] + +@ +@ Return to calling function +@---------------------------------------------------------------- + + LDMFD sp!,{r4-r9,lr} + BX lr + + .endfunc + .end + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_mastergain_gnu.s b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_mastergain_gnu.s new file mode 100755 index 0000000..b4e905b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_mastergain_gnu.s @@ -0,0 +1,109 @@ +@*********************************************************** +@ Function: SynthMasterGain +@ Processor: ARM-E +@ Description: Copies 32-bit synth output to 16-bit buffer +@ with saturated gain control +@ C-callable. +@ +@ Usage: +@ SynthMasterGain( +@ pInputBuffer +@ pOutputBuffer, +@ nGain, +@ nNumLoopSamples +@ ); +@ +@ Copyright Sonic Network Inc. 2004 +@**************************************************************** +@ Revision Control: +@ $Revision: 496 $ +@ $Date: 2006-12-11 14:33:26 -0800 (Mon, 11 Dec 2006) $ +@**************************************************************** +@ +@ where: +@ long *pInputBuffer +@ PASSED IN: r0 +@ +@ EAS_PCM *pOutputBuffer +@ PASSED IN: r1 +@ +@ short nGain +@ PASSED IN: r2 +@ +@ EAS_U16 nNumLoopSamples +@ PASSED IN: r3 +@ +@**************************************************************** + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + .func SynthMasterGain +SynthMasterGain: + + .global SynthMasterGain @ allow other files to use this function + + + + + +@ Stack frame +@ ----------- + .equ RET_ADDR_SZ, 0 @return address + .equ REG_SAVE_SZ, 0 @save-on-entry registers saved + .equ FRAME_SZ, (8) @local variables + .equ ARG_BLK_SZ, 0 @argument block + + .equ PARAM_OFFSET, (ARG_BLK_SZ + FRAME_SZ + REG_SAVE_SZ + RET_ADDR_SZ) + +@ Register usage +@ -------------- +pnInputBuffer .req r0 +pnOutputBuffer .req r1 +nGain .req r2 +nNumLoopSamples .req r3 + + STMFD sp!,{r4-r6,r14} @Save any save-on-entry registers that are used + + LDR r6, =0x7fff @constant for saturation tests + +loop: + LDR r4, [pnInputBuffer], #4 @fetch 1st output sample + + LDR r5, [pnInputBuffer], #4 @fetch 2nd output sample + + SMULWB r4, r4, nGain @output = gain * input + + CMP r4, r6 @check for positive saturation + MOVGT r4, r6 @saturate + CMN r4, r6 @check for negative saturation + MVNLT r4, r6 @saturate + + SMULWB r5, r5, nGain @output = gain * input + + STRH r4, [pnOutputBuffer], #NEXT_OUTPUT_PCM @save 1st output sample + + CMP r5, r6 @check for positive saturation + MOVGT r5, r6 @saturate + CMN r5, r6 @check for negative saturation + MVNLT r5, r6 @saturate + STRH r5, [pnOutputBuffer], #NEXT_OUTPUT_PCM @save 2nd output sample + + SUBS nNumLoopSamples, nNumLoopSamples, #2 + BGT loop + +@ +@ Return to calling function +@---------------------------------------------------------------- + + LDMFD sp!,{r4-r6, lr} @ return to calling function + BX lr + +@***************************************************************************** + + .endfunc @ end of function/procedure + + .end @ end of assembly code + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_voice_gain_gnu.s b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_voice_gain_gnu.s new file mode 100755 index 0000000..4517a3d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM-E_voice_gain_gnu.s @@ -0,0 +1,166 @@ +@*********************************************************** +@ Function: WT_VoiceGain +@ Processor: ARM-E +@ Description: the main synthesis function when fetching +@ wavetable samples. +@ C-callable. +@ +@ Usage: +@ Usage: +@ WT_VoiceGain( +@ S_WT_VOICE *pWTVoice, +@ S_WT_FRAME *pWTFrame); +@ +@ Copyright 2004, 2005 Sonic Network, Inc. +@**************************************************************** +@ Revision Control: +@ $Revision: 814 $ +@ $Date: 2007-08-02 10:34:53 -0700 (Thu, 02 Aug 2007) $ +@**************************************************************** +@ +@ where: +@ S_WT_VOICE *psVoice +@ PASSED IN: r0 +@ +@ S_WT_FRAME *pWTFrame +@ PASSED IN: r1 +@**************************************************************** + + + + .include "ARM_synth_constants_gnu.inc" + + .arm + .text + + .global WT_VoiceGain + +@ Register usage +@ -------------- +pWTVoice .req r0 +pWTFrame .req r1 +pInputBuffer .req r2 +pMixBuffer .req r3 + +tmp0 .req r4 +tmp1 .req r5 +tmp2 .req r1 @ reuse register +tmp3 .req r6 + +numSamples .req r9 + + .if STEREO_OUTPUT +gainIncLeft .req r7 +gainIncRight .req r8 +gainLeft .req r10 +gainRight .req r11 + .else +gainIncrement .req r7 +gain .req r8 + .endif + + +@ register context for local variables +@SaveRegs RLIST {r4-r11,lr} +@RestoreRegs RLIST {r4-r11,pc} + + .func WT_VoiceGain +WT_VoiceGain: + + STMFD sp!, {r4-r11,lr} + + LDR pInputBuffer, [pWTFrame, #m_pAudioBuffer] + LDR pMixBuffer, [pWTFrame, #m_pMixBuffer] + LDR numSamples, [pWTFrame, #m_numSamples] + +@---------------------------------------------------------------- +@ Stereo version +@---------------------------------------------------------------- +@ NOTE: instructions are reordered to reduce the effect of latency +@ due to storage and computational dependencies. +@---------------------------------------------------------------- + + .if STEREO_OUTPUT + + LDR tmp0, [pWTFrame, #m_prevGain] + LDR tmp1, [pWTFrame, #m_gainTarget] + + LDRSH gainLeft, [pWTVoice, #m_gainLeft] + LDRSH gainRight, [pWTVoice, #m_gainRight] + + MOV gainIncLeft, gainLeft + SMULBB gainLeft, tmp0, gainLeft + + SMULBB gainIncLeft, tmp1, gainIncLeft + SUB gainIncLeft, gainIncLeft, gainLeft + MOV gainLeft, gainLeft, ASR #(NUM_MIXER_GUARD_BITS - 2) + MOV gainIncLeft, gainIncLeft, ASR #(SYNTH_UPDATE_PERIOD_IN_BITS + NUM_MIXER_GUARD_BITS - 2) + + MOV gainIncRight, gainRight + SMULBB gainRight, tmp0, gainRight + + SMULBB gainIncRight, tmp1, gainIncRight + SUB gainIncRight, gainIncRight, gainRight + MOV gainRight, gainRight, ASR #(NUM_MIXER_GUARD_BITS - 2) + MOV gainIncRight, gainIncRight, ASR #(SYNTH_UPDATE_PERIOD_IN_BITS + NUM_MIXER_GUARD_BITS - 2) + + LDRSH tmp0, [pInputBuffer], #2 + +StereoGainLoop: + LDR tmp1, [pMixBuffer] + + ADD gainLeft, gainLeft, gainIncLeft + + SMLAWB tmp1, gainLeft, tmp0, tmp1 + + LDR tmp2, [pMixBuffer, #4] + + ADD gainRight, gainRight, gainIncRight + + STR tmp1, [pMixBuffer], #4 + + SMLAWB tmp2, gainRight, tmp0, tmp2 + + SUBS numSamples, numSamples, #1 + + LDRGTSH tmp0, [pInputBuffer], #2 + + STR tmp2, [pMixBuffer], #4 + + BGT StereoGainLoop + +@---------------------------------------------------------------- +@ Mono version +@---------------------------------------------------------------- + .else + + LDR gain, [pWTFrame, #m_prevGain] + MOV gain, gain, LSL #(NUM_MIXER_GUARD_BITS + 4) + LDR gainIncrement, [pWTFrame, #m_gainTarget] + MOV gainIncrement, gainIncrement, LSL #(NUM_MIXER_GUARD_BITS + 4) + SUB gainIncrement, gainIncrement, gain + MOV gainIncrement, gainIncrement, ASR #SYNTH_UPDATE_PERIOD_IN_BITS + +MonoGainLoop: + + LDRSH tmp0, [pInputBuffer], #NEXT_OUTPUT_PCM @ fetch voice output + + LDR tmp1, [pMixBuffer] @ get left channel output sample + ADD gain, gain, gainIncrement @ gain step to eliminate zipper noise + SMULWB tmp0, gain, tmp0 @ sample * local gain + + MOV tmp0, tmp0, ASR #1 @ add 6dB headroom + ADD tmp1, tmp0, tmp1 + STR tmp1, [pMixBuffer], #4 @ save and bump pointer + + SUBS numSamples, numSamples, #1 + BGT MonoGainLoop + + .endif @end Mono version + + LDMFD sp!,{r4-r11,lr} + BX lr + + .endfunc + .end + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc new file mode 100755 index 0000000..c0f8df3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/ARM_synth_constants_gnu.inc @@ -0,0 +1,153 @@ +@*********************************************************** +@ File: ARM_synth_constants.inc +@ Processor: ARM +@ Description: Contains constants and defines, most of which +@ are mirrored in synth.h +@ +@ Copyright Sonic Network Inc. 2004 +@**************************************************************** +@ Revision Control: +@ $Revision: 741 $ +@ $Date: 2007-06-22 16:39:21 -0700 (Fri, 22 Jun 2007) $ +@**************************************************************** + + + .ifdef SAMPLE_RATE_8000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 5 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 32 + .endif + + .ifdef SAMPLE_RATE_16000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 6 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 64 + .endif + + .ifdef SAMPLE_RATE_20000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128 + .endif + + .ifdef SAMPLE_RATE_22050 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128 + .endif + + .ifdef SAMPLE_RATE_24000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128 + .endif + + .ifdef SAMPLE_RATE_32000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 7 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 128 + .endif + + .ifdef SAMPLE_RATE_44100 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 8 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 256 + .endif + + .ifdef SAMPLE_RATE_48000 + .equ SYNTH_UPDATE_PERIOD_IN_BITS, 8 + .equ BUFFER_SIZE_IN_MONO_SAMPLES, 256 + .endif + + +@ if the OUTPUT PCM sample is 16-bits, then when using indexed addressing, +@ the next sample is this many bytes away + .equ NEXT_OUTPUT_PCM, 2 + +@**************************************************************************** +@/* macros for fractional phase accumulator */ + .equ NUM_PHASE_FRAC_BITS, 15 + + .equ PHASE_FRAC_MASK, 0x7FFF + +@ shift for phase accumulator when fraction carries over + .ifdef SAMPLES_8_BIT + .equ NEXT_INPUT_PCM_SHIFT, 0 + .endif + + .ifdef SAMPLES_16_BIT + .equ NEXT_INPUT_PCM_SHIFT, 1 + .endif + +@**************************************************************************** + .equ NUM_MIXER_GUARD_BITS, 4 + +@**************************************************************************** +@/* Envelope 1 (EG1) calculation macros */ + .equ NUM_EG1_FRAC_BITS, 15 + +@**************************************************************************** + + .equ NUM_ENHANCER_FILTER_COEF_FRAC_BITS, 5 + +@**************************************************************************** + +@ +@ I've temporarily given up on the idea of getting ADS/RV and gcc to +@ handle a struct in a compatible fashion. Switching to old fashion EQU +@ + + .if FILTER_ENABLED +@************************************** +@ typedef struct s_filter_tag + .equ m_z1, 0 + .equ m_z2, 2 + .endif + +@************************************** +@ typedef struct s_wt_frame_tag + .equ m_gainTarget, 0 + .equ m_phaseIncrement, 4 + + .if FILTER_ENABLED + .equ m_k, 8 + .equ m_b1, 12 + .equ m_b2, 16 + .equ m_pAudioBuffer, 20 + .equ m_pMixBuffer, 24 + .equ m_numSamples, 28 + .equ m_prevGain, 32 + .else + .equ m_pAudioBuffer, 8 + .equ m_pMixBuffer, 12 + .equ m_numSamples, 16 + .equ m_prevGain, 20 + .endif + + +@************************************** +@ typedef struct s_wt_voice_tag + .equ m_pLoopEnd, 0 @ /* points to last PCM sample (not 1 beyond last) */ + .equ m_pLoopStart, 4 @ /* points to first sample at start of loop */ + .equ m_pPhaseAccum, 8 @ /* points to first sample at start of loop */ + .equ m_phaseFrac, 12 @ /* points to first sample at start of loop */ + + .if STEREO_OUTPUT + .equ m_gainLeft, 16 @ /* current gain, left ch */ + .equ m_gainRight, 18 @ /* current gain, right ch */ + .endif + + +@**************************************************************************** +@ enhancer + .equ m_nEnhancerFeedForward1, 0 + .equ m_nEnhancerFeedback1, 1 + .equ m_nDriveCoef, 2 + .equ m_nEnhancerFeedback2, 3 + .equ m_nWet, 4 + .equ m_nDry, 5 + + .equ m_zF0L, 6 @ filter 1 zero state var, left + .equ m_zF1L, 8 @ filter 1 pole state var, left + .equ m_zF2L, 10 @ filter 2 zero state var, left + .equ m_zF0R, 12 @ filter 1 zero state var, right + .equ m_zF1R, 14 @ filter 1 pole state var, right + .equ m_zF2R, 16 @ filter 2 zero state var, right + +@**************************************************************************** + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/arm-wt-22k_lib.mak b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/arm-wt-22k_lib.mak new file mode 100755 index 0000000..8e9824f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/arm-wt-22k_lib.mak @@ -0,0 +1,25 @@ +# +# Auto-generated sample makefile +# +# This makefile is intended for use with GNU make. +# Set the paths to the tools (CC, AR, LD, etc.) +# + +vpath %.c lib_src + +CC = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AS = C:\Program Files\GNUARM\bin\arm-elf-as.exe +LD = C:\Program Files\GNUARM\bin\arm-elf-gcc.exe +AR = C:\Program Files\GNUARM\bin\arm-elf-ar.exe + +%.o: %.c + $(CC) -c -O2 -o $@ -I lib_src -I host_src -D NUM_OUTPUT_CHANNELS=2 -D _SAMPLE_RATE_22050 -D MAX_SYNTH_VOICES=64 -D EAS_WT_SYNTH -D _8_BIT_SAMPLES -D _FILTER_ENABLED -D _IMELODY_PARSER -D _RTTTL_PARSER -D _OTA_PARSER -D _XMF_PARSER -D _WAVE_PARSER -D _REVERB_ENABLED -D _CHORUS_ENABLED -D DLS_SYNTHESIZER -D _IMA_DECODER -D MMAPI_SUPPORT -D NATIVE_EAS_KERNEL -D JET_INTERFACE $< + +%.o: %.s + $(AS) -o $@ -EL -mcpu=arm946e-s -mfpu=softfpa -I lib_src --defsym CHECK_STACK=0 --defsym REVERB=0 --defsym CHORUS=0 --defsym STEREO_OUTPUT=1 --defsym SAMPLE_RATE_22050=1 --defsym SAMPLES_8_BIT=1 --defsym FILTER_ENABLED=1 $< + +OBJS = eas_mididata.o eas_pan.o eas_wavefiledata.o eas_imelody.o eas_xmfdata.o ARM-E_interpolate_noloop_gnu.o eas_chorusdata.o ARM-E_voice_gain_gnu.o eas_ota.o eas_reverbdata.o eas_rtttl.o eas_reverb.o jet.o eas_mdls.o eas_mixbuf.o eas_smf.o eas_tcdata.o eas_chorus.o eas_pcmdata.o eas_xmf.o eas_smfdata.o eas_math.o eas_tonecontrol.o eas_rtttldata.o eas_voicemgt.o eas_public.o eas_dlssynth.o ARM-E_interpolate_loop_gnu.o ARM-E_filter_gnu.o eas_midi.o eas_otadata.o eas_flog.o eas_wtengine.o eas_imaadpcm.o eas_wtsynth.o wt_22khz.o eas_pcm.o eas_mixer.o eas_wavefile.o eas_ima_tables.o eas_data.o ARM-E_mastergain_gnu.o eas_imelodydata.o + +arm-wt-22k.a: $(OBJS) + $(AR) rc lib$@ $(OBJS) + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/dls.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/dls.h new file mode 100755 index 0000000..0a9e302 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/dls.h @@ -0,0 +1,268 @@ + /* + + dls.h + + Description: + + Interface defines and structures for the Instrument Collection Form + RIFF DLS. + + Written by Sonic Foundry 1996. Released for public use. + + */ + + #ifndef _INC_DLS + #define _INC_DLS + + /* + + Layout of an instrument collection: + + + RIFF [] 'DLS ' [colh,INSTLIST,WAVEPOOL,INFOLIST] + + INSTLIST + LIST [] 'lins' + LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST] + LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST] + LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST] + + RGNLIST + LIST [] 'lrgn' + LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST] + LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST] + LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST] + + ARTLIST + LIST [] 'lart' + 'art1' level 1 Articulation connection graph + 'art2' level 2 Articulation connection graph + '3rd1' Possible 3rd party articulation structure 1 + '3rd2' Possible 3rd party articulation structure 2 .... and so on + + WAVEPOOL + ptbl [] [pool table] + LIST [] 'wvpl' + [path], + [path], + LIST [] 'wave',RIFFWAVE + LIST [] 'wave',RIFFWAVE + LIST [] 'wave',RIFFWAVE + LIST [] 'wave',RIFFWAVE + LIST [] 'wave',RIFFWAVE + + INFOLIST + LIST [] 'INFO' + 'icmt' 'One of those crazy comments.' + 'icop' 'Copyright (C) 1996 Sonic Foundry' + + */ + + + /* + FOURCC's used in the DLS file + */ +/* shree */ +//#define FAR + +/* shree + + #define FOURCC_DLS mmioFOURCC('D','L','S',' ') + #define FOURCC_COLH mmioFOURCC('c','o','l','h') + #define FOURCC_WVPL mmioFOURCC('w','v','p','l') + #define FOURCC_PTBL mmioFOURCC('p','t','b','l') + #define FOURCC_PATH mmioFOURCC('p','a','t','h') + #define FOURCC_wave mmioFOURCC('w','a','v','e') + #define FOURCC_LINS mmioFOURCC('l','i','n','s') + #define FOURCC_INS mmioFOURCC('i','n','s',' ') + #define FOURCC_INSH mmioFOURCC('i','n','s','h') + #define FOURCC_LRGN mmioFOURCC('l','r','g','n') + #define FOURCC_RGN mmioFOURCC('r','g','n',' ') + #define FOURCC_RGNH mmioFOURCC('r','g','n','h') + #define FOURCC_LART mmioFOURCC('l','a','r','t') + #define FOURCC_ART1 mmioFOURCC('a','r','t','1') + #define FOURCC_WLNK mmioFOURCC('w','l','n','k') + #define FOURCC_WSMP mmioFOURCC('w','s','m','p') + #define FOURCC_VERS mmioFOURCC('v','e','r','s') +*/ + /* + Articulation connection graph definitions + */ + + /* Generic Sources */ + #define CONN_SRC_NONE 0x0000 + #define CONN_SRC_LFO 0x0001 + #define CONN_SRC_KEYONVELOCITY 0x0002 + #define CONN_SRC_KEYNUMBER 0x0003 + #define CONN_SRC_EG1 0x0004 + #define CONN_SRC_EG2 0x0005 + #define CONN_SRC_PITCHWHEEL 0x0006 + + /* Midi Controllers 0-127 */ + #define CONN_SRC_CC1 0x0081 + #define CONN_SRC_CC7 0x0087 + #define CONN_SRC_CC10 0x008a + #define CONN_SRC_CC11 0x008b + + /* Registered Parameter Numbers */ + #define CONN_SRC_RPN0 0x0100 + #define CONN_SRC_RPN1 0x0101 + #define CONN_SRC_RPN2 0x0102 + + /* Generic Destinations */ + #define CONN_DST_NONE 0x0000 + #define CONN_DST_ATTENUATION 0x0001 + #define CONN_DST_RESERVED 0x0002 + #define CONN_DST_PITCH 0x0003 + #define CONN_DST_PAN 0x0004 + + /* LFO Destinations */ + #define CONN_DST_LFO_FREQUENCY 0x0104 + #define CONN_DST_LFO_STARTDELAY 0x0105 + + /* EG1 Destinations */ + #define CONN_DST_EG1_ATTACKTIME 0x0206 + #define CONN_DST_EG1_DECAYTIME 0x0207 + #define CONN_DST_EG1_RESERVED 0x0208 + #define CONN_DST_EG1_RELEASETIME 0x0209 + #define CONN_DST_EG1_SUSTAINLEVEL 0x020a + + /* EG2 Destinations */ + #define CONN_DST_EG2_ATTACKTIME 0x030a + #define CONN_DST_EG2_DECAYTIME 0x030b + #define CONN_DST_EG2_RESERVED 0x030c + #define CONN_DST_EG2_RELEASETIME 0x030d + #define CONN_DST_EG2_SUSTAINLEVEL 0x030e + + #define CONN_TRN_NONE 0x0000 + #define CONN_TRN_CONCAVE 0x0001 + + typedef struct _DLSVERSION { + DWORD dwVersionMS; + DWORD dwVersionLS; + }DLSVERSION, FAR *LPDLSVERSION; + + + typedef struct _CONNECTION { + USHORT usSource; + USHORT usControl; + USHORT usDestination; + USHORT usTransform; + LONG lScale; + }CONNECTION, FAR *LPCONNECTION; + + + /* Level 1 Articulation Data */ + + typedef struct _CONNECTIONLIST { + ULONG cbSize; /* size of the connection list structure */ + ULONG cConnections; /* count of connections in the list */ + } CONNECTIONLIST, FAR *LPCONNECTIONLIST; + + + + /* + Generic type defines for regions and instruments + */ + + typedef struct _RGNRANGE { + USHORT usLow; + USHORT usHigh; + }RGNRANGE, FAR * LPRGNRANGE; + + #define F_INSTRUMENT_DRUMS 0x80000000 + + typedef struct _MIDILOCALE { + ULONG ulBank; + ULONG ulInstrument; + }MIDILOCALE, FAR *LPMIDILOCALE; + + /* + Header structures found in an DLS file for collection, instruments, and + regions. + */ + + #define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001 + + typedef struct _RGNHEADER { + RGNRANGE RangeKey; /* Key range */ + RGNRANGE RangeVelocity; /* Velocity Range */ + USHORT fusOptions; /* Synthesis options for this range */ + USHORT usKeyGroup; /* Key grouping for non simultaneous play + 0 = no group, 1 up is group + for Level 1 only groups 1-15 are allowed */ + }RGNHEADER, FAR *LPRGNHEADER; + + typedef struct _INSTHEADER { + ULONG cRegions; /* Count of regions in this instrument */ + MIDILOCALE Locale; /* Intended MIDI locale of this instrument */ + }INSTHEADER, FAR *LPINSTHEADER; + + typedef struct _DLSHEADER { + ULONG cInstruments; /* Count of instruments in the collection */ + }DLSHEADER, FAR *LPDLSHEADER; + + /* + definitions for the Wave link structure + */ + + /***** For level 1 only WAVELINK_CHANNEL_MONO is valid **** + ulChannel allows for up to 32 channels of audio with each bit position + specifiying a channel of playback */ + + #define WAVELINK_CHANNEL_LEFT 0x0001 + #define WAVELINK_CHANNEL_RIGHT 0x0002 + + #define F_WAVELINK_PHASE_MASTER 0x0001 + + typedef struct _WAVELINK { /* any paths or links are stored right after struct */ + USHORT fusOptions; /* options flags for this wave */ + USHORT usPhaseGroup; /* Phase grouping for locking channels */ + ULONG ulChannel; /* channel placement */ + ULONG ulTableIndex; /* index into the wave pool table, 0 based */ + }WAVELINK, FAR *LPWAVELINK; + + #define POOL_CUE_NULL 0xffffffff + + typedef struct _POOLCUE { + // ULONG ulEntryIndex; /* Index entry in the list */ + ULONG ulOffset; /* Offset to the entry in the list */ + }POOLCUE, FAR *LPPOOLCUE; + + typedef struct _POOLTABLE { + ULONG cbSize; /* size of the pool table structure */ + ULONG cCues; /* count of cues in the list */ + } POOLTABLE, FAR *LPPOOLTABLE; + + /* + Structures for the "wsmp" chunk + */ + + #define F_WSMP_NO_TRUNCATION 0x0001 + #define F_WSMP_NO_COMPRESSION 0x0002 + + + typedef struct _rwsmp { + ULONG cbSize; + USHORT usUnityNote; /* MIDI Unity Playback Note */ + SHORT sFineTune; /* Fine Tune in log tuning */ + LONG lAttenuation; /* Overall Attenuation to be applied to data */ + ULONG fulOptions; /* Flag options */ + ULONG cSampleLoops; /* Count of Sample loops, 0 loops is one shot */ + } WSMPL, FAR *LPWSMPL; + + + /* This loop type is a normal forward playing loop which is continually + played until the envelope reaches an off threshold in the release + portion of the volume envelope */ + + #define WLOOP_TYPE_FORWARD 0 + + typedef struct _rloop { + ULONG cbSize; + ULONG ulType; /* Loop Type */ + ULONG ulStart; /* Start of loop in samples */ + ULONG ulLength; /* Length of loop in samples */ + } WLOOP, FAR *LPWLOOP; + + #endif /* _INC_DLS */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/dls2.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/dls2.h new file mode 100755 index 0000000..081557d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/dls2.h @@ -0,0 +1,122 @@ +/* + + dls2.h + + Description: + + Interface defines and structures for the DLS2 extensions of DLS. + + + Written by Microsoft 1998. Released for public use. + +*/ + +#ifndef _INC_DLS2 +#define _INC_DLS2 + +/* + FOURCC's used in the DLS2 file, in addition to DLS1 chunks +*/ + +#define FOURCC_RGN2 mmioFOURCC('r','g','n','2') +#define FOURCC_LAR2 mmioFOURCC('l','a','r','2') +#define FOURCC_ART2 mmioFOURCC('a','r','t','2') +#define FOURCC_CDL mmioFOURCC('c','d','l',' ') +#define FOURCC_DLID mmioFOURCC('d','l','i','d') + +/* + Articulation connection graph definitions. These are in addition to + the definitions in the DLS1 header. +*/ + +/* Generic Sources (in addition to DLS1 sources. */ +#define CONN_SRC_POLYPRESSURE 0x0007 /* Polyphonic Pressure */ +#define CONN_SRC_CHANNELPRESSURE 0x0008 /* Channel Pressure */ +#define CONN_SRC_VIBRATO 0x0009 /* Vibrato LFO */ +#define CONN_SRC_MONOPRESSURE 0x000a /* MIDI Mono pressure */ + + +/* Midi Controllers */ +#define CONN_SRC_CC91 0x00db /* Reverb Send */ +#define CONN_SRC_CC93 0x00dd /* Chorus Send */ + + +/* Generic Destinations */ +#define CONN_DST_GAIN 0x0001 /* Same as CONN_DST_ ATTENUATION, but more appropriate terminology. */ +#define CONN_DST_KEYNUMBER 0x0005 /* Key Number Generator */ + +/* Audio Channel Output Destinations */ +#define CONN_DST_LEFT 0x0010 /* Left Channel Send */ +#define CONN_DST_RIGHT 0x0011 /* Right Channel Send */ +#define CONN_DST_CENTER 0x0012 /* Center Channel Send */ +#define CONN_DST_LEFTREAR 0x0013 /* Left Rear Channel Send */ +#define CONN_DST_RIGHTREAR 0x0014 /* Right Rear Channel Send */ +#define CONN_DST_LFE_CHANNEL 0x0015 /* LFE Channel Send */ +#define CONN_DST_CHORUS 0x0080 /* Chorus Send */ +#define CONN_DST_REVERB 0x0081 /* Reverb Send */ + +/* Vibrato LFO Destinations */ +#define CONN_DST_VIB_FREQUENCY 0x0114 /* Vibrato Frequency */ +#define CONN_DST_VIB_STARTDELAY 0x0115 /* Vibrato Start Delay */ + +/* EG1 Destinations */ +#define CONN_DST_EG1_DELAYTIME 0x020B /* EG1 Delay Time */ +#define CONN_DST_EG1_HOLDTIME 0x020C /* EG1 Hold Time */ +#define CONN_DST_EG1_SHUTDOWNTIME 0x020D /* EG1 Shutdown Time */ + + +/* EG2 Destinations */ +#define CONN_DST_EG2_DELAYTIME 0x030F /* EG2 Delay Time */ +#define CONN_DST_EG2_HOLDTIME 0x0310 /* EG2 Hold Time */ + + +/* Filter Destinations */ +#define CONN_DST_FILTER_CUTOFF 0x0500 /* Filter Cutoff Frequency */ +#define CONN_DST_FILTER_Q 0x0501 /* Filter Resonance */ + + +/* Transforms */ +#define CONN_TRN_CONVEX 0x0002 /* Convex Transform */ +#define CONN_TRN_SWITCH 0x0003 /* Switch Transform */ + + +/* Conditional chunk operators */ + #define DLS_CDL_AND 0x0001 /* X = X & Y */ + #define DLS_CDL_OR 0x0002 /* X = X | Y */ + #define DLS_CDL_XOR 0x0003 /* X = X ^ Y */ + #define DLS_CDL_ADD 0x0004 /* X = X + Y */ + #define DLS_CDL_SUBTRACT 0x0005 /* X = X - Y */ + #define DLS_CDL_MULTIPLY 0x0006 /* X = X * Y */ + #define DLS_CDL_DIVIDE 0x0007 /* X = X / Y */ + #define DLS_CDL_LOGICAL_AND 0x0008 /* X = X && Y */ + #define DLS_CDL_LOGICAL_OR 0x0009 /* X = X || Y */ + #define DLS_CDL_LT 0x000A /* X = (X < Y) */ + #define DLS_CDL_LE 0x000B /* X = (X <= Y) */ + #define DLS_CDL_GT 0x000C /* X = (X > Y) */ + #define DLS_CDL_GE 0x000D /* X = (X >= Y) */ + #define DLS_CDL_EQ 0x000E /* X = (X == Y) */ + #define DLS_CDL_NOT 0x000F /* X = !X */ + #define DLS_CDL_CONST 0x0010 /* 32-bit constant */ + #define DLS_CDL_QUERY 0x0011 /* 32-bit value returned from query */ + #define DLS_CDL_QUERYSUPPORTED 0x0012 /* 32-bit value returned from query */ + +/* + Loop and release +*/ + +#define WLOOP_TYPE_RELEASE 1 + +/* + DLSID queries for +*/ +DEFINE_DLSID(DLSID_GMInHardware, 0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); +DEFINE_DLSID(DLSID_GSInHardware, 0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); +DEFINE_DLSID(DLSID_XGInHardware, 0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); +DEFINE_DLSID(DLSID_SupportsDLS1, 0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); +DEFINE_DLSID(DLSID_SupportsDLS2, 0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6); +DEFINE_DLSID(DLSID_SampleMemorySize, 0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); +DEFINE_DLSID(DLSID_ManufacturersID, 0xb03e1181, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); +DEFINE_DLSID(DLSID_ProductID, 0xb03e1182, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); +DEFINE_DLSID(DLSID_SamplePlaybackRate, 0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); +#endif /* _INC_DLS2 */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_audioconst.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_audioconst.h new file mode 100755 index 0000000..066148e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_audioconst.h @@ -0,0 +1,97 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_audioconst.h + * + * Contents and purpose: + * Defines audio constants related to the sample rate, bit size, etc. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_AUDIOCONST_H +#define _EAS_AUDIOCONST_H + +/*---------------------------------------------------------------------------- + * These macros define the various characteristics of the defined sample rates + *---------------------------------------------------------------------------- + * BUFFER_SIZE_IN_MONO_SAMPLES size of buffer in samples + * _OUTPUT_SAMPLE_RATE compiled output sample rate + * AUDIO_FRAME_LENGTH length of an audio frame in 256ths of a millisecond + * SYNTH_UPDATE_PERIOD_IN_BITS length of an audio frame (2^x samples) + *---------------------------------------------------------------------------- +*/ + +#if defined (_SAMPLE_RATE_8000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 32 +#define _OUTPUT_SAMPLE_RATE 8000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 5 + +#elif defined (_SAMPLE_RATE_16000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 64 +#define _OUTPUT_SAMPLE_RATE 16000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 6 + +#elif defined (_SAMPLE_RATE_20000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 20000 +#define AUDIO_FRAME_LENGTH 1638 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_22050) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 22050 +#define AUDIO_FRAME_LENGTH 1486 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_24000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 24000 +#define AUDIO_FRAME_LENGTH 1365 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_32000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 128 +#define _OUTPUT_SAMPLE_RATE 32000 +#define AUDIO_FRAME_LENGTH 1024 +#define SYNTH_UPDATE_PERIOD_IN_BITS 7 + +#elif defined (_SAMPLE_RATE_44100) +#define BUFFER_SIZE_IN_MONO_SAMPLES 256 +#define _OUTPUT_SAMPLE_RATE 44100 +#define AUDIO_FRAME_LENGTH 1486 +#define SYNTH_UPDATE_PERIOD_IN_BITS 8 + +#elif defined (_SAMPLE_RATE_48000) +#define BUFFER_SIZE_IN_MONO_SAMPLES 256 +#define _OUTPUT_SAMPLE_RATE 48000 +#define AUDIO_FRAME_LENGTH 1365 +#define SYNTH_UPDATE_PERIOD_IN_BITS 8 + +#else +#error "_SAMPLE_RATE_XXXXX must be defined to valid rate" +#endif + +#endif /* #ifndef _EAS_AUDIOCONST_H */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorus.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorus.c new file mode 100755 index 0000000..422eb38 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorus.c @@ -0,0 +1,604 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorus.c + * + * Contents and purpose: + * Contains the implementation of the Chorus effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 499 $ + * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_effects.h" +#include "eas_math.h" +#include "eas_chorusdata.h" +#include "eas_chorus.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" + +/* prototypes for effects interface */ +static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); +static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); +static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + +/* common effects interface for configuration module */ +const S_EFFECTS_INTERFACE EAS_Chorus = +{ + ChorusInit, + ChorusProcess, + ChorusShutdown, + ChorusGetParam, + ChorusSetParam +}; + + + +//LFO shape table used by the chorus, larger table would sound better +//this is a sine wave, where 32767 = 1.0 +static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = { + 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170, + 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728, + 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329, + 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212, + 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519, + -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785, + -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621, + -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010, + -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608 +}; + +/*---------------------------------------------------------------------------- + * InitializeChorus() + *---------------------------------------------------------------------------- + * Purpose: Initializes chorus parameters + * + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) +{ + S_CHORUS_OBJECT *pChorusData; + S_CHORUS_PRESET *pPreset; + EAS_I32 index; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS); + + /* allocate dynamic memory */ + else + pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT)); + + if (pChorusData == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* clear the structure */ + EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT)); + + ChorusReadInPresets(pChorusData); + + /* set some default values */ + pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT; + pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT; + pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT; + pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT; + pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT; + + //chorus rate and depth need some massaging from preset value (which is sample rate independent) + + //convert rate from steps of .05 Hz to value which can be used as phase increment, + //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits + //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate; + //computing it as below allows rate steps to be evenly spaced + //uses 32 bit divide, but only once when new value is selected + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction + //want to compute ((depth * sampleRate)/20000) + //use the following approximation since 105/32 is roughly 65536/20000 + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + pChorusData->m_nLevel = pChorusData->m_nLevel; + + //zero delay memory for chorus + for (index = CHORUS_L_SIZE - 1; index >= 0; index--) + { + pChorusData->chorusDelayL[index] = 0; + } + for (index = CHORUS_R_SIZE - 1; index >= 0; index--) + { + pChorusData->chorusDelayR[index] = 0; + } + + //init delay line index, these are used to implement circular delay buffer + pChorusData->chorusIndexL = 0; + pChorusData->chorusIndexR = 0; + + //init LFO phase + //16 bit whole part, 16 bit fraction + pChorusData->lfoLPhase = 0; + pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase; + + //init chorus delay position + //right now chorus delay is a compile-time value, as is sample rate + pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000); + + //now copy from the new preset into Chorus + pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; + + pChorusData->m_nLevel = pPreset->m_nLevel; + pChorusData->m_nRate = pPreset->m_nRate; + pChorusData->m_nDepth = pPreset->m_nDepth; + + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + *pInstData = pChorusData; + + return EAS_SUCCESS; +} /* end ChorusInit */ + +/*---------------------------------------------------------------------------- + * WeightedTap() + *---------------------------------------------------------------------------- + * Purpose: Does fractional array look-up using linear interpolation + * + * first convert indexDesired to actual desired index by taking into account indexReference + * then do linear interpolation between two actual samples using fractional part + * + * Inputs: + * array: pointer to array of signed 16 bit values, typically either PCM data or control data + * indexReference: the circular buffer relative offset + * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) + * indexLimit: the total size of the array, used to compute buffer wrap + * + * Outputs: + * Value from the input array, linearly interpolated between two actual data values + * + *---------------------------------------------------------------------------- +*/ +EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit) +{ + EAS_I16 index; + EAS_I16 fraction; + EAS_I16 val1; + EAS_I16 val2; + + //separate indexDesired into whole and fractional parts + /*lint -e{704} use shift for performance */ + index = (EAS_I16)(indexDesired >> 16); + /*lint -e{704} use shift for performance */ + fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part + + //adjust whole part by indexReference + index = indexReference - index; + //make sure we stay within array bounds, this implements circular buffer + while (index < 0) + { + index += indexLimit; + } + + //get two adjacent values from the array + val1 = array[index]; + + //handle special case when index == 0, else typical case + if (index == 0) + { + val2 = array[indexLimit-1]; //get last value from array + } + else + { + val2 = array[index-1]; //get previous value from array + } + + //compute linear interpolation as (val1 + ((val2-val1)*fraction)) + return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction)); +} + +/*---------------------------------------------------------------------------- + * ChorusProcess() + *---------------------------------------------------------------------------- + * Purpose: compute the chorus on the input buffer, and mix into output buffer + * + * + * Inputs: + * src: pointer to input buffer of PCM values to be processed + * dst: pointer to output buffer of PCM values we are to sume the result with + * bufSize: the number of sample frames (i.e. stereo samples) in the buffer + * + * Outputs: + * None + * + *---------------------------------------------------------------------------- +*/ +//compute the chorus, and mix into output buffer +static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) +{ + EAS_I32 ix; + EAS_I32 nChannelNumber; + EAS_I16 lfoValueLeft; + EAS_I16 lfoValueRight; + EAS_I32 positionOffsetL; + EAS_I32 positionOffsetR; + EAS_PCM tapL; + EAS_PCM tapR; + EAS_I32 tempValue; + EAS_PCM nInputSample; + EAS_I32 nOutputSample; + EAS_PCM *pIn; + EAS_PCM *pOut; + + S_CHORUS_OBJECT *pChorusData; + + pChorusData = (S_CHORUS_OBJECT*) pInstData; + + //if the chorus is disabled or turned all the way down + if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0) + { + if (pSrc != pDst) + EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); + return; + } + + if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus) + { + ChorusUpdate(pChorusData); + } + + for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++) + { + + pIn = pSrc + nChannelNumber; + pOut = pDst + nChannelNumber; + + if(nChannelNumber==0) + { + for (ix = 0; ix < numSamples; ix++) + { + nInputSample = *pIn; + pIn += NUM_OUTPUT_CHANNELS; + + //feed input into chorus delay line + pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample; + + //compute chorus lfo value using phase as fractional index into chorus shape table + //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number + lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE); + + //scale chorus depth by lfo value to get relative fractional sample index + //index is expressed as 32 bit number with 16 bit fractional part + /*lint -e{703} use shift for performance */ + positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1); + + //add fixed chorus delay to get actual fractional sample index + positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16; + + //get tap value from chorus delay using fractional sample index + tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE); + + //scale by chorus level, then sum with input buffer contents and saturate + tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel); + nOutputSample = SATURATE(tempValue + nInputSample); + + *pOut = (EAS_I16)SATURATE(nOutputSample); + pOut += NUM_OUTPUT_CHANNELS; + + + //increment chorus delay index and make it wrap as needed + //this implements circular buffer + if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE) + pChorusData->chorusIndexL = 0; + + //increment fractional lfo phase, and make it wrap as needed + pChorusData->lfoLPhase += pChorusData->m_nRate; + while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16)) + { + pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16); + } + } + } + else + { + for (ix = 0; ix < numSamples; ix++) + { + nInputSample = *pIn; + pIn += NUM_OUTPUT_CHANNELS; + + //feed input into chorus delay line + pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample; + + //compute chorus lfo value using phase as fractional index into chorus shape table + //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number + lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE); + + //scale chorus depth by lfo value to get relative fractional sample index + //index is expressed as 32 bit number with 16 bit fractional part + /*lint -e{703} use shift for performance */ + positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1); + + //add fixed chorus delay to get actual fractional sample index + positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16; + + //get tap value from chorus delay using fractional sample index + tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE); + + //scale by chorus level, then sum with output buffer contents and saturate + tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel); + nOutputSample = SATURATE(tempValue + nInputSample); + + *pOut = (EAS_I16)SATURATE(nOutputSample); + pOut += NUM_OUTPUT_CHANNELS; + + //increment chorus delay index and make it wrap as needed + //this implements circular buffer + if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE) + pChorusData->chorusIndexR = 0; + + //increment fractional lfo phase, and make it wrap as needed + pChorusData->lfoRPhase += pChorusData->m_nRate; + while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16)) + { + pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16); + } + } + } + + } +} /* end ChorusProcess */ + + + +/*---------------------------------------------------------------------------- + * ChorusShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the Chorus effect. + * + * Inputs: + * pInstData - handle to instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) +{ + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pInstData); + return EAS_SUCCESS; +} /* end ChorusShutdown */ + +/*---------------------------------------------------------------------------- + * ChorusGetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Get a Chorus parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - pointer to variable to hold retrieved value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_CHORUS_OBJECT *p; + + p = (S_CHORUS_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_CHORUS_BYPASS: + *pValue = (EAS_I32) p->bypass; + break; + case EAS_PARAM_CHORUS_PRESET: + *pValue = (EAS_I8) p->m_nCurrentChorus; + break; + case EAS_PARAM_CHORUS_RATE: + *pValue = (EAS_I32) p->m_nRate; + break; + case EAS_PARAM_CHORUS_DEPTH: + *pValue = (EAS_I32) p->m_nDepth; + break; + case EAS_PARAM_CHORUS_LEVEL: + *pValue = (EAS_I32) p->m_nLevel; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ChorusGetParam */ + + +/*---------------------------------------------------------------------------- + * ChorusSetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Set a Chorus parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - new paramter value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_CHORUS_OBJECT *p; + + p = (S_CHORUS_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_CHORUS_BYPASS: + p->bypass = (EAS_BOOL) value; + break; + case EAS_PARAM_CHORUS_PRESET: + if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 && + value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nNextChorus = (EAS_I8)value; + break; + case EAS_PARAM_CHORUS_RATE: + if(valueEAS_CHORUS_RATE_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nRate = (EAS_I16) value; + break; + case EAS_PARAM_CHORUS_DEPTH: + if(valueEAS_CHORUS_DEPTH_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nDepth = (EAS_I16) value; + break; + case EAS_PARAM_CHORUS_LEVEL: + if(valueEAS_CHORUS_LEVEL_MAX) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nLevel = (EAS_I16) value; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ChorusSetParam */ + + +/*---------------------------------------------------------------------------- + * ChorusReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global Chorus preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData) +{ + + int preset = 0; + int defaultPreset = 0; + + //now init any remaining presets to defaults + for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++) + { + S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset]; + if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1) + { + pPreset->m_nDepth = 39; + pPreset->m_nRate = 30; + pPreset->m_nLevel = 32767; + } + else if (defaultPreset == 1) + { + pPreset->m_nDepth = 21; + pPreset->m_nRate = 45; + pPreset->m_nLevel = 25000; + } + else if (defaultPreset == 2) + { + pPreset->m_nDepth = 53; + pPreset->m_nRate = 25; + pPreset->m_nLevel = 32000; + } + else if (defaultPreset == 3) + { + pPreset->m_nDepth = 32; + pPreset->m_nRate = 37; + pPreset->m_nLevel = 29000; + } + } + + return EAS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + * ChorusUpdate + *---------------------------------------------------------------------------- + * Purpose: + * Update the Chorus preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - chorus paramters will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData) +{ + S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; + + pChorusData->m_nLevel = pPreset->m_nLevel; + pChorusData->m_nRate = pPreset->m_nRate; + pChorusData->m_nDepth = pPreset->m_nDepth; + + pChorusData->m_nRate = (EAS_I16) + ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); + + /*lint -e{704} use shift for performance */ + pChorusData->m_nDepth = (EAS_I16) + (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); + + pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus; + + return EAS_SUCCESS; + +} /* end ChorusUpdate */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorusdata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorusdata.c new file mode 100755 index 0000000..ec71ff8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorusdata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorusdata.c + * + * Contents and purpose: + * Contains the static data allocation for the Chorus effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_chorusdata.h" + +S_CHORUS_OBJECT eas_ChorusData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorusdata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorusdata.h new file mode 100755 index 0000000..094dc79 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorusdata.h @@ -0,0 +1,160 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_chorusdata.h + * + * Contents and purpose: + * Contains the prototypes for the Chorus effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 309 $ + * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_CHORUS_H +#define _EAS_CHORUS_H + +#include "eas_types.h" +#include "eas_audioconst.h" + +//defines for chorus + +#define EAS_CHORUS_BYPASS_DEFAULT 1 +#define EAS_CHORUS_PRESET_DEFAULT 0 +#define EAS_CHORUS_RATE_DEFAULT 30 +#define EAS_CHORUS_DEPTH_DEFAULT 39 +#define EAS_CHORUS_LEVEL_DEFAULT 32767 + +#define EAS_CHORUS_LEVEL_MIN 0 +#define EAS_CHORUS_LEVEL_MAX 32767 + +#define EAS_CHORUS_RATE_MIN 10 +#define EAS_CHORUS_RATE_MAX 50 + +#define EAS_CHORUS_DEPTH_MIN 15 +#define EAS_CHORUS_DEPTH_MAX 60 + +#define CHORUS_SIZE_MS 20 +#define CHORUS_L_SIZE ((CHORUS_SIZE_MS*_OUTPUT_SAMPLE_RATE)/1000) +#define CHORUS_R_SIZE CHORUS_L_SIZE +#define CHORUS_SHAPE_SIZE 128 +#define CHORUS_DELAY_MS 10 + +#define CHORUS_MAX_TYPE 4 // any Chorus numbers larger than this are invalid + +typedef struct +{ + EAS_I16 m_nRate; + EAS_I16 m_nDepth; + EAS_I16 m_nLevel; + +} S_CHORUS_PRESET; + +typedef struct +{ + S_CHORUS_PRESET m_sPreset[CHORUS_MAX_TYPE]; //array of presets + +} S_CHORUS_PRESET_BANK; + +/* parameters for each Chorus */ +typedef struct +{ + EAS_I32 lfoLPhase; + EAS_I32 lfoRPhase; + EAS_I16 chorusIndexL; + EAS_I16 chorusIndexR; + EAS_U16 chorusTapPosition; + + EAS_I16 m_nRate; + EAS_I16 m_nDepth; + EAS_I16 m_nLevel; + + //delay lines used by the chorus, longer would sound better + EAS_PCM chorusDelayL[CHORUS_L_SIZE]; + EAS_PCM chorusDelayR[CHORUS_R_SIZE]; + + EAS_BOOL bypass; + EAS_I8 preset; + + EAS_I16 m_nCurrentChorus; // preset number for current Chorus + EAS_I16 m_nNextChorus; // preset number for next Chorus + + S_CHORUS_PRESET pPreset; + + S_CHORUS_PRESET_BANK m_sPreset; + +} S_CHORUS_OBJECT; + + +/*---------------------------------------------------------------------------- + * WeightedTap() + *---------------------------------------------------------------------------- + * Purpose: Does fractional array look-up using linear interpolation + * + * first convert indexDesired to actual desired index by taking into account indexReference + * then do linear interpolation between two actual samples using fractional part + * + * Inputs: + * array: pointer to array of signed 16 bit values, typically either PCM data or control data + * indexReference: the circular buffer relative offset + * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) + * indexLimit: the total size of the array, used to compute buffer wrap + * + * Outputs: + * Value from the input array, linearly interpolated between two actual data values + * + *---------------------------------------------------------------------------- +*/ +EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit); + +/*---------------------------------------------------------------------------- + * ChorusReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global Chorus preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData); + +/*---------------------------------------------------------------------------- + * ChorusUpdate + *---------------------------------------------------------------------------- + * Purpose: + * Update the Chorus preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - chorus paramters will be changed + * - m_nCurrentChorus := m_nNextChorus + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT* pChorusData); + +#endif /* #ifndef _EAS_CHORUSDATA_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ctype.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ctype.h new file mode 100755 index 0000000..14fa96f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ctype.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ctype.h + * + * Contents and purpose: + * This is a replacement for the CRT ctype.h functions. These + * functions are currently ASCII only, but eventually, we will want + * to support wide-characters for localization. + * + * Copyright (c) 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 429 $ + * $Date: 2006-10-19 23:50:15 -0700 (Thu, 19 Oct 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_CTYPE_H +#define _EAS_CTYPE_H + +EAS_INLINE EAS_I8 IsDigit (EAS_I8 c) { return ((c >= '0') && (c <= '9')); } +EAS_INLINE EAS_I8 IsSpace (EAS_I8 c) { return (((c >= 9) && (c <= 13)) || (c == ' ')); } +EAS_INLINE EAS_I8 ToUpper (EAS_I8 c) { if ((c >= 'a') && (c <= 'z')) return c & ~0x20; else return c; } +EAS_INLINE EAS_I8 ToLower (EAS_I8 c) { if ((c >= 'A') && (c <= 'Z')) return c |= 0x20; else return c; } + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_data.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_data.c new file mode 100755 index 0000000..31a4e6a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_data.c @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_data.c + * + * Contents and purpose: + * Contains a data allocation for synthesizer + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" + +// globals +S_EAS_DATA eas_Data; +S_VOICE_MGR eas_Synth; +S_SYNTH eas_MIDI; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_data.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_data.h new file mode 100755 index 0000000..ab724e6 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_data.h @@ -0,0 +1,133 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_data.h + * + * Contents and purpose: + * This header defines all types, to support dynamic allocation of the + * memory resources needed for persistent EAS data. + * + * Copyright 2004 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 842 $ + * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_DATA_H +#define _EAS_DATA_H + +//#define JET_INTERFACE + +#include "eas_types.h" +#include "eas_synthcfg.h" +#include "eas.h" +#include "eas_audioconst.h" +#include "eas_sndlib.h" +#include "eas_pcm.h" +#include "eas_pcmdata.h" +#include "eas_synth.h" +#include "eas_miditypes.h" +#include "eas_effects.h" + +#ifdef AUX_MIXER +#include "eas_auxmixdata.h" +#endif + +#ifdef JET_INTERFACE +#include "jet.h" +#endif + +#ifdef _METRICS_ENABLED +#include "eas_perf.h" +#endif + +#ifndef MAX_NUMBER_STREAMS +#define MAX_NUMBER_STREAMS 4 +#endif + +/* flags for S_EAS_STREAM */ +#define STREAM_FLAGS_PARSED 1 +#define STREAM_FLAGS_PAUSE 2 +#define STREAM_FLAGS_LOCATE 4 +#define STREAM_FLAGS_RESUME 8 + +/* structure for parsing a stream */ +typedef struct s_eas_stream_tag +{ + void *pParserModule; + EAS_U32 time; + EAS_U32 frameLength; + EAS_I32 repeatCount; + EAS_VOID_PTR handle; + EAS_U8 volume; + EAS_BOOL8 streamFlags; +} S_EAS_STREAM; + +/* default master volume is -10dB */ +#define DEFAULT_VOLUME 90 +#define DEFAULT_STREAM_VOLUME 100 +#define DEFAULT_STREAM_GAIN 14622 + +/* 10 dB of boost available for individual parsers */ +#define STREAM_VOLUME_HEADROOM 10 + +/* amalgamated persistent data type */ +typedef struct s_eas_data_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; +#endif + EAS_HW_DATA_HANDLE hwInstData; + + S_EFFECTS_MODULE effectsModules[NUM_EFFECTS_MODULES]; + +#ifdef _METRICS_ENABLED + S_METRICS_INTERFACE *pMetricsModule; + EAS_VOID_PTR pMetricsData; +#endif + + EAS_I32 *pMixBuffer; + EAS_PCM *pOutputAudioBuffer; + +#ifdef AUX_MIXER + S_EAS_AUX_MIXER auxMixer; +#endif + +#ifdef _MAXIMIZER_ENABLED + EAS_VOID_PTR pMaximizerData; +#endif + + S_EAS_STREAM streams[MAX_NUMBER_STREAMS]; + + S_PCM_STATE *pPCMStreams; + + S_VOICE_MGR *pVoiceMgr; + +#ifdef JET_INTERFACE + JET_DATA_HANDLE jetHandle; +#endif + + EAS_U32 renderTime; + EAS_I16 masterGain; + EAS_U8 masterVolume; + EAS_BOOL8 staticMemoryModel; + EAS_BOOL8 searchHeaderFlag; +} S_EAS_DATA; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_dlssynth.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_dlssynth.c new file mode 100755 index 0000000..8606a29 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_dlssynth.c @@ -0,0 +1,578 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_dlssynth.c + * + * Contents and purpose: + * Implements the Mobile DLS synthesizer. + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_math.h" +#include "eas_synth_protos.h" +#include "eas_wtsynth.h" +#include "eas_pan.h" +#include "eas_mdls.h" +#include "eas_dlssynth.h" + +#ifdef _METRICS_ENABLED +#include "eas_perf.h" +#endif + +static void DLS_UpdateEnvelope (S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, const S_DLS_ENVELOPE *pEnvParams, EAS_I16 *pValue, EAS_I16 *pIncrement, EAS_U8 *pState); + +/*---------------------------------------------------------------------------- + * DLS_MuteVoice() + *---------------------------------------------------------------------------- + * Mute the voice using shutdown time from the DLS articulation data + *---------------------------------------------------------------------------- +*/ +void DLS_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + S_WT_VOICE *pWTVoice; + const S_DLS_ARTICULATION *pDLSArt; + + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; + + /* clear deferred action flags */ + pVoice->voiceFlags &= + ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | + VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF | + VOICE_FLAG_DEFER_MUTE); + + /* set the envelope state */ + pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateRelease; + pWTVoice->eg1Increment = pDLSArt->eg1ShutdownTime; + pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateRelease; + pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime; +} + +/*---------------------------------------------------------------------------- + * DLS_ReleaseVoice() + *---------------------------------------------------------------------------- + * Release the selected voice. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoice) standard API, pVoice may be used by other synthesizers */ +void DLS_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + S_WT_VOICE *pWTVoice; + const S_DLS_ARTICULATION *pDLSArt; + + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; + + /* if still in attack phase, convert units to log */ + /*lint -e{732} eg1Value is never negative */ + /*lint -e{703} use shift for performance */ + if (pWTVoice->eg1State == eEnvelopeStateAttack) + pWTVoice->eg1Value = (EAS_I16) ((EAS_flog2(pWTVoice->eg1Value) << 1) + 2048); + + /* release EG1 */ + pWTVoice->eg1State = eEnvelopeStateRelease; + pWTVoice->eg1Increment = pDLSArt->eg1.releaseTime; + + /* release EG2 */ + pWTVoice->eg2State = eEnvelopeStateRelease; + pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime; +} + +/*---------------------------------------------------------------------------- + * DLS_SustainPedal() + *---------------------------------------------------------------------------- + * The sustain pedal was just depressed. If the voice is still + * above the sustain level, catch the voice and continue holding. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pChannel) pChannel reserved for future use */ +void DLS_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) +{ + S_WT_VOICE *pWTVoice; + const S_DLS_ARTICULATION *pDLSArt; + + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; + + /* don't catch the voice if below the sustain level */ + if (pWTVoice->eg1Value < pDLSArt->eg1.sustainLevel) + return; + + /* defer releasing this note until the damper pedal is off */ + pWTVoice->eg1State = eEnvelopeStateDecay; + pVoice->voiceState = eVoiceStatePlay; + pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_SustainPedal: defer note off because sustain pedal is on\n"); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * DLS_UpdatePhaseInc() + *---------------------------------------------------------------------------- + * Calculate the oscillator phase increment for the next frame + *---------------------------------------------------------------------------- +*/ +static EAS_I32 DLS_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents) +{ + EAS_I32 temp; + + /* start with base mod LFO modulation */ + temp = pDLSArt->modLFOToPitch; + + /* add mod wheel effect */ + /*lint -e{702} use shift for performance */ + temp += ((pDLSArt->modLFOCC1ToPitch * pChannel->modWheel) >> 7); + + /* add channel pressure effect */ + /*lint -e{702} use shift for performance */ + temp += ((pDLSArt->modLFOChanPressToPitch * pChannel->channelPressure) >> 7); + + /* add total mod LFO effect */ + pitchCents += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); + + /* start with base vib LFO modulation */ + temp = pDLSArt->vibLFOToPitch; + + /* add mod wheel effect */ + /*lint -e{702} use shift for performance */ + temp += ((pDLSArt->vibLFOCC1ToPitch * pChannel->modWheel) >> 7); + + /* add channel pressure effect */ + /*lint -e{702} use shift for performance */ + temp += ((pDLSArt->vibLFOChanPressToPitch * pChannel->channelPressure) >> 7); + + /* add total vibrato LFO effect */ + pitchCents += FMUL_15x15(temp, pWTVoice->vibLFO.lfoValue); + + /* add EG2 effect */ + pitchCents += FMUL_15x15(pDLSArt->eg2ToPitch, pWTVoice->eg2Value); + + /* convert from cents to linear phase increment */ + return EAS_Calculate2toX(pitchCents); +} + +/*---------------------------------------------------------------------------- + * DLS_UpdateGain() + *---------------------------------------------------------------------------- + * Calculate the gain for the next frame + *---------------------------------------------------------------------------- +*/ +static EAS_I32 DLS_UpdateGain (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain, EAS_U8 velocity) +{ + EAS_I32 temp; + + /* start with base mod LFO modulation */ + temp = pDLSArt->modLFOToGain; + + /* add mod wheel effect */ + /*lint -e{702} use shift for performance */ + temp += ((pDLSArt->modLFOCC1ToGain * pChannel->modWheel) >> 7); + + /* add channel pressure effect */ + /*lint -e{702} use shift for performance */ + temp += ((pDLSArt->modLFOChanPressToGain * pChannel->channelPressure) >> 7); + + /* add total mod LFO effect */ + gain += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); + if (gain > 0) + gain = 0; + + /* convert to linear gain including EG1 */ + if (pWTVoice->eg1State != eEnvelopeStateAttack) + { + gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT; + /*lint -e{702} use shift for performance */ +#if 1 + gain += (pWTVoice->eg1Value - 32767) >> 1; + gain = EAS_LogToLinear16(gain); +#else + gain = EAS_LogToLinear16(gain); + temp = EAS_LogToLinear16((pWTVoice->eg1Value - 32767) >> 1); + gain = FMUL_15x15(gain, temp); +#endif + } + else + { + gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT; + gain = EAS_LogToLinear16(gain); + gain = FMUL_15x15(gain, pWTVoice->eg1Value); + } + + /* include MIDI channel gain */ + gain = FMUL_15x15(gain, pChannel->staticGain); + + /* include velocity */ + if (pDLSArt->filterQandFlags & FLAG_DLS_VELOCITY_SENSITIVE) + { + temp = velocity << 8; + temp = FMUL_15x15(temp, temp); + gain = FMUL_15x15(gain, temp); + } + + /* return gain */ + return gain; +} + +/*---------------------------------------------------------------------------- + * DLS_UpdateFilter() + *---------------------------------------------------------------------------- + * Update the Filter parameters + *---------------------------------------------------------------------------- +*/ +static void DLS_UpdateFilter (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, S_SYNTH_CHANNEL *pChannel, const S_DLS_ARTICULATION *pDLSArt) +{ + EAS_I32 cutoff; + EAS_I32 temp; + + /* no need to calculate filter coefficients if it is bypassed */ + if (pDLSArt->filterCutoff == DEFAULT_DLS_FILTER_CUTOFF_FREQUENCY) + { + pIntFrame->frame.k = 0; + return; + } + + /* start with base cutoff frequency */ + cutoff = pDLSArt->filterCutoff; + + /* get base mod LFO modulation */ + temp = pDLSArt->modLFOToFc; + + /* add mod wheel effect */ + /*lint -e{702} use shift for performance */ + temp += ((pDLSArt->modLFOCC1ToFc * pChannel->modWheel) >> 7); + + /* add channel pressure effect */ + /*lint -e{702} use shift for performance */ + temp += ((pDLSArt->modLFOChanPressToFc* pChannel->channelPressure) >> 7); + + /* add total mod LFO effect */ + cutoff += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); + + /* add EG2 effect */ + cutoff += FMUL_15x15(pWTVoice->eg2Value, pDLSArt->eg2ToFc); + + /* add velocity effect */ + /*lint -e{702} use shift for performance */ + cutoff += (pVoice->velocity * pDLSArt->velToFc) >> 7; + + /* add velocity effect */ + /*lint -e{702} use shift for performance */ + cutoff += (pVoice->note * pDLSArt->keyNumToFc) >> 7; + + /* subtract the A5 offset and the sampling frequency */ + cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS; + + /* limit the cutoff frequency */ + if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS) + cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS; + else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS) + cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS; + + WT_SetFilterCoeffs(pIntFrame, cutoff, pDLSArt->filterQandFlags & FILTER_Q_MASK); +} + +/*---------------------------------------------------------------------------- + * DLS_StartVoice() + *---------------------------------------------------------------------------- + * Start up a DLS voice + *---------------------------------------------------------------------------- +*/ +EAS_RESULT DLS_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) +{ + S_WT_VOICE *pWTVoice; + const S_DLS_REGION *pDLSRegion; + const S_DLS_ARTICULATION *pDLSArt; + S_SYNTH_CHANNEL *pChannel; + +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ } +#endif + + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pChannel = &pSynth->channels[pVoice->channel & 15]; + pDLSRegion = &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK]; + pWTVoice->artIndex = pDLSRegion->wtRegion.artIndex; + pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; + + /* initialize the envelopes */ + pWTVoice->eg1State = eEnvelopeStateInit; + DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); + pWTVoice->eg2State = eEnvelopeStateInit; + DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); + + /* initialize the LFOs */ + pWTVoice->modLFO.lfoValue = 0; + pWTVoice->modLFO.lfoPhase = pDLSArt->modLFO.lfoDelay; + pWTVoice->vibLFO.lfoValue = 0; + pWTVoice->vibLFO.lfoPhase = pDLSArt->vibLFO.lfoDelay; + + /* initalize the envelopes and calculate initial gain */ + DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); + DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); + pVoice->gain = (EAS_I16) DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity); + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_CalcPanControl((EAS_INT) pChannel->pan - 64 + (EAS_INT) pDLSArt->pan, &pWTVoice->gainLeft, &pWTVoice->gainRight); +#endif + + /* initialize the filter states */ + pWTVoice->filter.z1 = 0; + pWTVoice->filter.z2 = 0; + + /* initialize the oscillator */ + pWTVoice->phaseAccum = (EAS_U32) pSynth->pDLS->pDLSSamples + pSynth->pDLS->pDLSSampleOffsets[pDLSRegion->wtRegion.waveIndex]; + if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED) + { + pWTVoice->loopStart = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopStart; + pWTVoice->loopEnd = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopEnd - 1; + } + else + pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pDLS->pDLSSampleLen[pDLSRegion->wtRegion.waveIndex] - 1; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * DLS_UpdateVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize a block of samples for the given voice. + * Use linear interpolation. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL DLS_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples) +{ + S_WT_VOICE *pWTVoice; + S_SYNTH_CHANNEL *pChannel; + const S_DLS_REGION *pDLSRegion; + const S_DLS_ARTICULATION *pDLSArt; + S_WT_INT_FRAME intFrame; + EAS_I32 temp; + EAS_BOOL done = EAS_FALSE; + + /* establish pointers to critical data */ + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pDLSRegion = &pSynth->pDLS->pDLSRegions[pVoice->regionIndex & REGION_INDEX_MASK]; + pChannel = &pSynth->channels[pVoice->channel & 15]; + pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; + + /* update the envelopes */ + DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); + DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); + + /* update the LFOs using the EAS synth function */ + WT_UpdateLFO(&pWTVoice->modLFO, pDLSArt->modLFO.lfoFreq); + WT_UpdateLFO(&pWTVoice->vibLFO, pDLSArt->vibLFO.lfoFreq); + + /* calculate base frequency */ + temp = pDLSArt->tuning + pChannel->staticPitch + pDLSRegion->wtRegion.tuning + + (((EAS_I32) pVoice->note * (EAS_I32) pDLSArt->keyNumToPitch) >> 7); + + /* don't transpose rhythm channel */ + if ((pChannel ->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) == 0) + temp += pSynth->globalTranspose * 100; + + /* calculate phase increment including modulation effects */ + intFrame.frame.phaseIncrement = DLS_UpdatePhaseInc(pWTVoice, pDLSArt, pChannel, temp); + + /* calculate gain including modulation effects */ + intFrame.frame.gainTarget = DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity); + intFrame.prevGain = pVoice->gain; + + DLS_UpdateFilter(pVoice, pWTVoice, &intFrame, pChannel, pDLSArt); + + /* call into engine to generate samples */ + intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer; + intFrame.pMixBuffer = pMixBuffer; + intFrame.numSamples = numSamples; + if (numSamples < 0) + return EAS_FALSE; + + /* check for end of sample */ + if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd)) + done = WT_CheckSampleEnd(pWTVoice, &intFrame, EAS_FALSE); + + WT_ProcessVoice(pWTVoice, &intFrame); + + /* clear flag */ + pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + + /* if the update interval has elapsed, then force the current gain to the next + * gain since we never actually reach the next gain when ramping -- we just get + * very close to the target gain. + */ + pVoice->gain = (EAS_I16) intFrame.frame.gainTarget; + + /* if voice has finished, set flag for voice manager */ + if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted)) + done = EAS_TRUE; + + return done; +} + +/*---------------------------------------------------------------------------- + * DLS_UpdateEnvelope() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize a block of samples for the given voice. + * Use linear interpolation. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pChannel) pChannel not used in this instance */ +static void DLS_UpdateEnvelope (S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, const S_DLS_ENVELOPE *pEnvParams, EAS_I16 *pValue, EAS_I16 *pIncrement, EAS_U8 *pState) +{ + EAS_I32 temp; + + switch (*pState) + { + /* initial state */ + case eEnvelopeStateInit: + *pState = eEnvelopeStateDelay; + *pValue = 0; + *pIncrement = pEnvParams->delayTime; + if (*pIncrement != 0) + return; + /*lint -e{825} falls through to next case */ + + case eEnvelopeStateDelay: + if (*pIncrement) + { + *pIncrement = *pIncrement - 1; + return; + } + + /* calculate attack rate */ + *pState = eEnvelopeStateAttack; + if (pEnvParams->attackTime != ZERO_TIME_IN_CENTS) + { + /*lint -e{702} use shift for performance */ + temp = pEnvParams->attackTime + ((pEnvParams->velToAttack * pVoice->velocity) >> 7); + *pIncrement = ConvertRate(temp); + return; + } + + *pValue = SYNTH_FULL_SCALE_EG1_GAIN; + /*lint -e{825} falls through to next case */ + + case eEnvelopeStateAttack: + if (*pValue < SYNTH_FULL_SCALE_EG1_GAIN) + { + temp = *pValue + *pIncrement; + *pValue = (EAS_I16) (temp < SYNTH_FULL_SCALE_EG1_GAIN ? temp : SYNTH_FULL_SCALE_EG1_GAIN); + return; + } + + /* calculate hold time */ + *pState = eEnvelopeStateHold; + if (pEnvParams->holdTime != ZERO_TIME_IN_CENTS) + { + /*lint -e{702} use shift for performance */ + temp = pEnvParams->holdTime + ((pEnvParams->keyNumToHold * pVoice->note) >> 7); + *pIncrement = ConvertDelay(temp); + return; + } + else + *pIncrement = 0; + /*lint -e{825} falls through to next case */ + + case eEnvelopeStateHold: + if (*pIncrement) + { + *pIncrement = *pIncrement - 1; + return; + } + + /* calculate decay rate */ + *pState = eEnvelopeStateDecay; + if (pEnvParams->decayTime != ZERO_TIME_IN_CENTS) + { + /*lint -e{702} use shift for performance */ + temp = pEnvParams->decayTime + ((pEnvParams->keyNumToDecay * pVoice->note) >> 7); + *pIncrement = ConvertRate(temp); + return; + } + +// *pValue = pEnvParams->sustainLevel; + /*lint -e{825} falls through to next case */ + + case eEnvelopeStateDecay: + if (*pValue > pEnvParams->sustainLevel) + { + temp = *pValue - *pIncrement; + *pValue = (EAS_I16) (temp > pEnvParams->sustainLevel ? temp : pEnvParams->sustainLevel); + return; + } + + *pState = eEnvelopeStateSustain; + *pValue = pEnvParams->sustainLevel; + /*lint -e{825} falls through to next case */ + + case eEnvelopeStateSustain: + return; + + case eEnvelopeStateRelease: + temp = *pValue - *pIncrement; + if (temp <= 0) + { + *pState = eEnvelopeStateMuted; + *pValue = 0; + } + else + *pValue = (EAS_I16) temp; + break; + + case eEnvelopeStateMuted: + *pValue = 0; + return; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Envelope in invalid state %d\n", *pState); */ } + break; + } +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_dlssynth.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_dlssynth.h new file mode 100755 index 0000000..17a635a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_dlssynth.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_dlssynth.h + * + * Contents and purpose: + * Implements the Mobile DLS synthesizer. + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 143 $ + * $Date: 2006-07-17 14:09:35 -0700 (Mon, 17 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_DLSSYNTH_H +#define _EAS_DLSSYNTH_H + +/* prototypes */ +void DLS_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +void DLS_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +void DLS_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); +EAS_RESULT DLS_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); +EAS_BOOL DLS_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_effects.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_effects.h new file mode 100755 index 0000000..86dedac --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_effects.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_effects.h + * + * Contents and purpose: + * Defines a generic effects interface. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_EFFECTS_H +#define _EAS_EFFECTS_H + +#include "eas_types.h" + +typedef struct +{ + EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); + void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_PCM *in, EAS_PCM *out, EAS_I32 numSamples); + EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +} S_EFFECTS_INTERFACE; + +typedef struct +{ + EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); + void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_I32 *in, EAS_I32 *out, EAS_I32 numSamples); + EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +} S_EFFECTS32_INTERFACE; + +/* mixer instance data */ +typedef struct +{ + S_EFFECTS_INTERFACE *effect; + EAS_VOID_PTR effectData; +} S_EFFECTS_MODULE; + +#endif /* end _EAS_EFFECTS_H */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_flog.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_flog.c new file mode 100755 index 0000000..16539f5 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_flog.c @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_flog2.c + * + * Contents and purpose: + * Fixed point square root + * + * + * Copyright (c) 2006 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision$ + * $Date$ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_math.h" + +#define MANTISSA_SHIFT 27 +#define MANTISSA_MASK 0x0000000f +#define MANTISSA_LSB_SHIFT 7 +#define MANTISSA_LSB_MASK 0x000fffff +#define LOG_EXPONENT_SHIFT 10 +#define INTERPOLATION_SHIFT 20 +#define MAX_NEGATIVE (-2147483647-1) + +/* log lookup table */ +static const EAS_U16 eas_log2_table[] = +{ + 0, 90, 174, 254, 330, 402, 470, 536, + 599, 659, 717, 773, 827, 879, 929, 977, + 1024 +}; + +/*---------------------------------------------------------------------------- + * EAS_flog2() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the log2 of a 32-bit fixed point value + * + * Inputs: + * n = value of interest + * + * Outputs: + * returns the log2 of n + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_flog2 (EAS_U32 n) +{ + EAS_U32 exp; + EAS_U32 interp; + + /* check for error condition */ + if (n == 0) + return MAX_NEGATIVE; + + /* find exponent */ + for (exp = 31; exp > 0; exp--) + { + /* shift until we get a 1 bit in bit 31 */ + if ((n & (EAS_U32) MAX_NEGATIVE) != 0) + break; + n <<= 1; + } + /*lint -e{701} use shift for performance */ + exp <<= LOG_EXPONENT_SHIFT; + + /* get the least significant bits for interpolation */ + interp = (n >> MANTISSA_LSB_SHIFT) & MANTISSA_LSB_MASK; + + /* get the most significant bits for mantissa lookup */ + n = (n >> MANTISSA_SHIFT) & MANTISSA_MASK; + + /* interpolate mantissa */ + interp = ((eas_log2_table[n+1] - eas_log2_table[n]) * interp) >> INTERPOLATION_SHIFT; + exp += eas_log2_table[n] + interp; + + return (EAS_I32) exp; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ima_tables.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ima_tables.c new file mode 100755 index 0000000..b03b4d4 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ima_tables.c @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ima_tables.c + * + * Contents and purpose: + * Contains the constant tables for IMA encode/decode + * + * Copyright (c) 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 760 $ + * $Date: 2007-07-17 23:09:36 -0700 (Tue, 17 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" + +/*---------------------------------------------------------------------------- + * ADPCM decode tables + *---------------------------------------------------------------------------- +*/ +const EAS_I16 imaIndexTable[16] = +{ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +const EAS_I16 imaStepSizeTable[89] = +{ + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 +}; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imaadpcm.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imaadpcm.c new file mode 100755 index 0000000..41280b5 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imaadpcm.c @@ -0,0 +1,368 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imaadpcm.c + * + * Contents and purpose: + * Implements the IMA ADPCM decoder + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_host.h" +#include "eas_pcm.h" +#include "eas_math.h" +#include "eas_report.h" + +// #define _DEBUG_IMA_ADPCM_LOCATE + +/*---------------------------------------------------------------------------- + * externs + *---------------------------------------------------------------------------- +*/ +extern const EAS_I16 imaIndexTable[]; +extern const EAS_I16 imaStepSizeTable[]; + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble); +static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); + +/*---------------------------------------------------------------------------- + * IMA ADPCM Decoder interface + *---------------------------------------------------------------------------- +*/ +const S_DECODER_INTERFACE IMADecoder = +{ + IMADecoderInit, + IMADecoderSample, + IMADecoderLocate +}; + +/*---------------------------------------------------------------------------- + * IMADecoderInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the IMA ADPCM decoder + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + pState->decoderL.step = 0; + pState->decoderR.step = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMADecoderSample() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes an IMA ADPCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + EAS_RESULT result; + EAS_I16 sTemp; + + /* if high nibble, decode */ + if (pState->hiNibble) + { + IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte >> 4)); + pState->hiNibble = EAS_FALSE; + } + + /* low nibble, need to fetch another byte */ + else + { + /* check for loop */ + if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) + { + /* seek to start of loop */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) + return result; + pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; + pState->blockCount = 0; + pState->flags &= ~PCM_FLAGS_EMPTY; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMADecoderSample: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } + } + + /* if start of block, fetch new predictor and step index */ + if ((pState->blockSize != 0) && (pState->blockCount == 0) && (pState->bytesLeft != 0)) + { + + /* get predicted sample for left channel */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Predictor: Was %d, now %d\n", pState->decoderL.acc, sTemp); */ } +#endif + pState->decoderL.acc = pState->decoderL.x1 = sTemp; + + /* get step index for left channel - upper 8 bits are reserved */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderL.step, sTemp); */ } +#endif + pState->decoderL.step = sTemp & 0xff; + + if (pState->flags & PCM_FLAGS_STEREO) + { + /* get predicted sample for right channel */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->decoderR.acc = pState->decoderR.x1 = sTemp; + + /* get step index for right channel - upper 8 bits are reserved */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) + return result; +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderR.step, sTemp); */ } +#endif + pState->decoderR.step = sTemp & 0xff; + + pState->blockCount = pState->blockSize - 8; + pState->bytesLeft -= 8; + } + else + { + pState->blockCount = pState->blockSize - 4; + pState->bytesLeft -= 4; + } + } + else + { + + /* get another ADPCM data pair */ + if (pState->bytesLeft) + { + + if ((result = EAS_HWGetByte(pEASData->hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* decode the low nibble */ + pState->bytesLeft--; + pState->blockCount--; + IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte & 0x0f)); + + if (pState->flags & PCM_FLAGS_STEREO) + IMADecoderADPCM(&pState->decoderR, (EAS_U8)(pState->srcByte >> 4)); + else + pState->hiNibble = EAS_TRUE; + } + + /* out of ADPCM data, generate enough samples to fill buffer */ + else + { + pState->decoderL.x1 = pState->decoderL.x0; + pState->decoderR.x1 = pState->decoderR.x0; + } + } + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMADecoderADPCM() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes an IMA ADPCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble) +{ + EAS_INT delta; + EAS_INT stepSize; + + /* get stepsize from table */ + stepSize = imaStepSizeTable[pState->step]; + + /* delta = (abs(delta) + 0.5) * step / 4 */ + delta = 0; + if (nibble & 4) + delta += stepSize; + + if (nibble & 2) + /*lint -e{702} use shift for performance */ + delta += stepSize >> 1; + + if (nibble & 1) + /*lint -e{702} use shift for performance */ + delta += stepSize >> 2; + + /*lint -e{702} use shift for performance */ + delta += stepSize >> 3; + + /* integrate the delta */ + if (nibble & 8) + pState->acc -= delta; + else + pState->acc += delta; + + /* saturate */ + if (pState->acc > 32767) + pState->acc = 32767; + if (pState->acc < -32768) + pState->acc = -32768; + pState->x1 = (EAS_PCM) pState->acc; + + /* compute new step size */ + pState->step += imaIndexTable[nibble]; + if (pState->step < 0) + pState->step = 0; + if (pState->step > 88) + pState->step = 88; + +#ifdef _DEBUG_IMA_ADPCM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "In=%u, Pred=%d, Step=%d\n", nibble, pState->acc, imaStepSizeTable[pState->step]); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * IMADecoderLocate() + *---------------------------------------------------------------------------- + * Locate in an IMA ADPCM stream + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_I32 samplesPerBlock; + EAS_I32 secs, msecs; + + /* no need to calculate if time is zero */ + if (time == 0) + temp = 0; + + /* not zero */ + else + { + + /* can't seek if not a blocked file */ + if (pState->blockSize == 0) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* calculate number of samples per block */ + if (pState->flags & PCM_FLAGS_STEREO) + samplesPerBlock = pState->blockSize - 7; + else + samplesPerBlock = (pState->blockSize << 1) - 7; + + /* break down into secs and msecs */ + secs = time / 1000; + msecs = time - (secs * 1000); + + /* calculate sample number fraction from msecs */ + temp = (msecs * pState->sampleRate); + temp = (temp >> 10) + ((temp * 49) >> 21); + + /* add integer sample count */ + temp += secs * pState->sampleRate; + +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000006 , time, temp); +#endif + + /* for looped samples, calculate position in the loop */ + if ((temp > pState->byteCount) && (pState->loopSamples != 0)) + { + EAS_I32 numBlocks; + EAS_I32 samplesPerLoop; + EAS_I32 samplesInLastBlock; + + numBlocks = (EAS_I32) (pState->loopStart / pState->blockSize); + samplesInLastBlock = (EAS_I32) pState->loopStart - (numBlocks * pState->blockSize); + if (samplesInLastBlock) + { + if (pState->flags & PCM_FLAGS_STEREO) + samplesInLastBlock = samplesInLastBlock - 7; + else + /*lint -e{703} use shift for performance */ + samplesInLastBlock = (samplesInLastBlock << 1) - 7; + } + samplesPerLoop = numBlocks * samplesPerBlock + samplesInLastBlock; + temp = temp % samplesPerLoop; +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000007 , numBlocks, samplesPerLoop, samplesInLastBlock, temp); +#endif + } + + /* find start of block for requested sample */ + temp = (temp / samplesPerBlock) * pState->blockSize; +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000008 , temp); +#endif + + } + + /* seek to new location */ + if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMA_ADPCM_LOCATE + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000009 , pState->bytesLeft); +#endif + + /* reset state */ + pState->blockCount = 0; + pState->hiNibble = EAS_FALSE; + if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) + pState->state = EAS_STATE_READY; + + return EAS_SUCCESS; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelody.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelody.c new file mode 100755 index 0000000..05380e5 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelody.c @@ -0,0 +1,1747 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelody.c + * + * Contents and purpose: + * iMelody parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 797 $ + * $Date: 2007-08-01 00:15:56 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* lint doesn't like the way some string.h files look */ +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#endif + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_imelodydata.h" +#include "eas_ctype.h" + +// #define _DEBUG_IMELODY + +/* increase gain for mono ringtones */ +#define IMELODY_GAIN_OFFSET 8 + +/* length of 32nd note in 1/256ths of a msec for 120 BPM tempo */ +#define DEFAULT_TICK_CONV 16000 +#define TICK_CONVERT 1920000 + +/* default channel and program for iMelody playback */ +#define IMELODY_CHANNEL 0 +#define IMELODY_PROGRAM 80 +#define IMELODY_VEL_MUL 4 +#define IMELODY_VEL_OFS 67 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +static const char* const tokens[] = +{ + "BEGIN:IMELODY", + "VERSION:", + "FORMAT:CLASS", + "NAME:", + "COMPOSER:", + "BEAT:", + "STYLE:", + "VOLUME:", + "MELODY:", + "END:IMELODY" +}; + +/* ledon or ledoff */ +static const char ledStr[] = "edo"; + +/* vibeon or vibeoff */ +static const char vibeStr[] = "ibeo"; + +/* backon or backoff */ +static const char backStr[] = "cko"; + +typedef enum +{ + TOKEN_BEGIN, + TOKEN_VERSION, + TOKEN_FORMAT, + TOKEN_NAME, + TOKEN_COMPOSER, + TOKEN_BEAT, + TOKEN_STYLE, + TOKEN_VOLUME, + TOKEN_MELODY, + TOKEN_END, + TOKEN_INVALID +} ENUM_IMELODY_TOKENS; + +/* lookup table for note values */ +static const EAS_I8 noteTable[] = { 9, 11, 0, 2, 4, 5, 7 }; + +/* inline functions */ +#ifdef _DEBUG_IMELODY +static void PutBackChar (S_IMELODY_DATA *pData) +{ + if (pData->index) + pData->index--; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "PutBackChar '%c'\n", pData->buffer[pData->index]); */ } +} +#else +EAS_INLINE void PutBackChar (S_IMELODY_DATA *pData) { if (pData->index) pData->index--; } +#endif + + +/* local prototypes */ +static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode); +static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration); +static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); +static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader); +static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader); +static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData); +static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader); +static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine); +static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex); + + +/*---------------------------------------------------------------------------- + * + * EAS_iMelody_Parser + * + * This structure contains the functional interface for the iMelody parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_iMelody_Parser = +{ + IMY_CheckFileType, + IMY_Prepare, + IMY_Time, + IMY_Event, + IMY_State, + IMY_Close, + IMY_Reset, + IMY_Pause, + IMY_Resume, + NULL, + IMY_SetData, + IMY_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * IMY_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_IMELODY_DATA* pData; + EAS_I8 buffer[MAX_LINE_SIZE+1]; + EAS_U8 index; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_CheckFileType\n"); */ } +#endif + + /* read the first line of the file */ + *ppHandle = NULL; + if (IMY_ReadLine(pEASData->hwInstData, fileHandle, buffer, NULL) != EAS_SUCCESS) + return EAS_SUCCESS; + + /* check for header string */ + if (IMY_ParseLine(buffer, &index) == TOKEN_BEGIN) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_IMELODY_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_IMELODY_DATA)); + if (!pData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pData, 0, sizeof(S_IMELODY_DATA)); + + /* initialize */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_ERROR; + pData->state = EAS_STATE_OPEN; + + /* return a pointer to the instance data */ + *ppHandle = pData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_Prepare\n"); */ } +#endif + + /* check for valid state */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + /* parse the header */ + if ((result = IMY_ParseHeader(pEASData, pData)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Prepare: state set to EAS_STATE_READY\n"); */ } +#endif + + pData ->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + EAS_I8 c; + EAS_BOOL eof; + EAS_INT temp; + + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + if (pData->state == EAS_STATE_READY) { + pData->state = EAS_STATE_PLAY; + } + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: Reset\n"); */ } +#endif + /* set program to square lead */ + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, IMELODY_PROGRAM); + + /* set channel volume to max */ + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Stopping note %d\n", pData->note); */ } +#endif + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* parse the next event */ + eof = EAS_FALSE; + while (!eof) + { + + /* get next character */ + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + + switch (c) + { + /* start repeat */ + case '(': + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter repeat section\n", c); */ } +#endif + + if (pData->repeatOffset < 0) + { + pData->repeatOffset = pData->startLine + (EAS_I32) pData->index; + + /* save current time and check it later to make sure the loop isn't zero length */ + pData->repeatTime = pData->time; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat offset = %d\n", pData->repeatOffset); */ } +#endif + } + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring nested repeat section\n"); */ } + break; + + /* end repeat */ + case ')': + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "End repeat section, repeat offset = %d\n", pData->repeatOffset); */ } +#endif + /* ignore zero-length loops */ + if (pData->repeatTime == pData->time) { + pData->repeatCount = -1; + pData->repeatOffset = -1; + } else if (pData->repeatCount >= 0) { + + /* decrement repeat count (repeatCount == 0 means infinite loop) */ + if (pData->repeatCount > 0) + { + if (--pData->repeatCount == 0) + { + pData->repeatCount = -1; +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat loop complete\n"); */ } +#endif + } + } + +//2 TEMPORARY FIX: If locating, don't do infinite loops. +//3 We need a different mode for metadata parsing where we don't loop at all + if ((parserMode == eParserModePlay) || (pData->repeatCount != 0)) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Rewinding file for repeat\n"); */ } +#endif + /* rewind to start of loop */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS) + return result; + IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine); + pData->index = 0; + + /* if last loop, prevent future loops */ + if (pData->repeatCount == -1) + pData->repeatOffset = -1; + } + } + break; + + /* repeat count */ + case '@': + if (!IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_FALSE)) + eof = EAS_TRUE; + else if (pData->repeatOffset > 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat count = %dt", pData->repeatCount); */ } +#endif + if (pData->repeatCount < 0) + pData->repeatCount = (EAS_I16) temp; + } + break; + + /* volume */ + case 'V': + if (!IMY_GetVolume(pEASData->hwInstData, pData, EAS_FALSE)) + eof = EAS_TRUE; + break; + + /* flat */ + case '&': + pData->noteModifier = -1; + break; + + /* sharp */ + case '#': + pData->noteModifier = +1; + break; + + /* octave */ + case '*': + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (IsDigit(c)) + pData->octave = (EAS_U8) ((c - '0' + 1) * 12); + else if (!c) + eof = EAS_TRUE; + break; + + /* ledon or ledoff */ + case 'l': + if (!IMY_GetLEDState(pEASData, pData)) + eof = EAS_TRUE; + break; + + /* vibeon or vibeoff */ + case 'v': + if (!IMY_GetVibeState(pEASData, pData)) + eof = EAS_TRUE; + break; + + /* either a B note or backon or backoff */ + case 'b': + if (IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE) == 'a') + { + if (!IMY_GetBackState(pEASData, pData)) + eof = EAS_TRUE; + } + else + { + PutBackChar(pData); + if (IMY_PlayNote(pEASData, pData, c, parserMode)) + return EAS_SUCCESS; + eof = EAS_TRUE; + } + break; + + /* rest */ + case 'r': + case 'R': + if (IMY_PlayRest(pEASData, pData)) + return EAS_SUCCESS; + eof = EAS_TRUE; + break; + + /* EOF */ + case 0: +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: end of iMelody file detected\n"); */ } +#endif + eof = EAS_TRUE; + break; + + /* must be a note */ + default: + c = ToLower(c); + if ((c >= 'a') && (c <= 'g')) + { + if (IMY_PlayNote(pEASData, pData, c, parserMode)) + return EAS_SUCCESS; + eof = EAS_TRUE; + } + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unexpected character '%c' [0x%02x]\n", c, c); */ } + break; + } + } + + /* handle EOF */ +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: state set to EAS_STATE_STOPPING\n"); */ } +#endif + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_IMELODY_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_IMELODY_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + { + pData->state = EAS_STATE_STOPPED; +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_STOPPED\n"); */ } +#endif + } + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_PAUSED\n"); */ } +#endif + pData->state = EAS_STATE_PAUSED; + } + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Close: close file\n"); */ } +#endif + + pData = (S_IMELODY_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA* pData; + EAS_RESULT result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: reset file\n"); */ } +#endif + pData = (S_IMELODY_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + + /* reset time to zero */ + pData->time = 0; + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + if ((result = IMY_ParseHeader (pEASData, pData)) != EAS_SUCCESS) + return result; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: state set to EAS_STATE_ERROR\n"); */ } +#endif + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA *pData; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Pause: pause file\n"); */ } +#endif + + /* can't pause a stopped stream */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_IMELODY_DATA *pData; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Resume: resume file\n"); */ } +#endif + + /* can't resume a stopped stream */ + pData = (S_IMELODY_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Adjust tempo relative to song tempo + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pInstData - pointer to iMelody instance data + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return the file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pInstData - pointer to iMelody instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_IMELODY_DATA *pData; + + pData = (S_IMELODY_DATA*) pInstData; + + switch (param) + { + /* return file type as iMelody */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_IMELODY; + break; + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = IMELODY_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_PlayNote() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode) +{ + EAS_I32 duration; + EAS_U8 velocity; + + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: start note %d\n", note); */ } +#endif + + /* get the duration */ + if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration)) + return EAS_FALSE; + + /* save note value */ + pData->note = (EAS_U8) (pData->octave + noteTable[note - 'a'] + pData->noteModifier); + velocity = (EAS_U8) (pData->volume ? pData->volume * IMELODY_VEL_MUL + IMELODY_VEL_OFS : 0); + + /* start note only if in play mode */ + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, velocity); + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: Start note %d, duration %d\n", pData->note, duration); */ } +#endif + + /* determine note length */ + switch (pData->style) + { + case 0: + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 4; + break; + case 1: + pData->restTicks = 0; + break; + case 2: + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 1; + break; + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "IMY_PlayNote: Note style out of range: %d\n", pData->style); */ } + /*lint -e{704} shift for performance */ + pData->restTicks = duration >> 4; + break; + } + + /* next event is at end of this note */ + pData->time += duration - pData->restTicks; + + /* reset the flat/sharp modifier */ + pData->noteModifier = 0; + + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_PlayRest() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I32 duration; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_PlayRest]n"); */ } +#endif + + /* get the duration */ + if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration)) + return EAS_FALSE; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayRest: note duration %d\n", duration); */ } +#endif + + /* next event is at end of this note */ + pData->time += duration; + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetDuration() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ + +static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration) +{ + EAS_I32 duration; + EAS_I8 c; + + /* get the duration */ + *pDuration = 0; + c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + if ((c < '0') || (c > '5')) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetDuration: error in duration '%c'\n", c); */ } +#endif + return EAS_FALSE; + } + + /* calculate total length of note */ + duration = pData->tick * (1 << ('5' - c)); + + /* check for duration modifier */ + c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE); + if (c) + { + if (c == '.') + /*lint -e{704} shift for performance */ + duration += duration >> 1; + else if (c == ':') + /*lint -e{704} shift for performance */ + duration += (duration >> 1) + (duration >> 2); + else if (c == ';') + /*lint -e{704} shift for performance */ + duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT; + else + PutBackChar(pData); + } + + *pDuration = duration; + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetLEDState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetLEDState\n"); */ } +#endif + + for (i = 0; i < 5; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 3: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED on\n"); */ } +#endif + EAS_HWLED(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 4: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED off\n"); */ } +#endif + EAS_HWLED(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != ledStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetVibeState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVibeState\n"); */ } +#endif + + for (i = 0; i < 6; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 4: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate on\n"); */ } +#endif + EAS_HWVibrate(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 5: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate off\n"); */ } +#endif + EAS_HWVibrate(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != vibeStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetBackState() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) +{ + EAS_I8 c; + EAS_INT i; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetBackState\n"); */ } +#endif + + for (i = 0; i < 5; i++) + { + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); + if (!c) + return EAS_FALSE; + switch (i) + { + case 3: + if (c == 'n') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight on\n"); */ } +#endif + EAS_HWBackLight(pEASData->hwInstData, EAS_TRUE); + return EAS_TRUE; + } + else if (c != 'f') + return EAS_FALSE; + break; + + case 4: + if (c == 'f') + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight off\n"); */ } +#endif + EAS_HWBackLight(pEASData->hwInstData, EAS_FALSE); + return EAS_TRUE; + } + return EAS_FALSE; + + default: + if (c != backStr[i]) + return EAS_FALSE; + break; + } + } + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader) +{ + EAS_INT temp; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVolume\n"); */ } +#endif + + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (c == '+') + { + if (pData->volume < 15) + pData->volume++; + return EAS_TRUE; + } + else if (c == '-') + { + if (pData->volume > 0) + pData->volume--; + return EAS_TRUE; + } + else if (IsDigit(c)) + temp = c - '0'; + else + return EAS_FALSE; + + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (IsDigit(c)) + temp = temp * 10 + c - '0'; + else if (c) + PutBackChar(pData); + if ((temp >= 0) && (temp <= 15)) + { + if (inHeader && (temp == 0)) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring V0 encountered in header\n"); */ } + else + pData->volume = (EAS_U8) temp; + } + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * IMY_GetNumber() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader) +{ + EAS_BOOL ok; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetNumber\n"); */ } +#endif + + *temp = 0; + ok = EAS_FALSE; + for (;;) + { + c = IMY_GetNextChar(hwInstData, pData, inHeader); + if (IsDigit(c)) + { + *temp = *temp * 10 + c - '0'; + ok = EAS_TRUE; + } + else + { + if (c) + PutBackChar(pData); + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNumber: value %d\n", *temp); */ } +#endif + + return ok; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_GetVersion() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL IMY_GetVersion (S_IMELODY_DATA *pData, EAS_INT *pVersion) +{ + EAS_I8 c; + EAS_INT temp; + EAS_INT version; + + version = temp = 0; + for (;;) + { + c = pData->buffer[pData->index++]; + if ((c == 0) || (c == '.')) + { + /*lint -e{701} use shift for performance */ + version = (version << 8) + temp; + if (c == 0) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVersion: version 0x%04x\n", version); */ } +#endif + + *pVersion = version; + return EAS_TRUE; + } + temp = 0; + } + else if (IsDigit(c)) + temp = (temp * 10) + c - '0'; + } +} + +/*---------------------------------------------------------------------------- + * IMY_MetaData() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void IMY_MetaData (S_IMELODY_DATA *pData, E_EAS_METADATA_TYPE metaType, EAS_I8 *buffer) +{ + EAS_I32 len; + + /* check for callback */ + if (!pData->metadata.callback) + return; + + /* copy data to host buffer */ + len = (EAS_I32) strlen((char*) buffer); + if (len >pData->metadata.bufferSize) + len = pData->metadata.bufferSize; + strncpy((char*) pData->metadata.buffer, (char*) buffer, (size_t) len); + pData->metadata.buffer[len] = 0; + + /* callback to host */ + pData->metadata.callback(metaType, pData->metadata.buffer, pData->metadata.pUserData); +} + +/*---------------------------------------------------------------------------- + * IMY_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData) +{ + EAS_RESULT result; + EAS_INT token; + EAS_INT temp; + EAS_I8 c; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_ParseHeader\n"); */ } +#endif + + /* initialize some defaults */ + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->note = 0; + pData->noteModifier = 0; + pData ->restTicks = 0; + pData->volume = 7; + pData->octave = 60; + pData->repeatOffset = -1; + pData->repeatCount = -1; + pData->style = 0; + + /* force the read of the first line */ + pData->index = 1; + + /* read data until we get to melody */ + for (;;) + { + /* read a line from the file and parse the token */ + if (pData->index != 0) + { + if ((result = IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine)) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: IMY_ReadLine returned %d\n", result); */ } +#endif + return result; + } + } + token = IMY_ParseLine(pData->buffer, &pData->index); + + switch (token) + { + /* ignore these valid tokens */ + case TOKEN_BEGIN: + break; + + case TOKEN_FORMAT: + if (!IMY_GetVersion(pData, &temp)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid FORMAT field '%s'\n", pData->buffer); */ } + return EAS_ERROR_FILE_FORMAT; + } + if ((temp != 0x0100) && (temp != 0x0200)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported FORMAT %02x\n", temp); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + break; + + case TOKEN_VERSION: + if (!IMY_GetVersion(pData, &temp)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid VERSION field '%s'\n", pData->buffer); */ } + return EAS_ERROR_FILE_FORMAT; + } + if ((temp != 0x0100) && (temp != 0x0102)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported VERSION %02x\n", temp); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + break; + + case TOKEN_NAME: + IMY_MetaData(pData, EAS_METADATA_TITLE, pData->buffer + pData->index); + break; + + case TOKEN_COMPOSER: + IMY_MetaData(pData, EAS_METADATA_AUTHOR, pData->buffer + pData->index); + break; + + /* handle beat */ + case TOKEN_BEAT: + IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_TRUE); + if ((temp >= 25) && (temp <= 900)) + pData->tick = TICK_CONVERT / temp; + break; + + /* handle style */ + case TOKEN_STYLE: + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if (c == 'S') + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if ((c >= '0') && (c <= '2')) + pData->style = (EAS_U8) (c - '0'); + else + { + PutBackChar(pData); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in style command: %s\n", pData->buffer); */ } + } + break; + + /* handle volume */ + case TOKEN_VOLUME: + c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); + if (c != 'V') + { + PutBackChar(pData); + if (!IsDigit(c)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in volume command: %s\n", pData->buffer); */ } + break; + } + } + IMY_GetVolume(pEASData->hwInstData, pData, EAS_TRUE); + break; + + case TOKEN_MELODY: +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Header successfully parsed\n"); */ } +#endif + return EAS_SUCCESS; + + case TOKEN_END: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unexpected END:IMELODY encountered\n"); */ } + return EAS_ERROR_FILE_FORMAT; + + default: + /* force a read of the next line */ + pData->index = 1; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized token in iMelody file: %s\n", pData->buffer); */ } + break; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_GetNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader) +{ + EAS_I8 c; + EAS_U8 index; + + for (;;) + { + /* get next character */ + c = pData->buffer[pData->index++]; + + /* buffer empty, read more */ + if (!c) + { + /* don't read the next line in the header */ + if (inHeader) + return 0; + + pData->index = 0; + pData->buffer[0] = 0; + if (IMY_ReadLine(hwInstData, pData->fileHandle, pData->buffer, &pData->startLine) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: EOF\n"); */ } +#endif + return 0; + } + + /* check for END:IMELODY token */ + if (IMY_ParseLine(pData->buffer, &index) == TOKEN_END) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: found END:IMELODY\n"); */ } +#endif + pData->buffer[0] = 0; + return 0; + } + continue; + } + + /* ignore white space */ + if (!IsSpace(c)) + { + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar returned '%c'\n", c); */ } +#endif + return c; + } + } +} + +/*---------------------------------------------------------------------------- + * IMY_ReadLine() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a line of input from the file, discarding the CR/LF + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine) +{ + EAS_RESULT result; + EAS_INT i; + EAS_I8 c; + + /* fetch current file position and save it */ + if (pStartLine != NULL) + { + if ((result = EAS_HWFilePos(hwInstData, fileHandle, pStartLine)) != EAS_SUCCESS) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: EAS_HWFilePos returned %d\n", result); */ } +#endif + return result; + } + } + + buffer[0] = 0; + for (i = 0; i < MAX_LINE_SIZE; ) + { + if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) + { + if ((result == EAS_EOF) && (i > 0)) + break; + return result; + } + + /* return on LF or end of data */ + if (c == '\n') + break; + + /* store characters in buffer */ + if (c != '\r') + buffer[i++] = c; + } + buffer[i] = 0; + +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ReadLine read %s\n", buffer); */ } +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * IMY_ParseLine() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex) +{ + EAS_INT i; + EAS_INT j; + + /* there's no strnicmp() in stdlib, so we have to roll our own */ + for (i = 0; i < TOKEN_INVALID; i++) + { + for (j = 0; ; j++) + { + /* end of token, must be a match */ + if (tokens[i][j] == 0) + { +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine found token %d\n", i); */ } +#endif + *pIndex = (EAS_U8) j; + return i; + } + if (tokens[i][j] != ToUpper(buffer[j])) + break; + } + } +#ifdef _DEBUG_IMELODY + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine: no token found\n"); */ } +#endif + return TOKEN_INVALID; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelodydata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelodydata.c new file mode 100755 index 0000000..9437e08 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelodydata.c @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelodydata.c + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_imelodydata.h" + +/*---------------------------------------------------------------------------- + * + * eas_iMelodyData + * + * Static memory allocation for iMelody parser + *---------------------------------------------------------------------------- +*/ +S_IMELODY_DATA eas_iMelodyData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelodydata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelodydata.h new file mode 100755 index 0000000..17d03dc --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelodydata.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_imelodydata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data declarations for the iMelody parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_IMELODYDATA_H +#define EAS_IMELODYDATA_H + +#include "eas_data.h" + +/* maximum line size as specified in iMelody V1.2 spec */ +#define MAX_LINE_SIZE 75 + +/*---------------------------------------------------------------------------- + * + * S_IMELODY_DATA + * + * This structure contains the state data for the iMelody parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* pointer to synth */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_I32 tickBase; /* basline length of 32nd note in 256th of a msec */ + EAS_I32 tick; /* actual length of 32nd note in 256th of a msec */ + EAS_I32 restTicks; /* ticks to rest after current note */ + EAS_I32 startLine; /* file offset at start of line (for repeats) */ + EAS_I32 repeatOffset; /* file offset to start of repeat section */ + EAS_I32 repeatTime; /* time at start of repeat section */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I16 repeatCount; /* repeat counter */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 style; /* from STYLE */ + EAS_U8 index; /* index into buffer */ + EAS_U8 octave; /* octave prefix */ + EAS_U8 volume; /* current volume */ + EAS_U8 note; /* MIDI note number */ + EAS_I8 noteModifier; /* sharp or flat */ + EAS_I8 buffer[MAX_LINE_SIZE+1]; /* buffer for ASCII data */ +} S_IMELODY_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_math.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_math.c new file mode 100755 index 0000000..ac22d26 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_math.c @@ -0,0 +1,168 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_math.c + * + * Contents and purpose: + * Contains common math routines for the various audio engines. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 586 $ + * $Date: 2007-03-08 20:33:04 -0800 (Thu, 08 Mar 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas.h" +#include "eas_math.h" + +/* anything less than this converts to a fraction too small to represent in 32-bits */ +#define MIN_CENTS -18000 + +/*---------------------------------------------------------------------------- + * EAS_Calculate2toX() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate 2^x + * + * Inputs: + * nCents - measured in cents + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_Calculate2toX (EAS_I32 nCents) +{ + EAS_I32 nDents; + EAS_I32 nExponentInt, nExponentFrac; + EAS_I32 nTemp1, nTemp2; + EAS_I32 nResult; + + /* check for minimum value */ + if (nCents < MIN_CENTS) + return 0; + + /* for the time being, convert cents to dents */ + nDents = FMUL_15x15(nCents, CENTS_TO_DENTS); + + nExponentInt = GET_DENTS_INT_PART(nDents); + nExponentFrac = GET_DENTS_FRAC_PART(nDents); + + /* + implement 2^(fracPart) as a power series + */ + nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3); + nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1); + nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2); + + /* + implement 2^(intPart) as + a left shift for intPart >= 0 or + a left shift for intPart < 0 + */ + if (nExponentInt >= 0) + { + /* left shift for positive exponents */ + /*lint -e{703} */ + nResult = nTemp1 << nExponentInt; + } + else + { + /* right shift for negative exponents */ + nExponentInt = -nExponentInt; + nResult = nTemp1 >> nExponentInt; + } + + return nResult; +} + +/*---------------------------------------------------------------------------- + * EAS_LogToLinear16() + *---------------------------------------------------------------------------- + * Purpose: + * Transform log value to linear gain multiplier using piece-wise linear + * approximation + * + * Inputs: + * nGain - log scale value in 20.10 format. Even though gain is normally + * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate + * the need for saturation checking when combining gain values. + * + * Outputs: + * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain) +{ + EAS_LONG nExp; + EAS_U16 nTemp; + + /* bias to positive */ + nGain += 32767; + + /* check for infinite attenuation */ + if (nGain < 0) + return 0; + + /* extract the exponent */ + nExp = (int)(31 - (nGain >> 10)); + + /* check for maximum output */ + if (nExp < 0) + return 0x7fff; + + /* extract mantissa and restore implied 1 bit */ + nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp); + + /* use shift to approximate power-of-2 operation */ + return nTemp; +} + +/*---------------------------------------------------------------------------- + * EAS_VolumeToGain() + *---------------------------------------------------------------------------- + * Purpose: + * Transform volume control in 1dB increments to gain multiplier + * + * Inputs: + * volume - 100 = 0dB, 99 = -1dB, 0 = -inf + * + * Outputs: + * Returns a 16-bit linear value + *---------------------------------------------------------------------------- +*/ +EAS_I16 EAS_VolumeToGain (EAS_INT volume) +{ + /* check for limits */ + if (volume <= 0) + return 0; + if (volume >= 100) + return 0x7fff; + + /*lint -e{702} use shift instead of division */ + return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1); +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_math.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_math.h new file mode 100755 index 0000000..f240b51 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_math.h @@ -0,0 +1,412 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_math.h + * + * Contents and purpose: + * Contains common math routines for the various audio engines. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 584 $ + * $Date: 2007-03-08 09:49:24 -0800 (Thu, 08 Mar 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MATH_H +#define _EAS_MATH_H + + +/** coefs for pan, generates sin, cos */ +#define COEFF_PAN_G2 -27146 /* -0.82842712474619 = 2 - 4/sqrt(2) */ +#define COEFF_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ + +/* +coefficients for approximating +2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3 +where x is a int.frac number representing number of octaves. +Actually, we approximate only the 2^(frac) using the power series +and implement the 2^(int) as a shift, so that +2^x == 2^(int.frac) == 2^(int) * 2^(fract) + == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int) + +The gn2toX.. were generated using a best fit for a 3rd +order polynomial, instead of taking the coefficients from +a truncated Taylor (or Maclaurin?) series. +*/ + +#define GN2_TO_X0 32768 /* 1 */ +#define GN2_TO_X1 22833 /* 0.696807861328125 */ +#define GN2_TO_X2 7344 /* 0.22412109375 */ +#define GN2_TO_X3 2588 /* 0.0789794921875 */ + +/*---------------------------------------------------------------------------- + * Fixed Point Math + *---------------------------------------------------------------------------- + * These macros are used for fixed point multiplies. If the processor + * supports fixed point multiplies, replace these macros with inline + * assembly code to improve performance. + *---------------------------------------------------------------------------- +*/ + +/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */ +#define FMUL_15x15(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b)) >> 15) + +/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */ +#define FMUL_7x7(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b) ) << 1) + +/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */ +#define FMUL_8x8(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)(a) * (EAS_I32)(b) ) >> 1) + +/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */ +#define FMUL_8x15(a,b) \ + /*lint -e(704) */ \ + (((EAS_I32)((a) << 7) * (EAS_I32)(b)) >> 15) + +/* macros for fractional phase accumulator */ +/* +Note: changed the _U32 to _I32 on 03/14/02. This should not +affect the phase calculations, and should allow us to reuse these +macros for other audio sample related math. +*/ +#define HARDWARE_BIT_WIDTH 32 + +#define NUM_PHASE_INT_BITS 1 +#define NUM_PHASE_FRAC_BITS 15 + +#define PHASE_FRAC_MASK (EAS_U32) ((0x1L << NUM_PHASE_FRAC_BITS) -1) + +#define GET_PHASE_INT_PART(x) (EAS_U32)((EAS_U32)(x) >> NUM_PHASE_FRAC_BITS) +#define GET_PHASE_FRAC_PART(x) (EAS_U32)((EAS_U32)(x) & PHASE_FRAC_MASK) + +#define DEFAULT_PHASE_FRAC 0 +#define DEFAULT_PHASE_INT 0 + +/* +Linear interpolation calculates: +output = (1-frac) * sample[n] + (frac) * sample[n+1] + +where conceptually 0 <= frac < 1 + +For a fixed point implementation, frac is actually an integer value +with an implied binary point one position to the left. The value of +one (unity) is given by PHASE_ONE +one half and one quarter are useful for 4-point linear interp. +*/ +#define PHASE_ONE (EAS_I32) (0x1L << NUM_PHASE_FRAC_BITS) + +/* + Multiply the signed audio sample by the unsigned fraction. +- a is the signed audio sample +- b is the unsigned fraction (cast to signed int as long as coef + uses (n-1) or less bits, where n == hardware bit width) +*/ +#define MULT_AUDIO_COEF(audio,coef) /*lint -e704 */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_PHASE_FRAC_BITS \ + ) \ + /* lint +704 */ + +/* wet / dry calculation macros */ +#define NUM_WET_DRY_FRAC_BITS 7 // 15 +#define NUM_WET_DRY_INT_BITS 9 // 1 + +/* define a 1.0 */ +#define WET_DRY_ONE (EAS_I32) ((0x1L << NUM_WET_DRY_FRAC_BITS)) +#define WET_DRY_MINUS_ONE (EAS_I32) (~WET_DRY_ONE) +#define WET_DRY_FULL_SCALE (EAS_I32) (WET_DRY_ONE - 1) + +#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_WET_DRY_FRAC_BITS \ + ) + +/* Envelope 1 (EG1) calculation macros */ +#define NUM_EG1_INT_BITS 1 +#define NUM_EG1_FRAC_BITS 15 + +/* the max positive gain used in the synth for EG1 */ +/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas +converter, otherwise, the values we read from the .eas file are bogus. */ +#define SYNTH_FULL_SCALE_EG1_GAIN (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS) -1) + +/* define a 1.0 */ +#define EG1_ONE (EAS_I32) ((0x1L << NUM_EG1_FRAC_BITS)) +#define EG1_MINUS_ONE (EAS_I32) (~SYNTH_FULL_SCALE_EG1_GAIN) + +#define EG1_HALF (EAS_I32) (EG1_ONE/2) +#define EG1_MINUS_HALF (EAS_I32) (EG1_MINUS_ONE/2) + +/* +We implement the EG1 using a linear gain value, which means that the +attack segment is handled by incrementing (adding) the linear gain. +However, EG1 treats the Decay, Sustain, and Release differently than +the Attack portion. For Decay, Sustain, and Release, the gain is +linear on dB scale, which is equivalent to exponential damping on +a linear scale. Because we use a linear gain for EG1, we implement +the Decay and Release as multiplication (instead of incrementing +as we did for the attack segment). +Therefore, we need the following macro to implement the multiplication +(i.e., exponential damping) during the Decay and Release segments of +the EG1 +*/ +#define MULT_EG1_EG1(gain,damping) /*lint -e(704) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \ + ) \ + >> NUM_EG1_FRAC_BITS \ + ) + +// Use the following macro specifically for the filter, when multiplying +// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow +// in certain conditions because we store b1 as a 1.15 value. +// Instead, we could store b1 as b1p (b1' == b1 "prime") where +// b1p == b1/2, thus ensuring no potential overflow for b1p because +// 0 <= |b1p| < 1 +// However, during the filter calculation, we must account for the fact +// that we are using b1p instead of b1, and thereby multiply by +// an extra factor of 2. Rather than multiply by an extra factor of 2, +// we can instead shift the result right by one less, hence the +// modified shift right value of (NUM_EG1_FRAC_BITS -1) +#define MULT_EG1_EG1_X2(gain,damping) /*lint -e(702) */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(gain)) * ((EAS_I32)(damping)) \ + ) \ + >> (NUM_EG1_FRAC_BITS -1) \ + ) + +#define SATURATE_EG1(x) /*lint -e{734} saturation operation */ \ + ((EAS_I32)(x) > SYNTH_FULL_SCALE_EG1_GAIN) ? (SYNTH_FULL_SCALE_EG1_GAIN) : \ + ((EAS_I32)(x) < EG1_MINUS_ONE) ? (EG1_MINUS_ONE) : (x); + + +/* use "digital cents" == "dents" instead of cents */ +/* we coudl re-use the phase frac macros, but if we do, +we must change the phase macros to cast to _I32 instead of _U32, +because using a _U32 cast causes problems when shifting the exponent +for the 2^x calculation, because right shift a negative values MUST +be sign extended, or else the 2^x calculation is wrong */ + +/* use "digital cents" == "dents" instead of cents */ +#define NUM_DENTS_FRAC_BITS 12 +#define NUM_DENTS_INT_BITS (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS) + +#define DENTS_FRAC_MASK (EAS_I32) ((0x1L << NUM_DENTS_FRAC_BITS) -1) + +#define GET_DENTS_INT_PART(x) /*lint -e(704) */ \ + (EAS_I32)((EAS_I32)(x) >> NUM_DENTS_FRAC_BITS) + +#define GET_DENTS_FRAC_PART(x) (EAS_I32)((EAS_I32)(x) & DENTS_FRAC_MASK) + +#define DENTS_ONE (EAS_I32) (0x1L << NUM_DENTS_FRAC_BITS) + +/* use CENTS_TO_DENTS to convert a value in cents to dents */ +#define CENTS_TO_DENTS (EAS_I32) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L) \ + + +/* +For gain, the LFO generates a value that modulates in terms +of dB. However, we use a linear gain value, so we must convert +the LFO value in dB to a linear gain. Normally, we would use +linear gain = 10^x, where x = LFO value in dB / 20. +Instead, we implement 10^x using our 2^x approximation. +because + + 10^x = 2^(log2(10^x)) = 2^(x * log2(10)) + +so we need to multiply by log2(10) which is just a constant. +Ah, but just wait -- our 2^x actually doesn't exactly implement +2^x, but it actually assumes that the input is in cents, and within +the 2^x approximation converts its input from cents to octaves +by dividing its input by 1200. + +So, in order to convert the LFO gain value in dB to something +that our existing 2^x approximation can use, multiply the LFO gain +by log2(10) * 1200 / 20 + +The divide by 20 helps convert dB to linear gain, and we might +as well incorporate that operation into this conversion. +Of course, we need to keep some fractional bits, so multiply +the constant by NUM_EG1_FRAC_BITS +*/ + +/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */ +#if 0 +#define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */ + +#define DOUBLE_LFO_GAIN_TO_CENTS (double) \ + ( \ + (DOUBLE_LOG2_10) * \ + 1200.0 / \ + 20.0 \ + ) + +#define LFO_GAIN_TO_CENTS (EAS_I32) \ + ( \ + DOUBLE_LFO_GAIN_TO_CENTS * \ + (0x1L << NUM_EG1_FRAC_BITS) \ + ) +#endif + +#define LFO_GAIN_TO_CENTS (EAS_I32) (1671981156L >> (23 - NUM_EG1_FRAC_BITS)) + + +#define MULT_DENTS_COEF(dents,coef) /*lint -e704 */ \ + (EAS_I32)( \ + ( \ + ((EAS_I32)(dents)) * ((EAS_I32)(coef)) \ + ) \ + >> NUM_DENTS_FRAC_BITS \ + ) \ + /* lint +e704 */ + +/* we use 16-bits in the PC per audio sample */ +#define BITS_PER_AUDIO_SAMPLE 16 + +/* we define 1 as 1.0 - 1 LSbit */ +#define DISTORTION_ONE (EAS_I32)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1) +#define DISTORTION_MINUS_ONE (EAS_I32)(~DISTORTION_ONE) + +/* drive coef is given as int.frac */ +#define NUM_DRIVE_COEF_INT_BITS 1 +#define NUM_DRIVE_COEF_FRAC_BITS 4 + +#define MULT_AUDIO_DRIVE(audio,drive) /*lint -e(702) */ \ + (EAS_I32) ( \ + ( \ + ((EAS_I32)(audio)) * ((EAS_I32)(drive)) \ + ) \ + >> NUM_DRIVE_COEF_FRAC_BITS \ + ) + +#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) */ \ + (EAS_I32) ( \ + ( \ + ((EAS_I32)(audio1)) * ((EAS_I32)(audio2)) \ + ) \ + >> (BITS_PER_AUDIO_SAMPLE-1) \ + ) + +#define SATURATE(x) \ + ((((EAS_I32)(x)) > DISTORTION_ONE) ? (DISTORTION_ONE) : \ + (((EAS_I32)(x)) < DISTORTION_MINUS_ONE) ? (DISTORTION_MINUS_ONE) : ((EAS_I32)(x))); + + + +/*---------------------------------------------------------------------------- + * EAS_Calculate2toX() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate 2^x + * + * Inputs: + * nCents - measured in cents + * + * Outputs: + * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_Calculate2toX (EAS_I32 nCents); + +/*---------------------------------------------------------------------------- + * EAS_LogToLinear16() + *---------------------------------------------------------------------------- + * Purpose: + * Transform log value to linear gain multiplier using piece-wise linear + * approximation + * + * Inputs: + * nGain - log scale value in 20.10 format. Even though gain is normally + * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate + * the need for saturation checking when combining gain values. + * + * Outputs: + * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain); + +/*---------------------------------------------------------------------------- + * EAS_VolumeToGain() + *---------------------------------------------------------------------------- + * Purpose: + * Transform volume control in 1dB increments to gain multiplier + * + * Inputs: + * volume - 100 = 0dB, 99 = -1dB, 0 = -inf + * + * Outputs: + * Returns a 16-bit linear value + *---------------------------------------------------------------------------- +*/ +EAS_I16 EAS_VolumeToGain (EAS_INT volume); + +/*---------------------------------------------------------------------------- + * EAS_fsqrt() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the square root of a 32-bit fixed point value + * + * Inputs: + * n = value of interest + * + * Outputs: + * returns the square root of n + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 EAS_fsqrt (EAS_U32 n); + +/*---------------------------------------------------------------------------- + * EAS_flog2() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the log2 of a 32-bit fixed point value + * + * Inputs: + * n = value of interest + * + * Outputs: + * returns the log2 of n + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_flog2 (EAS_U32 n); + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mdls.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mdls.c new file mode 100755 index 0000000..3948a85 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mdls.c @@ -0,0 +1,2668 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mdls.c + * + * Contents and purpose: + * This file contains DLS to EAS converter. + * + * Copyright (c) 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 818 $ + * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* + * NOTES: + * + * Processor Endian-ness: + * + * We use the EAS_HWGetDWord() and EAS_HWGetWord () functions + * extensively in this module. It would probably be faster to read + * an entire data structure, but this introduces the problem of + * sensitivity to processor endian-ness to the parser. By utlilizing + * the host wrapper functions, we avoid having to flip bytes around + * for big-endian processors. The default host wrapper versions of + * these functions are insensitive to processor endian-ness due to + * the fact that they read the file as a byte stream. + * + * Dynamic Memory: + * + * Dynamic memory allocation is a risky proposition in a mobile + * device. The memory can become fragmented, resulting in an + * inability to allocate a memory block, or garbage collection + * routines can use many CPU cycles. Either can contribute to + * failures of critical systems. Therefore, we try to minimize the + * number of memory allocations we make. + * + * We allocate a single large block of memory for the entire + * converted DLS collection, including the articulation data and + * samples. This block is then sub-allocated for the various + * data structures. + * + * Parser Overview: + * + * We make two passes through the file, the first pass to count the + * number of instruments, regions, etc. and allocate memory for + * them. The second pass parses the data into the allocated data + * structures. + * + * Conditional chunks are challenging in that they can occur + * anywhere in the list chunk that contains them. To simplify, we + * parse the blocks in a list in specific order, no matter which + * order they appear in the file. This way we don't allocate memory + * and parse a block that we end up throwing away later due to + * a conditional chunk. + * + * Assumptions that may bite us in the future: + * + * We make some assumptions to simplify things. The most fundamental + * assumption is that there will be no more than one of any type of + * chunk in a list. While this is consistent with the block diagram + * of the file layout in the mDLS spec, there is nothing in the + * spec that precludes having mulitple lar2 or rgn2 chunks, with + * conditional blocks that dictate their usage. + * + * DLS -> EAS Conversion Process: + * + * Another challenge is that the DLS structure does not map well to + * the current EAS sound library structure. Not all DLS constructs + * are supported, and data from DLS structures must sometimes be + * mapped to multiple EAS data structures. To simplify the process, + * the EAS region, articulation, and envelopes are treated as a + * single combined unit. Thus for each region, there must be one + * articulation element and two envelope elements. + * + * The sample processing is also a multi-step process. First the + * ptbl chunk is pre-parsed to determine the number of samples + * in the collection. The next step is to parse the instrument data + * to determine which samples are actually used by instruments. + * Some samples may not be used because they are used only in + * conditional blocks that the synthesizer cannot parse, or the + * author neglected to remove unused samples from the collection. + * In the next step, the active samples are read into memory and + * converted to the appropriate playback format. Finally, as the + * instruments are processed, the links are made to the samples and + * wsmp data is extracted for the region and articulation data + * structures. +*/ + +#ifndef _FILTER_ENABLED +#error "Filter must be enabled if DLS_SYNTHESIZER is enabled" +#endif + +/*------------------------------------ + * includes + *------------------------------------ +*/ + +/* this define allows us to use the sndlib.h structures as RW memory */ +#define SCNST + +#include "eas_data.h" +#include "eas_host.h" +#include "eas_mdls.h" +#include "eas_math.h" +#include "dls.h" +#include "dls2.h" +#include "eas_report.h" + +//2 we should replace log10() function with fixed point routine in ConvertSampleRate() +/* lint is choking on the ARM math.h file, so we declare the log10 function here */ +extern double log10(double x); + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +// #define _DEBUG_DLS + +#define DLS_MAX_WAVE_COUNT 1024 +#define DLS_MAX_ART_COUNT 2048 +#define DLS_MAX_REGION_COUNT 2048 +#define DLS_MAX_INST_COUNT 256 +#define MAX_DLS_WAVE_SIZE (1024*1024) + +/*------------------------------------ + * typedefs + *------------------------------------ +*/ + +/* offsets to articulation data */ +typedef enum +{ + PARAM_MODIFIED = 0, + PARAM_MOD_LFO_FREQ, + PARAM_MOD_LFO_DELAY, + + PARAM_VIB_LFO_FREQ, + PARAM_VIB_LFO_DELAY, + + PARAM_VOL_EG_DELAY, + PARAM_VOL_EG_ATTACK, + PARAM_VOL_EG_HOLD, + PARAM_VOL_EG_DECAY, + PARAM_VOL_EG_SUSTAIN, + PARAM_VOL_EG_RELEASE, + PARAM_VOL_EG_SHUTDOWN, + PARAM_VOL_EG_VEL_TO_ATTACK, + PARAM_VOL_EG_KEY_TO_DECAY, + PARAM_VOL_EG_KEY_TO_HOLD, + + PARAM_MOD_EG_DELAY, + PARAM_MOD_EG_ATTACK, + PARAM_MOD_EG_HOLD, + PARAM_MOD_EG_DECAY, + PARAM_MOD_EG_SUSTAIN, + PARAM_MOD_EG_RELEASE, + PARAM_MOD_EG_VEL_TO_ATTACK, + PARAM_MOD_EG_KEY_TO_DECAY, + PARAM_MOD_EG_KEY_TO_HOLD, + + PARAM_INITIAL_FC, + PARAM_INITIAL_Q, + PARAM_MOD_LFO_TO_FC, + PARAM_MOD_LFO_CC1_TO_FC, + PARAM_MOD_LFO_CHAN_PRESS_TO_FC, + PARAM_MOD_EG_TO_FC, + PARAM_VEL_TO_FC, + PARAM_KEYNUM_TO_FC, + + PARAM_MOD_LFO_TO_GAIN, + PARAM_MOD_LFO_CC1_TO_GAIN, + PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN, + PARAM_VEL_TO_GAIN, + + PARAM_TUNING, + PARAM_KEYNUM_TO_PITCH, + PARAM_VIB_LFO_TO_PITCH, + PARAM_VIB_LFO_CC1_TO_PITCH, + PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH, + PARAM_MOD_LFO_TO_PITCH, + PARAM_MOD_LFO_CC1_TO_PITCH, + PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH, + PARAM_MOD_EG_TO_PITCH, + + PARAM_DEFAULT_PAN, + PARAM_MIDI_CC91_TO_REVERB_SEND, + PARAM_DEFAULT_REVERB_SEND, + PARAM_MIDI_CC93_TO_CHORUS_SEND, + PARAM_DEFAULT_CHORUS_SEND, + PARAM_TABLE_SIZE +} E_ART_INDEX; + +/* temporary data structure combining region, articulation, and envelope data */ +typedef struct s_art_dls_tag +{ + EAS_I16 values[PARAM_TABLE_SIZE]; +} S_DLS_ART_VALUES; + +/* temporary data structure for wlnk chunk data */ +typedef struct +{ + EAS_I32 gain; + EAS_U32 loopStart; + EAS_U32 loopLength; + EAS_U32 sampleRate; + EAS_U16 bitsPerSample; + EAS_I16 fineTune; + EAS_U8 unityNote; +} S_WSMP_DATA; + +/* temporary data structure used while parsing a DLS file */ +typedef struct +{ + S_DLS *pDLS; + EAS_HW_DATA_HANDLE hwInstData; + EAS_FILE_HANDLE fileHandle; + S_WSMP_DATA *wsmpData; + EAS_U32 instCount; + EAS_U32 regionCount; + EAS_U32 artCount; + EAS_U32 waveCount; + EAS_U32 wavePoolSize; + EAS_U32 wavePoolOffset; + EAS_BOOL bigEndian; + EAS_BOOL filterUsed; +} SDLS_SYNTHESIZER_DATA; + +/* connection lookup table */ +typedef struct s_connection_tag +{ + EAS_U16 source; + EAS_U16 control; + EAS_U16 destination; + EAS_U16 connection; +} S_CONNECTION; + +static const S_CONNECTION connTable[] = +{ + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_FREQUENCY, PARAM_MOD_LFO_FREQ }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_STARTDELAY, PARAM_MOD_LFO_DELAY}, + + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_VIB_FREQUENCY, PARAM_VIB_LFO_FREQ }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_VIB_STARTDELAY, PARAM_VIB_LFO_DELAY }, + + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DELAYTIME, PARAM_VOL_EG_DELAY }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME, PARAM_VOL_EG_ATTACK }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME, PARAM_VOL_EG_HOLD }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME, PARAM_VOL_EG_DECAY }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SUSTAINLEVEL, PARAM_VOL_EG_SUSTAIN }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_RELEASETIME, PARAM_VOL_EG_RELEASE }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SHUTDOWNTIME, PARAM_VOL_EG_SHUTDOWN }, + { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME, PARAM_VOL_EG_VEL_TO_ATTACK }, + { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME, PARAM_VOL_EG_KEY_TO_DECAY }, + { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME, PARAM_VOL_EG_KEY_TO_HOLD }, + + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DELAYTIME, PARAM_MOD_EG_DELAY }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME, PARAM_MOD_EG_ATTACK }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_HOLDTIME, PARAM_MOD_EG_HOLD }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME, PARAM_MOD_EG_DECAY }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_SUSTAINLEVEL, PARAM_MOD_EG_SUSTAIN }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_RELEASETIME, PARAM_MOD_EG_RELEASE }, + { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME, PARAM_MOD_EG_VEL_TO_ATTACK }, + { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME, PARAM_MOD_EG_KEY_TO_DECAY }, + { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG2_HOLDTIME, PARAM_MOD_EG_KEY_TO_HOLD }, + + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_INITIAL_FC }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_FILTER_Q, PARAM_INITIAL_Q }, + { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_TO_FC }, + { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_CC1_TO_FC }, + { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_CHAN_PRESS_TO_FC }, + { CONN_SRC_EG2, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_EG_TO_FC }, + { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_VEL_TO_FC }, + { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_KEYNUM_TO_FC }, + + { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_GAIN, PARAM_MOD_LFO_TO_GAIN }, + { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_GAIN, PARAM_MOD_LFO_CC1_TO_GAIN }, + { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_GAIN, PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN }, + { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_GAIN, PARAM_VEL_TO_GAIN }, + + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_TUNING }, + { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_KEYNUM_TO_PITCH }, + { CONN_SRC_VIBRATO, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_VIB_LFO_TO_PITCH }, + { CONN_SRC_VIBRATO, CONN_SRC_CC1, CONN_DST_PITCH, PARAM_VIB_LFO_CC1_TO_PITCH }, + { CONN_SRC_VIBRATO, CONN_SRC_CHANNELPRESSURE, CONN_DST_PITCH, PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH }, + { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_MOD_LFO_TO_PITCH }, + { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_PITCH, PARAM_MOD_LFO_CC1_TO_PITCH }, + { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_PITCH, PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH }, + { CONN_SRC_EG2, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_MOD_EG_TO_PITCH }, + + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PAN, PARAM_DEFAULT_PAN }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_DEFAULT_REVERB_SEND }, + { CONN_SRC_CC91, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_MIDI_CC91_TO_REVERB_SEND }, + { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_CHORUS, PARAM_DEFAULT_CHORUS_SEND }, + { CONN_SRC_CC93, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_MIDI_CC93_TO_CHORUS_SEND } +}; +#define ENTRIES_IN_CONN_TABLE (sizeof(connTable)/sizeof(S_CONNECTION)) + +static const S_DLS_ART_VALUES defaultArt = +{{ + 0, /* not modified */ + -851, /* Mod LFO frequency: 5 Hz */ + -7973, /* Mod LFO delay: 10 milliseconds */ + + -851, /* Vib LFO frequency: 5 Hz */ + -7973, /* Vib LFO delay: 10 milliseconds */ + + -32768, /* EG1 delay time: 0 secs */ + -32768, /* EG1 attack time: 0 secs */ + -32768, /* EG1 hold time: 0 secs */ + -32768, /* EG1 decay time: 0 secs */ + 1000, /* EG1 sustain level: 100.0% */ + -32768, /* EG1 release time: 0 secs */ + -7271, /* EG1 shutdown time: 15 msecs */ + 0, /* EG1 velocity to attack: 0 time cents */ + 0, /* EG1 key number to decay: 0 time cents */ + 0, /* EG1 key number to hold: 0 time cents */ + + -32768, /* EG2 delay time: 0 secs */ + -32768, /* EG2 attack time: 0 secs */ + -32768, /* EG2 hold time: 0 secs */ + -32768, /* EG2 decay time: 0 secs */ + 1000, /* EG2 sustain level: 100.0% */ + -32768, /* EG2 release time: 0 secs */ + 0, /* EG2 velocity to attack: 0 time cents */ + 0, /* EG2 key number to decay: 0 time cents */ + 0, /* EG2 key number to hold: 0 time cents */ + + 0x7fff, /* Initial Fc: Disabled */ + 0, /* Initial Q: 0 dB */ + 0, /* Mod LFO to Fc: 0 cents */ + 0, /* Mod LFO CC1 to Fc: 0 cents */ + 0, /* Mod LFO channel pressure to Fc: 0 cents */ + 0, /* EG2 to Fc: 0 cents */ + 0, /* Velocity to Fc: 0 cents */ + 0, /* Key number to Fc: 0 cents */ + + 0, /* Mod LFO to gain: 0 dB */ + 0, /* Mod LFO CC1 to gain: 0 dB */ + 0, /* Mod LFO channel pressure to gain: 0 dB */ + 960, /* Velocity to gain: 96 dB */ + + 0, /* Tuning: 0 cents */ + 12800, /* Key number to pitch: 12,800 cents */ + 0, /* Vibrato to pitch: 0 cents */ + 0, /* Vibrato CC1 to pitch: 0 cents */ + 0, /* Vibrato channel pressure to pitch: 0 cents */ + 0, /* Mod LFO to pitch: 0 cents */ + 0, /* Mod LFO CC1 to pitch: 0 cents */ + 0, /* Mod LFO channel pressure to pitch: 0 cents */ + 0, /* Mod EG to pitch: 0 cents */ + + 0, /* Default pan: 0.0% */ + 0, /* Default reverb send: 0.0% */ + 1000, /* Default CC91 to reverb send: 100.0% */ + 0, /* Default chorus send: 0.0% */ + 1000 /* Default CC93 to chorus send: 100.0% */ +}}; + +/*------------------------------------ + * local variables + *------------------------------------ +*/ + +#if defined(_8_BIT_SAMPLES) +static const EAS_INT bitDepth = 8; +#elif defined(_16_BIT_SAMPLES) +static const EAS_INT bitDepth = 16; +#else +#error "Must define _8_BIT_SAMPLES or _16_BIT_SAMPLES" +#endif + +static const EAS_U32 outputSampleRate = _OUTPUT_SAMPLE_RATE; +static const EAS_I32 dlsRateConvert = DLS_RATE_CONVERT; +static const EAS_I32 dlsLFOFrequencyConvert = DLS_LFO_FREQUENCY_CONVERT; + +/*------------------------------------ + * inline functions + *------------------------------------ +*/ +EAS_INLINE void *PtrOfs (void *p, EAS_I32 offset) +{ + return (void*) (((EAS_U8*) p) + offset); +} + +/*------------------------------------ + * prototypes + *------------------------------------ +*/ +static EAS_RESULT NextChunk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 *pPos, EAS_U32 *pChunkType, EAS_I32 *pSize); +static EAS_RESULT Parse_ptbl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 wsmpPos, EAS_I32 wsmpSize); +static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex); +static EAS_RESULT Parse_wsmp (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p); +static EAS_RESULT Parse_fmt (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p); +static EAS_RESULT Parse_data (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_WSMP_DATA *p, EAS_SAMPLE *pSample); +static EAS_RESULT Parse_lins(SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size); +static EAS_RESULT Parse_ins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size); +static EAS_RESULT Parse_insh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pRgnCount, EAS_U32 *pLocale); +static EAS_RESULT Parse_lrgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex, EAS_U32 numRegions); +static EAS_RESULT Parse_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex); +static EAS_RESULT Parse_rgnh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_REGION *pRgn); +static EAS_RESULT Parse_lart (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_DLS_ART_VALUES *pArt); +static EAS_RESULT Parse_art (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_ART_VALUES *pArt); +static EAS_RESULT Parse_wlnk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pWaveIndex); +static EAS_RESULT Parse_cdl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 size, EAS_U32 *pValue); +static void Convert_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_U16 regionIndex, EAS_U16 artIndex, EAS_U16 waveIndex, S_WSMP_DATA *pWsmp); +static void Convert_art (SDLS_SYNTHESIZER_DATA *pDLSData, const S_DLS_ART_VALUES *pDLSArt, EAS_U16 artIndex); +static EAS_I16 ConvertSampleRate (EAS_U32 sampleRate); +static EAS_I16 ConvertSustain (EAS_I32 sustain); +static EAS_I16 ConvertLFOPhaseIncrement (EAS_I32 pitchCents); +static EAS_I8 ConvertPan (EAS_I32 pan); +static EAS_U8 ConvertQ (EAS_I32 q); + +#ifdef _DEBUG_DLS +static void DumpDLS (S_EAS *pEAS); +#endif + + +/*---------------------------------------------------------------------------- + * DLSParser () + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pEASData - pointer to over EAS data instance + * fileHandle - file handle for input file + * offset - offset into file where DLS data starts + * + * Outputs: + * EAS_RESULT + * ppEAS - address of pointer to alternate EAS wavetable + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS) +{ + EAS_RESULT result; + SDLS_SYNTHESIZER_DATA dls; + EAS_U32 temp; + EAS_I32 pos; + EAS_I32 chunkPos; + EAS_I32 size; + EAS_I32 instSize; + EAS_I32 rgnPoolSize; + EAS_I32 artPoolSize; + EAS_I32 waveLenSize; + EAS_I32 endDLS; + EAS_I32 wvplPos; + EAS_I32 wvplSize; + EAS_I32 linsPos; + EAS_I32 linsSize; + EAS_I32 ptblPos; + EAS_I32 ptblSize; + void *p; + + /* zero counts and pointers */ + EAS_HWMemSet(&dls, 0, sizeof(dls)); + + /* save file handle and hwInstData to save copying pointers around */ + dls.hwInstData = hwInstData; + dls.fileHandle = fileHandle; + + /* NULL return value in case of error */ + *ppDLS = NULL; + + /* seek to start of DLS and read in RIFF tag and set processor endian flag */ + if ((result = EAS_HWFileSeek(dls.hwInstData, dls.fileHandle, offset)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWReadFile(dls.hwInstData, dls.fileHandle, &temp, sizeof(temp), &size)) != EAS_SUCCESS) + return result; + + /* check for processor endian-ness */ + dls.bigEndian = (temp == CHUNK_RIFF); + + /* first chunk should be DLS */ + pos = offset; + if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + if (temp != CHUNK_DLS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected DLS chunk, got %08lx\n", temp); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* no instrument or wavepool chunks */ + linsSize = wvplSize = ptblSize = linsPos = wvplPos = ptblPos = 0; + + /* scan the chunks in the DLS list */ + endDLS = offset + size; + pos = offset + 12; + while (pos < endDLS) + { + chunkPos = pos; + + /* get the next chunk type */ + if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + + /* parse useful chunks */ + switch (temp) + { + case CHUNK_CDL: + if ((result = Parse_cdl(&dls, size, &temp)) != EAS_SUCCESS) + return result; + if (!temp) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + break; + + case CHUNK_LINS: + linsPos = chunkPos + 12; + linsSize = size - 4; + break; + + case CHUNK_WVPL: + wvplPos = chunkPos + 12; + wvplSize = size - 4; + break; + + case CHUNK_PTBL: + ptblPos = chunkPos + 8; + ptblSize = size - 4; + break; + + default: + break; + } + } + + /* must have a lins chunk */ + if (linsSize == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No lins chunk found"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* must have a wvpl chunk */ + if (wvplSize == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No wvpl chunk found"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* must have a ptbl chunk */ + if ((ptblSize == 0) || (ptblSize > DLS_MAX_WAVE_COUNT * sizeof(POOLCUE) + sizeof(POOLTABLE))) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No ptbl chunk found"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* pre-parse the wave pool chunk */ + if ((result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize)) != EAS_SUCCESS) + return result; + + /* limit check */ + if ((dls.waveCount == 0) || (dls.waveCount > DLS_MAX_WAVE_COUNT)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #waves [%u]\n", dls.waveCount); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* allocate memory for wsmp data */ + dls.wsmpData = EAS_HWMalloc(dls.hwInstData, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount)); + if (dls.wsmpData == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc for wsmp data failed\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(dls.wsmpData, 0, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount)); + + /* pre-parse the lins chunk */ + result = Parse_lins(&dls, linsPos, linsSize); + if (result == EAS_SUCCESS) + { + + /* limit check */ + if ((dls.regionCount == 0) || (dls.regionCount > DLS_MAX_REGION_COUNT)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #regions [%u]\n", dls.regionCount); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* limit check */ + if ((dls.artCount == 0) || (dls.artCount > DLS_MAX_ART_COUNT)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #articulations [%u]\n", dls.regionCount); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* limit check */ + if ((dls.instCount == 0) || (dls.instCount > DLS_MAX_INST_COUNT)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #instruments [%u]\n", dls.instCount); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* Allocate memory for the converted DLS data */ + /* calculate size of instrument data */ + instSize = (EAS_I32) (sizeof(S_PROGRAM) * dls.instCount); + + /* calculate size of region pool */ + rgnPoolSize = (EAS_I32) (sizeof(S_DLS_REGION) * dls.regionCount); + + /* calculate size of articulation pool, add one for default articulation */ + dls.artCount++; + artPoolSize = (EAS_I32) (sizeof(S_DLS_ARTICULATION) * dls.artCount); + + /* calculate size of wave length and offset arrays */ + waveLenSize = (EAS_I32) (dls.waveCount * sizeof(EAS_U32)); + + /* calculate final memory size */ + size = (EAS_I32) sizeof(S_EAS) + instSize + rgnPoolSize + artPoolSize + (2 * waveLenSize) + (EAS_I32) dls.wavePoolSize; + if (size <= 0) { + return EAS_ERROR_FILE_FORMAT; + } + + /* allocate the main EAS chunk */ + dls.pDLS = EAS_HWMalloc(dls.hwInstData, size); + if (dls.pDLS == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc failed for DLS memory allocation size %ld\n", size); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(dls.pDLS, 0, size); + dls.pDLS->refCount = 1; + p = PtrOfs(dls.pDLS, sizeof(S_EAS)); + + /* setup pointer to programs */ + dls.pDLS->numDLSPrograms = (EAS_U16) dls.instCount; + dls.pDLS->pDLSPrograms = p; + p = PtrOfs(p, instSize); + + /* setup pointer to regions */ + dls.pDLS->pDLSRegions = p; + dls.pDLS->numDLSRegions = (EAS_U16) dls.regionCount; + p = PtrOfs(p, rgnPoolSize); + + /* setup pointer to articulations */ + dls.pDLS->numDLSArticulations = (EAS_U16) dls.artCount; + dls.pDLS->pDLSArticulations = p; + p = PtrOfs(p, artPoolSize); + + /* setup pointer to wave length table */ + dls.pDLS->numDLSSamples = (EAS_U16) dls.waveCount; + dls.pDLS->pDLSSampleLen = p; + p = PtrOfs(p, waveLenSize); + + /* setup pointer to wave offsets table */ + dls.pDLS->pDLSSampleOffsets = p; + p = PtrOfs(p, waveLenSize); + + /* setup pointer to wave pool */ + dls.pDLS->pDLSSamples = p; + + /* clear filter flag */ + dls.filterUsed = EAS_FALSE; + + /* parse the wave pool and load samples */ + result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize); + } + + /* create the default articulation */ + Convert_art(&dls, &defaultArt, 0); + dls.artCount = 1; + + /* parse the lins chunk and load instruments */ + dls.regionCount = dls.instCount = 0; + if (result == EAS_SUCCESS) + result = Parse_lins(&dls, linsPos, linsSize); + + /* clean up any temporary objects that were allocated */ + if (dls.wsmpData) + EAS_HWFree(dls.hwInstData, dls.wsmpData); + + /* if successful, return a pointer to the EAS collection */ + if (result == EAS_SUCCESS) + { + *ppDLS = dls.pDLS; +#ifdef _DEBUG_DLS + DumpDLS(dls.pDLS); +#endif + } + + /* something went wrong, deallocate the EAS collection */ + else + DLSCleanup(dls.hwInstData, dls.pDLS); + + return result; +} + +/*---------------------------------------------------------------------------- + * DLSCleanup () + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pEASData - pointer to over EAS data instance + * pEAS - pointer to alternate EAS wavetable + * + * Outputs: + * EAS_RESULT + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT DLSCleanup (EAS_HW_DATA_HANDLE hwInstData, S_DLS *pDLS) +{ + + /* free the allocated memory */ + if (pDLS) + { + if (pDLS->refCount) + { + if (--pDLS->refCount == 0) + EAS_HWFree(hwInstData, pDLS); + } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * DLSAddRef () + *---------------------------------------------------------------------------- + * Increment reference count + *---------------------------------------------------------------------------- +*/ +void DLSAddRef (S_DLS *pDLS) +{ + if (pDLS) + pDLS->refCount++; +} + +/*---------------------------------------------------------------------------- + * NextChunk () + *---------------------------------------------------------------------------- + * Purpose: + * Returns the type and size of the next chunk in the file + * + * Inputs: + * + * Outputs: + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT NextChunk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 *pPos, EAS_U32 *pChunkType, EAS_I32 *pSize) +{ + EAS_RESULT result; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, *pPos)) != EAS_SUCCESS) + return result; + + /* read the chunk type */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pChunkType, EAS_TRUE)) != EAS_SUCCESS) + return result; + + /* read the chunk size */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pSize, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* get form type for RIFF and LIST types */ + if ((*pChunkType == CHUNK_RIFF) || (*pChunkType == CHUNK_LIST)) + { + + /* read the form type */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pChunkType, EAS_TRUE)) != EAS_SUCCESS) + return result; + + } + + /* calculate start of next chunk */ + *pPos += *pSize + 8; + + /* adjust to word boundary */ + if (*pPos & 1) + (*pPos)++; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_ptbl () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_ptbl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 wtblPos, EAS_I32 wtblSize) +{ + EAS_RESULT result; + EAS_U32 temp; + EAS_FILE_HANDLE tempFile; + EAS_U16 waveIndex; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get the structure size */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &temp, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* get the number of waves */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSData->waveCount, EAS_FALSE)) != EAS_SUCCESS) + return result; + +#if 0 + /* just need the wave count on the first pass */ + if (!pDLSData->pDLS) + return EAS_SUCCESS; +#endif + + /* open duplicate file handle */ + if ((result = EAS_HWDupHandle(pDLSData->hwInstData, pDLSData->fileHandle, &tempFile)) != EAS_SUCCESS) + return result; + + /* read to end of chunk */ + for (waveIndex = 0; waveIndex < pDLSData->waveCount; waveIndex++) + { + + /* get the offset to the wave and make sure it is within the wtbl chunk */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, tempFile, &temp, EAS_FALSE)) != EAS_SUCCESS) + return result; + if (temp > (EAS_U32) wtblSize) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Ptbl offset exceeds size of wtbl\n"); */ } + EAS_HWCloseFile(pDLSData->hwInstData, tempFile); + return EAS_ERROR_FILE_FORMAT; + } + + /* parse the wave */ + if ((result = Parse_wave(pDLSData, wtblPos +(EAS_I32) temp, waveIndex)) != EAS_SUCCESS) + return result; + } + + /* close the temporary handle and return */ + EAS_HWCloseFile(pDLSData->hwInstData, tempFile); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_wave () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex) +{ + EAS_RESULT result; + EAS_U32 temp; + EAS_I32 size; + EAS_I32 endChunk; + EAS_I32 chunkPos; + EAS_I32 wsmpPos = 0; + EAS_I32 fmtPos = 0; + EAS_I32 dataPos = 0; + EAS_I32 dataSize = 0; + S_WSMP_DATA *p; + void *pSample; + S_WSMP_DATA wsmp; + + /* seek to start of chunk */ + chunkPos = pos + 12; + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get the chunk type */ + if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + + /* make sure it is a wave chunk */ + if (temp != CHUNK_WAVE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Offset in ptbl does not point to wave chunk\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* read to end of chunk */ + pos = chunkPos; + endChunk = pos + size; + while (pos < endChunk) + { + chunkPos = pos; + + /* get the chunk type */ + if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + + /* parse useful chunks */ + switch (temp) + { + case CHUNK_WSMP: + wsmpPos = chunkPos + 8; + break; + + case CHUNK_FMT: + fmtPos = chunkPos + 8; + break; + + case CHUNK_DATA: + dataPos = chunkPos + 8; + dataSize = size; + break; + + default: + break; + } + } + + // limit to reasonable size + if (dataSize > MAX_DLS_WAVE_SIZE) + { + return EAS_ERROR_SOUND_LIBRARY; + } + + /* for first pass, use temporary variable */ + if (pDLSData->pDLS == NULL) + p = &wsmp; + else + p = &pDLSData->wsmpData[waveIndex]; + + /* set the defaults */ + p->fineTune = 0; + p->unityNote = 60; + p->gain = 0; + p->loopStart = 0; + p->loopLength = 0; + + /* must have a fmt chunk */ + if (!fmtPos) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no fmt chunk\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* must have a data chunk */ + if (!dataPos) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no data chunk\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* parse the wsmp chunk */ + if (wsmpPos) + { + if ((result = Parse_wsmp(pDLSData, wsmpPos, p)) != EAS_SUCCESS) + return result; + } + + /* parse the fmt chunk */ + if ((result = Parse_fmt(pDLSData, fmtPos, p)) != EAS_SUCCESS) + return result; + + /* calculate the size of the wavetable needed. We need only half + * the memory for 16-bit samples when in 8-bit mode, and we need + * double the memory for 8-bit samples in 16-bit mode. For + * unlooped samples, we may use ADPCM. If so, we need only 1/4 + * the memory. + * + * We also need to add one for looped samples to allow for + * the first sample to be copied to the end of the loop. + */ + + /* use ADPCM encode for unlooped 16-bit samples if ADPCM is enabled */ + /*lint -e{506} -e{774} groundwork for future version to support 8 & 16 bit */ + if (bitDepth == 8) + { + if (p->bitsPerSample == 8) + size = dataSize; + else + /*lint -e{704} use shift for performance */ + size = dataSize >> 1; + if (p->loopLength) + size++; + } + + else + { + if (p->bitsPerSample == 16) + size = dataSize; + else + /*lint -e{703} use shift for performance */ + size = dataSize << 1; + if (p->loopLength) + size += 2; + } + + /* for first pass, add size to wave pool size and return */ + if (pDLSData->pDLS == NULL) + { + pDLSData->wavePoolSize += (EAS_U32) size; + return EAS_SUCCESS; + } + + /* allocate memory and read in the sample data */ + pSample = pDLSData->pDLS->pDLSSamples + pDLSData->wavePoolOffset; + pDLSData->pDLS->pDLSSampleOffsets[waveIndex] = pDLSData->wavePoolOffset; + pDLSData->pDLS->pDLSSampleLen[waveIndex] = (EAS_U32) size; + pDLSData->wavePoolOffset += (EAS_U32) size; + if (pDLSData->wavePoolOffset > pDLSData->wavePoolSize) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Wave pool exceeded allocation\n"); */ } + return EAS_ERROR_SOUND_LIBRARY; + } + + if ((result = Parse_data(pDLSData, dataPos, dataSize, p, pSample)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_wsmp () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_wsmp (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p) +{ + EAS_RESULT result; + EAS_U16 wtemp; + EAS_U32 ltemp; + EAS_U32 cbSize; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get structure size */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &cbSize, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* get unity note */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS) + return result; + if (wtemp <= 127) + p->unityNote = (EAS_U8) wtemp; + else + { + p->unityNote = 60; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid unity note [%u] in DLS wsmp ignored, set to 60\n", wtemp); */ } + } + + /* get fine tune */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->fineTune, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* get gain */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->gain, EAS_FALSE)) != EAS_SUCCESS) + return result; + if (p->gain > 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Positive gain [%ld] in DLS wsmp ignored, set to 0dB\n", p->gain); */ } + p->gain = 0; + } + + /* option flags */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* sample loops */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* if looped sample, get loop data */ + if (ltemp) + { + + if (ltemp > 1) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS sample with %lu loops, ignoring extra loops\n", ltemp); */ } + + /* skip ahead to loop data */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos + (EAS_I32) cbSize)) != EAS_SUCCESS) + return result; + + /* get structure size */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* get loop type */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* get loop start */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->loopStart, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* get loop length */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->loopLength, EAS_FALSE)) != EAS_SUCCESS) + return result; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_fmt () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_fmt (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p) +{ + EAS_RESULT result; + EAS_U16 wtemp; + EAS_U32 ltemp; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get format tag */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS) + return result; + if (wtemp != WAVE_FORMAT_PCM) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unsupported DLS sample format %04x\n", wtemp); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* get number of channels */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS) + return result; + if (wtemp != 1) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No support for DLS multi-channel samples\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* get sample rate */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->sampleRate, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* bytes/sec */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* block align */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* bits/sample */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->bitsPerSample, EAS_FALSE)) != EAS_SUCCESS) + return result; + + if ((p->bitsPerSample != 8) && (p->bitsPerSample != 16)) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unsupported DLS bits-per-sample %d\n", p->bitsPerSample); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + return EAS_SUCCESS; +} + +#if defined( _8_BIT_SAMPLES) +/*---------------------------------------------------------------------------- + * Parse_data () + *---------------------------------------------------------------------------- + * Purpose: + * + * NOTE: The optimized assembly versions of the interpolator require + * an extra sample at the end of the loop - a copy of the first + * sample. This routine must allocate an extra sample of data and + * copy the first sample of the loop to the end. + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_data (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_WSMP_DATA *pWsmp, EAS_SAMPLE *pSample) +{ + EAS_RESULT result; + EAS_U8 convBuf[SAMPLE_CONVERT_CHUNK_SIZE]; + EAS_I32 count; + EAS_I32 i; + EAS_I8 *p; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* 8-bit samples in an 8-bit synth, just copy the data, and flip bit 7 */ + p = pSample; + if (pWsmp->bitsPerSample == 8) + { + if ((result = EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, pSample, size, &count)) != EAS_SUCCESS) + return result; + for (i = 0; i < size; i++) + /*lint -e{734} convert from unsigned to signed audio */ + *p++ ^= 0x80; + } + + /* 16-bit samples, need to convert to 8-bit or ADPCM */ + else + { + + while (size) + { + EAS_I8 *pInput; + + /* for undithered conversion, we're just copying the 8-bit data */ + if (pDLSData->bigEndian) + pInput = (EAS_I8*) convBuf; + else + pInput = (EAS_I8*) convBuf + 1; + + /* read a small chunk of data and convert it */ + count = (size < SAMPLE_CONVERT_CHUNK_SIZE ? size : SAMPLE_CONVERT_CHUNK_SIZE); + if ((result = EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, convBuf, count, &count)) != EAS_SUCCESS) + return result; + size -= count; + /*lint -e{704} use shift for performance */ + count = count >> 1; + + while (count--) + { + *p++ = *pInput; + pInput += 2; + } + } + } + + /* for looped samples, copy the last sample to the end */ + if (pWsmp->loopLength) + pSample[pWsmp->loopStart + pWsmp->loopLength] = pSample[pWsmp->loopStart]; + + return EAS_SUCCESS; +} +#elif defined(_16_BIT_SAMPLES) +#error "16-bit DLS conversion not implemented yet" +#else +#error "Must specifiy _8_BIT_SAMPLES or _16_BIT_SAMPLES" +#endif + +/*---------------------------------------------------------------------------- + * Parse_lins () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_lins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size) +{ + EAS_RESULT result; + EAS_U32 temp; + EAS_I32 endChunk; + EAS_I32 chunkPos; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* read to end of chunk */ + endChunk = pos + size; + while (pos < endChunk) + { + chunkPos = pos; + + /* get the next chunk type */ + if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + + /* only instrument chunks are useful */ + if (temp != CHUNK_INS) + continue; + + if ((result = Parse_ins(pDLSData, chunkPos + 12, size)) != EAS_SUCCESS) + return result; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_ins () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_ins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size) +{ + EAS_RESULT result; + EAS_U32 temp; + EAS_I32 chunkPos; + EAS_I32 endChunk; + EAS_I32 lrgnPos; + EAS_I32 lrgnSize; + EAS_I32 lartPos; + EAS_I32 lartSize; + EAS_I32 lar2Pos; + EAS_I32 lar2Size; + EAS_I32 inshPos; + EAS_U32 regionCount; + EAS_U32 locale; + S_DLS_ART_VALUES art; + S_PROGRAM *pProgram; + EAS_U16 artIndex; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* no chunks yet */ + lrgnPos = lrgnSize = lartPos = lartSize = lar2Pos = lar2Size = inshPos = artIndex = 0; + + /* read to end of chunk */ + endChunk = pos + size; + while (pos < endChunk) + { + chunkPos = pos; + + /* get the next chunk type */ + if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + + /* parse useful chunks */ + switch (temp) + { + case CHUNK_INSH: + inshPos = chunkPos + 8; + break; + + case CHUNK_LART: + lartPos = chunkPos + 12; + lartSize = size; + break; + + case CHUNK_LAR2: + lar2Pos = chunkPos + 12; + lar2Size = size; + break; + + case CHUNK_LRGN: + lrgnPos = chunkPos + 12; + lrgnSize = size; + break; + + default: + break; + } + } + + /* must have an lrgn to be useful */ + if (!lrgnPos) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS ins chunk has no lrgn chunk\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* must have an insh to be useful */ + if (!inshPos) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS ins chunk has no insh chunk\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* parse the instrument header */ + if ((result = Parse_insh(pDLSData, inshPos, ®ionCount, &locale)) != EAS_SUCCESS) + return result; + + /* initialize and parse the global data first */ + EAS_HWMemCpy(&art, &defaultArt, sizeof(S_DLS_ART_VALUES)); + if (lartPos) + if ((result = Parse_lart(pDLSData, lartPos, lartSize, &art)) != EAS_SUCCESS) + return result; + if (lar2Pos) + if ((result = Parse_lart(pDLSData, lar2Pos, lar2Size, &art)) != EAS_SUCCESS) + return result; + + if (art.values[PARAM_MODIFIED]) + { + artIndex = (EAS_U16) pDLSData->artCount; + pDLSData->artCount++; + } + + /* convert data on second pass */ + if (pDLSData->pDLS) + { + + if (art.values[PARAM_MODIFIED]) + Convert_art(pDLSData, &art, artIndex); + + /* setup pointers */ + pProgram = &pDLSData->pDLS->pDLSPrograms[pDLSData->instCount]; + + /* initialize instrument */ + pProgram->locale = locale; + pProgram->regionIndex = (EAS_U16) pDLSData->regionCount | FLAG_RGN_IDX_DLS_SYNTH; + + } + + /* parse the region data */ + if ((result = Parse_lrgn(pDLSData, lrgnPos, lrgnSize, artIndex, regionCount)) != EAS_SUCCESS) + return result; + + /* bump instrument count */ + pDLSData->instCount++; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_insh () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_insh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pRgnCount, EAS_U32 *pLocale) +{ + EAS_RESULT result; + EAS_U32 bank; + EAS_U32 program; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get the region count and locale */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pRgnCount, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &bank, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &program, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* verify the parameters are valid */ + if (bank & 0x7fff8080) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS bank number is out of range: %08lx\n", bank); */ } + bank &= 0xff7f; + } + if (program > 127) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS program number is out of range: %08lx\n", program); */ } + program &= 0x7f; + } + + /* save the program number */ + *pLocale = (bank << 8) | program; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_lrgn () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_lrgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex, EAS_U32 numRegions) +{ + EAS_RESULT result; + EAS_U32 temp; + EAS_I32 chunkPos; + EAS_I32 endChunk; + EAS_U16 regionCount; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* read to end of chunk */ + regionCount = 0; + endChunk = pos + size; + while (pos < endChunk) + { + chunkPos = pos; + + /* get the next chunk type */ + if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + + if ((temp == CHUNK_RGN) || (temp == CHUNK_RGN2)) + { + if (regionCount == numRegions) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS region count exceeded cRegions value in insh, extra region ignored\n"); */ } + return EAS_SUCCESS; + } + if ((result = Parse_rgn(pDLSData, chunkPos + 12, size, artIndex)) != EAS_SUCCESS) + return result; + regionCount++; + } + } + + /* set a flag in the last region */ + if ((pDLSData->pDLS != NULL) && (regionCount > 0)) + pDLSData->pDLS->pDLSRegions[pDLSData->regionCount - 1].wtRegion.region.keyGroupAndFlags |= REGION_FLAG_LAST_REGION; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_rgn () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex) +{ + EAS_RESULT result; + EAS_U32 temp; + EAS_I32 chunkPos; + EAS_I32 endChunk; + EAS_I32 rgnhPos; + EAS_I32 lartPos; + EAS_I32 lartSize; + EAS_I32 lar2Pos; + EAS_I32 lar2Size; + EAS_I32 wlnkPos; + EAS_I32 wsmpPos; + EAS_U32 waveIndex; + S_DLS_ART_VALUES art; + S_WSMP_DATA wsmp; + S_WSMP_DATA *pWsmp; + EAS_U16 regionIndex; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* no chunks found yet */ + rgnhPos = lartPos = lartSize = lar2Pos = lar2Size = wsmpPos = wlnkPos = 0; + regionIndex = (EAS_U16) pDLSData->regionCount; + + /* read to end of chunk */ + endChunk = pos + size; + while (pos < endChunk) + { + chunkPos = pos; + + /* get the next chunk type */ + if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + + /* parse useful chunks */ + switch (temp) + { + case CHUNK_CDL: + if ((result = Parse_cdl(pDLSData, size, &temp)) != EAS_SUCCESS) + return result; + + /* if conditional chunk evaluates false, skip this list */ + if (!temp) + return EAS_SUCCESS; + break; + + case CHUNK_RGNH: + rgnhPos = chunkPos + 8; + break; + + case CHUNK_WLNK: + wlnkPos = chunkPos + 8; + break; + + case CHUNK_WSMP: + wsmpPos = chunkPos + 8; + break; + + case CHUNK_LART: + lartPos = chunkPos + 12; + lartSize = size; + break; + + case CHUNK_LAR2: + lar2Pos = chunkPos + 12; + lar2Size = size; + break; + + default: + break; + } + } + + /* must have a rgnh chunk to be useful */ + if (!rgnhPos) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS rgn chunk has no rgnh chunk\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* must have a wlnk chunk to be useful */ + if (!wlnkPos) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS rgn chunk has no wlnk chunk\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* parse wlnk chunk */ + if ((result = Parse_wlnk(pDLSData, wlnkPos, &waveIndex)) != EAS_SUCCESS) + return result; + pWsmp = &pDLSData->wsmpData[waveIndex]; + + /* if there is any articulation data, parse it */ + EAS_HWMemCpy(&art, &defaultArt, sizeof(S_DLS_ART_VALUES)); + if (lartPos) + { + if ((result = Parse_lart(pDLSData, lartPos, lartSize, &art)) != EAS_SUCCESS) + return result; + } + + if (lar2Pos) + { + if ((result = Parse_lart(pDLSData, lar2Pos, lar2Size, &art)) != EAS_SUCCESS) + return result; + } + + /* if second pass, process region header */ + if (pDLSData->pDLS) + { + + /* if local data was found convert it */ + if (art.values[PARAM_MODIFIED] == EAS_TRUE) + { + Convert_art(pDLSData, &art, (EAS_U16) pDLSData->artCount); + artIndex = (EAS_U16) pDLSData->artCount; + } + + /* parse region header */ + if ((result = Parse_rgnh(pDLSData, rgnhPos, &pDLSData->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK])) != EAS_SUCCESS) + return result; + + /* parse wsmp chunk, copying parameters from original first */ + if (wsmpPos) + { + EAS_HWMemCpy(&wsmp, pWsmp, sizeof(wsmp)); + if ((result = Parse_wsmp(pDLSData, wsmpPos, &wsmp)) != EAS_SUCCESS) + return result; + + pWsmp = &wsmp; + } + + Convert_rgn(pDLSData, regionIndex, artIndex, (EAS_U16) waveIndex, pWsmp); + } + + /* if local articulation, bump count */ + if (art.values[PARAM_MODIFIED]) + pDLSData->artCount++; + + /* increment region count */ + pDLSData->regionCount++; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_rgnh () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_rgnh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_REGION *pRgn) +{ + EAS_RESULT result; + EAS_U16 lowKey; + EAS_U16 highKey; + EAS_U16 lowVel; + EAS_U16 highVel; + EAS_U16 optionFlags; + EAS_U16 keyGroup; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get the key range */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &lowKey, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &highKey, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* check the range */ + if (lowKey > 127) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: Low key out of range [%u]\n", lowKey); */ } + lowKey = 127; + } + if (highKey > 127) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: High key out of range [%u]\n", lowKey); */ } + highKey = 127; + } + + /* get the velocity range */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &lowVel, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &highVel, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* check the range */ + if (lowVel > 127) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: Low velocity out of range [%u]\n", lowVel); */ } + lowVel = 127; + } + if (highVel > 127) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: High velocity out of range [%u]\n", highVel); */ } + highVel = 127; + } + + /* get the option flags */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &optionFlags, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* get the key group */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &keyGroup, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* save the key range and key group */ + pRgn->wtRegion.region.rangeLow = (EAS_U8) lowKey; + pRgn->wtRegion.region.rangeHigh = (EAS_U8) highKey; + + /*lint -e{734} keyGroup will always be from 0-15 */ + pRgn->wtRegion.region.keyGroupAndFlags = keyGroup << 8; + pRgn->velLow = (EAS_U8) lowVel; + pRgn->velHigh = (EAS_U8) highVel; + if (optionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE) + pRgn->wtRegion.region.keyGroupAndFlags |= REGION_FLAG_NON_SELF_EXCLUSIVE; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_lart () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_lart (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_DLS_ART_VALUES *pArt) +{ + EAS_RESULT result; + EAS_U32 temp; + EAS_I32 endChunk; + EAS_I32 chunkPos; + EAS_I32 art1Pos; + EAS_I32 art2Pos; + + /* seek to start of chunk */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* no articulation chunks yet */ + art1Pos = art2Pos = 0; + + /* read to end of chunk */ + endChunk = pos + size; + while (pos < endChunk) + { + chunkPos = pos; + + /* get the next chunk type */ + if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) + return result; + + /* parse useful chunks */ + switch (temp) + { + case CHUNK_CDL: + if ((result = Parse_cdl(pDLSData, size, &temp)) != EAS_SUCCESS) + return result; + + /* if conditional chunk evaluates false, skip this list */ + if (!temp) + return EAS_SUCCESS; + break; + + case CHUNK_ART1: + art1Pos = chunkPos + 8; + break; + + case CHUNK_ART2: + art2Pos = chunkPos + 8; + break; + + default: + break; + + } + } + + if (art1Pos) + { + if ((result = Parse_art(pDLSData, art1Pos, pArt)) != EAS_SUCCESS) + return result; + } + + if (art2Pos) + { + if ((result = Parse_art(pDLSData, art2Pos, pArt)) != EAS_SUCCESS) + return result; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_art() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_art (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_ART_VALUES *pArt) +{ + EAS_RESULT result; + EAS_U32 structSize; + EAS_U32 numConnections; + EAS_U16 source; + EAS_U16 control; + EAS_U16 destination; + EAS_U16 transform; + EAS_I32 scale; + EAS_INT i; + + /* seek to start of data */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get the structure size */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &structSize, EAS_FALSE)) != EAS_SUCCESS) + return result; + pos += (EAS_I32) structSize; + + /* get the number of connections */ + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &numConnections, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* skip to start of connections */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + while (numConnections--) + { + + /* read the connection data */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &source, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &control, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &destination, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &transform, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &scale, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* look up the connection */ + for (i = 0; i < (EAS_INT) ENTRIES_IN_CONN_TABLE; i++) + { + if ((connTable[i].source == source) && + (connTable[i].destination == destination) && + (connTable[i].control == control)) + { + /*lint -e{704} use shift for performance */ + pArt->values[connTable[i].connection] = (EAS_I16) (scale >> 16); + pArt->values[PARAM_MODIFIED] = EAS_TRUE; + break; + } + } + if (i == PARAM_TABLE_SIZE) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "WARN: Unsupported parameter in DLS file\n"); */ } + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * Parse_wlnk () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_wlnk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pWaveIndex) +{ + EAS_RESULT result; + + /* we only care about the the index */ + if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos + 8)) != EAS_SUCCESS) + return result; + + /* read the index */ + return EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle,pWaveIndex, EAS_FALSE); +} + +/*---------------------------------------------------------------------------- + * PopcdlStack () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT PopcdlStack (EAS_U32 *pStack, EAS_INT *pStackPtr, EAS_U32 *pValue) +{ + + /* stack underflow, cdl block has an errorr */ + if (*pStackPtr < 0) + return EAS_ERROR_FILE_FORMAT; + + /* pop the value off the stack */ + *pValue = pStack[*pStackPtr]; + *pStackPtr = *pStackPtr - 1; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * PushcdlStack () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT PushcdlStack (EAS_U32 *pStack, EAS_INT *pStackPtr, EAS_U32 value) +{ + + /* stack overflow, return an error */ + if (*pStackPtr >= CDL_STACK_SIZE) + return EAS_ERROR_FILE_FORMAT; + + /* push the value onto the stack */ + *pStackPtr = *pStackPtr + 1; + pStack[*pStackPtr] = value; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * QueryGUID () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL QueryGUID (const DLSID *pGUID, EAS_U32 *pValue) +{ + + /* assume false */ + *pValue = 0; + if (EAS_HWMemCmp(&DLSID_GMInHardware, pGUID, sizeof(DLSID)) == 0) + { + *pValue = 0xffffffff; + return EAS_TRUE; + } + + if (EAS_HWMemCmp(&DLSID_GSInHardware, pGUID, sizeof(DLSID)) == 0) + return EAS_TRUE; + + if (EAS_HWMemCmp(&DLSID_XGInHardware, pGUID, sizeof(DLSID)) == 0) + return EAS_TRUE; + + if (EAS_HWMemCmp(&DLSID_SupportsDLS1, pGUID, sizeof(DLSID)) == 0) + { + *pValue = 0xffffffff; + return EAS_TRUE; + } + + if (EAS_HWMemCmp(&DLSID_SupportsDLS2, pGUID, sizeof(DLSID)) == 0) + return EAS_TRUE; + + if (EAS_HWMemCmp(&DLSID_SampleMemorySize, pGUID, sizeof(DLSID)) == 0) + { + *pValue = MAX_DLS_MEMORY; + return EAS_TRUE; + } + + if (EAS_HWMemCmp(&DLSID_ManufacturersID, pGUID, sizeof(DLSID)) == 0) + { + *pValue = 0x0000013A; + return EAS_TRUE; + } + + if (EAS_HWMemCmp(&DLSID_ProductID, pGUID, sizeof(DLSID)) == 0) + { + *pValue = LIB_VERSION; + return EAS_TRUE; + } + + if (EAS_HWMemCmp(&DLSID_SamplePlaybackRate, pGUID, sizeof(DLSID)) == 0) + { + *pValue = (EAS_U32) outputSampleRate; + return EAS_TRUE; + } + + /* unrecognized DLSID */ + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * ReadDLSID () + *---------------------------------------------------------------------------- + * Purpose: + * Reads a DLSID in a manner that is not sensitive to processor endian-ness + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReadDLSID (SDLS_SYNTHESIZER_DATA *pDLSData, DLSID *pDLSID) +{ + EAS_RESULT result; + EAS_I32 n; + + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data1, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data2, EAS_FALSE)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data3, EAS_FALSE)) != EAS_SUCCESS) + return result; + return EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, pDLSID->Data4, sizeof(pDLSID->Data4), &n); +} + +/*---------------------------------------------------------------------------- + * Parse_cdl () + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT Parse_cdl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 size, EAS_U32 *pValue) +{ + EAS_RESULT result; + EAS_U32 stack[CDL_STACK_SIZE]; + EAS_U16 opcode; + EAS_INT stackPtr; + EAS_U32 x, y; + DLSID dlsid; + + stackPtr = -1; + *pValue = 0; + x = 0; + while (size) + { + /* read the opcode */ + if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &opcode, EAS_FALSE)) != EAS_SUCCESS) + return result; + + /* handle binary opcodes */ + if (opcode <= DLS_CDL_EQ) + { + /* pop X and Y */ + if ((result = PopcdlStack(stack, &stackPtr, &x)) != EAS_SUCCESS) + return result; + if ((result = PopcdlStack(stack, &stackPtr, &y)) != EAS_SUCCESS) + return result; + switch (opcode) + { + case DLS_CDL_AND: + x = x & y; + break; + case DLS_CDL_OR: + x = x | y; + break; + case DLS_CDL_XOR: + x = x ^ y; + break; + case DLS_CDL_ADD: + x = x + y; + break; + case DLS_CDL_SUBTRACT: + x = x - y; + break; + case DLS_CDL_MULTIPLY: + x = x * y; + break; + case DLS_CDL_DIVIDE: + if (!y) + return EAS_ERROR_FILE_FORMAT; + x = x / y; + break; + case DLS_CDL_LOGICAL_AND: + x = (x && y); + break; + case DLS_CDL_LOGICAL_OR: + x = (x || y); + break; + case DLS_CDL_LT: + x = (x < y); + break; + case DLS_CDL_LE: + x = (x <= y); + break; + case DLS_CDL_GT: + x = (x > y); + break; + case DLS_CDL_GE: + x = (x >= y); + break; + case DLS_CDL_EQ: + x = (x == y); + break; + default: + break; + } + } + + else if (opcode == DLS_CDL_NOT) + { + if ((result = PopcdlStack(stack, &stackPtr, &x)) != EAS_SUCCESS) + return result; + x = !x; + } + + else if (opcode == DLS_CDL_CONST) + { + if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &x, EAS_FALSE)) != EAS_SUCCESS) + return result; + } + + else if (opcode == DLS_CDL_QUERY) + { + if ((result = ReadDLSID(pDLSData, &dlsid)) != EAS_SUCCESS) + return result; + QueryGUID(&dlsid, &x); + } + + else if (opcode == DLS_CDL_QUERYSUPPORTED) + { + if ((result = ReadDLSID(pDLSData, &dlsid)) != EAS_SUCCESS) + return result; + x = QueryGUID(&dlsid, &y); + } + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported opcode %d in DLS file\n", opcode); */ } + + /* push the result on the stack */ + if ((result = PushcdlStack(stack, &stackPtr, x)) != EAS_SUCCESS) + return result; + } + + /* pop the last result off the stack */ + return PopcdlStack(stack, &stackPtr, pValue); +} + +/*---------------------------------------------------------------------------- + * Convert_rgn() + *---------------------------------------------------------------------------- + * Purpose: + * Convert region data from DLS to EAS + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static void Convert_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_U16 regionIndex, EAS_U16 artIndex, EAS_U16 waveIndex, S_WSMP_DATA *pWsmp) +{ + S_DLS_REGION *pRgn; + + /* setup pointers to data structures */ + pRgn = &pDLSData->pDLS->pDLSRegions[regionIndex]; + + /* intiailize indices */ + pRgn->wtRegion.artIndex = artIndex; + pRgn->wtRegion.waveIndex = waveIndex; + + /* convert region data */ + /*lint -e{704} use shift for performance */ + pRgn->wtRegion.gain = (EAS_I16) (pWsmp->gain >> 16); + pRgn->wtRegion.loopStart = pWsmp->loopStart; + pRgn->wtRegion.loopEnd = (pWsmp->loopStart + pWsmp->loopLength); + pRgn->wtRegion.tuning = pWsmp->fineTune -(pWsmp->unityNote * 100) + ConvertSampleRate(pWsmp->sampleRate); + if (pWsmp->loopLength != 0) + pRgn->wtRegion.region.keyGroupAndFlags |= REGION_FLAG_IS_LOOPED; +} + +/*---------------------------------------------------------------------------- + * Convert_art() + *---------------------------------------------------------------------------- + * Purpose: + * Convert articulation data from DLS to EAS + * + * Inputs: + * + * + * Outputs: + * + * + *---------------------------------------------------------------------------- +*/ +static void Convert_art (SDLS_SYNTHESIZER_DATA *pDLSData, const S_DLS_ART_VALUES *pDLSArt, EAS_U16 artIndex) +{ + S_DLS_ARTICULATION *pArt; + + /* setup pointers to data structures */ + pArt = &pDLSData->pDLS->pDLSArticulations[artIndex]; + + /* LFO parameters */ + pArt->modLFO.lfoFreq = ConvertLFOPhaseIncrement(pDLSArt->values[PARAM_MOD_LFO_FREQ]); + pArt->modLFO.lfoDelay = -ConvertDelay(pDLSArt->values[PARAM_MOD_LFO_DELAY]); + pArt->vibLFO.lfoFreq = ConvertLFOPhaseIncrement(pDLSArt->values[PARAM_VIB_LFO_FREQ]); + pArt->vibLFO.lfoDelay = -ConvertDelay(pDLSArt->values[PARAM_VIB_LFO_DELAY]); + + /* EG1 parameters */ + pArt->eg1.delayTime = ConvertDelay(pDLSArt->values[PARAM_VOL_EG_DELAY]); + pArt->eg1.attackTime = pDLSArt->values[PARAM_VOL_EG_ATTACK]; + pArt->eg1.holdTime = pDLSArt->values[PARAM_VOL_EG_HOLD]; + pArt->eg1.decayTime = pDLSArt->values[PARAM_VOL_EG_DECAY]; + pArt->eg1.sustainLevel = ConvertSustain(pDLSArt->values[PARAM_VOL_EG_SUSTAIN]); + pArt->eg1.releaseTime = ConvertRate(pDLSArt->values[PARAM_VOL_EG_RELEASE]); + pArt->eg1.velToAttack = pDLSArt->values[PARAM_VOL_EG_VEL_TO_ATTACK]; + pArt->eg1.keyNumToDecay = pDLSArt->values[PARAM_VOL_EG_KEY_TO_DECAY]; + pArt->eg1.keyNumToHold = pDLSArt->values[PARAM_VOL_EG_KEY_TO_HOLD]; + pArt->eg1ShutdownTime = ConvertRate(pDLSArt->values[PARAM_VOL_EG_SHUTDOWN]); + + /* EG2 parameters */ + pArt->eg2.delayTime = ConvertDelay(pDLSArt->values[PARAM_MOD_EG_DELAY]); + pArt->eg2.attackTime = pDLSArt->values[PARAM_MOD_EG_ATTACK]; + pArt->eg2.holdTime = pDLSArt->values[PARAM_MOD_EG_HOLD]; + pArt->eg2.decayTime = pDLSArt->values[PARAM_MOD_EG_DECAY]; + pArt->eg2.sustainLevel = ConvertSustain(pDLSArt->values[PARAM_MOD_EG_SUSTAIN]); + pArt->eg2.releaseTime = ConvertRate(pDLSArt->values[PARAM_MOD_EG_RELEASE]); + pArt->eg2.velToAttack = pDLSArt->values[PARAM_MOD_EG_VEL_TO_ATTACK]; + pArt->eg2.keyNumToDecay = pDLSArt->values[PARAM_MOD_EG_KEY_TO_DECAY]; + pArt->eg2.keyNumToHold = pDLSArt->values[PARAM_MOD_EG_KEY_TO_HOLD]; + + /* filter parameters */ + pArt->filterCutoff = pDLSArt->values[PARAM_INITIAL_FC]; + pArt->filterQandFlags = ConvertQ(pDLSArt->values[PARAM_INITIAL_Q]); + pArt->modLFOToFc = pDLSArt->values[PARAM_MOD_LFO_TO_FC]; + pArt->modLFOCC1ToFc = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_FC]; + pArt->modLFOChanPressToFc = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_FC]; + pArt->eg2ToFc = pDLSArt->values[PARAM_MOD_EG_TO_FC]; + pArt->velToFc = pDLSArt->values[PARAM_VEL_TO_FC]; + pArt->keyNumToFc = pDLSArt->values[PARAM_KEYNUM_TO_FC]; + + /* gain parameters */ + pArt->modLFOToGain = pDLSArt->values[PARAM_MOD_LFO_TO_GAIN]; + pArt->modLFOCC1ToGain = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_GAIN]; + pArt->modLFOChanPressToGain = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN]; + + /* pitch parameters */ + pArt->tuning = pDLSArt->values[PARAM_TUNING]; + pArt->keyNumToPitch = pDLSArt->values[PARAM_KEYNUM_TO_PITCH]; + pArt->vibLFOToPitch = pDLSArt->values[PARAM_VIB_LFO_TO_PITCH]; + pArt->vibLFOCC1ToPitch = pDLSArt->values[PARAM_VIB_LFO_CC1_TO_PITCH]; + pArt->vibLFOChanPressToPitch = pDLSArt->values[PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH]; + pArt->modLFOToPitch = pDLSArt->values[PARAM_MOD_LFO_TO_PITCH]; + pArt->modLFOCC1ToPitch = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_PITCH]; + pArt->modLFOChanPressToPitch = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH]; + pArt->eg2ToPitch = pDLSArt->values[PARAM_MOD_EG_TO_PITCH]; + + /* output parameters */ + pArt->pan = ConvertPan(pDLSArt->values[PARAM_DEFAULT_PAN]); + + if (pDLSArt->values[PARAM_VEL_TO_GAIN] != 0) + pArt->filterQandFlags |= FLAG_DLS_VELOCITY_SENSITIVE; + +#ifdef _REVERB + pArt->reverbSend = pDLSArt->values[PARAM_DEFAULT_REVERB_SEND]; + pArt->cc91ToReverbSend = pDLSArt->values[PARAM_MIDI_CC91_TO_REVERB_SEND]; +#endif + +#ifdef _CHORUS + pArt->chorusSend = pDLSArt->values[PARAM_DEFAULT_CHORUS_SEND]; + pArt->cc93ToChorusSend = pDLSArt->values[PARAM_MIDI_CC93_TO_CHORUS_SEND]; +#endif +} + +/*---------------------------------------------------------------------------- + * ConvertSampleRate() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * + * Outputs: + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +static EAS_I16 ConvertSampleRate (EAS_U32 sampleRate) +{ + return (EAS_I16) (1200.0 * log10((double) sampleRate / (double) outputSampleRate) / log10(2.0)); +} + +/*---------------------------------------------------------------------------- + * ConvertSustainEG2() + *---------------------------------------------------------------------------- + * Convert sustain level to pitch/Fc multipler for EG2 + *---------------------------------------------------------------------------- +*/ +static EAS_I16 ConvertSustain (EAS_I32 sustain) +{ + /* check for sustain level of zero */ + if (sustain == 0) + return 0; + + /* convert to log2 factor */ + /*lint -e{704} use shift for performance */ + sustain = (sustain * SUSTAIN_LINEAR_CONVERSION_FACTOR) >> 15; + + if (sustain > SYNTH_FULL_SCALE_EG1_GAIN) + return SYNTH_FULL_SCALE_EG1_GAIN; + return (EAS_I16) sustain; +} + +/*---------------------------------------------------------------------------- + * ConvertDelay () + *---------------------------------------------------------------------------- + * Converts timecents to frame count. Used for LFO and envelope + * delay times. + *---------------------------------------------------------------------------- +*/ +EAS_I16 ConvertDelay (EAS_I32 timeCents) +{ + EAS_I32 temp; + + if (timeCents == ZERO_TIME_IN_CENTS) + return 0; + + /* divide time by secs per frame to get number of frames */ + temp = timeCents - dlsRateConvert; + + /* convert from time cents to 10-bit fraction */ + temp = FMUL_15x15(temp, TIME_CENTS_TO_LOG2); + + /* convert to frame count */ + temp = EAS_LogToLinear16(temp - (15 << 10)); + + if (temp < SYNTH_FULL_SCALE_EG1_GAIN) + return (EAS_I16) temp; + return SYNTH_FULL_SCALE_EG1_GAIN; +} + +/*---------------------------------------------------------------------------- + * ConvertRate () + *---------------------------------------------------------------------------- + * Convert timecents to rate + *---------------------------------------------------------------------------- +*/ +EAS_I16 ConvertRate (EAS_I32 timeCents) +{ + EAS_I32 temp; + + if (timeCents == ZERO_TIME_IN_CENTS) + return SYNTH_FULL_SCALE_EG1_GAIN; + + /* divide frame rate by time in log domain to get rate */ + temp = dlsRateConvert - timeCents; + +#if 1 + temp = EAS_Calculate2toX(temp); +#else + /* convert from time cents to 10-bit fraction */ + temp = FMUL_15x15(temp, TIME_CENTS_TO_LOG2); + + /* convert to rate */ + temp = EAS_LogToLinear16(temp); +#endif + + if (temp < SYNTH_FULL_SCALE_EG1_GAIN) + return (EAS_I16) temp; + return SYNTH_FULL_SCALE_EG1_GAIN; +} + + +/*---------------------------------------------------------------------------- + * ConvertLFOPhaseIncrement() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * + * Outputs: + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +static EAS_I16 ConvertLFOPhaseIncrement (EAS_I32 pitchCents) +{ + + /* check range */ + if (pitchCents > MAX_LFO_FREQUENCY_IN_PITCHCENTS) + pitchCents = MAX_LFO_FREQUENCY_IN_PITCHCENTS; + if (pitchCents < MIN_LFO_FREQUENCY_IN_PITCHCENTS) + pitchCents = MIN_LFO_FREQUENCY_IN_PITCHCENTS; + + /* double the rate and divide by frame rate by subtracting in log domain */ + pitchCents = pitchCents - dlsLFOFrequencyConvert; + + /* convert to phase increment */ + return (EAS_I16) EAS_Calculate2toX(pitchCents); +} + +/*---------------------------------------------------------------------------- + * ConvertPan() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * + * Outputs: + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +static EAS_I8 ConvertPan (EAS_I32 pan) +{ + + /* multiply by conversion factor */ + pan = FMUL_15x15 (PAN_CONVERSION_FACTOR, pan); + if (pan < MIN_PAN_VALUE) + return MIN_PAN_VALUE; + if (pan > MAX_PAN_VALUE) + return MAX_PAN_VALUE; + return (EAS_I8) pan; +} + +/*---------------------------------------------------------------------------- + * ConvertQ() + *---------------------------------------------------------------------------- + * Convert the DLS filter resonance to an index value used by the synth + * that accesses tables of coefficients based on the Q. + *---------------------------------------------------------------------------- +*/ +static EAS_U8 ConvertQ (EAS_I32 q) +{ + + /* apply limits */ + if (q <= 0) + return 0; + + /* convert to table index */ + /*lint -e{704} use shift for performance */ + q = (FILTER_Q_CONVERSION_FACTOR * q + 0x4000) >> 15; + + /* apply upper limit */ + if (q >= FILTER_RESONANCE_NUM_ENTRIES) + q = FILTER_RESONANCE_NUM_ENTRIES - 1; + return (EAS_U8) q; +} + +#ifdef _DEBUG_DLS +/*---------------------------------------------------------------------------- + * DumpDLS() + *---------------------------------------------------------------------------- +*/ +static void DumpDLS (S_EAS *pEAS) +{ + S_DLS_ARTICULATION *pArt; + S_DLS_REGION *pRegion; + EAS_INT i; + EAS_INT j; + + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000022 , pEAS->numPrograms); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000023 , pEAS->numWTRegions); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000024 , pEAS->numDLSArticulations); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000025 , pEAS->numSamples); + + /* dump the instruments */ + for (i = 0; i < pEAS->numPrograms; i++) + { + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000026 , + pEAS->pPrograms[i].locale >> 16, + (pEAS->pPrograms[i].locale >> 8) & 0x7f, + pEAS->pPrograms[i].locale & 0x7f); + + for (j = pEAS->pPrograms[i].regionIndex; ; j++) + { + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000027 , j); + pRegion = &pEAS->pWTRegions[j]; + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000028 , pRegion->gain); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000029 , pRegion->region.rangeLow, pRegion->region.rangeHigh); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002a , pRegion->region.keyGroupAndFlags); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002b , pRegion->loopStart); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002c , pRegion->loopEnd); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002d , pRegion->tuning); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002e , pRegion->artIndex); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002f , pRegion->waveIndex); + + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_LAST_REGION) + break; + } + + } + + /* dump the articulation data */ + for (i = 0; i < pEAS->numDLSArticulations; i++) + { + /* articulation data */ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000030 , i); + pArt = &pEAS->pDLSArticulations[i]; + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000031 , pArt->m_nEG2toFilterDepth); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000032 , pArt->m_nEG2toPitchDepth); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000033 , pArt->m_nFilterCutoffFrequency); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000034 , pArt->m_nFilterResonance); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000035 , pArt->m_nLFOAmplitudeDepth); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000036 , pArt->m_nLFODelayTime); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000037 , pArt->m_nLFOFrequency); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000038 , pArt->m_nLFOPitchDepth); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000039 , pArt->m_nPan); + + /* EG1 data */ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003a , pArt->m_sEG1.m_nAttack); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003b , pArt->m_sEG1.m_nDecay); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003c , pArt->m_sEG1.m_nSustain); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003d , pArt->m_sEG1.m_nRelease); + + /* EG2 data */ + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003e , pArt->m_sEG2.m_nAttack); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003f , pArt->m_sEG2.m_nDecay); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000040 , pArt->m_sEG2.m_nSustain); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000041 , pArt->m_sEG2.m_nRelease); + + } + + /* dump the waves */ + for (i = 0; i < pEAS->numSamples; i++) + { + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000042 , i); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000043 , pEAS->pSampleLen[i]); + EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000044 , pEAS->ppSamples[i]); + } + +} +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mdls.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mdls.h new file mode 100755 index 0000000..42cb23d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mdls.h @@ -0,0 +1,295 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mdls.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for eas_mdls.c + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MDLS_H +#define _EAS_MDLS_H + +/*------------------------------------ + * includes + *------------------------------------ +*/ +#include "eas_sndlib.h" + + +/*------------------------------------ + * Some defines for dls.h + *------------------------------------ +*/ +#ifndef DWORD +#define DWORD EAS_I32 +#define FAR +#define SHORT EAS_I16 +#define USHORT EAS_U16 +#define LONG EAS_I32 +#define ULONG EAS_U32 +#endif + + +/* GUID struct (call it DLSID in case GUID is defined elsewhere) */ +typedef struct +{ + EAS_U32 Data1; + EAS_U16 Data2; + EAS_U16 Data3; + EAS_U8 Data4[8]; +} DLSID; + +#define DEFINE_DLSID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const DLSID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +/* maximum sample memory for DLS query support */ +#ifndef MAX_DLS_MEMORY +#define MAX_DLS_MEMORY 65536 +#endif + +/* size of conditional chunk stack */ +#ifndef CDL_STACK_SIZE +#define CDL_STACK_SIZE 8 +#endif + +/* size of read buffer for sample conversion */ +#ifndef SAMPLE_CONVERT_CHUNK_SIZE +#define SAMPLE_CONVERT_CHUNK_SIZE 32 +#endif + + +#define ZERO_TIME_IN_CENTS -32768 + +/* Pan calculation macros */ +#define PAN_CONVERSION_FACTOR 4129 +#define MAX_PAN_VALUE 63 +#define MIN_PAN_VALUE -63 + +/* multiplier to convert time cents to 10-bit fraction log for EAS_LogToLinear16 */ +#define TIME_CENTS_TO_LOG2 27962 + +/* conversion factor sustain level from percent to exponent for LogToLinear16 */ +#define SUSTAIN_LOG_CONVERSION_FACTOR 536871 +#define SUSTAIN_LOG_CONVERSION_SHIFT 15 + +/* conversion factor sustain level from percent to EG full scale */ +#define SUSTAIN_LINEAR_CONVERSION_FACTOR 1073709 + +/* conversion factor to convert frame period to decay rate */ +#define DECAY_CONVERSION_FACTOR -16 + +/*---------------------------------------------------------------------------- + * These macros define the various characteristics of the defined sample rates + *---------------------------------------------------------------------------- + * DLS_ATTACK_TIME_CONVERT log offset for conversion from time cents to attack rate + * DLS_LFO_FREQUENCY_CONVERT pitch-cents offset for LFO frequency conversion + *---------------------------------------------------------------------------- +*/ + +#if defined (_SAMPLE_RATE_8000) +#define DLS_RATE_CONVERT -9559 +#define DLS_LFO_FREQUENCY_CONVERT 5921 + +#elif defined (_SAMPLE_RATE_16000) +#define DLS_RATE_CONVERT -9559 +#define DLS_LFO_FREQUENCY_CONVERT 5921 + +#elif defined (_SAMPLE_RATE_20000) +#define DLS_RATE_CONVERT -8745 +#define DLS_LFO_FREQUENCY_CONVERT 5108 + +#elif defined (_SAMPLE_RATE_22050) +#define DLS_RATE_CONVERT -8914 +#define DLS_LFO_FREQUENCY_CONVERT 5277 + +#elif defined (_SAMPLE_RATE_24000) +#define DLS_RATE_CONVERT -9061 +#define DLS_LFO_FREQUENCY_CONVERT 5423 + +#elif defined (_SAMPLE_RATE_32000) +#define DLS_RATE_CONVERT -9559 +#define DLS_LFO_FREQUENCY_CONVERT 5921 + +#elif defined (_SAMPLE_RATE_44100) +#define DLS_RATE_CONVERT -8914 +#define DLS_LFO_FREQUENCY_CONVERT 5277 + +#elif defined (_SAMPLE_RATE_48000) +#define DLS_RATE_CONVERT -9061 +#define DLS_LFO_FREQUENCY_CONVERT 5423 + +#else +#error "_SAMPLE_RATE_XXXXX must be defined to valid rate" +#endif + +/* + * FILTER_Q_CONVERSION_FACTOR convers the 0.1dB steps in the DLS + * file to our internal 0.75 dB steps. The value is calculated + * as follows: + * + * 32768 / (10 * ) + * + * FILTER_RESONANCE_NUM_ENTRIES is the number of entries in the table +*/ +#define FILTER_Q_CONVERSION_FACTOR 4369 +#define FILTER_RESONANCE_NUM_ENTRIES 31 + +/* + * Multiplier to convert DLS gain units (10ths of a dB) to a + * power-of-two exponent for conversion to linear gain using our + * piece-wise linear approximator. Note that we ignore the lower + * 16-bits of the DLS gain value. The result is a 10-bit fraction + * that works with the EAS_LogToLinear16 function. + * + * DLS_GAIN_FACTOR = (2^18) / (200 * log10(2)) + */ +#define DLS_GAIN_FACTOR 4354 +#define DLS_GAIN_SHIFT 8 + +/* + * Reciprocal of 10 for quick divide by 10's + * + * DLS_GAIN_FACTOR = (2^18) / (200 * log10(2)) + */ +#define DLS_DIV_10_FACTOR 3277 +#define DLS_DIV_10_SHIFT 16 + +/* + * Multiplier to convert DLS time cents units to a power-of-two + * exponent for conversion to absolute time units using our + * piece-wise linear approximator. + * + * DLS_TIME_FACTOR = (2^22) / 1200 + */ +#define DLS_TIME_FACTOR 3495 +#define DLS_TIME_SHIFT 22 + + +/* LFO limits */ +#define MAX_LFO_FREQUENCY_IN_HERTZ 20 +#define MIN_LFO_FREQUENCY_IN_HERTZ 0.1 +#define MAX_LFO_FREQUENCY_IN_PITCHCENTS 1549 +#define MIN_LFO_FREQUENCY_IN_PITCHCENTS -7624 +#define MAX_LFO_AMPLITUDE_DEPTH 12 /* in dB, DLS2.1 p 31*/ +#define MIN_LFO_AMPLITUDE_DEPTH -12 /* in dB, DLS2.1 p 31*/ + +/* add to pitch cents before pow(2.0, n) to convert to frequency */ +#define ABSOLUTE_PITCH_BIAS 238395828 + +#define A5_PITCH_OFFSET 6900 + +/* +CHUNK_TYPE is a macro that converts the 4 input args into a 32-bit int +where +argument a is placed at the MSB location and +argument d is placed at the LSB location. +This is useful for determining the DLS chunk types +*/ +#define CHUNK_TYPE(a,b,c,d) ( \ + ( ((EAS_U32)(a) & 0xFF) << 24 ) \ + + ( ((EAS_U32)(b) & 0xFF) << 16 ) \ + + ( ((EAS_U32)(c) & 0xFF) << 8 ) \ + + ( ((EAS_U32)(d) & 0xFF) ) ) + +#define CHUNK_RIFF CHUNK_TYPE('R','I','F','F') +#define CHUNK_DLS CHUNK_TYPE('D','L','S',' ') +#define CHUNK_CDL CHUNK_TYPE('c','d','l',' ') +#define CHUNK_VERS CHUNK_TYPE('v','e','r','s') +#define CHUNK_DLID CHUNK_TYPE('d','l','i','d') +#define CHUNK_LIST CHUNK_TYPE('L','I','S','T') +#define CHUNK_COLH CHUNK_TYPE('c','o','l','h') +#define CHUNK_LINS CHUNK_TYPE('l','i','n','s') +#define CHUNK_PTBL CHUNK_TYPE('p','t','b','l') +#define CHUNK_WVPL CHUNK_TYPE('w','v','p','l') +#define CHUNK_INFO CHUNK_TYPE('I','N','F','O') +#define CHUNK_INAM CHUNK_TYPE('I','N','A','M') +#define CHUNK_INS CHUNK_TYPE('i','n','s',' ') +#define CHUNK_INSH CHUNK_TYPE('i','n','s','h') +#define CHUNK_LRGN CHUNK_TYPE('l','r','g','n') +#define CHUNK_RGN CHUNK_TYPE('r','g','n',' ') +#define CHUNK_RGN2 CHUNK_TYPE('r','g','n','2') +#define CHUNK_RGNH CHUNK_TYPE('r','g','n','h') +#define CHUNK_WSMP CHUNK_TYPE('w','s','m','p') +#define CHUNK_WLNK CHUNK_TYPE('w','l','n','k') +#define CHUNK_LART CHUNK_TYPE('l','a','r','t') +#define CHUNK_LAR2 CHUNK_TYPE('l','a','r','2') +#define CHUNK_ART1 CHUNK_TYPE('a','r','t','1') +#define CHUNK_ART2 CHUNK_TYPE('a','r','t','2') +#define CHUNK_WAVE CHUNK_TYPE('w','a','v','e') +#define CHUNK_FMT CHUNK_TYPE('f','m','t',' ') +#define CHUNK_DATA CHUNK_TYPE('d','a','t','a') +#define CHUNK_DMPR CHUNK_TYPE('d','m','p','r') + + +#define WAVE_FORMAT_PCM 0x0001 /* Microsoft PCM format, see DLS2.1 p60 */ +#define WAVE_FORMAT_EXTENSIBLE 0xffff + +/* defines for wave table structures */ + +/* initialize each articulation structure to a harmless state */ +/* change art values after we've determined EAS internals */ +#define DEFAULT_DLS_FILTER_CUTOFF_FREQUENCY 0x7FFF /* DLS2.1, p 31 means leave filter off */ + +/**********/ + +/* define the waves that we expect to generate instead of store */ +/* NOTE: our comparison routine converts the input string +to lowercase, so the following comparison values should all +be in lowercase. +*/ +#define STRING_NOISE "noise" + + +/*------------------------------------ + * type definitions + *------------------------------------ +*/ +#ifdef _STANDALONE_CONVERTER +typedef struct s_dls_params +{ + EAS_INT sampleRate; + EAS_INT samplesPerFrame; + EAS_INT bitDepth; + double ditherLevel; + double ditherFilterCoeff; + EAS_BOOL compatibility; + EAS_BOOL encodeADPCM; +} S_DLS_PARAMS; +#endif + + +/* function prototypes */ +EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, S_DLS **pDLS); +EAS_RESULT DLSCleanup (EAS_HW_DATA_HANDLE hwInstData, S_DLS *pDLS); +void DLSAddRef (S_DLS *pDLS); +EAS_I16 ConvertDelay (EAS_I32 timeCents); +EAS_I16 ConvertRate (EAS_I32 timeCents); + + +#ifdef _STANDALONE_CONVERTER +void DLSConvParams (S_DLS_PARAMS *pParams, EAS_BOOL set); +#endif + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midi.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midi.c new file mode 100755 index 0000000..8cb043a --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midi.c @@ -0,0 +1,569 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midi.c + * + * Contents and purpose: + * This file implements the MIDI stream parser. It is called by eas_smf.c to parse MIDI messages + * that are streamed out of the file. It can also parse live MIDI streams. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 794 $ + * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_miditypes.h" +#include "eas_midi.h" +#include "eas_vm_protos.h" +#include "eas_parser.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + + +/* state enumerations for ProcessSysExMessage */ +typedef enum +{ + eSysEx, + eSysExUnivNonRealTime, + eSysExUnivNrtTargetID, + eSysExGMControl, + eSysExUnivRealTime, + eSysExUnivRtTargetID, + eSysExDeviceControl, + eSysExMasterVolume, + eSysExMasterVolLSB, + eSysExSPMIDI, + eSysExSPMIDIchan, + eSysExSPMIDIMIP, + eSysExMfgID1, + eSysExMfgID2, + eSysExMfgID3, + eSysExEnhancer, + eSysExEnhancerSubID, + eSysExEnhancerFeedback1, + eSysExEnhancerFeedback2, + eSysExEnhancerDrive, + eSysExEnhancerWet, + eSysExEOX, + eSysExIgnore +} E_SYSEX_STATES; + +/* local prototypes */ +static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode); +static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode); + +/*---------------------------------------------------------------------------- + * EAS_InitMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the MIDI stream state for parsing. + * + * Inputs: + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream) +{ + pMIDIStream->byte3 = EAS_FALSE; + pMIDIStream->pending = EAS_FALSE; + pMIDIStream->runningStatus = 0; + pMIDIStream->status = 0; +} + +/*---------------------------------------------------------------------------- + * EAS_ParseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled) + * so the interface works equally well for both file and stream I/O. + * + * Inputs: + * c - character from MIDI stream + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) +{ + + /* check for new status byte */ + if (c & 0x80) + { + /* save new running status */ + if (c < 0xf8) + { + pMIDIStream->runningStatus = c; + pMIDIStream->byte3 = EAS_FALSE; + + /* deal with SysEx */ + if ((c == 0xf7) || (c == 0xf0)) + { + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode); + } + + /* inform the file parser that we're in the middle of a message */ + if ((c < 0xf4) || (c > 0xf6)) + pMIDIStream->pending = EAS_TRUE; + } + + /* real-time message - ignore it */ + return EAS_SUCCESS; + } + + /* 3rd byte of a 3-byte message? */ + if (pMIDIStream->byte3) + { + pMIDIStream->d2 = c; + pMIDIStream->byte3 = EAS_FALSE; + pMIDIStream->pending = EAS_FALSE; + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode); + } + + /* check for status received */ + if (pMIDIStream->runningStatus) + { + + /* save new status and data byte */ + pMIDIStream->status = pMIDIStream->runningStatus; + + /* check for 3-byte messages */ + if (pMIDIStream->status < 0xc0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_TRUE; + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + + /* check for 2-byte messages */ + if (pMIDIStream->status < 0xe0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_FALSE; + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode); + } + + /* check for more 3-bytes message */ + if (pMIDIStream->status < 0xf0) + { + pMIDIStream->d1 = c; + pMIDIStream->pending = EAS_TRUE; + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + + /* SysEx message? */ + if (pMIDIStream->status == 0xF0) + { + if (parserMode == eParserModeMetaData) + return EAS_SUCCESS; + return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode); + } + + /* remaining messages all clear running status */ + pMIDIStream->runningStatus = 0; + + /* F2 is 3-byte message */ + if (pMIDIStream->status == 0xf2) + { + pMIDIStream->byte3 = EAS_TRUE; + return EAS_SUCCESS; + } + } + + /* no status byte received, provide a warning, but we should be able to recover */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Received MIDI data without a valid status byte: %d\n",c); */ } + pMIDIStream->pending = EAS_FALSE; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * ProcessMIDIMessage() + *---------------------------------------------------------------------------- + * Purpose: + * This function processes a typical MIDI message. All of the data has been received, just need + * to take appropriate action. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode) +{ + EAS_U8 channel; + + channel = pMIDIStream->status & 0x0f; + switch (pMIDIStream->status & 0xf0) + { + case 0x80: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode <= eParserModeMute) + VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + break; + + case 0x90: + if (pMIDIStream->d2) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOn: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + pMIDIStream->flags |= MIDI_FLAG_FIRST_NOTE; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + } + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode <= eParserModeMute) + VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + } + break; + + case 0xa0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PolyPres: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + break; + + case 0xb0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Control: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode <= eParserModeMute) + VMControlChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); +#ifdef JET_INTERFACE + if (pMIDIStream->jetData & MIDI_FLAGS_JET_CB) + { + JET_Event(pEASData, pMIDIStream->jetData & (JET_EVENT_SEG_MASK | JET_EVENT_TRACK_MASK), + channel, pMIDIStream->d1, pMIDIStream->d2); + } +#endif + break; + + case 0xc0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Program: %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1); */ } + if (parserMode <= eParserModeMute) + VMProgramChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1); + break; + + case 0xd0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"ChanPres: %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1); */ } + if (parserMode <= eParserModeMute) + VMChannelPressure(pSynth, channel, pMIDIStream->d1); + break; + + case 0xe0: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PBend: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + if (parserMode <= eParserModeMute) + VMPitchBend(pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Unknown: %02x %02x %02x\n", + pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * ProcessSysExMessage() + *---------------------------------------------------------------------------- + * Purpose: + * Process a SysEx character byte from the MIDI stream. Since we cannot + * simply wait for the next character to arrive, we are forced to save + * state after each character. It would be easier to parse at the file + * level, but then we lose the nice feature of being able to support + * these messages in a real-time MIDI stream. + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * c - character to be processed + * locating - if true, the sequencer is relocating to a new position + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * These are the SysEx messages we can receive: + * + * SysEx messages + * { f0 7e 7f 09 01 f7 } GM 1 On + * { f0 7e 7f 09 02 f7 } GM 1/2 Off + * { f0 7e 7f 09 03 f7 } GM 2 On + * { f0 7f 7f 04 01 lsb msb } Master Volume + * { f0 7f 7f 0b 01 ch mip [ch mip ...] f7 } SP-MIDI + * { f0 00 01 3a 04 01 fdbk1 fdbk2 drive wet dry f7 } Enhancer + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) +{ + + /* check for start byte */ + if (c == 0xf0) + { + pMIDIStream->sysExState = eSysEx; + } + /* check for end byte */ + else if (c == 0xf7) + { + /* if this was a MIP message, update the MIP table */ + if ((pMIDIStream->sysExState == eSysExSPMIDIchan) && (parserMode != eParserModeMetaData)) + VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); + pMIDIStream->sysExState = eSysExIgnore; + } + + /* process SysEx message */ + else + { + switch (pMIDIStream->sysExState) + { + case eSysEx: + + /* first byte, determine message class */ + switch (c) + { + case 0x7e: + pMIDIStream->sysExState = eSysExUnivNonRealTime; + break; + case 0x7f: + pMIDIStream->sysExState = eSysExUnivRealTime; + break; + case 0x00: + pMIDIStream->sysExState = eSysExMfgID1; + break; + default: + pMIDIStream->sysExState = eSysExIgnore; + break; + } + break; + + /* process GM message */ + case eSysExUnivNonRealTime: + if (c == 0x7f) + pMIDIStream->sysExState = eSysExUnivNrtTargetID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExUnivNrtTargetID: + if (c == 0x09) + pMIDIStream->sysExState = eSysExGMControl; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExGMControl: + if ((c == 1) || (c == 3)) + { + /* GM 1 or GM2 On, reset synth */ + if (parserMode != eParserModeMetaData) + { + pMIDIStream->flags |= MIDI_FLAG_GM_ON; + VMReset(pEASData->pVoiceMgr, pSynth, EAS_FALSE); + VMInitMIPTable(pSynth); + } + pMIDIStream->sysExState = eSysExEOX; + } + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + /* Process Master Volume and SP-MIDI */ + case eSysExUnivRealTime: + if (c == 0x7f) + pMIDIStream->sysExState = eSysExUnivRtTargetID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExUnivRtTargetID: + if (c == 0x04) + pMIDIStream->sysExState = eSysExDeviceControl; + else if (c == 0x0b) + pMIDIStream->sysExState = eSysExSPMIDI; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + /* process master volume */ + case eSysExDeviceControl: + if (c == 0x01) + pMIDIStream->sysExState = eSysExMasterVolume; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMasterVolume: + /* save LSB */ + pMIDIStream->d1 = c; + pMIDIStream->sysExState = eSysExMasterVolLSB; + break; + + case eSysExMasterVolLSB: + if (parserMode != eParserModeMetaData) + { + EAS_I32 gain = ((EAS_I32) c << 8) | ((EAS_I32) pMIDIStream->d1 << 1); + gain = (gain * gain) >> 15; + VMSetVolume(pSynth, (EAS_U16) gain); + } + pMIDIStream->sysExState = eSysExEOX; + break; + + /* process SP-MIDI MIP message */ + case eSysExSPMIDI: + if (c == 0x01) + { + /* assume all channels are muted */ + if (parserMode != eParserModeMetaData) + VMInitMIPTable(pSynth); + pMIDIStream->d1 = 0; + pMIDIStream->sysExState = eSysExSPMIDIchan; + } + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExSPMIDIchan: + if (c < NUM_SYNTH_CHANNELS) + { + pMIDIStream->d2 = c; + pMIDIStream->sysExState = eSysExSPMIDIMIP; + } + else + { + /* bad MIP message - unmute channels */ + if (parserMode != eParserModeMetaData) + VMInitMIPTable(pSynth); + pMIDIStream->sysExState = eSysExIgnore; + } + break; + + case eSysExSPMIDIMIP: + /* process MIP entry here */ + if (parserMode != eParserModeMetaData) + VMSetMIPEntry(pEASData->pVoiceMgr, pSynth, pMIDIStream->d2, pMIDIStream->d1, c); + pMIDIStream->sysExState = eSysExSPMIDIchan; + + /* if 16 channels received, update MIP table */ + if (++pMIDIStream->d1 == NUM_SYNTH_CHANNELS) + { + if (parserMode != eParserModeMetaData) + VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); + pMIDIStream->sysExState = eSysExEOX; + } + break; + + /* process Enhancer */ + case eSysExMfgID1: + if (c == 0x01) + pMIDIStream->sysExState = eSysExMfgID1; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMfgID2: + if (c == 0x3a) + pMIDIStream->sysExState = eSysExMfgID1; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExMfgID3: + if (c == 0x04) + pMIDIStream->sysExState = eSysExEnhancer; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExEnhancer: + if (c == 0x01) + pMIDIStream->sysExState = eSysExEnhancerSubID; + else + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExEnhancerSubID: + pMIDIStream->sysExState = eSysExEnhancerFeedback1; + break; + + case eSysExEnhancerFeedback1: + pMIDIStream->sysExState = eSysExEnhancerFeedback2; + break; + + case eSysExEnhancerFeedback2: + pMIDIStream->sysExState = eSysExEnhancerDrive; + break; + + case eSysExEnhancerDrive: + pMIDIStream->sysExState = eSysExEnhancerWet; + break; + + case eSysExEnhancerWet: + pMIDIStream->sysExState = eSysExEOX; + break; + + case eSysExEOX: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Expected F7, received %02x\n", c); */ } + pMIDIStream->sysExState = eSysExIgnore; + break; + + case eSysExIgnore: + break; + + default: + pMIDIStream->sysExState = eSysExIgnore; + break; + } + } + + if (pMIDIStream->sysExState == eSysExIgnore) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Ignoring SysEx byte %02x\n", c); */ } + return EAS_SUCCESS; +} /* end ProcessSysExMessage */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midi.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midi.h new file mode 100755 index 0000000..10649a0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midi.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midi.h + * + * Contents and purpose: + * Prototypes for MIDI stream parsing functions + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDI_H +#define _EAS_MIDI_H + +/*---------------------------------------------------------------------------- + * EAS_InitMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the MIDI stream state for parsing. + * + * Inputs: + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream); + +/*---------------------------------------------------------------------------- + * EAS_ParseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled) + * so the interface works equally well for both file and stream I/O. + * + * Inputs: + * c - character from MIDI stream + * + * Outputs: + * returns EAS_RESULT (EAS_SUCCESS is OK) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode); + +#endif /* #define _EAS_MIDI_H */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midictrl.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midictrl.h new file mode 100755 index 0000000..46fdc4f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midictrl.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_midictrl.h + * + * Contents and purpose: + * MIDI controller definitions + * + * This header only contains declarations that are specific + * to this implementation. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDICTRL_H +#define _EAS_MIDICTRL_H + +/* define controller types */ +/* + Note that these controller types are specified in base 10 (decimal) + and not in hexadecimal. The above midi messages are specified + in hexadecimal. +*/ +#define MIDI_CONTROLLER_BANK_SELECT 0 +#define MIDI_CONTROLLER_BANK_SELECT_MSB 0 +#define MIDI_CONTROLLER_MOD_WHEEL 1 +#define MIDI_CONTROLLER_ENTER_DATA_MSB 6 +#define MIDI_CONTROLLER_VOLUME 7 +#define MIDI_CONTROLLER_PAN 10 +#define MIDI_CONTROLLER_EXPRESSION 11 +#define MIDI_CONTROLLER_BANK_SELECT_LSB 32 +#define MIDI_CONTROLLER_ENTER_DATA_LSB 38 /* 0x26 */ +#define MIDI_CONTROLLER_SUSTAIN_PEDAL 64 +#define MIDI_CONTROLLER_SELECT_NRPN_LSB 98 +#define MIDI_CONTROLLER_SELECT_NRPN_MSB 99 +#define MIDI_CONTROLLER_SELECT_RPN_LSB 100 /* 0x64 */ +#define MIDI_CONTROLLER_SELECT_RPN_MSB 101 /* 0x65 */ +#define MIDI_CONTROLLER_ALL_SOUND_OFF 120 +#define MIDI_CONTROLLER_RESET_CONTROLLERS 121 +#define MIDI_CONTROLLER_ALL_NOTES_OFF 123 +#define MIDI_CONTROLLER_OMNI_OFF 124 +#define MIDI_CONTROLLER_OMNI_ON 125 +#define MIDI_CONTROLLER_MONO_ON_POLY_OFF 126 +#define MIDI_CONTROLLER_POLY_ON_MONO_OFF 127 + +#endif /* #ifndef _EAS_MIDICTRL_H */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mididata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mididata.c new file mode 100755 index 0000000..4463b7e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mididata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mididata.c + * + * Contents and purpose: + * Data module for MIDI stream interface + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_miditypes.h" + +S_INTERACTIVE_MIDI eas_MIDIData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_miditypes.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_miditypes.h new file mode 100755 index 0000000..015f08b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_miditypes.h @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_miditypes.h + * + * Contents and purpose: + * Contains declarations for the MIDI stream parser. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIDITYPES_H +#define _EAS_MIDITYPES_H + +#include "eas_data.h" +#include "eas_parser.h" + +/*---------------------------------------------------------------------------- + * S_MIDI_STREAM + * + * Maintains parser state for the MIDI stream parser + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_midi_stream_tag +{ + EAS_BOOL8 byte3; /* flag indicates 3rd byte expected */ + EAS_BOOL8 pending; /* flag indicates more data expected */ + EAS_U8 sysExState; /* maintains the SysEx state */ + EAS_U8 runningStatus; /* last running status received */ + EAS_U8 status; /* status byte */ + EAS_U8 d1; /* first data byte */ + EAS_U8 d2; /* second data byte */ + EAS_U8 flags; /* flags - see below for definition */ +#ifdef JET_INTERFACE + EAS_U32 jetData; /* JET data */ +#endif +} S_MIDI_STREAM; + +/* flags for S_MIDI_STREAM.flags */ +#define MIDI_FLAG_GM_ON 0x01 /* GM System On message received */ +#define MIDI_FLAG_FIRST_NOTE 0x02 /* first note received */ + +/* flags for S_MIDI_STREAM.jetFlags */ +#define MIDI_FLAGS_JET_MUTE 0x00000001 /* track is muted */ +#define MIDI_FLAGS_JET_CB 0x00000002 /* JET callback enabled */ + +/*---------------------------------------------------------------------------- + * + * S_SMF_STREAM + * + * This structure contains data required to parse an SMF stream. For SMF0 files, there + * will be a single instance of this per file. For SMF1 files, there will be multiple instance, + * one for each separate stream in the file. + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_smf_stream_tag +{ + EAS_FILE_HANDLE fileHandle; /* host wrapper file handle */ + EAS_U32 ticks; /* time of next event in stream */ + EAS_I32 startFilePos; /* start location of track within file */ + S_MIDI_STREAM midiStream; /* MIDI stream state */ +} S_SMF_STREAM; + +/*---------------------------------------------------------------------------- + * + * S_SMF_DATA + * + * This structure contains the instance data required to parse an SMF stream. + * + *---------------------------------------------------------------------------- +*/ + +typedef struct s_smf_data_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + S_SMF_STREAM *streams; /* pointer to individual streams in file */ + S_SMF_STREAM *nextStream; /* pointer to next stream with event */ + S_SYNTH *pSynth; /* pointer to synth */ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I32 fileOffset; /* for embedded files */ + EAS_I32 time; /* current time in milliseconds/256 */ + EAS_U16 numStreams; /* actual number of streams */ + EAS_U16 tickConv; /* current MIDI tick to msec conversion */ + EAS_U16 ppqn; /* ticks per quarter note */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 flags; /* flags - see definitions below */ +} S_SMF_DATA; + +#define SMF_FLAGS_CHASE_MODE 0x01 /* chase mode - skip to first note */ +#define SMF_FLAGS_HAS_TIME_SIG 0x02 /* time signature encountered at time 0 */ +#define SMF_FLAGS_HAS_TEMPO 0x04 /* tempo encountered at time 0 */ +#define SMF_FLAGS_HAS_GM_ON 0x08 /* GM System On encountered at time 0 */ +#define SMF_FLAGS_JET_STREAM 0x80 /* JET in use - keep strict timing */ + +/* combo flags indicate setup bar */ +#define SMF_FLAGS_SETUP_BAR (SMF_FLAGS_HAS_TIME_SIG | SMF_FLAGS_HAS_TEMPO | SMF_FLAGS_HAS_GM_ON) + +/*---------------------------------------------------------------------------- + * Interactive MIDI structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_interactive_midi_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + S_SYNTH *pSynth; /* pointer to synth */ + S_MIDI_STREAM stream; /* stream data */ +} S_INTERACTIVE_MIDI; + +#endif /* #ifndef _EAS_MIDITYPES_H */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixbuf.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixbuf.c new file mode 100755 index 0000000..db5bd02 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixbuf.c @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixbuf.c + * + * Contents and purpose: + * Contains a data allocation for synthesizer + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" +#include "eas_mixer.h" + +// globals +EAS_I32 eas_MixBuffer[BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS]; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixer.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixer.c new file mode 100755 index 0000000..0a839a8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixer.c @@ -0,0 +1,464 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixer.c + * + * Contents and purpose: + * This file contains the critical components of the mix engine that + * must be optimized for best performance. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 706 $ + * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +//3 dls: This module is in the midst of being converted from a synth +//3 specific module to a general purpose mix engine + +/*------------------------------------ + * includes + *------------------------------------ +*/ +#include "eas_data.h" +#include "eas_host.h" +#include "eas_math.h" +#include "eas_mixer.h" +#include "eas_config.h" +#include "eas_report.h" + +#ifdef _MAXIMIZER_ENABLED +EAS_I32 MaximizerProcess (EAS_VOID_PTR pInstData, EAS_I32 *pSrc, EAS_I32 *pDst, EAS_I32 numSamples); +#endif + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +/* need to boost stereo by ~3dB to compensate for the panner */ +#define STEREO_3DB_GAIN_BOOST 512 + +/*---------------------------------------------------------------------------- + * EAS_MixEngineInit() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the mix engine for work, allocates buffers, locates effects modules, etc. + * + * Inputs: + * pEASData - instance data + * pInstData - pointer to variable to receive instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineInit (S_EAS_DATA *pEASData) +{ + + /* check Configuration Module for mix buffer allocation */ + if (pEASData->staticMemoryModel) + pEASData->pMixBuffer = EAS_CMEnumData(EAS_CM_MIX_BUFFER); + else + pEASData->pMixBuffer = EAS_HWMalloc(pEASData->hwInstData, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32)); + if (pEASData->pMixBuffer == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate mix buffer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet((void *)(pEASData->pMixBuffer), 0, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32)); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePrep() + *---------------------------------------------------------------------------- + * Purpose: + * Performs prep before synthesize a buffer of audio, such as clearing + * audio buffers, etc. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePrep (S_EAS_DATA *pEASData, EAS_I32 numSamples) +{ + + /* clear the mix buffer */ +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_HWMemSet(pEASData->pMixBuffer, 0, numSamples * (EAS_I32) sizeof(long) * 2); +#else + EAS_HWMemSet(pEASData->pMixBuffer, 0, (EAS_I32) numSamples * (EAS_I32) sizeof(long)); +#endif + + /* need to clear other side-chain effect buffers (chorus & reverb) */ +} + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePost + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the post-processing after all voices have been + * synthesized. It calls any sweeteners and does the final mixdown to + * the output buffer. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePost (S_EAS_DATA *pEASData, EAS_I32 numSamples) +{ + EAS_U16 gain; + +//3 dls: Need to restore the mix engine metrics + + /* calculate the gain multiplier */ +#ifdef _MAXIMIZER_ENABLED + if (pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effect) + { + EAS_I32 temp; + temp = MaximizerProcess(pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effectData, pEASData->pMixBuffer, pEASData->pMixBuffer, numSamples); + temp = (temp * pEASData->masterGain) >> 15; + if (temp > 32767) + gain = 32767; + else + gain = (EAS_U16) temp; + } + else + gain = (EAS_U16) pEASData->masterGain; +#else + gain = (EAS_U16) pEASData->masterGain; +#endif + + /* Not using all the gain bits for now + * Reduce the input to the compressor by 6dB to prevent saturation + */ +#ifdef _COMPRESSOR_ENABLED + if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData) + gain = gain >> 5; + else + gain = gain >> 4; +#else + gain = gain >> 4; +#endif + + /* convert 32-bit mix buffer to 16-bit output format */ +#if (NUM_OUTPUT_CHANNELS == 2) + SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) ((EAS_U16) numSamples * 2)); +#else + SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) numSamples); +#endif + +#ifdef _ENHANCER_ENABLED + /* enhancer effect */ + if (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData) + (*pEASData->effectsModules[EAS_MODULE_ENHANCER].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _GRAPHIC_EQ_ENABLED + /* graphic EQ effect */ + if (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData) + (*pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _COMPRESSOR_ENABLED + /* compressor effect */ + if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData) + (*pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _WOW_ENABLED + /* WOW requires a 32-bit buffer, borrow the mix buffer and + * pass it as the destination buffer + */ + /*lint -e{740} temporarily passing a parameter through an existing I/F */ + if (pEASData->effectsModules[EAS_MODULE_WOW].effectData) + (*pEASData->effectsModules[EAS_MODULE_WOW].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_WOW].effectData, + pEASData->pOutputAudioBuffer, + (EAS_PCM*) pEASData->pMixBuffer, + numSamples); +#endif + +#ifdef _TONECONTROLEQ_ENABLED + /* ToneControlEQ effect */ + if (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData) + (*pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _REVERB_ENABLED + /* Reverb effect */ + if (pEASData->effectsModules[EAS_MODULE_REVERB].effectData) + (*pEASData->effectsModules[EAS_MODULE_REVERB].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_REVERB].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +#ifdef _CHORUS_ENABLED + /* Chorus effect */ + if (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData) + (*pEASData->effectsModules[EAS_MODULE_CHORUS].effect->pfProcess) + (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData, + pEASData->pOutputAudioBuffer, + pEASData->pOutputAudioBuffer, + numSamples); +#endif + +} + +#ifndef NATIVE_EAS_KERNEL +/*---------------------------------------------------------------------------- + * SynthMasterGain + *---------------------------------------------------------------------------- + * Purpose: + * Mixes down audio from 32-bit to 16-bit target buffer + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void SynthMasterGain (long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 numSamples) { + + /* loop through the buffer */ + while (numSamples--) { + long s; + + /* read a sample from the input buffer and add some guard bits */ + s = *pInputBuffer++; + + /* add some guard bits */ + /*lint -e{704} */ + s = s >> 7; + + /* apply master gain */ + s *= (long) nGain; + + /* shift to lower 16-bits */ + /*lint -e{704} */ + s = s >> 9; + + /* saturate */ + s = SATURATE(s); + + *pOutputBuffer++ = (EAS_PCM)s; + } +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_MixEngineShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down effects modules and deallocates memory + * + * Inputs: + * pEASData - instance data + * pInstData - instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineShutdown (S_EAS_DATA *pEASData) +{ + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel && (pEASData->pMixBuffer != NULL)) + EAS_HWFree(pEASData->hwInstData, pEASData->pMixBuffer); + + return EAS_SUCCESS; +} + +#ifdef UNIFIED_MIXER +#ifndef NATIVE_MIX_STREAM +/*---------------------------------------------------------------------------- + * EAS_MixStream + *---------------------------------------------------------------------------- + * Mix a 16-bit stream into a 32-bit buffer + * + * pInputBuffer 16-bit input buffer + * pMixBuffer 32-bit mix buffer + * numSamples number of samples to mix + * gainLeft initial gain left or mono + * gainRight initial gain right + * gainLeft left gain increment per sample + * gainRight right gain increment per sample + * flags bit 0 = stereo source + * bit 1 = stereo output + *---------------------------------------------------------------------------- +*/ +void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags) +{ + EAS_I32 temp; + EAS_INT src, dest; + + /* NOTE: There are a lot of optimizations that can be done + * in the native implementations based on register + * availability, etc. For example, it may make sense to + * break this down into 8 separate routines: + * + * 1. Mono source to mono output + * 2. Mono source to stereo output + * 3. Stereo source to mono output + * 4. Stereo source to stereo output + * 5. Mono source to mono output - no gain change + * 6. Mono source to stereo output - no gain change + * 7. Stereo source to mono output - no gain change + * 8. Stereo source to stereo output - no gain change + * + * Other possibilities include loop unrolling, skipping + * a gain calculation every 2 or 4 samples, etc. + */ + + /* no gain change, use fast loops */ + if ((gainIncLeft == 0) && (gainIncRight == 0)) + { + switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT)) + { + /* mono to mono */ + case 0: + gainLeft >>= 15; + for (src = dest = 0; src < numSamples; src++, dest++) + { + + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* mono to stereo */ + case MIX_FLAGS_STEREO_OUTPUT: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src++, dest+=2) + { + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src] * gainRight) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* stereo to mono */ + case MIX_FLAGS_STEREO_SOURCE: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src+=2, dest++) + { + temp = (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + temp += ((pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS); + pMixBuffer[dest] += temp; + } + break; + + /* stereo to stereo */ + case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT: + gainLeft >>= 15; + gainRight >>= 15; + for (src = dest = 0; src < numSamples; src+=2, dest+=2) + { + pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS; + } + break; + } + } + + /* gain change - do gain increment */ + else + { + switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT)) + { + /* mono to mono */ + case 0: + for (src = dest = 0; src < numSamples; src++, dest++) + { + gainLeft += gainIncLeft; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* mono to stereo */ + case MIX_FLAGS_STEREO_OUTPUT: + for (src = dest = 0; src < numSamples; src++, dest+=2) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + + /* stereo to mono */ + case MIX_FLAGS_STEREO_SOURCE: + for (src = dest = 0; src < numSamples; src+=2, dest++) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + temp = (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + temp += ((pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS); + pMixBuffer[dest] += temp; + } + break; + + /* stereo to stereo */ + case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT: + for (src = dest = 0; src < numSamples; src+=2, dest+=2) + { + gainLeft += gainIncLeft; + gainRight += gainIncRight; + pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; + pMixBuffer[dest+1] += (pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS; + } + break; + } + } +} +#endif +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixer.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixer.h new file mode 100755 index 0000000..b2eb33b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixer.h @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_mixer.h + * + * Contents and purpose: + * This file contains the critical components of the mix engine that + * must be optimized for best performance. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 706 $ + * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_MIXER_H +#define _EAS_MIXER_H + +//3 dls: This module is in the midst of being converted from a synth +//3 specific module to a general purpose mix engine + +#define MIX_FLAGS_STEREO_SOURCE 1 +#define MIX_FLAGS_STEREO_OUTPUT 2 +#define NUM_MIXER_GUARD_BITS 4 + +#include "eas_effects.h" + +extern void SynthMasterGain( long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 nNumLoopSamples); + +/*---------------------------------------------------------------------------- + * EAS_MixEngineInit() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the mix engine for work, allocates buffers, locates effects modules, etc. + * + * Inputs: + * pEASData - instance data + * pInstData - pointer to variable to receive instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineInit (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePrep() + *---------------------------------------------------------------------------- + * Purpose: + * Performs prep before synthesize a buffer of audio, such as clearing + * audio buffers, etc. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePrep (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * EAS_MixEnginePost + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the post-processing after all voices have been + * synthesized. It calls any sweeteners and does the final mixdown to + * the output buffer. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void EAS_MixEnginePost (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * EAS_MixEngineShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down effects modules and deallocates memory + * + * Inputs: + * pEASData - instance data + * pInstData - instance data handle + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_MixEngineShutdown (EAS_DATA_HANDLE pEASData); + +#ifdef UNIFIED_MIXER +/*---------------------------------------------------------------------------- + * EAS_MixStream + *---------------------------------------------------------------------------- + * Mix a 16-bit stream into a 32-bit buffer + * + * pInputBuffer 16-bit input buffer + * pMixBuffer 32-bit mix buffer + * numSamples number of samples to mix + * gainLeft initial gain left or mono + * gainRight initial gain right + * gainLeft left gain increment per sample + * gainRight right gain increment per sample + * flags bit 0 = stereo source + * bit 1 = stereo output + *---------------------------------------------------------------------------- +*/ +void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags); +#endif + +#endif /* #ifndef _EAS_MIXER_H */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ota.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ota.c new file mode 100755 index 0000000..5bc9062 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ota.c @@ -0,0 +1,1077 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_ota.c + * + * Contents and purpose: + * OTA parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_otadata.h" + +/* increase gain for mono ringtones */ +#define OTA_GAIN_OFFSET 8 + +/* file definitions */ +#define OTA_RINGTONE 0x25 +#define OTA_SOUND 0x1d +#define OTA_UNICODE 0x22 + +/* song type definitions */ +#define OTA_BASIC_SONG_TYPE 0x01 +#define OTA_TEMPORARY_SONG_TYPE 0x02 + +/* instruction ID coding */ +#define OTA_PATTERN_HEADER_ID 0x00 +#define OTA_NOTE_INST_ID 0x01 +#define OTA_SCALE_INST_ID 0x02 +#define OTA_STYLE_INST_ID 0x03 +#define OTA_TEMPO_INST_ID 0x04 +#define OTA_VOLUME_INST_ID 0x05 + +/* note durations */ +#define OTA_NORMAL_DURATION 0x00 +#define OTA_DOTTED_NOTE 0x01 +#define OTA_DOUBLE_DOTTED_NOTE 0x02 +#define OTA_TRIPLET_NOTE 0x03 + +/* loop count value for infinite loop */ +#define OTA_INFINITE_LOOP 0x0f + +/* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */ +#define DEFAULT_TICK_CONV 30476 + +/* default channel and program for OTA playback */ +#define OTA_CHANNEL 0 +#define OTA_PROGRAM 80 +#define OTA_VEL_MUL 4 +#define OTA_VEL_OFS 67 +#define OTA_VEL_DEFAULT 95 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +/* local prototypes */ +static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData); +static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue); +static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc); +static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc); + + +/*---------------------------------------------------------------------------- + * + * EAS_OTA_Parser + * + * This structure contains the functional interface for the OTA parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_OTA_Parser = +{ + OTA_CheckFileType, + OTA_Prepare, + OTA_Time, + OTA_Event, + OTA_State, + OTA_Close, + OTA_Reset, + OTA_Pause, + OTA_Resume, + NULL, + OTA_SetData, + OTA_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * + * bpmTable + * + * BPM conversion table. Converts bpm values to 256ths of a millisecond for a 32nd note + *---------------------------------------------------------------------------- +*/ +static const EAS_U32 bpmTable[32] = +{ + 76800, 68571, 61935, 54857, + 48000, 42667, 38400, 34286, + 30476, 27429, 24000, 21333, + 19200, 17143, 15360, 13714, + 12000, 10667, 9600, 8533, + 7680, 6737, 6000, 5408, + 4800, 4267, 3840, 3398, + 3024, 2685, 2400, 2133 +}; + +/*---------------------------------------------------------------------------- + * OTA_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + EAS_INT cmdLen; + EAS_INT state; + EAS_U8 temp; + + /* read the first byte, should be command length */ + *ppHandle = NULL; + if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS) + return result; + + /* read all the commands */ + cmdLen = temp; + state = 0; + while (cmdLen--) + { + + /* read the command, upper 7 bits */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS) + return result; + temp = temp >> 1; + + if (state == 0) + { + if (temp != OTA_RINGTONE) + break; + state++; + } + else + { + + if (temp == OTA_SOUND) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_OTA_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_OTA_DATA)); + if (!pData) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Malloc failed in OTA_Prepare\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pData, 0, sizeof(S_OTA_DATA)); + + /* return a pointer to the instance data */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_OPEN; + *ppHandle = pData; + break; + } + + if (temp != OTA_UNICODE) + break; + } + } + + /* not recognized */ + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + /* check for valid state */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + pData->state = EAS_STATE_ERROR; + if ((result = OTA_ParseHeader(pEASData, pData)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + EAS_U32 duration; + EAS_U8 temp; + + pData = (S_OTA_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + /* set program to square lead */ + if (parserMode != eParserModeMetaData) + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, OTA_PROGRAM); + + /* set channel volume to max */ + if (parserMode != eParserModeMetaData) + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += (EAS_I32) pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* if not in a pattern, read the pattern header */ + while (pData->current.patternLen == 0) + { + + /* check for loop - don't do infinite loops when locating */ + if (pData->loopCount && ((parserMode == eParserModePlay) || (pData->loopCount != OTA_INFINITE_LOOP))) + { + /* if not infinite loop, decrement loop count */ + if (pData->loopCount != OTA_INFINITE_LOOP) + pData->loopCount--; + + /* back to start of pattern*/ + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* if no previous position to restore, continue forward */ + else if (pData->restore.fileOffset < 0) + { + + /* check for end of song */ + if (pData->numPatterns == 0) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* read the next pattern header */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + if (temp != OTA_PATTERN_HEADER_ID) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA pattern header\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* get the pattern ID */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->currentPattern)) != EAS_SUCCESS) + return result; + + /* get the loop count */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->loopCount)) != EAS_SUCCESS) + return result; + + /* get the pattern length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->current.patternLen)) != EAS_SUCCESS) + return result; + + /* if pattern definition, save the current position */ + if (pData->current.patternLen) + { + if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* if pattern length is zero, repeat a previous pattern */ + else + { + /* make sure it's a valid pattern */ + if (pData->patterns[pData->currentPattern].fileOffset < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA pattern error, invalid pattern specified\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* save current position and data */ + if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS) + return result; + + /* seek to the pattern in the file */ + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) + return result; + } + + /* decrement pattern count */ + pData->numPatterns--; + } + + /* restore previous position */ + else + { + if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS) + return result; + } + } + + /* get the next event */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + + switch (temp) + { + case OTA_NOTE_INST_ID: + /* fetch note value */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->note)) != EAS_SUCCESS) + return result; + + /* fetch note duration */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + duration = pData->tick * (0x20 >> temp); + + /* fetch note duration modifier */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS) + return result; + switch (temp) + { + case OTA_NORMAL_DURATION: + break; + + case OTA_DOTTED_NOTE: + duration += duration >> 1; + break; + + case OTA_DOUBLE_DOTTED_NOTE: + duration += (duration >> 1) + (duration >> 2); + break; + + case OTA_TRIPLET_NOTE: + duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note duration ignored\n"); */ } + break; + } + + /* check for note */ + if (pData->note) + { + + /* determine note length based on style */ + switch (pData->style) + { + case 0: + pData->restTicks = duration >> 4; + break; + case 1: + pData->restTicks = 0; + break; + case 2: + pData->restTicks = duration >> 1; + break; + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note style ignored\n"); */ } + } + + /* add octave */ + pData->note += pData->octave; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, pData->velocity); + pData->time += (EAS_I32) duration - (EAS_I32) pData->restTicks; + } + + /* this is a rest */ + else + pData->time += (EAS_I32) duration; + break; + + case OTA_SCALE_INST_ID: + /* fetch octave */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS) + return result; + pData->octave = (EAS_U8) (temp * 12 + 59); + break; + + case OTA_STYLE_INST_ID: + /* fetch note style */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->style)) != EAS_SUCCESS) + return result; + break; + + case OTA_TEMPO_INST_ID: + /* fetch tempo */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 5, &temp)) != EAS_SUCCESS) + return result; + pData->tick = bpmTable[temp]; + break; + + case OTA_VOLUME_INST_ID: + /* fetch volume */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &temp)) != EAS_SUCCESS) + return result; + pData->velocity = temp ? (EAS_U8) (temp * OTA_VEL_MUL + OTA_VEL_OFS) : 0; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected instruction ID in OTA stream\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* decrement pattern length */ + pData->current.patternLen--; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_OTA_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_OTA_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_STOPPED; + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + pData = (S_OTA_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA* pData; + EAS_RESULT result; + + pData = (S_OTA_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = OTA_ParseHeader (pEASData, pData)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA *pData; + + /* can't pause a stopped stream */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_OTA_DATA *pData; + + /* can't resume a stopped stream */ + pData = (S_OTA_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA *) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) common decoder interface - pEASData not used */ +static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_OTA_DATA *pData; + + pData = (S_OTA_DATA*) pInstData; + switch (param) + { + /* return file type as OTA */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_OTA; + break; + +#if 0 + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = OTA_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData) +{ + EAS_RESULT result; + EAS_INT i; + EAS_INT state; + EAS_U8 temp; + EAS_U8 titleLen; + + /* initialize some data */ + pData->flags = 0; + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->patterns[0].fileOffset = pData->patterns[1].fileOffset = + pData->patterns[2].fileOffset = pData->patterns[3].fileOffset = -1; + pData->current.bitCount = 0; + pData->current.patternLen = 0; + pData->loopCount = 0; + pData->restore.fileOffset = -1; + pData->note = 0; + pData->restTicks = 0; + pData->velocity = OTA_VEL_DEFAULT; + pData->style = 0; + pData->octave = 59; + + /* seek to start of data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + + /* read the first byte, should be command length */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + + /* read all the commands */ + i = temp; + state = 0; + while (i--) + { + + /* fetch command, always starts on byte boundary */ + pData->current.bitCount = 0; + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 7, &temp)) != EAS_SUCCESS) + return result; + + if (state == 0) + { + if (temp != OTA_RINGTONE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Ring Tone Programming type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + state++; + } + else + { + + if (temp == OTA_SOUND) + break; + + if (temp == OTA_UNICODE) + pData->flags |= OTA_FLAGS_UNICODE; + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Sound or Unicode type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + } + } + + /* get song type */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) + return result; + + /* check for basic song type */ + if (temp == OTA_BASIC_SONG_TYPE) + { + /* fetch title length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &titleLen)) != EAS_SUCCESS) + return result; + + /* if unicode, double the length */ + if (pData->flags & OTA_FLAGS_UNICODE) + titleLen = (EAS_U8) (titleLen << 1); + + /* zero the metadata buffer */ + if (pData->metadata.buffer) + EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize); + + /* read the song title */ + for (i = 0; i < titleLen; i++) + { + /* fetch character */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &temp)) != EAS_SUCCESS) + return result; + + /* check for metadata callback */ + if (pData->metadata.callback) + { + if (i < (pData->metadata.bufferSize - 1)) + pData->metadata.buffer[i] = (char) temp; + } + } + + /* if host has registered callback, call it now */ + if (pData->metadata.callback) + (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData); + } + + /* must be temporary song */ + else if (temp != OTA_TEMPORARY_SONG_TYPE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA basic or temporary song type\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* get the song length */ + if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->numPatterns)) != EAS_SUCCESS) + return result; + + /* sanity check */ + if (pData->numPatterns == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA number of patterns is zero\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* at start of first pattern */ + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_FetchBitField() + *---------------------------------------------------------------------------- + * Purpose: + * Fetch a specified number of bits from the input stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue) +{ + EAS_RESULT result; + EAS_I32 bitsLeft; + EAS_U8 value; + + value = 0; + + /* do we have enough bits? */ + bitsLeft = pData->current.bitCount - numBits; + + /* not enough bits, assemble them from 2 characters */ + if (bitsLeft < 0) + { + /* grab the remaining bits from the previous byte */ + if (pData->current.bitCount) + /*lint -e{504,734} this is a legitimate shift operation */ + value = pData->current.dataByte << -bitsLeft; + + /* read the next byte */ + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->current.dataByte)) != EAS_SUCCESS) + return result; + bitsLeft += 8; + } + + /* more bits than needed? */ + if (bitsLeft > 0) + { + value |= pData->current.dataByte >> bitsLeft; + pData->current.bitCount = (EAS_U8) bitsLeft; + pData->current.dataByte = pData->current.dataByte & (0xff >> (8 - bitsLeft)); + } + + /* exactly the right number of bits */ + else + { + value |= pData->current.dataByte; + pData->current.bitCount = 0; + } + + *pValue = value; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * OTA_SavePosition() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc) +{ + EAS_HWMemCpy(pLoc, &pData->current, sizeof(S_OTA_LOC)); + return EAS_HWFilePos(hwInstData, pData->fileHandle, &pLoc->fileOffset); +} + +/*---------------------------------------------------------------------------- + * OTA_RestorePosition() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc) +{ + EAS_HWMemCpy(&pData->current, pLoc, sizeof(S_OTA_LOC)); + pData->restore.fileOffset = -1; + return EAS_HWFileSeek(hwInstData, pData->fileHandle, pLoc->fileOffset); +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_otadata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_otadata.c new file mode 100755 index 0000000..7463a0c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_otadata.c @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_otadata..c + * + * Contents and purpose: + * OTA Stream Parser data module for static memory model + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_otadata.h" + +/*---------------------------------------------------------------------------- + * + * eas_OTAData + * + * Static memory allocation for OTA parser + *---------------------------------------------------------------------------- +*/ +S_OTA_DATA eas_OTAData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_otadata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_otadata.h new file mode 100755 index 0000000..c06e3d3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_otadata.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_otadata.h + * + * Contents and purpose: + * OTA File Parser + * + * This file contains data declarations for the OTA parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_OTADATA_H +#define EAS_OTADATA_H + +#include "eas_data.h" + +/* definition for state flags */ +#define OTA_FLAGS_UNICODE 0x01 /* unicode text */ + +/*---------------------------------------------------------------------------- + * + * S_OTA_DATA + * + * This structure contains the state data for the OTA parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_I32 fileOffset; /* offset to location in file */ + EAS_U8 patternLen; /* length of current pattern */ + EAS_U8 dataByte; /* previous char from file */ + EAS_U8 bitCount; /* bit count in char */ +} S_OTA_LOC; + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* synth handle */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_U32 tick; /* length of 32nd note in 256th of a msec */ + EAS_U32 restTicks; /* ticks to rest after current note */ + S_OTA_LOC patterns[4]; /* pattern locations */ + S_OTA_LOC current; /* current location */ + S_OTA_LOC restore; /* previous location */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_U8 flags; /* bit flags */ + EAS_U8 numPatterns; /* number of patterns left in song */ + EAS_U8 currentPattern; /* current pattern for loop */ + EAS_U8 note; /* MIDI note number */ + EAS_U8 octave; /* octave modifier */ + EAS_U8 style; /* from STYLE */ + EAS_U8 velocity; /* current volume */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 loopCount; /* loop count for pattern */ +} S_OTA_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pan.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pan.c new file mode 100755 index 0000000..92ce1a3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pan.c @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pan.c + * + * Contents and purpose: + * Calculates left and right gain multipliers based on a pan value from -63 to +63 + * + * NOTES: + * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine + * whether the parser works for those particular file formats. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_pan.h" +#include "eas_math.h" + +/*---------------------------------------------------------------------------- + * EAS_CalcPanControl() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the left and right gain values corresponding to the given pan value. + * + * This routine uses sin/cos approximations for an equal power curve: + * + * sin(x) = (2-4*c)*x^2 + c + x + * cos(x) = (2-4*c)*x^2 + c - x + * + * where c = 1/sqrt(2) + * using the a0 + x*(a1 + x*a2) approach + * + * Inputs: + * pan - pan value (-63 to + 63) + * + * Outputs: + * pGainLeft linear gain multiplier for left channel (15-bit fraction) + * pGainRight linear gain multiplier for left channel (15-bit fraction) + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight) +{ + EAS_LONG temp; + EAS_INT netAngle; + + /* impose hard limit */ + if (pan < -63) + netAngle = -63; + else if (pan > 63) + netAngle = 63; + else + netAngle = pan; + + /*lint -e{701} */ + netAngle = netAngle << 8; + + /* calculate sin */ + temp = (int)(EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle)); + temp = (int)(COEFF_PAN_G0 + FMUL_15x15(temp, netAngle)); + + if (temp > SYNTH_FULL_SCALE_EG1_GAIN) + temp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (temp < 0) + temp = 0; + + *pGainRight = (EAS_I16) temp; + + /* calculate cos */ + temp = (int)(-EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle)); + temp = (int)(COEFF_PAN_G0 + FMUL_15x15(temp, netAngle)); + if (temp > SYNTH_FULL_SCALE_EG1_GAIN) + temp = SYNTH_FULL_SCALE_EG1_GAIN; + else if (temp < 0) + temp = 0; + + *pGainLeft = (EAS_I16) temp; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pan.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pan.h new file mode 100755 index 0000000..aa16dcd --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pan.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pan.h + * + * Contents and purpose: + * Calculates left and right gain multipliers based on a pan value from -63 to +63 + * + * NOTES: + * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine + * whether the parser works for those particular file formats. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_PAN_H +#define EAS_PAN_H + +#include "eas_types.h" + +/*---------------------------------------------------------------------------- + * EAS_CalcPanControl() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the left and right gain values corresponding to the given pan value. + * + * This routine uses sin/cos approximations for an equal power curve: + * + * sin(x) = (2-4*c)*x^2 + c + x + * cos(x) = (2-4*c)*x^2 + c - x + * + * where c = 1/sqrt(2) + * using the a0 + x*(a1 + x*a2) approach + * + * Inputs: + * pan - pan value (-63 to + 63) + * + * Outputs: + * pGainLeft linear gain multiplier for left channel (15-bit fraction) + * pGainRight linear gain multiplier for left channel (15-bit fraction) + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight); + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_parser.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_parser.h new file mode 100755 index 0000000..96ec35b --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_parser.h @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_parser.h + * + * Contents and purpose: + * Interface declarations for the generic parser interface + * + * This header only contains declarations that are specific + * to this implementation. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 767 $ + * $Date: 2007-07-19 13:47:31 -0700 (Thu, 19 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PARSER_H +#define _EAS_PARSER_H + +#include "eas_types.h" + + +/* metadata callback */ +typedef struct s_metadata_cb_tag +{ + EAS_METADATA_CBFUNC callback; + char *buffer; + EAS_VOID_PTR pUserData; + EAS_I32 bufferSize; +} S_METADATA_CB; + +/* generic parser interface */ +typedef struct +{ + EAS_RESULT (* EAS_CONST pfCheckFileType)(struct s_eas_data_tag *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); + EAS_RESULT (* EAS_CONST pfPrepare)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfTime)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); + EAS_RESULT (* EAS_CONST pfEvent)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_INT parseMode); + EAS_RESULT (* EAS_CONST pfState)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); + EAS_RESULT (* EAS_CONST pfClose)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfReset)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfPause)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfResume)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); + EAS_RESULT (* EAS_CONST pfLocate)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate); + EAS_RESULT (* EAS_CONST pfSetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + EAS_RESULT (* EAS_CONST pfGetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); + EAS_RESULT (* EAS_CONST pfGetMetaData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength); +} S_FILE_PARSER_INTERFACE; + +typedef enum +{ + eParserModePlay, + eParserModeLocate, + eParserModeMute, + eParserModeMetaData +} E_PARSE_MODE; + +typedef enum +{ + PARSER_DATA_FILE_TYPE, + PARSER_DATA_PLAYBACK_RATE, + PARSER_DATA_TRANSPOSITION, + PARSER_DATA_VOLUME, + PARSER_DATA_SYNTH_HANDLE, + PARSER_DATA_METADATA_CB, + PARSER_DATA_DLS_COLLECTION, + PARSER_DATA_EAS_LIBRARY, + PARSER_DATA_POLYPHONY, + PARSER_DATA_PRIORITY, + PARSER_DATA_FORMAT, + PARSER_DATA_MEDIA_LENGTH, + PARSER_DATA_JET_CB, + PARSER_DATA_MUTE_FLAGS, + PARSER_DATA_SET_MUTE, + PARSER_DATA_CLEAR_MUTE, + PARSER_DATA_NOTE_COUNT, + PARSER_DATA_MAX_PCM_STREAMS, + PARSER_DATA_GAIN_OFFSET, + PARSER_DATA_PLAY_MODE +} E_PARSER_DATA; + +#endif /* #ifndef _EAS_PARSER_H */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcm.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcm.c new file mode 100755 index 0000000..ff3f6f9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcm.c @@ -0,0 +1,1482 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcm.c + * + * Contents and purpose: + * Implements the PCM engine including ADPCM decode for SMAF and CMX audio playback. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 849 $ + * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_config.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_math.h" +#include "eas_mixer.h" + +#define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1) + +/*---------------------------------------------------------------------------- + * Decoder interfaces + *---------------------------------------------------------------------------- +*/ + +static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); +static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); + +static const S_DECODER_INTERFACE PCMDecoder = +{ + NULL, + LinearPCMDecode, + LinearPCMLocate, +}; + +/* SMAF ADPCM decoder */ +#ifdef _SMAF_PARSER +extern S_DECODER_INTERFACE SmafDecoder; +#define SMAF_DECODER &SmafDecoder +extern S_DECODER_INTERFACE Smaf7BitDecoder; +#define SMAF_7BIT_DECODER &Smaf7BitDecoder +#else +#define SMAF_DECODER NULL +#define SMAF_7BIT_DECODER NULL +#endif + +/* IMA ADPCM decoder */ +#ifdef _IMA_DECODER +extern S_DECODER_INTERFACE IMADecoder; +#define IMA_DECODER &IMADecoder +#else +#define IMA_DECODER NULL +#endif + +static const S_DECODER_INTERFACE * const decoders[] = +{ + &PCMDecoder, + SMAF_DECODER, + IMA_DECODER, + SMAF_7BIT_DECODER +}; + +/*---------------------------------------------------------------------------- + * Sample rate conversion + *---------------------------------------------------------------------------- +*/ + +#define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE) + +#ifdef _LOOKUP_SAMPLE_RATE +static const EAS_U32 srcConvRate[][2] = +{ + 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE, + 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE, + 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE, + 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE, + 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE, + 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE, + 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE, + 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE +}; +static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate); +#define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2) +#endif + + +/* interface prototypes */ +static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples); + + +/* local prototypes */ +static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData); +static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_PEInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData) +{ + S_PCM_STATE *pState; + EAS_INT i; + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA); + /* allocate dynamic memory */ + else + pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); + + if (!pEASData->pPCMStreams) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + //zero the memory to insure complete initialization + EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); + + /* initialize the state data */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + pState->fileHandle = NULL; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData) +{ + + /* free any dynamic memory */ + if (!pEASData->staticMemoryModel) + { + if (pEASData->pPCMStreams) + { + EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams); + pEASData->pPCMStreams = NULL; + } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PERender() + *---------------------------------------------------------------------------- + * Purpose: + * Render a buffer of PCM audio + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples) +{ + S_PCM_STATE *pState; + EAS_RESULT result; + EAS_INT i; + + /* render all the active streams */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + { + if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED)) + if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS) + return result; + } + return EAS_SUCCESS; +} + + +/*---------------------------------------------------------------------------- + * EAS_PEState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState) +{ + /* return current state */ + *pState = pInstData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_RESULT result; + + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS) + return result; + + pState->fileHandle = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * PCM_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_RESULT result; + + /* reset file position to first byte of data in the stream */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ } + return result; + } + + /* re-initialize stream */ + return InitPCMStream(pEASData, pState); +} + +/*---------------------------------------------------------------------------- + * EAS_PEOpenStream() + *---------------------------------------------------------------------------- + * Purpose: + * Starts up a PCM playback + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle) +{ + EAS_RESULT result; + S_PCM_STATE *pState; + EAS_I32 filePos; + + /* make sure we support this decoder */ + if (pParams->decoder >= NUM_DECODER_MODULES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ } + return EAS_ERROR_PARAMETER_RANGE; + } + if (decoders[pParams->decoder] == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ } + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + } + + /* find a slot for the new stream */ + if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ } + return EAS_ERROR_MAX_PCM_STREAMS; + } + + /* get the current file position */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ } + pState->fileHandle = NULL; + return result; + } + + pState->pDecoder = decoders[pParams->decoder]; + pState->startPos = filePos; + pState->bytesLeftLoop = pState->byteCount = pParams->size; + pState->loopStart = pParams->loopStart; + pState->samplesTilLoop = (EAS_I32) pState->loopStart; + pState->loopSamples = pParams->loopSamples; + pState->samplesInLoop = 0; + pState->blockSize = (EAS_U16) pParams->blockSize; + pState->flags = pParams->flags; + pState->envData = pParams->envData; + pState->volume = pParams->volume; + pState->sampleRate = (EAS_U16) pParams->sampleRate; + + /* set the base frequency */ + pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15; + + /* calculate shift for frequencies > 1.0 */ + pState->rateShift = 0; + while (pState->basefreq > 32767) + { + pState->basefreq = pState->basefreq >> 1; + pState->rateShift++; + } + + /* initialize */ + if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS) + return result; + + *pHandle = pState; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n", + pState->startPos, pState->byteCount, pState->loopSamples); */ } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEContinueStream() + *---------------------------------------------------------------------------- + * Purpose: + * Continues a PCM stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{715} reserved for future use */ +EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size) +{ + + /* add new samples to count */ + pState->bytesLeft += size; + if (pState->bytesLeft > 0) + pState->flags &= ~PCM_FLAGS_EMPTY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEGetFileHandle() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the file handle of a stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle) +{ + *pFileHandle = pState->fileHandle; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateParams() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch and volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * pitch - pitch shift in cents + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +/*lint -esym(715, gainRight) used only in 2-channel version */ +EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight) +{ + + pState->gainLeft = gainLeft; + +#if (NUM_OUTPUT_CHANNELS == 2) + pState->gainRight = gainRight; +#endif + + pState->pitch = pitch; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PELocate() + *---------------------------------------------------------------------------- + * Purpose: + * This function seeks to the requested place in the file. Accuracy + * is dependent on the sample rate and block size. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pState - stream handle + * time - media time in milliseconds + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time) +{ + if (pState->pDecoder->pfLocate == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + return pState->pDecoder->pfLocate(pEASData, pState, time); +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Update the volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume) +{ + pState->volume = volume; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEUpdatePitch() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch parameter for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * pState - pointer to S_PCM_STATE for this stream + * pitch - new pitch value in pitch cents + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch) +{ + pState->pitch = pitch; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEPause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + /* set state to stopping */ + pState->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PEResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + /* set state to stopping */ + pState->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +EAS_U32 getDecayScale(EAS_U32 index) +{ + EAS_U32 utemp; + + //envelope decay segment + switch (index) + { + case 0: //no decay + utemp = 512;//32768; + break; + case 1: //.0156 dB per update + utemp = 511;//32709; + break; + case 2: //.03125 + utemp = 510;//32649; + break; + case 3: //.0625 + utemp = 508;//32532; + break; + case 4: //.125 + utemp = 505;//32298; + break; + case 5: //.25 + utemp = 497;//31835; + break; + case 6: //.5 + utemp = 483;//30929; + break; + case 7: //1.0 + utemp = 456;//29193; + break; + case 8: //2.0 + utemp = 406;//26008; + break; + case 9: //4.0 + utemp = 323;//20642; + break; + case 10: //8.0 + utemp = 203;//13004; + break; + case 11: //16.0 + utemp = 81;//5160; + break; + case 12: //32.0 + utemp = 13;//813; + break; + case 13: //64.0 + utemp = 0;//20; + break; + case 14: //128.0 + utemp = 0; + break; + case 15: //256.0 + default: + utemp = 0; + break; + } + //printf("getdecayscale returned %d\n",utemp); + return utemp; +} + +EAS_U32 getAttackIncrement(EAS_U32 index) +{ + EAS_U32 utemp; + + //envelope decay segment + switch (index) + { + case 0: + utemp = 32; + break; + case 1: + utemp = 64; + break; + case 2: + utemp = 128; + break; + case 3: + utemp = 256; + break; + case 4: + utemp = 512; + break; + case 5: + utemp = 1024; + break; + case 6: + utemp = 2048; + break; + case 7: + utemp = 4096; + break; + case 8: + utemp = 8192; + break; + case 9: + utemp = 16384; + break; + case 10: + utemp = 32768; + break; + case 11: + utemp = 65536; + break; + case 12: + utemp = 65536; + break; + case 13: + utemp = 65536; + break; + case 14: + utemp = 65535; + break; + case 15: + default: + utemp = 0; + break; + } + //printf("getattackincrement returned %d\n",utemp); + return utemp; +} + +/*---------------------------------------------------------------------------- + * EAS_PERelease() + *---------------------------------------------------------------------------- + * Purpose: + * Put the PCM stream envelope into release. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) +{ + EAS_U32 utemp; + + //printf("handling note-off part of envelope\n"); + /*if the note is not ignore release or sustained*/ + if (((pState->envData >> 24) & 0x0F)==0) + { + /* set envelope state to release */ + pState->envState = PCM_ENV_RELEASE; + utemp = ((pState->envData >> 20) & 0x0F); + pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp); + } + else + { + /*else change envelope state to sustain */ + pState->envState = PCM_ENV_SUSTAIN; + utemp = ((pState->envData >> 28) & 0x0F); + pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); + } + //since we are in release, don't let anything hang around too long + //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale); + if (pState->envScale > 505) + pState->envScale = 505; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * FindSlot() + *---------------------------------------------------------------------------- + * Purpose: + * Locates an empty stream slot and assigns the file handle + * + * Inputs: + * pEASData - pointer to EAS library instance data + * fileHandle - file handle + * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED + * + * Outputs: + * returns handle to slot or NULL if all slots are used + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData) +{ + EAS_INT i; + S_PCM_STATE *pState; + +#ifndef NO_PCM_STEAL + S_PCM_STATE *foundState = NULL; + EAS_INT count = 0; + EAS_U32 startOrder = 0xFFFFFFFF; + S_PCM_STATE *stealState = NULL; + EAS_U32 youngest = 0; + + /* find an empty slot, count total in use, and find oldest in use (lowest start order) */ + for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) + { + /* if this one is available */ + if (pState->fileHandle == NULL) + { + foundState = pState; + } + /* else this one is in use, so see if it is the oldest, and count total in use */ + /* also find youngest */ + else + { + /*one more voice in use*/ + count++; + /* is this the oldest? (lowest start order) */ + if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder)) + { + /* remember this one */ + stealState = pState; + /* remember the oldest so far */ + startOrder = pState->startOrder; + } + /* is this the youngest? (highest start order) */ + if (pState->startOrder >= youngest) + { + youngest = pState->startOrder; + } + } + } + + /* if there are too many voices active, stop the oldest one */ + if (count > PCM_STREAM_THRESHOLD) + { + //printf("stealing!!!\n"); + /* make sure we got one, although we should always have one at this point */ + if (stealState != NULL) + { + //flag this as stopping, so it will get shut off + stealState->state = EAS_STATE_STOPPING; + } + } + + /* if there are no available open streams (we won't likely see this, due to stealing) */ + if (foundState == NULL) + return NULL; + + /* save info */ + foundState->startOrder = youngest + 1; + foundState->fileHandle = fileHandle; + foundState->pCallback = pCallbackFunc; + foundState->cbInstData = cbInstData; + return foundState; +#else + /* find an empty slot*/ + for (i = 0; i < MAX_PCM_STREAMS; i++) + { + pState = &pEASData->pPCMStreams[i]; + if (pState->fileHandle != NULL) + continue; + + pState->fileHandle = fileHandle; + pState->pCallback = pCallbackFunc; + pState->cbInstData = cbInstData; + return pState; + } + return NULL; +#endif +} + +#ifdef _LOOKUP_SAMPLE_RATE +/*---------------------------------------------------------------------------- + * CalcBaseFreq() + *---------------------------------------------------------------------------- + * Purpose: + * Calculates the fractional phase increment for the sample rate converter + * + * Inputs: + * sampleRate - sample rate in samples/sec + * + * Outputs: + * Returns fractional sample rate with a 15-bit fraction + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate) +{ + EAS_INT i; + + /* look up the conversion rate */ + for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++) + { + if (srcConvRate[i][0] == sampleRate) + return srcConvRate[i][1]; + } + + /* if not found in table, do it the long way */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ } + + return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15; +} +#endif + +/*---------------------------------------------------------------------------- + * InitPCMStream() + *---------------------------------------------------------------------------- + * Purpose: + * Start an ADPCM stream playback. Decodes the header, preps the engine. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState) +{ + + /* initialize the data structure */ + pState->bytesLeft = pState->byteCount; + pState->phase = 0; + pState->srcByte = 0; + pState->decoderL.acc = 0; + pState->decoderL.output = 0; + pState->decoderL.x0 = pState->decoderL.x1 = 0; + pState->decoderL.step = 0; + pState->decoderR.acc = 0; + pState->decoderR.output = 0; + pState->decoderR.x0 = pState->decoderR.x1 = 0; + pState->decoderR.step = 0; + pState->hiNibble = EAS_FALSE; + pState->pitch = 0; + pState->blockCount = 0; + pState->gainLeft = PCM_DEFAULT_GAIN_SETTING; +// pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING; + pState->envValue = 0; + pState->envState = PCM_ENV_START; + +#if (NUM_OUTPUT_CHANNELS == 2) + pState->gainRight = PCM_DEFAULT_GAIN_SETTING; +// pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING; +#endif + pState->state = EAS_STATE_READY; + + /* initialize the decoder */ + if (pState->pDecoder->pfInit) + return (*pState->pDecoder->pfInit)(pEASData, pState); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RenderPCMStream() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes a buffer of ADPCM data. + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples) +{ + EAS_RESULT result; + EAS_U32 phaseInc; + EAS_I32 gainLeft, gainIncLeft; + EAS_I32 *pOut; + EAS_I32 temp; + EAS_U32 utemp; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I32 gainRight, gainIncRight; +#endif + +#if 0 + printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n", + ((pState->envData >> 12) & 0x0F), + ((pState->envData >> 16) & 0x0F), + ((pState->envData >> 8) & 0x0F), + ((pState->envData >> 28) & 0x0F), + ((pState->envData >> 20) & 0x0F)); +#endif + + if (pState->envState == PCM_ENV_START) + { + //printf("env start\n"); + utemp = ((pState->envData >> 12) & 0x0F); + //if fastest rate, attack is already completed + //do the same for slowest rate, since that allows zero to be passed for default envelope + if (utemp == 0x0F || utemp == 0x00) + { + //start envelope at full + pState->envValue = (32768<<7); + //jump right into decay + utemp = ((pState->envData >> 16) & 0x0F); + pState->envScale = getDecayScale(utemp); + pState->envState = PCM_ENV_DECAY; + pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume); + pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume); + } + //else attack has a ramp + else + { + //start the envelope very low + pState->envValue = (2<<7); + pState->currentGainLeft = 0; + pState->currentGainRight = 0; + //get envelope attack scaling value + pState->envScale = getAttackIncrement(utemp); + //go to attack state + pState->envState = PCM_ENV_ATTACK; + } + } + if (pState->envState == PCM_ENV_ATTACK) + { + //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = pState->envValue + (pState->envScale << 7); + //check envelope level and update state if needed + if (pState->envValue >= (32768<<7)) + { + pState->envValue = (32768<<7); + utemp = ((pState->envData >> 16) & 0x0F); + pState->envScale = getDecayScale(utemp); + pState->envState = PCM_ENV_DECAY; + } + } + else if (pState->envState == PCM_ENV_DECAY) + { + //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against sustain level and update state if needed + utemp = ((pState->envData >> 8) & 0x0F); + if (utemp == (EAS_U32)0x0F) + utemp = (2<<7); + else + { + utemp = ((32769<<7) >> (utemp>>1)); + } + if (pState->envValue <= utemp) + { + utemp = ((pState->envData >> 28) & 0x0F); + pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); + pState->envState = PCM_ENV_SUSTAIN; + } + } + else if (pState->envState == PCM_ENV_SUSTAIN) + { + //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against bottom level and update state if needed + if (pState->envValue <= (2<<7)) + { + //no more decay + pState->envScale = 512; + pState->envState = PCM_ENV_END; + } + } + else if (pState->envState == PCM_ENV_RELEASE) + { + //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); + //update envelope value + pState->envValue = (pState->envValue * pState->envScale)>>9; + //check envelope level against bottom level and update state if needed + if (pState->envValue <= (2<<7)) + { + //no more decay + pState->envScale = 512; + pState->envState = PCM_ENV_END; + } + } + else if (pState->envState == PCM_ENV_END) + { + //printf("env end\n"); + /* set state to stopping, already ramped down */ + pState->state = EAS_STATE_STOPPING; + } + + //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15); + //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15); + + /* gain to 32-bits to increase resolution on anti-zipper filter */ + /*lint -e{703} use shift for performance */ + gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS; +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{703} use shift for performance */ + gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS; +#endif + + /* calculate a new gain increment, gain target is zero if pausing */ + if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED)) + { + gainIncLeft = -pState->currentGainLeft; +#if (NUM_OUTPUT_CHANNELS == 2) + gainIncRight= -pState->currentGainRight; +#endif + } + else + { + EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume); + gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft; +#if (NUM_OUTPUT_CHANNELS == 2) + gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight; +#endif + } + + /* calculate phase increment */ + phaseInc = pState->basefreq; + + /* convert pitch cents to linear multiplier */ + if (pState->pitch) + { + temp = EAS_Calculate2toX(pState->pitch); + phaseInc = FMUL_15x15(phaseInc, temp); + } + phaseInc = phaseInc << pState->rateShift; + + /* pointer to mix buffer */ + pOut = pEASData->pMixBuffer; + + /* render a buffer of samples */ + while (numSamples--) + { + + /* interpolate an output sample */ + pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK); + + /* stereo output */ +#if (NUM_OUTPUT_CHANNELS == 2) + + /* stereo stream? */ + if (pState->flags & PCM_FLAGS_STEREO) + pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); + + /* gain scale and mix */ + /*lint -e{704} use shift instead of division */ + *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + gainLeft += gainIncLeft; + + /*lint -e{704} use shift instead of division */ + if (pState->flags & PCM_FLAGS_STEREO) + *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + else + *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + + gainRight += gainIncRight; + + /* mono output */ +#else + /* if stereo stream, decode right channel and mix to mono */ + if (pState->flags & PCM_FLAGS_STEREO) + { + pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); + + /* for mono, sum stereo ADPCM to mono */ + /*lint -e{704} use shift instead of division */ + *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + } + else + /*lint -e{704} use shift instead of division */ + *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; + + gainLeft += gainIncLeft; +#endif + + /* advance phase accumulator */ + pState->phase += phaseInc; + + /* if integer part of phase accumulator is non-zero, advance to next sample */ + while (pState->phase & ~PHASE_FRAC_MASK) + { + pState->decoderL.x0 = pState->decoderL.x1; + pState->decoderR.x0 = pState->decoderR.x1; + + /* give the source a chance to continue the stream */ + if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0)) + { + pState->flags |= PCM_FLAGS_EMPTY; + (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ } + } + + /* decode the next sample */ + if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS) + return result; + + /* adjust phase by one sample */ + pState->phase -= (1L << NUM_PHASE_FRAC_BITS); + } + + } + + /* save new gain */ + /*lint -e{704} use shift instead of division */ + pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS); + +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{704} use shift instead of division */ + pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS); +#endif + + /* if pausing, set new state and notify */ + if (pState->state == EAS_STATE_PAUSING) + { + pState->state = EAS_STATE_PAUSED; + if (pState->pCallback) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); + } + + /* if out of data, set stopped state and notify */ + if (pState->bytesLeft == 0 || pState->state == EAS_STATE_STOPPING) + { + pState->state = EAS_STATE_STOPPED; + + /* do callback unless the file has already been closed */ + if (pState->pCallback && pState->fileHandle) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); + } + + if (pState->state == EAS_STATE_READY) + pState->state = EAS_STATE_PLAY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * LinearPCMDecode() + *---------------------------------------------------------------------------- + * Purpose: + * Decodes a PCM sample + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) +{ + EAS_RESULT result; + EAS_HW_DATA_HANDLE hwInstData; + + hwInstData = ((S_EAS_DATA*) pEASData)->hwInstData; + + /* if out of data, check for loop */ + if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) + { + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) + return result; + pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; + pState->flags &= ~PCM_FLAGS_EMPTY; + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "LinearPCMDecode: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } + } + + if (pState->bytesLeft) + { + + /* check format byte for 8-bit samples */ + if (pState->flags & PCM_FLAGS_8_BIT) + { + /* fetch left or mono sample */ + if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* if unsigned */ + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ + pState->decoderL.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); + } + else + { + /*lint -e{734} converting signed 8-bit to signed 16-bit */ + pState->decoderL.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); + } + pState->bytesLeft--; + + /* fetch right sample */ + if(pState->flags & PCM_FLAGS_STEREO) + { + if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) + return result; + + /* if unsigned */ + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ + pState->decoderR.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); + } + else + { + /*lint -e{734} converting signed 8-bit to signed 16-bit */ + pState->decoderR.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); + } + pState->bytesLeft--; + } + } + + /* must be 16-bit samples */ + else + { + //unsigned 16 bit currently not supported + if (pState->flags & PCM_FLAGS_UNSIGNED) + { + return EAS_ERROR_INVALID_PCM_TYPE; + } + + /* fetch left or mono sample */ + if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderL.x1, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->bytesLeft -= 2; + + /* fetch right sample */ + if(pState->flags & PCM_FLAGS_STEREO) + { + if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderR.x1, EAS_FALSE)) != EAS_SUCCESS) + return result; + pState->bytesLeft -= 2; + } + } + } + + /* no more data, force zero samples */ + else + pState->decoderL.x1 = pState->decoderR.x1 = 0; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * LinearPCMLocate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate in a linear PCM stream + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_I32 secs, msecs; + EAS_INT shift; + + /* calculate size of sample frame */ + if (pState->flags & PCM_FLAGS_8_BIT) + shift = 0; + else + shift = 1; + if (pState->flags & PCM_FLAGS_STEREO) + shift++; + + /* break down into secs and msecs */ + secs = time / 1000; + msecs = time - (secs * 1000); + + /* calculate sample number fraction from msecs */ + temp = (msecs * pState->sampleRate); + temp = (temp >> 10) + ((temp * 49) >> 21); + + /* add integer sample count */ + temp += secs * pState->sampleRate; + + /* calculate the position based on sample frame size */ + /*lint -e{703} use shift for performance */ + temp <<= shift; + + /* past end of sample? */ + if (temp > (EAS_I32) pState->loopStart) + { + /* if not looped, flag error */ + if (pState->loopSamples == 0) + { + pState->bytesLeft = 0; + pState->flags |= PCM_FLAGS_EMPTY; + return EAS_ERROR_LOCATE_BEYOND_END; + } + + /* looped sample - calculate position in loop */ + while (temp > (EAS_I32) pState->loopStart) + temp -= (EAS_I32) pState->loopStart; + } + + /* seek to new position */ + if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) + return result; + + /* reset state */ + if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) + pState->state = EAS_STATE_READY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_PESeek + *---------------------------------------------------------------------------- + * Purpose: + * Locate to a particular byte in a PCM stream + *---------------------------------------------------------------------------- + * This bit is tricky because the chunks may not be contiguous, + * so we have to rely on the parser to position in the file. We + * do this by seeking to the end of each chunk and simulating an + * empty buffer condition until we get to where we want to go. + * + * A better solution would be a parser API for re-positioning, + * but there isn't time at the moment to re-factor all the + * parsers to support a new API. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PESeek (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation) +{ + EAS_RESULT result; + + /* seek to start of audio */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + pState->bytesLeft = pState->bytesLeftLoop; + + /* skip through chunks until we find the right chunk */ + while (*pLocation > (EAS_I32) pState->bytesLeft) + { + /* seek to end of audio chunk */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", pState->bytesLeft); */ } + if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, pState->bytesLeft)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + *pLocation -= pState->bytesLeft; + pState->bytesLeft = 0; + pState->flags |= PCM_FLAGS_EMPTY; + + /* retrieve more data */ + if (pState->pCallback) + (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: bytesLeft=%d, byte location = %d\n", pState->bytesLeft, *pLocation); */ } + + /* no more samples */ + if (pState->bytesLeft == 0) + return EAS_ERROR_LOCATE_BEYOND_END; + } + + /* seek to new offset in current chunk */ + if (*pLocation > 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", *pLocation); */ } + if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, *pLocation)) != EAS_SUCCESS) + { + pState->state = EAS_STATE_ERROR; + return result; + } + + /* if not streamed, calculate number of bytes left */ + if (pState->flags & PCM_FLAGS_STREAMING) + pState->bytesLeft = 0x7fffffff; + else + pState->bytesLeft -= *pLocation; + } + return EAS_SUCCESS; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcm.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcm.h new file mode 100755 index 0000000..4fc77e9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcm.h @@ -0,0 +1,359 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcm.h + * + * Contents and purpose: + * External function prototypes for eas_pcm.c module + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PCM_H +#define _EAS_PCM_H + +/* default gain setting - roughly unity gain */ +#define PCM_DEFAULT_GAIN_SETTING 0x6000 + +typedef struct s_pcm_state_tag *EAS_PCM_HANDLE; +typedef void (*EAS_PCM_CALLBACK) (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR cbInstData, EAS_PCM_HANDLE pcmHandle, EAS_STATE state); + +/* parameters for EAS_PEOpenStream */ +typedef struct s_pcm_open_params_tag +{ + EAS_FILE_HANDLE fileHandle; + EAS_I32 decoder; + EAS_U32 sampleRate; + EAS_I32 size; + EAS_U32 loopStart; + EAS_U32 loopSamples; + EAS_I32 blockSize; + EAS_U32 flags; + EAS_U32 envData; + EAS_I16 volume; + EAS_PCM_CALLBACK pCallbackFunc; + EAS_VOID_PTR cbInstData; + } S_PCM_OPEN_PARAMS; + +/*---------------------------------------------------------------------------- + * EAS_PEInit() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEInit (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_PEShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the PCM engine + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEShutdown (EAS_DATA_HANDLE pEASData); + +/*---------------------------------------------------------------------------- + * EAS_PEOpenStream() + *---------------------------------------------------------------------------- + * Purpose: + * Starts up a PCM playback + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEOpenStream (EAS_DATA_HANDLE pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle); + +/*---------------------------------------------------------------------------- + * EAS_PEContinueStream() + *---------------------------------------------------------------------------- + * Purpose: + * Continues a PCM stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEContinueStream (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_I32 size); + +/*---------------------------------------------------------------------------- + * EAS_PEGetFileHandle() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the file handle of a stream + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEGetFileHandle (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_FILE_HANDLE *pFileHandle); + +/*---------------------------------------------------------------------------- + * EAS_PERender() + *---------------------------------------------------------------------------- + * Purpose: + * Render a buffer of PCM audio + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERender (EAS_DATA_HANDLE pEASData, EAS_I32 numSamples); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateParams() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch and volume parameters using MIDI controls + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEUpdateParams (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight); + +/*---------------------------------------------------------------------------- + * EAS_PELocate() + *---------------------------------------------------------------------------- + * Purpose: + * This function seeks to the requested place in the file. Accuracy + * is dependent on the sample rate and block size. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pState - stream handle + * time - media time in milliseconds + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PELocate (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I32 time); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdateVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Update the volume parameters for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * gainLeft - linear gain multipler in 1.15 fraction format + * gainRight - linear gain multipler in 1.15 fraction format + * initial - initial settings, set current gain + * + * Outputs: + * + * + * Side Effects: + * + * Notes + * In mono mode, leftGain controls the output gain and rightGain is ignored + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdateVolume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume); + +/*---------------------------------------------------------------------------- + * EAS_PEUpdatePitch() + *---------------------------------------------------------------------------- + * Purpose: + * Update the pitch parameter for a PCM stream + * + * Inputs: + * pEASData - pointer to EAS library instance data + * pState - pointer to S_PCM_STATE for this stream + * pitch - new pitch value in pitch cents + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT EAS_PEUpdatePitch (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch); + +/*---------------------------------------------------------------------------- + * EAS_PEState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEState (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_STATE *pState); + +/*---------------------------------------------------------------------------- + * EAS_PEClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEClose (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEReset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEReset (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEPause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and pause rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEPause (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PEResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PEResume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +/*---------------------------------------------------------------------------- + * EAS_PERelease() + *---------------------------------------------------------------------------- + * Purpose: + * Put the PCM stream envelope into release. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_PCM_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PERelease (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); + +#endif /* end _EAS_PCM_H */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcmdata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcmdata.c new file mode 100755 index 0000000..2d85ac2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcmdata.c @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcmdata.c + * + * Contents and purpose: + * Contains the static data for the PCM engine. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" + +/* static data allocation */ +S_PCM_STATE eas_PCMData[MAX_PCM_STREAMS]; + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcmdata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcmdata.h new file mode 100755 index 0000000..ae18d6d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcmdata.h @@ -0,0 +1,157 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_pcmdata.h + * + * Contents and purpose: + * Data declarations for the PCM engine + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 847 $ + * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_PCMDATA_H +#define _EAS_PCMDATA_H + +/* sets the maximum number of simultaneous PCM streams */ +#ifndef MAX_PCM_STREAMS +#define MAX_PCM_STREAMS 16 +#define PCM_STREAM_THRESHOLD (MAX_PCM_STREAMS - 4) +#endif + +/* coefficents for high-pass filter in ADPCM */ +#define INTEGRATOR_COEFFICIENT 100 /* coefficient for leaky integrator */ + +/* additional flags in S_PCM_STATE.flags used internal to module */ +#define PCM_FLAGS_EMPTY 0x01000000 /* unsigned format */ + +/*---------------------------------------------------------------------------- + * S_PCM_STATE + * + * Retains state information for PCM streams. + *---------------------------------------------------------------------------- +*/ +typedef struct s_decoder_state_tag +{ + EAS_I32 output; /* last output for DC offset filter */ + EAS_I32 acc; /* accumulator for DC offset filter */ + EAS_I32 step; /* current ADPCM step size */ + EAS_PCM x1; /* current generated sample */ + EAS_PCM x0; /* previous generated sample */ +} S_DECODER_STATE; + +typedef enum +{ + PCM_ENV_START = 0, + PCM_ENV_ATTACK, + PCM_ENV_DECAY, + PCM_ENV_SUSTAIN, + PCM_ENV_RELEASE, + PCM_ENV_END +} E_PCM_ENV_STATE; + +typedef struct s_pcm_state_tag +{ +#ifdef _CHECKED_BUILD + EAS_U32 handleCheck; /* signature check for checked build */ +#endif + EAS_FILE_HANDLE fileHandle; /* pointer to input file */ + EAS_PCM_CALLBACK pCallback; /* pointer to callback function */ + EAS_VOID_PTR cbInstData; /* instance data for callback function */ + struct s_decoder_interface_tag EAS_CONST * pDecoder; /* pointer to decoder interface */ + EAS_STATE state; /* stream state */ + EAS_I32 time; /* media time */ + EAS_I32 startPos; /* start of PCM stream */ + EAS_I32 loopLocation; /* file location where loop starts */ + EAS_I32 byteCount; /* size of file */ + EAS_U32 loopStart; /* loop start, offset in samples from startPos */ + /* NOTE: For CMF, we use this to store total sample size */ + EAS_U32 loopSamples; /* total loop length, in samples, 0 means no loop */ + /* NOTE: For CMF, non-zero means looped */ + EAS_U32 samplesInLoop; /* samples left in the loop to play back */ + EAS_I32 samplesTilLoop; /* samples left to play until top of loop */ + EAS_I32 bytesLeft; /* count of bytes left in stream */ + EAS_I32 bytesLeftLoop; /* count of bytes left in stream, value at start of loop */ + EAS_U32 phase; /* current phase for interpolator */ + EAS_U32 basefreq; /* frequency multiplier */ + EAS_U32 flags; /* stream flags */ + EAS_U32 envData; /* envelope data (and LFO data) */ + EAS_U32 envValue; /* current envelope value */ + EAS_U32 envScale; /* current envelope scale */ + EAS_U32 startOrder; /* start order index, first is 0, next is 1, etc. */ + S_DECODER_STATE decoderL; /* left (mono) ADPCM state */ + S_DECODER_STATE decoderR; /* right ADPCM state */ + S_DECODER_STATE decoderLLoop; /* left (mono) ADPCM state, value at start of loop */ + S_DECODER_STATE decoderRLoop; /* right ADPCM state, value at start of loop */ + E_PCM_ENV_STATE envState; /* current envelope state */ + EAS_I16 volume; /* volume for stream */ + EAS_I16 pitch; /* relative pitch in cents - zero is unity playback */ + EAS_I16 gainLeft; /* requested gain */ + EAS_I16 gainRight; /* requested gain */ + EAS_I16 currentGainLeft; /* current gain for anti-zipper filter */ + EAS_I16 currentGainRight; /* current gain for anti-zipper filter */ + EAS_U16 blockSize; /* block size for ADPCM decoder */ + EAS_U16 blockCount; /* block counter for ADPCM decoder */ + EAS_U16 sampleRate; /* input sample rate */ + EAS_U8 srcByte; /* source byte */ + EAS_U8 msBitCount; /* count keeps track of MS bits */ + EAS_U8 msBitMask; /* mask keeps track of MS bits */ + EAS_U8 msBitValue; /* value keeps track of MS bits */ + EAS_U8 msBitCountLoop; /* count keeps track of MS bits, value at loop start */ + EAS_U8 msBitMaskLoop; /* mask keeps track of MS bits, value at loop start */ + EAS_U8 msBitValueLoop; /* value keeps track of MS bits, value at loop start */ + EAS_BOOL8 hiNibble; /* indicates high/low nibble is next */ + EAS_BOOL8 hiNibbleLoop; /* indicates high/low nibble is next, value loop start */ + EAS_U8 rateShift; /* for playback rate greater than 1.0 */ +} S_PCM_STATE; + +/*---------------------------------------------------------------------------- + * S_DECODER_INTERFACE + * + * Generic interface for audio decoders + *---------------------------------------------------------------------------- +*/ +typedef struct s_decoder_interface_tag +{ + EAS_RESULT (* EAS_CONST pfInit)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); + EAS_RESULT (* EAS_CONST pfDecodeSample)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); + EAS_RESULT (* EAS_CONST pfLocate)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); +} S_DECODER_INTERFACE; + + +/* header chunk for SMAF ADPCM */ +#define TAG_YAMAHA_ADPCM 0x4d776100 +#define TAG_MASK 0xffffff00 +#define TAG_RIFF_FILE 0x52494646 +#define TAG_WAVE_CHUNK 0x57415645 +#define TAG_FMT_CHUNK 0x666d7420 + +/*---------------------------------------------------------------------------- + * EAS_PESeek + *---------------------------------------------------------------------------- + * Purpose: + * Locate to a particular byte in a PCM stream + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_PESeek (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation); + +#endif /* _EAS_PCMDATA_H */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_public.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_public.c new file mode 100755 index 0000000..8d33b09 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_public.c @@ -0,0 +1,2601 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_public.c + * + * Contents and purpose: + * Contains EAS library public interface + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 842 $ + * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_synthcfg.h" +#include "eas.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" +#include "eas_data.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_midi.h" +#include "eas_mixer.h" +#include "eas_build.h" +#include "eas_vm_protos.h" +#include "eas_math.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + +#ifdef DLS_SYNTHESIZER +#include "eas_mdls.h" +#endif + +/* number of events to parse before calling EAS_HWYield function */ +#define YIELD_EVENT_COUNT 10 + +/*---------------------------------------------------------------------------- + * easLibConfig + * + * This structure is available through the EAS public interface to allow + * the user to check the configuration of the library. + *---------------------------------------------------------------------------- +*/ +static const S_EAS_LIB_CONFIG easLibConfig = +{ + LIB_VERSION, +#ifdef _CHECKED_BUILD + EAS_TRUE, +#else + EAS_FALSE, +#endif + MAX_SYNTH_VOICES, + NUM_OUTPUT_CHANNELS, + _OUTPUT_SAMPLE_RATE, + BUFFER_SIZE_IN_MONO_SAMPLES, +#ifdef _FILTER_ENABLED + EAS_TRUE, +#else + EAS_FALSE, +#endif + _BUILD_TIME_, + _BUILD_VERSION_ +}; + +/* local prototypes */ +static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, S_EAS_STREAM *pStream, EAS_U32 endTime, EAS_INT parseMode); + +/*---------------------------------------------------------------------------- + * EAS_SetStreamParameter + *---------------------------------------------------------------------------- + * Sets the specified parameter in the stream. Allows access to + * customizable settings within the individual file parsers. + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * param - enumerated parameter (see eas_parser.h) + * value - new value + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 value) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfSetData) + return (*pParserModule->pfSetData)(pEASData, pStream->handle, param, value); + return EAS_ERROR_FEATURE_NOT_AVAILABLE; +} + +/*---------------------------------------------------------------------------- + * EAS_GetStreamParameter + *---------------------------------------------------------------------------- + * Sets the specified parameter in the stream. Allows access to + * customizable settings within the individual file parsers. + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * param - enumerated parameter (see eas_parser.h) + * pValue - pointer to variable to receive current setting + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_GetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 *pValue) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfGetData) + return (*pParserModule->pfGetData)(pEASData, pStream->handle, param, pValue); + return EAS_ERROR_FEATURE_NOT_AVAILABLE; +} + +/*---------------------------------------------------------------------------- + * EAS_StreamReady() + *---------------------------------------------------------------------------- + * This routine sets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_SetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * set the parameter directly on the synth. This eliminates duplicate + * code in the parser. + *---------------------------------------------------------------------------- +*/ +EAS_BOOL EAS_StreamReady (S_EAS_DATA *pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule->pfState(pEASData, pStream->handle, &state) != EAS_SUCCESS) + return EAS_FALSE; + return (state < EAS_STATE_OPEN); +} + +/*---------------------------------------------------------------------------- + * EAS_IntSetStrmParam() + *---------------------------------------------------------------------------- + * This routine sets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_SetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * set the parameter directly on the synth. This eliminates duplicate + * code in the parser. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value) +{ + S_SYNTH *pSynth; + + /* try to set the parameter using stream interface */ + if (EAS_SetStreamParameter(pEASData, pStream, param, value) == EAS_SUCCESS) + return EAS_SUCCESS; + + /* get a pointer to the synth object and set it directly */ + /*lint -e{740} we are cheating by passing a pointer through this interface */ + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + switch (param) + { + +#ifdef DLS_SYNTHESIZER + case PARSER_DATA_DLS_COLLECTION: + { + EAS_RESULT result = VMSetDLSLib(pSynth, (EAS_DLSLIB_HANDLE) value); + if (result == EAS_SUCCESS) + { + DLSAddRef((S_DLS*) value); + VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); + } + return result; + } +#endif + + case PARSER_DATA_EAS_LIBRARY: + return VMSetEASLib(pSynth, (EAS_SNDLIB_HANDLE) value); + + case PARSER_DATA_POLYPHONY: + return VMSetPolyphony(pEASData->pVoiceMgr, pSynth, value); + + case PARSER_DATA_PRIORITY: + return VMSetPriority(pEASData->pVoiceMgr, pSynth, value); + + case PARSER_DATA_TRANSPOSITION: + VMSetTranposition(pSynth, value); + break; + + case PARSER_DATA_VOLUME: + VMSetVolume(pSynth, (EAS_U16) value); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_IntGetStrmParam() + *---------------------------------------------------------------------------- + * This routine gets common parameters like transpose, volume, etc. + * First, it attempts to use the parser EAS_GetStreamParameter interface. If that + * fails, it attempts to get the synth handle from the parser and + * get the parameter directly on the synth. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_IntGetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 *pValue) +{ + S_SYNTH *pSynth; + + /* try to set the parameter */ + if (EAS_GetStreamParameter(pEASData, pStream, param, pValue) == EAS_SUCCESS) + return EAS_SUCCESS; + + /* get a pointer to the synth object and retrieve data directly */ + /*lint -e{740} we are cheating by passing a pointer through this interface */ + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + switch (param) + { + case PARSER_DATA_POLYPHONY: + return VMGetPolyphony(pEASData->pVoiceMgr, pSynth, pValue); + + case PARSER_DATA_PRIORITY: + return VMGetPriority(pEASData->pVoiceMgr, pSynth, pValue); + + case PARSER_DATA_TRANSPOSITION: + VMGetTranposition(pSynth, pValue); + break; + + case PARSER_DATA_NOTE_COUNT: + *pValue = VMGetNoteCount(pSynth); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_AllocateStream() + *---------------------------------------------------------------------------- + * Purpose: + * Allocates a stream handle + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_INT EAS_AllocateStream (EAS_DATA_HANDLE pEASData) +{ + EAS_INT streamNum; + + /* check for static allocation, only one stream allowed */ + if (pEASData->staticMemoryModel) + { + if (pEASData->streams[0].handle != NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Attempt to open multiple streams in static model\n"); */ } + return -1; + } + return 0; + } + + /* dynamic model */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + if (pEASData->streams[streamNum].handle == NULL) + break; + if (streamNum == MAX_NUMBER_STREAMS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Exceeded maximum number of open streams\n"); */ } + return -1; + } + return streamNum; +} + +/*---------------------------------------------------------------------------- + * EAS_InitStream() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize a stream + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static void EAS_InitStream (S_EAS_STREAM *pStream, EAS_VOID_PTR pParserModule, EAS_VOID_PTR streamHandle) +{ + pStream->pParserModule = pParserModule; + pStream->handle = streamHandle; + pStream->time = 0; + pStream->frameLength = AUDIO_FRAME_LENGTH; + pStream->repeatCount = 0; + pStream->volume = DEFAULT_STREAM_VOLUME; + pStream->streamFlags = 0; +} + +/*---------------------------------------------------------------------------- + * EAS_Config() + *---------------------------------------------------------------------------- + * Purpose: + * Returns a pointer to a structure containing the configuration options + * in this library build. + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void) +{ + return &easLibConfig; +} + +/*---------------------------------------------------------------------------- + * EAS_Init() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the synthesizer library + * + * Inputs: + * ppEASData - pointer to data handle variable for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData) +{ + EAS_HW_DATA_HANDLE pHWInstData; + EAS_RESULT result; + S_EAS_DATA *pEASData; + EAS_INT module; + EAS_BOOL staticMemoryModel; + + /* get the memory model */ + staticMemoryModel = EAS_CMStaticMemoryModel(); + + /* initialize the host wrapper interface */ + *ppEASData = NULL; + if ((result = EAS_HWInit(&pHWInstData)) != EAS_SUCCESS) + return result; + + /* check Configuration Module for S_EAS_DATA allocation */ + if (staticMemoryModel) + pEASData = EAS_CMEnumData(EAS_CM_EAS_DATA); + else + pEASData = EAS_HWMalloc(pHWInstData, sizeof(S_EAS_DATA)); + if (!pEASData) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate EAS library memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* initialize some data */ + EAS_HWMemSet(pEASData, 0, sizeof(S_EAS_DATA)); + pEASData->staticMemoryModel = (EAS_BOOL8) staticMemoryModel; + pEASData->hwInstData = pHWInstData; + pEASData->renderTime = 0; + + /* set header search flag */ +#ifdef FILE_HEADER_SEARCH + pEASData->searchHeaderFlag = EAS_TRUE; +#endif + + /* initalize parameters */ + EAS_SetVolume(pEASData, NULL, DEFAULT_VOLUME); + +#ifdef _METRICS_ENABLED + /* initalize the metrics module */ + pEASData->pMetricsModule = EAS_CMEnumOptModules(EAS_MODULE_METRICS); + if (pEASData->pMetricsModule != NULL) + { + if ((result = (*pEASData->pMetricsModule->pfInit)(pEASData, &pEASData->pMetricsData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld initializing metrics module\n", result); */ } + return result; + } + } +#endif + + /* initailize the voice manager & synthesizer */ + if ((result = VMInitialize(pEASData)) != EAS_SUCCESS) + return result; + + /* initialize mix engine */ + if ((result = EAS_MixEngineInit(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld starting up mix engine\n", result); */ } + return result; + } + + /* initialize effects modules */ + for (module = 0; module < NUM_EFFECTS_MODULES; module++) + { + pEASData->effectsModules[module].effect = EAS_CMEnumFXModules(module); + if (pEASData->effectsModules[module].effect != NULL) + { + if ((result = (*pEASData->effectsModules[module].effect->pfInit)(pEASData, &pEASData->effectsModules[module].effectData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Initialization of effects module %d returned %d\n", module, result); */ } + return result; + } + } + } + + /* initialize PCM engine */ + if ((result = EAS_PEInit(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_PEInit failed with error code %ld\n", result); */ } + return result; + } + + /* return instance data pointer to host */ + *ppEASData = pEASData; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_Shutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Shuts down the library. Deallocates any memory associated with the + * synthesizer (dynamic memory model only) + * + * Inputs: + * pEASData - handle to data for this instance + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData) +{ + EAS_HW_DATA_HANDLE hwInstData; + EAS_RESULT result, reportResult; + EAS_INT i; + + /* establish pointers */ + hwInstData = pEASData->hwInstData; + + /* check for NULL handle */ + if (!pEASData) + return EAS_ERROR_HANDLE_INTEGRITY; + + /* if there are streams open, close them */ + reportResult = EAS_SUCCESS; + for (i = 0; i < MAX_NUMBER_STREAMS; i++) + { + if (pEASData->streams[i].pParserModule && pEASData->streams[i].handle) + { + if ((result = (*((S_FILE_PARSER_INTERFACE*)(pEASData->streams[i].pParserModule))->pfClose)(pEASData, pEASData->streams[i].handle)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down parser module\n", result); */ } + reportResult = result; + } + } + } + + /* shutdown PCM engine */ + if ((result = EAS_PEShutdown(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down PCM engine\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + + /* shutdown mix engine */ + if ((result = EAS_MixEngineShutdown(pEASData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down mix engine\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + + /* shutdown effects modules */ + for (i = 0; i < NUM_EFFECTS_MODULES; i++) + { + if (pEASData->effectsModules[i].effect) + { + if ((result = (*pEASData->effectsModules[i].effect->pfShutdown)(pEASData, pEASData->effectsModules[i].effectData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Shutdown of effects module %d returned %d\n", i, result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + } + + /* shutdown the voice manager & synthesizer */ + VMShutdown(pEASData); + +#ifdef _METRICS_ENABLED + /* shutdown the metrics module */ + if (pEASData->pMetricsModule != NULL) + { + if ((result = (*pEASData->pMetricsModule->pfShutdown)(pEASData, pEASData->pMetricsData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down metrics module\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } +#endif + + /* release allocated memory */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(hwInstData, pEASData); + + /* shutdown host wrappers */ + if (hwInstData) + { + if ((result = EAS_HWShutdown(hwInstData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down host wrappers\n", result); */ } + if (reportResult == EAS_SUCCESS) + reportResult = result; + } + } + + return reportResult; +} + +#ifdef JET_INTERFACE +/*---------------------------------------------------------------------------- + * EAS_OpenJETStream() + *---------------------------------------------------------------------------- + * Private interface for JET to open an SMF stream with an offset + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for SMF parser */ + *ppStream = NULL; + streamHandle = NULL; + pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(0); + if (pParserModule == NULL) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* see if SMF parser recognizes the file */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, offset)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser recognized the file, return the handle */ + if (streamHandle) + { + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_OpenFile() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_FILE_HANDLE fileHandle; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + EAS_INT moduleNum; + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for file parsers */ + pParserModule = NULL; + *ppStream = NULL; + streamHandle = NULL; + for (moduleNum = 0; ; moduleNum++) + { + pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(moduleNum); + if (pParserModule == NULL) + break; + + /* see if this parser recognizes it */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser recognized the file, return the handle */ + if (streamHandle) + { + + /* save the parser pointer and file handle */ + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + /* rewind the file for the next parser */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, 0L)) != EAS_SUCCESS) + return result; + } + + /* no parser was able to recognize the file, close it and return an error */ + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * EAS_MMAPIToneControl() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a ToneControl file for audio playback. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) +{ + EAS_RESULT result; + EAS_FILE_HANDLE fileHandle; + EAS_VOID_PTR streamHandle; + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_INT streamNum; + + /* check if the tone control parser is available */ + *ppStream = NULL; + streamHandle = NULL; + pParserModule = EAS_CMEnumOptModules(EAS_MODULE_MMAPI_TONE_CONTROL); + if (pParserModule == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_MMAPIToneControl: ToneControl parser not available\n"); */ } + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + } + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* see if ToneControl parser recognizes it */ + if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } + return result; + } + + /* parser accepted the file, return the handle */ + if (streamHandle) + { + + /* save the parser pointer and file handle */ + EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); + *ppStream = &pEASData->streams[streamNum]; + return EAS_SUCCESS; + } + + /* parser did not recognize the file, close it and return an error */ + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } + return EAS_ERROR_UNRECOGNIZED_FORMAT; +} + +/*---------------------------------------------------------------------------- + * EAS_GetWaveFmtChunk + *---------------------------------------------------------------------------- + * Helper function to retrieve WAVE file fmt chunk for MMAPI + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * pFmtChunk - pointer to variable to receive current setting + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_VOID_PTR *ppFmtChunk) +{ + EAS_RESULT result; + EAS_I32 value; + + if ((result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FORMAT, &value)) != EAS_SUCCESS) + return result; + *ppFmtChunk = (EAS_VOID_PTR) value; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_GetFileType + *---------------------------------------------------------------------------- + * Returns the file type (see eas_types.h for enumerations) + *---------------------------------------------------------------------------- + * pEASData - pointer to EAS persistent data object + * pStream - stream handle + * pFileType - pointer to variable to receive file type + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetFileType (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 *pFileType) +{ + if (!EAS_StreamReady (pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FILE_TYPE, pFileType); +} + +/*---------------------------------------------------------------------------- + * EAS_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepares the synthesizer to play the file or stream. Parses the first + * frame of data from the file and arms the synthesizer. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + /* prepare the stream */ + if (state == EAS_STATE_OPEN) + { + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + result = (*pParserModule->pfPrepare)(pEASData, pStream->handle); + + /* set volume */ + if (result == EAS_SUCCESS) + result = EAS_SetVolume(pEASData, pStream, pStream->volume); + } + else + result = EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_Render() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the Midi data and render PCM audio data. + * + * Inputs: + * pEASData - buffer for internal EAS data + * pOut - output buffer pointer + * nNumRequested - requested num samples to generate + * pnNumGenerated - actual number of samples generated + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_I32 voicesRendered; + EAS_STATE parserState; + EAS_INT streamNum; + + /* assume no samples generated and reset workload */ + *pNumGenerated = 0; + VMInitWorkload(pEASData->pVoiceMgr); + + /* no support for other buffer sizes yet */ + if (numRequested != BUFFER_SIZE_IN_MONO_SAMPLES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "This library supports only %ld samples in buffer, host requested %ld samples\n", + (EAS_I32) BUFFER_SIZE_IN_MONO_SAMPLES, numRequested); */ } + return EAS_BUFFER_SIZE_MISMATCH; + } + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); +#endif + + /* prep the frame buffer, do mix engine prep only if TRUE */ +#ifdef _SPLIT_ARCHITECTURE + if (VMStartFrame(pEASData)) + EAS_MixEnginePrep(pEASData, numRequested); +#else + /* prep the mix engine */ + EAS_MixEnginePrep(pEASData, numRequested); +#endif + + /* save the output buffer pointer */ + pEASData->pOutputAudioBuffer = pOut; + + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); +#endif + + /* if we haven't finished parsing from last time, do it now */ + /* need to parse another frame of events before we render again */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + { + /* clear the locate flag */ + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_LOCATE; + + if (pEASData->streams[streamNum].pParserModule) + { + + /* establish pointer to parser module */ + pParserModule = pEASData->streams[streamNum].pParserModule; + + /* handle pause */ + if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PAUSE) + { + if (pParserModule->pfPause) + result = pParserModule->pfPause(pEASData, pEASData->streams[streamNum].handle); + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PAUSE; + } + + /* get current state */ + if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) + return result; + + /* handle resume */ + if (parserState == EAS_STATE_PAUSED) + { + if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_RESUME) + { + if (pParserModule->pfResume) + result = pParserModule->pfResume(pEASData, pEASData->streams[streamNum].handle); + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_RESUME; + } + } + + /* if necessary, parse stream */ + if ((pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PARSED) == 0) + if ((result = EAS_ParseEvents(pEASData, &pEASData->streams[streamNum], pEASData->streams[streamNum].time + pEASData->streams[streamNum].frameLength, eParserModePlay)) != EAS_SUCCESS) + return result; + + /* check for an early abort */ + if ((pEASData->streams[streamNum].streamFlags) == 0) + { + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); +#endif + + return EAS_SUCCESS; + } + + /* check for repeat */ + if (pEASData->streams[streamNum].repeatCount) + { + + /* check for stopped state */ + if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) + return result; + if (parserState == EAS_STATE_STOPPED) + { + + /* decrement repeat count, unless it is negative */ + if (pEASData->streams[streamNum].repeatCount > 0) + pEASData->streams[streamNum].repeatCount--; + + /* reset the parser */ + if ((result = (*pParserModule->pfReset)(pEASData, pEASData->streams[streamNum].handle)) != EAS_SUCCESS) + return result; + pEASData->streams[streamNum].time = 0; + } + } + } + } + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); +#endif + +#ifdef _METRICS_ENABLED + /* start the render timer */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); +#endif + + /* render audio */ + if ((result = VMRender(pEASData->pVoiceMgr, BUFFER_SIZE_IN_MONO_SAMPLES, pEASData->pMixBuffer, &voicesRendered)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "pfRender function returned error %ld\n", result); */ } + return result; + } + +#ifdef _METRICS_ENABLED + /* stop the render timer */ + if (pEASData->pMetricsData) { + (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_FRAME_COUNT, 1); + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); + (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_TOTAL_VOICE_COUNT, (EAS_U32) voicesRendered); + (void)(*pEASData->pMetricsModule->pfRecordMaxValue)(pEASData->pMetricsData, EAS_PM_MAX_VOICES, (EAS_U32) voicesRendered); + } +#endif + + //2 Do we really need frameParsed? + /* need to parse another frame of events before we render again */ + for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) + if (pEASData->streams[streamNum].pParserModule != NULL) + pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PARSED; + +#ifdef _METRICS_ENABLED + /* start performance counter */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); +#endif + + /* render PCM audio */ + if ((result = EAS_PERender(pEASData, numRequested)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_PERender returned error %ld\n", result); */ } + return result; + } + +#ifdef _METRICS_ENABLED + /* stop the stream timer */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); +#endif + +#ifdef _METRICS_ENABLED + /* start the post timer */ + if (pEASData->pMetricsData) + (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); +#endif + + /* for split architecture, send DSP vectors. Do post only if return is TRUE */ +#ifdef _SPLIT_ARCHITECTURE + if (VMEndFrame(pEASData)) + { + /* now do post-processing */ + EAS_MixEnginePost(pEASData, numRequested); + *pNumGenerated = numRequested; + } +#else + /* now do post-processing */ + EAS_MixEnginePost(pEASData, numRequested); + *pNumGenerated = numRequested; +#endif + +#ifdef _METRICS_ENABLED + /* stop the post timer */ + if (pEASData->pMetricsData) + (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); +#endif + + /* advance render time */ + pEASData->renderTime += AUDIO_FRAME_LENGTH; + +#if 0 + /* dump workload for debug */ + if (pEASData->pVoiceMgr->workload) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Workload = %d\n", pEASData->pVoiceMgr->workload); */ } +#endif + +#ifdef _METRICS_ENABLED + /* stop performance counter */ + if (pEASData->pMetricsData) + { + PERF_TIMER temp; + temp = (*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); + + /* if max render time, record the number of voices and time */ + if ((*pEASData->pMetricsModule->pfRecordMaxValue) + (pEASData->pMetricsData, EAS_PM_MAX_CYCLES, (EAS_U32) temp)) + { + (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_VOICES, (EAS_U32) voicesRendered); + (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_TIME, (EAS_I32) (pEASData->renderTime >> 8)); + } + } +#endif + +#ifdef JET_INTERFACE + /* let JET to do its thing */ + if (pEASData->jetHandle != NULL) + { + result = JET_Process(pEASData); + if (result != EAS_SUCCESS) + return result; + } +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Set the selected stream to repeat. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * repeatCount - repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 repeatCount) +{ + pStream->repeatCount = repeatCount; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetRepeat() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the current repeat count for the selected stream. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * pRrepeatCount - pointer to variable to hold repeat count + * + * Outputs: + * + * Side Effects: + * + * Notes: + * 0 = no repeat + * 1 = repeat once, i.e. play through twice + * -1 = repeat forever + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pRepeatCount) +{ + *pRepeatCount = pStream->repeatCount; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPlaybackRate() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the playback rate. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * rate - rate (28-bit fractional amount) + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U32 rate) +{ + + /* check range */ + if ((rate < (1 << 27)) || (rate > (1 << 29))) + return EAS_ERROR_INVALID_PARAMETER; + + /* calculate new frame length + * + * NOTE: The maximum frame length we can accomodate based on a + * maximum rate of 2.0 (2^28) is 2047 (2^13-1). To accomodate a + * longer frame length or a higher maximum rate, the fixed point + * divide below will need to be adjusted + */ + pStream->frameLength = (AUDIO_FRAME_LENGTH * (rate >> 8)) >> 20; + + /* notify stream of new playback rate */ + EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_PLAYBACK_RATE, (EAS_I32) rate); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetTransposition) + *---------------------------------------------------------------------------- + * Purpose: + * Sets the key tranposition for the synthesizer. Transposes all + * melodic instruments by the specified amount. Range is limited + * to +/-12 semitones. + * + * Inputs: + * pEASData - handle to data for this instance + * handle - handle to stream + * transposition - +/-12 semitones + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 transposition) +{ + + /* check range */ + if ((transposition < -12) || (transposition > 12)) + return EAS_ERROR_INVALID_PARAMETER; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_TRANSPOSITION, transposition); +} + +/*---------------------------------------------------------------------------- + * EAS_ParseEvents() + *---------------------------------------------------------------------------- + * Purpose: + * Parse events in the current streams until the desired time is reached. + * + * Inputs: + * pEASData - buffer for internal EAS data + * endTime - stop parsing if this time is reached + * parseMode - play, locate, or metadata + * + * Outputs: + * EAS_SUCCESS if PCM data was successfully rendered + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_U32 endTime, EAS_INT parseMode) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_I32 parserState; + EAS_BOOL done; + EAS_INT yieldCount = YIELD_EVENT_COUNT; + EAS_U32 time = 0; + + /* does this parser have a time function? */ + pParserModule = pStream->pParserModule; + if (pParserModule->pfTime == NULL) + { + /* check state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) + return result; + /* if play state, advance time */ + if ((parserState >= EAS_STATE_READY) && (parserState <= EAS_STATE_PAUSING)) + pStream->time += pStream->frameLength; + done = EAS_TRUE; + } + + /* assume we're not done, in case we abort out */ + else + { + pStream->streamFlags &= ~STREAM_FLAGS_PARSED; + done = EAS_FALSE; + } + + while (!done) + { + + /* check for stopped state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) + return result; + if (parserState > EAS_STATE_PLAY) + { + /* save current time if we're not in play mode */ + if (parseMode != eParserModePlay) + pStream->time = time << 8; + done = EAS_TRUE; + break; + } + + /* get the next event time */ + if (pParserModule->pfTime) + { + if ((result = (*pParserModule->pfTime)(pEASData, pStream->handle, &time)) != EAS_SUCCESS) + return result; + + /* if next event is within this frame, parse it */ + if (time < (endTime >> 8)) + { + + /* parse the next event */ + if (pParserModule->pfEvent) + if ((result = (*pParserModule->pfEvent)(pEASData, pStream->handle, parseMode)) != EAS_SUCCESS) + return result; + } + + /* no more events in this frame, advance time */ + else + { + pStream->time = endTime; + done = EAS_TRUE; + } + } + + /* check for max workload exceeded */ + if (VMCheckWorkload(pEASData->pVoiceMgr)) + { + /* stop even though we may not have parsed + * all the events in this frame. The parser will try to + * catch up on the next frame. + */ + break; + } + + /* give host a chance for an early abort */ + if (--yieldCount == 0) + { + if (EAS_HWYield(pEASData->hwInstData)) + break; + yieldCount = YIELD_EVENT_COUNT; + } + } + + /* if no early abort, parsing is complete for this frame */ + if (done) + pStream->streamFlags |= STREAM_FLAGS_PARSED; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_ParseMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * playLength - pointer to variable to store the play length (in msecs) + * + * Outputs: + * + * + * Side Effects: + * - resets the parser to the start of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *playLength) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_STATE state; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check parser state */ + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) + return result; + if (state >= EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* if parser has metadata function, use that */ + if (pParserModule->pfGetMetaData != NULL) + return pParserModule->pfGetMetaData(pEASData, pStream->handle, playLength); + + /* reset the parser to the beginning */ + if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) + return result; + + /* parse the file to end */ + pStream->time = 0; + VMInitWorkload(pEASData->pVoiceMgr); + if ((result = EAS_ParseEvents(pEASData, pStream, 0x7fffffff, eParserModeMetaData)) != EAS_SUCCESS) + return result; + + /* get the parser time */ + if ((result = EAS_GetLocation(pEASData, pStream, playLength)) != EAS_SUCCESS) + return result; + + /* reset the parser to the beginning */ + pStream->time = 0; + return (*pParserModule->pfReset)(pEASData, pStream->handle); +} + +/*---------------------------------------------------------------------------- + * EAS_RegisterMetaDataCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers a metadata callback function for parsed metadata. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * cbFunc - pointer to host callback function + * metaDataBuffer - pointer to metadata buffer + * metaDataBufSize - maximum size of the metadata buffer + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( + EAS_DATA_HANDLE pEASData, + EAS_HANDLE pStream, + EAS_METADATA_CBFUNC cbFunc, + char *metaDataBuffer, + EAS_I32 metaDataBufSize, + EAS_VOID_PTR pUserData) +{ + S_METADATA_CB metadata; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* register callback function */ + metadata.callback = cbFunc; + metadata.buffer = metaDataBuffer; + metadata.bufferSize = metaDataBufSize; + metadata.pUserData = pUserData; + return EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_METADATA_CB, (EAS_I32) &metadata); +} + +/*---------------------------------------------------------------------------- + * EAS_GetNoteCount () + *---------------------------------------------------------------------------- + * Returns the total number of notes played in this stream + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_NOTE_COUNT, pNoteCount); +} + +/*---------------------------------------------------------------------------- + * EAS_CloseFile() + *---------------------------------------------------------------------------- + * Purpose: + * Closes an audio file or stream. Playback should have either paused or + * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + + /* call the close function */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + result = (*pParserModule->pfClose)(pEASData, pStream->handle); + + /* clear the handle and parser interface pointer */ + pStream->handle = NULL; + pStream->pParserModule = NULL; + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_OpenMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pHandle - pointer to variable to hold file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *ppStream, EAS_HANDLE streamHandle) +{ + EAS_RESULT result; + S_INTERACTIVE_MIDI *pMIDIStream; + EAS_INT streamNum; + + /* initialize some pointers */ + *ppStream = NULL; + + /* allocate a stream */ + if ((streamNum = EAS_AllocateStream(pEASData)) < 0) + return EAS_ERROR_MAX_STREAMS_OPEN; + + /* check Configuration Module for S_EAS_DATA allocation */ + if (pEASData->staticMemoryModel) + pMIDIStream = EAS_CMEnumData(EAS_CM_MIDI_STREAM_DATA); + else + pMIDIStream = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_INTERACTIVE_MIDI)); + + /* allocate dynamic memory */ + if (!pMIDIStream) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate MIDI stream data\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* zero the memory to insure complete initialization */ + EAS_HWMemSet(pMIDIStream, 0, sizeof(S_INTERACTIVE_MIDI)); + EAS_InitStream(&pEASData->streams[streamNum], NULL, pMIDIStream); + + /* instantiate a new synthesizer */ + if (streamHandle == NULL) + { + result = VMInitMIDI(pEASData, &pMIDIStream->pSynth); + } + + /* use an existing synthesizer */ + else + { + EAS_I32 value; + result = EAS_GetStreamParameter(pEASData, streamHandle, PARSER_DATA_SYNTH_HANDLE, &value); + pMIDIStream->pSynth = (S_SYNTH*) value; + VMIncRefCount(pMIDIStream->pSynth); + } + if (result != EAS_SUCCESS) + { + EAS_CloseMIDIStream(pEASData, &pEASData->streams[streamNum]); + return result; + } + + /* initialize the MIDI stream data */ + EAS_InitMIDIStream(&pMIDIStream->stream); + + *ppStream = (EAS_HANDLE) &pEASData->streams[streamNum]; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_WriteMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Send data to the MIDI stream device + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - stream handle + * pBuffer - pointer to buffer + * count - number of bytes to write + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 *pBuffer, EAS_I32 count) +{ + S_INTERACTIVE_MIDI *pMIDIStream; + EAS_RESULT result; + + pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; + + if (count <= 0) + return EAS_ERROR_PARAMETER_RANGE; + + /* send the entire buffer */ + while (count--) + { + if ((result = EAS_ParseMIDIStream(pEASData, pMIDIStream->pSynth, &pMIDIStream->stream, *pBuffer++, eParserModePlay)) != EAS_SUCCESS) + return result; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_CloseMIDIStream() + *---------------------------------------------------------------------------- + * Purpose: + * Closes a raw MIDI stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_INTERACTIVE_MIDI *pMIDIStream; + + pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; + + /* close synth */ + if (pMIDIStream->pSynth != NULL) + { + VMMIDIShutdown(pEASData, pMIDIStream->pSynth); + pMIDIStream->pSynth = NULL; + } + + /* release allocated memory */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(((S_EAS_DATA*) pEASData)->hwInstData, pMIDIStream); + + pStream->handle = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the state of an audio file or stream. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_STATE *pState) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + + /* call the parser to return state */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, pState)) != EAS_SUCCESS) + return result; + + /* if repeat count is set for this parser, mask the stopped state from the application */ + if (pStream->repeatCount && (*pState == EAS_STATE_STOPPED)) + *pState = EAS_STATE_PLAY; + + /* if we're not ready or playing, we don't need to hide state from host */ + if (*pState > EAS_STATE_PLAY) + return EAS_SUCCESS; + + /* if stream is about to be paused, report it as paused */ + if (pStream->streamFlags & STREAM_FLAGS_PAUSE) + { + if (pStream->streamFlags & STREAM_FLAGS_LOCATE) + *pState = EAS_STATE_PAUSED; + else + *pState = EAS_STATE_PAUSING; + } + + /* if stream is about to resume, report it as playing */ + if (pStream->streamFlags & STREAM_FLAGS_RESUME) + *pState = EAS_STATE_PLAY; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the stream. A value of 0 allows the stream + * to use all voices (set by EAS_SetSynthPolyphony). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 polyphonyCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, polyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_GetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPolyphonyCount) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, pPolyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_SetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the polyphony of the synth . Value must be >= 1 and <= the + * maximum number of voices. This function will pin the polyphony + * at those limits + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount) +{ + return VMSetSynthPolyphony(pEASData->pVoiceMgr, synthNum, polyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_GetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting of the synth + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * synthNum - synthesizer number (0 = onboard, 1 = DSP) + * pPolyphonyCount - pointer to variable to receive polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount) +{ + return VMGetSynthPolyphony(pEASData->pVoiceMgr, synthNum, pPolyphonyCount); +} + +/*---------------------------------------------------------------------------- + * EAS_SetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the priority of the stream. Determines which stream's voices + * are stolen when there are insufficient voices for all notes. + * Value must be in the range of 1-15, lower values are higher + * priority. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * polyphonyCount - the desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 priority) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, priority); +} + +/*---------------------------------------------------------------------------- + * EAS_GetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current priority setting of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * pPriority - pointer to variable to receive priority + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPriority) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, pPriority); +} + +/*---------------------------------------------------------------------------- + * EAS_SetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master gain for the mix engine in 1dB increments + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master gain (100 is max) + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 volume) +{ + EAS_I16 gain; + + /* check range */ + if ((volume < 0) || (volume > EAS_MAX_VOLUME)) + return EAS_ERROR_PARAMETER_RANGE; + + /* stream volume */ + if (pStream != NULL) + { + EAS_I32 gainOffset; + EAS_RESULT result; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* get gain offset */ + pStream->volume = (EAS_U8) volume; + result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_GAIN_OFFSET, &gainOffset); + if (result == EAS_SUCCESS) + volume += gainOffset; + + /* set stream volume */ + gain = EAS_VolumeToGain((int)volume - STREAM_VOLUME_HEADROOM); + + /* convert to linear scalar */ + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_VOLUME, gain); + } + + /* master volume */ + pEASData->masterVolume = (EAS_U8) volume; +#if (NUM_OUTPUT_CHANNELS == 1) + /* leave 3dB headroom for mono output */ + volume -= 3; +#endif + + gain = EAS_VolumeToGain((int)volume - STREAM_VOLUME_HEADROOM); + pEASData->masterGain = gain; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the master volume for the synthesizer. The default volume setting is + * 50. The volume range is 0 to 100; + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * volume - the desired master volume + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + if (pStream == NULL) + return pEASData->masterVolume; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return pStream->volume; +} + +/*---------------------------------------------------------------------------- + * EAS_SetMaxLoad() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the maximum workload the parsers will do in a single call to + * EAS_Render. The units are currently arbitrary, but should correlate + * well to the actual CPU cycles consumed. The primary effect is to + * reduce the occasional peaks in CPU cycles consumed when parsing + * dense parts of a MIDI score. + * + * Inputs: + * pEASData - handle to data for this instance + * maxLoad - the desired maximum workload + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad) +{ + VMSetWorkload(pEASData->pVoiceMgr, maxLoad); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetMaxPCMStreams() + *---------------------------------------------------------------------------- + * Sets the maximum number of PCM streams allowed in parsers that + * use PCM streaming. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * streamHandle - handle returned by EAS_OpenFile + * maxNumStreams - maximum number of PCM streams + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_MAX_PCM_STREAMS, maxNumStreams); +} + +/*---------------------------------------------------------------------------- + * EAS_Locate() + *---------------------------------------------------------------------------- + * Purpose: + * Locate into the file associated with the handle. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file handle + * milliseconds - playback offset from start of file in milliseconds + * + * Outputs: + * + * + * Side Effects: + * the actual offset will be quantized to the closest update period, typically + * a resolution of 5.9ms. Notes that are started prior to this time will not + * sound. Any notes currently playing will be shut off. + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 milliseconds, EAS_BOOL offset) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_RESULT result; + EAS_U32 requestedTime; + EAS_STATE state; + + /* get pointer to parser function table */ + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) + return result; + if (state >= EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* handle offset and limit to start of file */ + /*lint -e{704} use shift for performance*/ + if (offset) + milliseconds += (EAS_I32) pStream->time >> 8; + if (milliseconds < 0) + milliseconds = 0; + + /* check to see if the request is different from the current time */ + requestedTime = (EAS_U32) milliseconds; + if (requestedTime == (pStream->time >> 8)) + return EAS_SUCCESS; + + /* set the locate flag */ + pStream->streamFlags |= STREAM_FLAGS_LOCATE; + + /* use the parser locate function, if available */ + if (pParserModule->pfLocate != NULL) + { + EAS_BOOL parserLocate = EAS_FALSE; + result = pParserModule->pfLocate(pEASData, pStream->handle, (EAS_I32) requestedTime, &parserLocate); + if (!parserLocate) + { + if (result == EAS_SUCCESS) + pStream->time = requestedTime << 8; + return result; + } + } + + /* if we were paused and not going to resume, set pause request flag */ + if (((state == EAS_STATE_PAUSING) || (state == EAS_STATE_PAUSED)) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) + pStream->streamFlags |= STREAM_FLAGS_PAUSE; + + /* reset the synth and parser */ + if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) + return result; + pStream->time = 0; + + /* locating forward, clear parsed flag and parse data until we get to the requested location */ + if ((result = EAS_ParseEvents(pEASData, pStream, requestedTime << 8, eParserModeLocate)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetLocation() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file handle + * + * Outputs: + * The offset in milliseconds from the start of the current sequence, quantized + * to the nearest update period. Actual resolution is typically 5.9 ms. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pTime) +{ + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + *pTime = pStream->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetRenderTime() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current playback offset + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * Gets the render time clock in msecs. + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime) +{ + *pTime = pEASData->renderTime >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the playback of the data associated with this handle. The audio + * is gracefully ramped down to prevent clicks and pops. It may take several + * buffers of audio before the audio is muted. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + if ((state != EAS_STATE_PLAY) && (state != EAS_STATE_READY) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* make sure parser implements pause */ + if (pParserModule->pfPause == NULL) + result = EAS_ERROR_NOT_IMPLEMENTED; + + /* clear resume flag */ + pStream->streamFlags &= ~STREAM_FLAGS_RESUME; + + /* set pause flag */ + pStream->streamFlags |= STREAM_FLAGS_PAUSE; + +#if 0 + /* pause the stream */ + if (pParserModule->pfPause) + result = pParserModule->pfPause(pEASData, pStream->handle); + else + result = EAS_ERROR_NOT_IMPLEMENTED; +#endif + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resumes the playback of the data associated with this handle. The audio + * is gracefully ramped up to prevent clicks and pops. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) +{ + S_FILE_PARSER_INTERFACE *pParserModule; + EAS_STATE state; + EAS_RESULT result; + + pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; + if (pParserModule == NULL) + return EAS_ERROR_FEATURE_NOT_AVAILABLE; + + /* check for valid state */ + result = pParserModule->pfState(pEASData, pStream->handle, &state); + if (result == EAS_SUCCESS) + { + if ((state != EAS_STATE_PAUSED) && (state != EAS_STATE_PAUSING) && ((pStream->streamFlags & STREAM_FLAGS_PAUSE) == 0)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* make sure parser implements this function */ + if (pParserModule->pfResume == NULL) + result = EAS_ERROR_NOT_IMPLEMENTED; + + /* clear pause flag */ + pStream->streamFlags &= ~STREAM_FLAGS_PAUSE; + + /* set resume flag */ + pStream->streamFlags |= STREAM_FLAGS_RESUME; + +#if 0 + /* resume the stream */ + if (pParserModule->pfResume) + result = pParserModule->pfResume(pEASData, pStream->handle); + else + result = EAS_ERROR_NOT_IMPLEMENTED; +#endif + } + + return result; +} + +/*---------------------------------------------------------------------------- + * EAS_GetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * pValue - pointer to variable to receive parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue) +{ + + if (module >= NUM_EFFECTS_MODULES) + return EAS_ERROR_INVALID_MODULE; + + if (pEASData->effectsModules[module].effectData == NULL) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->effectsModules[module].effect->pFGetParam) + (pEASData->effectsModules[module].effectData, param, pValue); +} + +/*---------------------------------------------------------------------------- + * EAS_SetParameter() + *---------------------------------------------------------------------------- + * Purpose: + * Set the parameter of a module. See E_MODULES for a list of modules + * and the header files of the modules for a list of parameters. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * handle - file or stream handle + * module - enumerated module number + * param - enumerated parameter number + * value - new parameter value + * + * Outputs: + * + * + * Side Effects: + * + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value) +{ + + if (module >= NUM_EFFECTS_MODULES) + return EAS_ERROR_INVALID_MODULE; + + if (pEASData->effectsModules[module].effectData == NULL) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->effectsModules[module].effect->pFSetParam) + (pEASData->effectsModules[module].effectData, param, value); +} + +#ifdef _METRICS_ENABLED +/*---------------------------------------------------------------------------- + * EAS_MetricsReport() + *---------------------------------------------------------------------------- + * Purpose: + * Displays the current metrics through the metrics interface. + * + * Inputs: + * p - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData) +{ + if (!pEASData->pMetricsModule) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->pMetricsModule->pfReport)(pEASData->pMetricsData); +} + +/*---------------------------------------------------------------------------- + * EAS_MetricsReset() + *---------------------------------------------------------------------------- + * Purpose: + * Resets the metrics. + * + * Inputs: + * p - instance data handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData) +{ + + if (!pEASData->pMetricsModule) + return EAS_ERROR_INVALID_MODULE; + + return (*pEASData->pMetricsModule->pfReset)(pEASData->pMetricsData); +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_SetSoundLibrary() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_SNDLIB_HANDLE pSndLib) +{ + if (pStream) + { + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_EAS_LIBRARY, (EAS_I32) pSndLib); + } + + return VMSetGlobalEASLib(pEASData->pVoiceMgr, pSndLib); +} + +/*---------------------------------------------------------------------------- + * EAS_SetHeaderSearchFlag() + *---------------------------------------------------------------------------- + * By default, when EAS_OpenFile is called, the parsers check the + * first few bytes of the file looking for a specific header. Some + * mobile devices may add a header to the start of a file, which + * will prevent the parser from recognizing the file. If the + * searchFlag is set to EAS_TRUE, the parser will search the entire + * file looking for the header. This may enable EAS to recognize + * some files that it would ordinarily reject. The negative is that + * it make take slightly longer to process the EAS_OpenFile request. + * + * Inputs: + * pEASData - instance data handle + * searchFlag - search flag (EAS_TRUE or EAS_FALSE) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag) +{ + pEASData->searchHeaderFlag = (EAS_BOOL8) searchFlag; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_SetPlayMode() + *---------------------------------------------------------------------------- + * Some file formats support special play modes, such as iMode partial + * play mode. This call can be used to change the play mode. The + * default play mode (usually straight playback) is always zero. + * + * Inputs: + * pEASData - instance data handle + * handle - file or stream handle + * playMode - play mode (see file parser for specifics) + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode) +{ + return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PLAY_MODE, playMode); +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * EAS_LoadDLSCollection() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the location of the sound library. + * + * Inputs: + * pEASData - instance data handle + * pSoundLib - pointer to sound library + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_FILE_LOCATOR locator) +{ + EAS_FILE_HANDLE fileHandle; + EAS_RESULT result; + EAS_DLSLIB_HANDLE pDLS; + + if (pStream != NULL) + { + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + } + + /* open the file */ + if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) + return result; + + /* parse the file */ + result = DLSParser(pEASData->hwInstData, fileHandle, 0, &pDLS); + EAS_HWCloseFile(pEASData->hwInstData, fileHandle); + + if (result == EAS_SUCCESS) + { + + /* if a stream pStream is specified, point it to the DLS collection */ + if (pStream) + result = EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_DLS_COLLECTION, (EAS_I32) pDLS); + + /* global DLS load */ + else + result = VMSetGlobalDLSLib(pEASData, pDLS); + } + + return result; +} +#endif + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Purpose: + * Registers callback functions for audio events. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * cbProgChgFunc - pointer to host callback function for program change + * cbEventFunc - pointer to host callback functio for note events + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, + EAS_HANDLE pStream, + EAS_VOID_PTR pInstData, + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, + EAS_EXT_EVENT_FUNC cbEventFunc) +{ + S_SYNTH *pSynth; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + VMRegExtAudioCallback(pSynth, pInstData, cbProgChgFunc, cbEventFunc); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_GetMIDIControllers() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of MIDI controllers on the requested channel. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - file or stream handle + * pControl - pointer to structure to receive data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) +{ + S_SYNTH *pSynth; + + if (!EAS_StreamReady(pEASData, pStream)) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) + return EAS_ERROR_INVALID_PARAMETER; + + if (pSynth == NULL) + return EAS_ERROR_INVALID_PARAMETER; + + VMGetMIDIControllers(pSynth, channel, pControl); + return EAS_SUCCESS; +} +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * EAS_SetFrameBuffer() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the frame buffer pointer passed to the IPC communications functions + * + * Inputs: + * pEASData - instance data handle + * locator - file locator + * + * Outputs: + * + * + * Side Effects: + * May overlay instruments in the GM sound set + * + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer) +{ + if (pEASData->pVoiceMgr) + pEASData->pVoiceMgr->pFrameBuffer = pFrameBuffer; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * EAS_SearchFile + *---------------------------------------------------------------------------- + * Search file for specific sequence starting at current file + * position. Returns offset to start of sequence. + * + * Inputs: + * pEASData - pointer to EAS persistent data object + * fileHandle - file handle + * searchString - pointer to search sequence + * len - length of search sequence + * pOffset - pointer to variable to store offset to sequence + * + * Returns EAS_EOF if end-of-file is reached + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_SearchFile (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset) +{ + EAS_RESULT result; + EAS_INT index; + EAS_U8 c; + + *pOffset = -1; + index = 0; + for (;;) + { + result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &c); + if (result != EAS_SUCCESS) + return result; + if (c == searchString[index]) + { + index++; + if (index == 4) + { + result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, pOffset); + if (result != EAS_SUCCESS) + return result; + *pOffset -= len; + break; + } + } + else + index = 0; + } + return EAS_SUCCESS; +} + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverb.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverb.c new file mode 100755 index 0000000..99acb81 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverb.c @@ -0,0 +1,1154 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverb.c + * + * Contents and purpose: + * Contains the implementation of the Reverb effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 510 $ + * $Date: 2006-12-19 01:47:33 -0800 (Tue, 19 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +/*------------------------------------ + * includes + *------------------------------------ +*/ + +#include "eas_data.h" +#include "eas_effects.h" +#include "eas_math.h" +#include "eas_reverbdata.h" +#include "eas_reverb.h" +#include "eas_config.h" +#include "eas_host.h" +#include "eas_report.h" + +/* prototypes for effects interface */ +static EAS_RESULT ReverbInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); +static void ReverbProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); +static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); + +/* common effects interface for configuration module */ +const S_EFFECTS_INTERFACE EAS_Reverb = +{ + ReverbInit, + ReverbProcess, + ReverbShutdown, + ReverbGetParam, + ReverbSetParam +}; + + + +/*---------------------------------------------------------------------------- + * InitializeReverb() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbInit(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) +{ + EAS_I32 i; + EAS_U16 nOffset; + EAS_INT temp; + + S_REVERB_OBJECT *pReverbData; + S_REVERB_PRESET *pPreset; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pReverbData = EAS_CMEnumFXData(EAS_MODULE_REVERB); + + /* allocate dynamic memory */ + else + pReverbData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_REVERB_OBJECT)); + + if (pReverbData == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Reverb memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + + /* clear the structure */ + EAS_HWMemSet(pReverbData, 0, sizeof(S_REVERB_OBJECT)); + + ReverbReadInPresets(pReverbData); + + pReverbData->m_nMinSamplesToAdd = REVERB_UPDATE_PERIOD_IN_SAMPLES; + + pReverbData->m_nRevOutFbkR = 0; + pReverbData->m_nRevOutFbkL = 0; + + pReverbData->m_sAp0.m_zApIn = AP0_IN; + pReverbData->m_sAp0.m_zApOut = AP0_IN + DEFAULT_AP0_LENGTH; + pReverbData->m_sAp0.m_nApGain = DEFAULT_AP0_GAIN; + + pReverbData->m_zD0In = DELAY0_IN; + + pReverbData->m_sAp1.m_zApIn = AP1_IN; + pReverbData->m_sAp1.m_zApOut = AP1_IN + DEFAULT_AP1_LENGTH; + pReverbData->m_sAp1.m_nApGain = DEFAULT_AP1_GAIN; + + pReverbData->m_zD1In = DELAY1_IN; + + pReverbData->m_zLpf0 = 0; + pReverbData->m_zLpf1 = 0; + pReverbData->m_nLpfFwd = 8837; + pReverbData->m_nLpfFbk = 6494; + + pReverbData->m_nSin = 0; + pReverbData->m_nCos = 0; + pReverbData->m_nSinIncrement = 0; + pReverbData->m_nCosIncrement = 0; + + // set xfade parameters + pReverbData->m_nXfadeInterval = (EAS_U16)REVERB_XFADE_PERIOD_IN_SAMPLES; + pReverbData->m_nXfadeCounter = pReverbData->m_nXfadeInterval + 1; // force update on first iteration + pReverbData->m_nPhase = -32768; + pReverbData->m_nPhaseIncrement = REVERB_XFADE_PHASE_INCREMENT; + + pReverbData->m_nNoise = (EAS_I16)0xABCD; + + pReverbData->m_nMaxExcursion = 0x007F; + + // set delay tap lengths + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD1Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD0Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD0Self = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, + &pReverbData->m_nNoise ); + + pReverbData->m_zD1Self = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + // for debugging purposes, allow noise generator + pReverbData->m_bUseNoise = EAS_FALSE; + + // for debugging purposes, allow bypass + pReverbData->m_bBypass = EAS_TRUE; //EAS_FALSE; + + pReverbData->m_nNextRoom = 1; + + pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom + 1; // force update on first iteration + + pReverbData->m_nWet = REVERB_DEFAULT_WET; + + pReverbData->m_nDry = REVERB_DEFAULT_DRY; + + // set base index into circular buffer + pReverbData->m_nBaseIndex = 0; + + // set the early reflections, L + pReverbData->m_sEarlyL.m_nLpfFbk = 4915; + pReverbData->m_sEarlyL.m_nLpfFwd = 27852; + pReverbData->m_sEarlyL.m_zLpf = 0; + + for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) + { + pReverbData->m_sEarlyL.m_nGain[i] = 0; + pReverbData->m_sEarlyL.m_zDelay[i] = 0; + } + + // set the early reflections, R + pReverbData->m_sEarlyR.m_nLpfFbk = 4915; + pReverbData->m_sEarlyR.m_nLpfFwd = 27852; + pReverbData->m_sEarlyR.m_zLpf = 0; + + for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) + { + pReverbData->m_sEarlyR.m_nGain[i] = 0; + pReverbData->m_sEarlyR.m_zDelay[i] = 0; + } + + // clear the reverb delay line + for (i=0; i < REVERB_BUFFER_SIZE_IN_SAMPLES; i++) + { + pReverbData->m_nDelayLine[i] = 0; + } + + //////////////////////////////// + ///code from the EAS DEMO Reverb + //now copy from the new preset into the reverb + pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; + + pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; + pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; + + pReverbData->m_nEarly = pPreset->m_nEarly; + pReverbData->m_nWet = pPreset->m_nWet; + pReverbData->m_nDry = pPreset->m_nDry; + + pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_nXfadeInterval = (EAS_U16) temp; + //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval; + + pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); + //gsReverbObject.m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; + + pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); + //gsReverbObject.m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + ///code from the EAS DEMO Reverb + //////////////////////////////// + + *pInstData = pReverbData; + + return EAS_SUCCESS; + +} /* end InitializeReverb */ + + + +/*---------------------------------------------------------------------------- + * ReverbProcess() + *---------------------------------------------------------------------------- + * Purpose: + * Reverberate the requested number of samples (block based processing) + * + * Inputs: + * pInputBuffer - src buffer + * pOutputBuffer - dst buffer + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +static void ReverbProcess(EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) +{ + S_REVERB_OBJECT *pReverbData; + + pReverbData = (S_REVERB_OBJECT*) pInstData; + + //if bypassed or the preset forces the signal to be completely dry + if (pReverbData->m_bBypass || + (pReverbData->m_nWet == 0 && pReverbData->m_nDry == 32767)) + { + if (pSrc != pDst) + EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); + return; + } + + if (pReverbData->m_nNextRoom != pReverbData->m_nCurrentRoom) + { + ReverbUpdateRoom(pReverbData); + } + + ReverbUpdateXfade(pReverbData, (int)numSamples); + + Reverb(pReverbData, (int)numSamples, pDst, pSrc); + + /* check if update counter needs to be reset */ + if (pReverbData->m_nUpdateCounter >= REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES) + { + /* update interval has elapsed, so reset counter */ + pReverbData->m_nUpdateCounter = 0; + } /* end if m_nUpdateCounter >= update interval */ + + /* increment update counter */ + pReverbData->m_nUpdateCounter += (EAS_I16)numSamples; + +} /* end ComputeReverb */ + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd) +{ + EAS_U16 nOffset; + EAS_I16 tempCos; + EAS_I16 tempSin; + + if (pReverbData->m_nXfadeCounter >= pReverbData->m_nXfadeInterval) + { + /* update interval has elapsed, so reset counter */ + pReverbData->m_nXfadeCounter = 0; + + // Pin the sin,cos values to min / max values to ensure that the + // modulated taps' coefs are zero (thus no clicks) + if (pReverbData->m_nPhaseIncrement > 0) + { + // if phase increment > 0, then sin -> 1, cos -> 0 + pReverbData->m_nSin = 32767; + pReverbData->m_nCos = 0; + + // reset the phase to match the sin, cos values + pReverbData->m_nPhase = 32767; + + // modulate the cross taps because their tap coefs are zero + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD1Cross = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD0Cross = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + } + else + { + // if phase increment < 0, then sin -> 0, cos -> 1 + pReverbData->m_nSin = 0; + pReverbData->m_nCos = 32767; + + // reset the phase to match the sin, cos values + pReverbData->m_nPhase = -32768; + + // modulate the self taps because their tap coefs are zero + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD0Self = + DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; + + nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); + + pReverbData->m_zD1Self = + DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; + + } // end if-else (pReverbData->m_nPhaseIncrement > 0) + + // Reverse the direction of the sin,cos so that the + // tap whose coef was previously increasing now decreases + // and vice versa + pReverbData->m_nPhaseIncrement = -pReverbData->m_nPhaseIncrement; + + } // end if counter >= update interval + + //compute what phase will be next time + pReverbData->m_nPhase += pReverbData->m_nPhaseIncrement; + + //calculate what the new sin and cos need to reach by the next update + ReverbCalculateSinCos(pReverbData->m_nPhase, &tempSin, &tempCos); + + //calculate the per-sample increment required to get there by the next update + /*lint -e{702} shift for performance */ + pReverbData->m_nSinIncrement = + (tempSin - pReverbData->m_nSin) >> REVERB_UPDATE_PERIOD_IN_BITS; + + /*lint -e{702} shift for performance */ + pReverbData->m_nCosIncrement = + (tempCos - pReverbData->m_nCos) >> REVERB_UPDATE_PERIOD_IN_BITS; + + + /* increment update counter */ + pReverbData->m_nXfadeCounter += (EAS_U16) nNumSamplesToAdd; + + return EAS_SUCCESS; + +} /* end ReverbUpdateXfade */ + + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * nMaxExcursion - noise value is limited to this value + * pnNoise - return new noise sample in this (not limited) + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - *pnNoise noise value is updated + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise) +{ + // calculate new noise value + *pnNoise = (EAS_I16) (*pnNoise * 5 + 1); + +#if 0 // 1xxx, test + *pnNoise = 0; +#endif // 1xxx, test + + // return the limited noise value + return (nMaxExcursion & (*pnNoise)); + +} /* end ReverbCalculateNoise */ + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos) +{ + EAS_I32 nTemp; + EAS_I32 nNetAngle; + + // -1 <= nPhase < 1 + // However, for the calculation, we need a value + // that ranges from -1/2 to +1/2, so divide the phase by 2 + /*lint -e{702} shift for performance */ + nNetAngle = nPhase >> 1; + + /* + Implement the following + sin(x) = (2-4*c)*x^2 + c + x + cos(x) = (2-4*c)*x^2 + c - x + + where c = 1/sqrt(2) + using the a0 + x*(a1 + x*a2) approach + */ + + /* limit the input "angle" to be between -0.5 and +0.5 */ + if (nNetAngle > EG1_HALF) + { + nNetAngle = EG1_HALF; + } + else if (nNetAngle < EG1_MINUS_HALF) + { + nNetAngle = EG1_MINUS_HALF; + } + + /* calculate sin */ + nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnSin = (EAS_I16) SATURATE_EG1(nTemp); + + /* calculate cos */ + nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); + nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); + *pnCos = (EAS_I16) SATURATE_EG1(nTemp); + + return EAS_SUCCESS; +} /* end ReverbCalculateSinCos */ + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT Reverb(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer) +{ + EAS_I32 i; + EAS_I32 nDelayOut; + EAS_U16 nBase; + + EAS_U32 nAddr; + EAS_I32 nTemp1; + EAS_I32 nTemp2; + EAS_I32 nApIn; + EAS_I32 nApOut; + + EAS_I32 j; + EAS_I32 nEarlyOut; + + EAS_I32 tempValue; + + + // get the base address + nBase = pReverbData->m_nBaseIndex; + + for (i=0; i < nNumSamplesToAdd; i++) + { + // ********** Left Allpass - start + // left input = (left dry/4) + right feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkR; +// nApIn = *pInputBuffer++; // 1xxx test and debug ap + + // fetch allpass delay line out + //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, REVERB_BUFFER_MASK); + nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApOut, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp0.m_nApGain); + nApOut = SATURATE(nDelayOut - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp0.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApIn, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverbData->m_zD0In, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; + + // ********** Left Allpass - end + + // ********** Right Allpass - start + // right input = (right dry/4) + left feedback from previous period + /*lint -e{702} use shift for performance */ + nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkL; +// nApIn = *pInputBuffer++; // 1xxx test and debug ap + + // fetch allpass delay line out + nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApOut, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate allpass feedforward; subtract the feedforward result + nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp1.m_nApGain); + nApOut = SATURATE(nDelayOut - nTemp1); // allpass output + + // calculate allpass feedback; add the feedback result + nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp1.m_nApGain); + nTemp1 = SATURATE(nApIn + nTemp1); + + // inject into allpass delay + nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApIn, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; + + // inject allpass output into delay line + nAddr = CIRCULAR(nBase, pReverbData->m_zD1In, REVERB_BUFFER_MASK); + pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; + + // ********** Right Allpass - end + + // ********** D0 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverbData->m_zD0Self, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverbData->m_zD1Cross, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); + + // calculate unfiltered delay out + nDelayOut = SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf0, pReverbData->m_nLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_zLpf0 + pReverbData->m_zLpf0 = (EAS_PCM) SATURATE(nTemp1 + nTemp2); + + // ********** D0 output - end + + // ********** D1 output - start + // fetch delay line self out + nAddr = CIRCULAR(nBase, pReverbData->m_zD1Self, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); + + // fetch delay line cross out + nAddr = CIRCULAR(nBase, pReverbData->m_zD0Cross, REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate delay line self out + nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); + + // calculate unfiltered delay out + nDelayOut = SATURATE(nTemp1 + nTemp2); + + // calculate lowpass filter (mixer scale factor included in LPF feedforward) + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf1, pReverbData->m_nLpfFbk); + + // calculate filtered delay out and simultaneously update LPF state variable + // filtered delay output is stored in m_zLpf1 + pReverbData->m_zLpf1 = (EAS_PCM)SATURATE(nTemp1 + nTemp2); + + // ********** D1 output - end + + // ********** mixer and feedback - start + // sum is fedback to right input (R + L) + pReverbData->m_nRevOutFbkL = + (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 + (EAS_I32)pReverbData->m_zLpf0); + + // difference is feedback to left input (R - L) + /*lint -e{685} lint complains that it can't saturate negative */ + pReverbData->m_nRevOutFbkR = + (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 - (EAS_I32)pReverbData->m_zLpf0); + + // ********** mixer and feedback - end + + // ********** start early reflection generator, left + //psEarly = &(pReverbData->m_sEarlyL); + + nEarlyOut = 0; + + for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + { + // fetch delay line out + //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], REVERB_BUFFER_MASK); + nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyL.m_zDelay[j], REVERB_BUFFER_MASK); + + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate reflection + //nTemp1 = MULT_EG1_EG1(nDelayOut, psEarly->m_nGain[j]); + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyL.m_nGain[j]); + + nEarlyOut = SATURATE(nEarlyOut + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nLpfFwd); + nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyL.m_nLpfFwd); + + //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk); + nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyL.m_zLpf, pReverbData->m_sEarlyL.m_nLpfFbk); + + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zLpf1 + //psEarly->m_zLpf = SATURATE(nTemp1 + nTemp2); + pReverbData->m_sEarlyL.m_zLpf = (EAS_PCM) SATURATE(nTemp1 + nTemp2); + + // combine filtered early and late reflections for output + //*pOutputBuffer++ = inL; + //tempValue = SATURATE(psEarly->m_zLpf + pReverbData->m_nRevOutFbkL); + tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyL.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkL); + //scale reverb output by wet level + /*lint -e{701} use shift for performance */ + tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet<<1)); + //sum with output buffer + tempValue += *pOutputBuffer; + *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); + + // ********** end early reflection generator, left + + // ********** start early reflection generator, right + //psEarly = &(pReverbData->m_sEarlyR); + + nEarlyOut = 0; + + for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + { + // fetch delay line out + nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyR.m_zDelay[j], REVERB_BUFFER_MASK); + nDelayOut = pReverbData->m_nDelayLine[nAddr]; + + // calculate reflection + nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyR.m_nGain[j]); + + nEarlyOut = SATURATE(nEarlyOut + nTemp1); + + } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) + + // apply lowpass to early reflections + nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyR.m_nLpfFwd); + + nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyR.m_zLpf, pReverbData->m_sEarlyR.m_nLpfFbk); + + // calculate filtered out and simultaneously update LPF state variable + // filtered output is stored in m_zLpf1 + pReverbData->m_sEarlyR.m_zLpf = (EAS_PCM)SATURATE(nTemp1 + nTemp2); + + // combine filtered early and late reflections for output + //*pOutputBuffer++ = inR; + tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyR.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkR); + //scale reverb output by wet level + /*lint -e{701} use shift for performance */ + tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet << 1)); + //sum with output buffer + tempValue = tempValue + *pOutputBuffer; + *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); + + // ********** end early reflection generator, right + + // decrement base addr for next sample period + nBase--; + + pReverbData->m_nSin += pReverbData->m_nSinIncrement; + pReverbData->m_nCos += pReverbData->m_nCosIncrement; + + } // end for (i=0; i < nNumSamplesToAdd; i++) + + // store the most up to date version + pReverbData->m_nBaseIndex = nBase; + + return EAS_SUCCESS; +} /* end Reverb */ + + + +/*---------------------------------------------------------------------------- + * ReverbShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Initializes the Reverb effect. + * + * Inputs: + * pInstData - handle to instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) +{ + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pInstData); + return EAS_SUCCESS; +} /* end ReverbShutdown */ + +/*---------------------------------------------------------------------------- + * ReverbGetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Get a Reverb parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - pointer to variable to hold retrieved value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_REVERB_OBJECT *p; + + p = (S_REVERB_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_REVERB_BYPASS: + *pValue = (EAS_I32) p->m_bBypass; + break; + case EAS_PARAM_REVERB_PRESET: + *pValue = (EAS_I8) p->m_nCurrentRoom; + break; + case EAS_PARAM_REVERB_WET: + *pValue = p->m_nWet; + break; + case EAS_PARAM_REVERB_DRY: + *pValue = p->m_nDry; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ReverbGetParam */ + + +/*---------------------------------------------------------------------------- + * ReverbSetParam() + *---------------------------------------------------------------------------- + * Purpose: + * Set a Reverb parameter + * + * Inputs: + * pInstData - handle to instance data + * param - parameter index + * *pValue - new paramter value + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_REVERB_OBJECT *p; + + p = (S_REVERB_OBJECT*) pInstData; + + switch (param) + { + case EAS_PARAM_REVERB_BYPASS: + p->m_bBypass = (EAS_BOOL) value; + break; + case EAS_PARAM_REVERB_PRESET: + if(value!=EAS_PARAM_REVERB_LARGE_HALL && value!=EAS_PARAM_REVERB_HALL && + value!=EAS_PARAM_REVERB_CHAMBER && value!=EAS_PARAM_REVERB_ROOM) + return EAS_ERROR_INVALID_PARAMETER; + p->m_nNextRoom = (EAS_I16)value; + break; + case EAS_PARAM_REVERB_WET: + if(value>EAS_REVERB_WET_MAX || valuem_nWet = (EAS_I16)value; + break; + case EAS_PARAM_REVERB_DRY: + if(value>EAS_REVERB_DRY_MAX || valuem_nDry = (EAS_I16)value; + break; + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} /* end ReverbSetParam */ + + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT *pReverbData) +{ + EAS_INT temp; + + S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; + + pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; + pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; + + pReverbData->m_nEarly = pPreset->m_nEarly; + pReverbData->m_nWet = pPreset->m_nWet; + pReverbData->m_nDry = pPreset->m_nDry; + + + pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; + //stored as time based, convert to sample based + temp = pPreset->m_nXfadeInterval; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_nXfadeInterval = (EAS_U16) temp; + //gpsReverbObject->m_nXfadeInterval = pPreset->m_nXfadeInterval; + pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp0_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); + //gpsReverbObject->m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; + pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; + //stored as time based, convert to absolute sample value + temp = pPreset->m_nAp1_ApOut; + /*lint -e{702} shift for performance */ + temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; + pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); + //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; + + pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom; + + return EAS_SUCCESS; + +} /* end ReverbUpdateRoom */ + + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT *pReverbData) +{ + + int preset = 0; + int defaultPreset = 0; + + //now init any remaining presets to defaults + for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++) + { + S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[defaultPreset]; + if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE-1) + { + pPreset->m_nLpfFbk = 8307; + pPreset->m_nLpfFwd = 14768; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 27690; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6388; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 711; + pPreset->m_nAp1_ApGain = 17999; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 1) + { + pPreset->m_nLpfFbk = 6461; + pPreset->m_nLpfFwd = 14307; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 27690; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6391; + pPreset->m_nAp0_ApGain = 15230; + pPreset->m_nAp0_ApOut = 708; + pPreset->m_nAp1_ApGain = 9692; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 2) + { + pPreset->m_nLpfFbk = 5077; + pPreset->m_nLpfFwd = 12922; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 24460; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6449; + pPreset->m_nAp0_ApGain = 15691; + pPreset->m_nAp0_ApOut = 774; + pPreset->m_nAp1_ApGain = 15691; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + } + else if (defaultPreset == 3) + { + pPreset->m_nLpfFbk = 5077; + pPreset->m_nLpfFwd = 11076; + pPreset->m_nEarly = 0; + pPreset->m_nWet = 23075; + pPreset->m_nDry = 32767; + pPreset->m_nEarlyL_LpfFbk = 3692; + pPreset->m_nEarlyL_LpfFwd = 29075; + pPreset->m_nEarlyL_Delay0 = 922; + pPreset->m_nEarlyL_Gain0 = 22152; + pPreset->m_nEarlyL_Delay1 = 1462; + pPreset->m_nEarlyL_Gain1 = 17537; + pPreset->m_nEarlyL_Delay2 = 0; + pPreset->m_nEarlyL_Gain2 = 14768; + pPreset->m_nEarlyL_Delay3 = 1221; + pPreset->m_nEarlyL_Gain3 = 14307; + pPreset->m_nEarlyL_Delay4 = 0; + pPreset->m_nEarlyL_Gain4 = 13384; + pPreset->m_nEarlyR_Delay0 = 502; + pPreset->m_nEarlyR_Gain0 = 20306; + pPreset->m_nEarlyR_Delay1 = 1762; + pPreset->m_nEarlyR_Gain1 = 17537; + pPreset->m_nEarlyR_Delay2 = 0; + pPreset->m_nEarlyR_Gain2 = 14768; + pPreset->m_nEarlyR_Delay3 = 0; + pPreset->m_nEarlyR_Gain3 = 16153; + pPreset->m_nEarlyR_Delay4 = 0; + pPreset->m_nEarlyR_Gain4 = 13384; + pPreset->m_nMaxExcursion = 127; + pPreset->m_nXfadeInterval = 6470; //6483; + pPreset->m_nAp0_ApGain = 14768; + pPreset->m_nAp0_ApOut = 792; + pPreset->m_nAp1_ApGain = 15783; + pPreset->m_nAp1_ApOut = 1113; + pPreset->m_rfu4 = 0; + pPreset->m_rfu5 = 0; + pPreset->m_rfu6 = 0; + pPreset->m_rfu7 = 0; + pPreset->m_rfu8 = 0; + pPreset->m_rfu9 = 0; + pPreset->m_rfu10 = 0; + + } + } + + return EAS_SUCCESS; +} diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverbdata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverbdata.c new file mode 100755 index 0000000..db34b48 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverbdata.c @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverbdata.c + * + * Contents and purpose: + * Contains the static data allocation for the Reverb effect + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_reverbdata.h" + +S_REVERB_OBJECT eas_ReverbData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverbdata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverbdata.h new file mode 100755 index 0000000..6171a01 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverbdata.h @@ -0,0 +1,486 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_reverbdata.h + * + * Contents and purpose: + * Contains the prototypes for the Reverb effect. + * + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 499 $ + * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_REVERBDATA_H +#define _EAS_REVERBDATA_H + +#include "eas_types.h" +#include "eas_audioconst.h" + +/*------------------------------------ + * defines + *------------------------------------ +*/ + +/* +CIRCULAR() calculates the array index using modulo arithmetic. +The "trick" is that modulo arithmetic is simplified by masking +the effective address where the mask is (2^n)-1. This only works +if the buffer size is a power of two. +*/ +#define CIRCULAR(base,offset,size) (EAS_U32)( \ + ( \ + ((EAS_I32)(base)) + ((EAS_I32)(offset)) \ + ) \ + & size \ + ) + +/* reverb parameters are updated every 2^(REVERB_UPDATE_PERIOD_IN_BITS) samples */ +#if defined (_SAMPLE_RATE_8000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 5 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 2048 + +#elif defined (_SAMPLE_RATE_16000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 6 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 + +#elif defined (_SAMPLE_RATE_22050) + +#define REVERB_UPDATE_PERIOD_IN_BITS 7 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 + +#elif defined (_SAMPLE_RATE_32000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 7 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#elif defined (_SAMPLE_RATE_44100) + +#define REVERB_UPDATE_PERIOD_IN_BITS 8 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#elif defined (_SAMPLE_RATE_48000) + +#define REVERB_UPDATE_PERIOD_IN_BITS 8 +#define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 + +#endif + +// Define a mask for circular addressing, so that array index +// can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1) +// The buffer size MUST be a power of two +#define REVERB_BUFFER_MASK (REVERB_BUFFER_SIZE_IN_SAMPLES -1) + +#define REVERB_MAX_ROOM_TYPE 4 // any room numbers larger than this are invalid +#define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ +#define REVERB_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << REVERB_UPDATE_PERIOD_IN_BITS) + +/* +calculate the update counter by bitwise ANDING with this value to +generate a 2^n modulo value +*/ +#define REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(REVERB_UPDATE_PERIOD_IN_SAMPLES -1) + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SECONDS seconds */ +#define REVERB_UPDATE_PERIOD_IN_SECONDS (REVERB_UPDATE_PERIOD_IN_SAMPLES / _OUTPUT_SAMPLE_RATE) + +// xfade parameters +#define REVERB_XFADE_PERIOD_IN_SECONDS (100.0 / 1000.0) // xfade once every this many seconds + +#define REVERB_XFADE_PERIOD_IN_SAMPLES (REVERB_XFADE_PERIOD_IN_SECONDS * _OUTPUT_SAMPLE_RATE) + +#define REVERB_XFADE_PHASE_INCREMENT (EAS_I16)(65536 / ((EAS_I16)REVERB_XFADE_PERIOD_IN_SAMPLES/(EAS_I16)REVERB_UPDATE_PERIOD_IN_SAMPLES)) + +/**********/ +/* the entire synth uses various flags in a bit field */ + +/* if flag is set, synth reset has been requested */ +#define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */ +#define MASK_REVERB_RESET_IS_REQUESTED 0x01 +#define MASK_REVERB_RESET_IS_NOT_REQUESTED (EAS_U32)(~MASK_REVERB_RESET_IS_REQUESTED) + +/* +by default, we always want to update ALL channel parameters +when we reset the synth (e.g., during GM ON) +*/ +#define DEFAULT_REVERB_FLAGS 0x0 + +/* coefficients for generating sin, cos */ +#define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */ +/* +EAS_I32 nPanG1 = +1.0 for sin +EAS_I32 nPanG1 = -1.0 for cos +*/ +#define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ + +/*************************************************************/ +// define the input injection points +#define GUARD 5 // safety guard of this many samples + +#define MAX_AP_TIME (double) (20.0/1000.0) // delay time in milliseconds +#define MAX_DELAY_TIME (double) (65.0/1000.0) // delay time in milliseconds + +#define MAX_AP_SAMPLES (int)(((double) MAX_AP_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) +#define MAX_DELAY_SAMPLES (int)(((double) MAX_DELAY_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) + +#define AP0_IN 0 +#define AP1_IN (AP0_IN + MAX_AP_SAMPLES + GUARD) +#define DELAY0_IN (AP1_IN + MAX_AP_SAMPLES + GUARD) +#define DELAY1_IN (DELAY0_IN + MAX_DELAY_SAMPLES + GUARD) + +// Define the max offsets for the end points of each section +// i.e., we don't expect a given section's taps to go beyond +// the following limits +#define AP0_OUT (AP0_IN + MAX_AP_SAMPLES -1) +#define AP1_OUT (AP1_IN + MAX_AP_SAMPLES -1) +#define DELAY0_OUT (DELAY0_IN + MAX_DELAY_SAMPLES -1) +#define DELAY1_OUT (DELAY1_IN + MAX_DELAY_SAMPLES -1) + +#define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number +#define DEFAULT_AP0_LENGTH (int)(((double) (17.0/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) +#define DEFAULT_AP0_GAIN 19400 +#define DEFAULT_AP1_LENGTH (int)(((double) (16.5/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) +#define DEFAULT_AP1_GAIN -19400 + +#define REVERB_DEFAULT_WET 32767 +#define REVERB_DEFAULT_DRY 0 + +#define EAS_REVERB_WET_MAX 32767 +#define EAS_REVERB_WET_MIN 0 +#define EAS_REVERB_DRY_MAX 32767 +#define EAS_REVERB_DRY_MIN 0 + +/* parameters for each allpass */ +typedef struct +{ + EAS_U16 m_zApOut; // delay offset for ap out + + EAS_I16 m_nApGain; // gain for ap + + EAS_U16 m_zApIn; // delay offset for ap in + +} S_ALLPASS_OBJECT; + + +/* parameters for each allpass */ +typedef struct +{ + EAS_PCM m_zLpf; // actual state variable, not a length + + EAS_I16 m_nLpfFwd; // lpf forward gain + + EAS_I16 m_nLpfFbk; // lpf feedback gain + + EAS_U16 m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out + + EAS_I16 m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap + +} S_EARLY_REFLECTION_OBJECT; + +//demo +typedef struct +{ + EAS_I16 m_nLpfFbk; + EAS_I16 m_nLpfFwd; + + EAS_I16 m_nEarly; + EAS_I16 m_nWet; + EAS_I16 m_nDry; + + EAS_I16 m_nEarlyL_LpfFbk; + EAS_I16 m_nEarlyL_LpfFwd; + + EAS_I16 m_nEarlyL_Delay0; //8 + EAS_I16 m_nEarlyL_Gain0; + EAS_I16 m_nEarlyL_Delay1; + EAS_I16 m_nEarlyL_Gain1; + EAS_I16 m_nEarlyL_Delay2; + EAS_I16 m_nEarlyL_Gain2; + EAS_I16 m_nEarlyL_Delay3; + EAS_I16 m_nEarlyL_Gain3; + EAS_I16 m_nEarlyL_Delay4; + EAS_I16 m_nEarlyL_Gain4; + + EAS_I16 m_nEarlyR_Delay0; //18 + EAS_I16 m_nEarlyR_Gain0; + EAS_I16 m_nEarlyR_Delay1; + EAS_I16 m_nEarlyR_Gain1; + EAS_I16 m_nEarlyR_Delay2; + EAS_I16 m_nEarlyR_Gain2; + EAS_I16 m_nEarlyR_Delay3; + EAS_I16 m_nEarlyR_Gain3; + EAS_I16 m_nEarlyR_Delay4; + EAS_I16 m_nEarlyR_Gain4; + + EAS_U16 m_nMaxExcursion; //28 + EAS_I16 m_nXfadeInterval; + + EAS_I16 m_nAp0_ApGain; //30 + EAS_I16 m_nAp0_ApOut; + EAS_I16 m_nAp1_ApGain; + EAS_I16 m_nAp1_ApOut; + + EAS_I16 m_rfu4; + EAS_I16 m_rfu5; + EAS_I16 m_rfu6; + EAS_I16 m_rfu7; + EAS_I16 m_rfu8; + EAS_I16 m_rfu9; + EAS_I16 m_rfu10; //43 + +} S_REVERB_PRESET; + +typedef struct +{ + S_REVERB_PRESET m_sPreset[REVERB_MAX_ROOM_TYPE]; //array of presets + +} S_REVERB_PRESET_BANK; + +/* parameters for each reverb */ +typedef struct +{ + /* controls entire reverb playback volume */ + /* to conserve memory, use the MSB and ignore the LSB */ + EAS_U8 m_nMasterVolume; + + /* update counter keeps track of when synth params need updating */ + /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */ + EAS_I16 m_nUpdateCounter; + + EAS_U16 m_nMinSamplesToAdd; /* ComputeReverb() generates this many samples */ + + EAS_U8 m_nFlags; /* misc flags/bit fields */ + + EAS_PCM *m_pOutputBuffer; + EAS_PCM *m_pInputBuffer; + + EAS_U16 m_nNumSamplesInOutputBuffer; + EAS_U16 m_nNumSamplesInInputBuffer; + + EAS_U16 m_nNumInputSamplesRead; // if m_nNumInputSamplesRead >= NumSamplesInInputBuffer + // then get a new input buffer + EAS_PCM *m_pNextInputSample; + + EAS_U16 m_nBaseIndex; // base index for circular buffer + + // reverb delay line offsets, allpass parameters, etc: + + EAS_PCM m_nRevOutFbkR; // combine feedback reverb right out with dry left in + + S_ALLPASS_OBJECT m_sAp0; // allpass 0 (left channel) + + EAS_U16 m_zD0In; // delay offset for delay line D0 in + + EAS_PCM m_nRevOutFbkL; // combine feedback reverb left out with dry right in + + S_ALLPASS_OBJECT m_sAp1; // allpass 1 (right channel) + + EAS_U16 m_zD1In; // delay offset for delay line D1 in + + // delay output taps, notice criss cross order + EAS_U16 m_zD0Self; // self feeds forward d0 --> d0 + + EAS_U16 m_zD1Cross; // cross feeds across d1 --> d0 + + EAS_PCM m_zLpf0; // actual state variable, not a length + + EAS_U16 m_zD1Self; // self feeds forward d1 --> d1 + + EAS_U16 m_zD0Cross; // cross feeds across d0 --> d1 + + EAS_PCM m_zLpf1; // actual state variable, not a length + + EAS_I16 m_nSin; // gain for self taps + + EAS_I16 m_nCos; // gain for cross taps + + EAS_I16 m_nSinIncrement; // increment for gain + + EAS_I16 m_nCosIncrement; // increment for gain + + EAS_I16 m_nLpfFwd; // lpf forward gain (includes scaling for mixer) + + EAS_I16 m_nLpfFbk; // lpf feedback gain + + EAS_U16 m_nXfadeInterval; // update/xfade after this many samples + + EAS_U16 m_nXfadeCounter; // keep track of when to xfade + + EAS_I16 m_nPhase; // -1 <= m_nPhase < 1 + // but during sin,cos calculations + // use m_nPhase/2 + + EAS_I16 m_nPhaseIncrement; // add this to m_nPhase each frame + + EAS_I16 m_nNoise; // random noise sample + + EAS_U16 m_nMaxExcursion; // the taps can excurse +/- this amount + + EAS_BOOL m_bUseNoise; // if EAS_TRUE, use noise as input signal + + EAS_BOOL m_bBypass; // if EAS_TRUE, then bypass reverb and copy input to output + + EAS_I16 m_nCurrentRoom; // preset number for current room + + EAS_I16 m_nNextRoom; // preset number for next room + + EAS_I16 m_nWet; // gain for wet (processed) signal + + EAS_I16 m_nDry; // gain for dry (unprocessed) signal + + EAS_I16 m_nEarly; // gain for early (widen) signal + + S_EARLY_REFLECTION_OBJECT m_sEarlyL; // left channel early reflections + S_EARLY_REFLECTION_OBJECT m_sEarlyR; // right channel early reflections + + EAS_PCM m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES]; // one large delay line for all reverb elements + + S_REVERB_PRESET pPreset; + + S_REVERB_PRESET_BANK m_sPreset; + + //EAS_I8 preset; + +} S_REVERB_OBJECT; + + +/*------------------------------------ + * prototypes + *------------------------------------ +*/ + +/*---------------------------------------------------------------------------- + * ReverbUpdateXfade + *---------------------------------------------------------------------------- + * Purpose: + * Update the xfade parameters as required + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * + * Outputs: + * + * + * Side Effects: + * - xfade parameters will be changed + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd); + +/*---------------------------------------------------------------------------- + * ReverbCalculateNoise + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a noise sample and limit its value + * + * Inputs: + * nMaxExcursion - noise value is limited to this value + * pnNoise - return new noise sample in this (not limited) + * + * Outputs: + * new limited noise value + * + * Side Effects: + * - *pnNoise noise value is updated + * + *---------------------------------------------------------------------------- +*/ +EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise); + +/*---------------------------------------------------------------------------- + * ReverbCalculateSinCos + *---------------------------------------------------------------------------- + * Purpose: + * Calculate a new sin and cosine value based on the given phase + * + * Inputs: + * nPhase - phase angle + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * + * Side Effects: + * - *pnSin, *pnCos are updated + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos); + +/*---------------------------------------------------------------------------- + * Reverb + *---------------------------------------------------------------------------- + * Purpose: + * apply reverb to the given signal + * + * Inputs: + * nNu + * pnSin - input old value, output new value + * pnCos - input old value, output new value + * + * Outputs: + * number of samples actually reverberated + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT Reverb(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer); + +/*---------------------------------------------------------------------------- + * ReverbReadInPresets() + *---------------------------------------------------------------------------- + * Purpose: sets global reverb preset bank to defaults + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT* pReverbData); + + +/*---------------------------------------------------------------------------- + * ReverbUpdateRoom + *---------------------------------------------------------------------------- + * Purpose: + * Update the room's preset parameters as required + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * - reverb paramters (fbk, fwd, etc) will be changed + * - m_nCurrentRoom := m_nNextRoom + *---------------------------------------------------------------------------- +*/ +EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT* pReverbData); + +#endif /* #ifndef _EAS_REVERBDATA_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttl.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttl.c new file mode 100755 index 0000000..d8253fb --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttl.c @@ -0,0 +1,1197 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttl.c + * + * Contents and purpose: + * RTTTL parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_rtttldata.h" +#include "eas_ctype.h" + +/* increase gain for mono ringtones */ +#define RTTTL_GAIN_OFFSET 8 + +/* maximum title length including colon separator */ +#define RTTTL_MAX_TITLE_LEN 32 +#define RTTTL_INFINITE_LOOP 15 + +/* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */ +#define DEFAULT_TICK_CONV 30476 +#define TICK_CONVERT 1920000 + +/* default channel and program for RTTTL playback */ +#define RTTTL_CHANNEL 0 +#define RTTTL_PROGRAM 80 +#define RTTTL_VELOCITY 127 + +/* note used for rest */ +#define RTTTL_REST 1 + +/* multiplier for fixed point triplet conversion */ +#define TRIPLET_MULTIPLIER 683 +#define TRIPLET_SHIFT 10 + +/* local prototypes */ +static EAS_RESULT RTTTL_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT RTTTL_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT RTTTL_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT RTTTL_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT RTTTL_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT RTTTL_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT RTTTL_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT RTTTL_GetStyle (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData); +static EAS_RESULT RTTTL_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pDuration); +static EAS_RESULT RTTTL_GetOctave (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_U8 *pOctave); +static EAS_RESULT RTTTL_GetTempo (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData); +static EAS_RESULT RTTTL_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I32 *pValue); +static EAS_RESULT RTTTL_ParseHeader (S_EAS_DATA *pEASData, S_RTTTL_DATA* pData, EAS_BOOL metaData); +static EAS_RESULT RTTTL_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue); +static EAS_RESULT RTTTL_PeekNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue); + +/* inline functions */ +EAS_INLINE void RTTTL_PutBackChar (S_RTTTL_DATA *pData, EAS_I8 value) { pData->dataByte = value; } + + +/* lookup table for note values */ +static const EAS_U8 noteTable[] = { 21, 23, 12, 14, 16, 17, 19, 23 }; + +/*---------------------------------------------------------------------------- + * + * EAS_RTTTL_Parser + * + * This structure contains the functional interface for the iMelody parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_RTTTL_Parser = +{ + RTTTL_CheckFileType, + RTTTL_Prepare, + RTTTL_Time, + RTTTL_Event, + RTTTL_State, + RTTTL_Close, + RTTTL_Reset, + RTTTL_Pause, + RTTTL_Resume, + NULL, + RTTTL_SetData, + RTTTL_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * RTTTL_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_RTTTL_DATA data; + S_RTTTL_DATA *pData; + + /* see if we can parse the header */ + data.fileHandle = fileHandle; + data.fileOffset = offset; + *ppHandle= NULL; + if (RTTTL_ParseHeader (pEASData, &data, EAS_FALSE) == EAS_SUCCESS) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumData(EAS_CM_RTTTL_DATA); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_RTTTL_DATA)); + if (!pData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pData, 0, sizeof(S_RTTTL_DATA)); + + /* return a pointer to the instance data */ + pData->fileHandle = fileHandle; + pData->fileOffset = offset; + pData->state = EAS_STATE_OPEN; + *ppHandle = pData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + /* check for valid state */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + pData->state = EAS_STATE_ERROR; + if ((result = RTTTL_ParseHeader (pEASData, pData, (EAS_BOOL) (pData->metadata.callback != NULL))) != EAS_SUCCESS) + { + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + return result; + } + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + EAS_I32 ticks; + EAS_I32 temp; + EAS_I8 c; + EAS_U8 note; + EAS_U8 octave; + + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + /* set program to square lead */ + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, RTTTL_PROGRAM); + + /* set channel volume to max */ + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note) + { + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, pData->note, 0); + pData->note = 0; + + /* check for rest between notes */ + if (pData->restTicks) + { + pData->time += pData->restTicks; + pData->restTicks = 0; + return EAS_SUCCESS; + } + } + + /* parse the next event */ + octave = pData->octave; + note = 0; + ticks = pData->duration * pData->tick; + for (;;) + { + + /* get next character */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + { + if (result != EAS_EOF) + return result; + + /* end of file, if no notes to process, check for looping */ + if (!note) + { + /* if no loop set state to stopping */ + if (pData->repeatCount == 0) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* decrement loop count */ + if (pData->repeatCount != RTTTL_INFINITE_LOOP) + pData->repeatCount--; + + /* if locating, ignore infinite loops */ + else if (parserMode != eParserModePlay) + { + pData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); + return EAS_SUCCESS; + } + + /* loop back to start of notes */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS) + return result; + continue; + } + + /* still have a note to process */ + else + c = ','; + } + + /* bpm */ + if (c == 'b') + { + /* peek at next character */ + if ((result = RTTTL_PeekNextChar(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + return result; + + /* if a number, must be octave or tempo */ + if (IsDigit(c)) + { + if ((result = RTTTL_GetNumber(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + + /* check for octave first */ + if ((temp >= 4) && (temp <= 7)) + { + octave = (EAS_U8) temp; + } + + /* check for tempo */ + else if ((temp >= 25) && (temp <= 900)) + { + pData->tick = TICK_CONVERT / (EAS_U32) temp; + } + + /* don't know what it was */ + else + return EAS_ERROR_FILE_FORMAT; + } + + /* must be a note */ + else + { + note = noteTable[1]; + } + } + + /* octave */ + else if (c == 'o') + { + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &pData->octave)) != EAS_SUCCESS) + return result; + } + + /* style */ + else if (c == 's') + { + if ((result = RTTTL_GetStyle(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + } + + /* duration or octave */ + else if (IsDigit(c)) + { + RTTTL_PutBackChar(pData, c); + + /* duration comes before note */ + if (!note) + { + if ((result = RTTTL_GetDuration(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) + return result; + ticks = c * pData->tick; + } + + /* octave comes after note */ + else + { + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &octave)) != EAS_SUCCESS) + return result; + } + } + + /* note or rest */ + else if ((c >= 'a') && (c <= 'h')) + { + note = noteTable[c - 'a']; + } + + else if (c == 'p') + { + note = RTTTL_REST; + } + + /* dotted note */ + else if (c == '.') + { + /*lint -e{704} shift for performance */ + ticks += ticks >> 1; + } + + /* accidental */ + else if (c == '#') + { + if (note) + note++; + } + + /* end of event */ + else if ((c == ',') && note) + { + + /* handle note events */ + if (note != RTTTL_REST) + { + + /* save note and start it */ + pData->note = note + octave; + if (parserMode == eParserModePlay) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, pData->note, RTTTL_VELOCITY); + + /* determine note length */ + switch (pData->style) + { + /* natural */ + case 'n': + /*lint -e{704} shift for performance */ + pData->restTicks = ticks >> 4; + break; + /* continuous */ + + case 'c': + pData->restTicks = 0; + break; + + /* staccato */ + case 's': + /*lint -e{704} shift for performance */ + pData->restTicks = ticks >> 1; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "RTTTL_Event: Unexpected style type %c\n", pData->style); */ } + break; + } + + /* next event is at end of this note */ + pData->time += ticks - pData->restTicks; + } + + /* rest */ + else + pData->time += ticks; + + /* event found, return to caller */ + break; + } + } + + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_RTTTL_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_RTTTL_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_STOPPED; + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + pData = (S_RTTTL_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA* pData; + EAS_RESULT result; + + pData = (S_RTTTL_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + + /* reset time to zero */ + pData->time = 0; + pData->note = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + if ((result = RTTTL_ParseHeader (pEASData, pData, EAS_TRUE)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA *pData; + + /* can't pause a stopped stream */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_RTTTL_DATA *pData; + + /* can't resume a stopped stream */ + pData = (S_RTTTL_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA *) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT RTTTL_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_RTTTL_DATA *pData; + + pData = (S_RTTTL_DATA *) pInstData; + switch (param) + { + /* return file type as RTTTL */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_RTTTL; + break; + +#if 0 + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + case PARSER_DATA_GAIN_OFFSET: + *pValue = RTTTL_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetStyle() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetStyle (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData) +{ + EAS_RESULT result; + EAS_I8 style; + + /* get style */ + if ((result = RTTTL_GetNextChar(hwInstData, pData, &style)) != EAS_SUCCESS) + return result; + + if ((style != 's') && (style != 'n') && (style != 'c')) + return EAS_ERROR_FILE_FORMAT; + + pData->style = style; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetDuration() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pDuration) +{ + EAS_RESULT result; + EAS_I32 duration; + EAS_I8 temp; + + /* get the duration */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &duration)) != EAS_SUCCESS) + return result; + + if ((duration != 1) && (duration != 2) && (duration != 4) && (duration != 8) && (duration != 16) && (duration != 32)) + return EAS_ERROR_FILE_FORMAT; + + temp = 64; + while (duration) + { + /*lint -e{704} shift for performance */ + duration = duration >> 1; + /*lint -e{702} use shift for performance */ + temp = temp >> 1; + } + + *pDuration = temp; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetOctave() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetOctave (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_U8 *pOctave) +{ + EAS_RESULT result; + EAS_I32 octave; + + /* get the tempo */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &octave)) != EAS_SUCCESS) + return result; + + if ((octave < 4) || (octave > 7)) + return EAS_ERROR_FILE_FORMAT; + + *pOctave = (EAS_U8) (octave * 12); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetTempo() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetTempo (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData) +{ + EAS_RESULT result; + EAS_I32 tempo; + + /* get the tempo */ + if ((result = RTTTL_GetNumber(hwInstData, pData, &tempo)) != EAS_SUCCESS) + return result; + + if ((tempo < 25) || (tempo > 900)) + return EAS_ERROR_FILE_FORMAT; + + pData->tick = TICK_CONVERT / (EAS_U32) tempo; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetNumber() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I32 *pValue) +{ + EAS_RESULT result; + EAS_INT temp; + EAS_I8 c; + + *pValue = -1; + temp = 0; + for (;;) + { + if ((result = RTTTL_PeekNextChar(hwInstData, pData, &c)) != EAS_SUCCESS) + { + if ((result == EAS_EOF) && (*pValue != -1)) + return EAS_SUCCESS; + return result; + } + + if (IsDigit(c)) + { + pData->dataByte = 0; + temp = temp * 10 + c - '0'; + *pValue = temp; + } + else + return EAS_SUCCESS; + } +} + +/*---------------------------------------------------------------------------- + * RTTTL_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_ParseHeader (S_EAS_DATA *pEASData, S_RTTTL_DATA* pData, EAS_BOOL metaData) +{ + EAS_RESULT result; + EAS_I32 i; + EAS_I8 temp; + EAS_I8 control; + + /* initialize some defaults */ + pData->time = 0; + pData->tick = DEFAULT_TICK_CONV; + pData->note = 0; + pData->duration = 4; + pData ->restTicks = 0; + pData->octave = 60; + pData->repeatOffset = -1; + pData->repeatCount = 0; + pData->style = 'n'; + pData->dataByte = 0; + + metaData = metaData && (pData->metadata.buffer != NULL) && (pData->metadata.callback != NULL); + + /* seek to start of data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + + /* zero the metadata buffer */ + if (metaData) + EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize); + + /* read the title */ + for (i = 0; i < RTTTL_MAX_TITLE_LEN; i++) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + + if (temp == ':') + break; + + /* pass along metadata */ + if (metaData) + { + if (i < (pData->metadata.bufferSize- 1)) + pData->metadata.buffer[i] = (char) temp; + } + } + + /* check for error in title */ + if (i == RTTTL_MAX_TITLE_LEN) + return EAS_ERROR_FILE_FORMAT; + + /* pass along metadata */ + if (metaData) + (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData); + + /* control fields */ + for (;;) + { + + /* get control type */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &control)) != EAS_SUCCESS) + return result; + + /* next char should be equal sign */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + if (temp != '=') + return EAS_ERROR_FILE_FORMAT; + + /* get the control value */ + switch (control) + { + + /* bpm */ + case 'b': + if ((result = RTTTL_GetTempo(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + break; + + /* duration */ + case 'd': + if ((result = RTTTL_GetDuration(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + pData->duration = temp; + break; + + /* loop */ + case 'l': + if ((result = RTTTL_GetNumber(pEASData->hwInstData, pData, &i)) != EAS_SUCCESS) + return result; + if ((i < 0) || (i > 15)) + return EAS_ERROR_FILE_FORMAT; + pData->repeatCount = (EAS_U8) i; + break; + + /* octave */ + case 'o': + if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &pData->octave)) != EAS_SUCCESS) + return result; + break; + + /* get style */ + case 's': + if ((result = RTTTL_GetStyle(pEASData->hwInstData, pData)) != EAS_SUCCESS) + return result; + break; + + /* unrecognized control */ + default: + return EAS_ERROR_FILE_FORMAT; + } + + /* next character should be comma or colon */ + if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + + /* check for end of control field */ + if (temp == ':') + break; + + /* must be a comma */ + if (temp != ',') + return EAS_ERROR_FILE_FORMAT; + } + + /* should be at the start of the music block */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pData->fileHandle, &pData->repeatOffset)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * RTTTL_GetNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue) +{ + EAS_RESULT result; + EAS_I8 temp; + + *pValue = 0; + for(;;) + { + + /* check for character that has been put back */ + if (pData->dataByte) + { + temp = pData->dataByte; + pData->dataByte = 0; + } + else + { + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) + return result; + } + + /* ignore white space */ + if (!IsSpace(temp)) + { + *pValue = ToLower(temp); + return EAS_SUCCESS; + } + } +} + +/*---------------------------------------------------------------------------- + * RTTTL_PeekNextChar() + *---------------------------------------------------------------------------- + * Purpose: + * + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT RTTTL_PeekNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue) +{ + EAS_RESULT result; + EAS_I8 temp; + + *pValue = 0; + for(;;) + { + + /* read a character from the file, if necessary */ + if (!pData->dataByte) + { + if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->dataByte)) != EAS_SUCCESS) + return result; + + } + temp = pData->dataByte; + + /* ignore white space */ + if (!IsSpace(temp)) + { + *pValue = ToLower(temp); + return EAS_SUCCESS; + } + pData->dataByte = 0; + } +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttldata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttldata.c new file mode 100755 index 0000000..708a1d9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttldata.c @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttldata.c + * + * Contents and purpose: + * RTTTL File Parser data module for static memory models + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_rtttldata.h" + +/*---------------------------------------------------------------------------- + * + * eas_RTTTLData + * + * Static memory allocation for RTTTL parser + *---------------------------------------------------------------------------- +*/ +S_RTTTL_DATA eas_RTTTLData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttldata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttldata.h new file mode 100755 index 0000000..31dd522 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttldata.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_rtttldata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data declarations for the RTTTL parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_RTTTLDATA_H +#define EAS_RTTTLDATA_H + +#include "eas_data.h" + + +/* maximum line size as specified in iMelody V1.2 spec */ +#define MAX_LINE_SIZE 75 + +/*---------------------------------------------------------------------------- + * + * S_RTTTL_DATA + * + * This structure contains the state data for the iMelody parser + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* synthesizer handle */ + S_METADATA_CB metadata; /* metadata callback */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_I32 tick; /* length of 32nd note in 256th of a msec */ + EAS_I32 restTicks; /* ticks to rest after current note */ + EAS_I32 repeatOffset; /* file offset to start of repeat section */ + EAS_U8 repeatCount; /* repeat counter */ + EAS_I8 dataByte; /* storage for characters that are "put back" */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_I8 style; /* from STYLE */ + EAS_U8 note; /* MIDI note number */ + EAS_U8 octave; /* decault octave prefix */ + EAS_I8 duration; /* default note duration */ +} S_RTTTL_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smf.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smf.c new file mode 100755 index 0000000..9e096b6 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smf.c @@ -0,0 +1,1207 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smf.c + * + * Contents and purpose: + * SMF Type 0 and 1 File Parser + * + * For SMF timebase analysis, see "MIDI Sequencer Analysis.xls". + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 803 $ + * $Date: 2007-08-01 09:57:00 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_smfdata.h" +#include "eas_smf.h" + +#ifdef JET_INTERFACE +#include "jet_data.h" +#endif + +//3 dls: The timebase for this module is adequate to keep MIDI and +//3 digital audio synchronized for only a few minutes. It should be +//3 sufficient for most mobile applications. If better accuracy is +//3 required, more fractional bits should be added to the timebase. + +static const EAS_U8 smfHeader[] = { 'M', 'T', 'h', 'd' }; + +/* local prototypes */ +static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData); +static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream); +static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode); +static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode); +static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream); +static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks); + + +/*---------------------------------------------------------------------------- + * + * SMF_Parser + * + * This structure contains the functional interface for the SMF parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_SMF_Parser = +{ + SMF_CheckFileType, + SMF_Prepare, + SMF_Time, + SMF_Event, + SMF_State, + SMF_Close, + SMF_Reset, + SMF_Pause, + SMF_Resume, + NULL, + SMF_SetData, + SMF_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * SMF_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + + /* seek to starting offset - usually 0 */ + *ppHandle = NULL; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS) + return result; + + /* search through file for header - slow method */ + if (pEASData->searchHeaderFlag) + { + result = EAS_SearchFile(pEASData, fileHandle, smfHeader, sizeof(smfHeader), &offset); + if (result != EAS_SUCCESS) + return (result == EAS_EOF) ? EAS_SUCCESS : result; + } + + /* read the first 4 bytes of the file - quick method */ + else { + EAS_U8 header[4]; + EAS_I32 count; + if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, header, sizeof(header), &count)) != EAS_SUCCESS) + return result; + + /* check for 'MTrk' - return if no match */ + if ((header[0] != 'M') || (header[1] != 'T') || (header[2] != 'h') || (header[3] != 'd')) + return EAS_SUCCESS; + } + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pSMFData = EAS_CMEnumData(EAS_CM_SMF_DATA); + else + { + pSMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SMF_DATA)); + EAS_HWMemSet((void *)pSMFData,0, sizeof(S_SMF_DATA)); + } + if (!pSMFData) + return EAS_ERROR_MALLOC_FAILED; + + /* initialize some critical data */ + pSMFData->fileHandle = fileHandle; + pSMFData->fileOffset = offset; + pSMFData->pSynth = NULL; + pSMFData->time = 0; + pSMFData->state = EAS_STATE_OPEN; + *ppHandle = pSMFData; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + + /* check for valid state */ + pSMFData = (S_SMF_DATA *) pInstData; + if (pSMFData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pSMFData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + /* parse the file header and setup the individual stream parsers */ + if ((result = SMF_ParseHeader(pEASData->hwInstData, pSMFData)) != EAS_SUCCESS) + return result; + + /* ready to play */ + pSMFData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* sanity check */ +#ifdef _CHECKED_BUILD + if (pSMFData->state == EAS_STATE_STOPPED) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Can't ask for time on a stopped stream\n"); */ } + } + + if (pSMFData->nextStream == NULL) + { + { /* dpp: EAS_ReportEx( _EAS_SEVERITY_ERROR, "no is NULL\n"); */ } + } +#endif + +#if 0 + /* return time in milliseconds */ + /* if chase mode, lie about time */ + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + *pTime = 0; + + else +#endif + + /*lint -e{704} use shift instead of division */ + *pTime = pSMFData->time >> 8; + + *pTime = pSMFData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_SMF_DATA* pSMFData; + EAS_RESULT result; + EAS_I32 i; + EAS_U32 ticks; + EAS_U32 temp; + + /* establish pointer to instance data */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* get current ticks */ + ticks = pSMFData->nextStream->ticks; + + /* assume that an error occurred */ + pSMFData->state = EAS_STATE_ERROR; + +#ifdef JET_INTERFACE + /* if JET has track muted, set parser mode to mute */ + if (pSMFData->nextStream->midiStream.jetData & MIDI_FLAGS_JET_MUTE) + parserMode = eParserModeMute; +#endif + + /* parse the next event from all the streams */ + if ((result = SMF_ParseEvent(pEASData, pSMFData, pSMFData->nextStream, parserMode)) != EAS_SUCCESS) + { + /* check for unexpected end-of-file */ + if (result != EAS_EOF) + return result; + + /* indicate end of track for this stream */ + pSMFData->nextStream->ticks = SMF_END_OF_TRACK; + } + + /* get next delta time, unless already at end of track */ + else if (pSMFData->nextStream->ticks != SMF_END_OF_TRACK) + { + if ((result = SMF_GetDeltaTime(pEASData->hwInstData, pSMFData->nextStream)) != EAS_SUCCESS) + { + /* check for unexpected end-of-file */ + if (result != EAS_EOF) + return result; + + /* indicate end of track for this stream */ + pSMFData->nextStream->ticks = SMF_END_OF_TRACK; + } + + /* if zero delta to next event, stay with this stream */ + else if (pSMFData->nextStream->ticks == ticks) + { + pSMFData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; + } + } + + /* find next event in all streams */ + temp = 0x7ffffff; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + if (pSMFData->streams[i].ticks < temp) + { + temp = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + } + + /* are there any more events to parse? */ + if (pSMFData->nextStream) + { + pSMFData->state = EAS_STATE_PLAY; + + /* update the time of the next event */ + SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks - ticks); + } + else + { + pSMFData->state = EAS_STATE_STOPPING; + VMReleaseAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth); + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_SMF_DATA* pSMFData; + + /* establish pointer to instance data */ + pSMFData = (S_SMF_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pSMFData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pSMFData->pSynth) == 0) + pSMFData->state = EAS_STATE_STOPPED; + } + + if (pSMFData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pSMFData->pSynth) == 0) + pSMFData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pSMFData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_I32 i; + EAS_RESULT result; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* close all the streams */ + for (i = 0; i < pSMFData->numStreams; i++) + { + if (pSMFData->streams[i].fileHandle != NULL) + { + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->streams[i].fileHandle)) != EAS_SUCCESS) + return result; + } + } + if (pSMFData->fileHandle != NULL) + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pSMFData->pSynth != NULL) + VMMIDIShutdown(pEASData, pSMFData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + { + if (pSMFData->streams) + EAS_HWFree(pEASData->hwInstData, pSMFData->streams); + + /* free the instance data */ + EAS_HWFree(pEASData->hwInstData, pSMFData); + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA* pSMFData; + EAS_I32 i; + EAS_RESULT result; + EAS_U32 ticks; + + pSMFData = (S_SMF_DATA*) pInstData; + + /* reset time to zero */ + pSMFData->time = 0; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pSMFData->pSynth, EAS_TRUE); + + /* find the start of each track */ + ticks = 0x7fffffffL; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + + /* reset file position to first byte of data in track */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFData->streams[i].fileHandle, pSMFData->streams[i].startFilePos)) != EAS_SUCCESS) + return result; + + /* initalize some data */ + pSMFData->streams[i].ticks = 0; + + /* initalize the MIDI parser data */ + EAS_InitMIDIStream(&pSMFData->streams[i].midiStream); + + /* parse the first delta time in each stream */ + if ((result = SMF_GetDeltaTime(pEASData->hwInstData,&pSMFData->streams[i])) != EAS_SUCCESS) + return result; + if (pSMFData->streams[i].ticks < ticks) + { + ticks = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + } + + + pSMFData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA *pSMFData; + + /* can't pause a stopped stream */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth); + pSMFData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_SMF_DATA *pSMFData; + + /* can't resume a stopped stream */ + pSMFData = (S_SMF_DATA*) pInstData; + if (pSMFData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pSMFData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Sets parser parameters + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + switch (param) + { + + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pSMFData->metadata, (void*) value, sizeof(S_METADATA_CB)); + break; + +#ifdef JET_INTERFACE + /* set jet segment and track ID of all tracks for callback function */ + case PARSER_DATA_JET_CB: + { + EAS_U32 i; + EAS_U32 bit = (EAS_U32) value; + bit = (bit << JET_EVENT_SEG_SHIFT) & JET_EVENT_SEG_MASK; + for (i = 0; i < pSMFData->numStreams; i++) + pSMFData->streams[i].midiStream.jetData = + (pSMFData->streams[i].midiStream.jetData & + ~(JET_EVENT_TRACK_MASK | JET_EVENT_SEG_MASK)) | + i << JET_EVENT_TRACK_SHIFT | bit | MIDI_FLAGS_JET_CB; + pSMFData->flags |= SMF_FLAGS_JET_STREAM; + } + break; + + /* set state of all mute flags at once */ + case PARSER_DATA_MUTE_FLAGS: + { + EAS_INT i; + EAS_U32 bit = (EAS_U32) value; + for (i = 0; i < pSMFData->numStreams; i++) + { + if (bit & 1) + pSMFData->streams[i].midiStream.jetData |= MIDI_FLAGS_JET_MUTE; + else + pSMFData->streams[i].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE; + bit >>= 1; + } + } + break; + + /* set track mute */ + case PARSER_DATA_SET_MUTE: + if (value < pSMFData->numStreams) + pSMFData->streams[value].midiStream.jetData |= MIDI_FLAGS_JET_MUTE; + else + return EAS_ERROR_PARAMETER_RANGE; + break; + + /* clear track mute */ + case PARSER_DATA_CLEAR_MUTE: + if (value < pSMFData->numStreams) + pSMFData->streams[value].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE; + else + return EAS_ERROR_PARAMETER_RANGE; + break; +#endif + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Retrieves parser parameters + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_SMF_DATA *pSMFData; + + pSMFData = (S_SMF_DATA*) pInstData; + switch (param) + { + /* return file type */ + case PARSER_DATA_FILE_TYPE: + if (pSMFData->numStreams == 1) + *pValue = EAS_FILE_SMF0; + else + *pValue = EAS_FILE_SMF1; + break; + +/* now handled in eas_public.c */ +#if 0 + case PARSER_DATA_POLYPHONY: + if (pSMFData->pSynth) + VMGetPolyphony(pEASData->pVoiceMgr, pSMFData->pSynth, pValue); + else + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + break; + + case PARSER_DATA_PRIORITY: + if (pSMFData->pSynth) + VMGetPriority(pEASData->pVoiceMgr, pSMFData->pSynth, pValue); + break; + + /* set transposition */ + case PARSER_DATA_TRANSPOSITION: + *pValue = pSMFData->transposition; + break; +#endif + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pSMFData->pSynth; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetVarLenData() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData) +{ + EAS_RESULT result; + EAS_U32 data; + EAS_U8 c; + + /* read until bit 7 is zero */ + data = 0; + do + { + if ((result = EAS_HWGetByte(hwInstData, fileHandle,&c)) != EAS_SUCCESS) + return result; + data = (data << 7) | (c & 0x7f); + } while (c & 0x80); + *pData = data; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_GetDeltaTime() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream) +{ + EAS_RESULT result; + EAS_U32 ticks; + + if ((result = SMF_GetVarLenData(hwInstData, pSMFStream->fileHandle, &ticks)) != EAS_SUCCESS) + return result; + + pSMFStream->ticks += ticks; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseMetaEvent() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream) +{ + EAS_RESULT result; + EAS_U32 len; + EAS_I32 pos; + EAS_U32 temp; + EAS_U8 c; + + /* get the meta-event type */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + + /* get the length */ + if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS) + return result; + + /* get the current file position so we can skip the event */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pSMFStream->fileHandle, &pos)) != EAS_SUCCESS) + return result; + pos += (EAS_I32) len; + + /* end of track? */ + if (c == SMF_META_END_OF_TRACK) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: end of track\n", c, len); */ } + pSMFStream->ticks = SMF_END_OF_TRACK; + } + + /* tempo event? */ + else if (c == SMF_META_TEMPO) + { + /* read the 3-byte timebase value */ + temp = 0; + while (len--) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + temp = (temp << 8) | c; + } + + pSMFData->tickConv = (EAS_U16) (((temp * 1024) / pSMFData->ppqn + 500) / 1000); + pSMFData->flags |= SMF_FLAGS_HAS_TEMPO; + } + + /* check for time signature - see iMelody spec V1.4 section 4.1.2.2.3.6 */ + else if (c == SMF_META_TIME_SIGNATURE) + { + pSMFData->flags |= SMF_FLAGS_HAS_TIME_SIG; + } + + /* if the host has registered a metadata callback return the metadata */ + else if (pSMFData->metadata.callback) + { + EAS_I32 readLen; + E_EAS_METADATA_TYPE metaType; + + metaType = EAS_METADATA_UNKNOWN; + + /* only process title on the first track */ + if (c == SMF_META_SEQTRK_NAME) + metaType = EAS_METADATA_TITLE; + else if (c == SMF_META_TEXT) + metaType = EAS_METADATA_TEXT; + else if (c == SMF_META_COPYRIGHT) + metaType = EAS_METADATA_COPYRIGHT; + else if (c == SMF_META_LYRIC) + metaType = EAS_METADATA_LYRIC; + + if (metaType != EAS_METADATA_UNKNOWN) + { + readLen = pSMFData->metadata.bufferSize - 1; + if ((EAS_I32) len < readLen) + readLen = (EAS_I32) len; + if ((result = EAS_HWReadFile(pEASData->hwInstData, pSMFStream->fileHandle, pSMFData->metadata.buffer, readLen, &readLen)) != EAS_SUCCESS) + return result; + pSMFData->metadata.buffer[readLen] = 0; + pSMFData->metadata.callback(metaType, pSMFData->metadata.buffer, pSMFData->metadata.pUserData); + } + } + + /* position file to next event - in case we ignored all or part of the meta-event */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFStream->fileHandle, pos)) != EAS_SUCCESS) + return result; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: type=%02x, len=%d\n", c, len); */ } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseSysEx() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode) +{ + EAS_RESULT result; + EAS_U32 len; + EAS_U8 c; + + /* get the length */ + if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS) + return result; + + /* start of SysEx message? */ + if (f0 == 0xf0) + { + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, f0, parserMode)) != EAS_SUCCESS) + return result; + } + + /* feed the SysEx to the stream parser */ + while (len--) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + + /* check for GM system ON */ + if (pSMFStream->midiStream.flags & MIDI_FLAG_GM_ON) + pSMFData->flags |= SMF_FLAGS_HAS_GM_ON; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseEvent() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a varible length quantity from an SMF file + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode) +{ + EAS_RESULT result; + EAS_U8 c; + + /* get the event type */ + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + + /* parse meta-event */ + if (c == 0xff) + { + if ((result = SMF_ParseMetaEvent(pEASData, pSMFData, pSMFStream)) != EAS_SUCCESS) + return result; + } + + /* parse SysEx */ + else if ((c == 0xf0) || (c == 0xf7)) + { + if ((result = SMF_ParseSysEx(pEASData, pSMFData, pSMFStream, c, parserMode)) != EAS_SUCCESS) + return result; + } + + /* parse MIDI message */ + else + { + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + + /* keep streaming data to the MIDI parser until the message is complete */ + while (pSMFStream->midiStream.pending) + { + if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) + return result; + if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) + return result; + } + + } + + /* chase mode logic */ + if (pSMFData->time == 0) + { + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + { + if (pSMFStream->midiStream.flags & MIDI_FLAG_FIRST_NOTE) + pSMFData->flags &= ~SMF_FLAGS_CHASE_MODE; + } + else if ((pSMFData->flags & SMF_FLAGS_SETUP_BAR) == SMF_FLAGS_SETUP_BAR) + pSMFData->flags = (pSMFData->flags & ~SMF_FLAGS_SETUP_BAR) | SMF_FLAGS_CHASE_MODE; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * SMF_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Parses the header of an SMF file, allocates memory the stream parsers and initializes the + * stream parsers. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pSMFData - pointer to parser instance data + * fileHandle - file handle + * fileOffset - offset in the file where the header data starts, usually 0 + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{801} we know that 'goto' is deprecated - but it's cleaner in this case */ +EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData) +{ + EAS_RESULT result; + EAS_I32 i; + EAS_U16 division; + EAS_U32 chunkSize; + EAS_U32 chunkStart; + EAS_U32 temp; + EAS_U32 ticks; + + /* rewind the file and find the end of the header chunk */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_HEADER_SIZE)) != EAS_SUCCESS) + goto ReadError; + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* determine the number of tracks */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_NUM_TRACKS)) != EAS_SUCCESS) + goto ReadError; + if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &pSMFData->numStreams, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* limit the number of tracks */ + if (pSMFData->numStreams > MAX_SMF_STREAMS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "SMF file contains %u tracks, playing %d tracks\n", pSMFData->numStreams, MAX_SMF_STREAMS); */ } + pSMFData->numStreams = MAX_SMF_STREAMS; + } else if (pSMFData->numStreams == 0) + { + /* avoid 0 sized allocation */ + return EAS_ERROR_PARAMETER_RANGE; + } + + /* get the time division */ + if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &division, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* setup default timebase for 120 bpm */ + pSMFData->ppqn = 192; + if (!division || division & 0x8000) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"No support for SMPTE code timebase\n"); */ } + else + pSMFData->ppqn = (division & 0x7fff); + pSMFData->tickConv = (EAS_U16) (((SMF_DEFAULT_TIMEBASE * 1024) / pSMFData->ppqn + 500) / 1000); + + /* dynamic memory allocation, allocate memory for streams */ + if (pSMFData->streams == NULL) + { + pSMFData->streams = EAS_HWMalloc(hwInstData,sizeof(S_SMF_STREAM) * pSMFData->numStreams); + if (pSMFData->streams == NULL) + return EAS_ERROR_MALLOC_FAILED; + + /* zero the memory to insure complete initialization */ + EAS_HWMemSet((void *)(pSMFData->streams), 0, sizeof(S_SMF_STREAM) * pSMFData->numStreams); + } + + /* find the start of each track */ + chunkStart = (EAS_U32) pSMFData->fileOffset; + ticks = 0x7fffffffL; + pSMFData->nextStream = NULL; + for (i = 0; i < pSMFData->numStreams; i++) + { + + for (;;) + { + + /* calculate start of next chunk - checking for errors */ + temp = chunkStart + SMF_CHUNK_INFO_SIZE + chunkSize; + if (temp <= chunkStart) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Error in chunk size at offset %d\n", chunkStart); */ } + return EAS_ERROR_FILE_FORMAT; + } + chunkStart = temp; + + /* seek to the start of the next chunk */ + if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, (EAS_I32) chunkStart)) != EAS_SUCCESS) + goto ReadError; + + /* read the chunk identifier */ + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* read the chunk size */ + if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS) + goto ReadError; + + /* make sure this is an 'MTrk' chunk */ + if (temp == SMF_CHUNK_TYPE_TRACK) + break; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Unexpected chunk type: 0x%08x\n", temp); */ } + } + + /* initalize some data */ + pSMFData->streams[i].ticks = 0; + pSMFData->streams[i].fileHandle = pSMFData->fileHandle; + + /* NULL the file handle so we don't try to close it twice */ + pSMFData->fileHandle = NULL; + + /* save this file position as the start of the track */ + pSMFData->streams[i].startFilePos = (EAS_I32) chunkStart + SMF_CHUNK_INFO_SIZE; + + /* initalize the MIDI parser data */ + EAS_InitMIDIStream(&pSMFData->streams[i].midiStream); + + /* parse the first delta time in each stream */ + if ((result = SMF_GetDeltaTime(hwInstData, &pSMFData->streams[i])) != EAS_SUCCESS) + goto ReadError; + + if (pSMFData->streams[i].ticks < ticks) + { + ticks = pSMFData->streams[i].ticks; + pSMFData->nextStream = &pSMFData->streams[i]; + } + + /* more tracks to do, create a duplicate file handle */ + if (i < (pSMFData->numStreams - 1)) + { + if ((result = EAS_HWDupHandle(hwInstData, pSMFData->streams[i].fileHandle, &pSMFData->fileHandle)) != EAS_SUCCESS) + goto ReadError; + } + } + + /* update the time of the next event */ + if (pSMFData->nextStream) + SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks); + + return EAS_SUCCESS; + + /* ugly goto: but simpler than structured */ + ReadError: + if (result == EAS_EOF) + return EAS_ERROR_FILE_FORMAT; + return result; +} + +/*---------------------------------------------------------------------------- + * SMF_UpdateTime() + *---------------------------------------------------------------------------- + * Purpose: + * Update the millisecond time base by converting the ticks into millieconds + * + * Inputs: + * + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks) +{ + EAS_U32 temp1, temp2; + + if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) + return; + + temp1 = (ticks >> 10) * pSMFData->tickConv; + temp2 = (ticks & 0x3ff) * pSMFData->tickConv; + pSMFData->time += (EAS_I32)((temp1 << 8) + (temp2 >> 2)); +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smf.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smf.h new file mode 100755 index 0000000..37c0790 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smf.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smf.h + * + * Contents and purpose: + * SMF Type 0 and 1 File Parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SMF_H +#define _EAS_SMF_H + +/* prototypes for private interface to SMF parser */ +EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData); + +#endif /* end _EAS_SMF_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smfdata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smfdata.c new file mode 100755 index 0000000..383d7f3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smfdata.c @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smfdata.c + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 778 $ + * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_miditypes.h" +#include "eas_smfdata.h" + +/*---------------------------------------------------------------------------- + * + * S_SMF_STREAM + * + * Static memory allocation for SMF parser + *---------------------------------------------------------------------------- +*/ +static S_SMF_STREAM eas_SMFStreams[MAX_SMF_STREAMS]; + +/*---------------------------------------------------------------------------- + * + * eas_SMFData + * + * Static memory allocation for SMF parser + *---------------------------------------------------------------------------- +*/ +S_SMF_DATA eas_SMFData = +{ + eas_SMFStreams, /* pointer to individual streams in file */ + 0, /* pointer to next stream with event */ + 0, /* pointer to synth */ + 0, /* file handle */ + { 0, 0, 0, 0}, /* metadata callback */ + 0, /* file offset */ + 0, /* current time in milliseconds/256 */ + 0, /* actual number of streams */ + 0, /* current MIDI tick to msec conversion */ + 0, /* ticks per quarter note */ + 0, /* current state EAS_STATE_XXXX */ + 0 /* flags */ +}; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smfdata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smfdata.h new file mode 100755 index 0000000..8f08839 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smfdata.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_smfdata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data definitions for the SMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 686 $ + * $Date: 2007-05-03 14:10:54 -0700 (Thu, 03 May 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SMF_DATA_H +#define _EAS_SMF_DATA_H + +#ifndef MAX_SMF_STREAMS +#define MAX_SMF_STREAMS 128 +#endif + +/* offsets in to the SMF file */ +#define SMF_OFS_HEADER_SIZE 4 +#define SMF_OFS_FILE_TYPE 8 +#define SMF_OFS_NUM_TRACKS 10 + +/* size of chunk info (chunk ID + chunk size) */ +#define SMF_CHUNK_INFO_SIZE 8 + +/* 'MTrk' track chunk ID */ +#define SMF_CHUNK_TYPE_TRACK 0x4d54726bL + +/* some useful meta-events */ +#define SMF_META_TEXT 0x01 +#define SMF_META_COPYRIGHT 0x02 +#define SMF_META_SEQTRK_NAME 0x03 +#define SMF_META_LYRIC 0x05 +#define SMF_META_END_OF_TRACK 0x2f +#define SMF_META_TEMPO 0x51 +#define SMF_META_TIME_SIGNATURE 0x58 + +/* default timebase (120BPM) */ +#define SMF_DEFAULT_TIMEBASE 500000L + +/* value for pSMFStream->ticks to signify end of track */ +#define SMF_END_OF_TRACK 0xffffffff + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_sndlib.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_sndlib.h new file mode 100755 index 0000000..416be6e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_sndlib.h @@ -0,0 +1,406 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_sndlib.h + * + * Contents and purpose: + * Declarations for the sound library + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 550 $ + * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SNDLIB_H +#define _EAS_SNDLIB_H + +#include "eas_types.h" +#include "eas_synthcfg.h" + +#ifdef _WT_SYNTH +#include "eas_wtengine.h" +#endif + +/*---------------------------------------------------------------------------- + * This is bit of a hack to allow us to keep the same structure + * declarations for the DLS parser. Normally, the data is located + * in read-only memory, but for DLS, we store the data in RW + * memory. + *---------------------------------------------------------------------------- +*/ +#ifndef SCNST +#define SCNST const +#endif + +/*---------------------------------------------------------------------------- + * sample size + *---------------------------------------------------------------------------- +*/ +#ifdef _16_BIT_SAMPLES +typedef EAS_I16 EAS_SAMPLE; +#else +typedef EAS_I8 EAS_SAMPLE; +#endif + +/*---------------------------------------------------------------------------- + * EAS Library ID - quick check for valid library and version + *---------------------------------------------------------------------------- +*/ +#define _EAS_LIBRARY_VERSION 0x01534145 + +#define NUM_PROGRAMS_IN_BANK 128 +#define INVALID_REGION_INDEX 0xffff + +/* this bit in region index indicates that region is for secondary synth */ +#define FLAG_RGN_IDX_FM_SYNTH 0x8000 +#define FLAG_RGN_IDX_DLS_SYNTH 0x4000 +#define REGION_INDEX_MASK 0x3fff + +/*---------------------------------------------------------------------------- + * Generic region data structure + * + * This must be the first element in each region structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_region_tag +{ + EAS_U16 keyGroupAndFlags; + EAS_U8 rangeLow; + EAS_U8 rangeHigh; +} S_REGION; + +/* + * Bit fields for m_nKeyGroupAndFlags + * Bits 0-2 are mode bits in FM synth + * Bits 8-11 are the key group + */ +#define REGION_FLAG_IS_LOOPED 0x01 +#define REGION_FLAG_USE_WAVE_GENERATOR 0x02 +#define REGION_FLAG_USE_ADPCM 0x04 +#define REGION_FLAG_ONE_SHOT 0x08 +#define REGION_FLAG_SQUARE_WAVE 0x10 +#define REGION_FLAG_OFF_CHIP 0x20 +#define REGION_FLAG_NON_SELF_EXCLUSIVE 0x40 +#define REGION_FLAG_LAST_REGION 0x8000 + +/*---------------------------------------------------------------------------- + * Envelope data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_envelope_tag +{ + EAS_I16 attackTime; + EAS_I16 decayTime; + EAS_I16 sustainLevel; + EAS_I16 releaseTime; +} S_ENVELOPE; + +/*---------------------------------------------------------------------------- + * DLS envelope data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_dls_envelope_tag +{ + EAS_I16 delayTime; + EAS_I16 attackTime; + EAS_I16 holdTime; + EAS_I16 decayTime; + EAS_I16 sustainLevel; + EAS_I16 releaseTime; + EAS_I16 velToAttack; + EAS_I16 keyNumToDecay; + EAS_I16 keyNumToHold; +} S_DLS_ENVELOPE; + +/*---------------------------------------------------------------------------- + * LFO data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_lfo_params_tag +{ + EAS_I16 lfoFreq; + EAS_I16 lfoDelay; +} S_LFO_PARAMS; + +/*---------------------------------------------------------------------------- + * Articulation data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_articulation_tag +{ + S_ENVELOPE eg1; + S_ENVELOPE eg2; + EAS_I16 lfoToPitch; + EAS_I16 lfoDelay; + EAS_I16 lfoFreq; + EAS_I16 eg2ToPitch; + EAS_I16 eg2ToFc; + EAS_I16 filterCutoff; + EAS_I8 lfoToGain; + EAS_U8 filterQ; + EAS_I8 pan; +} S_ARTICULATION; + +/*---------------------------------------------------------------------------- + * DLS articulation data structure + *---------------------------------------------------------------------------- +*/ + +typedef struct s_dls_articulation_tag +{ + S_LFO_PARAMS modLFO; + S_LFO_PARAMS vibLFO; + + S_DLS_ENVELOPE eg1; + S_DLS_ENVELOPE eg2; + + EAS_I16 eg1ShutdownTime; + + EAS_I16 filterCutoff; + EAS_I16 modLFOToFc; + EAS_I16 modLFOCC1ToFc; + EAS_I16 modLFOChanPressToFc; + EAS_I16 eg2ToFc; + EAS_I16 velToFc; + EAS_I16 keyNumToFc; + + EAS_I16 modLFOToGain; + EAS_I16 modLFOCC1ToGain; + EAS_I16 modLFOChanPressToGain; + + EAS_I16 tuning; + EAS_I16 keyNumToPitch; + EAS_I16 vibLFOToPitch; + EAS_I16 vibLFOCC1ToPitch; + EAS_I16 vibLFOChanPressToPitch; + EAS_I16 modLFOToPitch; + EAS_I16 modLFOCC1ToPitch; + EAS_I16 modLFOChanPressToPitch; + EAS_I16 eg2ToPitch; + + /* pad to 4-byte boundary */ + EAS_U16 pad; + + EAS_I8 pan; + EAS_U8 filterQandFlags; + +#ifdef _REVERB + EAS_I16 reverbSend; + EAS_I16 cc91ToReverbSend; +#endif + +#ifdef _CHORUS + EAS_I16 chorusSend; + EAS_I16 cc93ToChorusSend; +#endif +} S_DLS_ARTICULATION; + +/* flags in filterQandFlags + * NOTE: Q is stored in bottom 5 bits + */ +#define FLAG_DLS_VELOCITY_SENSITIVE 0x80 +#define FILTER_Q_MASK 0x1f + +/*---------------------------------------------------------------------------- + * Wavetable region data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_region_tag +{ + S_REGION region; + EAS_I16 tuning; + EAS_I16 gain; + EAS_U32 loopStart; + EAS_U32 loopEnd; + EAS_U16 waveIndex; + EAS_U16 artIndex; +} S_WT_REGION; + +/*---------------------------------------------------------------------------- + * DLS region data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_dls_region_tag +{ + S_WT_REGION wtRegion; + EAS_U8 velLow; + EAS_U8 velHigh; +} S_DLS_REGION; + +/*---------------------------------------------------------------------------- + * FM synthesizer data structures + *---------------------------------------------------------------------------- +*/ +typedef struct s_fm_oper_tag +{ + EAS_I16 tuning; + EAS_U8 attackDecay; + EAS_U8 velocityRelease; + EAS_U8 egKeyScale; + EAS_U8 sustain; + EAS_U8 gain; + EAS_U8 flags; +} S_FM_OPER; + +/* defines for S_FM_OPER.m_nFlags */ +#define FM_OPER_FLAG_MONOTONE 0x01 +#define FM_OPER_FLAG_NO_VIBRATO 0x02 +#define FM_OPER_FLAG_NOISE 0x04 +#define FM_OPER_FLAG_LINEAR_VELOCITY 0x08 + +/* NOTE: The first two structure elements are common with S_WT_REGION + * and we will rely on that in the voice management code and must + * remain there unless the voice management code is revisited. + */ +typedef struct s_fm_region_tag +{ + S_REGION region; + EAS_U8 vibTrem; + EAS_U8 lfoFreqDelay; + EAS_U8 feedback; + EAS_I8 pan; + S_FM_OPER oper[4]; +} S_FM_REGION; + +/*---------------------------------------------------------------------------- + * Common data structures + *---------------------------------------------------------------------------- +*/ + +/*---------------------------------------------------------------------------- + * Program data structure + * Used for individual programs not stored as a complete bank. + *---------------------------------------------------------------------------- +*/ +typedef struct s_program_tag +{ + EAS_U32 locale; + EAS_U16 regionIndex; +} S_PROGRAM; + +/*---------------------------------------------------------------------------- + * Bank data structure + * + * A bank always consists of 128 programs. If a bank is less than 128 + * programs, it should be stored as a spare matrix in the pPrograms + * array. + * + * bankNum: MSB/LSB of MIDI bank select controller + * regionIndex: Index of first region in program + *---------------------------------------------------------------------------- +*/ +typedef struct s_bank_tag +{ + EAS_U16 locale; + EAS_U16 regionIndex[NUM_PROGRAMS_IN_BANK]; +} S_BANK; + + +/* defines for libFormat field + * bits 0-17 are the sample rate + * bit 18 is true if wavetable is present + * bit 19 is true if FM is present + * bit 20 is true if filter is enabled + * bit 21 is sample depth (0 = 8-bits, 1 = 16-bits) + * bits 22-31 are reserved + */ +#define LIBFORMAT_SAMPLE_RATE_MASK 0x0003ffff +#define LIB_FORMAT_TYPE_MASK 0x000c0000 +#define LIB_FORMAT_WAVETABLE 0x00000000 +#define LIB_FORMAT_FM 0x00040000 +#define LIB_FORMAT_HYBRID 0x00080000 +#define LIB_FORMAT_FILTER_ENABLED 0x00100000 +#define LIB_FORMAT_16_BIT_SAMPLES 0x00200000 + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * DLS data structure + * + * pDLSPrograms pointer to array of DLS programs + * pDLSRegions pointer to array of DLS regions + * pDLSArticulations pointer to array of DLS articulations + * pSampleLen pointer to array of sample lengths + * ppSamples pointer to array of sample pointers + * numDLSPrograms number of DLS programs + * numDLSRegions number of DLS regions + * numDLSArticulations number of DLS articulations + * numDLSSamples number of DLS samples + *---------------------------------------------------------------------------- +*/ +typedef struct s_eas_dls_tag +{ + S_PROGRAM *pDLSPrograms; + S_DLS_REGION *pDLSRegions; + S_DLS_ARTICULATION *pDLSArticulations; + EAS_U32 *pDLSSampleLen; + EAS_U32 *pDLSSampleOffsets; + EAS_SAMPLE *pDLSSamples; + EAS_U16 numDLSPrograms; + EAS_U16 numDLSRegions; + EAS_U16 numDLSArticulations; + EAS_U16 numDLSSamples; + EAS_U8 refCount; +} S_DLS; +#endif + +/*---------------------------------------------------------------------------- + * Sound library data structure + * + * pBanks pointer to array of banks + * pPrograms pointer to array of programs + * pWTRegions pointer to array of wavetable regions + * pFMRegions pointer to array of FM regions + * pArticulations pointer to array of articulations + * pSampleLen pointer to array of sample lengths + * ppSamples pointer to array of sample pointers + * numBanks number of banks + * numPrograms number of individual program + * numRegions number of regions + * numArticulations number of articulations + * numSamples number of samples + *---------------------------------------------------------------------------- +*/ +typedef struct s_eas_sndlib_tag +{ + SCNST EAS_U32 identifier; + SCNST EAS_U32 libAttr; + + SCNST S_BANK *pBanks; + SCNST S_PROGRAM *pPrograms; + + SCNST S_WT_REGION *pWTRegions; + SCNST S_ARTICULATION *pArticulations; + SCNST EAS_U32 *pSampleLen; + SCNST EAS_U32 *pSampleOffsets; + SCNST EAS_SAMPLE *pSamples; + + SCNST S_FM_REGION *pFMRegions; + + SCNST EAS_U16 numBanks; + SCNST EAS_U16 numPrograms; + + SCNST EAS_U16 numWTRegions; + SCNST EAS_U16 numArticulations; + SCNST EAS_U16 numSamples; + + SCNST EAS_U16 numFMRegions; +} S_EAS; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synth.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synth.h new file mode 100755 index 0000000..6274b7d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synth.h @@ -0,0 +1,395 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synth.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for synth. + * + * Copyright Sonic Network Inc. 2004, 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 718 $ + * $Date: 2007-06-08 16:43:16 -0700 (Fri, 08 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTH_H +#define _EAS_SYNTH_H + +#include "eas_types.h" +#include "eas_sndlib.h" + +#ifdef _WT_SYNTH +#include "eas_wtsynth.h" +#endif + +#ifdef _FM_SYNTH +#include "eas_fmsynth.h" +#endif + +#ifndef NUM_OUTPUT_CHANNELS +#define NUM_OUTPUT_CHANNELS 2 +#endif + +#ifndef MAX_SYNTH_VOICES +#define MAX_SYNTH_VOICES 64 +#endif + +#ifndef MAX_VIRTUAL_SYNTHESIZERS +#define MAX_VIRTUAL_SYNTHESIZERS 4 +#endif + +/* defines */ +#ifndef NUM_PRIMARY_VOICES +#define NUM_PRIMARY_VOICES MAX_SYNTH_VOICES +#elif !defined(NUM_SECONDARY_VOICES) +#define NUM_SECONDARY_VOICES (MAX_SYNTH_VOICES - NUM_PRIMARY_VOICES) +#endif + +#if defined(EAS_WT_SYNTH) +#define NUM_WT_VOICES MAX_SYNTH_VOICES + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +#define NUM_FM_VOICES MAX_SYNTH_VOICES + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +#define NUM_WT_VOICES MAX_SYNTH_VOICES + +/* wavetable drums and FM melodic on MCU */ +#elif defined(EAS_HYBRID_SYNTH) +#define NUM_WT_VOICES NUM_PRIMARY_VOICES +#define NUM_FM_VOICES NUM_SECONDARY_VOICES + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +#define NUM_WT_VOICES NUM_PRIMARY_VOICES +#define NUM_FM_VOICES NUM_SECONDARY_VOICES + +/* FM synth on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +#define NUM_FM_VOICES MAX_SYNTH_VOICES + +#else +#error "Unrecognized architecture option" +#endif + +#define NUM_SYNTH_CHANNELS 16 + +#define DEFAULT_SYNTH_VOICES MAX_SYNTH_VOICES + +/* use the following values to specify unassigned channels or voices */ +#define UNASSIGNED_SYNTH_CHANNEL NUM_SYNTH_CHANNELS +#define UNASSIGNED_SYNTH_VOICE MAX_SYNTH_VOICES + + +/* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ +#define SYNTH_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << SYNTH_UPDATE_PERIOD_IN_BITS) + +/* stealing weighting factors */ +#define NOTE_AGE_STEAL_WEIGHT 1 +#define NOTE_GAIN_STEAL_WEIGHT 4 +#define CHANNEL_POLY_STEAL_WEIGHT 12 +#define CHANNEL_PRIORITY_STEAL_WEIGHT 2 +#define NOTE_MATCH_PENALTY 128 +#define SYNTH_PRIORITY_WEIGHT 8 + +/* default synth master volume */ +#define DEFAULT_SYNTH_MASTER_VOLUME 0x7fff + +#define DEFAULT_SYNTH_PRIORITY 5 + +/* default tuning values */ +#define DEFAULT_PITCH_BEND_SENSITIVITY 200 /* 2 semitones */ +#define DEFAULT_FINE_PITCH 0 /* 0 cents */ +#define DEFAULT_COARSE_PITCH 0 /* 0 semitones */ + +/* default drum channel is 10, but is internally 9 due to unit offset */ +#define DEFAULT_DRUM_CHANNEL 9 + +/* drum channel can simultaneously play this many voices at most */ +#define DEFAULT_CHANNEL_POLYPHONY_LIMIT 2 + +/* default instrument is acoustic piano */ +#define DEFAULT_MELODY_BANK_MSB 0x79 +#define DEFAULT_RHYTHM_BANK_MSB 0x78 +#define DEFAULT_MELODY_BANK_NUMBER (DEFAULT_MELODY_BANK_MSB << 8) +#define DEFAULT_RHYTHM_BANK_NUMBER (DEFAULT_RHYTHM_BANK_MSB << 8) +#define DEFAULT_SYNTH_PROGRAM_NUMBER 0 + +#define DEFAULT_PITCH_BEND 0x2000 /* 0x2000 == (0x40 << 7) | 0x00 */ +#define DEFAULT_MOD_WHEEL 0 +#define DEFAULT_CHANNEL_VOLUME 0x64 +#define DEFAULT_PAN 0x40 /* decimal 64, center */ + +#ifdef _REVERB +#define DEFAULT_REVERB_SEND 40 /* some reverb */ +#endif + +#ifdef _CHORUS +#define DEFAULT_CHORUS_SEND 0 /* no chorus */ +#endif + +#define DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY 0 /* EAS synth uses a different default */ +#define DEFAULT_FILTER_RESONANCE 0 +#define DEFAULT_EXPRESSION 0x7F + +#define DEFAULT_CHANNEL_PRESSURE 0 + +#define DEFAULT_REGISTERED_PARAM 0x3FFF + +#define DEFAULT_CHANNEL_STATIC_GAIN 0 +#define DEFAULT_CHANNEL_STATIC_PITCH 0 + +#define DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS 50 +#define DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS 50 + +#define DEFAULT_KEY_NUMBER 0x69 +#define DEFAULT_VELOCITY 0x64 +#define DEFAULT_REGION_INDEX 0 +#define DEFAULT_ARTICULATION_INDEX 0 +#define DEFAULT_VOICE_GAIN 0 +#define DEFAULT_AGE 0 +#define DEFAULT_SP_MIDI_PRIORITY 16 + + +/* filter defines */ +#define DEFAULT_FILTER_ZERO 0 +#define FILTER_CUTOFF_MAX_PITCH_CENTS 1919 +#define FILTER_CUTOFF_MIN_PITCH_CENTS -4467 +#define A5_PITCH_OFFSET_IN_CENTS 6900 + +/*------------------------------------ + * S_SYNTH_CHANNEL data structure + *------------------------------------ +*/ + +/* S_SYNTH_CHANNEL.m_nFlags */ +#define CHANNEL_FLAG_SUSTAIN_PEDAL 0x01 +#define CHANNEL_FLAG_MUTE 0x02 +#define CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS 0x04 +#define CHANNEL_FLAG_RHYTHM_CHANNEL 0x08 +#define CHANNEL_FLAG_EXTERNAL_AUDIO 0x10 +#define DEFAULT_CHANNEL_FLAGS 0 + +/* macros for extracting virtual synth and channel numbers */ +#define GET_VSYNTH(a) ((a) >> 4) +#define GET_CHANNEL(a) ((a) & 15) + +typedef struct s_synth_channel_tag +{ + /* use static channel parameters to reduce MIPs */ + /* parameters shared by multiple voices assigned to same channel */ + EAS_I32 staticPitch; /* (pitch bend * pitch sens) + fine pitch */ + EAS_I16 staticGain; /* (CC7 * CC11 * master vol)^2 */ + + EAS_U16 regionIndex; /* index of first region in program */ + + EAS_U16 bankNum; /* play programs from this bank */ + EAS_I16 pitchBend; /* pitch wheel value */ + EAS_I16 pitchBendSensitivity; + EAS_I16 registeredParam; /* currently selected registered param */ + + +#if defined(_FM_SYNTH) + EAS_I16 lfoAmt; /* amount of LFO to apply to voice */ +#endif + + EAS_U8 programNum; /* play this instrument number */ + EAS_U8 modWheel; /* CC1 */ + EAS_U8 volume; /* CC7 */ + EAS_U8 pan; /* CC10 */ + + EAS_U8 expression; /* CC11 */ + + /* the following parameters are controlled by RPNs */ + EAS_I8 finePitch; + EAS_I8 coarsePitch; + + EAS_U8 channelPressure; /* applied to all voices on a given channel */ + + EAS_U8 channelFlags; /* bit field channelFlags for */ + /* CC64, SP-MIDI channel masking */ + + EAS_U8 pool; /* SPMIDI channel voice pool */ + EAS_U8 mip; /* SPMIDI MIP setting */ + +#ifdef _REVERB + EAS_U8 reverbSend; /* CC91 */ +#endif + +#ifdef _CHORUS + EAS_U8 chorusSend; /* CC93 */ +#endif +} S_SYNTH_CHANNEL; + +/*------------------------------------ + * S_SYNTH_VOICE data structure + *------------------------------------ +*/ + +/* S_SYNTH_VOICE.m_nFlags */ +#define VOICE_FLAG_UPDATE_VOICE_PARAMETERS 0x01 +#define VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF 0x02 +#define VOICE_FLAG_DEFER_MIDI_NOTE_OFF 0x04 +#define VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET 0x08 +#define VOICE_FLAG_DEFER_MUTE 0x40 +#define DEFAULT_VOICE_FLAGS 0 + +/* S_SYNTH_VOICE.m_eState */ +typedef enum { + + eVoiceStateFree = 0, + eVoiceStateStart, + eVoiceStatePlay, + eVoiceStateRelease, + eVoiceStateMuting, + eVoiceStateStolen, + eVoiceStateInvalid /* should never be in this state! */ + +} E_VOICE_STATE; +#define DEFAULT_VOICE_STATE eVoiceStateFree + +typedef struct s_synth_voice_tag +{ + +/* These parameters are common to both wavetable and FM + * synthesizers. The voice manager should only access this data. + * Any other data should be manipulated by the code that is + * specific to that synthesizer and reflected back through the + * common state data available here. + */ + EAS_U16 regionIndex; /* index to wave and playback params */ + EAS_I16 gain; /* current gain */ + EAS_U16 age; /* large value means old note */ + EAS_U16 nextRegionIndex; /* index to wave and playback params */ + EAS_U8 voiceState; /* current voice state */ + EAS_U8 voiceFlags; /* misc flags/bit fields */ + EAS_U8 channel; /* this voice plays on this synth channel */ + EAS_U8 note; /* 12 <= key number <= 108 */ + EAS_U8 velocity; /* 0 <= velocity <= 127 */ + EAS_U8 nextChannel; /* play stolen voice on this channel */ + EAS_U8 nextNote; /* 12 <= key number <= 108 */ + EAS_U8 nextVelocity; /* 0 <= velocity <= 127 */ +} S_SYNTH_VOICE; + +/*------------------------------------ + * S_SYNTH data structure + * + * One instance for each MIDI stream + *------------------------------------ +*/ + +/* S_SYNTH.m_nFlags */ +#define SYNTH_FLAG_RESET_IS_REQUESTED 0x01 +#define SYNTH_FLAG_SP_MIDI_ON 0x02 +#define SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS 0x04 +#define SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING 0x08 +#define DEFAULT_SYNTH_FLAGS SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS + +typedef struct s_synth_tag +{ + struct s_eas_data_tag *pEASData; + const S_EAS *pEAS; + +#ifdef DLS_SYNTHESIZER + S_DLS *pDLS; +#endif + +#ifdef EXTERNAL_AUDIO + EAS_EXT_PRG_CHG_FUNC cbProgChgFunc; + EAS_EXT_EVENT_FUNC cbEventFunc; + EAS_VOID_PTR *pExtAudioInstData; +#endif + + S_SYNTH_CHANNEL channels[NUM_SYNTH_CHANNELS]; + EAS_I32 totalNoteCount; + EAS_U16 maxPolyphony; + EAS_U16 numActiveVoices; + EAS_U16 masterVolume; + EAS_U8 channelsByPriority[NUM_SYNTH_CHANNELS]; + EAS_U8 poolCount[NUM_SYNTH_CHANNELS]; + EAS_U8 poolAlloc[NUM_SYNTH_CHANNELS]; + EAS_U8 synthFlags; + EAS_I8 globalTranspose; + EAS_U8 vSynthNum; + EAS_U8 refCount; + EAS_U8 priority; +} S_SYNTH; + +/*------------------------------------ + * S_VOICE_MGR data structure + * + * One instance for each EAS library instance + *------------------------------------ +*/ +typedef struct s_voice_mgr_tag +{ + S_SYNTH *pSynth[MAX_VIRTUAL_SYNTHESIZERS]; + EAS_PCM voiceBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES]; + +#ifdef _FM_SYNTH + EAS_PCM operMixBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES]; + S_FM_VOICE fmVoices[NUM_FM_VOICES]; +#endif + +#ifdef _WT_SYNTH + S_WT_VOICE wtVoices[NUM_WT_VOICES]; +#endif + +#ifdef _REVERB + EAS_PCM reverbSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES]; +#endif + +#ifdef _CHORUS + EAS_PCM chorusSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES]; +#endif + S_SYNTH_VOICE voices[MAX_SYNTH_VOICES]; + + EAS_SNDLIB_HANDLE pGlobalEAS; + +#ifdef DLS_SYNTHESIZER + S_DLS *pGlobalDLS; +#endif + +#ifdef _SPLIT_ARCHITECTURE + EAS_FRAME_BUFFER_HANDLE pFrameBuffer; +#endif + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + EAS_U16 maxPolyphonyPrimary; + EAS_U16 maxPolyphonySecondary; +#endif + + EAS_I32 workload; + EAS_I32 maxWorkLoad; + + EAS_U16 activeVoices; + EAS_U16 maxPolyphony; + + EAS_U16 age; + +/* limits the number of voice starts in a frame for split architecture */ +#ifdef MAX_VOICE_STARTS + EAS_U16 numVoiceStarts; +#endif +} S_VOICE_MGR; + +#endif /* #ifdef _EAS_SYNTH_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synth_protos.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synth_protos.h new file mode 100755 index 0000000..b03af0f --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synth_protos.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synth_protos.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for synth. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTH_PROTOS_H +#define _EAS_SYNTH_PROTOS_H + +/* includes */ +#include "eas_data.h" +#include "eas_sndlib.h" + +#ifdef _SPLIT_ARCHITECTURE +typedef struct s_frame_interface_tag +{ + EAS_BOOL (* EAS_CONST pfStartFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer); + EAS_BOOL (* EAS_CONST pfEndFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain); +} S_FRAME_INTERFACE; +#endif + +/* generic synthesizer interface */ +typedef struct +{ + EAS_RESULT (* EAS_CONST pfInitialize)(S_VOICE_MGR *pVoiceMgr); + EAS_RESULT (* EAS_CONST pfStartVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); + EAS_BOOL (* EAS_CONST pfUpdateVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); + void (* EAS_CONST pfReleaseVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); + void (* EAS_CONST pfMuteVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); + void (* EAS_CONST pfSustainPedal)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); + void (* EAS_CONST pfUpdateChannel)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); +} S_SYNTH_INTERFACE; + +#endif + + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synthcfg.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synthcfg.h new file mode 100755 index 0000000..78a4178 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synthcfg.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_synthcfg.h + * + * Contents and purpose: + * Defines for various synth configurations + * + * Copyright Sonic Network Inc. 2004, 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 664 $ + * $Date: 2007-04-25 13:11:22 -0700 (Wed, 25 Apr 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_SYNTHCFG_H +#define _EAS_SYNTHCFG_H + +#if defined(EAS_WT_SYNTH) +#define _WT_SYNTH + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +#define _FM_SYNTH + +/* wavetable drums and FM melodic on MCU */ +#elif defined(EAS_HYBRID_SYNTH) +#define _WT_SYNTH +#define _FM_SYNTH +#define _SECONDARY_SYNTH +#define _HYBRID_SYNTH + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +#define _WT_SYNTH +#define _SPLIT_ARCHITECTURE + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +#define _WT_SYNTH +#define _FM_SYNTH +#define _SECONDARY_SYNTH +#define _SPLIT_ARCHITECTURE +#define _HYBRID_SYNTH + +/* FM synth on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +#define _FM_SYNTH +#define _SPLIT_ARCHITECTURE + +#else +#error "Unrecognized architecture option" +#endif + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tcdata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tcdata.c new file mode 100755 index 0000000..65ba49e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tcdata.c @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_tcdata.c + * + * Contents and purpose: + * ToneControl Parser data + * + * This file contains static data for the ToneControl parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_types.h" +#include "eas_tcdata.h" + +/*---------------------------------------------------------------------------- + * + * eas_iMelodyData + * + * Static memory allocation for iMelody parser + *---------------------------------------------------------------------------- +*/ +S_TC_DATA eas_TCData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tcdata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tcdata.h new file mode 100755 index 0000000..86e8d24 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tcdata.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_tcdata.h + * + * Contents and purpose: + * SMF File Parser + * + * This file contains data declarations for the ToneControl parser. + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef EAS_TCDATA_H +#define EAS_TCDATA_H + +#include "eas_data.h" + +/*---------------------------------------------------------------------------- + * + * S_TC_DATA + * + * This structure contains the state data for the ToneControl parser + *---------------------------------------------------------------------------- +*/ +typedef struct +{ + EAS_FILE_HANDLE fileHandle; /* file handle */ + S_SYNTH *pSynth; /* synthesizer handle */ + EAS_I32 fileOffset; /* offset to start of data */ + EAS_I32 time; /* current time in 256ths of a msec */ + EAS_I32 tick; /* tick based on current tempo and resolution */ + EAS_I32 length; /* length of current note */ + EAS_I32 restorePos; /* return to here after block */ + EAS_U8 state; /* current state EAS_STATE_XXXX */ + EAS_U8 volume; /* volume */ + EAS_I8 note; /* current note */ + EAS_I8 repeatCount; /* note repeat counter */ + EAS_I8 tempo; /* tempo from file (bpm = tempo * 4) */ + EAS_I8 resolution; /* resolution from file */ + EAS_I8 dataByte; /* storage for characters that are "put back" */ + EAS_BOOL8 byteAvail; /* char in "put back" buffer */ +} S_TC_DATA; + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tonecontrol.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tonecontrol.c new file mode 100755 index 0000000..cceb7f9 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tonecontrol.c @@ -0,0 +1,941 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_tonecontrol.c + * + * Contents and purpose: + * MMAPI ToneControl parser + * + * Copyright Sonic Network Inc. 2006 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_tcdata.h" + + +/* default channel and program for TC playback */ +#define TC_CHANNEL 0 +#define TC_PROGRAM 80 +#define TC_VELOCITY 127 + +#define TC_FIELD_SILENCE -1 +#define TC_FIELD_VERSION -2 +#define TC_FIELD_TEMPO -3 +#define TC_FIELD_RESOLUTION -4 +#define TC_FIELD_BLOCK_START -5 +#define TC_FIELD_BLOCK_END -6 +#define TC_FIELD_PLAY_BLOCK -7 +#define TC_FIELD_SET_VOLUME -8 +#define TC_FIELD_REPEAT -9 +#define TC_FIELD_INVALID -10 + +/* convert 0-100 volume to 0-127 velocity using fixed point */ +#define TC_VOLUME_CONV 21307064 +#define TC_VOLUME_SHIFT 24 + + +/* local prototypes */ +static EAS_RESULT TC_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT TC_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT TC_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT TC_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT TC_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT TC_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT TC_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT TC_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT TC_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT TC_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT TC_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT TC_ParseHeader (S_EAS_DATA *pEASData, S_TC_DATA* pData); +static EAS_RESULT TC_StartNote (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode, EAS_I8 note); +static EAS_RESULT TC_GetRepeat (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode); +static EAS_RESULT TC_PlayBlock (S_EAS_DATA *pEASData, S_TC_DATA* pData); +static EAS_RESULT TC_BlockEnd (S_EAS_DATA *pEASData, S_TC_DATA* pData); +static EAS_RESULT TC_GetVolume (S_EAS_DATA *pEASData, S_TC_DATA* pData); +static EAS_RESULT TC_GetTempo (S_EAS_DATA *pEASData, S_TC_DATA* pData); +static EAS_RESULT TC_GetResolution (S_EAS_DATA *pEASData, S_TC_DATA* pData); +static EAS_RESULT TC_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_TC_DATA *pData, EAS_I8 *pValue); +static void TC_PutBackChar (S_TC_DATA *pData, EAS_I8 value); + +/* calculate a new tick time based on resolution & tempo */ +EAS_INLINE void TC_CalcTimeBase (S_TC_DATA *pData) +{ + + /* ticks in 256ths of a millisecond */ + pData->tick = ((60 * 1000) << 8) / (pData->tempo * pData->resolution); +} + +/*---------------------------------------------------------------------------- + * + * EAS_TC_Parser + * + * This structure contains the functional interface for the iMelody parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_TC_Parser = +{ + TC_CheckFileType, + TC_Prepare, + TC_Time, + TC_Event, + TC_State, + TC_Close, + TC_Reset, + TC_Pause, + TC_Resume, + NULL, + TC_SetData, + TC_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * TC_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_TC_DATA data; + S_TC_DATA *pData; + + /* init data */ + EAS_HWMemSet(&data, 0, sizeof(S_TC_DATA)); + data.fileHandle = fileHandle; + data.fileOffset = offset; + *ppHandle= NULL; + + /* see if we can parse the header */ + if (TC_ParseHeader(pEASData, &data) == EAS_SUCCESS) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pData = EAS_CMEnumOptData(EAS_MODULE_MMAPI_TONE_CONTROL); + else + pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_TC_DATA)); + if (!pData) + return EAS_ERROR_MALLOC_FAILED; + + /* copy data to persistent storage */ + EAS_HWMemCpy(pData, &data, sizeof(S_TC_DATA)); + + /* return a pointer to the instance data */ + pData->state = EAS_STATE_OPEN; + *ppHandle = pData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_TC_DATA* pData; + EAS_RESULT result; + + /* check for valid state */ + pData = (S_TC_DATA*) pInstData; + if (pData->state != EAS_STATE_OPEN) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* instantiate a synthesizer */ + if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } + return result; + } + + /* set to ready state */ + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT TC_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + S_TC_DATA *pData; + + pData = (S_TC_DATA*) pInstData; + + /* return time in milliseconds */ + /*lint -e{704} use shift instead of division */ + *pTime = pData->time >> 8; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + S_TC_DATA* pData; + EAS_RESULT result; + EAS_I8 temp; + + pData = (S_TC_DATA*) pInstData; + if (pData->state >= EAS_STATE_OPEN) + return EAS_SUCCESS; + + /* initialize MIDI channel when the track starts playing */ + if (pData->time == 0) + { + /* set program to square lead */ + VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, TC_PROGRAM); + + /* set channel volume to max */ + VMControlChange(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, 7, 127); + } + + /* check for end of note */ + if (pData->note >= 0) + { + /* stop the note */ + VMStopNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, 0); + + /* check for repeat note */ + if (pData->repeatCount) + { + pData->repeatCount--; + pData->time += pData->length; + if ((pData->note >= 0) && (parserMode == eParserModePlay)) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, pData->volume); + return EAS_SUCCESS; + } + + pData->note = TC_FIELD_SILENCE; + } + + /* parse stream until we get a note or rest */ + for (;;) + { + + /* get next byte from stream */ + if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + { + if (result == EAS_EOF) + { + pData->state = EAS_STATE_STOPPING; + return EAS_SUCCESS; + } + break; + } + + /* check for musical events */ + if (temp >= TC_FIELD_SILENCE) + { + result = TC_StartNote(pEASData, pData, parserMode, temp); + break; + } + + /* must be a control field */ + switch (temp) + { + case TC_FIELD_TEMPO: + result = TC_GetTempo(pEASData, pData); + break; + + case TC_FIELD_RESOLUTION: + result = TC_GetResolution(pEASData, pData); + break; + + case TC_FIELD_SET_VOLUME: + result = TC_GetVolume(pEASData, pData); + break; + + case TC_FIELD_REPEAT: + result = TC_GetRepeat(pEASData, pData, parserMode); + break; + + case TC_FIELD_PLAY_BLOCK: + result = TC_PlayBlock(pEASData, pData); + break; + + case TC_FIELD_BLOCK_START: + result = TC_GetNextChar(pEASData->hwInstData, pData, &temp); + break; + + case TC_FIELD_BLOCK_END: + result = TC_BlockEnd(pEASData, pData); + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected byte 0x%02x in ToneControl stream\n", temp); */ } + result = EAS_ERROR_FILE_FORMAT; + } + + /* check for error */ + if (result != EAS_SUCCESS) + break; + } + + /* check for error */ + if (result != EAS_SUCCESS) + { + if (result == EAS_EOF) + result = EAS_ERROR_FILE_FORMAT; + pData->state = EAS_STATE_ERROR; + } + else + pData->state = EAS_STATE_PLAY; + return result; +} + +/*---------------------------------------------------------------------------- + * TC_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT TC_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + S_TC_DATA* pData; + + /* establish pointer to instance data */ + pData = (S_TC_DATA*) pInstData; + + /* if stopping, check to see if synth voices are active */ + if (pData->state == EAS_STATE_STOPPING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_STOPPED; + } + + if (pData->state == EAS_STATE_PAUSING) + { + if (VMActiveVoices(pData->pSynth) == 0) + pData->state = EAS_STATE_PAUSED; + } + + /* return current state */ + *pState = pData->state; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_TC_DATA* pData; + EAS_RESULT result; + + pData = (S_TC_DATA*) pInstData; + + /* close the file */ + if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) + return result; + + /* free the synth */ + if (pData->pSynth != NULL) + VMMIDIShutdown(pEASData, pData->pSynth); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pData); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_TC_DATA* pData; + EAS_RESULT result; + + pData = (S_TC_DATA*) pInstData; + + /* reset the synth */ + VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); + + /* reset time to zero */ + pData->time = 0; + + /* reset file position and re-parse header */ + pData->state = EAS_STATE_ERROR; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + if ((result = TC_ParseHeader (pEASData, pData)) != EAS_SUCCESS) + return result; + + pData->state = EAS_STATE_READY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_TC_DATA *pData; + + /* can't pause a stopped stream */ + pData = (S_TC_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* mute the synthesizer */ + VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); + pData->state = EAS_STATE_PAUSING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT TC_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_TC_DATA *pData; + + /* can't resume a stopped stream */ + pData = (S_TC_DATA*) pInstData; + if (pData->state == EAS_STATE_STOPPED) + return EAS_ERROR_ALREADY_STOPPED; + + /* nothing to do but resume playback */ + pData->state = EAS_STATE_PLAY; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData, pInstData, value) reserved for future use */ +static EAS_RESULT TC_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + /* we don't parse any metadata, but we need to return success here */ + if (param == PARSER_DATA_METADATA_CB) + return EAS_SUCCESS; + + return EAS_ERROR_INVALID_PARAMETER; +} + +/*---------------------------------------------------------------------------- + * TC_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Return file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -e{715} common with other parsers */ +static EAS_RESULT TC_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_TC_DATA *pData; + + pData = (S_TC_DATA *) pInstData; + switch (param) + { + /* return file type as TC */ + case PARSER_DATA_FILE_TYPE: + *pValue = EAS_FILE_MMAPI_TONE_CONTROL; + break; + + case PARSER_DATA_SYNTH_HANDLE: + *pValue = (EAS_I32) pData->pSynth; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_ParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_ParseHeader (S_EAS_DATA *pEASData, S_TC_DATA* pData) +{ + EAS_RESULT result; + EAS_I8 temp; + + /* initialize some defaults */ + pData->time = 0; + pData->tempo = 120; + pData->resolution = 64; + pData->volume = 127; + pData->repeatCount = 0; + pData->note = TC_FIELD_SILENCE; + pData->byteAvail = EAS_FALSE; + + /* set default timebase */ + TC_CalcTimeBase(pData); + + /* seek to start of data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + + /* get version */ + if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + + /* check for version number */ + if (temp == TC_FIELD_VERSION) + { + TC_GetNextChar(pEASData->hwInstData, pData, &temp); +// { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "ToneControl sequence version %d\n", temp); */ } + } + else + return EAS_ERROR_FILE_FORMAT; + + /* parse the header data until we find the first note or block */ + for (;;) + { + + /* get next byte from stream */ + if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) + return result; + + /* check for tempo */ + if (temp == TC_FIELD_TEMPO) + { + if ((result = TC_GetTempo(pEASData, pData)) != EAS_SUCCESS) + return result; + } + + /* or resolution */ + else if (temp == TC_FIELD_TEMPO) + { + if ((result = TC_GetResolution(pEASData, pData)) != EAS_SUCCESS) + return result; + } + + /* must be music data */ + else if (temp > TC_FIELD_INVALID) + { + TC_PutBackChar(pData, temp); + return EAS_SUCCESS; + } + + /* unknown codes */ + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected byte 0x%02x in ToneControl stream\n", temp); */ } + return EAS_ERROR_FILE_FORMAT; + } + } +} + +/*---------------------------------------------------------------------------- + * TC_StartNote() + *---------------------------------------------------------------------------- + * Process a note or silence event + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_StartNote (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode, EAS_I8 note) +{ + EAS_I8 duration; + + /* get the duration */ + if (TC_GetNextChar(pEASData->hwInstData, pData, &duration) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + + /* calculate time of next event */ + pData->length = (EAS_I32) duration * pData->tick; + pData->time += pData->length; + + /* start the note */ + if ((note >= 0) && (parserMode == eParserModePlay)) + { + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) note, pData->volume); + pData->note = note; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_GetRepeat() + *---------------------------------------------------------------------------- + * Process a repeat code + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_GetRepeat (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode) +{ + EAS_I8 count; + + /* get the repeat count */ + if (TC_GetNextChar(pEASData->hwInstData, pData, &count) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + + /* validiate it */ + if (count < 2) + return EAS_ERROR_FILE_FORMAT; + + /* calculate time of next event */ + pData->time += pData->length; + pData->repeatCount = count - 2; + + /* start the note */ + if ((pData->note >= 0) && (parserMode == eParserModePlay)) + VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, pData->volume); + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_PlayBlock() + *---------------------------------------------------------------------------- + * Play a block of notes + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_PlayBlock (S_EAS_DATA *pEASData, S_TC_DATA* pData) +{ + EAS_RESULT result; + EAS_I8 blockNum; + EAS_I8 temp; + EAS_I8 temp2; + + /* get the block number */ + if (TC_GetNextChar(pEASData->hwInstData, pData, &blockNum) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + + /* validiate it */ + if (blockNum < 0) + return EAS_ERROR_FILE_FORMAT; + + /* save the current position */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, pData->fileHandle, &pData->restorePos)) != EAS_SUCCESS) + return result; + + /* return to start of file */ + pData->byteAvail = EAS_FALSE; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) + return result; + + /* find the block */ + for (;;) + { + if (TC_GetNextChar(pEASData->hwInstData, pData, &temp) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + + if (TC_GetNextChar(pEASData->hwInstData, pData, &temp2) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + + if ((temp == TC_FIELD_BLOCK_START) && (temp2 == blockNum)) + return EAS_SUCCESS; + } +} + +/*---------------------------------------------------------------------------- + * TC_BlockEnd() + *---------------------------------------------------------------------------- + * Handle end of block + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_BlockEnd (S_EAS_DATA *pEASData, S_TC_DATA* pData) +{ + EAS_I8 blockNum; + + /* get the block number */ + if (TC_GetNextChar(pEASData->hwInstData, pData, &blockNum) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + + /* validiate it */ + if (blockNum < 0) + return EAS_ERROR_FILE_FORMAT; + + /* if we were playing this block, restore to previous position */ + pData->byteAvail = EAS_FALSE; + return EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->restorePos); +} + +/*---------------------------------------------------------------------------- + * TC_GetVolume() + *---------------------------------------------------------------------------- + * Get the volume field and process it + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_GetVolume (S_EAS_DATA *pEASData, S_TC_DATA* pData) +{ + EAS_I8 volume; + + /* get volume */ + if (TC_GetNextChar(pEASData->hwInstData, pData, &volume) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + if ((volume < 0) || (volume > 100)) + return EAS_ERROR_FILE_FORMAT; + + /* save volume */ + pData->volume = (EAS_U8) ((EAS_I32) (volume * TC_VOLUME_CONV + 1) >> TC_VOLUME_SHIFT); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_GetTempo() + *---------------------------------------------------------------------------- + * Get the tempo field and process it + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_GetTempo (S_EAS_DATA *pEASData, S_TC_DATA* pData) +{ + EAS_I8 tempo; + + /* get tempo */ + if (TC_GetNextChar(pEASData->hwInstData, pData, &tempo) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + if (tempo < 5) + return EAS_ERROR_FILE_FORMAT; + + /* save tempo */ + pData->tempo = tempo; + + /* calculate new timebase */ + TC_CalcTimeBase(pData); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_GetResolution() + *---------------------------------------------------------------------------- + * Get the resolution field and process it + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_GetResolution (S_EAS_DATA *pEASData, S_TC_DATA* pData) +{ + EAS_I8 resolution; + + /* get resolution */ + if (TC_GetNextChar(pEASData->hwInstData, pData, &resolution) != EAS_SUCCESS) + return EAS_ERROR_FILE_FORMAT; + if (resolution < 0) + return EAS_ERROR_FILE_FORMAT; + + /* save tempo */ + pData->resolution = resolution; + + /* calculate new timebase */ + TC_CalcTimeBase(pData); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * TC_GetNextChar() + *---------------------------------------------------------------------------- + * Fetch the next character from the stream + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT TC_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_TC_DATA *pData, EAS_I8 *pValue) +{ + + /* get character from "put back" buffer */ + if (pData->byteAvail) + { + pData->byteAvail = EAS_FALSE; + *pValue = pData->dataByte; + return EAS_SUCCESS; + } + + /* get character from file */ + return EAS_HWGetByte(hwInstData, pData->fileHandle, pValue); +} + +/*---------------------------------------------------------------------------- + * TC_PutBackChar() + *---------------------------------------------------------------------------- + * Put back the character + *---------------------------------------------------------------------------- +*/ +static void TC_PutBackChar (S_TC_DATA *pData, EAS_I8 value) +{ + + pData->dataByte = value; + pData->byteAvail = EAS_TRUE; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_vm_protos.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_vm_protos.h new file mode 100755 index 0000000..20f7c09 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_vm_protos.h @@ -0,0 +1,1086 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_vm_protos.h + * + * Contents and purpose: + * Declarations, interfaces, and prototypes for voice manager. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 736 $ + * $Date: 2007-06-22 13:51:24 -0700 (Fri, 22 Jun 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_VM_PROTOS_H +#define _EAS_VM_PROTOS_H + +// includes +#include "eas_data.h" +#include "eas_sndlib.h" + +/*---------------------------------------------------------------------------- + * VMInitialize() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitialize (S_EAS_DATA *pEASData); + +/*---------------------------------------------------------------------------- + * VMInitMIDI() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitMIDI (S_EAS_DATA *pEASData, S_SYNTH **ppSynth); + +/*---------------------------------------------------------------------------- + * VMInitializeAllChannels() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllChannels (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMResetControllers() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMResetControllers (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMInitMIPTable() + *---------------------------------------------------------------------------- + * Purpose: + * Initialize the SP-MIDI MIP table + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * mute - EAS_FALSE to unmute channels, EAS_TRUE to mute + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitMIPTable (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMSetMIPEntry() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the priority and MIP level for a MIDI channel + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * channel - MIDI channel number + * priority - priority (0-15 with 0 = highest priority) + * mip - maximum instantaneous polyphony + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetMIPEntry (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 priority, EAS_U8 mip); + +/*---------------------------------------------------------------------------- + * VMUpdateMIPTable() + *---------------------------------------------------------------------------- + * Purpose: + * This routine is called when the polyphony count in the synthesizer changes + * + * Inputs: + * pEASData - pointer to synthesizer instance data + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMUpdateMIPTable (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMInitializeAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllVoices (S_VOICE_MGR *pVoiceMgr, EAS_INT vSynthNum); + +/*---------------------------------------------------------------------------- + * VMStartNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to play the requested note on the requested + * channel if possible. + * + * Inputs: + * nChannel - the MIDI channel + * nKeyNumber - the MIDI key number for this note + * nNoteVelocity - the key velocity for this note + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMStartNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity); + +/*---------------------------------------------------------------------------- + * VMCheckKeyGroup() + *---------------------------------------------------------------------------- + * Purpose: + * If the note that we've been asked to start is in the same key group as + * any currently playing notes, then we must shut down the currently playing + * note in the same key group and then start the newly requested note. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nRegionIndex - calling routine finds this index and gives to us + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * + * Side Effects: + * gsSynthObject.m_sVoice[free voice num].m_nKeyNumber may be assigned + * gsSynthObject.m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +void VMCheckKeyGroup (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U16 keyGroup, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMCheckPolyphonyLimiting() + *---------------------------------------------------------------------------- + * Purpose: + * We only play at most 2 of the same note on a MIDI channel. + * E.g., if we are asked to start note 36, and there are already two voices + * that are playing note 36, then we must steal the voice playing + * the oldest note 36 and use that stolen voice to play the new note 36. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * * + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber may be assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckPolyphonyLimiting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to end the requested note on the requested + * channel. + * + * Inputs: + * nChannel - the MIDI channel + * nKeyNumber - the key number of the note to stop + * nNoteVelocity - the note-off velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sVoice[free voice num].m_nSynthChannel may be assigned + * gsSynthObject.m_sVoice[free voice num].m_nKeyNumber is assigned + * gsSynthObject.m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +void VMStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 key, EAS_U8 velocity); + +/*---------------------------------------------------------------------------- + * VMFindAvailableVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Find an available voice and return the voice number if available. + * + * Inputs: + * pnVoiceNumber - really an output, see below + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - returns the voice number of available voice if found + * success - if there is an available voice + * failure - otherwise + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindAvailableVoice (S_VOICE_MGR *pVoiceMgr, EAS_INT *pVoiceNumber, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMStealVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Steal a voice and return the voice number + * + * Stealing algorithm: steal the best choice with minimal work, taking into + * account SP-Midi channel priorities and polyphony allocation. + * + * In one pass through all the voices, figure out which voice to steal + * taking into account a number of different factors: + * Priority of the voice's MIDI channel + * Number of voices over the polyphony allocation for voice's MIDI channel + * Amplitude of the voice + * Note age + * Key velocity (for voices that haven't been started yet) + * If any matching notes are found + * + * Inputs: + * nChannel - the channel that this voice wants to be started on + * nKeyNumber - the key number for this new voice + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - voice stolen + * EAS_RESULT EAS_SUCCESS - always successful + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMStealVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_INT *pVoiceNumber, EAS_U8 channel, EAS_U8 note, EAS_I32 lowVoice, EAS_I32 highVoice); + +/*---------------------------------------------------------------------------- + * VMAddSamples() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize the requested number of samples. + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMAddSamples (S_VOICE_MGR *pVoiceMgr, EAS_I32 *pMixBuffer, EAS_I32 numSamplesToAdd); + +/*---------------------------------------------------------------------------- + * VMProgramChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the instrument (program) for the given channel. + * + * Depending on the program number, and the bank selected for this channel, the + * program may be in ROM, RAM (from SMAF or CMX related RAM wavetable), or + * Alternate wavetable (from mobile DLS or other DLS file) + * + * This function figures out what wavetable should be used, and sets it up as the + * wavetable to use for this channel. Also the channel may switch from a melodic + * channel to a rhythm channel, or vice versa. + * + * Inputs: + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nProgramNumber is likely changed + * gsSynthObject.m_sChannel[nChannel].m_psEAS may be changed + * gsSynthObject.m_sChannel[nChannel].m_bRhythmChannel may be changed + * + *---------------------------------------------------------------------------- +*/ +void VMProgramChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 program); + +/*---------------------------------------------------------------------------- + * VMChannelPressure() + *---------------------------------------------------------------------------- + * Purpose: + * Change the channel pressure for the given channel + * + * Inputs: + * nChannel - the MIDI channel + * nVelocity - the channel pressure value + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nChannelPressure is updated + *---------------------------------------------------------------------------- +*/ +void VMChannelPressure (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMPitchBend() + *---------------------------------------------------------------------------- + * Purpose: + * Change the pitch wheel value for the given channel. + * This routine constructs the proper 14-bit argument when the calling routine + * passes the pitch LSB and MSB. + * + * Note: some midi disassemblers display a bipolar pitch bend value. + * We can display the bipolar value using + * if m_nPitchBend >= 0x2000 + * bipolar pitch bend = postive (m_nPitchBend - 0x2000) + * else + * bipolar pitch bend = negative (0x2000 - m_nPitchBend) + * + * Inputs: + * nChannel - the MIDI channel + * nPitchLSB - the LSB byte from the pitch bend message + * nPitchMSB - the MSB byte from the message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nPitchBend is changed + * + *---------------------------------------------------------------------------- +*/ +void VMPitchBend (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 pitchLSB, EAS_U8 pitchMSB); + +/*---------------------------------------------------------------------------- + * VMControlChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the controller (or mode) for the given channel. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the controller number + * nControlValue - the controller number for this control change + * nControlValue - the value for this control change + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel] controller is changed + * + *---------------------------------------------------------------------------- +*/ +void VMControlChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMUpdateRPNStateMachine() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when we want to parse a stream of RPN messages. + * NOTE: The synth has only one set of global RPN data instead of RPN data + * per channel. + * So actually, we don't really need to look at the nChannel parameter, + * but we pass it to facilitate future upgrades. Furthermore, we only + * support RPN0 (pitch bend sensitivity), RPN1 (fine tuning) and + * RPN2 (coarse tuning). Any other RPNs are rejected. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the RPN controller number + * nControlValue - the value for this control change + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * gsSynthObject.m_RPN0 (or m_RPN1 or m_RPN2) may be updated if the + * proper RPN message sequence is parsed. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMUpdateRPNStateMachine (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); + +/*---------------------------------------------------------------------------- + * VMUpdateStaticChannelParameters() + *---------------------------------------------------------------------------- + * Purpose: + * Update all of the static channel parameters for channels that have had + * a controller change values + * Or if the synth has signalled that all channels must forcibly + * be updated + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * none + * + * Side Effects: + * - psSynthObject->m_sChannel[].m_nStaticGain and m_nStaticPitch + * are updated for channels whose controller values have changed + * or if the synth has signalled that all channels must forcibly + * be updated + *---------------------------------------------------------------------------- +*/ +void VMUpdateStaticChannelParameters (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReleaseAllDeferredNoteOffs() + *---------------------------------------------------------------------------- + * Purpose: + * Call this functin when the sustain flag is presently set but + * we are now transitioning from damper pedal on to + * damper pedal off. This means all notes in this channel + * that received a note off while the damper pedal was on, and + * had their note-off requests deferred, should now proceed to + * the release state. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllDeferredNoteOffs (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMCatchNotesForSustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when the sustain flag is presently clear and + * the damper pedal is off and we are transitioning from damper pedal OFF to + * damper pedal ON. Currently sounding notes should be left + * unchanged. However, we should try to "catch" notes if possible. + * If any notes have levels >= sustain level, catch them, + * otherwise, let them continue to release. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * psVoice->m_sEG1.m_eState = eEnvelopeStateSustainPedal + *---------------------------------------------------------------------------- +*/ +void VMCatchNotesForSustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMUpdateAllNotesAge() + *---------------------------------------------------------------------------- + * Purpose: + * Increment the note age for all voices older than the age of the voice + * that is stopping, effectively making the voices "younger". + * + * Inputs: + * nAge - age of voice that is going away + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * m_nAge for some voices is incremented + *---------------------------------------------------------------------------- +*/ +void VMUpdateAllNotesAge (S_VOICE_MGR *pVoiceMgr, EAS_U16 nAge); + +/*---------------------------------------------------------------------------- + * VMFindRegionIndex() + *---------------------------------------------------------------------------- + * Purpose: + * Find the region index for the given instrument using the midi key number + * and the RPN2 (coarse tuning) value. By using RPN2 as part of the + * region selection process, we reduce the amount a given sample has + * to be transposed by selecting the closest recorded root instead. + * + * Inputs: + * nChannel - current channel for this note + * nKeyNumber - current midi note number + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnRegionIndex - valid only if we returned success + * success if we found the region index number, otherwise + * failure + * + * Side Effects: + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindRegionIndex (S_VOICE_MGR *pVoiceMgr, EAS_U8 channel, EAS_U8 note, EAS_U16 *pRegionIndex); + +/*---------------------------------------------------------------------------- + * VMIncRefCount() + *---------------------------------------------------------------------------- + * Increment reference count for virtual synth + *---------------------------------------------------------------------------- +*/ +void VMIncRefCount (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReset() + *---------------------------------------------------------------------------- + * Purpose: + * We call this routine to start the process of reseting the synth. + * This routine sets a flag for the entire synth indicating that we want + * to reset. + * We also force all voices to mute quickly. + * However, we do not actually perform any synthesis in this routine. That + * is, we do not ramp the voices down from this routine, but instead, we + * let the "regular" synth processing steps take care of adding the ramp + * down samples to the output buffer. After we are sure that all voices + * have completed ramping down, we continue the process of resetting the + * synth (from another routine). + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - set a flag (in gsSynthObject.m_nFlags) indicating synth reset requested. + * - force all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMReset (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_BOOL force); + +/*---------------------------------------------------------------------------- + * VMMuteAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this in an emergency reset situation. + * This forces all voices to mute quickly. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMMuteVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum); +void VMMuteAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMReleaseAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this after we've encountered the end of the Midi file. + * This ensures all voice are either in release (because we received their + * note off already) or forces them to mute quickly. + * We use this as a safety to prevent bad midi files from playing forever. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to release or mute + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMAllNotesOff() + *---------------------------------------------------------------------------- + * Purpose: + * Quickly mute all notes on the given channel. + * + * Inputs: + * nChannel - quickly turn off all notes on this channel + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices on this channel to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMAllNotesOff (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); + +/*---------------------------------------------------------------------------- + * VMDeferredStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Stop the notes that had deferred note-off requests. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None. + * + * Side Effects: + * voices that have had deferred note-off requests are now put into release + * gsSynthObject.m_sVoice[i].m_nFlags has the VOICE_FLAG_DEFER_MIDI_NOTE_OFF + * cleared + *---------------------------------------------------------------------------- +*/ +void VMDeferredStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMSetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * VMGetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * polyphonyCount desired polyphony count + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * VMSetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth polyphony. 0 = no limit (i.e. can use + * all available voices). + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 polyphonyCount); + +/*---------------------------------------------------------------------------- + * VMGetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pSynth pointer to virtual synth + * pPolyphonyCount pointer to variable to receive data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPolyphonyCount); + +/*---------------------------------------------------------------------------- + * VMSetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * priority new priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 priority); + +/*---------------------------------------------------------------------------- + * VMGetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPriority pointer to variable to hold priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPriority); + +/*---------------------------------------------------------------------------- + * VMSetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for this sequence + * + * Inputs: + * nSynthVolume - the desired master volume + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +void VMSetVolume (S_SYNTH *pSynth, EAS_U16 masterVolume); + +/*---------------------------------------------------------------------------- + * VMSetPitchBendRange() + *---------------------------------------------------------------------------- + * Set the pitch bend range for the given channel. + *---------------------------------------------------------------------------- +*/ +void VMSetPitchBendRange (S_SYNTH *pSynth, EAS_INT channel, EAS_I16 pitchBendRange); + +/*---------------------------------------------------------------------------- + * VMSetEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the pointer to the sound library + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalEASLib (S_VOICE_MGR *pVoiceMgr, EAS_SNDLIB_HANDLE pEAS); +EAS_RESULT VMSetEASLib (S_SYNTH *pSynth, EAS_SNDLIB_HANDLE pEAS); + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMSetDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the pointer to the sound library + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalDLSLib (EAS_DATA_HANDLE pEASData, EAS_DLSLIB_HANDLE pDLS); +EAS_RESULT VMSetDLSLib (S_SYNTH *pSynth, EAS_DLSLIB_HANDLE pDLS); +#endif + +/*---------------------------------------------------------------------------- + * VMSetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * transposition - transpose amount (+/-12) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetTranposition (S_SYNTH *pSynth, EAS_I32 transposition); + +/*---------------------------------------------------------------------------- + * VMGetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMGetTranposition (S_SYNTH *pSynth, EAS_I32 *pTransposition); + +/*---------------------------------------------------------------------------- + * VMGetNoteCount() + *---------------------------------------------------------------------------- +* Returns the total note count +*---------------------------------------------------------------------------- +*/ +EAS_I32 VMGetNoteCount (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMRender() + *---------------------------------------------------------------------------- + * Purpose: + * This routine renders a frame of audio + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pVoicesRendered - number of voices rendered this frame + * + * Side Effects: + * sets psMidiObject->m_nMaxWorkloadPerFrame + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMRender (S_VOICE_MGR *pVoiceMgr, EAS_I32 numSamples, EAS_I32 *pMixBuffer, EAS_I32 *pVoicesRendered); + +/*---------------------------------------------------------------------------- + * VMInitWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Clears the workload counter + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitWorkload (S_VOICE_MGR *pVoiceMgr); + +/*---------------------------------------------------------------------------- + * VMSetWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the max workload for a single frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetWorkload (S_VOICE_MGR *pVoiceMgr, EAS_I32 maxWorkLoad); + +/*---------------------------------------------------------------------------- + * VMCheckWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Checks to see if work load has been exceeded on this frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckWorkload (S_VOICE_MGR *pVoiceMgr); + +/*---------------------------------------------------------------------------- + * VMActiveVoices() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the number of active voices in the synthesizer. + * + * Inputs: + * pEASData - pointer to instance data + * + * Outputs: + * Returns the number of active voices + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMActiveVoices (S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMMIDIShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMMIDIShutdown (S_EAS_DATA *pEASData, S_SYNTH *pSynth); + +/*---------------------------------------------------------------------------- + * VMShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMShutdown (S_EAS_DATA *pEASData); + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Register a callback for external audio processing + *---------------------------------------------------------------------------- +*/ +void VMRegExtAudioCallback (S_SYNTH *pSynth, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc); + +/*---------------------------------------------------------------------------- + * VMGetMIDIControllers() + *---------------------------------------------------------------------------- + * Returns the MIDI controller values on the specified channel + *---------------------------------------------------------------------------- +*/ +void VMGetMIDIControllers (S_SYNTH *pSynth, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl); +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * VMStartFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Starts an audio frame + * + * Inputs: + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMStartFrame (S_EAS_DATA *pEASData); + +/*---------------------------------------------------------------------------- + * VMEndFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Stops an audio frame + * + * Inputs: + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMEndFrame (S_EAS_DATA *pEASData); +#endif + +#endif /* #ifdef _EAS_VM_PROTOS_H */ + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_voicemgt.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_voicemgt.c new file mode 100755 index 0000000..fc78805 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_voicemgt.c @@ -0,0 +1,3971 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_voicemgt.c + * + * Contents and purpose: + * Implements the synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 794 $ + * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/* includes */ +#include "eas.h" +#include "eas_data.h" +#include "eas_config.h" +#include "eas_report.h" +#include "eas_midictrl.h" +#include "eas_host.h" +#include "eas_synth_protos.h" +#include "eas_vm_protos.h" + +#ifdef DLS_SYNTHESIZER +#include "eas_mdls.h" +#endif + +// #define _DEBUG_VM + +/* some defines for workload */ +#define WORKLOAD_AMOUNT_SMALL_INCREMENT 5 +#define WORKLOAD_AMOUNT_START_NOTE 10 +#define WORKLOAD_AMOUNT_STOP_NOTE 10 +#define WORKLOAD_AMOUNT_KEY_GROUP 10 +#define WORKLOAD_AMOUNT_POLY_LIMIT 10 + +/* pointer to base sound library */ +extern S_EAS easSoundLib; + +#ifdef TEST_HARNESS +extern S_EAS easTestLib; +EAS_SNDLIB_HANDLE VMGetLibHandle(EAS_INT libNum) +{ + switch (libNum) + { + case 0: + return &easSoundLib; +#ifdef _WT_SYNTH + case 1: + return &easTestLib; +#endif + default: + return NULL; + } +} +#endif + +/* pointer to synthesizer interface(s) */ +#ifdef _WT_SYNTH +extern const S_SYNTH_INTERFACE wtSynth; +#endif + +#ifdef _FM_SYNTH +extern const S_SYNTH_INTERFACE fmSynth; +#endif + +typedef S_SYNTH_INTERFACE *S_SYNTH_INTERFACE_HANDLE; + +/* wavetable on MCU */ +#if defined(EAS_WT_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; + +/* FM on MCU */ +#elif defined(EAS_FM_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &fmSynth; + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_HYBRID_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +const S_SYNTH_INTERFACE *const pSecondarySynth = &fmSynth; + +/* wavetable drums on MCU, wavetable melodic on DSP */ +#elif defined(EAS_SPLIT_WT_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +extern const S_FRAME_INTERFACE wtFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &wtFrameInterface; + +/* wavetable drums on MCU, FM melodic on DSP */ +#elif defined(EAS_SPLIT_HYBRID_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; +const S_SYNTH_INTERFACE *const pSecondarySynth = &fmSynth; +extern const S_FRAME_INTERFACE fmFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &fmFrameInterface; + +/* FM on DSP */ +#elif defined(EAS_SPLIT_FM_SYNTH) +const S_SYNTH_INTERFACE *const pPrimarySynth = &fmSynth; +extern const S_FRAME_INTERFACE fmFrameInterface; +const S_FRAME_INTERFACE *const pFrameInterface = &fmFrameInterface; + +#else +#error "Undefined architecture option" +#endif + +/*---------------------------------------------------------------------------- + * inline functions + *---------------------------------------------------------------------------- +*/ +EAS_INLINE const S_REGION* GetRegionPtr (S_SYNTH *pSynth, EAS_U16 regionIndex) +{ +#if defined(DLS_SYNTHESIZER) + if (regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + return &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK].wtRegion.region; +#endif +#if defined(_HYBRID_SYNTH) + if (regionIndex & FLAG_RGN_IDX_FM_SYNTH) + return &pSynth->pEAS->pFMRegions[regionIndex & REGION_INDEX_MASK].region; + else + return &pSynth->pEAS->pWTRegions[regionIndex].region; +#elif defined(_WT_SYNTH) + return &pSynth->pEAS->pWTRegions[regionIndex].region; +#elif defined(_FM_SYNTH) + return &pSynth->pEAS->pFMRegions[regionIndex].region; +#endif +} + +/*lint -esym(715, voiceNum) used in some implementation */ +EAS_INLINE const S_SYNTH_INTERFACE* GetSynthPtr (EAS_INT voiceNum) +{ +#if defined(_HYBRID_SYNTH) + if (voiceNum < NUM_PRIMARY_VOICES) + return pPrimarySynth; + else + return pSecondarySynth; +#else + return pPrimarySynth; +#endif +} + +EAS_INLINE EAS_INT GetAdjustedVoiceNum (EAS_INT voiceNum) +{ +#if defined(_HYBRID_SYNTH) + if (voiceNum >= NUM_PRIMARY_VOICES) + return voiceNum - NUM_PRIMARY_VOICES; +#endif + return voiceNum; +} + +EAS_INLINE EAS_U8 VSynthToChannel (S_SYNTH *pSynth, EAS_U8 channel) +{ + /*lint -e{734} synthNum is always 0-15 */ + return channel | (pSynth->vSynthNum << 4); +} + +/*---------------------------------------------------------------------------- + * InitVoice() + *---------------------------------------------------------------------------- + * Initialize a synthesizer voice + *---------------------------------------------------------------------------- +*/ +void InitVoice (S_SYNTH_VOICE *pVoice) +{ + pVoice->channel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->nextChannel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->note = pVoice->nextNote = DEFAULT_KEY_NUMBER; + pVoice->velocity = pVoice->nextVelocity = DEFAULT_VELOCITY; + pVoice->regionIndex = DEFAULT_REGION_INDEX; + pVoice->age = DEFAULT_AGE; + pVoice->voiceFlags = DEFAULT_VOICE_FLAGS; + pVoice->voiceState = DEFAULT_VOICE_STATE; +} + +/*---------------------------------------------------------------------------- + * IncVoicePoolCount() + *---------------------------------------------------------------------------- + * Updates the voice pool count when a voice changes state + *---------------------------------------------------------------------------- +*/ +static void IncVoicePoolCount (S_VOICE_MGR *pVoiceMgr, S_SYNTH_VOICE *pVoice) +{ + S_SYNTH *pSynth; + EAS_INT pool; + + /* ignore muting voices */ + if (pVoice->voiceState == eVoiceStateMuting) + return; + + if (pVoice->voiceState == eVoiceStateStolen) + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool; + } + else + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->channel)].pool; + } + + pSynth->poolCount[pool]++; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IncVoicePoolCount: Synth=%d pool=%d\n", pSynth->vSynthNum, pool); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * DecVoicePoolCount() + *---------------------------------------------------------------------------- + * Updates the voice pool count when a voice changes state + *---------------------------------------------------------------------------- +*/ +static void DecVoicePoolCount (S_VOICE_MGR *pVoiceMgr, S_SYNTH_VOICE *pVoice) +{ + S_SYNTH *pSynth; + EAS_INT pool; + + /* ignore muting voices */ + if (pVoice->voiceState == eVoiceStateMuting) + return; + + if (pVoice->voiceState == eVoiceStateStolen) + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool; + } + else + { + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pool = pSynth->channels[GET_CHANNEL(pVoice->channel)].pool; + } + + pSynth->poolCount[pool]--; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "DecVoicePoolCount: Synth=%d pool=%d\n", pSynth->vSynthNum, pool); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * VMInitialize() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitialize (S_EAS_DATA *pEASData) +{ + S_VOICE_MGR *pVoiceMgr; + EAS_INT i; + + /* check Configuration Module for data allocation */ + if (pEASData->staticMemoryModel) + pVoiceMgr = EAS_CMEnumData(EAS_CM_SYNTH_DATA); + else + pVoiceMgr = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_VOICE_MGR)); + if (!pVoiceMgr) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitialize: Failed to allocate synthesizer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pVoiceMgr, 0, sizeof(S_VOICE_MGR)); + + /* initialize non-zero variables */ + pVoiceMgr->pGlobalEAS = (S_EAS*) &easSoundLib; + pVoiceMgr->maxPolyphony = (EAS_U16) MAX_SYNTH_VOICES; + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + pVoiceMgr->maxPolyphonyPrimary = NUM_PRIMARY_VOICES; + pVoiceMgr->maxPolyphonySecondary = NUM_SECONDARY_VOICES; +#endif + + /* set max workload to zero */ + pVoiceMgr->maxWorkLoad = 0; + + /* initialize the voice manager parameters */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + InitVoice(&pVoiceMgr->voices[i]); + + /* initialize the synth */ + /*lint -e{522} return unused at this time */ + pPrimarySynth->pfInitialize(pVoiceMgr); + + /* initialize the off-chip synth */ +#ifdef _HYBRID_SYNTH + /*lint -e{522} return unused at this time */ + pSecondarySynth->pfInitialize(pVoiceMgr); +#endif + + pEASData->pVoiceMgr = pVoiceMgr; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMInitMIDI() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMInitMIDI (S_EAS_DATA *pEASData, S_SYNTH **ppSynth) +{ + EAS_RESULT result; + S_SYNTH *pSynth; + EAS_INT virtualSynthNum; + + *ppSynth = NULL; + + /* static memory model only allows one synth */ + if (pEASData->staticMemoryModel) + { + if (pEASData->pVoiceMgr->pSynth[0] != NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: No virtual synthesizer support for static memory model\n"); */ } + return EAS_ERROR_NO_VIRTUAL_SYNTHESIZER; + } + + /* check Configuration Module for data allocation */ + pSynth = EAS_CMEnumData(EAS_CM_MIDI_DATA); + virtualSynthNum = 0; + } + + /* dynamic memory model */ + else + { + for (virtualSynthNum = 0; virtualSynthNum < MAX_VIRTUAL_SYNTHESIZERS; virtualSynthNum++) + if (pEASData->pVoiceMgr->pSynth[virtualSynthNum] == NULL) + break; + if (virtualSynthNum == MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: Exceeded number of active virtual synthesizers"); */ } + return EAS_ERROR_NO_VIRTUAL_SYNTHESIZER; + } + pSynth = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SYNTH)); + } + + /* make sure we have a valid memory pointer */ + if (pSynth == NULL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: Failed to allocate synthesizer memory\n"); */ } + return EAS_ERROR_MALLOC_FAILED; + } + EAS_HWMemSet(pSynth, 0, sizeof(S_SYNTH)); + + /* set the sound library pointer */ + if ((result = VMSetEASLib(pSynth, pEASData->pVoiceMgr->pGlobalEAS)) != EAS_SUCCESS) + { + VMMIDIShutdown(pEASData, pSynth); + return result; + } + + /* link in DLS bank if downloaded */ +#ifdef DLS_SYNTHESIZER + if (pEASData->pVoiceMgr->pGlobalDLS) + { + pSynth->pDLS = pEASData->pVoiceMgr->pGlobalDLS; + DLSAddRef(pSynth->pDLS); + } +#endif + + /* initialize MIDI state variables */ + pSynth->synthFlags = DEFAULT_SYNTH_FLAGS; + pSynth->masterVolume = DEFAULT_SYNTH_MASTER_VOLUME; + pSynth->refCount = 1; + pSynth->priority = DEFAULT_SYNTH_PRIORITY; + pSynth->poolAlloc[0] = (EAS_U8) pEASData->pVoiceMgr->maxPolyphony; + + VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); + + pSynth->vSynthNum = (EAS_U8) virtualSynthNum; + pEASData->pVoiceMgr->pSynth[virtualSynthNum] = pSynth; + + *ppSynth = pSynth; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMIncRefCount() + *---------------------------------------------------------------------------- + * Increment reference count for virtual synth + *---------------------------------------------------------------------------- +*/ +void VMIncRefCount (S_SYNTH *pSynth) +{ + pSynth->refCount++; +} + +/*---------------------------------------------------------------------------- + * VMReset() + *---------------------------------------------------------------------------- + * Purpose: + * We call this routine to start the process of reseting the synth. + * This routine sets a flag for the entire synth indicating that we want + * to reset. + * We also force all voices to mute quickly. + * However, we do not actually perform any synthesis in this routine. That + * is, we do not ramp the voices down from this routine, but instead, we + * let the "regular" synth processing steps take care of adding the ramp + * down samples to the output buffer. After we are sure that all voices + * have completed ramping down, we continue the process of resetting the + * synth (from another routine). + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * force - force reset even if voices are active + * + * Outputs: + * + * Side Effects: + * - set a flag (in psSynthObject->m_nFlags) indicating synth reset requested. + * - force all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMReset (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_BOOL force) +{ + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReset: request to reset synth. Force = %d\n", force); */ } +#endif + + /* force voices to off state - may cause audio artifacts */ + if (force) + { + pVoiceMgr->activeVoices -= pSynth->numActiveVoices; + pSynth->numActiveVoices = 0; + VMInitializeAllVoices(pVoiceMgr, pSynth->vSynthNum); + } + else + VMMuteAllVoices(pVoiceMgr, pSynth); + + /* don't reset if voices are still playing */ + if (pSynth->numActiveVoices == 0) + { + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReset: complete the reset process\n"); */ } +#endif + + VMInitializeAllChannels(pVoiceMgr, pSynth); + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + pSynth->poolCount[i] = 0; + + /* set polyphony */ + if (pSynth->maxPolyphony < pVoiceMgr->maxPolyphony) + pSynth->poolAlloc[0] = (EAS_U8) pVoiceMgr->maxPolyphony; + else + pSynth->poolAlloc[0] = (EAS_U8) pSynth->maxPolyphony; + + /* clear reset flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_RESET_IS_REQUESTED; + } + + /* handle reset after voices are muted */ + else + pSynth->synthFlags |= SYNTH_FLAG_RESET_IS_REQUESTED; +} + +/*---------------------------------------------------------------------------- + * VMInitializeAllChannels() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllChannels (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + + VMResetControllers(pSynth); + + /* init each channel */ + pChannel = pSynth->channels; + + for (i = 0; i < NUM_SYNTH_CHANNELS; i++, pChannel++) + { + pChannel->channelFlags = DEFAULT_CHANNEL_FLAGS; + pChannel->staticGain = DEFAULT_CHANNEL_STATIC_GAIN; + pChannel->staticPitch = DEFAULT_CHANNEL_STATIC_PITCH; + pChannel->pool = 0; + + /* the drum channel needs a different init */ + if (i == DEFAULT_DRUM_CHANNEL) + { + pChannel->bankNum = DEFAULT_RHYTHM_BANK_NUMBER; + pChannel->channelFlags |= CHANNEL_FLAG_RHYTHM_CHANNEL; + } + else + pChannel->bankNum = DEFAULT_MELODY_BANK_NUMBER; + + VMProgramChange(pVoiceMgr, pSynth, (EAS_U8) i, DEFAULT_SYNTH_PROGRAM_NUMBER); + } + +} + +/*---------------------------------------------------------------------------- + * VMResetControllers() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMResetControllers (S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + + pChannel = pSynth->channels; + + for (i = 0; i < NUM_SYNTH_CHANNELS; i++, pChannel++) + { + pChannel->pitchBend = DEFAULT_PITCH_BEND; + pChannel->modWheel = DEFAULT_MOD_WHEEL; + pChannel->volume = DEFAULT_CHANNEL_VOLUME; + pChannel->pan = DEFAULT_PAN; + pChannel->expression = DEFAULT_EXPRESSION; + +#ifdef _REVERB + pSynth->channels[i].reverbSend = DEFAULT_REVERB_SEND; +#endif + +#ifdef _CHORUS + pSynth->channels[i].chorusSend = DEFAULT_CHORUS_SEND; +#endif + + pChannel->channelPressure = DEFAULT_CHANNEL_PRESSURE; + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + pChannel->pitchBendSensitivity = DEFAULT_PITCH_BEND_SENSITIVITY; + pChannel->finePitch = DEFAULT_FINE_PITCH; + pChannel->coarsePitch = DEFAULT_COARSE_PITCH; + + /* update all voices on this channel */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + } +} + +/*---------------------------------------------------------------------------- + * VMInitializeAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void VMInitializeAllVoices (S_VOICE_MGR *pVoiceMgr, EAS_INT vSynthNum) +{ + EAS_INT i; + + /* initialize the voice manager parameters */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + if (pVoiceMgr->voices[i].voiceState != eVoiceStateStolen) + { + if (GET_VSYNTH(pVoiceMgr->voices[i].channel) == vSynthNum) + InitVoice(&pVoiceMgr->voices[i]); + } + else + { + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == vSynthNum) + InitVoice(&pVoiceMgr->voices[i]); + } + } +} + +/*---------------------------------------------------------------------------- + * VMMuteVoice() + *---------------------------------------------------------------------------- + * Mute the selected voice + *---------------------------------------------------------------------------- +*/ +void VMMuteVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum) +{ + S_SYNTH *pSynth; + S_SYNTH_VOICE *pVoice; + + /* take no action if voice is already muted */ + pVoice = &pVoiceMgr->voices[voiceNum]; + if ((pVoice->voiceState == eVoiceStateMuting) || (pVoice->voiceState == eVoiceStateFree)) + return; + + /* one less voice in pool */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + GetSynthPtr((int)voiceNum)->pfMuteVoice(pVoiceMgr, pSynth, pVoice, GetAdjustedVoiceNum((int)voiceNum)); + pVoice->voiceState = eVoiceStateMuting; + +} + +/*---------------------------------------------------------------------------- + * VMReleaseVoice() + *---------------------------------------------------------------------------- + * Release the selected voice + *---------------------------------------------------------------------------- +*/ +void VMReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 voiceNum) +{ + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + + /* take no action if voice is already free, muting, or releasing */ + if (( pVoice->voiceState == eVoiceStateMuting) || + (pVoice->voiceState == eVoiceStateFree) || + (pVoice->voiceState == eVoiceStateRelease)) + return; + + /* stolen voices should just be muted */ + if (pVoice->voiceState == eVoiceStateStolen) + VMMuteVoice(pVoiceMgr, voiceNum); + + /* release this voice */ + GetSynthPtr((int)voiceNum)->pfReleaseVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum((int)voiceNum)); + pVoice->voiceState = eVoiceStateRelease; +} + +/*---------------------------------------------------------------------------- + * VMInitMIPTable() + *---------------------------------------------------------------------------- + * Initialize the SP-MIDI MIP table in preparation for receiving MIP message + *---------------------------------------------------------------------------- +*/ +void VMInitMIPTable (S_SYNTH *pSynth) +{ + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMInitMIPTable\n"); */ } +#endif + + /* clear SP-MIDI flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_SP_MIDI_ON; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + pSynth->channels[i].pool = 0; + pSynth->channels[i].mip = 0; + } +} + +/*---------------------------------------------------------------------------- + * VMSetMIPEntry() + *---------------------------------------------------------------------------- + * Sets the priority and MIP level for a MIDI channel + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMSetMIPEntry (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 priority, EAS_U8 mip) +{ + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMSetMIPEntry: channel=%d, priority=%d, MIP=%d\n", channel, priority, mip); */ } +#endif + + /* save data for use by MIP message processing */ + if (priority < NUM_SYNTH_CHANNELS) + { + pSynth->channels[channel].pool = priority; + pSynth->channels[channel].mip = mip; + } +} + +/*---------------------------------------------------------------------------- + * VMMIPUpdateChannelMuting() + *---------------------------------------------------------------------------- + * This routine is called after an SP-MIDI message is received and + * any time the allocated polyphony changes. It mutes or unmutes + * channels based on polyphony. + *---------------------------------------------------------------------------- +*/ +void VMMIPUpdateChannelMuting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + EAS_INT maxPolyphony; + EAS_INT channel; + EAS_INT vSynthNum; + EAS_INT pool; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateMIPTable\n"); */ } +#endif + + /* determine max polyphony */ + if (pSynth->maxPolyphony) + maxPolyphony = pSynth->maxPolyphony; + else + maxPolyphony = pVoiceMgr->maxPolyphony; + + /* process channels */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + + /* channel must be in MIP message and must meet allocation target */ + if ((pSynth->channels[i].mip != 0) && (pSynth->channels[i].mip <= maxPolyphony)) + pSynth->channels[i].channelFlags &= ~CHANNEL_FLAG_MUTE; + else + pSynth->channels[i].channelFlags |= CHANNEL_FLAG_MUTE; + + /* reset voice pool count */ + pSynth->poolCount[i] = 0; + } + + /* mute any voices on muted channels, and count unmuted voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + /* ignore free voices */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateFree) + continue; + + /* get channel and virtual synth */ + if (pVoiceMgr->voices[i].voiceState != eVoiceStateStolen) + { + vSynthNum = GET_VSYNTH(pVoiceMgr->voices[i].channel); + channel = GET_CHANNEL(pVoiceMgr->voices[i].channel); + } + else + { + vSynthNum = GET_VSYNTH(pVoiceMgr->voices[i].nextChannel); + channel = GET_CHANNEL(pVoiceMgr->voices[i].nextChannel); + } + + /* ignore voices on other synths */ + if (vSynthNum != pSynth->vSynthNum) + continue; + + /* count voices */ + pool = pSynth->channels[channel].pool; + + /* deal with muted channels */ + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_MUTE) + { + /* mute stolen voices scheduled to play on this channel */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateStolen) + pVoiceMgr->voices[i].voiceState = eVoiceStateMuting; + + /* release voices that aren't already muting */ + else if (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting) + { + VMReleaseVoice(pVoiceMgr, pSynth, i); + pSynth->poolCount[pool]++; + } + } + + /* not muted, count this voice */ + else + pSynth->poolCount[pool]++; + } +} + +/*---------------------------------------------------------------------------- + * VMUpdateMIPTable() + *---------------------------------------------------------------------------- + * This routine is called at the end of the SysEx message to allow + * the Voice Manager to complete the initialization of the MIP + * table. It assigns channels to the appropriate voice pool based + * on the MIP setting and calculates the voices allocated for each + * pool. + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMUpdateMIPTable (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT i; + EAS_INT currentMIP; + EAS_INT currentPool; + EAS_INT priority[NUM_SYNTH_CHANNELS]; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateMIPTable\n"); */ } +#endif + + /* set SP-MIDI flag */ + pSynth->synthFlags |= SYNTH_FLAG_SP_MIDI_ON; + + /* sort channels into priority order */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + priority[i] = -1; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + if (pSynth->channels[i].pool != DEFAULT_SP_MIDI_PRIORITY) + priority[pSynth->channels[i].pool] = i; + } + + /* process channels in priority order */ + currentMIP = 0; + currentPool = -1; + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + /* stop when we run out of channels */ + if (priority[i] == -1) + break; + + pChannel = &pSynth->channels[priority[i]]; + + /* when 2 or more channels have the same MIP setting, they + * share a common voice pool + */ + if (pChannel->mip == currentMIP) + pChannel->pool = (EAS_U8) currentPool; + + /* new voice pool */ + else + { + currentPool++; + pSynth->poolAlloc[currentPool] = (EAS_U8) (pChannel->mip - currentMIP); + currentMIP = pChannel->mip; + } + } + + /* set SP-MIDI flag */ + pSynth->synthFlags |= SYNTH_FLAG_SP_MIDI_ON; + + /* update channel muting */ + VMMIPUpdateChannelMuting (pVoiceMgr, pSynth); +} + +/*---------------------------------------------------------------------------- + * VMMuteAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this in an emergency reset situation. + * This forces all voices to mute quickly. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMMuteAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMMuteAllVoices: about to mute all voices!!\n"); */ } +#endif + + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + /* for stolen voices, check new channel */ + if (pVoiceMgr->voices[i].voiceState == eVoiceStateStolen) + { + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == pSynth->vSynthNum) + VMMuteVoice(pVoiceMgr, i); + } + + else if (pSynth->vSynthNum == GET_VSYNTH(pVoiceMgr->voices[i].channel)) + VMMuteVoice(pVoiceMgr, i); + } +} + +/*---------------------------------------------------------------------------- + * VMReleaseAllVoices() + *---------------------------------------------------------------------------- + * Purpose: + * We call this after we've encountered the end of the Midi file. + * This ensures all voices are either in release (because we received their + * note off already) or forces them to mute quickly. + * We use this as a safety to prevent bad midi files from playing forever. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices to update their envelope states to release or mute + * + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT i; + + /* release sustain pedal on all channels */ + for (i = 0; i < NUM_SYNTH_CHANNELS; i++) + { + if (pSynth->channels[ i ].channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + VMReleaseAllDeferredNoteOffs(pVoiceMgr, pSynth, (EAS_U8) i); + pSynth->channels[i].channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + } + } + + /* release all voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + switch (pVoiceMgr->voices[i].voiceState) + { + case eVoiceStateStart: + case eVoiceStatePlay: + /* only release voices on this synth */ + if (GET_VSYNTH(pVoiceMgr->voices[i].channel) == pSynth->vSynthNum) + VMReleaseVoice(pVoiceMgr, pSynth, i); + break; + + case eVoiceStateStolen: + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == pSynth->vSynthNum) + VMMuteVoice(pVoiceMgr, i); + break; + + case eVoiceStateFree: + case eVoiceStateRelease: + case eVoiceStateMuting: + break; + + case eVoiceStateInvalid: + default: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReleaseAllVoices: error, %d is an unrecognized state\n", + pVoiceMgr->voices[i].voiceState); */ } +#endif + break; + } + } +} + +/*---------------------------------------------------------------------------- + * VMAllNotesOff() + *---------------------------------------------------------------------------- + * Purpose: + * Quickly mute all notes on the given channel. + * + * Inputs: + * nChannel - quickly turn off all notes on this channel + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - forces all voices on this channel to update their envelope states to mute + * + *---------------------------------------------------------------------------- +*/ +void VMAllNotesOff (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + EAS_INT voiceNum; + S_SYNTH_VOICE *pVoice; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMAllNotesOff: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif + + /* increment workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + + /* check each voice */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + pVoice = &pVoiceMgr->voices[voiceNum]; + if (pVoice->voiceState != eVoiceStateFree) + { + if (((pVoice->voiceState != eVoiceStateStolen) && (channel == pVoice->channel)) || + ((pVoice->voiceState == eVoiceStateStolen) && (channel == pVoice->nextChannel))) + { + /* this voice is assigned to the requested channel */ + GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pSynth, pVoice, GetAdjustedVoiceNum(voiceNum)); + pVoice->voiceState = eVoiceStateMuting; + } + } + } +} + +/*---------------------------------------------------------------------------- + * VMDeferredStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Stop the notes that had deferred note-off requests. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None. + * + * Side Effects: + * voices that have had deferred note-off requests are now put into release + * psSynthObject->m_sVoice[i].m_nFlags has the VOICE_FLAG_DEFER_MIDI_NOTE_OFF + * cleared + *---------------------------------------------------------------------------- +*/ +void VMDeferredStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT voiceNum; + EAS_INT channel; + EAS_BOOL deferredNoteOff; + + deferredNoteOff = EAS_FALSE; + + /* check each voice to see if it requires a deferred note off */ + for (voiceNum=0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_DEFER_MIDI_NOTE_OFF) + { + /* check if this voice was stolen */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) + { + /* + This voice was stolen, AND it also has a deferred note-off. + The stolen note must be completely ramped down at this point. + The note that caused the stealing to occur, however, must + have received a note-off request before the note that caused + stealing ever had a chance to even start. We want to give + the note that caused the stealing a chance to play, so we + start it on the next update interval, and we defer sending + the note-off request until the subsequent update interval. + So do not send the note-off request for this voice because + this voice was stolen and should have completed ramping down, + Also, do not clear the global flag nor this voice's flag + because we must indicate that the subsequent update interval, + after the note that caused stealing has started, should + then send the deferred note-off request. + */ + deferredNoteOff = EAS_TRUE; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: defer request to stop voice %d (channel=%d note=%d) - voice not started\n", + voiceNum, + pVoiceMgr->voices[voiceNum].nextChannel, + pVoiceMgr->voices[voiceNum].note); */ } + + /* sanity check: this stolen voice better be ramped to zero */ + if (0 != pVoiceMgr->voices[voiceNum].gain) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: warning, this voice did not complete its ramp to zero\n"); */ } + } +#endif // #ifdef _DEBUG_VM + + } + else + { + /* clear the flag using exor */ + pVoiceMgr->voices[voiceNum].voiceFlags ^= + VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: Stop voice %d (channel=%d note=%d)\n", + voiceNum, + pVoiceMgr->voices[voiceNum].nextChannel, + pVoiceMgr->voices[voiceNum].note); */ } +#endif + + channel = pVoiceMgr->voices[voiceNum].channel & 15; + + /* check if sustain pedal is on */ + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + GetSynthPtr(voiceNum)->pfSustainPedal(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], &pSynth->channels[channel], GetAdjustedVoiceNum(voiceNum)); + } + + /* release this voice */ + else + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + } + + } + + } + + /* clear the deferred note-off flag, unless there's another one pending */ + if (deferredNoteOff == EAS_FALSE) + pSynth->synthFlags ^= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; +} + +/*---------------------------------------------------------------------------- + * VMReleaseAllDeferredNoteOffs() + *---------------------------------------------------------------------------- + * Purpose: + * Call this functin when the sustain flag is presently set but + * we are now transitioning from damper pedal on to + * damper pedal off. This means all notes in this channel + * that received a note off while the damper pedal was on, and + * had their note-off requests deferred, should now proceed to + * the release state. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * any voice with deferred note offs on this channel are updated such that + * pVoice->m_sEG1.m_eState = eEnvelopeStateRelease + * pVoice->m_sEG1.m_nIncrement = release increment + * pVoice->m_nFlags = clear the deferred note off flag + *---------------------------------------------------------------------------- +*/ +void VMReleaseAllDeferredNoteOffs (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + S_SYNTH_VOICE *pVoice; + EAS_INT voiceNum; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReleaseAllDeferredNoteOffs: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif /* #ifdef _DEBUG_VM */ + + /* increment workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + + /* find all the voices assigned to this channel */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + pVoice = &pVoiceMgr->voices[voiceNum]; + if (channel == pVoice->channel) + { + + /* does this voice have a deferred note off? */ + if (pVoice->voiceFlags & VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF) + { + /* release voice */ + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + /* use exor to flip bit, clear the flag */ + pVoice->voiceFlags &= ~VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + + } + + } + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMCatchNotesForSustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when the sustain flag is presently clear and + * the damper pedal is off and we are transitioning from damper pedal OFF to + * damper pedal ON. Currently sounding notes should be left + * unchanged. However, we should try to "catch" notes if possible. + * If any notes are in release and have levels >= sustain level, catch them, + * otherwise, let them continue to release. + * + * Inputs: + * nChannel - this channel has its sustain pedal transitioning from on to off + * psEASData - pointer to overall EAS data structure + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +void VMCatchNotesForSustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + EAS_INT voiceNum; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCatchNotesForSustainPedal: error, %d invalid channel number\n", + channel); */ } + return; + } +#endif + + pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; + channel = VSynthToChannel(pSynth, channel); + + /* find all the voices assigned to this channel */ + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (channel == pVoiceMgr->voices[voiceNum].channel) + { + if (eVoiceStateRelease == pVoiceMgr->voices[voiceNum].voiceState) + GetSynthPtr(voiceNum)->pfSustainPedal(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], &pSynth->channels[channel], GetAdjustedVoiceNum(voiceNum)); + } + } +} + +/*---------------------------------------------------------------------------- + * VMUpdateAllNotesAge() + *---------------------------------------------------------------------------- + * Purpose: + * Increment the note age for all of the active voices. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * m_nAge for all voices is incremented + *---------------------------------------------------------------------------- +*/ +void VMUpdateAllNotesAge (S_VOICE_MGR *pVoiceMgr, EAS_U16 age) +{ + EAS_INT i; + + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + if (age - pVoiceMgr->voices[i].age > 0) + pVoiceMgr->voices[i].age++; + } +} + +/*---------------------------------------------------------------------------- + * VMStolenVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being stolen. Sets the parameters so that the + * voice will begin playing the new sound on the next buffer. + * + * Inputs: + * pVoice - pointer to voice to steal + * nChannel - the channel to start a note on + * nKeyNumber - the key number to start a note for + * nNoteVelocity - the key velocity from this note + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static void VMStolenVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 voiceNum, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex) +{ + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + + /* one less voice in old pool */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + /* mute the sound that is currently playing */ + GetSynthPtr((int)voiceNum)->pfMuteVoice(pVoiceMgr, pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)], &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum((int)voiceNum)); + pVoice->voiceState = eVoiceStateStolen; + + /* set new note data */ + pVoice->nextChannel = VSynthToChannel(pSynth, channel); + pVoice->nextNote = note; + pVoice->nextVelocity = velocity; + pVoice->nextRegionIndex = regionIndex; + + /* one more voice in new pool */ + IncVoicePoolCount(pVoiceMgr, pVoice); + + /* clear the deferred flags */ + pVoice->voiceFlags &= + ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | + VOICE_FLAG_DEFER_MUTE | + VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF); + + /* all notes older than this one get "younger" */ + VMUpdateAllNotesAge(pVoiceMgr, pVoice->age); + + /* assign current age to this note and increment for the next note */ + pVoice->age = pVoiceMgr->age++; +} + +/*---------------------------------------------------------------------------- + * VMFreeVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is done playing and being returned to the + * pool of free voices + * + * Inputs: + * pVoice - pointer to voice to free + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static void VMFreeVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice) +{ + + /* do nothing if voice is already free */ + if (pVoice->voiceState == eVoiceStateFree) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMFreeVoice: Attempt to free voice that is already free\n"); */ } + return; + } + + /* if we jump directly to free without passing muting stage, + * we need to adjust the voice count */ + DecVoicePoolCount(pVoiceMgr, pVoice); + + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMFreeVoice: Synth=%d\n", pSynth->vSynthNum); */ } +#endif + + /* return to free voice pool */ + pVoiceMgr->activeVoices--; + pSynth->numActiveVoices--; + InitVoice(pVoice); + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMFreeVoice: free voice %d\n", pVoice - pVoiceMgr->voices); */ } +#endif + + /* all notes older than this one get "younger" */ + VMUpdateAllNotesAge(pVoiceMgr, pVoice->age); + } + +/*---------------------------------------------------------------------------- + * VMRetargetStolenVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice has been stolen and needs to be initalized with + * the paramters of its new note. + * + * Inputs: + * pVoice - pointer to voice to retarget + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL VMRetargetStolenVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum) +{ + EAS_U8 flags; + S_SYNTH_CHANNEL *pMIDIChannel; + S_SYNTH_VOICE *pVoice; + S_SYNTH *pSynth; + S_SYNTH *pNextSynth; + + /* establish some pointers */ + pVoice = &pVoiceMgr->voices[voiceNum]; + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + pMIDIChannel = &pSynth->channels[pVoice->channel & 15]; + pNextSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; + +#ifdef _DEBUG_VM +{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetStolenVoice: retargeting stolen voice %d on channel %d\n", + voiceNum, pVoice->channel); */ } + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\to channel %d note: %d velocity: %d\n", + pVoice->nextChannel, pVoice->nextNote, pVoice->nextVelocity); */ } +#endif + + /* make sure new channel hasn't been muted by SP-MIDI since the voice was stolen */ + if ((pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) && + (pMIDIChannel->channelFlags & CHANNEL_FLAG_MUTE)) + { + VMFreeVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum]); + return EAS_FALSE; + } + + /* if assigned to a new synth, correct the active voice count */ + if (pVoice->channel != pVoice->nextChannel) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetStolenVoice: Note assigned to different virtual synth, adjusting numActiveVoices\n"); */ } +#endif + pSynth->numActiveVoices--; + pNextSynth->numActiveVoices++; + } + + /* assign new channel number, and increase channel voice count */ + pVoice->channel = pVoice->nextChannel; + pMIDIChannel = &pNextSynth->channels[pVoice->channel & 15]; + + /* assign other data */ + pVoice->note = pVoice->nextNote; + pVoice->velocity = pVoice->nextVelocity; + pVoice->nextChannel = UNASSIGNED_SYNTH_CHANNEL; + pVoice->regionIndex = pVoice->nextRegionIndex; + + /* save the flags, pfStartVoice() will clear them */ + flags = pVoice->voiceFlags; + + /* keep track of the note-start related workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_START_NOTE; + + /* setup the voice parameters */ + pVoice->voiceState = eVoiceStateStart; + + /*lint -e{522} return not used at this time */ + GetSynthPtr((int)voiceNum)->pfStartVoice(pVoiceMgr, pNextSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum((int)voiceNum), pVoice->regionIndex); + + /* did the new note already receive a MIDI note-off request? */ + if (flags & VOICE_FLAG_DEFER_MIDI_NOTE_OFF) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetVoice: stolen note note-off request deferred\n"); */ } +#endif + pVoice->voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + pNextSynth->synthFlags |= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; + } + + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * VMCheckKeyGroup() + *---------------------------------------------------------------------------- + * If the note that we've been asked to start is in the same key group as + * any currently playing notes, then we must shut down the currently playing + * note in the same key group + *---------------------------------------------------------------------------- +*/ +void VMCheckKeyGroup (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U16 keyGroup, EAS_U8 channel) +{ + const S_REGION *pRegion; + EAS_INT voiceNum; + + /* increment frame workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_KEY_GROUP; + + /* need to check all voices in case this is a layered sound */ + channel = VSynthToChannel(pSynth, channel); + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateStolen) + { + /* voice must be on the same channel */ + if (channel == pVoiceMgr->voices[voiceNum].channel) + { + /* check key group */ + pRegion = GetRegionPtr(pSynth, pVoiceMgr->voices[voiceNum].regionIndex); + if (keyGroup == (pRegion->keyGroupAndFlags & 0x0f00)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckKeyGroup: voice %d matches key group %d\n", voiceNum, keyGroup >> 8); */ } +#endif + + /* if this voice was just started, set it to mute on the next buffer */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MUTE; + + /* mute immediately */ + else + VMMuteVoice(pVoiceMgr, voiceNum); + } + } + } + + /* for stolen voice, check new values */ + else + { + /* voice must be on the same channel */ + if (channel == pVoiceMgr->voices[voiceNum].nextChannel) + { + /* check key group */ + pRegion = GetRegionPtr(pSynth, pVoiceMgr->voices[voiceNum].nextRegionIndex); + if (keyGroup == (pRegion->keyGroupAndFlags & 0x0f00)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckKeyGroup: voice %d matches key group %d\n", voiceNum, keyGroup >> 8); */ } +#endif + + /* if this voice was just started, set it to mute on the next buffer */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MUTE; + + /* mute immediately */ + else + VMMuteVoice(pVoiceMgr, voiceNum); + } + } + + } + } +} + +/*---------------------------------------------------------------------------- + * VMCheckPolyphonyLimiting() + *---------------------------------------------------------------------------- + * Purpose: + * We only play at most 2 of the same note on a MIDI channel. + * E.g., if we are asked to start note 36, and there are already two voices + * that are playing note 36, then we must steal the voice playing + * the oldest note 36 and use that stolen voice to play the new note 36. + * + * Inputs: + * nChannel - synth channel that wants to start a new note + * nKeyNumber - new note's midi note number + * nNoteVelocity - new note's velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pbVoiceStealingRequired - flag: this routine sets true if we needed to + * steal a voice + * * + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber may be assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity may be assigned + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckPolyphonyLimiting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + EAS_INT voiceNum; + EAS_INT oldestVoiceNum; + EAS_INT numVoicesPlayingNote; + EAS_U16 age; + EAS_U16 oldestNoteAge; + + pVoiceMgr->workload += WORKLOAD_AMOUNT_POLY_LIMIT; + + numVoicesPlayingNote = 0; + oldestVoiceNum = MAX_SYNTH_VOICES; + oldestNoteAge = 0; + channel = VSynthToChannel(pSynth, channel); + + /* examine each voice on this channel playing this note */ + for (voiceNum = (int)lowVoice; voiceNum <= highVoice; voiceNum++) + { + /* check stolen notes separately */ + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateStolen) + { + + /* same channel and note ? */ + if ((channel == pVoiceMgr->voices[voiceNum].channel) && (note == pVoiceMgr->voices[voiceNum].note)) + { + numVoicesPlayingNote++; + age = pVoiceMgr->age - pVoiceMgr->voices[voiceNum].age; + + /* is this the oldest voice for this note? */ + if (age >= oldestNoteAge) + { + oldestNoteAge = age; + oldestVoiceNum = voiceNum; + } + } + } + + /* handle stolen voices */ + else + { + /* same channel and note ? */ + if ((channel == pVoiceMgr->voices[voiceNum].nextChannel) && (note == pVoiceMgr->voices[voiceNum].nextNote)) + { + numVoicesPlayingNote++; + } + } + } + + /* check to see if we exceeded poly limit */ + if (numVoicesPlayingNote < DEFAULT_CHANNEL_POLYPHONY_LIMIT) + return EAS_FALSE; + + /* make sure we have a voice to steal */ + if (oldestVoiceNum != MAX_SYNTH_VOICES) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckPolyphonyLimiting: voice %d has the oldest note\n", oldestVoiceNum); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMCheckPolyphonyLimiting: polyphony limiting requires shutting down note %d \n", pVoiceMgr->voices[oldestVoiceNum].note); */ } +#endif + VMStolenVoice(pVoiceMgr, pSynth, oldestVoiceNum, channel, note, velocity, regionIndex); + return EAS_TRUE; + } + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMCheckPolyphonyLimiting: No oldest voice to steal\n"); */ } +#endif + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * VMStartVoice() + *---------------------------------------------------------------------------- + * Starts a voice given a region index + *---------------------------------------------------------------------------- +*/ +void VMStartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex) +{ + const S_REGION *pRegion; + S_SYNTH_CHANNEL *pChannel; + EAS_INT voiceNum; + EAS_INT maxSynthPoly; + EAS_I32 lowVoice, highVoice; + EAS_U16 keyGroup; + + pChannel = &pSynth->channels[channel]; + pRegion = GetRegionPtr(pSynth, regionIndex); + + /* select correct synth */ +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + { +#ifdef EAS_SPLIT_WT_SYNTH + if ((pRegion->keyGroupAndFlags & REGION_FLAG_OFF_CHIP) == 0) +#else + if ((regionIndex & FLAG_RGN_IDX_FM_SYNTH) == 0) +#endif + { + lowVoice = 0; + highVoice = NUM_PRIMARY_VOICES - 1; + } + else + { + lowVoice = NUM_PRIMARY_VOICES; + highVoice = MAX_SYNTH_VOICES - 1; + } + } +#else + lowVoice = 0; + highVoice = MAX_SYNTH_VOICES - 1; +#endif + + /* keep track of the note-start related workload */ + pVoiceMgr->workload+= WORKLOAD_AMOUNT_START_NOTE; + + /* other voices in pool, check for key group and poly limiting */ + if (pSynth->poolCount[pChannel->pool] != 0) + { + + /* check for key group exclusivity */ + keyGroup = pRegion->keyGroupAndFlags & 0x0f00; + if (keyGroup!= 0) + VMCheckKeyGroup(pVoiceMgr, pSynth, keyGroup, channel); + + /* check polyphony limit and steal a voice if necessary */ + if ((pRegion->keyGroupAndFlags & REGION_FLAG_NON_SELF_EXCLUSIVE) == 0) + { + if (VMCheckPolyphonyLimiting(pVoiceMgr, pSynth, channel, note, velocity, regionIndex, lowVoice, highVoice) == EAS_TRUE) + return; + } + } + + /* check max poly allocation */ + if ((pSynth->maxPolyphony == 0) || (pVoiceMgr->maxPolyphony < pSynth->maxPolyphony)) + maxSynthPoly = pVoiceMgr->maxPolyphony; + else + maxSynthPoly = pSynth->maxPolyphony; + + /* any free voices? */ + if ((pVoiceMgr->activeVoices < pVoiceMgr->maxPolyphony) && + (pSynth->numActiveVoices < maxSynthPoly) && + (EAS_SUCCESS == VMFindAvailableVoice(pVoiceMgr, &voiceNum, lowVoice, highVoice))) + { + S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMStartVoice: Synth=%d\n", pSynth->vSynthNum); */ } +#endif + + /* bump voice counts */ + pVoiceMgr->activeVoices++; + pSynth->numActiveVoices++; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStartVoice: voice %d assigned to channel %d note %d velocity %d\n", + voiceNum, channel, note, velocity); */ } +#endif + + /* save parameters */ + pVoiceMgr->voices[voiceNum].channel = VSynthToChannel(pSynth, channel); + pVoiceMgr->voices[voiceNum].note = note; + pVoiceMgr->voices[voiceNum].velocity = velocity; + + /* establish note age for voice stealing */ + pVoiceMgr->voices[voiceNum].age = pVoiceMgr->age++; + + /* setup the synthesis parameters */ + pVoiceMgr->voices[voiceNum].voiceState = eVoiceStateStart; + + /* increment voice pool count */ + IncVoicePoolCount(pVoiceMgr, pVoice); + + /* start voice on correct synth */ + /*lint -e{522} return not used at this time */ + GetSynthPtr(voiceNum)->pfStartVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), regionIndex); + return; + } + + /* no free voices, we have to steal one using appropriate algorithm */ + if (VMStealVoice(pVoiceMgr, pSynth, &voiceNum, channel, note, lowVoice, highVoice) == EAS_SUCCESS) + VMStolenVoice(pVoiceMgr, pSynth, voiceNum, channel, note, velocity, regionIndex); + +#ifdef _DEBUG_VM + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStartVoice: Could not steal a voice for channel %d note %d velocity %d\n", + channel, note, velocity); */ } + } +#endif + + return; +} + +/*---------------------------------------------------------------------------- + * VMStartNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to play the requested note on the requested + * channel if possible. + * + * Inputs: + * nChannel - the channel to start a note on + * nKeyNumber - the key number to start a note for + * nNoteVelocity - the key velocity from this note + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_nNumActiveVoices may be incremented + * psSynthObject->m_sVoice[free voice num].m_nSynthChannel may be assigned + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber is assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +void VMStartNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_U16 regionIndex; + EAS_I16 adjustedNote; + + /* bump note count */ + pSynth->totalNoteCount++; + + pChannel = &pSynth->channels[channel]; + + /* check channel mute */ + if (pChannel->channelFlags & CHANNEL_FLAG_MUTE) + return; + +#ifdef EXTERNAL_AUDIO + /* pass event to external audio when requested */ + if ((pChannel->channelFlags & CHANNEL_FLAG_EXTERNAL_AUDIO) && (pSynth->cbEventFunc != NULL)) + { + S_EXT_AUDIO_EVENT event; + event.channel = channel; + event.note = note; + event.velocity = velocity; + event.noteOn = EAS_TRUE; + if (pSynth->cbEventFunc(pSynth->pExtAudioInstData, &event)) + return; + } +#endif + + /* start search at first region */ + regionIndex = pChannel->regionIndex; + + /* handle transposition */ + adjustedNote = note; + if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) + adjustedNote += pChannel->coarsePitch; + else + adjustedNote += pChannel->coarsePitch + pSynth->globalTranspose; + + /* limit adjusted key number so it does not wraparound, over/underflow */ + if (adjustedNote < 0) + { + adjustedNote = 0; + } + else if (adjustedNote > 127) + { + adjustedNote = 127; + } + +#if defined(DLS_SYNTHESIZER) + if (regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + /* DLS voice */ + for (;;) + { + /*lint -e{740,826} cast OK, we know this is actually a DLS region */ + const S_DLS_REGION *pDLSRegion = (S_DLS_REGION*) GetRegionPtr(pSynth, regionIndex); + + /* check key against this region's key and velocity range */ + if (((adjustedNote >= pDLSRegion->wtRegion.region.rangeLow) && (adjustedNote <= pDLSRegion->wtRegion.region.rangeHigh)) && + ((velocity >= pDLSRegion->velLow) && (velocity <= pDLSRegion->velHigh))) + { + VMStartVoice(pVoiceMgr, pSynth, channel, note, velocity, regionIndex); + } + + /* last region in program? */ + if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_LAST_REGION) + break; + + /* advance to next region */ + regionIndex++; + } + } + else +#endif + + /* braces here for #if clause */ + { + /* EAS voice */ + for (;;) + { + const S_REGION *pRegion = GetRegionPtr(pSynth, regionIndex); + + /* check key against this region's keyrange */ + if ((adjustedNote >= pRegion->rangeLow) && (adjustedNote <= pRegion->rangeHigh)) + { + VMStartVoice(pVoiceMgr, pSynth, channel, note, velocity, regionIndex); + break; + } + + /* last region in program? */ + if (pRegion->keyGroupAndFlags & REGION_FLAG_LAST_REGION) + break; + + /* advance to next region */ + regionIndex++; + } + } +} + +/*---------------------------------------------------------------------------- + * VMStopNote() + *---------------------------------------------------------------------------- + * Purpose: + * Update the synth's state to end the requested note on the requested + * channel. + * + * Inputs: + * nChannel - the channel to stop a note on + * nKeyNumber - the key number for this note off + * nNoteVelocity - the note-off velocity + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sVoice[free voice num].m_nSynthChannel may be assigned + * psSynthObject->m_sVoice[free voice num].m_nKeyNumber is assigned + * psSynthObject->m_sVoice[free voice num].m_nVelocity is assigned + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, velocity) reserved for future use */ +void VMStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_INT voiceNum; + + pChannel = &(pSynth->channels[channel]); + +#ifdef EXTERNAL_AUDIO + if ((pChannel->channelFlags & CHANNEL_FLAG_EXTERNAL_AUDIO) && (pSynth->cbEventFunc != NULL)) + { + S_EXT_AUDIO_EVENT event; + event.channel = channel; + event.note = note; + event.velocity = velocity; + event.noteOn = EAS_FALSE; + if (pSynth->cbEventFunc(pSynth->pExtAudioInstData, &event)) + return; + } +#endif + + /* keep track of the note-start workload */ + pVoiceMgr->workload += WORKLOAD_AMOUNT_STOP_NOTE; + + channel = VSynthToChannel(pSynth, channel); + + for (voiceNum=0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + /* stolen notes are handled separately */ + if (eVoiceStateStolen != pVoiceMgr->voices[voiceNum].voiceState) + { + + /* channel and key number must match */ + if ((channel == pVoiceMgr->voices[voiceNum].channel) && (note == pVoiceMgr->voices[voiceNum].note)) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStopNote: voice %d channel %d note %d\n", + voiceNum, channel, note); */ } +#endif + + /* if sustain pedal is down, set deferred note-off flag */ + if (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + { + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + continue; + } + + /* if this note just started, wait before we stop it */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) + { +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tDeferred: Not started yet\n"); */ } +#endif + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + pSynth->synthFlags |= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; + } + + /* release voice */ + else + VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); + + } + } + + /* process stolen notes, new channel and key number must match */ + else if ((channel == pVoiceMgr->voices[voiceNum].nextChannel) && (note == pVoiceMgr->voices[voiceNum].nextNote)) + { + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStopNote: voice %d channel %d note %d\n\tDeferred: Stolen voice\n", + voiceNum, channel, note); */ } +#endif + pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; + } + } +} + +/*---------------------------------------------------------------------------- + * VMFindAvailableVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Find an available voice and return the voice number if available. + * + * Inputs: + * pnVoiceNumber - really an output, returns the voice number found + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * success - if there is an available voice + * failure - otherwise + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMFindAvailableVoice (S_VOICE_MGR *pVoiceMgr, EAS_INT *pVoiceNumber, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + EAS_INT voiceNum; + + /* Check each voice to see if it has been assigned to a synth channel */ + for (voiceNum = (int)lowVoice; voiceNum <= highVoice; voiceNum++) + { + /* check if this voice has been assigned to a synth channel */ + if ( pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateFree) + { + *pVoiceNumber = voiceNum; /* this voice is available */ + return EAS_SUCCESS; + } + } + + /* if we reach here, we have not found a free voice */ + *pVoiceNumber = UNASSIGNED_SYNTH_VOICE; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMFindAvailableVoice: error, could not find an available voice\n"); */ } +#endif + return EAS_FAILURE; +} + +/*---------------------------------------------------------------------------- + * VMStealVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Steal a voice and return the voice number + * + * Stealing algorithm: steal the best choice with minimal work, taking into + * account SP-Midi channel priorities and polyphony allocation. + * + * In one pass through all the voices, figure out which voice to steal + * taking into account a number of different factors: + * Priority of the voice's MIDI channel + * Number of voices over the polyphony allocation for voice's MIDI channel + * Amplitude of the voice + * Note age + * Key velocity (for voices that haven't been started yet) + * If any matching notes are found + * + * Inputs: + * pnVoiceNumber - really an output, see below + * nChannel - the channel that this voice wants to be started on + * nKeyNumber - the key number for this new voice + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pnVoiceNumber - voice number of the voice that was stolen + * EAS_RESULT EAS_SUCCESS - always successful + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMStealVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_INT *pVoiceNumber, EAS_U8 channel, EAS_U8 note, EAS_I32 lowVoice, EAS_I32 highVoice) +{ + S_SYNTH_VOICE *pCurrVoice; + S_SYNTH *pCurrSynth; + EAS_INT voiceNum; + EAS_INT bestCandidate; + EAS_U8 currChannel; + EAS_U8 currNote; + EAS_I32 bestPriority; + EAS_I32 currentPriority; + + /* determine which voice to steal */ + bestPriority = 0; + bestCandidate = MAX_SYNTH_VOICES; + + for (voiceNum = (int)lowVoice; voiceNum <= highVoice; voiceNum++) + { + pCurrVoice = &pVoiceMgr->voices[voiceNum]; + + /* ignore free voices */ + if (pCurrVoice->voiceState == eVoiceStateFree) + continue; + + /* for stolen voices, use the new parameters, not the old */ + if (pCurrVoice->voiceState == eVoiceStateStolen) + { + pCurrSynth = pVoiceMgr->pSynth[GET_VSYNTH(pCurrVoice->nextChannel)]; + currChannel = pCurrVoice->nextChannel; + currNote = pCurrVoice->nextNote; + } + else + { + pCurrSynth = pVoiceMgr->pSynth[GET_VSYNTH(pCurrVoice->channel)]; + currChannel = pCurrVoice->channel; + currNote = pCurrVoice->note; + } + + /* ignore voices that are higher priority */ + if (pSynth->priority > pCurrSynth->priority) + continue; +#ifdef _DEBUG_VM +// { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: New priority = %d exceeds old priority = %d\n", pSynth->priority, pCurrSynth->priority); */ } +#endif + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pCurrVoice->voiceState == eVoiceStateStolen) || (pCurrVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + currentPriority = 128 - pCurrVoice->nextVelocity; + } + else + { + /* compute the priority of this voice, higher means better for stealing */ + /* use not age */ + currentPriority = (EAS_I32) pCurrVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pCurrVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + } + + /* in SP-MIDI mode, include over poly allocation and channel priority */ + if (pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + { + S_SYNTH_CHANNEL *pChannel = &pCurrSynth->channels[GET_CHANNEL(currChannel)]; + /*lint -e{701} use shift for performance */ + if (pSynth->poolCount[pChannel->pool] >= pSynth->poolAlloc[pChannel->pool]) + currentPriority += (pSynth->poolCount[pChannel->pool] -pSynth->poolAlloc[pChannel->pool] + 1) << CHANNEL_POLY_STEAL_WEIGHT; + + /* include channel priority */ + currentPriority += (EAS_I32)(pChannel->pool << CHANNEL_PRIORITY_STEAL_WEIGHT); + } + + /* if a note is already playing that matches this note, consider stealing it more readily */ + if ((note == currNote) && (channel == currChannel)) + currentPriority += NOTE_MATCH_PENALTY; + + /* is this the best choice so far? */ + if (currentPriority >= bestPriority) + { + bestPriority = currentPriority; + bestCandidate = voiceNum; + } + } + + /* may happen if all voices are allocated to a higher priority virtual synth */ + if (bestCandidate == MAX_SYNTH_VOICES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: Unable to allocate a voice\n"); */ } + return EAS_ERROR_NO_VOICE_ALLOCATED; + } + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: Voice %d stolen\n", bestCandidate); */ } + + /* are we stealing a stolen voice? */ + if (pVoiceMgr->voices[bestCandidate].voiceState == eVoiceStateStolen) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMStealVoice: Voice %d is already marked as stolen and was scheduled to play ch: %d note: %d vel: %d\n", + bestCandidate, + pVoiceMgr->voices[bestCandidate].nextChannel, + pVoiceMgr->voices[bestCandidate].nextNote, + pVoiceMgr->voices[bestCandidate].nextVelocity); */ } + } +#endif + + *pVoiceNumber = (EAS_U16) bestCandidate; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMChannelPressure() + *---------------------------------------------------------------------------- + * Purpose: + * Change the channel pressure for the given channel + * + * Inputs: + * nChannel - the MIDI channel + * nVelocity - the channel pressure value + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sChannel[nChannel].m_nChannelPressure is updated + *---------------------------------------------------------------------------- +*/ +void VMChannelPressure (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + pChannel->channelPressure = value; + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMPitchBend() + *---------------------------------------------------------------------------- + * Purpose: + * Change the pitch wheel value for the given channel. + * This routine constructs the proper 14-bit argument when the calling routine + * passes the pitch LSB and MSB. + * + * Note: some midi disassemblers display a bipolar pitch bend value. + * We can display the bipolar value using + * if m_nPitchBend >= 0x2000 + * bipolar pitch bend = postive (m_nPitchBend - 0x2000) + * else + * bipolar pitch bend = negative (0x2000 - m_nPitchBend) + * + * Inputs: + * nChannel - the MIDI channel + * nPitchLSB - the LSB byte of the pitch bend message + * nPitchMSB - the MSB byte of the pitch bend message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * psSynthObject->m_sChannel[nChannel].m_nPitchBend is changed + * + *---------------------------------------------------------------------------- +*/ +void VMPitchBend (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 nPitchLSB, EAS_U8 nPitchMSB) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + pChannel->pitchBend = (EAS_I16) ((nPitchMSB << 7) | nPitchLSB); + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMControlChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the controller (or mode) for the given channel. + * + * Inputs: + * nChannel - the MIDI channel + * nControllerNumber - the MIDI controller number + * nControlValue - the value for this controller message + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * Side Effects: + * psSynthObject->m_sChannel[nChannel] controller is changed + * + *---------------------------------------------------------------------------- +*/ +void VMControlChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + + pChannel = &(pSynth->channels[channel]); + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + switch ( controller ) + { + case MIDI_CONTROLLER_BANK_SELECT_MSB: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: Bank Select MSB: msb 0x%X\n", value); */ } +#endif + /* use this MSB with a zero LSB, until we get an LSB message */ + pChannel->bankNum = value << 8; + break; + + case MIDI_CONTROLLER_MOD_WHEEL: + /* we treat mod wheel as a 7-bit controller and only use the MSB */ + pChannel->modWheel = value; + break; + + case MIDI_CONTROLLER_VOLUME: + /* we treat volume as a 7-bit controller and only use the MSB */ + pChannel->volume = value; + break; + + case MIDI_CONTROLLER_PAN: + /* we treat pan as a 7-bit controller and only use the MSB */ + pChannel->pan = value; + break; + + case MIDI_CONTROLLER_EXPRESSION: + /* we treat expression as a 7-bit controller and only use the MSB */ + pChannel->expression = value; + break; + + case MIDI_CONTROLLER_BANK_SELECT_LSB: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: Bank Select LSB: lsb 0x%X\n", value); */ } +#endif + /* + construct bank number as 7-bits (stored as 8) of existing MSB + and 7-bits of new LSB (also stored as 8( + */ + pChannel->bankNum = + (pChannel->bankNum & 0xFF00) | value; + + break; + + case MIDI_CONTROLLER_SUSTAIN_PEDAL: + /* we treat sustain pedal as a boolean on/off bit flag */ + if (value < 64) + { + /* + we are requested to turn the pedal off, but first check + if the pedal is already on + */ + if (0 != + (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + ) + { + /* + The sustain flag is presently set and the damper pedal is on. + We are therefore transitioning from damper pedal ON to + damper pedal OFF. This means all notes in this channel + that received a note off while the damper pedal was on, and + had their note-off requests deferred, should now proceed to + the release state. + */ + VMReleaseAllDeferredNoteOffs(pVoiceMgr, pSynth, channel); + } /* end if sustain pedal is already on */ + + /* turn the sustain pedal off */ + pChannel->channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + } + else + { + /* + we are requested to turn the pedal on, but first check + if the pedal is already off + */ + if (0 == + (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) + ) + { + /* + The sustain flag is presently clear and the damper pedal is off. + We are therefore transitioning from damper pedal OFF to + damper pedal ON. Currently sounding notes should be left + unchanged. However, we should try to "catch" notes if possible. + If any notes have levels >= sustain level, catch them, + otherwise, let them continue to release. + */ + VMCatchNotesForSustainPedal(pVoiceMgr, pSynth, channel); + } + + /* turn the sustain pedal on */ + pChannel->channelFlags |= CHANNEL_FLAG_SUSTAIN_PEDAL; + } + + break; +#ifdef _REVERB + case MIDI_CONTROLLER_REVERB_SEND: + /* we treat send as a 7-bit controller and only use the MSB */ + pSynth->channels[channel].reverbSend = value; + break; +#endif +#ifdef _CHORUS + case MIDI_CONTROLLER_CHORUS_SEND: + /* we treat send as a 7-bit controller and only use the MSB */ + pSynth->channels[channel].chorusSend = value; + break; +#endif + case MIDI_CONTROLLER_RESET_CONTROLLERS: + /* despite the Midi message name, not ALL controllers are reset */ + pChannel->modWheel = DEFAULT_MOD_WHEEL; + pChannel->expression = DEFAULT_EXPRESSION; + + /* turn the sustain pedal off as default/reset */ + pChannel->channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; + pChannel->pitchBend = DEFAULT_PITCH_BEND; + + /* reset channel pressure */ + pChannel->channelPressure = DEFAULT_CHANNEL_PRESSURE; + + /* reset RPN values */ + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + pChannel->pitchBendSensitivity = DEFAULT_PITCH_BEND_SENSITIVITY; + pChannel->finePitch = DEFAULT_FINE_PITCH; + pChannel->coarsePitch = DEFAULT_COARSE_PITCH; + + /* + program change, bank select, channel volume CC7, pan CC10 + are NOT reset + */ + break; + + /* + For logical reasons, the RPN data entry are grouped together. + However, keep in mind that these cases are not necessarily in + ascending order. + e.g., MIDI_CONTROLLER_DATA_ENTRY_MSB == 6, + whereas MIDI_CONTROLLER_SUSTAIN_PEDAL == 64. + So arrange these case statements in whatever manner is more efficient for + the processor / compiler. + */ + case MIDI_CONTROLLER_ENTER_DATA_MSB: + case MIDI_CONTROLLER_ENTER_DATA_LSB: + case MIDI_CONTROLLER_SELECT_RPN_LSB: + case MIDI_CONTROLLER_SELECT_RPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_LSB: + VMUpdateRPNStateMachine(pSynth, channel, controller, value); + break; + + case MIDI_CONTROLLER_ALL_SOUND_OFF: + case MIDI_CONTROLLER_ALL_NOTES_OFF: + case MIDI_CONTROLLER_OMNI_OFF: + case MIDI_CONTROLLER_OMNI_ON: + case MIDI_CONTROLLER_MONO_ON_POLY_OFF: + case MIDI_CONTROLLER_POLY_ON_MONO_OFF: + /* NOTE: we treat all sounds off the same as all notes off */ + VMAllNotesOff(pVoiceMgr, pSynth, channel); + break; + + default: +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: controller %d not yet implemented\n", controller); */ } +#endif + break; + + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMUpdateRPNStateMachine() + *---------------------------------------------------------------------------- + * Purpose: + * Call this function when we want to parse RPN related controller messages. + * We only support RPN0 (pitch bend sensitivity), RPN1 (fine tuning) and + * RPN2 (coarse tuning). Any other RPNs or NRPNs are ignored for now. + *. + * Supports any order, so not a state machine anymore. This function was + * rewritten to work correctly regardless of order. + * + * Inputs: + * nChannel - the channel this controller message is coming from + * nControllerNumber - which RPN related controller + * nControlValue - the value of the RPN related controller + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * returns EAS_RESULT, which is typically EAS_SUCCESS, since there are + * few possible errors + * + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nPitchBendSensitivity + * (or m_nFinePitch or m_nCoarsePitch) + * will be updated if the proper RPN message is received. + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMUpdateRPNStateMachine (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) +{ + S_SYNTH_CHANNEL *pChannel; + +#ifdef _DEBUG_VM + if (channel >= NUM_SYNTH_CHANNELS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateRPNStateMachines: error, %d invalid channel number\n", + channel); */ } + return EAS_FAILURE; + } +#endif + + pChannel = &(pSynth->channels[channel]); + + switch (controller) + { + case MIDI_CONTROLLER_SELECT_NRPN_MSB: + case MIDI_CONTROLLER_SELECT_NRPN_LSB: + pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; + break; + case MIDI_CONTROLLER_SELECT_RPN_MSB: + pChannel->registeredParam = + (pChannel->registeredParam & 0x7F) | (value<<7); + break; + case MIDI_CONTROLLER_SELECT_RPN_LSB: + pChannel->registeredParam = + (pChannel->registeredParam & 0x7F00) | value; + break; + case MIDI_CONTROLLER_ENTER_DATA_MSB: + switch (pChannel->registeredParam) + { + case 0: + pChannel->pitchBendSensitivity = value * 100; + break; + case 1: + /*lint -e{702} */ + pChannel->finePitch = (EAS_I8)((((value << 7) - 8192) * 100) >> 13); + break; + case 2: + pChannel->coarsePitch = (EAS_I8)(value - 64); + break; + default: + break; + } + break; + case MIDI_CONTROLLER_ENTER_DATA_LSB: + switch (pChannel->registeredParam) + { + case 0: + //ignore lsb + break; + case 1: + //ignore lsb + break; + case 2: + //ignore lsb + break; + default: + break; + } + break; + default: + return EAS_FAILURE; //not a RPN related controller + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMUpdateStaticChannelParameters() + *---------------------------------------------------------------------------- + * Purpose: + * Update all of the static channel parameters for channels that have had + * a controller change values + * Or if the synth has signalled that all channels must forcibly + * be updated + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * none + * + * Side Effects: + * - psSynthObject->m_sChannel[].m_nStaticGain and m_nStaticPitch + * are updated for channels whose controller values have changed + * or if the synth has signalled that all channels must forcibly + * be updated + *---------------------------------------------------------------------------- +*/ +void VMUpdateStaticChannelParameters (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) +{ + EAS_INT channel; + + if (pSynth->synthFlags & SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS) + { + /* + the synth wants us to forcibly update all channel + parameters. This event occurs when we are about to + finish resetting the synth + */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + { +#ifdef _HYBRID_SYNTH + if (pSynth->channels[channel].regionIndex & FLAG_RGN_IDX_FM_SYNTH) + pSecondarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); + else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#endif + } + + /* + clear the flag to indicates we have now forcibly + updated all channel parameters + */ + pSynth->synthFlags &= ~SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS; + } + else + { + + /* only update channel params if signalled by a channel flag */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + { + if ( 0 != (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS)) + { +#ifdef _HYBRID_SYNTH + if (pSynth->channels[channel].regionIndex & FLAG_RGN_IDX_FM_SYNTH) + pSecondarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); + else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#else + pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); +#endif + } + } + + } + + return; +} + +/*---------------------------------------------------------------------------- + * VMFindProgram() + *---------------------------------------------------------------------------- + * Purpose: + * Look up an individual program in sound library. This function + * searches the bank list for a program, then the individual program + * list. + * + * Inputs: + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT VMFindProgram (const S_EAS *pEAS, EAS_U32 bank, EAS_U8 programNum, EAS_U16 *pRegionIndex) +{ + EAS_U32 locale; + const S_PROGRAM *p; + EAS_U16 i; + EAS_U16 regionIndex; + + /* make sure we have a valid sound library */ + if (pEAS == NULL) + return EAS_FAILURE; + + /* search the banks */ + for (i = 0; i < pEAS->numBanks; i++) + { + if (bank == (EAS_U32) pEAS->pBanks[i].locale) + { + regionIndex = pEAS->pBanks[i].regionIndex[programNum]; + if (regionIndex != INVALID_REGION_INDEX) + { + *pRegionIndex = regionIndex; + return EAS_SUCCESS; + } + break; + } + } + + /* establish locale */ + locale = ( bank << 8) | programNum; + + /* search for program */ + for (i = 0, p = pEAS->pPrograms; i < pEAS->numPrograms; i++, p++) + { + if (p->locale == locale) + { + *pRegionIndex = p->regionIndex; + return EAS_SUCCESS; + } + } + + return EAS_FAILURE; +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMFindDLSProgram() + *---------------------------------------------------------------------------- + * Purpose: + * Look up an individual program in sound library. This function + * searches the bank list for a program, then the individual program + * list. + * + * Inputs: + * + * Outputs: + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT VMFindDLSProgram (const S_DLS *pDLS, EAS_U32 bank, EAS_U8 programNum, EAS_U16 *pRegionIndex) +{ + EAS_U32 locale; + const S_PROGRAM *p; + EAS_U16 i; + + /* make sure we have a valid sound library */ + if (pDLS == NULL) + return EAS_FAILURE; + + /* establish locale */ + locale = (bank << 8) | programNum; + + /* search for program */ + for (i = 0, p = pDLS->pDLSPrograms; i < pDLS->numDLSPrograms; i++, p++) + { + if (p->locale == locale) + { + *pRegionIndex = p->regionIndex; + return EAS_SUCCESS; + } + } + + return EAS_FAILURE; +} +#endif + +/*---------------------------------------------------------------------------- + * VMProgramChange() + *---------------------------------------------------------------------------- + * Purpose: + * Change the instrument (program) for the given channel. + * + * Depending on the program number, and the bank selected for this channel, the + * program may be in ROM, RAM (from SMAF or CMX related RAM wavetable), or + * Alternate wavetable (from mobile DLS or other DLS file) + * + * This function figures out what wavetable should be used, and sets it up as the + * wavetable to use for this channel. Also the channel may switch from a melodic + * channel to a rhythm channel, or vice versa. + * + * Inputs: + * + * Outputs: + * Side Effects: + * gsSynthObject.m_sChannel[nChannel].m_nProgramNumber is likely changed + * gsSynthObject.m_sChannel[nChannel].m_psEAS may be changed + * gsSynthObject.m_sChannel[nChannel].m_bRhythmChannel may be changed + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +void VMProgramChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 program) +{ + S_SYNTH_CHANNEL *pChannel; + EAS_U32 bank; + EAS_U16 regionIndex; + +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMProgramChange: vSynthNum=%d, channel=%d, program=%d\n", pSynth->vSynthNum, channel, program); */ } +#endif + + /* setup pointer to MIDI channel data */ + pChannel = &pSynth->channels[channel]; + bank = pChannel->bankNum; + + /* allow channels to switch between being melodic or rhythm channels, using GM2 CC values */ + if ((bank & 0xFF00) == DEFAULT_RHYTHM_BANK_NUMBER) + { + /* make it a rhythm channel */ + pChannel->channelFlags |= CHANNEL_FLAG_RHYTHM_CHANNEL; + } + else if ((bank & 0xFF00) == DEFAULT_MELODY_BANK_NUMBER) + { + /* make it a melody channel */ + pChannel->channelFlags &= ~CHANNEL_FLAG_RHYTHM_CHANNEL; + } + + regionIndex = DEFAULT_REGION_INDEX; + +#ifdef EXTERNAL_AUDIO + /* give the external audio interface a chance to handle it */ + if (pSynth->cbProgChgFunc != NULL) + { + S_EXT_AUDIO_PRG_CHG prgChg; + prgChg.channel = channel; + prgChg.bank = (EAS_U16) bank; + prgChg.program = program; + if (pSynth->cbProgChgFunc(pSynth->pExtAudioInstData, &prgChg)) + pChannel->channelFlags |= CHANNEL_FLAG_EXTERNAL_AUDIO; + } + +#endif + + +#ifdef DLS_SYNTHESIZER + /* first check for DLS program that may overlay the internal instrument */ + if (VMFindDLSProgram(pSynth->pDLS, bank, program, ®ionIndex) != EAS_SUCCESS) +#endif + + /* braces to support 'if' clause above */ + { + + /* look in the internal banks */ + if (VMFindProgram(pSynth->pEAS, bank, program, ®ionIndex) != EAS_SUCCESS) + + /* fall back to default bank */ + { + if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) + bank = DEFAULT_RHYTHM_BANK_NUMBER; + else + bank = DEFAULT_MELODY_BANK_NUMBER; + + if (VMFindProgram(pSynth->pEAS, bank, program, ®ionIndex) != EAS_SUCCESS) + + /* switch to program 0 in the default bank */ + { + if (VMFindProgram(pSynth->pEAS, bank, 0, ®ionIndex) != EAS_SUCCESS) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMProgramChange: No program @ %03d:%03d:%03d\n", + (bank >> 8) & 0x7f, bank & 0x7f, program); */ } + } + } + } + + /* we have our new program change for this channel */ + pChannel->programNum = program; + pChannel->regionIndex = regionIndex; + + /* + set a channel flag to request parameter updates + for all the voices associated with this channel + */ + pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + return; +} + +/*---------------------------------------------------------------------------- + * VMAddSamples() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize the requested number of samples (block based processing) + * + * Inputs: + * nNumSamplesToAdd - number of samples to write to buffer + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * number of voices rendered + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMAddSamples (S_VOICE_MGR *pVoiceMgr, EAS_I32 *pMixBuffer, EAS_I32 numSamples) +{ + S_SYNTH *pSynth; + EAS_INT voicesRendered; + EAS_INT voiceNum; + EAS_BOOL done; + +#ifdef _REVERB + EAS_PCM *pReverbSendBuffer; +#endif // ifdef _REVERB + +#ifdef _CHORUS + EAS_PCM *pChorusSendBuffer; +#endif // ifdef _CHORUS + + voicesRendered = 0; + for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) + { + + /* retarget stolen voices */ + if ((pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) && (pVoiceMgr->voices[voiceNum].gain <= 0)) + VMRetargetStolenVoice(pVoiceMgr, voiceNum); + + /* get pointer to virtual synth */ + pSynth = pVoiceMgr->pSynth[pVoiceMgr->voices[voiceNum].channel >> 4]; + + /* synthesize active voices */ + if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateFree) + { + done = GetSynthPtr(voiceNum)->pfUpdateVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), pMixBuffer, numSamples); + voicesRendered++; + + /* voice is finished */ + if (done == EAS_TRUE) + { + /* set gain of stolen voice to zero so it will be restarted */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) + pVoiceMgr->voices[voiceNum].gain = 0; + + /* or return it to the free voice pool */ + else + VMFreeVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum]); + } + + /* if this voice is scheduled to be muted, set the mute flag */ + if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_DEFER_MUTE) + { + pVoiceMgr->voices[voiceNum].voiceFlags &= ~(VOICE_FLAG_DEFER_MUTE | VOICE_FLAG_DEFER_MIDI_NOTE_OFF); + VMMuteVoice(pVoiceMgr, voiceNum); + } + + /* if voice just started, advance state to play */ + if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStart) + pVoiceMgr->voices[voiceNum].voiceState = eVoiceStatePlay; + } + } + + return voicesRendered; +} + +/*---------------------------------------------------------------------------- + * VMRender() + *---------------------------------------------------------------------------- + * Purpose: + * This routine renders a frame of audio + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * pVoicesRendered - number of voices rendered this frame + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMRender (S_VOICE_MGR *pVoiceMgr, EAS_I32 numSamples, EAS_I32 *pMixBuffer, EAS_I32 *pVoicesRendered) +{ + S_SYNTH *pSynth; + EAS_INT i; + EAS_INT channel; + +#ifdef _CHECKED_BUILD + SanityCheck(pVoiceMgr); +#endif + + /* update MIDI channel parameters */ + *pVoicesRendered = 0; + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pVoiceMgr->pSynth[i] != NULL) + VMUpdateStaticChannelParameters(pVoiceMgr, pVoiceMgr->pSynth[i]); + } + + /* synthesize a buffer of audio */ + *pVoicesRendered = VMAddSamples(pVoiceMgr, pMixBuffer, numSamples); + + /* + * check for deferred note-off messages + * If flag is set, that means one or more voices are expecting deferred + * midi note-off messages because the midi note-on and corresponding midi + * note-off requests occurred during the same update interval. The goal + * is the defer the note-off request so that the note can at least start. + */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + pSynth = pVoiceMgr->pSynth[i]; + + if (pSynth== NULL) + continue; + + if (pSynth->synthFlags & SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING) + VMDeferredStopNote(pVoiceMgr, pSynth); + + /* check if we need to reset the synth */ + if ((pSynth->synthFlags & SYNTH_FLAG_RESET_IS_REQUESTED) && + (pSynth->numActiveVoices == 0)) + { + /* + complete the process of resetting the synth now that + all voices have muted + */ +#ifdef _DEBUG_VM + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMAddSamples: complete the reset process\n"); */ } +#endif + + VMInitializeAllChannels(pVoiceMgr, pSynth); + VMInitializeAllVoices(pVoiceMgr, pSynth->vSynthNum); + + /* clear the reset flag */ + pSynth->synthFlags &= ~SYNTH_FLAG_RESET_IS_REQUESTED; + } + + /* clear channel update flags */ + for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) + pSynth->channels[channel].channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + + } + +#ifdef _CHECKED_BUILD + SanityCheck(pVoiceMgr); +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMInitWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Clears the workload counter + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMInitWorkload (S_VOICE_MGR *pVoiceMgr) +{ + pVoiceMgr->workload = 0; +} + +/*---------------------------------------------------------------------------- + * VMSetWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the max workload for a single frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetWorkload (S_VOICE_MGR *pVoiceMgr, EAS_I32 maxWorkLoad) +{ + pVoiceMgr->maxWorkLoad = maxWorkLoad; +} + +/*---------------------------------------------------------------------------- + * VMCheckWorkload() + *---------------------------------------------------------------------------- + * Purpose: + * Checks to see if work load has been exceeded on this frame. + * + * Inputs: + * pVoiceMgr - pointer to instance data + * + * Outputs: + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMCheckWorkload (S_VOICE_MGR *pVoiceMgr) +{ + if (pVoiceMgr->maxWorkLoad > 0) + return (EAS_BOOL) (pVoiceMgr->workload >= pVoiceMgr->maxWorkLoad); + return EAS_FALSE; +} + +/*---------------------------------------------------------------------------- + * VMActiveVoices() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the number of active voices in the synthesizer. + * + * Inputs: + * pEASData - pointer to instance data + * + * Outputs: + * Returns the number of active voices + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 VMActiveVoices (S_SYNTH *pSynth) +{ + return pSynth->numActiveVoices; +} + +/*---------------------------------------------------------------------------- + * VMSetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the synth to a new polyphony value. Value must be >= 1 and + * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * synth synthesizer number (0 = onboard, 1 = DSP) + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 polyphonyCount) +{ + EAS_INT i; + EAS_INT activeVoices; + + /* lower limit */ + if (polyphonyCount < 1) + polyphonyCount = 1; + + /* split architecture */ +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + if (synth == EAS_MCU_SYNTH) + { + if (polyphonyCount > NUM_PRIMARY_VOICES) + polyphonyCount = NUM_PRIMARY_VOICES; + if (pVoiceMgr->maxPolyphonyPrimary == polyphonyCount) + return EAS_SUCCESS; + pVoiceMgr->maxPolyphonyPrimary = (EAS_U16) polyphonyCount; + } + else if (synth == EAS_DSP_SYNTH) + { + if (polyphonyCount > NUM_SECONDARY_VOICES) + polyphonyCount = NUM_SECONDARY_VOICES; + if (pVoiceMgr->maxPolyphonySecondary == polyphonyCount) + return EAS_SUCCESS; + pVoiceMgr->maxPolyphonySecondary = (EAS_U16) polyphonyCount; + } + else + return EAS_ERROR_PARAMETER_RANGE; + + /* setting for SP-MIDI */ + pVoiceMgr->maxPolyphony = pVoiceMgr->maxPolyphonyPrimary + pVoiceMgr->maxPolyphonySecondary; + + /* standard architecture */ +#else + if (synth != EAS_MCU_SYNTH) + return EAS_ERROR_PARAMETER_RANGE; + + /* pin desired value to possible limits */ + if (polyphonyCount > MAX_SYNTH_VOICES) + polyphonyCount = MAX_SYNTH_VOICES; + + /* set polyphony, if value is different than current value */ + if (pVoiceMgr->maxPolyphony == polyphonyCount) + return EAS_SUCCESS; + + pVoiceMgr->maxPolyphony = (EAS_U16) polyphonyCount; +#endif + + /* if SPMIDI enabled, update channel masking based on new polyphony */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pVoiceMgr->pSynth[i]) + { + if (pVoiceMgr->pSynth[i]->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + VMMIPUpdateChannelMuting(pVoiceMgr, pVoiceMgr->pSynth[i]); + else + pVoiceMgr->pSynth[i]->poolAlloc[0] = (EAS_U8) polyphonyCount; + } + } + + /* are we under polyphony limit? */ + if (pVoiceMgr->activeVoices <= polyphonyCount) + return EAS_SUCCESS; + + /* count the number of active voices */ + activeVoices = 0; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + /* is voice active? */ + if ((pVoiceMgr->voices[i].voiceState != eVoiceStateFree) && (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting)) + activeVoices++; + } + + /* we may have to mute voices to reach new target */ + while (activeVoices > polyphonyCount) + { + S_SYNTH *pSynth; + S_SYNTH_VOICE *pVoice; + EAS_I32 currentPriority, bestPriority; + EAS_INT bestCandidate; + + /* find the lowest priority voice */ + bestPriority = bestCandidate = -1; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + + pVoice = &pVoiceMgr->voices[i]; + + /* ignore free and muting voices */ + if ((pVoice->voiceState == eVoiceStateFree) || (pVoice->voiceState == eVoiceStateMuting)) + continue; + + pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pVoice->voiceState == eVoiceStateStolen) || (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + /* include velocity */ + currentPriority = 128 - pVoice->nextVelocity; + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + else + { + /* include age */ + currentPriority = (EAS_I32) pVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->channel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + + /* include synth priority */ + currentPriority += pSynth->priority << SYNTH_PRIORITY_WEIGHT; + + /* is this the best choice so far? */ + if (currentPriority > bestPriority) + { + bestPriority = currentPriority; + bestCandidate = i; + } + } + + /* shutdown best candidate */ + if (bestCandidate < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMSetPolyphony: Unable to reduce polyphony\n"); */ } + break; + } + + /* shut down this voice */ + /*lint -e{771} pSynth is initialized if bestCandidate >= 0 */ + VMMuteVoice(pVoiceMgr, bestCandidate); + activeVoices--; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetSynthPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current polyphony setting + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * synth synthesizer number (0 = onboard, 1 = DSP) + * + * Outputs: + * Returns actual polyphony value set, as pinned by limits + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMGetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 *pPolyphonyCount) +{ + +#if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) + if (synth == EAS_MCU_SYNTH) + *pPolyphonyCount = pVoiceMgr->maxPolyphonyPrimary; + else if (synth == EAS_DSP_SYNTH) + *pPolyphonyCount = pVoiceMgr->maxPolyphonySecondary; + else + return EAS_ERROR_PARAMETER_RANGE; +#else + if (synth != EAS_MCU_SYNTH) + return EAS_ERROR_PARAMETER_RANGE; + *pPolyphonyCount = pVoiceMgr->maxPolyphony; +#endif + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth polyphony. 0 = no limit (i.e. can use + * all available voices). + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * polyphonyCount desired polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 polyphonyCount) +{ + EAS_INT i; + EAS_INT activeVoices; + + /* check limits */ + if (polyphonyCount < 0) + return EAS_ERROR_PARAMETER_RANGE; + + /* zero is max polyphony */ + if ((polyphonyCount == 0) || (polyphonyCount > MAX_SYNTH_VOICES)) + { + pSynth->maxPolyphony = 0; + return EAS_SUCCESS; + } + + /* set new polyphony */ + pSynth->maxPolyphony = (EAS_U16) polyphonyCount; + + /* max polyphony is minimum of virtual synth and actual synth */ + if (polyphonyCount > pVoiceMgr->maxPolyphony) + polyphonyCount = pVoiceMgr->maxPolyphony; + + /* if SP-MIDI mode, update the channel muting */ + if (pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) + VMMIPUpdateChannelMuting(pVoiceMgr, pSynth); + else + pSynth->poolAlloc[0] = (EAS_U8) polyphonyCount; + + /* are we under polyphony limit? */ + if (pSynth->numActiveVoices <= polyphonyCount) + return EAS_SUCCESS; + + /* count the number of active voices */ + activeVoices = 0; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + /* this synth? */ + if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) != pSynth->vSynthNum) + continue; + + /* is voice active? */ + if ((pVoiceMgr->voices[i].voiceState != eVoiceStateFree) && (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting)) + activeVoices++; + } + + /* we may have to mute voices to reach new target */ + while (activeVoices > polyphonyCount) + { + S_SYNTH_VOICE *pVoice; + EAS_I32 currentPriority, bestPriority; + EAS_INT bestCandidate; + + /* find the lowest priority voice */ + bestPriority = bestCandidate = -1; + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + pVoice = &pVoiceMgr->voices[i]; + + /* this synth? */ + if (GET_VSYNTH(pVoice->nextChannel) != pSynth->vSynthNum) + continue; + + /* if voice is stolen or just started, reduce the likelihood it will be stolen */ + if (( pVoice->voiceState == eVoiceStateStolen) || (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) + { + /* include velocity */ + currentPriority = 128 - pVoice->nextVelocity; + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + else + { + /* include age */ + currentPriority = (EAS_I32) pVoice->age << NOTE_AGE_STEAL_WEIGHT; + + /* include note gain -higher gain is lower steal value */ + /*lint -e{704} use shift for performance */ + currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - + ((EAS_I32) pVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); + + /* include channel priority */ + currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; + } + + /* is this the best choice so far? */ + if (currentPriority > bestPriority) + { + bestPriority = currentPriority; + bestCandidate = i; + } + } + + /* shutdown best candidate */ + if (bestCandidate < 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMSetPolyphony: Unable to reduce polyphony\n"); */ } + break; + } + + /* shut down this voice */ + VMMuteVoice(pVoiceMgr, bestCandidate); + activeVoices--; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetPolyphony() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth polyphony + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPolyphonyCount pointer to variable to hold polyphony count + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMGetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPolyphonyCount) +{ + *pPolyphonyCount = (EAS_U16) pSynth->maxPolyphony; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Set the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * priority new priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMSetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 priority) +{ + pSynth->priority = (EAS_U8) priority ; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMGetPriority() + *---------------------------------------------------------------------------- + * Purpose: + * Get the virtual synth priority + * + * Inputs: + * pVoiceMgr pointer to synthesizer data + * pPriority pointer to variable to hold priority + * pSynth pointer to virtual synth + * + * Outputs: + * Returns error code + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +EAS_RESULT VMGetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPriority) +{ + *pPriority = pSynth->priority; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetVolume() + *---------------------------------------------------------------------------- + * Purpose: + * Set the master volume for this synthesizer for this sequence. + * + * Inputs: + * nSynthVolume - the desired master volume + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * overrides any previously set master volume from sysex + * + *---------------------------------------------------------------------------- +*/ +void VMSetVolume (S_SYNTH *pSynth, EAS_U16 masterVolume) +{ + pSynth->masterVolume = masterVolume; + pSynth->synthFlags |= SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS; +} + +/*---------------------------------------------------------------------------- + * VMSetPitchBendRange() + *---------------------------------------------------------------------------- + * Set the pitch bend range for the given channel. + *---------------------------------------------------------------------------- +*/ +void VMSetPitchBendRange (S_SYNTH *pSynth, EAS_INT channel, EAS_I16 pitchBendRange) +{ + pSynth->channels[channel].pitchBendSensitivity = pitchBendRange; +} + +/*---------------------------------------------------------------------------- + * VMValidateEASLib() + *---------------------------------------------------------------------------- + * Validates an EAS library + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMValidateEASLib (EAS_SNDLIB_HANDLE pEAS) +{ + /* validate the sound library */ + if (pEAS) + { + if (pEAS->identifier != _EAS_LIBRARY_VERSION) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Sound library mismatch in sound library: Read 0x%08x, expected 0x%08x\n", + pEAS->identifier, _EAS_LIBRARY_VERSION); */ } + return EAS_ERROR_SOUND_LIBRARY; + } + + /* check sample rate */ + if ((pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK) != _OUTPUT_SAMPLE_RATE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Sample rate mismatch in sound library: Read %lu, expected %lu\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } + +#ifdef _WT_SYNTH + /* check sample bit depth */ +#ifdef _8_BIT_SAMPLES + if (pEAS->libAttr & LIB_FORMAT_16_BIT_SAMPLES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Expected 8-bit samples and found 16-bit\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } +#endif +#ifdef _16_BIT_SAMPLES + if ((pEAS->libAttr & LIB_FORMAT_16_BIT_SAMPLES) == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Expected 16-bit samples and found 8-bit\n", + pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } + return EAS_ERROR_SOUND_LIBRARY; + } +#endif +#endif + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetGlobalEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the EAS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalEASLib (S_VOICE_MGR *pVoiceMgr, EAS_SNDLIB_HANDLE pEAS) +{ + EAS_RESULT result; + + result = VMValidateEASLib(pEAS); + if (result != EAS_SUCCESS) + return result; + + pVoiceMgr->pGlobalEAS = pEAS; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetEASLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the EAS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetEASLib (S_SYNTH *pSynth, EAS_SNDLIB_HANDLE pEAS) +{ + EAS_RESULT result; + + result = VMValidateEASLib(pEAS); + if (result != EAS_SUCCESS) + return result; + + pSynth->pEAS = pEAS; + return EAS_SUCCESS; +} + +#ifdef DLS_SYNTHESIZER +/*---------------------------------------------------------------------------- + * VMSetGlobalDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the DLS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetGlobalDLSLib (EAS_DATA_HANDLE pEASData, EAS_DLSLIB_HANDLE pDLS) +{ + + if (pEASData->pVoiceMgr->pGlobalDLS) + DLSCleanup(pEASData->hwInstData, pEASData->pVoiceMgr->pGlobalDLS); + + pEASData->pVoiceMgr->pGlobalDLS = pDLS; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * VMSetDLSLib() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the DLS library to be used by the synthesizer + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSetDLSLib (S_SYNTH *pSynth, EAS_DLSLIB_HANDLE pDLS) +{ + pSynth->pDLS = pDLS; + return EAS_SUCCESS; +} +#endif + +/*---------------------------------------------------------------------------- + * VMSetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMSetTranposition (S_SYNTH *pSynth, EAS_I32 transposition) +{ + pSynth->globalTranspose = (EAS_I8) transposition; +} + +/*---------------------------------------------------------------------------- + * VMGetTranposition() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the global key transposition used by the synthesizer. + * Transposes all melodic instruments up or down by the specified + * amount. Range is limited to +/-12 semitones. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMGetTranposition (S_SYNTH *pSynth, EAS_I32 *pTransposition) +{ + *pTransposition = pSynth->globalTranspose; +} + +/*---------------------------------------------------------------------------- + * VMGetNoteCount() + *---------------------------------------------------------------------------- +* Returns the total note count +*---------------------------------------------------------------------------- +*/ +EAS_I32 VMGetNoteCount (S_SYNTH *pSynth) +{ + return pSynth->totalNoteCount; +} + +/*---------------------------------------------------------------------------- + * VMMIDIShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMMIDIShutdown (S_EAS_DATA *pEASData, S_SYNTH *pSynth) +{ + EAS_INT vSynthNum; + + /* decrement reference count, free if all references are gone */ + if (--pSynth->refCount > 0) + return; + + vSynthNum = pSynth->vSynthNum; + + /* cleanup DLS load */ +#ifdef DLS_SYNTHESIZER + /*lint -e{550} result used only in debugging code */ + if (pSynth->pDLS != NULL) + { + EAS_RESULT result; + if ((result = DLSCleanup(pEASData->hwInstData, pSynth->pDLS)) != EAS_SUCCESS) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMMIDIShutdown: Error %ld cleaning up DLS collection\n", result); */ } + pSynth->pDLS = NULL; + } +#endif + + VMReset(pEASData->pVoiceMgr, pSynth, EAS_TRUE); + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pSynth); + + /* clear pointer to MIDI state */ + pEASData->pVoiceMgr->pSynth[vSynthNum] = NULL; +} + +/*---------------------------------------------------------------------------- + * VMShutdown() + *---------------------------------------------------------------------------- + * Purpose: + * Clean up any Synth related system issues. + * + * Inputs: + * psEASData - pointer to overall EAS data structure + * + * Outputs: + * None + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +void VMShutdown (S_EAS_DATA *pEASData) +{ + + /* don't free a NULL pointer */ + if (pEASData->pVoiceMgr == NULL) + return; + +#ifdef DLS_SYNTHESIZER + /* if we have a global DLS collection, clean it up */ + if (pEASData->pVoiceMgr->pGlobalDLS) + { + DLSCleanup(pEASData->hwInstData, pEASData->pVoiceMgr->pGlobalDLS); + pEASData->pVoiceMgr->pGlobalDLS = NULL; + } +#endif + + /* check Configuration Module for static memory allocation */ + if (!pEASData->staticMemoryModel) + EAS_HWFree(pEASData->hwInstData, pEASData->pVoiceMgr); + pEASData->pVoiceMgr = NULL; +} + +#ifdef EXTERNAL_AUDIO +/*---------------------------------------------------------------------------- + * EAS_RegExtAudioCallback() + *---------------------------------------------------------------------------- + * Register a callback for external audio processing + *---------------------------------------------------------------------------- +*/ +void VMRegExtAudioCallback (S_SYNTH *pSynth, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc) +{ + pSynth->pExtAudioInstData = pInstData; + pSynth->cbProgChgFunc = cbProgChgFunc; + pSynth->cbEventFunc = cbEventFunc; +} + +/*---------------------------------------------------------------------------- + * VMGetMIDIControllers() + *---------------------------------------------------------------------------- + * Returns the MIDI controller values on the specified channel + *---------------------------------------------------------------------------- +*/ +void VMGetMIDIControllers (S_SYNTH *pSynth, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) +{ + pControl->modWheel = pSynth->channels[channel].modWheel; + pControl->volume = pSynth->channels[channel].volume; + pControl->pan = pSynth->channels[channel].pan; + pControl->expression = pSynth->channels[channel].expression; + pControl->channelPressure = pSynth->channels[channel].channelPressure; + +#ifdef _REVERB + pControl->reverbSend = pSynth->channels[channel].reverbSend; +#endif + +#ifdef _CHORUSE + pControl->chorusSend = pSynth->channels[channel].chorusSend; +#endif +} +#endif + +#ifdef _SPLIT_ARCHITECTURE +/*---------------------------------------------------------------------------- + * VMStartFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Starts an audio frame + * + * Inputs: + * + * Outputs: + * Returns true if EAS_MixEnginePrep should be called (onboard mixing) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMStartFrame (S_EAS_DATA *pEASData) +{ + + /* init counter for voices starts in split architecture */ +#ifdef MAX_VOICE_STARTS + pVoiceMgr->numVoiceStarts = 0; +#endif + + return pFrameInterface->pfStartFrame(pEASData->pVoiceMgr->pFrameBuffer); +} + +/*---------------------------------------------------------------------------- + * VMEndFrame() + *---------------------------------------------------------------------------- + * Purpose: + * Stops an audio frame + * + * Inputs: + * + * Outputs: + * Returns true if EAS_MixEnginePost should be called (onboard mixing) + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL VMEndFrame (S_EAS_DATA *pEASData) +{ + + return pFrameInterface->pfEndFrame(pEASData->pVoiceMgr->pFrameBuffer, pEASData->pMixBuffer, pEASData->masterGain); +} +#endif + +#ifdef TEST_HARNESS +/*---------------------------------------------------------------------------- + * SanityCheck() + *---------------------------------------------------------------------------- +*/ +EAS_RESULT VMSanityCheck (EAS_DATA_HANDLE pEASData) +{ + S_SYNTH_VOICE *pVoice; + S_SYNTH *pSynth; + EAS_INT i; + EAS_INT j; + EAS_INT freeVoices; + EAS_INT activeVoices; + EAS_INT playingVoices; + EAS_INT stolenVoices; + EAS_INT releasingVoices; + EAS_INT mutingVoices; + EAS_INT poolCount[MAX_VIRTUAL_SYNTHESIZERS][NUM_SYNTH_CHANNELS]; + EAS_INT vSynthNum; + EAS_RESULT result = EAS_SUCCESS; + + /* initialize counts */ + EAS_HWMemSet(poolCount, 0, sizeof(poolCount)); + freeVoices = activeVoices = playingVoices = stolenVoices = releasingVoices = mutingVoices = 0; + + /* iterate through all voices */ + for (i = 0; i < MAX_SYNTH_VOICES; i++) + { + pVoice = &pEASData->pVoiceMgr->voices[i]; + if (pVoice->voiceState != eVoiceStateFree) + { + vSynthNum = GET_VSYNTH(pVoice->channel); + if (vSynthNum >= MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Voice %d has invalid virtual synth number %d\n", i, vSynthNum); */ } + result = EAS_FAILURE; + continue; + } + pSynth = pEASData->pVoiceMgr->pSynth[vSynthNum]; + + switch (pVoice->voiceState) + { + case eVoiceStateMuting: + activeVoices++; + mutingVoices++; + break; + + case eVoiceStateStolen: + vSynthNum = GET_VSYNTH(pVoice->nextChannel); + if (vSynthNum >= MAX_VIRTUAL_SYNTHESIZERS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Voice %d has invalid virtual synth number %d\n", i, vSynthNum); */ } + result = EAS_FAILURE; + continue; + } + pSynth = pEASData->pVoiceMgr->pSynth[vSynthNum]; + activeVoices++; + stolenVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool]++; + break; + + case eVoiceStateStart: + case eVoiceStatePlay: + activeVoices++; + playingVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->channel)].pool]++; + break; + + case eVoiceStateRelease: + activeVoices++; + releasingVoices++; + poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->channel)].pool]++; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck : voice %d in invalid state\n", i); */ } + result = EAS_FAILURE; + break; + } + } + + /* count free voices */ + else + freeVoices++; + } + + /* dump state info */ + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d free\n", freeVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d active\n", activeVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d playing\n", playingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d releasing\n", releasingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d muting\n", mutingVoices); */ } + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d stolen\n", stolenVoices); */ } + + if (pEASData->pVoiceMgr->activeVoices != activeVoices) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Active voice mismatch was %d should be %d\n", + pEASData->pVoiceMgr->activeVoices, activeVoices); */ } + result = EAS_FAILURE; + } + + /* check virtual synth status */ + for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) + { + if (pEASData->pVoiceMgr->pSynth[i] == NULL) + continue; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Synth %d numActiveVoices: %d\n", i, pEASData->pVoiceMgr->pSynth[i]->numActiveVoices); */ } + if (pEASData->pVoiceMgr->pSynth[i]->numActiveVoices > MAX_SYNTH_VOICES) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Synth %d illegal count for numActiveVoices: %d\n", i, pEASData->pVoiceMgr->pSynth[i]->numActiveVoices); */ } + result = EAS_FAILURE; + } + for (j = 0; j < NUM_SYNTH_CHANNELS; j++) + { + if (poolCount[i][j] != pEASData->pVoiceMgr->pSynth[i]->poolCount[j]) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Pool count mismatch synth %d pool %d, was %d, should be %d\n", + i, j, pEASData->pVoiceMgr->pSynth[i]->poolCount[j], poolCount[i][j]); */ } + result = EAS_FAILURE; + } + } + } + + return result; +} +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefile.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefile.c new file mode 100755 index 0000000..f24bde2 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefile.c @@ -0,0 +1,867 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefile.c + * + * Contents and purpose: + * This file implements the wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 852 $ + * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_config.h" +#include "eas_parser.h" +#include "eas_pcm.h" +#include "eas_wavefile.h" + +/* lint is choking on the ARM math.h file, so we declare the log10 function here */ +extern double log10(double x); + +/* increase gain to compensate for loss in mixer */ +#define WAVE_GAIN_OFFSET 6 + +/* constant for 1200 / log10(2.0) */ +#define PITCH_CENTS_CONVERSION 3986.313714 + +/*---------------------------------------------------------------------------- + * WAVE file defines + *---------------------------------------------------------------------------- +*/ +/* RIFF chunks */ +#define CHUNK_TYPE(a,b,c,d) ( \ + ( ((EAS_U32)(a) & 0xFF) << 24 ) \ + + ( ((EAS_U32)(b) & 0xFF) << 16 ) \ + + ( ((EAS_U32)(c) & 0xFF) << 8 ) \ + + ( ((EAS_U32)(d) & 0xFF) ) ) + +#define CHUNK_RIFF CHUNK_TYPE('R','I','F','F') +#define CHUNK_WAVE CHUNK_TYPE('W','A','V','E') +#define CHUNK_FMT CHUNK_TYPE('f','m','t',' ') +#define CHUNK_DATA CHUNK_TYPE('d','a','t','a') +#define CHUNK_LIST CHUNK_TYPE('L','I','S','T') +#define CHUNK_INFO CHUNK_TYPE('I','N','F','O') +#define CHUNK_INAM CHUNK_TYPE('I','N','A','M') +#define CHUNK_ICOP CHUNK_TYPE('I','C','O','P') +#define CHUNK_IART CHUNK_TYPE('I','A','R','T') + +/* wave file format identifiers */ +#define WAVE_FORMAT_PCM 0x0001 +#define WAVE_FORMAT_IMA_ADPCM 0x0011 + +/* file size for streamed file */ +#define FILE_SIZE_STREAMING 0x80000000 + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset); +static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate); +static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData); +static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength); + +#ifdef MMAPI_SUPPORT +static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 size); +#endif + +/*---------------------------------------------------------------------------- + * + * EAS_Wave_Parser + * + * This structure contains the functional interface for the Wave file parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_Wave_Parser = +{ + WaveCheckFileType, + WavePrepare, + NULL, + NULL, + WaveState, + WaveClose, + WaveReset, + WavePause, + WaveResume, + WaveLocate, + WaveSetData, + WaveGetData, + WaveGetMetaData +}; + +/*---------------------------------------------------------------------------- + * WaveCheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset) +{ + S_WAVE_STATE *pWaveData; + + /* zero the memory to insure complete initialization */ + *pHandle = NULL; + + /* read the file header */ + if (WaveParseHeader(pEASData, fileHandle, NULL) == EAS_SUCCESS) + { + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pWaveData = EAS_CMEnumData(EAS_CM_WAVE_DATA); + else + pWaveData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_WAVE_STATE)); + if (!pWaveData) + return EAS_ERROR_MALLOC_FAILED; + EAS_HWMemSet(pWaveData, 0, sizeof(S_WAVE_STATE)); + + /* return a pointer to the instance data */ + pWaveData->fileHandle = fileHandle; + pWaveData->fileOffset = offset; + *pHandle = pWaveData; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WavePrepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + + /* validate parser state */ + pWaveData = (S_WAVE_STATE*) pInstData; + if (pWaveData->streamHandle != NULL) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* back to start of file */ + pWaveData->time = 0; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->fileOffset)) != EAS_SUCCESS) + return result; + + /* parse the file header */ + if ((result = WaveParseHeader(pEASData, pWaveData->fileHandle, pWaveData)) != EAS_SUCCESS) + return result; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveState() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + * Notes: + * This interface is also exposed in the internal library for use by the other modules. + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState) +{ + S_WAVE_STATE *pWaveData; + + /* return current state */ + pWaveData = (S_WAVE_STATE*) pInstData; + if (pWaveData->streamHandle) + return EAS_PEState(pEASData, pWaveData->streamHandle, pState); + + /* if no stream handle, and time is not zero, we are done */ + if (pWaveData->time > 0) + *pState = EAS_STATE_STOPPED; + else + *pState = EAS_STATE_OPEN; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveClose() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + + pWaveData = (S_WAVE_STATE*) pInstData; + + /* close the stream */ + if (pWaveData->streamHandle) + { + if ((result = EAS_PEClose(pEASData, pWaveData->streamHandle)) != EAS_SUCCESS) + return result; + pWaveData->streamHandle = NULL; + } + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + { + +#ifdef MMAPI_SUPPORT + /* need to free the fmt chunk */ + if (pWaveData->fmtChunk != NULL) + EAS_HWFree(pEASData->hwInstData, pWaveData->fmtChunk); +#endif + + /* free the instance data */ + EAS_HWFree(pEASData->hwInstData, pWaveData); + + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveReset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* reset to first byte of data in the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEReset(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveLocate() + *---------------------------------------------------------------------------- + * Purpose: + * Rewind/fast-forward in file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * time - time (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pParserLocate) reserved for future use */ +static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate) +{ + EAS_PCM_HANDLE streamHandle; + + /* reset to first byte of data in the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PELocate(pEASData, streamHandle, time); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WavePause() + *---------------------------------------------------------------------------- + * Purpose: + * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback + * at the end of the next audio frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* pause the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEPause(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveResume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume rendering a PCM stream. Sets the gain target back to its + * previous setting and restarts playback at the end of the next audio + * frame. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + EAS_PCM_HANDLE streamHandle; + + /* resume the stream */ + streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; + if (streamHandle) + return EAS_PEResume(pEASData, streamHandle); + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; +} + +/*---------------------------------------------------------------------------- + * WaveSetData() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + S_WAVE_STATE *pWaveData = (S_WAVE_STATE*) pInstData; + + switch (param) + { + /* set metadata callback */ + case PARSER_DATA_METADATA_CB: + EAS_HWMemCpy(&pWaveData->metadata, (void*) value, sizeof(S_METADATA_CB)); + return EAS_SUCCESS; + + case PARSER_DATA_PLAYBACK_RATE: + value = (EAS_I32) (PITCH_CENTS_CONVERSION * log10((double) value / (double) (1 << 28))); + return EAS_PEUpdatePitch(pEASData, pWaveData->streamHandle, (EAS_I16) value); + + case PARSER_DATA_VOLUME: + return EAS_PEUpdateVolume(pEASData, pWaveData->streamHandle, (EAS_I16) value); + + default: + return EAS_ERROR_INVALID_PARAMETER; + } +} + +/*---------------------------------------------------------------------------- + * WaveGetData() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pEASData) reserved for future use */ +static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + S_WAVE_STATE *pWaveData; + + pWaveData = (S_WAVE_STATE*) pInstData; + switch (param) + { + /* return file type as WAVE */ + case PARSER_DATA_FILE_TYPE: + *pValue = pWaveData->fileType; + break; + +#ifdef MMAPI_SUPPORT + /* return pointer to 'fmt' chunk */ + case PARSER_DATA_FORMAT: + *pValue = (EAS_I32) pWaveData->fmtChunk; + break; +#endif + + case PARSER_DATA_GAIN_OFFSET: + *pValue = WAVE_GAIN_OFFSET; + break; + + default: + return EAS_ERROR_INVALID_PARAMETER; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WaveParseHeader() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the WAVE file header. + * + * Inputs: + * pEASData - pointer to EAS library instance data + * handle - pointer to S_WAVE_STATE for this stream + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData) +{ + S_PCM_OPEN_PARAMS params; + EAS_RESULT result; + EAS_U32 tag; + EAS_U32 fileSize; + EAS_U32 size; + EAS_I32 pos; + EAS_I32 audioOffset; + EAS_U16 usTemp; + EAS_BOOL parseDone; + EAS_U32 avgBytesPerSec; + + /* init some data (and keep lint happy) */ + params.sampleRate = 0; + params.size = 0; + audioOffset = 0; + params.decoder = 0; + params.blockSize = 0; + params.pCallbackFunc = NULL; + params.cbInstData = NULL; + params.loopSamples = 0; + params.fileHandle = fileHandle; + params.volume = 0x7fff; + params.envData = 0; + avgBytesPerSec = 8000; + + /* check for 'RIFF' tag */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag != CHUNK_RIFF) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get size */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &fileSize, EAS_FALSE)) != EAS_FALSE) + return result; + + /* check for 'WAVE' tag */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag != CHUNK_WAVE) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* this is enough to say we recognize the file */ + if (pWaveData == NULL) + return EAS_SUCCESS; + + /* check for streaming mode */ + pWaveData->flags = 0; + pWaveData->mediaLength = -1; + pWaveData->infoChunkPos = -1; + pWaveData->infoChunkSize = -1; + if (fileSize== FILE_SIZE_STREAMING) + { + pWaveData->flags |= PCM_FLAGS_STREAMING; + fileSize = 0x7fffffff; + } + + /* find out where we're at */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS) + return result; + fileSize -= 4; + + parseDone = EAS_FALSE; + for (;;) + { + /* get tag and size for next chunk */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &size, EAS_FALSE)) != EAS_FALSE) + return result; + + /* process chunk */ + pos += 8; + switch (tag) + { + case CHUNK_FMT: + +#ifdef MMAPI_SUPPORT + if ((result = SaveFmtChunk(pEASData, fileHandle, pWaveData, (EAS_I32) size)) != EAS_SUCCESS) + return result; +#endif + + /* get audio format */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + if (usTemp == WAVE_FORMAT_PCM) + { + params.decoder = EAS_DECODER_PCM; + pWaveData->fileType = EAS_FILE_WAVE_PCM; + } + else if (usTemp == WAVE_FORMAT_IMA_ADPCM) + { + params.decoder = EAS_DECODER_IMA_ADPCM; + pWaveData->fileType = EAS_FILE_WAVE_IMA_ADPCM; + } + else + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get number of channels */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + if (usTemp == 2) + pWaveData->flags |= PCM_FLAGS_STEREO; + else if (usTemp != 1) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* get sample rate */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, ¶ms.sampleRate, EAS_FALSE)) != EAS_FALSE) + return result; + + /* get stream rate */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &avgBytesPerSec, EAS_FALSE)) != EAS_FALSE) + return result; + + /* get block alignment */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + params.blockSize = usTemp; + + /* get bits per sample */ + if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) + return result; + + /* PCM, must be 8 or 16 bit samples */ + if (params.decoder == EAS_DECODER_PCM) + { + if (usTemp == 8) + pWaveData->flags |= PCM_FLAGS_8_BIT | PCM_FLAGS_UNSIGNED; + else if (usTemp != 16) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + /* for IMA ADPCM, we only support mono 4-bit ADPCM */ + else + { + if ((usTemp != 4) || (pWaveData->flags & PCM_FLAGS_STEREO)) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + } + + break; + + case CHUNK_DATA: + audioOffset = pos; + if (pWaveData->flags & PCM_FLAGS_STREAMING) + { + params.size = 0x7fffffff; + parseDone = EAS_TRUE; + } + else + { + params.size = (EAS_I32) size; + params.loopStart = size; + /* use more accurate method if possible */ + if (size <= (0x7fffffff / 1000)) + pWaveData->mediaLength = (EAS_I32) ((size * 1000) / avgBytesPerSec); + else + pWaveData->mediaLength = (EAS_I32) (size / (avgBytesPerSec / 1000)); + } + break; + + case CHUNK_LIST: + /* get the list type */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if (tag == CHUNK_INFO) + { + pWaveData->infoChunkPos = pos + 4; + pWaveData->infoChunkSize = (EAS_I32) size - 4; + } + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + if (parseDone) + break; + + /* subtract header size */ + fileSize -= 8; + + /* account for zero-padding on odd length chunks */ + if (size & 1) + size++; + + /* this check works for files with odd length last chunk and no zero-pad */ + if (size >= fileSize) + { + if (size > fileSize) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: '%c%c%c%c' chunk size exceeds length of file or is not zero-padded\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + /* subtract size of data chunk (including any zero-pad) */ + fileSize -= size; + + /* seek to next chunk */ + pos += (EAS_I32) size; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos)) != EAS_SUCCESS) + return result; + } + + /* check for valid header */ + if ((params.sampleRate == 0) || (params.size == 0)) + return EAS_ERROR_UNRECOGNIZED_FORMAT; + + /* save the pertinent information */ + pWaveData->audioOffset = audioOffset; + params.flags = pWaveData->flags; + + /* seek to data */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, audioOffset)) != EAS_SUCCESS) + return result; + + /* open a stream in the PCM engine */ + return EAS_PEOpenStream(pEASData, ¶ms, &pWaveData->streamHandle); +} + +/*---------------------------------------------------------------------------- + * WaveGetMetaData() + *---------------------------------------------------------------------------- + * Purpose: + * Process the INFO chunk and return metadata to host + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength) +{ + S_WAVE_STATE *pWaveData; + EAS_RESULT result; + EAS_I32 pos; + EAS_U32 size; + EAS_I32 infoSize; + EAS_U32 tag; + EAS_I32 restorePos; + E_EAS_METADATA_TYPE metaType; + EAS_I32 metaLen; + + /* get current position so we can restore it */ + pWaveData = (S_WAVE_STATE*) pInstData; + + /* return media length */ + *pMediaLength = pWaveData->mediaLength; + + /* did we encounter an INFO chunk? */ + if (pWaveData->infoChunkPos < 0) + return EAS_SUCCESS; + + if ((result = EAS_HWFilePos(pEASData->hwInstData, pWaveData->fileHandle, &restorePos)) != EAS_SUCCESS) + return result; + + /* offset to start of first chunk in INFO chunk */ + pos = pWaveData->infoChunkPos; + infoSize = pWaveData->infoChunkSize; + + /* read all the chunks in the INFO chunk */ + for (;;) + { + + /* seek to next chunk */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pos)) != EAS_SUCCESS) + return result; + + /* get tag and size for next chunk */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) + return result; + if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &size, EAS_FALSE)) != EAS_FALSE) + return result; + + /* process chunk */ + pos += 8; + metaType = EAS_METADATA_UNKNOWN; + switch (tag) + { + case CHUNK_INAM: + metaType = EAS_METADATA_TITLE; + break; + + case CHUNK_IART: + metaType = EAS_METADATA_AUTHOR; + break; + + case CHUNK_ICOP: + metaType = EAS_METADATA_COPYRIGHT; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n", + (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } + break; + } + + /* process known metadata */ + if (metaType != EAS_METADATA_UNKNOWN) + { + metaLen = pWaveData->metadata.bufferSize - 1; + if (metaLen > (EAS_I32) size) + metaLen = (EAS_I32) size; + if ((result = EAS_HWReadFile(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->metadata.buffer, metaLen, &metaLen)) != EAS_SUCCESS) + return result; + pWaveData->metadata.buffer[metaLen] = 0; + pWaveData->metadata.callback(metaType, pWaveData->metadata.buffer, pWaveData->metadata.pUserData); + } + + /* subtract this block */ + if (size & 1) + size++; + infoSize -= (EAS_I32) size + 8; + if (infoSize == 0) + break; + pos += (EAS_I32) size; + } + + + /* restore original position */ + return EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, restorePos); +} + +#ifdef MMAPI_SUPPORT +/*---------------------------------------------------------------------------- + * SaveFmtChunk() + *---------------------------------------------------------------------------- + * Purpose: + * Save the fmt chunk for the MMAPI library + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 fmtSize) +{ + EAS_RESULT result; + EAS_I32 pos; + EAS_I32 count; + + /* save current file position */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS) + return result; + + /* allocate a chunk of memory */ + pWaveData->fmtChunk = EAS_HWMalloc(pEASData->hwInstData, fmtSize); + if (!pWaveData->fmtChunk) + return EAS_ERROR_MALLOC_FAILED; + + /* read the fmt chunk into memory */ + if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, pWaveData->fmtChunk, fmtSize, &count)) != EAS_SUCCESS) + return result; + if (count != fmtSize) + return EAS_ERROR_FILE_READ_FAILED; + + /* restore file position */ + return EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos); +} +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefile.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefile.h new file mode 100755 index 0000000..f8814a8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefile.h @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefile.h + * + * Contents and purpose: + * Static data block for wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 439 $ + * $Date: 2006-10-26 11:53:18 -0700 (Thu, 26 Oct 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WAVEFILE_H +#define _EAS_WAVEFILE_H + +#include "eas_data.h" +#include "eas_pcm.h" + +/*---------------------------------------------------------------------------- + * + * S_WAVE_STATE + * + * This structure contains the WAVE file parser state information + *---------------------------------------------------------------------------- +*/ +typedef struct s_wave_state_tag +{ + EAS_FILE_HANDLE fileHandle; + EAS_PCM_HANDLE streamHandle; + S_METADATA_CB metadata; + EAS_U32 time; + EAS_I32 fileOffset; + EAS_I32 audioOffset; + EAS_I32 mediaLength; + EAS_U32 audioSize; + EAS_U32 flags; + EAS_I16 fileType; +#ifdef MMAPI_SUPPORT + EAS_VOID_PTR fmtChunk; +#endif + EAS_I32 infoChunkPos; + EAS_I32 infoChunkSize; +} S_WAVE_STATE; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefiledata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefiledata.c new file mode 100755 index 0000000..c224a6c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefiledata.c @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wavefiledata.c + * + * Contents and purpose: + * Static data block for wave file parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_wavefile.h" + +S_WAVE_STATE eas_WaveData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wt_IPC_frame.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wt_IPC_frame.h new file mode 100755 index 0000000..29d77aa --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wt_IPC_frame.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wt_IPC_frame.h + * + * Contents and purpose: + * This module contains data definitions for the interprocessor + * communications framework for a split-architecture synthesizer. + * + * This sample version writes IPC data to a file that can be used + * as a test vector for the DSP simulator. For a real-time system + * the file I/O is replaced with an IPC protocol in the hardware. + * + * Synchronization with the DSP is accomplished at the API level, + * i.e. the host code should call EAS_Render when it is ready to + * buffer another block of data for transmission to the DSP. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 818 $ + * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WT_IPC_FRAME_H +#define _EAS_WT_IPC_FRAME_H + +/*---------------------------------------------------------------------------- + * S_WT_FRAME + * + * This structure contains the common parameters that are updated + *for each frame of audio. + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_frame_tag +{ + EAS_I32 gainTarget; + EAS_I32 phaseIncrement; + +#if defined(_FILTER_ENABLED) + EAS_I32 k; + EAS_I32 b1; + EAS_I32 b2; +#endif +} S_WT_FRAME; + +/*---------------------------------------------------------------------------- + * S_WT_CONFIG + * + * This structure contains state data for the wavetable engine + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_config_tag +{ + EAS_U32 loopEnd; /* points to last PCM sample (not 1 beyond last) */ + EAS_U32 loopStart; /* points to first sample at start of loop */ + EAS_U32 phaseAccum; /* current sample, integer portion of phase */ + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I16 gainLeft; /* left channel gain */ + EAS_I16 gainRight; /* right channel gain */ +#endif + + EAS_I16 gain; /* current voice gain */ +} S_WT_CONFIG; + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtengine.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtengine.c new file mode 100755 index 0000000..224f60d --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtengine.c @@ -0,0 +1,661 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wtengine.c + * + * Contents and purpose: + * This file contains the critical synthesizer components that need to + * be optimized for best performance. + * + * Copyright Sonic Network Inc. 2004-2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 844 $ + * $Date: 2007-08-23 14:33:32 -0700 (Thu, 23 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +/*------------------------------------ + * includes + *------------------------------------ +*/ +#include "eas_types.h" +#include "eas_math.h" +#include "eas_audioconst.h" +#include "eas_sndlib.h" +#include "eas_wtengine.h" +#include "eas_mixer.h" + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +extern void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); +extern void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); + +#if defined(_OPTIMIZED_MONO) +extern void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); +#else +extern void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); +extern void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); +#endif + +#if defined(_FILTER_ENABLED) +extern void WT_VoiceFilter (S_FILTER_CONTROL*pFilter, S_WT_INT_FRAME *pWTIntFrame); +#endif + +#if defined(_OPTIMIZED_MONO) || !defined(NATIVE_EAS_KERNEL) +/*---------------------------------------------------------------------------- + * WT_VoiceGain + *---------------------------------------------------------------------------- + * Purpose: + * Output gain for individual voice + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pWTVoice) reserved for future use */ +void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_I32 *pMixBuffer; + EAS_PCM *pInputBuffer; + EAS_I32 gain; + EAS_I32 gainIncrement; + EAS_I32 tmp0; + EAS_I32 tmp1; + EAS_I32 tmp2; + EAS_I32 numSamples; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I32 gainLeft, gainRight; +#endif + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pMixBuffer = pWTIntFrame->pMixBuffer; + pInputBuffer = pWTIntFrame->pAudioBuffer; + + /*lint -e{703} */ + gainIncrement = (pWTIntFrame->frame.gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + if (gainIncrement < 0) + gainIncrement++; + /*lint -e{703} */ + gain = pWTIntFrame->prevGain << 16; + +#if (NUM_OUTPUT_CHANNELS == 2) + gainLeft = pWTVoice->gainLeft; + gainRight = pWTVoice->gainRight; +#endif + + while (numSamples--) { + + /* incremental gain step to prevent zipper noise */ + tmp0 = *pInputBuffer++; + gain += gainIncrement; + /*lint -e{704} */ + tmp2 = gain >> 16; + + /* scale sample by gain */ + tmp2 *= tmp0; + + + /* stereo output */ +#if (NUM_OUTPUT_CHANNELS == 2) + /*lint -e{704} */ + tmp2 = tmp2 >> 14; + + /* get the current sample in the final mix buffer */ + tmp1 = *pMixBuffer; + + /* left channel */ + tmp0 = tmp2 * gainLeft; + /*lint -e{704} */ + tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; + tmp1 += tmp0; + *pMixBuffer++ = tmp1; + + /* get the current sample in the final mix buffer */ + tmp1 = *pMixBuffer; + + /* right channel */ + tmp0 = tmp2 * gainRight; + /*lint -e{704} */ + tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; + tmp1 += tmp0; + *pMixBuffer++ = tmp1; + + /* mono output */ +#else + + /* get the current sample in the final mix buffer */ + tmp1 = *pMixBuffer; + /*lint -e{704} */ + tmp2 = tmp2 >> (NUM_MIXER_GUARD_BITS - 1); + tmp1 += tmp2; + *pMixBuffer++ = tmp1; +#endif + + } +} +#endif + +#ifndef NATIVE_EAS_KERNEL +/*---------------------------------------------------------------------------- + * WT_Interpolate + *---------------------------------------------------------------------------- + * Purpose: + * Interpolation engine for wavetable synth + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_PCM *pOutputBuffer; + EAS_I32 phaseInc; + EAS_I32 phaseFrac; + EAS_I32 acc0; + const EAS_SAMPLE *pSamples; + const EAS_SAMPLE *loopEnd; + EAS_I32 samp1; + EAS_I32 samp2; + EAS_I32 numSamples; + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pOutputBuffer = pWTIntFrame->pAudioBuffer; + + loopEnd = (const EAS_SAMPLE*) pWTVoice->loopEnd + 1; + pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; + /*lint -e{713} truncation is OK */ + phaseFrac = pWTVoice->phaseFrac; + phaseInc = pWTIntFrame->frame.phaseIncrement; + + /* fetch adjacent samples */ +#if defined(_8_BIT_SAMPLES) + /*lint -e{701} */ + samp1 = pSamples[0] << 8; + /*lint -e{701} */ + samp2 = pSamples[1] << 8; +#else + samp1 = pSamples[0]; + samp2 = pSamples[1]; +#endif + + while (numSamples--) { + + /* linear interpolation */ + acc0 = samp2 - samp1; + acc0 = acc0 * phaseFrac; + /*lint -e{704} */ + acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); + + /* save new output sample in buffer */ + /*lint -e{704} */ + *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); + + /* increment phase */ + phaseFrac += phaseInc; + /*lint -e{704} */ + acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; + + /* next sample */ + if (acc0 > 0) { + + /* advance sample pointer */ + pSamples += acc0; + phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); + + /* check for loop end */ + acc0 = (EAS_I32) (pSamples - loopEnd); + if (acc0 >= 0) + pSamples = (const EAS_SAMPLE*) pWTVoice->loopStart + acc0; + + /* fetch new samples */ +#if defined(_8_BIT_SAMPLES) + /*lint -e{701} */ + samp1 = pSamples[0] << 8; + /*lint -e{701} */ + samp2 = pSamples[1] << 8; +#else + samp1 = pSamples[0]; + samp2 = pSamples[1]; +#endif + } + } + + /* save pointer and phase */ + pWTVoice->phaseAccum = (EAS_U32) pSamples; + pWTVoice->phaseFrac = (EAS_U32) phaseFrac; +} +#endif + +#ifndef NATIVE_EAS_KERNEL +/*---------------------------------------------------------------------------- + * WT_InterpolateNoLoop + *---------------------------------------------------------------------------- + * Purpose: + * Interpolation engine for wavetable synth + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_PCM *pOutputBuffer; + EAS_I32 phaseInc; + EAS_I32 phaseFrac; + EAS_I32 acc0; + const EAS_SAMPLE *pSamples; + EAS_I32 samp1; + EAS_I32 samp2; + EAS_I32 numSamples; + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pOutputBuffer = pWTIntFrame->pAudioBuffer; + + phaseInc = pWTIntFrame->frame.phaseIncrement; + pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; + phaseFrac = (EAS_I32)pWTVoice->phaseFrac; + + /* fetch adjacent samples */ +#if defined(_8_BIT_SAMPLES) + /*lint -e{701} */ + samp1 = pSamples[0] << 8; + /*lint -e{701} */ + samp2 = pSamples[1] << 8; +#else + samp1 = pSamples[0]; + samp2 = pSamples[1]; +#endif + + while (numSamples--) { + + + /* linear interpolation */ + acc0 = samp2 - samp1; + acc0 = acc0 * phaseFrac; + /*lint -e{704} */ + acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); + + /* save new output sample in buffer */ + /*lint -e{704} */ + *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); + + /* increment phase */ + phaseFrac += phaseInc; + /*lint -e{704} */ + acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; + + /* next sample */ + if (acc0 > 0) { + + /* advance sample pointer */ + pSamples += acc0; + phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); + + /* fetch new samples */ +#if defined(_8_BIT_SAMPLES) + /*lint -e{701} */ + samp1 = pSamples[0] << 8; + /*lint -e{701} */ + samp2 = pSamples[1] << 8; +#else + samp1 = pSamples[0]; + samp2 = pSamples[1]; +#endif + } + } + + /* save pointer and phase */ + pWTVoice->phaseAccum = (EAS_U32) pSamples; + pWTVoice->phaseFrac = (EAS_U32) phaseFrac; +} +#endif + +#if defined(_FILTER_ENABLED) && !defined(NATIVE_EAS_KERNEL) +/*---------------------------------------------------------------------------- + * WT_VoiceFilter + *---------------------------------------------------------------------------- + * Purpose: + * Implements a 2-pole filter + * + * Inputs: + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +void WT_VoiceFilter (S_FILTER_CONTROL *pFilter, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_PCM *pAudioBuffer; + EAS_I32 k; + EAS_I32 b1; + EAS_I32 b2; + EAS_I32 z1; + EAS_I32 z2; + EAS_I32 acc0; + EAS_I32 acc1; + EAS_I32 numSamples; + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pAudioBuffer = pWTIntFrame->pAudioBuffer; + + z1 = pFilter->z1; + z2 = pFilter->z2; + b1 = -pWTIntFrame->frame.b1; + + /*lint -e{702} */ + b2 = -pWTIntFrame->frame.b2 >> 1; + + /*lint -e{702} */ + k = pWTIntFrame->frame.k >> 1; + + while (numSamples--) + { + + /* do filter calculations */ + acc0 = *pAudioBuffer; + acc1 = z1 * b1; + acc1 += z2 * b2; + acc0 = acc1 + k * acc0; + z2 = z1; + + /*lint -e{702} */ + z1 = acc0 >> 14; + *pAudioBuffer++ = (EAS_I16) z1; + } + + /* save delay values */ + pFilter->z1 = (EAS_I16) z1; + pFilter->z2 = (EAS_I16) z2; +} +#endif + +/*---------------------------------------------------------------------------- + * WT_NoiseGenerator + *---------------------------------------------------------------------------- + * Purpose: + * Generate pseudo-white noise using PRNG and interpolation engine + * + * Inputs: + * + * Outputs: + * + * Notes: + * This output is scaled -12dB to prevent saturation in the filter. For a + * high quality synthesizer, the output can be set to full scale, however + * if the filter is used, it can overflow with certain coefficients. In this + * case, either a saturation operation should take in the filter before + * scaling back to 16 bits or the signal path should be increased to 18 bits + * or more. + *---------------------------------------------------------------------------- +*/ + void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) + { + EAS_PCM *pOutputBuffer; + EAS_I32 phaseInc; + EAS_I32 tmp0; + EAS_I32 tmp1; + EAS_I32 nInterpolatedSample; + EAS_I32 numSamples; + + /* initialize some local variables */ + numSamples = pWTIntFrame->numSamples; + pOutputBuffer = pWTIntFrame->pAudioBuffer; + phaseInc = pWTIntFrame->frame.phaseIncrement; + + /* get last two samples generated */ + /*lint -e{704} */ + tmp0 = (EAS_I32) (pWTVoice->phaseAccum) >> 18; + /*lint -e{704} */ + tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; + + /* generate a buffer of noise */ + while (numSamples--) { + nInterpolatedSample = MULT_AUDIO_COEF( tmp0, (PHASE_ONE - pWTVoice->phaseFrac)); + nInterpolatedSample += MULT_AUDIO_COEF( tmp1, pWTVoice->phaseFrac); + *pOutputBuffer++ = (EAS_PCM) nInterpolatedSample; + + /* update PRNG */ + pWTVoice->phaseFrac += (EAS_U32) phaseInc; + if (GET_PHASE_INT_PART(pWTVoice->phaseFrac)) { + tmp0 = tmp1; + pWTVoice->phaseAccum = pWTVoice->loopEnd; + pWTVoice->loopEnd = (5 * pWTVoice->loopEnd + 1); + tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; + pWTVoice->phaseFrac = GET_PHASE_FRAC_PART(pWTVoice->phaseFrac); + } + + } +} + +#ifndef _OPTIMIZED_MONO +/*---------------------------------------------------------------------------- + * WT_ProcessVoice + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the block processing for one voice. It is isolated + * from the main synth code to allow for various implementation-specific + * optimizations. It calls the interpolator, filter, and gain routines + * appropriate for a particular configuration. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + + /* use noise generator */ + if (pWTVoice->loopStart == WT_NOISE_GENERATOR) + WT_NoiseGenerator(pWTVoice, pWTIntFrame); + + /* generate interpolated samples for looped waves */ + else if (pWTVoice->loopStart != pWTVoice->loopEnd) + WT_Interpolate(pWTVoice, pWTIntFrame); + + /* generate interpolated samples for unlooped waves */ + else + { + WT_InterpolateNoLoop(pWTVoice, pWTIntFrame); + } + +#ifdef _FILTER_ENABLED + if (pWTIntFrame->frame.k != 0) + WT_VoiceFilter(&pWTVoice->filter, pWTIntFrame); +#endif + +//2 TEST NEW MIXER FUNCTION +#ifdef UNIFIED_MIXER + { + EAS_I32 gainLeft, gainIncLeft; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I32 gainRight, gainIncRight; +#endif + + gainLeft = (pWTIntFrame->prevGain * pWTVoice->gainLeft) << 1; + gainIncLeft = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainLeft) << 1) - gainLeft) >> SYNTH_UPDATE_PERIOD_IN_BITS; + +#if (NUM_OUTPUT_CHANNELS == 2) + gainRight = (pWTIntFrame->prevGain * pWTVoice->gainRight) << 1; + gainIncRight = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainRight) << 1) - gainRight) >> SYNTH_UPDATE_PERIOD_IN_BITS; + EAS_MixStream( + pWTIntFrame->pAudioBuffer, + pWTIntFrame->pMixBuffer, + pWTIntFrame->numSamples, + gainLeft, + gainRight, + gainIncLeft, + gainIncRight, + MIX_FLAGS_STEREO_OUTPUT); + +#else + EAS_MixStream( + pWTIntFrame->pAudioBuffer, + pWTIntFrame->pMixBuffer, + pWTIntFrame->numSamples, + gainLeft, + 0, + gainIncLeft, + 0, + 0); +#endif + } + +#else + /* apply gain, and left and right gain */ + WT_VoiceGain(pWTVoice, pWTIntFrame); +#endif +} +#endif + +#if defined(_OPTIMIZED_MONO) && !defined(NATIVE_EAS_KERNEL) +/*---------------------------------------------------------------------------- + * WT_InterpolateMono + *---------------------------------------------------------------------------- + * Purpose: + * A C version of the sample interpolation + gain routine, optimized for mono. + * It's not pretty, but it matches the assembly code exactly. + * + * Inputs: + * + * Outputs: + * + * Notes: + *---------------------------------------------------------------------------- +*/ +void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + EAS_I32 *pMixBuffer; + const EAS_I8 *pLoopEnd; + const EAS_I8 *pCurrentPhaseInt; + EAS_I32 numSamples; + EAS_I32 gain; + EAS_I32 gainIncrement; + EAS_I32 currentPhaseFrac; + EAS_I32 phaseInc; + EAS_I32 tmp0; + EAS_I32 tmp1; + EAS_I32 tmp2; + EAS_I8 *pLoopStart; + + numSamples = pWTIntFrame->numSamples; + pMixBuffer = pWTIntFrame->pMixBuffer; + + /* calculate gain increment */ + gainIncrement = (pWTIntFrame->gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); + if (gainIncrement < 0) + gainIncrement++; + gain = pWTIntFrame->prevGain << 16; + + pCurrentPhaseInt = pWTVoice->pPhaseAccum; + currentPhaseFrac = pWTVoice->phaseFrac; + phaseInc = pWTIntFrame->phaseIncrement; + + pLoopStart = pWTVoice->pLoopStart; + pLoopEnd = pWTVoice->pLoopEnd + 1; + +InterpolationLoop: + tmp0 = (EAS_I32)(pCurrentPhaseInt - pLoopEnd); + if (tmp0 >= 0) + pCurrentPhaseInt = pLoopStart + tmp0; + + tmp0 = *pCurrentPhaseInt; + tmp1 = *(pCurrentPhaseInt + 1); + + tmp2 = phaseInc + currentPhaseFrac; + + tmp1 = tmp1 - tmp0; + tmp1 = tmp1 * currentPhaseFrac; + + tmp1 = tmp0 + (tmp1 >> NUM_EG1_FRAC_BITS); + + pCurrentPhaseInt += (tmp2 >> NUM_PHASE_FRAC_BITS); + currentPhaseFrac = tmp2 & PHASE_FRAC_MASK; + + gain += gainIncrement; + tmp2 = (gain >> SYNTH_UPDATE_PERIOD_IN_BITS); + + tmp0 = *pMixBuffer; + tmp2 = tmp1 * tmp2; + tmp2 = (tmp2 >> 9); + tmp0 = tmp2 + tmp0; + *pMixBuffer++ = tmp0; + + numSamples--; + if (numSamples > 0) + goto InterpolationLoop; + + pWTVoice->pPhaseAccum = pCurrentPhaseInt; + pWTVoice->phaseFrac = currentPhaseFrac; + /*lint -e{702} */ + pWTVoice->gain = (EAS_I16)(gain >> SYNTH_UPDATE_PERIOD_IN_BITS); +} +#endif + +#ifdef _OPTIMIZED_MONO +/*---------------------------------------------------------------------------- + * WT_ProcessVoice + *---------------------------------------------------------------------------- + * Purpose: + * This routine does the block processing for one voice. It is isolated + * from the main synth code to allow for various implementation-specific + * optimizations. It calls the interpolator, filter, and gain routines + * appropriate for a particular configuration. + * + * Inputs: + * + * Outputs: + * + * Notes: + * This special version works handles an optimized mono-only signal + * without filters + *---------------------------------------------------------------------------- +*/ +void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) +{ + + /* use noise generator */ + if (pWTVoice->loopStart== WT_NOISE_GENERATOR) + { + WT_NoiseGenerator(pWTVoice, pWTIntFrame); + WT_VoiceGain(pWTVoice, pWTIntFrame); + } + + /* or generate interpolated samples */ + else + { + WT_InterpolateMono(pWTVoice, pWTIntFrame); + } +} +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtengine.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtengine.h new file mode 100755 index 0000000..bba7a5e --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtengine.h @@ -0,0 +1,171 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wtengine.h + * + * Contents and purpose: + * This file defines the interface for wavetable synthesis engine + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 818 $ + * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WTENGINE_H +#define _EAS_WTENGINE_H + +/* option sanity check */ +#if defined(_OPTIMIZED_MONO) && defined(_FILTER_ENABLED) +#error "Incompatible build settings: _OPTIMIZED_MONO cannot be used with _FILTER_ENABLED" +#endif + +#if defined(_OPTIMIZED_MONO) && (NUM_OUTPUT_CHANNELS != 1) +#error "Incompatible build settings: _OPTIMIZED_MONO can only be used with NUM_OUTPUT_CHANNELS = 1" +#endif + +#include "eas_wt_IPC_frame.h" + +/*---------------------------------------------------------------------------- + * defines + *---------------------------------------------------------------------------- +*/ +#define WT_NOISE_GENERATOR 0xffffffff + +/*---------------------------------------------------------------------------- + * typedefs + *---------------------------------------------------------------------------- +*/ + +/*---------------------------------------------------------------------------- + * S_WT_INT_FRAME + * + * This structure includes S_WT_FRAME plus the bus mixing + * parameters for the internal voices. + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_int_frame_tag +{ + S_WT_FRAME frame; + EAS_PCM *pAudioBuffer; + EAS_I32 *pMixBuffer; + EAS_I32 numSamples; + EAS_I32 prevGain; +} S_WT_INT_FRAME; + +#if defined(_FILTER_ENABLED) +/*---------------------------------------------------------------------------- + * S_FILTER_CONTROL data structure + *---------------------------------------------------------------------------- +*/ +typedef struct s_filter_control_tag +{ + EAS_I16 z1; /* 1 sample delay state variable */ + EAS_I16 z2; /* 2 sample delay state variable */ +} S_FILTER_CONTROL; +#endif + +/*------------------------------------ + * S_LFO_CONTROL data structure + *------------------------------------ +*/ +typedef struct s_lfo_control_tag +{ + EAS_I16 lfoValue; /* LFO current output value */ + EAS_I16 lfoPhase; /* LFO current phase */ +} S_LFO_CONTROL; + +/* bit definitions for S_WT_VOICE:flags */ +#define WT_FLAGS_ADPCM_NIBBLE 1 /* high/low nibble flag */ +#define WT_FLAGS_ADPCM_READY 2 /* first 2 samples are decoded */ +#define WT_FLAGS_USE_ADPCM 4 /* sample is ADPCM encoded */ + +/* eg1State and eg2State */ +typedef enum { + eEnvelopeStateInit = 0, + eEnvelopeStateDelay, + eEnvelopeStateAttack, + eEnvelopeStateHold, + eEnvelopeStateDecay, + eEnvelopeStateSustain, + eEnvelopeStateRelease, + eEnvelopeStateMuting, + eEnvelopeStateMuted, + eEnvelopeStateInvalid /* should never be in this state! */ +} E_ENVELOPE_STATE; + +#define DEFAULT_EG1_STATE eEnvelopeStateAttack +#define DEFAULT_EG1_VALUE 0 +#define DEFAULT_EG1_INCREMENT 0 +#define DEFAULT_EG2_STATE eEnvelopeStateAttack +#define DEFAULT_EG2_VALUE 0 +#define DEFAULT_EG2_INCREMENT 0 + +/*---------------------------------------------------------------------------- + * S_WT_VOICE + * + * This structure contains state data for the wavetable engine + *---------------------------------------------------------------------------- +*/ +typedef struct s_wt_voice_tag +{ + EAS_U32 loopEnd; /* points to last PCM sample (not 1 beyond last) */ + EAS_U32 loopStart; /* points to first sample at start of loop */ + EAS_U32 phaseAccum; /* current sample, integer portion of phase */ + EAS_U32 phaseFrac; /* fractional portion of phase */ + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_I16 gainLeft; /* current gain, left ch */ + EAS_I16 gainRight; /* current gain, right ch */ +#endif + +#if defined(_FILTER_ENABLED) + S_FILTER_CONTROL filter; /* low pass filter */ +#endif + + S_LFO_CONTROL modLFO; /* modulator LFO */ + +#ifdef DLS_SYNTHESIZER + S_LFO_CONTROL vibLFO; /* vibrato LFO */ +#endif + + /* envelope control */ + EAS_I16 eg1Value; + EAS_I16 eg2Value; + EAS_I16 eg1Increment; + EAS_I16 eg2Increment; + EAS_U8 eg1State; + EAS_U8 eg2State; + + EAS_U16 artIndex; /* index to articulation params */ + +} S_WT_VOICE; + +/*---------------------------------------------------------------------------- + * prototypes + *---------------------------------------------------------------------------- +*/ +EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update); +void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); + +#ifdef EAS_SPLIT_WT_SYNTH +void WTE_ConfigVoice (EAS_I32 voiceNum, S_WT_CONFIG *pWTConfig, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +void WTE_ProcessVoice (EAS_I32 voiceNum, S_WT_FRAME *pWTParams, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +#endif + +#endif diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtsynth.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtsynth.c new file mode 100755 index 0000000..45cf4b1 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtsynth.c @@ -0,0 +1,1257 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wtsynth.c + * + * Contents and purpose: + * Implements the synthesizer functions. + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 795 $ + * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ + *---------------------------------------------------------------------------- +*/ + +// includes +#include "eas_data.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_math.h" +#include "eas_synth_protos.h" +#include "eas_wtsynth.h" +#include "eas_pan.h" + +#ifdef DLS_SYNTHESIZER +#include "eas_dlssynth.h" +#endif + +#ifdef _METRICS_ENABLED +#include "eas_perf.h" +#endif + +/* local prototypes */ +static EAS_RESULT WT_Initialize(S_VOICE_MGR *pVoiceMgr); +static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); +static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); +static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); +static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); +static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); +static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents); +static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain); +static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv); +static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv); + +#ifdef EAS_SPLIT_WT_SYNTH +extern EAS_BOOL WTE_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer); +extern EAS_BOOL WTE_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain); +#endif + +#ifdef _FILTER_ENABLED +static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt); +#endif + +#ifdef _STATS +extern double statsPhaseIncrement; +extern double statsMaxPhaseIncrement; +extern long statsPhaseSampleCount; +extern double statsSampleSize; +extern long statsSampleCount; +#endif + +/*---------------------------------------------------------------------------- + * Synthesizer interface + *---------------------------------------------------------------------------- +*/ + +const S_SYNTH_INTERFACE wtSynth = +{ + WT_Initialize, + WT_StartVoice, + WT_UpdateVoice, + WT_ReleaseVoice, + WT_MuteVoice, + WT_SustainPedal, + WT_UpdateChannel +}; + +#ifdef EAS_SPLIT_WT_SYNTH +const S_FRAME_INTERFACE wtFrameInterface = +{ + WTE_StartFrame, + WTE_EndFrame +}; +#endif + +/*---------------------------------------------------------------------------- + * WT_Initialize() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * pVoice - pointer to voice to initialize + * + * Outputs: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WT_Initialize (S_VOICE_MGR *pVoiceMgr) +{ + EAS_INT i; + + for (i = 0; i < NUM_WT_VOICES; i++) + { + + pVoiceMgr->wtVoices[i].artIndex = DEFAULT_ARTICULATION_INDEX; + + pVoiceMgr->wtVoices[i].eg1State = DEFAULT_EG1_STATE; + pVoiceMgr->wtVoices[i].eg1Value = DEFAULT_EG1_VALUE; + pVoiceMgr->wtVoices[i].eg1Increment = DEFAULT_EG1_INCREMENT; + + pVoiceMgr->wtVoices[i].eg2State = DEFAULT_EG2_STATE; + pVoiceMgr->wtVoices[i].eg2Value = DEFAULT_EG2_VALUE; + pVoiceMgr->wtVoices[i].eg2Increment = DEFAULT_EG2_INCREMENT; + + /* left and right gain values are needed only if stereo output */ +#if (NUM_OUTPUT_CHANNELS == 2) + pVoiceMgr->wtVoices[i].gainLeft = DEFAULT_VOICE_GAIN; + pVoiceMgr->wtVoices[i].gainRight = DEFAULT_VOICE_GAIN; +#endif + + pVoiceMgr->wtVoices[i].phaseFrac = DEFAULT_PHASE_FRAC; + pVoiceMgr->wtVoices[i].phaseAccum = DEFAULT_PHASE_INT; + +#ifdef _FILTER_ENABLED + pVoiceMgr->wtVoices[i].filter.z1 = DEFAULT_FILTER_ZERO; + pVoiceMgr->wtVoices[i].filter.z2 = DEFAULT_FILTER_ZERO; +#endif + } + + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * WT_ReleaseVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being released. + * + * Inputs: + * pEASData - pointer to S_EAS_DATA + * pVoice - pointer to voice to release + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoice) used in some implementations */ +static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + S_WT_VOICE *pWTVoice; + const S_ARTICULATION *pArticulation; + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + DLS_ReleaseVoice(pVoiceMgr, pSynth, pVoice, voiceNum); + return; + } +#endif + + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pArticulation = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; + + /* release EG1 */ + pWTVoice->eg1State = eEnvelopeStateRelease; + pWTVoice->eg1Increment = pArticulation->eg1.releaseTime; + + /* + The spec says we should release EG2, but doing so with the current + voicing is causing clicks. This fix will need to be coordinated with + a new sound library release + */ + + /* release EG2 */ + pWTVoice->eg2State = eEnvelopeStateRelease; + pWTVoice->eg2Increment = pArticulation->eg2.releaseTime; +} + +/*---------------------------------------------------------------------------- + * WT_MuteVoice() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is being muted. + * + * Inputs: + * pVoice - pointer to voice to release + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pSynth) used in some implementations */ +static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) +{ + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + DLS_MuteVoice(pVoiceMgr, pSynth, pVoice, voiceNum); + return; + } +#endif + + /* clear deferred action flags */ + pVoice->voiceFlags &= + ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | + VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF | + VOICE_FLAG_DEFER_MUTE); + + /* set the envelope state */ + pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateMuted; + pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateMuted; +} + +/*---------------------------------------------------------------------------- + * WT_SustainPedal() + *---------------------------------------------------------------------------- + * Purpose: + * The selected voice is held due to sustain pedal + * + * Inputs: + * pVoice - pointer to voice to sustain + * + * Outputs: + * None + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pChannel) used in some implementations */ +static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) +{ + S_WT_VOICE *pWTVoice; + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + { + DLS_SustainPedal(pVoiceMgr, pSynth, pVoice, pChannel, voiceNum); + return; + } +#endif + + /* don't catch the voice if below the sustain level */ + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + if (pWTVoice->eg1Value < pSynth->pEAS->pArticulations[pWTVoice->artIndex].eg1.sustainLevel) + return; + + /* sustain flag is set, damper pedal is on */ + /* defer releasing this note until the damper pedal is off */ + pWTVoice->eg1State = eEnvelopeStateDecay; + pVoice->voiceState = eVoiceStatePlay; + + /* + because sustain pedal is on, this voice + should defer releasing its note + */ + pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; + +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_SustainPedal: defer note off because sustain pedal is on\n"); */ } +#endif +} + +/*---------------------------------------------------------------------------- + * WT_StartVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Assign the region for the given instrument using the midi key number + * and the RPN2 (coarse tuning) value. By using RPN2 as part of the + * region selection process, we reduce the amount a given sample has + * to be transposed by selecting the closest recorded root instead. + * + * This routine is the second half of SynthAssignRegion(). + * If the region was successfully found by SynthFindRegionIndex(), + * then assign the region's parameters to the voice. + * + * Setup and initialize the following voice parameters: + * m_nRegionIndex + * + * Inputs: + * pVoice - ptr to the voice we have assigned for this channel + * nRegionIndex - index of the region + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * success - could find and assign the region for this voice's note otherwise + * failure - could not find nor assign the region for this voice's note + * + * Side Effects: + * psSynthObject->m_sVoice[].m_nRegionIndex is assigned + * psSynthObject->m_sVoice[] parameters are assigned + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) +{ + S_WT_VOICE *pWTVoice; + const S_WT_REGION *pRegion; + const S_ARTICULATION *pArt; + S_SYNTH_CHANNEL *pChannel; + +#if (NUM_OUTPUT_CHANNELS == 2) + EAS_INT pan; +#endif + +#ifdef EAS_SPLIT_WT_SYNTH + S_WT_CONFIG wtConfig; +#endif + + /* no samples have been synthesized for this note yet */ + pVoice->regionIndex = regionIndex; + pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + + /* get the articulation index for this region */ + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pChannel = &pSynth->channels[pVoice->channel & 15]; + + /* update static channel parameters */ + if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS) + WT_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15); + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + return DLS_StartVoice(pVoiceMgr, pSynth, pVoice, voiceNum, regionIndex); +#endif + + pRegion = &(pSynth->pEAS->pWTRegions[regionIndex]); + pWTVoice->artIndex = pRegion->artIndex; + +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ } +#endif + + pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; + + /* MIDI note on puts this voice into attack state */ + pWTVoice->eg1State = eEnvelopeStateAttack; + pWTVoice->eg1Value = 0; + pWTVoice->eg1Increment = pArt->eg1.attackTime; + pWTVoice->eg2State = eEnvelopeStateAttack; + pWTVoice->eg2Value = 0; + pWTVoice->eg2Increment = pArt->eg2.attackTime; + + /* init the LFO */ + pWTVoice->modLFO.lfoValue = 0; + pWTVoice->modLFO.lfoPhase = -pArt->lfoDelay; + + pVoice->gain = 0; + +#if (NUM_OUTPUT_CHANNELS == 2) + /* + Get the Midi CC10 pan value for this voice's channel + convert the pan value to an "angle" representation suitable for + our sin, cos calculator. This representation is NOT necessarily the same + as the transform in the GM manuals because of our sin, cos calculator. + "angle" = (CC10 - 64)/128 + */ + pan = (EAS_INT) pSynth->channels[pVoice->channel & 15].pan - 64; + pan += pArt->pan; + EAS_CalcPanControl(pan, &pWTVoice->gainLeft, &pWTVoice->gainRight); +#endif + +#ifdef _FILTER_ENABLED + /* clear out the filter states */ + pWTVoice->filter.z1 = 0; + pWTVoice->filter.z2 = 0; +#endif + + /* if this wave is to be generated using noise generator */ + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_USE_WAVE_GENERATOR) + { + pWTVoice->phaseAccum = 4574296; + pWTVoice->loopStart = WT_NOISE_GENERATOR; + pWTVoice->loopEnd = 4574295; + } + + /* normal sample */ + else + { + +#ifdef EAS_SPLIT_WT_SYNTH + if (voiceNum < NUM_PRIMARY_VOICES) + pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; + else + pWTVoice->phaseAccum = pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; +#else + pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; +#endif + + if (pRegion->region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED) + { + pWTVoice->loopStart = pWTVoice->phaseAccum + pRegion->loopStart; + pWTVoice->loopEnd = pWTVoice->phaseAccum + pRegion->loopEnd - 1; + } + else + pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pEAS->pSampleLen[pRegion->waveIndex] - 1; + } + +#ifdef EAS_SPLIT_WT_SYNTH + /* configure off-chip voices */ + if (voiceNum >= NUM_PRIMARY_VOICES) + { + wtConfig.phaseAccum = pWTVoice->phaseAccum; + wtConfig.loopStart = pWTVoice->loopStart; + wtConfig.loopEnd = pWTVoice->loopEnd; + wtConfig.gain = pVoice->gain; + +#if (NUM_OUTPUT_CHANNELS == 2) + wtConfig.gainLeft = pWTVoice->gainLeft; + wtConfig.gainRight = pWTVoice->gainRight; +#endif + + WTE_ConfigVoice(voiceNum - NUM_PRIMARY_VOICES, &wtConfig, pVoiceMgr->pFrameBuffer); + } +#endif + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * WT_CheckSampleEnd + *---------------------------------------------------------------------------- + * Purpose: + * Check for end of sample and calculate number of samples to synthesize + * + * Inputs: + * + * Outputs: + * + * Notes: + * + *---------------------------------------------------------------------------- +*/ +EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update) +{ + EAS_U32 endPhaseAccum; + EAS_U32 endPhaseFrac; + EAS_I32 numSamples; + EAS_BOOL done = EAS_FALSE; + + /* check to see if we hit the end of the waveform this time */ + /*lint -e{703} use shift for performance */ + endPhaseFrac = pWTVoice->phaseFrac + (pWTIntFrame->frame.phaseIncrement << SYNTH_UPDATE_PERIOD_IN_BITS); + endPhaseAccum = pWTVoice->phaseAccum + GET_PHASE_INT_PART(endPhaseFrac); + if (endPhaseAccum >= pWTVoice->loopEnd) + { + /* calculate how far current ptr is from end */ + numSamples = (EAS_I32) (pWTVoice->loopEnd - pWTVoice->phaseAccum); + + /* now account for the fractional portion */ + /*lint -e{703} use shift for performance */ + numSamples = (EAS_I32) ((numSamples << NUM_PHASE_FRAC_BITS) - pWTVoice->phaseFrac); + if (pWTIntFrame->frame.phaseIncrement) { + pWTIntFrame->numSamples = 1 + (numSamples / pWTIntFrame->frame.phaseIncrement); + } else { + pWTIntFrame->numSamples = numSamples; + } + + /* sound will be done this frame */ + done = EAS_TRUE; + } + + /* update data for off-chip synth */ + if (update) + { + pWTVoice->phaseFrac = endPhaseFrac; + pWTVoice->phaseAccum = endPhaseAccum; + } + + return done; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateVoice() + *---------------------------------------------------------------------------- + * Purpose: + * Synthesize a block of samples for the given voice. + * Use linear interpolation. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * number of samples actually written to buffer + * + * Side Effects: + * - samples are added to the presently free buffer + * + *---------------------------------------------------------------------------- +*/ +static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples) +{ + S_WT_VOICE *pWTVoice; + S_WT_INT_FRAME intFrame; + S_SYNTH_CHANNEL *pChannel; + const S_WT_REGION *pWTRegion; + const S_ARTICULATION *pArt; + EAS_I32 temp; + EAS_BOOL done; + +#ifdef DLS_SYNTHESIZER + if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) + return DLS_UpdateVoice(pVoiceMgr, pSynth, pVoice, voiceNum, pMixBuffer, numSamples); +#endif + + /* establish pointers to critical data */ + pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; + pWTRegion = &pSynth->pEAS->pWTRegions[pVoice->regionIndex & REGION_INDEX_MASK]; + pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; + pChannel = &pSynth->channels[pVoice->channel & 15]; + intFrame.prevGain = pVoice->gain; + + /* update the envelopes */ + WT_UpdateEG1(pWTVoice, &pArt->eg1); + WT_UpdateEG2(pWTVoice, &pArt->eg2); + + /* update the LFO */ + WT_UpdateLFO(&pWTVoice->modLFO, pArt->lfoFreq); + +#ifdef _FILTER_ENABLED + /* calculate filter if library uses filter */ + if (pSynth->pEAS->libAttr & LIB_FORMAT_FILTER_ENABLED) + WT_UpdateFilter(pWTVoice, &intFrame, pArt); + else + intFrame.frame.k = 0; +#endif + + /* update the gain */ + intFrame.frame.gainTarget = WT_UpdateGain(pVoice, pWTVoice, pArt, pChannel, pWTRegion->gain); + + /* calculate base pitch*/ + temp = pChannel->staticPitch + pWTRegion->tuning; + + /* include global transpose */ + if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) + temp += pVoice->note * 100; + else + temp += (pVoice->note + pSynth->globalTranspose) * 100; + intFrame.frame.phaseIncrement = WT_UpdatePhaseInc(pWTVoice, pArt, pChannel, temp); + + /* call into engine to generate samples */ + intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer; + intFrame.pMixBuffer = pMixBuffer; + intFrame.numSamples = numSamples; + + /* check for end of sample */ + if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd)) + done = WT_CheckSampleEnd(pWTVoice, &intFrame, (EAS_BOOL) (voiceNum >= NUM_PRIMARY_VOICES)); + else + done = EAS_FALSE; + + if (intFrame.numSamples < 0) intFrame.numSamples = 0; + +#ifdef EAS_SPLIT_WT_SYNTH + if (voiceNum < NUM_PRIMARY_VOICES) + { +#ifndef _SPLIT_WT_TEST_HARNESS + WT_ProcessVoice(pWTVoice, &intFrame); +#endif + } + else + WTE_ProcessVoice(voiceNum - NUM_PRIMARY_VOICES, &intFrame.frame, pVoiceMgr->pFrameBuffer); +#else + WT_ProcessVoice(pWTVoice, &intFrame); +#endif + + /* clear flag */ + pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; + + /* if voice has finished, set flag for voice manager */ + if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted)) + done = EAS_TRUE; + + /* if the update interval has elapsed, then force the current gain to the next + * gain since we never actually reach the next gain when ramping -- we just get + * very close to the target gain. + */ + pVoice->gain = (EAS_I16) intFrame.frame.gainTarget; + + return done; +} + +/*---------------------------------------------------------------------------- + * WT_UpdatePhaseInc() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the phase increment + * + * Inputs: + * pVoice - pointer to the voice being updated + * psRegion - pointer to the region + * psArticulation - pointer to the articulation + * nChannelPitchForThisVoice - the portion of the pitch that is fixed for this + * voice during the duration of this synthesis + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * set the phase increment for this voice + *---------------------------------------------------------------------------- +*/ +static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents) +{ + EAS_I32 temp; + + /*pitchCents due to CC1 = LFO * (CC1 / 128) * DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS */ + temp = MULT_EG1_EG1(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS, + ((pChannel->modWheel) << (NUM_EG1_FRAC_BITS -7))); + + /* pitchCents due to channel pressure = LFO * (channel pressure / 128) * DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS */ + temp += MULT_EG1_EG1(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS, + ((pChannel->channelPressure) << (NUM_EG1_FRAC_BITS -7))); + + /* now multiply the (channel pressure + CC1) pitch values by the LFO value */ + temp = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, temp); + + /* + add in the LFO pitch due to + channel pressure and CC1 along with + the LFO pitch, the EG2 pitch, and the + "static" pitch for this voice on this channel + */ + temp += pitchCents + + (MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToPitch)) + + (MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToPitch)); + + /* convert from cents to linear phase increment */ + return EAS_Calculate2toX(temp); +} + +/*---------------------------------------------------------------------------- + * WT_UpdateChannel() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate and assign static channel parameters + * These values only need to be updated if one of the controller values + * for this channel changes + * + * Inputs: + * nChannel - channel to update + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - the given channel's static gain and static pitch are updated + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, pVoiceMgr) reserved for future use */ +static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) +{ + EAS_I32 staticGain; + EAS_I32 pitchBend; + S_SYNTH_CHANNEL *pChannel; + + pChannel = &pSynth->channels[channel]; + + /* + nChannelGain = (CC7 * CC11)^2 * master volume + where CC7 == 100 by default, CC11 == 127, master volume == 32767 + */ + staticGain = MULT_EG1_EG1((pChannel->volume) << (NUM_EG1_FRAC_BITS - 7), + (pChannel->expression) << (NUM_EG1_FRAC_BITS - 7)); + + /* staticGain has to be squared */ + staticGain = MULT_EG1_EG1(staticGain, staticGain); + + pChannel->staticGain = (EAS_I16) MULT_EG1_EG1(staticGain, pSynth->masterVolume); + + /* + calculate pitch bend: RPN0 * ((2*pitch wheel)/16384 -1) + However, if we use the EG1 macros, remember that EG1 has a full + scale value of 32768 (instead of 16384). So instead of multiplying + by 2, multiply by 4 (left shift by 2), and subtract by 32768 instead + of 16384. This utilizes the fact that the EG1 macro places a binary + point 15 places to the left instead of 14 places. + */ + /*lint -e{703} */ + pitchBend = + (((EAS_I32)(pChannel->pitchBend) << 2) + - 32768); + + pChannel->staticPitch = + MULT_EG1_EG1(pitchBend, pChannel->pitchBendSensitivity); + + /* if this is not a drum channel, then add in the per-channel tuning */ + if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL)) + pChannel->staticPitch += pChannel->finePitch + (pChannel->coarsePitch * 100); + + /* clear update flag */ + pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; + return; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateGain() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate and assign static voice parameters as part of WT_UpdateVoice() + * + * Inputs: + * pVoice - ptr to the synth voice that we want to synthesize + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - various voice parameters are calculated and assigned + * + *---------------------------------------------------------------------------- +*/ +static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain) +{ + EAS_I32 lfoGain; + EAS_I32 temp; + + /* + If this voice was stolen, then the velocity is actually + for the new note, not the note that we are currently ramping down. + So we really shouldn't use this velocity. However, that would require + more memory to store the velocity value, and the improvement may + not be sufficient to warrant the added memory. + */ + /* velocity is fixed at note start for a given voice and must be squared */ + temp = (pVoice->velocity) << (NUM_EG1_FRAC_BITS - 7); + temp = MULT_EG1_EG1(temp, temp); + + /* region gain is fixed as part of the articulation */ + temp = MULT_EG1_EG1(temp, gain); + + /* include the channel gain */ + temp = MULT_EG1_EG1(temp, pChannel->staticGain); + + /* calculate LFO gain using an approximation for 10^x */ + lfoGain = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToGain); + lfoGain = MULT_EG1_EG1(lfoGain, LFO_GAIN_TO_CENTS); + + /* convert from a dB-like value to linear gain */ + lfoGain = EAS_Calculate2toX(lfoGain); + temp = MULT_EG1_EG1(temp, lfoGain); + + /* calculate the voice's gain */ + temp = (EAS_I16)MULT_EG1_EG1(temp, pWTVoice->eg1Value); + + return temp; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateEG1() + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the EG1 envelope for the given voice (but do not update any + * state) + * + * Inputs: + * pVoice - ptr to the voice whose envelope we want to update + * nVoice - this voice's number - used only for debug + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * nValue - the envelope value + * + * Side Effects: + * - updates EG1 state value for the given voice + *---------------------------------------------------------------------------- +*/ +static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv) +{ + EAS_I32 temp; + + switch (pWTVoice->eg1State) + { + case eEnvelopeStateAttack: + temp = pWTVoice->eg1Value + pWTVoice->eg1Increment; + + /* check if we have reached peak amplitude */ + if (temp >= SYNTH_FULL_SCALE_EG1_GAIN) + { + /* limit the volume */ + temp = SYNTH_FULL_SCALE_EG1_GAIN; + + /* prepare to move to decay state */ + pWTVoice->eg1State = eEnvelopeStateDecay; + pWTVoice->eg1Increment = pEnv->decayTime; + } + + break; + + /* exponential decay */ + case eEnvelopeStateDecay: + temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment); + + /* check if we have reached sustain level */ + if (temp <= pEnv->sustainLevel) + { + /* enforce the sustain level */ + temp = pEnv->sustainLevel; + + /* if sustain level is zero, skip sustain & release the voice */ + if (temp > 0) + pWTVoice->eg1State = eEnvelopeStateSustain; + + /* move to sustain state */ + else + pWTVoice->eg1State = eEnvelopeStateMuted; + } + + break; + + case eEnvelopeStateSustain: + return; + + case eEnvelopeStateRelease: + temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment); + + /* if we hit zero, this voice isn't contributing any audio */ + if (temp <= 0) + { + temp = 0; + pWTVoice->eg1State = eEnvelopeStateMuted; + } + break; + + /* voice is muted, set target to zero */ + case eEnvelopeStateMuted: + temp = 0; + break; + + case eEnvelopeStateInvalid: + default: + temp = 0; +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG1: error, %d is an unrecognized state\n", + pWTVoice->eg1State); */ } +#endif + break; + + } + + pWTVoice->eg1Value = (EAS_I16) temp; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateEG2() + *---------------------------------------------------------------------------- + * Purpose: + * Update the EG2 envelope for the given voice + * + * Inputs: + * pVoice - ptr to the voice whose envelope we want to update + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - updates EG2 values for the given voice + *---------------------------------------------------------------------------- +*/ + +static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv) +{ + EAS_I32 temp; + + switch (pWTVoice->eg2State) + { + case eEnvelopeStateAttack: + temp = pWTVoice->eg2Value + pWTVoice->eg2Increment; + + /* check if we have reached peak amplitude */ + if (temp >= SYNTH_FULL_SCALE_EG1_GAIN) + { + /* limit the volume */ + temp = SYNTH_FULL_SCALE_EG1_GAIN; + + /* prepare to move to decay state */ + pWTVoice->eg2State = eEnvelopeStateDecay; + + pWTVoice->eg2Increment = pEnv->decayTime; + } + + break; + + /* implement linear pitch decay in cents */ + case eEnvelopeStateDecay: + temp = pWTVoice->eg2Value -pWTVoice->eg2Increment; + + /* check if we have reached sustain level */ + if (temp <= pEnv->sustainLevel) + { + /* enforce the sustain level */ + temp = pEnv->sustainLevel; + + /* prepare to move to sustain state */ + pWTVoice->eg2State = eEnvelopeStateSustain; + } + break; + + case eEnvelopeStateSustain: + return; + + case eEnvelopeStateRelease: + temp = pWTVoice->eg2Value - pWTVoice->eg2Increment; + + if (temp <= 0) + { + temp = 0; + pWTVoice->eg2State = eEnvelopeStateMuted; + } + + break; + + /* voice is muted, set target to zero */ + case eEnvelopeStateMuted: + temp = 0; + break; + + case eEnvelopeStateInvalid: + default: + temp = 0; +#ifdef _DEBUG_SYNTH + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG2: error, %d is an unrecognized state\n", + pWTVoice->eg2State); */ } +#endif + break; + } + + pWTVoice->eg2Value = (EAS_I16) temp; +} + +/*---------------------------------------------------------------------------- + * WT_UpdateLFO () + *---------------------------------------------------------------------------- + * Purpose: + * Calculate the LFO for the given voice + * + * Inputs: + * pLFO - ptr to the LFO data + * phaseInc - phase increment + * + * Outputs: + * + * Side Effects: + * - updates LFO values for the given voice + *---------------------------------------------------------------------------- +*/ +void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc) +{ + + /* To save memory, if m_nPhaseValue is negative, we are in the + * delay phase, and m_nPhaseValue represents the time left + * in the delay. + */ + if (pLFO->lfoPhase < 0) + { + pLFO->lfoPhase++; + return; + } + + /* calculate LFO output from phase value */ + /*lint -e{701} Use shift for performance */ + pLFO->lfoValue = (EAS_I16) (pLFO->lfoPhase << 2); + /*lint -e{502} */ + if ((pLFO->lfoPhase > 0x1fff) && (pLFO->lfoPhase < 0x6000)) + pLFO->lfoValue = ~pLFO->lfoValue; + + /* update LFO phase */ + pLFO->lfoPhase = (pLFO->lfoPhase + phaseInc) & 0x7fff; +} + +#ifdef _FILTER_ENABLED +/*---------------------------------------------------------------------------- + * WT_UpdateFilter() + *---------------------------------------------------------------------------- + * Purpose: + * Update the Filter parameters + * + * Inputs: + * pVoice - ptr to the voice whose filter we want to update + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - updates Filter values for the given voice + *---------------------------------------------------------------------------- +*/ +static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt) +{ + EAS_I32 cutoff; + + /* no need to calculate filter coefficients if it is bypassed */ + if (pArt->filterCutoff == DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY) + { + pIntFrame->frame.k = 0; + return; + } + + /* determine the dynamic cutoff frequency */ + cutoff = MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToFc); + cutoff += pArt->filterCutoff; + + /* subtract the A5 offset and the sampling frequency */ + cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS; + + /* limit the cutoff frequency */ + if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS) + cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS; + else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS) + cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS; + + WT_SetFilterCoeffs(pIntFrame, cutoff, pArt->filterQ); +} +#endif + +#if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER) +/*---------------------------------------------------------------------------- + * coef + *---------------------------------------------------------------------------- + * Table of filter coefficients for low-pass filter + *---------------------------------------------------------------------------- + * + * polynomial coefficients are based on 8kHz sampling frequency + * filter coef b2 = k2 = k2g0*k^0 + k2g1*k^1*(2^x) + k2g2*k^2*(2^x) + * + *where k2g0, k2g1, k2g2 are from the truncated power series expansion on theta + *(k*2^x = theta, but we incorporate the k along with the k2g0, k2g1, k2g2) + *note: this is a power series in 2^x, not k*2^x + *where k = (2*pi*440)/8kHz == convert octaves to radians + * + * so actually, the following coefs listed as k2g0, k2g1, k2g2 are really + * k2g0*k^0 = k2g0 + * k2g1*k^1 + * k2g2*k^2 + * + * + * filter coef n1 = numerator = n1g0*k^0 + n1g1*k^1*(2^x) + n1g2*k^2*(2^x) + n1g3*k^3*(2^x) + * + *where n1g0, n1g1, n1g2, n1g3 are from the truncated power series expansion on theta + *(k*2^x = theta, but we incorporate the k along with the n1g0, n1g1, n1g2, n2g3) + *note: this is a power series in 2^x, not k*2^x + *where k = (2*pi*440)/8kHz == convert octaves to radians + *we also include the optimization factor of 0.81 + * + * so actually, the following coefs listed as n1g0, n1g1, n1g2, n2g3 are really + * n1g0*k^0 = n1g0 + * n1g1*k^1 + * n1g2*k^2 + * n1g3*k^3 + * + * NOTE that n1g0 == n1g1 == 0, always, so we only need to store n1g2 and n1g3 + *---------------------------------------------------------------------------- +*/ + +static const EAS_I16 nk1g0 = -32768; +static const EAS_I16 nk1g2 = 1580; +static const EAS_I16 k2g0 = 32767; + +static const EAS_I16 k2g1[] = +{ + -11324, /* k2g1[0] = -0.3455751918948761 */ + -10387, /* k2g1[1] = -0.3169878073928751 */ + -9528, /* k2g1[2] = -0.29076528753345476 */ + -8740, /* k2g1[3] = -0.2667120011011279 */ + -8017, /* k2g1[4] = -0.24464850028971705 */ + -7353, /* k2g1[5] = -0.22441018194495696 */ + -6745, /* k2g1[6] = -0.20584605955455101 */ + -6187, /* k2g1[7] = -0.18881763682420102 */ + -5675, /* k2g1[8] = -0.1731978744360067 */ + -5206, /* k2g1[9] = -0.15887024228080968 */ + -4775, /* k2g1[10] = -0.14572785009373057 */ + -4380, /* k2g1[11] = -0.13367265000706827 */ + -4018, /* k2g1[12] = -0.1226147050712642 */ + -3685, /* k2g1[13] = -0.11247151828678581 */ + -3381, /* k2g1[14] = -0.10316741714122014 */ + -3101, /* k2g1[15] = -0.0946329890599603 */ + -2844, /* k2g1[16] = -0.08680456355870586 */ + -2609, /* k2g1[17] = -0.07962373723441349 */ + -2393, /* k2g1[18] = -0.07303693805092666 */ + -2195, /* k2g1[19] = -0.06699502566866912 */ + -2014, /* k2g1[20] = -0.06145292483669077 */ + -1847, /* k2g1[21] = -0.056369289112013346 */ + -1694, /* k2g1[22] = -0.05170619239747895 */ + -1554, /* k2g1[23] = -0.04742884599684141 */ + -1426, /* k2g1[24] = -0.043505339076210514 */ + -1308, /* k2g1[25] = -0.03990640059558053 */ + -1199, /* k2g1[26] = -0.03660518093435039 */ + -1100, /* k2g1[27] = -0.03357705158166837 */ + -1009, /* k2g1[28] = -0.030799421397205727 */ + -926, /* k2g1[29] = -0.028251568071585884 */ + -849 /* k2g1[30] = -0.025914483529091967 */ +}; + +static const EAS_I16 k2g2[] = +{ + 1957, /* k2g2[0] = 0.059711106626580836 */ + 1646, /* k2g2[1] = 0.05024063501786333 */ + 1385, /* k2g2[2] = 0.042272226217199664 */ + 1165, /* k2g2[3] = 0.03556764576567844 */ + 981, /* k2g2[4] = 0.029926444346999134 */ + 825, /* k2g2[5] = 0.025179964880280382 */ + 694, /* k2g2[6] = 0.02118630011706455 */ + 584, /* k2g2[7] = 0.01782604998793514 */ + 491, /* k2g2[8] = 0.014998751854573014 */ + 414, /* k2g2[9] = 0.012619876941179595 */ + 348, /* k2g2[10] = 0.010618303146468736 */ + 293, /* k2g2[11] = 0.008934188679954682 */ + 246, /* k2g2[12] = 0.007517182949855368 */ + 207, /* k2g2[13] = 0.006324921212866403 */ + 174, /* k2g2[14] = 0.005321757979794424 */ + 147, /* k2g2[15] = 0.004477701309210577 */ + 123, /* k2g2[16] = 0.00376751612730811 */ + 104, /* k2g2[17] = 0.0031699697655869644 */ + 87, /* k2g2[18] = 0.00266719715992703 */ + 74, /* k2g2[19] = 0.0022441667321724647 */ + 62, /* k2g2[20] = 0.0018882309854916855 */ + 52, /* k2g2[21] = 0.0015887483774966232 */ + 44, /* k2g2[22] = 0.0013367651661223448 */ + 37, /* k2g2[23] = 0.0011247477162958733 */ + 31, /* k2g2[24] = 0.0009463572640678758 */ + 26, /* k2g2[25] = 0.0007962604042473498 */ + 22, /* k2g2[26] = 0.0006699696356181593 */ + 18, /* k2g2[27] = 0.0005637091964589207 */ + 16, /* k2g2[28] = 0.00047430217920125243 */ + 13, /* k2g2[29] = 0.00039907554925166274 */ + 11 /* k2g2[30] = 0.00033578022828973666 */ +}; + +static const EAS_I16 n1g2[] = +{ + 3170, /* n1g2[0] = 0.0967319927350769 */ + 3036, /* n1g2[1] = 0.0926446051254155 */ + 2908, /* n1g2[2] = 0.08872992911818503 */ + 2785, /* n1g2[3] = 0.08498066682523227 */ + 2667, /* n1g2[4] = 0.08138982872895201 */ + 2554, /* n1g2[5] = 0.07795072065216213 */ + 2446, /* n1g2[6] = 0.0746569312785634 */ + 2343, /* n1g2[7] = 0.07150232020051943 */ + 2244, /* n1g2[8] = 0.06848100647187474 */ + 2149, /* n1g2[9] = 0.06558735764447099 */ + 2058, /* n1g2[10] = 0.06281597926792246 */ + 1971, /* n1g2[11] = 0.06016170483307614 */ + 1888, /* n1g2[12] = 0.05761958614040857 */ + 1808, /* n1g2[13] = 0.05518488407540374 */ + 1732, /* n1g2[14] = 0.052853059773715245 */ + 1659, /* n1g2[15] = 0.05061976615964251 */ + 1589, /* n1g2[16] = 0.04848083984214659 */ + 1521, /* n1g2[17] = 0.046432293353298 */ + 1457, /* n1g2[18] = 0.04447030771468711 */ + 1396, /* n1g2[19] = 0.04259122531793907 */ + 1337, /* n1g2[20] = 0.040791543106060944 */ + 1280, /* n1g2[21] = 0.03906790604290942 */ + 1226, /* n1g2[22] = 0.037417100858604564 */ + 1174, /* n1g2[23] = 0.035836050059229754 */ + 1125, /* n1g2[24] = 0.03432180618965023 */ + 1077, /* n1g2[25] = 0.03287154633875494 */ + 1032, /* n1g2[26] = 0.03148256687687814 */ + 988, /* n1g2[27] = 0.030152278415589925 */ + 946, /* n1g2[28] = 0.028878200980459685 */ + 906, /* n1g2[29] = 0.02765795938779331 */ + 868 /* n1g2[30] = 0.02648927881672521 */ +}; + +static const EAS_I16 n1g3[] = +{ + -548, /* n1g3[0] = -0.016714088475899017 */ + -481, /* n1g3[1] = -0.014683605122742116 */ + -423, /* n1g3[2] = -0.012899791676436092 */ + -371, /* n1g3[3] = -0.01133268185193299 */ + -326, /* n1g3[4] = -0.00995594976868754 */ + -287, /* n1g3[5] = -0.008746467702146129 */ + -252, /* n1g3[6] = -0.00768391756106361 */ + -221, /* n1g3[7] = -0.006750449563854721 */ + -194, /* n1g3[8] = -0.005930382380083576 */ + -171, /* n1g3[9] = -0.005209939699767622 */ + -150, /* n1g3[10] = -0.004577018805123356 */ + -132, /* n1g3[11] = -0.004020987256990177 */ + -116, /* n1g3[12] = -0.003532504280467257 */ + -102, /* n1g3[13] = -0.00310336384922047 */ + -89, /* n1g3[14] = -0.002726356832432369 */ + -78, /* n1g3[15] = -0.002395149888601605 */ + -69, /* n1g3[16] = -0.0021041790717285314 */ + -61, /* n1g3[17] = -0.0018485563625771063 */ + -53, /* n1g3[18] = -0.001623987554831628 */ + -47, /* n1g3[19] = -0.0014267001167177025 */ + -41, /* n1g3[20] = -0.0012533798162347005 */ + -36, /* n1g3[21] = -0.0011011150453668693 */ + -32, /* n1g3[22] = -0.0009673479079754438 */ + -28, /* n1g3[23] = -0.0008498312496971563 */ + -24, /* n1g3[24] = -0.0007465909079943587 */ + -21, /* n1g3[25] = -0.0006558925481952733 */ + -19, /* n1g3[26] = -0.0005762125284029567 */ + -17, /* n1g3[27] = -0.0005062123038325457 */ + -15, /* n1g3[28] = -0.0004447159405951901 */ + -13, /* n1g3[29] = -0.00039069036118270117 */ + -11 /* n1g3[30] = -0.00034322798979677605 */ +}; + +/*---------------------------------------------------------------------------- + * WT_SetFilterCoeffs() + *---------------------------------------------------------------------------- + * Purpose: + * Update the Filter parameters + * + * Inputs: + * pVoice - ptr to the voice whose filter we want to update + * pEASData - pointer to overall EAS data structure + * + * Outputs: + * + * Side Effects: + * - updates Filter values for the given voice + *---------------------------------------------------------------------------- +*/ +void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance) +{ + EAS_I32 temp; + + /* + Convert the cutoff, which has had A5 subtracted, using the 2^x approx + Note, this cutoff is related to theta cutoff by + theta = k * 2^x + We use 2^x and incorporate k in the power series coefs instead + */ + cutoff = EAS_Calculate2toX(cutoff); + + /* calculate b2 coef */ + temp = k2g1[resonance] + MULT_AUDIO_COEF(cutoff, k2g2[resonance]); + temp = k2g0 + MULT_AUDIO_COEF(cutoff, temp); + pIntFrame->frame.b2 = temp; + + /* calculate b1 coef */ + temp = MULT_AUDIO_COEF(cutoff, nk1g2); + temp = nk1g0 + MULT_AUDIO_COEF(cutoff, temp); + temp += MULT_AUDIO_COEF(temp, pIntFrame->frame.b2); + pIntFrame->frame.b1 = temp >> 1; + + /* calculate K coef */ + temp = n1g2[resonance] + MULT_AUDIO_COEF(cutoff, n1g3[resonance]); + temp = MULT_AUDIO_COEF(cutoff, temp); + temp = MULT_AUDIO_COEF(cutoff, temp); + pIntFrame->frame.k = temp; +} +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtsynth.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtsynth.h new file mode 100755 index 0000000..90a7ad8 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtsynth.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_wtsynth.h + * + * Contents and purpose: + * This file defines the interface for synthesizer engine + * + * Copyright Sonic Network Inc. 2004 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_WTSYNTH_H +#define _EAS_WTSYNTH_H + +#include "eas_sndlib.h" +#include "eas_wtengine.h" + +/* adjust the filter cutoff frequency to the sample rate */ +#if defined (_SAMPLE_RATE_8000) +#define FILTER_CUTOFF_FREQ_ADJUST 0 +#elif defined (_SAMPLE_RATE_16000) +#define FILTER_CUTOFF_FREQ_ADJUST 1200 +#elif defined (_SAMPLE_RATE_20000) +#define FILTER_CUTOFF_FREQ_ADJUST 1586 +#elif defined (_SAMPLE_RATE_22050) +#define FILTER_CUTOFF_FREQ_ADJUST 1756 +#elif defined (_SAMPLE_RATE_24000) +#define FILTER_CUTOFF_FREQ_ADJUST 1902 +#elif defined (_SAMPLE_RATE_32000) +#define FILTER_CUTOFF_FREQ_ADJUST 2400 +#elif defined (_SAMPLE_RATE_44100) +#define FILTER_CUTOFF_FREQ_ADJUST 2956 +#elif defined (_SAMPLE_RATE_48000) +#define FILTER_CUTOFF_FREQ_ADJUST 3102 +#else +#error "_SAMPLE_RATE_XXXXX must be defined to valid rate" +#endif + +/* function prototypes */ +void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc); + +#if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER) +void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance); +#endif + +#endif + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmf.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmf.c new file mode 100755 index 0000000..0a92425 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmf.c @@ -0,0 +1,850 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_xmf.c + * 5 + * Contents and purpose: + * XMF File Parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 501 $ + * $Date: 2006-12-11 17:53:36 -0800 (Mon, 11 Dec 2006) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_data.h" +#include "eas_miditypes.h" +#include "eas_parser.h" +#include "eas_report.h" +#include "eas_host.h" +#include "eas_midi.h" +#include "eas_xmf.h" +#include "eas_xmfdata.h" +#include "eas_config.h" +#include "eas_vm_protos.h" +#include "eas_mdls.h" +#include "eas_smf.h" + + +/* XMF header file type */ +#define XMF_IDENTIFIER 0x584d465f +#define XMF_VERSION_2_00 0x322e3030 +#define XMF_FILE_TYPE 0x00000002 +#define XMF_SPEC_LEVEL 0x00000001 +#define XMF_RIFF_CHUNK 0x52494646 +#define XMF_RIFF_DLS 0x444c5320 +#define XMF_SMF_CHUNK 0x4d546864 + +/* local prototypes */ +static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); +static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); +static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); +static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); +static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); +static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); +static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); +static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData); +static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength); +static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value); + + +/*---------------------------------------------------------------------------- + * + * XMF_Parser + * + * This structure contains the functional interface for the XMF parser + *---------------------------------------------------------------------------- +*/ +const S_FILE_PARSER_INTERFACE EAS_XMF_Parser = +{ + XMF_CheckFileType, + XMF_Prepare, + XMF_Time, + XMF_Event, + XMF_State, + XMF_Close, + XMF_Reset, + XMF_Pause, + XMF_Resume, + NULL, + XMF_SetData, + XMF_GetData, + NULL +}; + +/*---------------------------------------------------------------------------- + * XMF_CheckFileType() + *---------------------------------------------------------------------------- + * Purpose: + * Check the file type to see if we can parse it + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) +{ + S_XMF_DATA *pXMFData; + EAS_RESULT result; + EAS_U32 temp; + + /* assume we don't recognize it initially */ + *ppHandle = NULL; + + /* read the file identifier */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) + return result; + if (temp != XMF_IDENTIFIER) + return EAS_SUCCESS; + + /* read the version */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) + return result; + if (temp != XMF_VERSION_2_00) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file version was 0x%08x, expected 0x%08x\n", temp, XMF_VERSION_2_00); */ } + return EAS_SUCCESS; + } + + /* read the file type */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) + return result; + if (temp != XMF_FILE_TYPE) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file type was 0x%08x, expected 0x%08x\n", temp, XMF_FILE_TYPE); */ } + return EAS_SUCCESS; + } + + /* read the spec level */ + if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) + return result; + if (temp != XMF_SPEC_LEVEL) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file spec was 0x%08x, expected 0x%08x\n", temp, XMF_SPEC_LEVEL); */ } + return EAS_SUCCESS; + } + + /* check for static memory allocation */ + if (pEASData->staticMemoryModel) + pXMFData = EAS_CMEnumData(EAS_CM_XMF_DATA); + else + pXMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_XMF_DATA)); + if (!pXMFData) + return EAS_ERROR_MALLOC_FAILED; + + /* zero the memory to insure complete initialization */ + EAS_HWMemSet((void *)pXMFData,0, sizeof(S_XMF_DATA)); + + pXMFData->fileHandle = fileHandle; + pXMFData->fileOffset = offset; + *ppHandle = pXMFData; + + /* locate the SMF and DLS contents */ + if ((result = XMF_FindFileContents(pEASData->hwInstData, pXMFData)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ } + return result; + } + + /* let the SMF parser take over */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pXMFData->midiOffset)) != EAS_SUCCESS) + return result; + return SMF_CheckFileType(pEASData, fileHandle, &pXMFData->pSMFData, pXMFData->midiOffset); +} + +/*---------------------------------------------------------------------------- + * XMF_Prepare() + *---------------------------------------------------------------------------- + * Purpose: + * Prepare to parse the file. Allocates instance data (or uses static allocation for + * static memory model). + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_XMF_DATA* pXMFData; + EAS_RESULT result; + + /* parse DLS collection */ + pXMFData = (S_XMF_DATA*) pInstData; + if (pXMFData->dlsOffset != 0) + { + if ((result = DLSParser(pEASData->hwInstData, pXMFData->fileHandle, pXMFData->dlsOffset, &pXMFData->pDLS)) != EAS_SUCCESS) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error converting XMF DLS data\n"); */ } + return result; + } + } + + /* Prepare the SMF parser */ + if ((result = SMF_Prepare(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS) + return result; + + /* if no DLS file, skip this step */ + if (pXMFData->pDLS == NULL) + return EAS_SUCCESS; + + /* tell the synth to use the DLS collection */ + result = VMSetDLSLib(((S_SMF_DATA*) pXMFData->pSMFData)->pSynth, pXMFData->pDLS); + if (result == EAS_SUCCESS) + { + DLSAddRef(pXMFData->pDLS); + VMInitializeAllChannels(pEASData->pVoiceMgr, ((S_SMF_DATA*) pXMFData->pSMFData)->pSynth); + } + return result; +} + +/*---------------------------------------------------------------------------- + * XMF_Time() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the time of the next event in msecs + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pTime - pointer to variable to hold time of next event (in msecs) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) +{ + return SMF_Time(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pTime); +} + +/*---------------------------------------------------------------------------- + * XMF_Event() + *---------------------------------------------------------------------------- + * Purpose: + * Parse the next event in the file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) +{ + return SMF_Event(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, parserMode); +} + +/*---------------------------------------------------------------------------- + * XMF_State() + *---------------------------------------------------------------------------- + * Purpose: + * Returns the current state of the stream + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * pState - pointer to variable to store state + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) +{ + return SMF_State(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pState); +} + +/*---------------------------------------------------------------------------- + * XMF_Close() + *---------------------------------------------------------------------------- + * Purpose: + * Close the file and clean up + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + S_XMF_DATA* pXMFData; + EAS_RESULT result; + + pXMFData = (S_XMF_DATA *)pInstData; + + /* close the SMF stream, it will close the file handle */ + if ((result = SMF_Close(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS) + return result; + + if (pXMFData->pDLS) + DLSCleanup(pEASData->hwInstData, pXMFData->pDLS); + + /* if using dynamic memory, free it */ + if (!pEASData->staticMemoryModel) + { + /* free the instance data */ + EAS_HWFree(pEASData->hwInstData, pXMFData); + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * XMF_Reset() + *---------------------------------------------------------------------------- + * Purpose: + * Reset the sequencer. Used for locating backwards in the file. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + return SMF_Reset(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); +} + +/*---------------------------------------------------------------------------- + * XMF_Pause() + *---------------------------------------------------------------------------- + * Purpose: + * Pauses the sequencer. Mutes all voices and sets state to pause. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + return SMF_Pause(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); +} + +/*---------------------------------------------------------------------------- + * XMF_Resume() + *---------------------------------------------------------------------------- + * Purpose: + * Resume playing after a pause, sets state back to playing. + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) +{ + return SMF_Resume(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); +} + +/*---------------------------------------------------------------------------- + * XMF_SetData() + *---------------------------------------------------------------------------- + * Purpose: + * Sets the playback rate of the underlying SMF file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * rate - rate (28-bit fraction) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) +{ + return SMF_SetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, value); +} + +/*---------------------------------------------------------------------------- + * XMF_GetData() + *---------------------------------------------------------------------------- + * Purpose: + * Gets the file type + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * handle - pointer to file handle + * rate - rate (28-bit fraction) + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) +{ + EAS_RESULT result; + + /* call SMF parser to get value */ + if ((result = SMF_GetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, pValue)) != EAS_SUCCESS) + return result; + + /* special case for file type */ + if (param == PARSER_DATA_FILE_TYPE) + { + if (*pValue == EAS_FILE_SMF0) + *pValue = EAS_FILE_XMF0; + else if (*pValue == EAS_FILE_SMF1) + *pValue = EAS_FILE_XMF1; + } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * XMF_FindFileContents() + *---------------------------------------------------------------------------- + * Purpose: + * Finds SMF data and DLS data in XMF file, and remembers offset for each. + * If more than one is found, uses the first one found of each. + * Makes assumptions about the format of a mobile XMF file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pXMFData - pointer to XMF parser instance data + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData) +{ + EAS_RESULT result; + EAS_I32 value; + EAS_I32 length; + + /* initialize offsets */ + pXMFData->dlsOffset = pXMFData->midiOffset = 0; + + /* read file length, ignore it for now */ + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) + return result; + + /* read MetaDataTypesTable length and skip over it */ + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, value)) != EAS_SUCCESS) + return result; + + /* get TreeStart offset and jump to it */ + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) + return result; + if ((result = XMF_ReadNode(hwInstData, pXMFData, value, &length)) != EAS_SUCCESS) + return result; + + /* check for SMF data */ + if (pXMFData->midiOffset == 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* check for SFM in wrong order */ + if ((pXMFData->dlsOffset > 0) && (pXMFData->midiOffset < pXMFData->dlsOffset)) + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS data must precede SMF data in Mobile XMF file\n"); */ } + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * XMF_ReadNode() + *---------------------------------------------------------------------------- + * Purpose: + * + * Inputs: + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength) +{ + EAS_RESULT result; + EAS_I32 refType; + EAS_I32 numItems; + EAS_I32 offset; + EAS_I32 length; + EAS_I32 headerLength; + EAS_U32 chunkType; + + /* seek to start of node */ + if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset)) != EAS_SUCCESS) + return result; + + /* get node length */ + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, pLength)) != EAS_SUCCESS) + return result; + + /* get number of contained items */ + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &numItems)) != EAS_SUCCESS) + return result; + + /* get node header length */ + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &headerLength)) != EAS_SUCCESS) + return result; + + /* get metadata length */ + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &length)) != EAS_SUCCESS) + return result; + + /* get the current location */ + if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) + return result; + + /* skip to node contents */ + if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset + headerLength)) != EAS_SUCCESS) + return result; + + /* get reference type */ + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &refType)) != EAS_SUCCESS) + return result; + + /* get the current location */ + if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) + return result; + + /* process file node */ + if (numItems == 0) + + { + /* if in-file resource, find out where it is and jump to it */ + if (refType == 2) + { + if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) + return result; + offset += pXMFData->fileOffset; + if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS) + return result; + } + + /* or else it must be an inline resource */ + else if (refType != 1) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected reference type %d\n", refType); */ } + return EAS_ERROR_FILE_FORMAT; + } + + /* get the chunk type */ + if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS) + return result; + + /* found a RIFF chunk, check for DLS type */ + if (chunkType == XMF_RIFF_CHUNK) + { + /* skip length */ + if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, sizeof(EAS_I32))) != EAS_SUCCESS) + return result; + + /* get RIFF file type */ + if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS) + return result; + if (chunkType == XMF_RIFF_DLS) + pXMFData->dlsOffset = offset; + } + + /* found an SMF chunk */ + else if (chunkType == XMF_SMF_CHUNK) + pXMFData->midiOffset = offset; + } + + /* folder node, process the items in the list */ + else + { + for ( ; numItems > 0; numItems--) + { + /* process this item */ + if ((result = XMF_ReadNode(hwInstData, pXMFData, offset, &length)) != EAS_SUCCESS) + return result; + + /* seek to start of next item */ + offset += length; + if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS) + return result; + } + } + + return EAS_SUCCESS; +} + +#if 0 +/*---------------------------------------------------------------------------- + * XMF_FindFileContents() + *---------------------------------------------------------------------------- + * Purpose: + * Finds SMF data and DLS data in XMF file, and remembers offset for each. + * If more than one is found, uses the first one found of each. + * Makes assumptions about the format of a mobile XMF file + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * pXMFData - pointer to XMF parser instance data + * handle - pointer to file handle + * + * Outputs: + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_FindFileContents(S_EAS_DATA *pEASData, S_XMF_DATA *pXMFData, EAS_FILE_HANDLE fileHandle) +{ + EAS_RESULT result; + EAS_I32 offset; + EAS_I32 value; + EAS_I32 numItems; + EAS_I32 length; + EAS_CHAR id[4]; + EAS_I32 location; + + /* init dls offset, so that we know we haven't found a dls chunk yet */ + pXMFData->dlsOffset = 0; + + /* read file length, ignore it for now */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) + return result; + + /* read MetaDataTypesTable length and skip over it */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWFileSeekOfs(pEASData, fileHandle, value)) != EAS_SUCCESS) + return result; + + /* get TreeStart offset and jump to it */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &offset)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS) + return result; + + /* read node length, ignore it for now */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) + return result; + + /* read number of contained items */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &numItems)) != EAS_SUCCESS) + return result; + + /*read node header length */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) + return result; + + /*go to the node offset */ + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS) + return result; + + /* read Reference Type */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) + return result; + + /* make sure it is an in-line resource, for now */ + if (value != 1) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file tree\n"); */ } + return EAS_FAILURE; + } + + /* parse through the list of items */ + while (numItems > 0) + { + /*get current offset */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &offset)) != EAS_SUCCESS) + return result; + + /*read node length */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &length)) != EAS_SUCCESS) + return result; + + /* read number of items */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) + return result; + + /* make sure not a folder */ + if (value != 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ } + return EAS_FAILURE; + } + + /* read offset to resource and jump to it */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) + return result; + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS) + return result; + + /* read Reference Type */ + if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) + return result; + + /* make sure it is an in-line resource */ + if (value != 1) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ } + return EAS_FAILURE; + } + + /* get current offset as a possible location for SMF file or DLS file */ + if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &location)) != EAS_SUCCESS) + return result; + + /* read four bytes */ + if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, id, sizeof(id), &value)) != EAS_SUCCESS) + return result; + + /* check if DLS */ + if (pXMFData->dlsOffset == 0 && id[0] == 'R' && id[1] == 'I' && id[2] == 'F' && id[3] == 'F') + { + //remember offset + pXMFData->dlsOffset = location; + } + + /* else check if SMF */ + else if (id[0] == 'M' && id[1] == 'T' && id[2] == 'h' && id[3] == 'd') + { + //remember offset + pXMFData->midiOffset = location; + + //we are done + return EAS_SUCCESS; + } + + //one less item + numItems--; + + //if more data, go to the next item + if (numItems >0) + { + if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + length)) != EAS_SUCCESS) + return result; + } + } + + return EAS_FAILURE; + +} +#endif + +/*---------------------------------------------------------------------------- + * XMF_ReadVLQ() + *---------------------------------------------------------------------------- + * Purpose: + * Reads a VLQ encoded value from the file referenced by fileHandle + * + * Inputs: + * pEASData - pointer to overall EAS data structure + * fileHandle - pointer to file handle + * + * Outputs: + * value - pointer to the value decoded from the VLQ data + * + * + * Side Effects: + * + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value) +{ + EAS_RESULT result; + EAS_U8 c; + + *value = 0; + + if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) + return result; + + while (c > 0x7F) + { + /*lint -e{703} shift for performance */ + *value = (*value << 7) | (c & 0x7F); + + if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) + return result; + } + + /*lint -e{703} shift for performance */ + *value = (*value << 7) | c; + + return EAS_SUCCESS; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmf.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmf.h new file mode 100755 index 0000000..b8f7a24 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmf.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_xmf.h + * + * Contents and purpose: + * XMF Type 0 and 1 File Parser + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_XMF_H +#define _EAS_XMF_H + +#ifndef MAX_XMF_STREAMS +#define MAX_XMF_STREAMS 16 +#endif + +/* offsets in to the XMF file */ +#define XMF_OFS_HEADER_SIZE 4 +#define XMF_OFS_FILE_TYPE 8 +#define XMF_OFS_NUM_TRACKS 10 + +/* size of chunk info (chunk ID + chunk size) */ +#define XMF_CHUNK_INFO_SIZE 8 + +/* 'MTrk' track chunk ID */ +#define XMF_CHUNK_TYPE_TRACK 0x4d54726bL + +/* some useful meta-events */ +#define XMF_META_END_OF_TRACK 0x2f +#define XMF_META_TEMPO 0x51 + +/* default timebase (120BPM) */ +#define XMF_DEFAULT_TIMEBASE 500000L + +/* value for pXMFStream->ticks to signify end of track */ +#define XMF_END_OF_TRACK 0xffffffff + +#endif /* end _EAS_XMF_H */ + + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmfdata.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmfdata.c new file mode 100755 index 0000000..f305c12 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmfdata.c @@ -0,0 +1,44 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_xmfdata.c + * + * Contents and purpose: + * XMF File Parser + * + * This file contains data definitions for the XMF parser. + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 547 $ + * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_miditypes.h" +#include "eas_xmf.h" +#include "eas_xmfdata.h" + +/*---------------------------------------------------------------------------- + * + * eas_XMFData + * + * Static memory allocation for XMF parser + *---------------------------------------------------------------------------- +*/ +S_XMF_DATA eas_XMFData; + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmfdata.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmfdata.h new file mode 100755 index 0000000..fce02a1 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmfdata.h @@ -0,0 +1,55 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_xmfdata.h + * + * Contents and purpose: + * Contains declarations for the XMF file parser. + * + * + * Copyright Sonic Network Inc. 2005 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 82 $ + * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _EAS_XMFDATA_H +#define _EAS_XMFDATA_H + +#include "eas_data.h" + +/*---------------------------------------------------------------------------- + * + * S_XMF_DATA + * + * This structure contains the instance data required to parse an XMF file. + * + *---------------------------------------------------------------------------- +*/ + +typedef struct +{ + EAS_FILE_HANDLE fileHandle; + EAS_I32 fileOffset; + EAS_VOID_PTR pSMFData; + EAS_I32 midiOffset; + EAS_I32 dlsOffset; + S_DLS *pDLS; +} S_XMF_DATA; + +#endif diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/jet.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/jet.c new file mode 100755 index 0000000..97672cf --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/jet.c @@ -0,0 +1,1129 @@ +/*---------------------------------------------------------------------------- + * + * File: + * jet.c + * + * Contents and purpose: + * Implementation for JET sound engine + * + * Copyright (c) 2006 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 563 $ + * $Date: 2007-02-13 20:26:23 -0800 (Tue, 13 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "JET_C" + +//#define DEBUG_JET + +#include "eas_data.h" +#include "eas_smf.h" +#include "jet_data.h" +#include "eas_host.h" +#include "eas_report.h" + + +/* default configuration */ +static const S_JET_CONFIG jetDefaultConfig = +{ + JET_EVENT_APP_LOW, + JET_EVENT_APP_HIGH +}; + +/* function prototypes */ +extern EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value); +extern EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream); +extern EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS); + +/*---------------------------------------------------------------------------- + * JET_ParseEvent() + *---------------------------------------------------------------------------- + * Returns current status + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC void JET_ParseEvent (EAS_U32 event, S_JET_EVENT *pEvent) +{ + pEvent->segment = (EAS_U8) ((event & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT); + pEvent->track = (EAS_U8) ((event & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT); + pEvent->channel = (EAS_U8) ((event & JET_EVENT_CHAN_MASK) >> JET_EVENT_CHAN_SHIFT); + pEvent->controller = (EAS_U8) ((event & JET_EVENT_CTRL_MASK) >> JET_EVENT_CTRL_SHIFT); + pEvent->value = (EAS_U8) (event & JET_EVENT_VAL_MASK); +} + +#ifdef DEBUG_JET +/*---------------------------------------------------------------------------- + * JET_DumpEvent + *---------------------------------------------------------------------------- + * Advances queue read/write index + *---------------------------------------------------------------------------- +*/ +static void JET_DumpEvent (const char *procName, EAS_U32 event) +{ + S_JET_EVENT sEvent; + JET_ParseEvent(event, &sEvent); + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "%s: SegID=%d, TrkID=%d, channel=%d, ctrl=%d, val=%d\n", + procName, sEvent.segment, sEvent.track, sEvent.channel, sEvent.controller, sEvent.value); */ } +} +#endif + +/*---------------------------------------------------------------------------- + * JET_IncQueueIndex + *---------------------------------------------------------------------------- + * Advances queue read/write index + *---------------------------------------------------------------------------- +*/ +EAS_INLINE EAS_U8 JET_IncQueueIndex (EAS_U8 index, EAS_U8 queueSize) +{ + if (++index == queueSize) + index = 0; + return index; +} + +/*---------------------------------------------------------------------------- + * JET_WriteQueue + *---------------------------------------------------------------------------- + * Save event to queue + *---------------------------------------------------------------------------- +*/ +EAS_INLINE void JET_WriteQueue (EAS_U32 *pEventQueue, EAS_U8 *pWriteIndex, EAS_U8 readIndex, EAS_U8 queueSize, EAS_U32 event) +{ + EAS_U8 temp; + + /* check for queue overflow */ + temp = JET_IncQueueIndex(*pWriteIndex, queueSize); + if (temp == readIndex) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "JET_Event: Event queue overflow --- event ignored!\n"); */ } + return; + } + + /* save in queue and advance write index */ + pEventQueue[*pWriteIndex] = event; + *pWriteIndex = temp; +} + +/*---------------------------------------------------------------------------- + * JET_ReadQueue + *---------------------------------------------------------------------------- + * Read event to queue + *---------------------------------------------------------------------------- +*/ +EAS_INLINE EAS_BOOL JET_ReadQueue (EAS_U32 *pEventQueue, EAS_U8 *pReadIndex, EAS_U8 writeIndex, EAS_U8 queueSize, EAS_U32 *pEvent) +{ + + /* check for empty queue */ + if (*pReadIndex == writeIndex) + return EAS_FALSE; + + /* save in queue and advance write index */ + *pEvent = pEventQueue[*pReadIndex]; + *pReadIndex = JET_IncQueueIndex(*pReadIndex, queueSize); + return EAS_TRUE; +} + +/*---------------------------------------------------------------------------- + * JET_NextSegment + *---------------------------------------------------------------------------- + * Advances segment number + *---------------------------------------------------------------------------- +*/ +EAS_INLINE EAS_INT JET_NextSegment (EAS_INT seg_num) +{ + if (++seg_num == SEG_QUEUE_DEPTH) + seg_num = 0; + return seg_num; +} + +/*---------------------------------------------------------------------------- + * JET_PrepareSegment() + *---------------------------------------------------------------------------- + * Prepare a segment for playback + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT JET_PrepareSegment (EAS_DATA_HANDLE easHandle, EAS_I32 queueNum) +{ + EAS_RESULT result; + S_JET_SEGMENT *p; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_PrepareSegment: %d\n", queueNum); */ } + + p = &easHandle->jetHandle->segQueue[queueNum]; + result = EAS_Prepare(easHandle, p->streamHandle); + if (result != EAS_SUCCESS) + return result; + + /* pause segment - must be triggered by play or end of previous segment */ + result = EAS_Pause(easHandle, p->streamHandle); + if (result != EAS_SUCCESS) + return result; + p->state = JET_STATE_READY; + + /* set calback data */ + result = EAS_IntSetStrmParam(easHandle, p->streamHandle, PARSER_DATA_JET_CB, queueNum); + if (result != EAS_SUCCESS) + return result; + + /* set DLS collection */ + if (p->libNum >= 0) + { + result = EAS_IntSetStrmParam(easHandle, p->streamHandle, + PARSER_DATA_DLS_COLLECTION, (EAS_I32) easHandle->jetHandle->libHandles[p->libNum]); + if (result != EAS_SUCCESS) + return result; + } + + /* set transposition */ + if (p->transpose) + { + result = EAS_SetTransposition(easHandle, p->streamHandle, p->transpose); + if (result != EAS_SUCCESS) + return result; + } + + return result; +} + +/*---------------------------------------------------------------------------- + * JET_StartPlayback() + *---------------------------------------------------------------------------- + * Start segment playback + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT JET_StartPlayback (EAS_DATA_HANDLE easHandle, EAS_I32 queueNum) +{ + EAS_RESULT result = EAS_SUCCESS; + S_JET_SEGMENT *pSeg; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_StartPlayback %d\n", queueNum); */ } + + /* if next segment is queued, start playback */ + pSeg = &easHandle->jetHandle->segQueue[queueNum]; + if (pSeg->streamHandle != NULL) + { + result = EAS_Resume(easHandle, pSeg->streamHandle); + easHandle->jetHandle->segQueue[queueNum].state = JET_STATE_PLAYING; + + /* set mute flags */ + if ((result == EAS_SUCCESS) && (pSeg->muteFlags != 0)) + result = EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); + } + return result; +} + +/*---------------------------------------------------------------------------- + * JET_CloseSegment + *---------------------------------------------------------------------------- + * Closes stream associated with a segment + *---------------------------------------------------------------------------- +*/ +EAS_INLINE EAS_INT JET_CloseSegment (EAS_DATA_HANDLE easHandle, EAS_INT queueNum) +{ + EAS_RESULT result; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_CloseSegment %d\n", queueNum); */ } + + /* close the segment */ + result = EAS_CloseFile(easHandle, easHandle->jetHandle->segQueue[queueNum].streamHandle); + if (result != EAS_SUCCESS) + return result; + + easHandle->jetHandle->segQueue[queueNum].streamHandle = NULL; + easHandle->jetHandle->segQueue[queueNum].state = JET_STATE_CLOSED; + easHandle->jetHandle->numQueuedSegments--; + return result; +} + +/*---------------------------------------------------------------------------- + * JetParseInfoChunk() + *---------------------------------------------------------------------------- + * Parses the JET info chunk + *---------------------------------------------------------------------------- +*/ +static EAS_RESULT JetParseInfoChunk (EAS_DATA_HANDLE easHandle, EAS_I32 pos, EAS_I32 chunkSize) +{ + EAS_RESULT result; + EAS_U32 infoType; + EAS_U32 temp; + + /* offset to data */ + result = EAS_HWFileSeek(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos); + if (result != EAS_SUCCESS) + return result; + + /* read the entire chunk */ + result = EAS_SUCCESS; + while ((result == EAS_SUCCESS) && (chunkSize > 0)) + { + + /* get info infoType */ + result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &infoType, EAS_TRUE); + if (result != EAS_SUCCESS) + break; + + /* get info field */ + result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &temp, EAS_FALSE); + if (result == EAS_SUCCESS) + + switch (infoType) + { + case INFO_NUM_SMF_CHUNKS: + easHandle->jetHandle->numSegments = (EAS_U8) temp; + break; + + case INFO_NUM_DLS_CHUNKS: + easHandle->jetHandle->numLibraries = (EAS_U8) temp; + break; + + case INFO_JET_VERSION: + /* check major version number */ + if ((temp & 0xff000000) != (JET_VERSION & 0xff000000)) + return EAS_ERROR_INCOMPATIBLE_VERSION; + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized JET info type 0x%08x", infoType); */ } + break; + } + + chunkSize -= 8; + } + + /* allocate pointers for chunks to follow */ + + return result; +} + +/*---------------------------------------------------------------------------- + * JET_OpenFile() + *---------------------------------------------------------------------------- + * Opens a JET content file for playback + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_OpenFile (EAS_DATA_HANDLE easHandle, EAS_FILE_LOCATOR locator) +{ + EAS_RESULT result; + EAS_U32 chunkType; + EAS_I32 pos; + EAS_I32 chunkSize; + EAS_INT smfChunkNum; + EAS_INT dlsChunkNum; + EAS_I32 dataSize = 0; /* make lint happy */ + + /* make sure that we don't have an open file */ + if (easHandle->jetHandle->jetFileHandle != NULL) + return EAS_ERROR_FILE_ALREADY_OPEN; + + /* open the media file */ + result = EAS_HWOpenFile(easHandle->hwInstData, locator, &easHandle->jetHandle->jetFileHandle, EAS_FILE_READ); + if (result != EAS_SUCCESS) + return result; + + /* check header */ + result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkType, EAS_TRUE); + if (result == EAS_SUCCESS) + { + if (chunkType != JET_HEADER_TAG) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "File is not JET format\n"); */ } + result = EAS_ERROR_UNRECOGNIZED_FORMAT; + } + } + /* get the file data size */ + if (result == EAS_SUCCESS) + result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &dataSize, EAS_FALSE); + + /* parse through the file to find contents */ + smfChunkNum = dlsChunkNum = 0; + pos = chunkSize = 8; + while ((result == EAS_SUCCESS) && (pos < dataSize)) + { + + /* offset to chunk data */ + result = EAS_HWFileSeek(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos); + if (result != EAS_SUCCESS) + break; + + /* get chunk size and type */ + result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkType, EAS_TRUE); + if (result != EAS_SUCCESS) + break; + + result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkSize, EAS_FALSE); + if (result != EAS_SUCCESS) + break; + pos += 8; + + switch (chunkType) + { + case JET_INFO_CHUNK: + result = JetParseInfoChunk(easHandle, pos, chunkSize); + break; + + case JET_SMF_CHUNK: + if (smfChunkNum < easHandle->jetHandle->numSegments) + easHandle->jetHandle->segmentOffsets[smfChunkNum++] = pos; + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring extraneous SMF chunk"); */ } + break; + + case JET_DLS_CHUNK: + if (dlsChunkNum < easHandle->jetHandle->numLibraries) + result = DLSParser(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos, &easHandle->jetHandle->libHandles[dlsChunkNum++]); + else + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring extraneous DLS chunk"); */ } + break; + + case JET_APP_DATA_CHUNK: + easHandle->jetHandle->appDataOffset = pos; + easHandle->jetHandle->appDataSize = chunkSize; + break; + + case INFO_JET_COPYRIGHT: + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized JET chunk type 0x%08x", chunkType); */ } + break; + } + + /* offset to next chunk */ + pos += chunkSize; + } + + /* close file if something went wrong */ + if (result != EAS_SUCCESS) + EAS_HWCloseFile(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle); + + return result; +} + +/*---------------------------------------------------------------------------- + * JET_GetAppData() + *---------------------------------------------------------------------------- + * Returns location and size of application data in the JET file + *---------------------------------------------------------------------------- +*/ +EAS_RESULT JET_GetAppData (EAS_DATA_HANDLE easHandle, EAS_I32 *pAppDataOffset, EAS_I32 *pAppDataSize) +{ + + /* check for app chunk */ + if (easHandle->jetHandle->appDataSize == 0) + { + *pAppDataOffset = *pAppDataSize = 0; + return EAS_FAILURE; + } + + /* return app data */ + *pAppDataOffset = easHandle->jetHandle->appDataOffset; + *pAppDataSize = easHandle->jetHandle->appDataSize; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * JET_CloseFile() + *---------------------------------------------------------------------------- + * Closes a JET content file and releases associated resources + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_CloseFile (EAS_DATA_HANDLE easHandle) +{ + EAS_INT index; + EAS_RESULT result = EAS_SUCCESS; + + /* close open streams */ + for (index = 0; index < SEG_QUEUE_DEPTH; index++) + { + if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) + { + result = JET_CloseSegment(easHandle, index); + if (result != EAS_SUCCESS) + break; + } + } + + /* close the main file handle */ + if ((result == EAS_SUCCESS) && (easHandle->jetHandle->jetFileHandle != NULL)) + { + result = EAS_HWCloseFile(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle); + if (result == EAS_SUCCESS) + easHandle->jetHandle->jetFileHandle = NULL; + } + return result; +} + +/*---------------------------------------------------------------------------- + * JET_Init() + *---------------------------------------------------------------------------- + * Initializes the JET library, allocates memory, etc. Call + * JET_Shutdown to de-allocate memory. + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Init (EAS_DATA_HANDLE easHandle, const S_JET_CONFIG *pConfig, EAS_INT configSize) +{ + S_JET_DATA *pJet; + EAS_U8 flags = 0; + + /* sanity check */ + if (easHandle == NULL) + return EAS_ERROR_HANDLE_INTEGRITY; + if (easHandle->jetHandle != NULL) + return EAS_ERROR_FEATURE_ALREADY_ACTIVE; + if (pConfig == NULL) + pConfig = &jetDefaultConfig; + + /* allocate the JET data object */ + pJet = EAS_HWMalloc(easHandle->hwInstData, sizeof(S_JET_DATA)); + if (pJet == NULL) + return EAS_ERROR_MALLOC_FAILED; + + /* initialize JET data structure */ + EAS_HWMemSet(pJet, 0, sizeof(S_JET_DATA)); + easHandle->jetHandle = pJet; + pJet->flags = flags; + + /* copy config data */ + if (configSize > (EAS_INT) sizeof(S_JET_CONFIG)) + configSize = sizeof(S_JET_CONFIG); + EAS_HWMemCpy(&pJet->config, pConfig, configSize); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * JET_Shutdown() + *---------------------------------------------------------------------------- + * Frees any memory used by the JET library + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Shutdown (EAS_DATA_HANDLE easHandle) +{ + EAS_RESULT result; + + /* close any open files */ + result = JET_CloseFile(easHandle); + + /* free allocated data */ + EAS_HWFree(easHandle->hwInstData, easHandle->jetHandle); + easHandle->jetHandle = NULL; + return result; +} + +/*---------------------------------------------------------------------------- + * JET_Status() + *---------------------------------------------------------------------------- + * Returns current status + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Status (EAS_DATA_HANDLE easHandle, S_JET_STATUS *pStatus) +{ + S_JET_SEGMENT *pSeg; + + pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; + if (pSeg->streamHandle != NULL) + { + pStatus->currentUserID = pSeg->userID; + pStatus->segmentRepeatCount = pSeg->repeatCount; + } + else + { + pStatus->currentUserID = -1; + pStatus->segmentRepeatCount = 0; + } + + pStatus->paused = !(easHandle->jetHandle->flags & JET_FLAGS_PLAYING); + pStatus->numQueuedSegments = easHandle->jetHandle->numQueuedSegments; + pStatus->currentPlayingSegment = easHandle->jetHandle->playSegment; + pStatus->currentQueuedSegment = easHandle->jetHandle->queueSegment; + if (pSeg->streamHandle != NULL) + { + EAS_RESULT result; + EAS_I32 location ; + if ((result = EAS_GetLocation(easHandle, pSeg->streamHandle, &location)) == EAS_SUCCESS) + if(location != 0) + { + pStatus->location = location; + } + } + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * JET_GetEvent() + *---------------------------------------------------------------------------- + * Checks for application events + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_BOOL JET_GetEvent (EAS_DATA_HANDLE easHandle, EAS_U32 *pEventRaw, S_JET_EVENT *pEvent) +{ + EAS_U32 jetEvent; + EAS_BOOL gotEvent; + + /* process event queue */ + gotEvent = JET_ReadQueue(easHandle->jetHandle->appEventQueue, + &easHandle->jetHandle->appEventQueueRead, + easHandle->jetHandle->appEventQueueWrite, + APP_EVENT_QUEUE_SIZE, &jetEvent); + + if (gotEvent) + { + if (pEventRaw != NULL) + *pEventRaw = jetEvent; + + if (pEvent != NULL) + JET_ParseEvent(jetEvent, pEvent); + } + + return gotEvent; +} + +/*---------------------------------------------------------------------------- + * JET_QueueSegment() + *---------------------------------------------------------------------------- + * Queue a segment for playback + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_QueueSegment (EAS_DATA_HANDLE easHandle, EAS_INT segmentNum, EAS_INT libNum, EAS_INT repeatCount, EAS_INT transpose, EAS_U32 muteFlags, EAS_U8 userID) +{ + EAS_FILE_HANDLE fileHandle; + EAS_RESULT result; + S_JET_SEGMENT *p; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_QueueSegment segNum=%d, queue=%d\n", segmentNum, easHandle->jetHandle->queueSegment); */ } + + /* make sure it's a valid segment */ + if (segmentNum >= easHandle->jetHandle->numSegments) + return EAS_ERROR_PARAMETER_RANGE; + + /* make sure it's a valid DLS */ + if (libNum >= easHandle->jetHandle->numLibraries) + return EAS_ERROR_PARAMETER_RANGE; + + /* check to see if queue is full */ + p = &easHandle->jetHandle->segQueue[easHandle->jetHandle->queueSegment]; + if (p->streamHandle != NULL) + return EAS_ERROR_QUEUE_IS_FULL; + + /* initialize data */ + p->userID = userID; + p->repeatCount = (EAS_I16) repeatCount; + p->transpose = (EAS_I8) transpose; + p->libNum = (EAS_I8) libNum; + p->muteFlags = muteFlags; + p->state = JET_STATE_CLOSED; + + /* open the file */ + result = EAS_OpenJETStream(easHandle, easHandle->jetHandle->jetFileHandle, easHandle->jetHandle->segmentOffsets[segmentNum], &p->streamHandle); + if (result != EAS_SUCCESS) + return result; + p->state = JET_STATE_OPEN; + + /* if less than SEG_QUEUE_DEPTH segments queued up, prepare file for playback */ + if (++easHandle->jetHandle->numQueuedSegments < SEG_QUEUE_DEPTH) + { + result = JET_PrepareSegment(easHandle, easHandle->jetHandle->queueSegment); + if (result != EAS_SUCCESS) + return result; + } + + /* create duplicate file handle */ + result = EAS_HWDupHandle(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &fileHandle); + if (result != EAS_SUCCESS) + return result; + + easHandle->jetHandle->jetFileHandle = fileHandle; + easHandle->jetHandle->queueSegment = (EAS_U8) JET_NextSegment(easHandle->jetHandle->queueSegment); + return result; +} + +/*---------------------------------------------------------------------------- + * JET_Play() + *---------------------------------------------------------------------------- + * Starts playback of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Play (EAS_DATA_HANDLE easHandle) +{ + EAS_RESULT result; + EAS_INT index; + EAS_INT count = 0; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Play\n"); */ } + + /* sanity check */ + if (easHandle->jetHandle->flags & JET_FLAGS_PLAYING) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* resume all paused streams */ + for (index = 0; index < SEG_QUEUE_DEPTH; index++) + { + if (((index == easHandle->jetHandle->playSegment) && (easHandle->jetHandle->segQueue[index].state == JET_STATE_READY)) || + (easHandle->jetHandle->segQueue[index].state == JET_STATE_PAUSED)) + { + result = JET_StartPlayback(easHandle, index); + if (result != EAS_SUCCESS) + return result; + count++; + } + } + + /* if no streams are playing, return error */ + if (!count) + return EAS_ERROR_QUEUE_IS_EMPTY; + + easHandle->jetHandle->flags |= JET_FLAGS_PLAYING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * JET_Pause() + *---------------------------------------------------------------------------- + * Pauses playback of the file + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Pause (EAS_DATA_HANDLE easHandle) +{ + EAS_RESULT result; + EAS_INT index; + EAS_INT count = 0; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Pause\n"); */ } + + /* sanity check */ + if ((easHandle->jetHandle->flags & JET_FLAGS_PLAYING) == 0) + return EAS_ERROR_NOT_VALID_IN_THIS_STATE; + + /* pause all playing streams */ + for (index = 0; index < SEG_QUEUE_DEPTH; index++) + { + if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) + { + result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle); + if (result != EAS_SUCCESS) + return result; + easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].state = JET_STATE_PAUSED; + count++; + } + } + + /* if no streams are paused, return error */ + if (!count) + return EAS_ERROR_QUEUE_IS_EMPTY; + + easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * JET_SetMuteFlags() + *---------------------------------------------------------------------------- + * Change the state of the mute flags + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_SetMuteFlags (EAS_DATA_HANDLE easHandle, EAS_U32 muteFlags, EAS_BOOL sync) +{ + S_JET_SEGMENT *pSeg; + + /* get pointer to current segment */ + pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; + + /* unsynchronized mute, set flags and return */ + if (!sync) + { + if (pSeg->streamHandle == NULL) + return EAS_ERROR_QUEUE_IS_EMPTY; + pSeg->muteFlags = muteFlags; + return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) muteFlags); + } + + + /* check for valid stream state */ + if (pSeg->state == JET_STATE_CLOSED) + return EAS_ERROR_QUEUE_IS_EMPTY; + + /* save mute flags */ + pSeg->muteFlags = muteFlags; + + /* if repeating segment, set mute update flag */ + if (sync) + pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * JET_SetMuteFlag() + *---------------------------------------------------------------------------- + * Change the state of a single mute flag + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_SetMuteFlag (EAS_DATA_HANDLE easHandle, EAS_INT trackNum, EAS_BOOL muteFlag, EAS_BOOL sync) +{ + S_JET_SEGMENT *pSeg; + EAS_U32 trackMuteFlag; + + + /* setup flag */ + if ((trackNum < 0) || (trackNum > 31)) + return EAS_ERROR_PARAMETER_RANGE; + trackMuteFlag = (1 << trackNum); + + /* get pointer to current segment */ + pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; + + /* unsynchronized mute, set flags and return */ + if (!sync) + { + if (pSeg->streamHandle == NULL) + return EAS_ERROR_QUEUE_IS_EMPTY; + if (muteFlag) + pSeg->muteFlags |= trackMuteFlag; + else + pSeg->muteFlags &= ~trackMuteFlag; + return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); + } + + + /* check for valid stream state */ + if (pSeg->state == JET_STATE_CLOSED) + return EAS_ERROR_QUEUE_IS_EMPTY; + + /* save mute flags and set mute update flag */ + if (muteFlag) + pSeg->muteFlags |= trackMuteFlag; + else + pSeg->muteFlags &= ~trackMuteFlag; + pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * JET_TriggerClip() + *---------------------------------------------------------------------------- + * Unmute a track and then mute it when it is complete. If a clip + * is already playing, change mute event to a trigger event. The + * JET_Event function will not mute the clip, but will allow it + * to continue playing through the next clip. + * + * NOTE: We use bit 7 to indicate an entry in the queue. For a + * small queue, it is cheaper in both memory and CPU cycles to + * scan the entire queue for non-zero events than keep enqueue + * and dequeue indices. + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_TriggerClip (EAS_DATA_HANDLE easHandle, EAS_INT clipID) +{ + EAS_INT i; + EAS_INT index = -1; + + /* check for valid clipID */ + if ((clipID < 0) || (clipID > 63)) + return EAS_ERROR_PARAMETER_RANGE; + + /* set active flag */ + clipID |= JET_CLIP_ACTIVE_FLAG; + + /* Reverse the search so that we get the first empty element */ + for (i = JET_MUTE_QUEUE_SIZE-1; i >= 0 ; i--) + { + if (easHandle->jetHandle->muteQueue[i] == clipID) + { + index = i; + break; + } + if (easHandle->jetHandle->muteQueue[i] == 0) + index = i; + } + if (index < 0) + return EAS_ERROR_QUEUE_IS_FULL; + + easHandle->jetHandle->muteQueue[index] = (EAS_U8) clipID | JET_CLIP_TRIGGER_FLAG; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * JET_Process() + *---------------------------------------------------------------------------- + * Called during EAS_Render to process stream states + *---------------------------------------------------------------------------- +*/ +EAS_PUBLIC EAS_RESULT JET_Process (EAS_DATA_HANDLE easHandle) +{ + S_JET_SEGMENT *pSeg; + EAS_STATE state; + EAS_INT index; + EAS_INT playIndex; + EAS_RESULT result = EAS_SUCCESS; + EAS_BOOL endOfLoop = EAS_FALSE; + EAS_BOOL startNextSegment = EAS_FALSE; + EAS_BOOL prepareNextSegment = EAS_FALSE; + EAS_U32 jetEvent; + + /* process event queue */ + while (JET_ReadQueue(easHandle->jetHandle->jetEventQueue, + &easHandle->jetHandle->jetEventQueueRead, + easHandle->jetHandle->jetEventQueueWrite, + JET_EVENT_QUEUE_SIZE, &jetEvent)) + { + S_JET_EVENT event; +#ifdef DEBUG_JET + JET_DumpEvent("JET_Process", jetEvent); +#endif + JET_ParseEvent(jetEvent, &event); + + /* check for end of loop */ + if ((event.controller == JET_EVENT_MARKER) && + (event.value == JET_MARKER_LOOP_END) && + (easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle != NULL)) + endOfLoop = EAS_TRUE; + } + + /* check state of all streams */ + index = playIndex = easHandle->jetHandle->playSegment; + for (;;) + { + pSeg = &easHandle->jetHandle->segQueue[index]; + if (pSeg->state != JET_STATE_CLOSED) + { + + /* get playback state */ + result = EAS_State(easHandle, pSeg->streamHandle, &state); + if (result != EAS_SUCCESS) + return result; + + /* process state */ + switch (pSeg->state) + { + /* take action if this segment is stopping */ + case JET_STATE_PLAYING: + if (endOfLoop || (state == EAS_STATE_STOPPING) || (state == EAS_STATE_STOPPED)) + { + /* handle repeats */ + if (pSeg->repeatCount != 0) + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render repeating segment %d\n", index); */ } + result = EAS_Locate(easHandle, pSeg->streamHandle, 0, EAS_FALSE); + if (result != EAS_SUCCESS) + return result; + if (pSeg->repeatCount > 0) + pSeg->repeatCount--; + + /* update mute flags if necessary */ + if (pSeg->flags & JET_SEG_FLAG_MUTE_UPDATE) + { + result = EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); + if (result != EAS_SUCCESS) + return result; + pSeg->flags &= ~JET_SEG_FLAG_MUTE_UPDATE; + } + + } + /* no repeat, start next segment */ + else + { + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render stopping queue %d\n", index); */ } + startNextSegment = EAS_TRUE; + pSeg->state = JET_STATE_STOPPING; + easHandle->jetHandle->playSegment = (EAS_U8) JET_NextSegment(index); + } + } + break; + + /* if playback has stopped, close the segment */ + case JET_STATE_STOPPING: + if (state == EAS_STATE_STOPPED) + { + result = JET_CloseSegment(easHandle, index); + if (result != EAS_SUCCESS) + return result; + } + break; + + case JET_STATE_READY: + if (startNextSegment) + { + result = JET_StartPlayback(easHandle, index); + if (result != EAS_SUCCESS) + return result; + startNextSegment = EAS_FALSE; + prepareNextSegment = EAS_TRUE; + } + break; + + case JET_STATE_OPEN: + if (prepareNextSegment) + { + result = JET_PrepareSegment(easHandle, index); + if (result != EAS_SUCCESS) + return result; + prepareNextSegment = EAS_FALSE; + } + break; + + case JET_STATE_PAUSED: + break; + + default: + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "JET_Render: Unexpected segment state %d\n", pSeg->state); */ } + break; + } + } + + /* increment index */ + index = JET_NextSegment(index); + if (index == playIndex) + break; + } + + /* if out of segments, clear playing flag */ + if (easHandle->jetHandle->numQueuedSegments == 0) + easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; + + return result; +} + +/*---------------------------------------------------------------------------- + * JET_Event() + *---------------------------------------------------------------------------- + * Called from MIDI parser when data of interest is received + *---------------------------------------------------------------------------- +*/ +void JET_Event (EAS_DATA_HANDLE easHandle, EAS_U32 segTrack, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) +{ + EAS_U32 event; + + if (easHandle->jetHandle == NULL) + return; + + /* handle triggers */ + if (controller == JET_EVENT_TRIGGER_CLIP) + { + S_JET_SEGMENT *pSeg; + EAS_INT i; + EAS_U32 muteFlag; + + for (i = 0; i < JET_MUTE_QUEUE_SIZE; i++) + { + /* search for event in queue */ + if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_ID_MASK) == (value & JET_CLIP_ID_MASK)) + { + /* get segment pointer and mute flag */ + pSeg = &easHandle->jetHandle->segQueue[segTrack >> JET_EVENT_SEG_SHIFT]; + muteFlag = 1 << ((segTrack & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT); + + /* un-mute the track */ + if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_TRIGGER_FLAG) && ((value & 0x40) > 0)) + { + pSeg->muteFlags &= ~muteFlag; + easHandle->jetHandle->muteQueue[i] &= ~JET_CLIP_TRIGGER_FLAG; + } + + /* mute the track */ + else + { + EAS_U32 beforeMute ; + beforeMute = pSeg->muteFlags ; + pSeg->muteFlags |= muteFlag; + if (beforeMute != pSeg->muteFlags) + easHandle->jetHandle->muteQueue[i] = 0; + } + EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); + return; + } + } + return; + } + + /* generic event stuff */ + event = (channel << JET_EVENT_CHAN_SHIFT) | (controller << JET_EVENT_CTRL_SHIFT) | value; + + /* write to app queue, translate queue index to segment number */ + if ((controller >= easHandle->jetHandle->config.appEventRangeLow) && (controller <= easHandle->jetHandle->config.appEventRangeHigh)) + { + + event |= easHandle->jetHandle->segQueue[(segTrack & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT].userID << JET_EVENT_SEG_SHIFT; +#ifdef DEBUG_JET + JET_DumpEvent("JET_Event[app]", event); +#endif + JET_WriteQueue(easHandle->jetHandle->appEventQueue, + &easHandle->jetHandle->appEventQueueWrite, + easHandle->jetHandle->appEventQueueRead, + APP_EVENT_QUEUE_SIZE, + event); + } + + /* write to JET queue */ + else if ((controller >= JET_EVENT_LOW) && (controller <= JET_EVENT_HIGH)) + { + event |= segTrack; +#ifdef DEBUG_JET + JET_DumpEvent("JET_Event[jet]", event); +#endif + JET_WriteQueue(easHandle->jetHandle->jetEventQueue, + &easHandle->jetHandle->jetEventQueueWrite, + easHandle->jetHandle->jetEventQueueRead, + JET_EVENT_QUEUE_SIZE, + event); + } +} + +/*---------------------------------------------------------------------------- + * JET_Clear_Queue() + *---------------------------------------------------------------------------- + * Clears the queue and stops play without a complete shutdown + *---------------------------------------------------------------------------- +*/ +EAS_RESULT JET_Clear_Queue(EAS_DATA_HANDLE easHandle) +{ + EAS_INT index; + EAS_RESULT result = EAS_SUCCESS; + + { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Clear_Queue\n"); */ } + + /* pause all playing streams */ + for (index = 0; index < SEG_QUEUE_DEPTH; index++) + { + if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) + { + result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[index].streamHandle); + if (result != EAS_SUCCESS) + return result; + + easHandle->jetHandle->segQueue[index].state = JET_STATE_PAUSED; + } + } + + /* close all streams */ + for (index = 0; index < SEG_QUEUE_DEPTH; index++) + { + if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) + { + result = JET_CloseSegment(easHandle, index); + if (result != EAS_SUCCESS) + return result; + } + } + + /* clear all clips */ + for (index = 0; index < JET_MUTE_QUEUE_SIZE ; index++) + { + easHandle->jetHandle->muteQueue[index] = 0; + } + + easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; + easHandle->jetHandle->playSegment = easHandle->jetHandle->queueSegment = 0; + return result; +} + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/jet_data.h b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/jet_data.h new file mode 100755 index 0000000..6bd72e0 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/jet_data.h @@ -0,0 +1,183 @@ +/*---------------------------------------------------------------------------- + * + * File: + * jet_data.h + * + * Contents and purpose: + * Internal data structures and interfaces for JET + * + * Copyright (c) 2006 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 554 $ + * $Date: 2007-02-02 11:06:10 -0800 (Fri, 02 Feb 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifndef _JET_DATA_H +#define _JET_DATA_H + +#include "eas.h" +#include "jet.h" + +/* maximum number of segments allowed in a JET file */ +#ifndef JET_MAX_SEGMENTS +#define JET_MAX_SEGMENTS 32 +#endif + +/* maximum number of DLS collections allowed in a JET file */ +#ifndef JET_MAX_DLS_COLLECTIONS +#define JET_MAX_DLS_COLLECTIONS 4 +#endif + +/* maximum number of JET events in internal queue */ +#ifndef JET_EVENT_QUEUE_SIZE +#define JET_EVENT_QUEUE_SIZE 32 +#endif + +/* maximum number of JET events in application queue */ +#ifndef APP_EVENT_QUEUE_SIZE +#define APP_EVENT_QUEUE_SIZE 32 +#endif + +/* maximum number of active mute events */ +#ifndef JET_MUTE_QUEUE_SIZE +#define JET_MUTE_QUEUE_SIZE 8 +#endif + +/*---------------------------------------------------------------------------- + * JET event definitions + *---------------------------------------------------------------------------- +*/ +#define JET_EVENT_APP_LOW 80 +#define JET_EVENT_APP_HIGH 83 +#define JET_EVENT_LOW 102 +#define JET_EVENT_HIGH 119 +#define JET_EVENT_MARKER 102 +#define JET_EVENT_TRIGGER_CLIP 103 + +#define JET_MARKER_LOOP_END 0 + +#define JET_CLIP_ACTIVE_FLAG 0x80 +#define JET_CLIP_TRIGGER_FLAG 0x40 +#define JET_CLIP_ID_MASK 0x3f + +/*---------------------------------------------------------------------------- + * JET file definitions + *---------------------------------------------------------------------------- +*/ +#define JET_TAG(a,b,c,d) (\ + ( ((EAS_U32)(a) & 0xFF) << 24 ) \ + + ( ((EAS_U32)(b) & 0xFF) << 16 ) \ + + ( ((EAS_U32)(c) & 0xFF) << 8 ) \ + + ( ((EAS_U32)(d) & 0xFF))) + +#define JET_VERSION 0x01000000 +#define JET_HEADER_TAG JET_TAG('J','E','T',' ') +#define JET_INFO_CHUNK JET_TAG('J','I','N','F') +#define JET_SMF_CHUNK JET_TAG('J','S','M','F') +#define JET_DLS_CHUNK JET_TAG('J','D','L','S') +#define INFO_JET_COPYRIGHT JET_TAG('J','C','O','P') +#define JET_APP_DATA_CHUNK JET_TAG('J','A','P','P') + +#define INFO_NUM_SMF_CHUNKS JET_TAG('S','M','F','#') +#define INFO_NUM_DLS_CHUNKS JET_TAG('D','L','S','#') +#define INFO_JET_VERSION JET_TAG('J','V','E','R') + +/*---------------------------------------------------------------------------- + * S_JET_SEGMENT + * + * JET segment data + *---------------------------------------------------------------------------- +*/ +typedef struct s_jet_segment_tag +{ + EAS_HANDLE streamHandle; + EAS_U32 muteFlags; + EAS_I16 repeatCount; + EAS_U8 userID; + EAS_I8 transpose; + EAS_I8 libNum; + EAS_U8 state; + EAS_U8 flags; +} S_JET_SEGMENT; + +/* S_JET_SEGMENT.state */ +typedef enum +{ + JET_STATE_CLOSED, + JET_STATE_OPEN, + JET_STATE_READY, + JET_STATE_PLAYING, + JET_STATE_PAUSED, + JET_STATE_STOPPING +} E_JET_SEGMENT_STATE; + +/* S_JEG_SEGMENT.flags */ +#define JET_SEG_FLAG_MUTE_UPDATE 0x01 + +/*---------------------------------------------------------------------------- + * S_JET_DATA + * + * Main JET data structure + *---------------------------------------------------------------------------- +*/ +#define SEG_QUEUE_DEPTH 3 +typedef struct s_jet_data_tag +{ + EAS_FILE_HANDLE jetFileHandle; + S_JET_SEGMENT segQueue[SEG_QUEUE_DEPTH]; + EAS_I32 segmentOffsets[JET_MAX_SEGMENTS]; + EAS_I32 appDataOffset; + EAS_I32 appDataSize; + EAS_DLSLIB_HANDLE libHandles[JET_MAX_DLS_COLLECTIONS]; + EAS_U32 jetEventQueue[JET_EVENT_QUEUE_SIZE]; + EAS_U32 appEventQueue[APP_EVENT_QUEUE_SIZE]; + S_JET_CONFIG config; + EAS_U32 segmentTime; + EAS_U8 muteQueue[JET_MUTE_QUEUE_SIZE]; + EAS_U8 numSegments; + EAS_U8 numLibraries; + EAS_U8 flags; + EAS_U8 playSegment; + EAS_U8 queueSegment; + EAS_U8 numQueuedSegments; + EAS_U8 jetEventQueueRead; + EAS_U8 jetEventQueueWrite; + EAS_U8 appEventQueueRead; + EAS_U8 appEventQueueWrite; +} S_JET_DATA; + +/* flags for S_JET_DATA.flags */ +#define JET_FLAGS_PLAYING 1 + +#define JET_EVENT_VAL_MASK 0x0000007f /* mask for value */ +#define JET_EVENT_CTRL_MASK 0x00003f80 /* mask for controller */ +#define JET_EVENT_CHAN_MASK 0x0003c000 /* mask for channel */ +#define JET_EVENT_TRACK_MASK 0x00fc0000 /* mask for track number */ +#define JET_EVENT_SEG_MASK 0xff000000 /* mask for segment ID */ +#define JET_EVENT_CTRL_SHIFT 7 /* shift for controller number */ +#define JET_EVENT_CHAN_SHIFT 14 /* shift to for MIDI channel */ +#define JET_EVENT_TRACK_SHIFT 18 /* shift to get track ID to bit 0 */ +#define JET_EVENT_SEG_SHIFT 24 /* shift to get segment ID to bit 0 */ + +/* prototype for callback function */ +extern void JET_Event (EAS_DATA_HANDLE easHandle, EAS_U32 segTrack, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); + +/* prototype for JET render function */ +extern EAS_PUBLIC EAS_RESULT JET_Process (EAS_DATA_HANDLE easHandle); + +#endif + diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/wt_22khz.c b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/wt_22khz.c new file mode 100755 index 0000000..6d2c24c --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/lib_src/wt_22khz.c @@ -0,0 +1,14731 @@ +/*---------------------------------------------------------------------------- + * + * Filename: wt_200k_G.c + * Source: wt_200k_G.dls + * CmdLine: -w wt_200k_G.c -l wt_200k_G.log -ce -cf wt_200k_G.dls -w -l -ce -cf wt_200k_G.dls + * Purpose: Wavetable sound libary + * + * Copyright (c) 2009 Sonic Network Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 960 $ + * $Date: 2009-03-18 15:08:29 -0500 (Wed, 18 Mar 2009) $ + *---------------------------------------------------------------------------- +*/ + +#include "eas_sndlib.h" + +/*---------------------------------------------------------------------------- + * Articulations + *---------------------------------------------------------------------------- +*/ +const S_ARTICULATION eas_articulations[] = +{ + { /* articulation 0 */ + { 32767, 30725, 0, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 1 */ + { 32767, 26863, 0, 26863 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 2 */ + { 32767, 30484, 0, 30668 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 3 */ + { 32767, 26439, 0, 26439 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 4 */ + { 32767, 0, 32767, 32715 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 5 */ + { 32767, 21333, 0, 21333 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 6 */ + { 32767, 31882, 0, 31938 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 7 */ + { 32767, 32663, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 8 */ + { 32767, 0, 32767, 0 }, + { 32767, 1902, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 9 */ + { 32767, 32349, 0, 32349 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 10 */ + { 32767, 0, 32767, 17213 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -1 + }, + { /* articulation 11 */ + { 32767, 31730, 0, 31730 }, + { 32767, 761, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -44 + }, + { /* articulation 12 */ + { 32767, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 13 */ + { 32767, 31730, 0, 31730 }, + { 32767, 761, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -31 + }, + { /* articulation 14 */ + { 9511, 21333, 0, 21333 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 15 */ + { 32767, 31617, 0, 31617 }, + { 32767, 761, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -6 + }, + { /* articulation 16 */ + { 32767, 32123, 0, 32194 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 56 + }, + { /* articulation 17 */ + { 32767, 31550, 0, 31550 }, + { 32767, 761, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 6 + }, + { /* articulation 18 */ + { 32767, 31391, 0, 31391 }, + { 32767, 951, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 31 + }, + { /* articulation 19 */ + { 32767, 31964, 0, 31964 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 20 */ + { 32767, 31056, 0, 31056 }, + { 32767, 951, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 21 */ + { 32767, 32289, 0, 32271 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 22 */ + { 19021, 31882, 0, 31911 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 23 */ + { 32767, 31988, 0, 32032 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 24 */ + { 32767, 0, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 12 + }, + { /* articulation 25 */ + { 32767, 31352, 0, 31352 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -25 + }, + { /* articulation 26 */ + { 32767, 0, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 27 */ + { 32767, 31817, 0, 31781 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -25 + }, + { /* articulation 28 */ + { 32767, 30725, 0, 30725 }, + { 32767, 95, 0, 0 }, + 0, 0, 951, 240, 0, 0, 0, 0, -56 + }, + { /* articulation 29 */ + { 32767, 32230, 0, 32218 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -37 + }, + { /* articulation 30 */ + { 32767, 26439, 0, 26439 }, + { 32767, 3804, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 50 + }, + { /* articulation 31 */ + { 32767, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -50 + }, + { /* articulation 32 */ + { 32767, 29434, 0, 29434 }, + { 32767, 3804, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -50 + }, + { /* articulation 33 */ + { 32767, 30240, 0, 30234 }, + { 32767, 3804, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -44 + }, + { /* articulation 34 */ + { 32767, 32558, 0, 32558 }, + { 32767, 254, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 35 */ + { 32767, 0, 32767, 32663 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -63 + }, + { /* articulation 36 */ + { 3804, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -63 + }, + { /* articulation 37 */ + { 32767, 23749, 0, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -59 + }, + { /* articulation 38 */ + { 32767, 30725, 0, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 50 + }, + { /* articulation 39 */ + { 32767, 28809, 0, 28809 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 44 + }, + { /* articulation 40 */ + { 1902, 30725, 0, 30725 }, + { 32767, 380, 0, 0 }, + 0, 0, 951, -100, 0, 0, 0, 0, 44 + }, + { /* articulation 41 */ + { 32767, 9042, 0, 9042 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 25 + }, + { /* articulation 42 */ + { 32767, 29889, 0, 29889 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 43 */ + { 32767, 30240, 0, 30234 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 63 + }, + { /* articulation 44 */ + { 19021, 19970, 0, 19970 }, + { 951, 32767, 32767, 0 }, + 0, 0, 951, 100, 0, 0, 0, 0, -25 + }, + { /* articulation 45 */ + { 3804, 17213, 0, 17213 }, + { 951, 32767, 32767, 0 }, + 0, 0, 951, 500, 0, 0, 0, 0, -25 + }, + { /* articulation 46 */ + { 32767, 17213, 0, 17213 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -56 + }, + { /* articulation 47 */ + { 32767, 30725, 0, 30725 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, -56 + }, + { /* articulation 48 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 49 */ + { 32767, 31180, 0, 31180 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 50 */ + { 19021, 31964, 0, 32071 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 51 */ + { 32767, 29669, 0, 29669 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 52 */ + { 32767, 31742, 0, 31352 }, + { 32767, 294, 0, 0 }, + 0, 0, 951, 0, 10000, 7121, 0, 0, 0 + }, + { /* articulation 53 */ + { 32767, 0, 32767, 31391 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 1555, 0, -2300, 11920, 0, 0, 0 + }, + { /* articulation 54 */ + { 1174, 0, 32767, 31988 }, + { 32767, 127, 0, 0 }, + 0, 0, 1555, 0, 2000, 10721, 0, 8, 15 + }, + { /* articulation 55 */ + { 1174, 0, 32767, 31988 }, + { 951, 127, 0, 0 }, + 0, 0, 1555, 0, 2000, 9023, 0, 5, 15 + }, + { /* articulation 56 */ + { 7608, 0, 32767, 30237 }, + { 32767, 69, 5898, 0 }, + 0, 0, 1555, 0, 6000, 9080, 0, 0, -2 + }, + { /* articulation 57 */ + { 32767, 0, 32767, 29337 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 1555, 0, 0, 0, 0, 0, 1 + }, + { /* articulation 58 */ + { 5141, 0, 32767, 30194 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 1555, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 59 */ + { 32767, 32558, 0, 26439 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 60 */ + { 32767, 32349, 0, 26439 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 61 */ + { 32767, 32072, 0, 32072 }, + { 32767, 95, 0, 0 }, + 0, 34, 989, 0, 2400, 9521, 0, 0, 0 + }, + { /* articulation 62 */ + { 32767, 30234, 0, 30234 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 11738, 0, 16, 0 + }, + { /* articulation 63 */ + { 32767, 32349, 0, 30073 }, + { 32767, 634, 0, 0 }, + 0, 34, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 64 */ + { 32767, 31730, 0, 31476 }, + { 32767, 634, 0, 0 }, + 0, 34, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 65 */ + { 32767, 32418, 0, 25329 }, + { 32767, 95, 0, 0 }, + 0, 34, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 66 */ + { 32767, 32052, 0, 31964 }, + { 32767, 634, 0, 0 }, + 0, 34, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 67 */ + { 32767, 31938, 0, 31938 }, + { 32767, 634, 0, 0 }, + 0, 34, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 68 */ + { 9511, 32663, 18820, 23749 }, + { 1902, 57, 13107, 0 }, + 0, 0, 989, 0, 6000, 5535, 0, 4, 0 + }, + { /* articulation 69 */ + { 32767, 31754, 0, 31730 }, + { 32767, 1902, 0, 0 }, + 0, 52, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 70 */ + { 127, 32686, 3811, 32349 }, + { 95, 38, 32767, 0 }, + 0, 0, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 71 */ + { 4755, 32663, 3566, 28809 }, + { 3804, 32767, 32767, 0 }, + 0, 0, 989, 100, 0, 11919, 0, 0, 0 + }, + { /* articulation 72 */ + { 32767, 31935, 0, 31935 }, + { 32767, 335, 0, 0 }, + 0, 17, 989, 0, 7000, 9023, 0, 0, 0 + }, + { /* articulation 73 */ + { 32767, 31391, 0, 31391 }, + { 32767, 335, 0, 0 }, + 0, 2, 951, 0, 7000, 9023, 0, 0, 0 + }, + { /* articulation 74 */ + { 32767, 32628, 6208, 31935 }, + { 380, 95, 0, 0 }, + 0, 0, 989, 0, 3840, 8302, 0, 8, 0 + }, + { /* articulation 75 */ + { 32767, 32072, 0, 32171 }, + { 32767, 380, 0, 0 }, + 0, 0, 989, 0, 5000, 8321, 0, 0, 0 + }, + { /* articulation 76 */ + { 32767, 31935, 0, 31935 }, + { 32767, 380, 0, 0 }, + 0, 0, 951, 0, 5000, 7934, 0, 0, 0 + }, + { /* articulation 77 */ + { 32767, 32117, 0, 30685 }, + { 32767, 63, 0, 0 }, + 0, 17, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 78 */ + { 32767, 32245, 0, 23749 }, + { 32767, 1902, 0, 0 }, + 0, 172, 989, 0, 1000, 11107, 0, 0, 0 + }, + { /* articulation 79 */ + { 32767, 32663, 6208, 31935 }, + { 95, 95, 0, 0 }, + 0, 34, 1622, 0, 3560, 8834, 1, 8, 0 + }, + { /* articulation 80 */ + { 32767, 32362, 0, 26439 }, + { 32767, 190, 0, 0 }, + 0, 17, 989, 0, 6000, 9907, 0, 0, 0 + }, + { /* articulation 81 */ + { 32767, 32245, 0, 23749 }, + { 32767, 63, 0, 0 }, + 0, 17, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 82 */ + { 32767, 31730, 18820, 9042 }, + { 32767, 32767, 32767, 0 }, + 0, 17, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 83 */ + { 32767, 32715, 128, 32168 }, + { 32767, 127, 0, 0 }, + 0, 0, 989, 0, 0, 11920, 0, 8, 0 + }, + { /* articulation 84 */ + { 32767, 32072, 0, 32072 }, + { 32767, 67, 0, 0 }, + 3, 0, 572, 0, 5000, 5535, 0, 0, 0 + }, + { /* articulation 85 */ + { 3804, 32663, 18820, 23749 }, + { 32767, 2024, 0, 0 }, + 10, 34, 1008, -30, 0, 0, 0, 0, 0 + }, + { /* articulation 86 */ + { 19021, 32663, 18820, 23749 }, + { 761, 95, 0, 0 }, + 0, 34, 989, 0, 4473, 7131, 0, 8, 0 + }, + { /* articulation 87 */ + { 1902, 32628, 6208, 32171 }, + { 634, 38, 16384, 0 }, + 0, 0, 989, 0, 2987, 7877, 0, 12, 0 + }, + { /* articulation 88 */ + { 32767, 32593, 0, 31935 }, + { 32767, 95, 0, 0 }, + 0, 0, 1162, 0, 4053, 7930, 2, 12, 0 + }, + { /* articulation 89 */ + { 380, 32684, 6208, 31935 }, + { 32767, 112, 0, 0 }, + 0, 0, 989, 0, 0, 8887, 0, 0, 0 + }, + { /* articulation 90 */ + { 19021, 32663, 18820, 23749 }, + { 1268, 95, 0, 0 }, + 0, 34, 989, 0, 5113, 7981, 0, 4, 0 + }, + { /* articulation 91 */ + { 1902, 32663, 6208, 30725 }, + { 1902, 127, 0, 0 }, + 0, 34, 989, 0, 3500, 7877, 0, 5, 0 + }, + { /* articulation 92 */ + { 1902, 32663, 6208, 30725 }, + { 1268, 95, 0, 0 }, + 0, 34, 951, 0, 4773, 8355, 0, 5, 0 + }, + { /* articulation 93 */ + { 476, 32663, 10809, 31935 }, + { 32767, 32767, 32767, 0 }, + 0, 34, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 94 */ + { 3804, 32663, 18820, 30234 }, + { 32767, 32767, 32767, 0 }, + 0, 34, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 95 */ + { 7608, 32663, 18820, 17213 }, + { 2536, 261, 0, 0 }, + 0, 34, 989, 0, 1200, 11690, 0, 4, 0 + }, + { /* articulation 96 */ + { 32767, 32468, 15076, 30234 }, + { 32767, 32767, 32767, 0 }, + 0, 36, 2183, 0, 0, 11919, 1, 0, 0 + }, + { /* articulation 97 */ + { 32767, 0, 32767, 32663 }, + { 380, 32767, 32767, 0 }, + 0, 0, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 98 */ + { 32767, 31391, 0, 31391 }, + { 32767, 634, 0, 0 }, + 0, 0, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 99 */ + { 32767, 32558, 0, 23749 }, + { 1268, 190, 13107, 0 }, + 0, 34, 989, 0, 3200, 8321, 0, 0, 0 + }, + { /* articulation 100 */ + { 32767, 0, 32767, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 101 */ + { 32767, 32072, 0, 23749 }, + { 32767, 1087, 0, 0 }, + 0, 34, 989, 0, 8187, 5535, 0, 5, 0 + }, + { /* articulation 102 */ + { 32767, 32558, 0, 29434 }, + { 32767, 190, 7667, 0 }, + 5, 0, 989, 0, 6053, 5535, 0, 5, 0 + }, + { /* articulation 103 */ + { 32767, 32663, 18820, 23749 }, + { 1902, 95, 0, 0 }, + 0, 0, 989, 0, 2700, 9852, 0, 0, 0 + }, + { /* articulation 104 */ + { 32767, 32663, 18820, 27897 }, + { 1902, 95, 0, 0 }, + 0, 0, 989, 0, 2700, 9852, 0, 0, 0 + }, + { /* articulation 105 */ + { 32767, 32663, 18820, 23749 }, + { 32767, 1268, 0, 0 }, + 0, 52, 951, 0, 2500, 10490, 1, 8, 0 + }, + { /* articulation 106 */ + { 32767, 32663, 23493, 23749 }, + { 32767, 380, 0, 0 }, + 0, 34, 988, 0, 4000, 10223, 1, 4, 0 + }, + { /* articulation 107 */ + { 32767, 32663, 18820, 27897 }, + { 32767, 126, 7667, 0 }, + 0, 0, 989, 0, 1813, 9154, 0, 0, 0 + }, + { /* articulation 108 */ + { 32767, 31730, 0, 31730 }, + { 32767, 380, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 109 */ + { 32767, 31180, 0, 30484 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 11690, 0, 0, 0 + }, + { /* articulation 110 */ + { 32767, 30725, 0, 30725 }, + { 32767, 380, 0, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 111 */ + { 32767, 32349, 18820, 27897 }, + { 32767, 95, 0, 0 }, + 12, 34, 951, 0, 3000, 10223, 0, 0, 0 + }, + { /* articulation 112 */ + { 32767, 32349, 18820, 27897 }, + { 32767, 63, 0, 0 }, + 12, 34, 951, 0, 1900, 10031, 0, 0, 0 + }, + { /* articulation 113 */ + { 32767, 32663, 18820, 26439 }, + { 32767, 63, 0, 0 }, + 12, 34, 988, 0, 1000, 11107, 0, 0, 0 + }, + { /* articulation 114 */ + { 32767, 32663, 18820, 26439 }, + { 32767, 63, 0, 0 }, + 12, 34, 988, 0, 2000, 11107, 0, 0, 0 + }, + { /* articulation 115 */ + { 32767, 32505, 0, 26439 }, + { 32767, 190, 0, 0 }, + 0, 17, 989, 0, 4000, 8321, 0, 0, 0 + }, + { /* articulation 116 */ + { 32767, 31832, 19893, 9042 }, + { 32767, 476, 0, 0 }, + 0, 34, 1452, 0, 0, 11919, 0, 0, 0 + }, + { /* articulation 117 */ + { 19021, 32072, 23493, 9042 }, + { 32767, 32767, 32767, 0 }, + 0, 34, 1355, 0, 0, 11877, 1, 0, 0 + }, + { /* articulation 118 */ + { 32767, 32468, 0, 23749 }, + { 32767, 190, 0, 0 }, + 0, 34, 989, 0, 3500, 9023, 0, 0, 0 + }, + { /* articulation 119 */ + { 32767, 17213, 23493, 0 }, + { 32767, 32767, 32767, 0 }, + 0, 17, 1521, 0, 0, 10925, 1, 0, 0 + }, + { /* articulation 120 */ + { 32767, 32505, 0, 26439 }, + { 32767, 190, 0, 0 }, + 0, 52, 989, 0, 3200, 8721, 0, 4, 0 + }, + { /* articulation 121 */ + { 3804, 32663, 18820, 23749 }, + { 32767, 32767, 32767, 0 }, + 0, 34, 989, 0, 0, 0, 1, 0, 0 + }, + { /* articulation 122 */ + { 9511, 32663, 18820, 25329 }, + { 32767, 32767, 32767, 0 }, + 0, 34, 989, 0, 0, 11877, 0, 8, 0 + }, + { /* articulation 123 */ + { 32767, 32663, 18820, 23749 }, + { 32767, 32, 0, 0 }, + 0, 17, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 124 */ + { 32767, 32558, 0, 23749 }, + { 32767, 380, 0, 0 }, + 0, 34, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 125 */ + { 32767, 32663, 18820, 23749 }, + { 32767, 24, 0, 0 }, + 0, 17, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 126 */ + { 32767, 30725, 0, 30725 }, + { 32767, 761, 0, 0 }, + 0, 0, 989, 0, 3000, 10223, 0, 8, 0 + }, + { /* articulation 127 */ + { 127, 0, 32767, 32349 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 1522, 0, 0, 11423, 4, 0, 0 + }, + { /* articulation 128 */ + { 951, 32422, 0, 32387 }, + { 32767, 19, 0, 0 }, + 0, 0, 989, 0, 0, 11423, 0, 0, 0 + }, + { /* articulation 129 */ + { 391, 0, 0, 31180 }, + { 190, 32767, 32767, 0 }, + 0, 0, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 130 */ + { 32767, 30725, 0, 30725 }, + { 32767, 761, 0, 0 }, + 0, 0, 989, 1200, 0, 0, 0, 0, 0 + }, + { /* articulation 131 */ + { 32767, 31730, 0, 31935 }, + { 32767, 380, 0, 0 }, + 0, 0, 989, 50, 0, 0, 0, 0, 0 + }, + { /* articulation 132 */ + { 32767, 32072, 0, 32072 }, + { 32767, 19021, 0, 0 }, + 0, 0, 989, 0, 4700, 7769, 0, 0, 0 + }, + { /* articulation 133 */ + { 32767, 30073, 0, 30073 }, + { 32767, 32767, 0, 0 }, + 0, 0, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 134 */ + { 32767, 32558, 32767, 32558 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 135 */ + { 32767, 32663, 18820, 17213 }, + { 32767, 190, 0, 0 }, + 10, 34, 951, 0, 2000, 10696, 0, 0, 0 + }, + { /* articulation 136 */ + { 32767, 32663, 10809, 17213 }, + { 32767, 190, 0, 0 }, + 12, 34, 982, 0, 0, 10910, 0, 0, 0 + }, + { /* articulation 137 */ + { 32767, 32663, 18820, 17213 }, + { 32767, 190, 0, 0 }, + 10, 34, 951, 0, 1200, 10218, 0, 0, 0 + }, + { /* articulation 138 */ + { 32767, 32663, 18820, 17213 }, + { 32767, 190, 0, 0 }, + 10, 34, 951, 0, 1100, 9525, 0, 0, 0 + }, + { /* articulation 139 */ + { 19021, 32558, 18820, 23749 }, + { 32767, 19, 0, 0 }, + 10, 34, 988, 0, 2000, 10962, 0, 0, 0 + }, + { /* articulation 140 */ + { 32767, 32349, 18820, 23749 }, + { 19021, 634, 0, 0 }, + 10, 32, 1008, 0, 1200, 10090, 0, 0, 0 + }, + { /* articulation 141 */ + { 2536, 0, 32767, 27897 }, + { 1902, 380, 0, 0 }, + 7, 34, 988, 0, 1620, 8933, 0, 0, 0 + }, + { /* articulation 142 */ + { 32767, 32349, 10809, 23749 }, + { 32767, 380, 0, 0 }, + 7, 34, 988, 0, 2200, 8994, 0, 0, 0 + }, + { /* articulation 143 */ + { 32767, 32663, 15076, 23749 }, + { 32767, 1902, 0, 0 }, + 10, 34, 982, 0, 2500, 9525, 0, 0, 0 + }, + { /* articulation 144 */ + { 32767, 32663, 15076, 23749 }, + { 32767, 190, 0, 0 }, + 10, 34, 951, 0, 1500, 11423, 0, 0, 0 + }, + { /* articulation 145 */ + { 32767, 32663, 18820, 23749 }, + { 32767, 1902, 0, 0 }, + 9, 34, 982, 0, 1500, 9521, 0, 0, 0 + }, + { /* articulation 146 */ + { 3804, 0, 32767, 28809 }, + { 32767, 32767, 32767, 0 }, + 0, 0, 1521, 0, 0, 9521, 0, 0, 0 + }, + { /* articulation 147 */ + { 32767, 32558, 0, 23749 }, + { 32767, 19021, 0, 0 }, + 0, 17, 989, 0, 5000, 10223, 0, 0, 0 + }, + { /* articulation 148 */ + { 32767, 32663, 18820, 23749 }, + { 32767, 63, 0, 0 }, + 10, 34, 951, 0, 1500, 9907, 0, 0, 0 + }, + { /* articulation 149 */ + { 32767, 32698, 11682, 23749 }, + { 32767, 1902, 0, 0 }, + 0, 34, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 150 */ + { 32767, 32072, 0, 32072 }, + { 32767, 380, 0, 0 }, + 0, 17, 989, 0, 3440, 9260, 0, 0, 0 + }, + { /* articulation 151 */ + { 32767, 30234, 0, 30725 }, + { 32767, 1902, 0, 0 }, + 0, 17, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 152 */ + { 32767, 31730, 0, 30725 }, + { 32767, 380, 0, 0 }, + 0, 17, 989, 0, 4000, 7823, 0, 0, 0 + }, + { /* articulation 153 */ + { 32767, 32558, 3566, 23749 }, + { 783, 32767, 32767, 0 }, + 100, 0, 1522, 500, 0, 11877, 0, 0, 0 + }, + { /* articulation 154 */ + { 32767, 32663, 18820, 17213 }, + { 32767, 1902, 0, 0 }, + 8, 34, 989, -22, 0, 0, 0, 0, 0 + }, + { /* articulation 155 */ + { 19021, 29007, 6784, 23749 }, + { 32767, 1902, 0, 0 }, + 0, 34, 951, 0, 5000, 9521, 1, 0, 0 + }, + { /* articulation 156 */ + { 32767, 32558, 0, 31935 }, + { 1902, 254, 16384, 0 }, + 0, 52, 989, 0, 3627, 10547, 0, 5, 0 + }, + { /* articulation 157 */ + { 3804, 0, 32767, 23749 }, + { 1902, 1902, 0, 0 }, + 0, 34, 989, 27, 0, 11919, 0, 0, 0 + }, + { /* articulation 158 */ + { 32767, 0, 32767, 31730 }, + { 76, 66, 10092, 0 }, + 5, 0, 989, 0, 8007, 5535, 0, 8, 0 + }, + { /* articulation 159 */ + { 32767, 32468, 0, 29434 }, + { 32767, 127, 0, 0 }, + 0, 52, 989, 0, 2500, 9032, 0, 0, 0 + }, + { /* articulation 160 */ + { 9511, 32663, 10809, 25329 }, + { 32767, 32767, 32767, 0 }, + 0, 34, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 161 */ + { 19021, 32558, 18820, 23749 }, + { 32767, 190, 0, 0 }, + 10, 34, 988, 0, 2600, 9513, 0, 0, 0 + }, + { /* articulation 162 */ + { 32767, 32106, 9568, 23749 }, + { 2348, 391, 0, 0 }, + 10, 52, 980, 0, 6500, 9023, 0, 0, 0 + }, + { /* articulation 163 */ + { 32767, 32558, 0, 26439 }, + { 32767, 63, 0, 0 }, + 0, 34, 989, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 164 */ + { 32767, 32072, 15076, 17213 }, + { 32767, 1268, 0, 0 }, + 0, 0, 951, 0, 2000, 10223, 0, 0, 0 + }, + { /* articulation 165 */ + { 32767, 32558, 0, 23749 }, + { 32767, 380, 0, 0 }, + 0, 34, 989, 0, 3000, 9366, 0, 0, 0 + }, + { /* articulation 166 */ + { 32767, 32663, 18820, 23749 }, + { 1902, 127, 10879, 0 }, + 0, 0, 989, 0, 6000, 7121, 0, 4, 0 + }, + { /* articulation 167 */ + { 32767, 32505, 0, 26439 }, + { 32767, 21, 0, 0 }, + 0, 52, 989, 0, 3500, 6236, 0, 5, 0 + }, + { /* articulation 168 */ + { 32767, 32505, 0, 26439 }, + { 32767, 190, 0, 0 }, + 0, 52, 989, 0, 2800, 7121, 0, 0, 0 + }, + { /* articulation 169 */ + { 32767, 32418, 0, 29434 }, + { 32767, 127, 0, 0 }, + 0, 52, 989, 0, 2100, 9626, 0, 0, 0 + }, + { /* articulation 170 */ + { 32767, 32349, 0, 30234 }, + { 32767, 127, 0, 0 }, + 0, 52, 989, 0, 3000, 9626, 0, 0, 0 + }, + { /* articulation 171 */ + { 32767, 32288, 0, 28400 }, + { 32767, 127, 0, 0 }, + 0, 52, 989, 0, 1000, 9032, 0, 0, 0 + }, + { /* articulation 172 */ + { 32767, 32072, 0, 28809 }, + { 32767, 127, 0, 0 }, + 0, 52, 989, 0, 1000, 9032, 0, 0, 0 + }, + { /* articulation 173 */ + { 3804, 32072, 15076, 17213 }, + { 32767, 1268, 0, 0 }, + 0, 52, 991, 0, 0, 11107, 0, 8, 0 + }, + { /* articulation 174 */ + { 32767, 32349, 15076, 23749 }, + { 7608, 147, 0, 0 }, + 0, 0, 989, 0, 4500, 9521, 0, 8, 0 + }, + { /* articulation 175 */ + { 32767, 32663, 18820, 23749 }, + { 32767, 95, 0, 0 }, + 0, 0, 989, 0, 2000, 8321, 0, 8, 0 + }, + { /* articulation 176 */ + { 32767, 32715, 128, 29669 }, + { 32767, 1729, 0, 0 }, + 0, 0, 989, 0, 6000, 7823, 0, 8, 0 + }, + { /* articulation 177 */ + { 19021, 32448, 0, 31882 }, + { 32767, 95, 0, 0 }, + 0, 0, 989, 0, 4500, 7121, 0, 8, 0 + }, + { /* articulation 178 */ + { 32767, 32560, 3646, 32107 }, + { 32767, 190, 0, 0 }, + 0, 0, 989, 0, 4000, 8321, 0, 8, 0 + }, + { /* articulation 179 */ + { 32767, 32602, 13644, 26439 }, + { 32767, 63, 0, 0 }, + 12, 34, 988, 0, 2000, 11107, 0, 0, 0 + }, + { /* articulation 180 */ + { 19021, 30484, 0, 23749 }, + { 32767, 1902, 0, 0 }, + 0, 0, 989, 0, 5000, 8321, 1, 0, 0 + }, + { /* articulation 181 */ + { 261, 32466, 0, 31938 }, + { 32767, 634, 0, 0 }, + 0, 34, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 182 */ + { 32767, 32418, 0, 31742 }, + { 2348, 39, 0, 0 }, + 0, 34, 989, 0, 3600, 7121, 0, 4, 0 + }, + { /* articulation 183 */ + { 32767, 32090, 0, 32090 }, + { 32767, 634, 0, 0 }, + 0, 34, 951, 0, 0, 0, 0, 0, 0 + }, + { /* articulation 184 */ + { 1669, 32715, 19242, 30194 }, + { 32767, 296, 0, 0 }, + 0, 0, 1555, 0, 3000, 9907, 0, 4, 0 + } +}; /*end Articulations */ + +/*---------------------------------------------------------------------------- + * Regions + *---------------------------------------------------------------------------- +*/ +const S_WT_REGION eas_regions[] = +{ + { { 0, 27, 27 }, -2868, 16422, 0, 0, 81, 0 }, /* region 0 */ + { { 0, 28, 28 }, -3568, 32767, 0, 0, 40, 0 }, /* region 1 */ + { { 0, 29, 29 }, -4553, 32767, 0, 0, 32, 1 }, /* region 2 */ + { { 0, 30, 30 }, -4853, 32767, 0, 0, 32, 2 }, /* region 3 */ + { { 0, 31, 31 }, -3868, 23197, 0, 0, 48, 3 }, /* region 4 */ + { { 1536, 32, 32 }, -3200, 20675, 0, 0, 137, 4 }, /* region 5 */ + { { 1537, 33, 33 }, -3703, 20675, 792, 879, 50, 5 }, /* region 6 */ + { { 1537, 34, 34 }, -3803, 16422, 792, 879, 50, 6 }, /* region 7 */ + { { 0, 35, 35 }, -4968, 32767, 0, 0, 83, 7 }, /* region 8 */ + { { 0, 36, 36 }, -4968, 32767, 0, 0, 83, 7 }, /* region 9 */ + { { 0, 37, 37 }, -4051, 18426, 0, 0, 53, 8 }, /* region 10 */ + { { 0, 38, 38 }, -4151, 23197, 0, 0, 16, 9 }, /* region 11 */ + { { 0, 39, 39 }, -3568, 32767, 0, 0, 40, 10 }, /* region 12 */ + { { 0, 40, 40 }, -4151, 23197, 0, 0, 16, 4 }, /* region 13 */ + { { 1, 41, 41 }, -5855, 26028, 798, 993, 45, 11 }, /* region 14 */ + { { 257, 42, 42 }, -4200, 26028, 4288, 7488, 7, 12 }, /* region 15 */ + { { 1, 43, 43 }, -5755, 26028, 798, 993, 45, 13 }, /* region 16 */ + { { 257, 44, 44 }, -4400, 26028, 4288, 7488, 7, 14 }, /* region 17 */ + { { 1, 45, 45 }, -5755, 26028, 798, 993, 45, 15 }, /* region 18 */ + { { 257, 46, 46 }, -4600, 26028, 4288, 7488, 7, 16 }, /* region 19 */ + { { 1, 47, 47 }, -5455, 26028, 798, 993, 45, 17 }, /* region 20 */ + { { 1, 48, 48 }, -5355, 26028, 798, 993, 45, 18 }, /* region 21 */ + { { 1, 49, 49 }, -5200, 16422, 1294, 5778, 8, 19 }, /* region 22 */ + { { 1, 50, 50 }, -5255, 26028, 798, 993, 45, 20 }, /* region 23 */ + { { 1, 51, 51 }, -5268, 16422, 6592, 9921, 6, 21 }, /* region 24 */ + { { 1, 52, 52 }, -5600, 32767, 1294, 5778, 8, 22 }, /* region 25 */ + { { 1, 53, 53 }, -5418, 14636, 6592, 9921, 6, 23 }, /* region 26 */ + { { 0, 54, 54 }, -5751, 26028, 0, 0, 39, 24 }, /* region 27 */ + { { 1, 55, 55 }, -5300, 32767, 1294, 5778, 8, 25 }, /* region 28 */ + { { 0, 56, 56 }, -7255, 32767, 0, 0, 90, 26 }, /* region 29 */ + { { 1, 57, 57 }, -5700, 32767, 1294, 5778, 8, 27 }, /* region 30 */ + { { 1, 58, 58 }, -7053, 23197, 0, 166, 113, 28 }, /* region 31 */ + { { 1, 59, 59 }, -5968, 16422, 6592, 9921, 6, 29 }, /* region 32 */ + { { 1, 60, 60 }, -6453, 23197, 432, 582, 63, 30 }, /* region 33 */ + { { 1, 61, 61 }, -6853, 16422, 432, 582, 63, 30 }, /* region 34 */ + { { 1, 62, 62 }, -7253, 20675, 432, 582, 63, 31 }, /* region 35 */ + { { 1, 63, 63 }, -7353, 23197, 432, 582, 63, 32 }, /* region 36 */ + { { 1, 64, 64 }, -7953, 23197, 432, 582, 63, 33 }, /* region 37 */ + { { 0, 65, 65 }, -7555, 32767, 0, 0, 14, 34 }, /* region 38 */ + { { 0, 66, 66 }, -7955, 20675, 0, 0, 14, 34 }, /* region 39 */ + { { 512, 67, 67 }, -7155, 18426, 0, 0, 90, 35 }, /* region 40 */ + { { 512, 68, 68 }, -7755, 18426, 0, 0, 90, 35 }, /* region 41 */ + { { 0, 69, 69 }, -7755, 32767, 0, 0, 86, 36 }, /* region 42 */ + { { 0, 70, 70 }, -6855, 21900, 0, 0, 86, 37 }, /* region 43 */ + { { 769, 71, 71 }, -6355, 23197, 0, 1226, 35, 38 }, /* region 44 */ + { { 769, 72, 72 }, -6955, 26028, 0, 1226, 35, 38 }, /* region 45 */ + { { 1024, 73, 73 }, -7955, 32767, 0, 0, 22, 39 }, /* region 46 */ + { { 1024, 74, 74 }, -8455, 32767, 0, 0, 22, 40 }, /* region 47 */ + { { 1, 75, 75 }, -7900, 23197, 0, 31, 139, 41 }, /* region 48 */ + { { 0, 76, 76 }, -10455, 23197, 0, 0, 134, 42 }, /* region 49 */ + { { 0, 77, 77 }, -10055, 23197, 0, 0, 134, 43 }, /* region 50 */ + { { 0, 78, 78 }, -8853, 16422, 0, 0, 89, 44 }, /* region 51 */ + { { 0, 79, 79 }, -10253, 16422, 0, 0, 89, 45 }, /* region 52 */ + { { 1281, 80, 80 }, -6300, 13045, 209, 230, 103, 46 }, /* region 53 */ + { { 1281, 81, 81 }, -6400, 16422, 209, 230, 103, 47 }, /* region 54 */ + { { 0, 82, 82 }, -8455, 20675, 0, 0, 87, 48 }, /* region 55 */ + { { 0, 83, 83 }, -8900, 32767, 0, 0, 13, 49 }, /* region 56 */ + { { 1, 84, 84 }, -8400, 23197, 0, 10294, 5, 50 }, /* region 57 */ + { { 0, 85, 85 }, -9655, 32767, 0, 0, 135, 4 }, /* region 58 */ + { { 0, 86, 86 }, -9068, 16422, 0, 0, 24, 51 }, /* region 59 */ + { { 32769, 87, 87 }, -9168, 32767, 1335, 1603, 24, 52 }, /* region 60 */ + { { 1, 12, 67 }, -6605, 23197, 437, 16584, 2, 48 }, /* region 61 */ + { { 1, 68, 73 }, -7196, 23197, 452, 16803, 0, 48 }, /* region 62 */ + { { 32769, 74, 108 }, -8467, 23197, 404, 16698, 1, 48 }, /* region 63 */ + { { 1, 12, 78 }, -6605, 16422, 437, 16584, 2, 48 }, /* region 64 */ + { { 1, 79, 91 }, -7196, 16422, 452, 16803, 0, 48 }, /* region 65 */ + { { 32769, 92, 108 }, -8467, 16422, 404, 16698, 1, 48 }, /* region 66 */ + { { 1, 12, 78 }, -6605, 16422, 437, 16584, 2, 48 }, /* region 67 */ + { { 1, 79, 91 }, -7196, 16422, 452, 16803, 0, 48 }, /* region 68 */ + { { 32769, 92, 108 }, -8467, 16422, 404, 16698, 1, 48 }, /* region 69 */ + { { 1, 12, 70 }, -6600, 23197, 437, 16584, 2, 48 }, /* region 70 */ + { { 1, 71, 88 }, -7191, 23197, 452, 16803, 0, 48 }, /* region 71 */ + { { 32769, 89, 108 }, -8462, 23197, 404, 16698, 1, 48 }, /* region 72 */ + { { 1, 12, 54 }, -5956, 13045, 639, 4368, 10, 48 }, /* region 73 */ + { { 32769, 55, 108 }, -6351, 18426, 702, 3112, 12, 48 }, /* region 74 */ + { { 1, 12, 66 }, -6611, 23197, 437, 16584, 2, 48 }, /* region 75 */ + { { 1, 67, 87 }, -7202, 23197, 452, 16803, 0, 48 }, /* region 76 */ + { { 32769, 88, 108 }, -8473, 16422, 404, 16698, 1, 48 }, /* region 77 */ + { { 1, 12, 43 }, -3055, 23197, 920, 1383, 30, 59 }, /* region 78 */ + { { 32769, 44, 96 }, -5060, 18426, 885, 1176, 37, 59 }, /* region 79 */ + { { 1, 12, 48 }, -3461, 18426, 1148, 1514, 26, 60 }, /* region 80 */ + { { 32769, 49, 96 }, -6253, 16422, 1347, 1420, 29, 60 }, /* region 81 */ + { { 1, 33, 56 }, -5600, 26028, 1064, 1170, 38, 61 }, /* region 82 */ + { { 1, 57, 72 }, -6000, 26028, 930, 1014, 44, 61 }, /* region 83 */ + { { 32769, 73, 108 }, -7600, 26028, 726, 826, 52, 61 }, /* region 84 */ + { { 1, 36, 96 }, -7600, 20675, 635, 735, 58, 62 }, /* region 85 */ + { { 32769, 97, 108 }, -10108, 13045, 0, 31, 139, 62 }, /* region 86 */ + { { 1, 36, 96 }, -7600, 14636, 635, 735, 58, 0 }, /* region 87 */ + { { 32769, 97, 108 }, -10108, 13045, 0, 31, 139, 0 }, /* region 88 */ + { { 1, 36, 83 }, -6006, 13045, 838, 922, 47, 63 }, /* region 89 */ + { { 1, 84, 93 }, -8406, 14636, 209, 230, 103, 63 }, /* region 90 */ + { { 32769, 94, 108 }, -10108, 13045, 0, 31, 139, 63 }, /* region 91 */ + { { 1, 36, 83 }, -6006, 13045, 838, 922, 47, 64 }, /* region 92 */ + { { 1, 84, 93 }, -8406, 13045, 209, 230, 103, 64 }, /* region 93 */ + { { 32769, 94, 108 }, -10108, 13045, 0, 31, 139, 64 }, /* region 94 */ + { { 1, 21, 56 }, -5595, 23197, 1064, 1170, 38, 65 }, /* region 95 */ + { { 1, 57, 72 }, -5995, 23197, 930, 1014, 44, 65 }, /* region 96 */ + { { 32769, 73, 108 }, -7598, 23197, 726, 826, 52, 65 }, /* region 97 */ + { { 1, 12, 83 }, -6006, 16422, 838, 922, 47, 66 }, /* region 98 */ + { { 1, 84, 93 }, -8406, 16422, 209, 230, 103, 66 }, /* region 99 */ + { { 32769, 94, 108 }, -10108, 16422, 0, 31, 139, 66 }, /* region 100 */ + { { 1, 24, 83 }, -6006, 16422, 838, 922, 47, 67 }, /* region 101 */ + { { 1, 84, 93 }, -8406, 16422, 209, 230, 103, 67 }, /* region 102 */ + { { 32769, 94, 108 }, -10108, 16422, 0, 31, 139, 67 }, /* region 103 */ + { { 1, 12, 83 }, -6020, 16422, 0, 83, 126, 68 }, /* region 104 */ + { { 1, 84, 90 }, -8482, 16422, 0, 20, 145, 68 }, /* region 105 */ + { { 32769, 91, 108 }, -9101, 16422, 6, 20, 147, 68 }, /* region 106 */ + { { 1, 21, 75 }, -7241, 16422, 419, 460, 76, 69 }, /* region 107 */ + { { 32769, 76, 108 }, -9690, 14636, 254, 264, 101, 69 }, /* region 108 */ + { { 32769, 36, 84 }, -7755, 16422, 0, 2775, 17, 70 }, /* region 109 */ + { { 32769, 12, 108 }, -6655, 23197, 30, 276, 100, 71 }, /* region 110 */ + { { 0, 12, 60 }, -7914, 26028, 0, 0, 15, 72 }, /* region 111 */ + { { 32768, 61, 96 }, -7914, 26028, 0, 0, 15, 73 }, /* region 112 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 74 }, /* region 113 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 74 }, /* region 114 */ + { { 1, 12, 35 }, -5355, 16422, 2869, 3778, 11, 75 }, /* region 115 */ + { { 1, 36, 48 }, -6555, 20675, 2869, 3778, 11, 75 }, /* region 116 */ + { { 32769, 49, 72 }, -6555, 20675, 2869, 3778, 11, 76 }, /* region 117 */ + { { 1, 16, 55 }, -6224, 20675, 1045, 1119, 41, 77 }, /* region 118 */ + { { 32769, 56, 96 }, -6718, 20675, 907, 963, 46, 77 }, /* region 119 */ + { { 1, 16, 53 }, -5994, 29204, 1140, 1479, 27, 78 }, /* region 120 */ + { { 1, 54, 70 }, -7171, 29204, 726, 812, 55, 78 }, /* region 121 */ + { { 32769, 71, 108 }, -7788, 29204, 718, 748, 56, 78 }, /* region 122 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 79 }, /* region 123 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 79 }, /* region 124 */ + { { 1, 16, 54 }, -5727, 20675, 5362, 5461, 9, 80 }, /* region 125 */ + { { 1, 55, 63 }, -5851, 26028, 1362, 1454, 28, 80 }, /* region 126 */ + { { 32769, 64, 108 }, -6744, 16422, 311, 366, 88, 80 }, /* region 127 */ + { { 1, 16, 48 }, -4798, 20675, 1132, 1301, 31, 81 }, /* region 128 */ + { { 32769, 49, 108 }, -5988, 20675, 1099, 1184, 36, 81 }, /* region 129 */ + { { 1, 21, 68 }, -8458, 20675, 87, 2170, 18, 82 }, /* region 130 */ + { { 1, 69, 82 }, -8960, 20675, 120, 2167, 19, 82 }, /* region 131 */ + { { 32769, 83, 108 }, -10160, 20675, 376, 2041, 20, 82 }, /* region 132 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 83 }, /* region 133 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 83 }, /* region 134 */ + { { 32769, 55, 108 }, -7368, 20675, 0, 477, 75, 84 }, /* region 135 */ + { { 32769, 36, 96 }, -6900, 14636, 101, 151, 116, 85 }, /* region 136 */ + { { 1, 24, 83 }, -6020, 13045, 0, 83, 126, 86 }, /* region 137 */ + { { 1, 84, 90 }, -8482, 13045, 0, 20, 145, 86 }, /* region 138 */ + { { 32769, 91, 108 }, -9101, 13045, 6, 20, 147, 86 }, /* region 139 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 87 }, /* region 140 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 87 }, /* region 141 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 88 }, /* region 142 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 88 }, /* region 143 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 89 }, /* region 144 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 89 }, /* region 145 */ + { { 1, 24, 83 }, -6020, 13045, 0, 83, 126, 90 }, /* region 146 */ + { { 1, 84, 90 }, -8482, 13045, 0, 20, 145, 90 }, /* region 147 */ + { { 32769, 91, 108 }, -9101, 13045, 6, 20, 147, 90 }, /* region 148 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 91 }, /* region 149 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 91 }, /* region 150 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 92 }, /* region 151 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 92 }, /* region 152 */ + { { 1, 12, 62 }, -7053, 16422, 23, 10953, 4, 93 }, /* region 153 */ + { { 32769, 63, 108 }, -7755, 20675, 11, 11753, 3, 93 }, /* region 154 */ + { { 1, 12, 62 }, -7053, 16422, 23, 10953, 4, 94 }, /* region 155 */ + { { 32769, 63, 108 }, -7755, 16422, 11, 11753, 3, 94 }, /* region 156 */ + { { 1, 24, 79 }, -6020, 13045, 0, 83, 126, 95 }, /* region 157 */ + { { 1, 80, 90 }, -8482, 13045, 0, 20, 145, 95 }, /* region 158 */ + { { 32769, 91, 108 }, -9101, 13045, 6, 20, 147, 95 }, /* region 159 */ + { { 1, 12, 65 }, -7053, 13045, 23, 10953, 4, 96 }, /* region 160 */ + { { 32769, 66, 108 }, -7755, 16422, 11, 11753, 3, 96 }, /* region 161 */ + { { 32768, 36, 84 }, -7500, 20675, 0, 0, 25, 97 }, /* region 162 */ + { { 32769, 36, 96 }, -8855, 20675, 1482, 1613, 23, 98 }, /* region 163 */ + { { 32769, 12, 96 }, -4366, 32767, 818, 1033, 42, 99 }, /* region 164 */ + { { 32769, 36, 84 }, -8568, 18426, 0, 293, 98, 100 }, /* region 165 */ + { { 32769, 12, 96 }, -6020, 26028, 0, 83, 125, 101 }, /* region 166 */ + { { 32769, 12, 96 }, -6020, 20675, 0, 83, 125, 102 }, /* region 167 */ + { { 1, 12, 83 }, -6020, 13045, 0, 83, 125, 104 }, /* region 168 */ + { { 1, 84, 90 }, -8482, 13045, 0, 20, 146, 104 }, /* region 169 */ + { { 32769, 91, 108 }, -9101, 13045, 6, 20, 148, 104 }, /* region 170 */ + { { 32769, 36, 108 }, -8570, 32767, 472, 491, 74, 105 }, /* region 171 */ + { { 32769, 36, 108 }, -8570, 20675, 472, 491, 74, 106 }, /* region 172 */ + { { 1, 12, 72 }, -6012, 7336, 2, 86, 124, 107 }, /* region 173 */ + { { 1, 73, 101 }, -8500, 8231, 2, 22, 143, 107 }, /* region 174 */ + { { 32769, 102, 108 }, -9683, 20675, 173, 183, 110, 107 }, /* region 175 */ + { { 1, 21, 96 }, -7768, 13045, 477, 507, 73, 108 }, /* region 176 */ + { { 32769, 97, 108 }, -9683, 13045, 173, 183, 110, 109 }, /* region 177 */ + { { 32769, 12, 108 }, -7771, 16422, 477, 507, 73, 110 }, /* region 178 */ + { { 1, 12, 53 }, -4971, 16422, 388, 541, 68, 111 }, /* region 179 */ + { { 32769, 54, 60 }, -5949, 11626, 473, 560, 65, 111 }, /* region 180 */ + { { 32769, 36, 72 }, -5949, 16422, 473, 560, 65, 112 }, /* region 181 */ + { { 1, 48, 58 }, -7053, 16422, 356, 402, 82, 113 }, /* region 182 */ + { { 1, 59, 65 }, -7574, 16422, 514, 548, 67, 113 }, /* region 183 */ + { { 1, 66, 78 }, -8174, 16422, 505, 529, 71, 113 }, /* region 184 */ + { { 32769, 79, 96 }, -9233, 16422, 178, 191, 109, 113 }, /* region 185 */ + { { 1, 55, 60 }, -7053, 16422, 356, 402, 82, 114 }, /* region 186 */ + { { 1, 61, 69 }, -7574, 16422, 514, 548, 67, 114 }, /* region 187 */ + { { 1, 70, 79 }, -8174, 16422, 505, 529, 71, 114 }, /* region 188 */ + { { 32769, 80, 108 }, -9233, 16422, 178, 191, 109, 114 }, /* region 189 */ + { { 1, 16, 82 }, -8029, 23197, 180, 206, 106, 115 }, /* region 190 */ + { { 32769, 83, 108 }, -7240, 18426, 3, 44, 131, 115 }, /* region 191 */ + { { 32769, 21, 108 }, -8869, 20675, 483, 515, 72, 116 }, /* region 192 */ + { { 1, 21, 89 }, -7205, 18426, 3, 45, 130, 117 }, /* region 193 */ + { { 32769, 90, 108 }, -9101, 10362, 6, 20, 148, 117 }, /* region 194 */ + { { 1, 21, 42 }, -4686, 20675, 0, 180, 111, 118 }, /* region 195 */ + { { 1, 43, 51 }, -5286, 23197, 0, 127, 120, 118 }, /* region 196 */ + { { 1, 52, 58 }, -6292, 26028, 0, 71, 127, 118 }, /* region 197 */ + { { 1, 59, 68 }, -7468, 23197, 0, 36, 136, 118 }, /* region 198 */ + { { 32769, 69, 108 }, -8574, 20675, 0, 19, 149, 118 }, /* region 199 */ + { { 1, 21, 89 }, -7199, 20675, 3, 45, 130, 119 }, /* region 200 */ + { { 32769, 90, 108 }, -9101, 14636, 6, 20, 148, 119 }, /* region 201 */ + { { 1, 21, 46 }, -5651, 26028, 236, 340, 92, 120 }, /* region 202 */ + { { 1, 47, 71 }, -6563, 20675, 824, 885, 49, 120 }, /* region 203 */ + { { 1, 72, 88 }, -7907, 18426, 719, 747, 57, 120 }, /* region 204 */ + { { 1, 89, 93 }, -8876, 16422, 83, 99, 122, 120 }, /* region 205 */ + { { 32769, 94, 108 }, -9689, 16422, 173, 183, 110, 120 }, /* region 206 */ + { { 1, 60, 71 }, -7205, 16422, 0, 42, 132, 121 }, /* region 207 */ + { { 1, 72, 78 }, -7903, 16422, 0, 28, 141, 121 }, /* region 208 */ + { { 32769, 79, 96 }, -8405, 16422, 0, 21, 144, 121 }, /* region 209 */ + { { 1, 48, 65 }, -6316, 11626, 0, 70, 128, 122 }, /* region 210 */ + { { 1, 66, 79 }, -7724, 14636, 0, 31, 138, 122 }, /* region 211 */ + { { 32769, 80, 96 }, -8030, 11626, 0, 26, 142, 122 }, /* region 212 */ + { { 1, 16, 44 }, -5868, 14636, 163, 254, 102, 123 }, /* region 213 */ + { { 1, 45, 51 }, -6418, 16422, 261, 393, 85, 123 }, /* region 214 */ + { { 1, 52, 58 }, -7333, 18426, 190, 229, 104, 123 }, /* region 215 */ + { { 1, 59, 66 }, -8100, 18426, 168, 193, 108, 123 }, /* region 216 */ + { { 1, 67, 70 }, -8576, 18426, 138, 157, 115, 123 }, /* region 217 */ + { { 1, 71, 80 }, -9103, 18426, 166, 180, 112, 123 }, /* region 218 */ + { { 32769, 81, 108 }, -10074, 18426, 135, 151, 117, 123 }, /* region 219 */ + { { 32769, 12, 96 }, -5004, 23197, 570, 719, 59, 124 }, /* region 220 */ + { { 1, 12, 48 }, -5868, 14636, 163, 254, 102, 125 }, /* region 221 */ + { { 1, 49, 54 }, -6418, 16422, 261, 393, 85, 125 }, /* region 222 */ + { { 1, 55, 63 }, -7333, 18426, 190, 229, 104, 125 }, /* region 223 */ + { { 1, 64, 70 }, -8100, 18426, 168, 193, 108, 125 }, /* region 224 */ + { { 1, 71, 75 }, -8576, 18426, 138, 157, 115, 125 }, /* region 225 */ + { { 1, 76, 82 }, -9103, 18426, 166, 180, 112, 125 }, /* region 226 */ + { { 32769, 83, 108 }, -10074, 18426, 135, 151, 117, 125 }, /* region 227 */ + { { 32770, 36, 84 }, -7200, 29204, 0, 0, 0, 126 }, /* region 228 */ + { { 32770, 36, 84 }, -7600, 8231, 0, 0, 0, 127 }, /* region 229 */ + { { 32770, 36, 84 }, -7200, 20675, 0, 0, 0, 128 }, /* region 230 */ + { { 32769, 36, 84 }, -6000, -24285, 1294, 5778, 8, 129 }, /* region 231 */ + { { 32769, 36, 84 }, -6555, 29204, 798, 993, 45, 130 }, /* region 232 */ + { { 32769, 36, 84 }, -6855, 20675, 798, 993, 45, 131 }, /* region 233 */ + { { 32769, 36, 84 }, -7755, 29204, 798, 993, 45, 132 }, /* region 234 */ + { { 32768, 36, 84 }, -8155, 32767, 0, 0, 133, 133 }, /* region 235 */ + { { 32768, 36, 84 }, -6555, 20675, 0, 0, 91, 134 }, /* region 236 */ + { { 1, 24, 62 }, -7000, 23197, 286, 333, 94, 135 }, /* region 237 */ + { { 1, 63, 66 }, -7364, 26028, 297, 335, 93, 135 }, /* region 238 */ + { { 1, 67, 72 }, -7722, 23197, 368, 399, 84, 135 }, /* region 239 */ + { { 32769, 73, 96 }, -8310, 23197, 116, 138, 119, 135 }, /* region 240 */ + { { 1, 24, 48 }, -5141, 23197, 309, 447, 77, 136 }, /* region 241 */ + { { 1, 49, 56 }, -6266, 26028, 211, 283, 99, 136 }, /* region 242 */ + { { 1, 57, 63 }, -7000, 26028, 286, 333, 94, 136 }, /* region 243 */ + { { 32769, 64, 84 }, -7722, 23197, 368, 399, 84, 136 }, /* region 244 */ + { { 1, 24, 56 }, -6266, 29204, 211, 283, 99, 137 }, /* region 245 */ + { { 1, 57, 63 }, -7000, 29204, 286, 333, 94, 137 }, /* region 246 */ + { { 1, 64, 69 }, -7722, 29204, 368, 399, 84, 137 }, /* region 247 */ + { { 32769, 70, 96 }, -8310, 29204, 116, 138, 119, 137 }, /* region 248 */ + { { 1, 24, 68 }, -7722, 18426, 368, 399, 84, 138 }, /* region 249 */ + { { 1, 69, 76 }, -8310, 26028, 116, 138, 119, 138 }, /* region 250 */ + { { 32769, 77, 108 }, -8758, 23197, 127, 144, 118, 138 }, /* region 251 */ + { { 1, 24, 82 }, -7613, 23197, 389, 422, 80, 139 }, /* region 252 */ + { { 32769, 83, 108 }, -8764, 26028, 146, 163, 114, 139 }, /* region 253 */ + { { 1, 12, 58 }, -6898, 29204, 386, 436, 78, 140 }, /* region 254 */ + { { 32769, 59, 96 }, -7371, 26028, 290, 328, 95, 140 }, /* region 255 */ + { { 1, 12, 58 }, -6898, 16422, 386, 436, 78, 141 }, /* region 256 */ + { { 32769, 59, 96 }, -7371, 18426, 290, 328, 95, 141 }, /* region 257 */ + { { 1, 12, 48 }, -6898, -28771, 386, 436, 78, 142 }, /* region 258 */ + { { 32769, 49, 84 }, -7371, 29204, 290, 328, 95, 142 }, /* region 259 */ + { { 1, 12, 60 }, -5453, 20675, 314, 430, 79, 143 }, /* region 260 */ + { { 32769, 61, 84 }, -6553, 18426, 263, 324, 96, 143 }, /* region 261 */ + { { 1, 24, 60 }, -6553, 16422, 263, 324, 96, 144 }, /* region 262 */ + { { 1, 61, 70 }, -7669, 20675, 279, 311, 97, 144 }, /* region 263 */ + { { 32769, 71, 96 }, -8098, 23197, 179, 204, 107, 144 }, /* region 264 */ + { { 1, 24, 84 }, -8483, 20675, 191, 211, 105, 145 }, /* region 265 */ + { { 32769, 85, 108 }, -9683, 20675, 92, 102, 121, 145 }, /* region 266 */ + { { 1, 21, 69 }, -6553, 13045, 263, 324, 96, 146 }, /* region 267 */ + { { 1, 70, 94 }, -7669, 20675, 279, 311, 97, 146 }, /* region 268 */ + { { 1, 95, 96 }, -8098, -24285, 179, 204, 107, 146 }, /* region 269 */ + { { 32769, 97, 108 }, -9683, -24285, 173, 183, 110, 146 }, /* region 270 */ + { { 1, 16, 55 }, -8100, 20675, 168, 193, 108, 147 }, /* region 271 */ + { { 1, 56, 74 }, -8576, 26028, 138, 157, 115, 147 }, /* region 272 */ + { { 32769, 75, 96 }, -10074, 26028, 135, 151, 117, 147 }, /* region 273 */ + { { 1, 24, 72 }, -8098, 26028, 179, 204, 107, 148 }, /* region 274 */ + { { 1, 73, 85 }, -8483, 20675, 191, 211, 105, 148 }, /* region 275 */ + { { 32769, 86, 108 }, -9683, 18426, 92, 102, 121, 148 }, /* region 276 */ + { { 32769, 36, 108 }, -7730, 18426, 1839, 1901, 21, 149 }, /* region 277 */ + { { 32769, 24, 108 }, -7273, 20675, 494, 534, 69, 150 }, /* region 278 */ + { { 32769, 12, 108 }, -7273, 20675, 494, 534, 69, 151 }, /* region 279 */ + { { 32769, 24, 108 }, -7273, 20675, 494, 534, 69, 152 }, /* region 280 */ + { { 1, 36, 60 }, -4900, 5193, 2, 22, 143, 153 }, /* region 281 */ + { { 32769, 61, 84 }, -6083, 20675, 173, 183, 110, 153 }, /* region 282 */ + { { 32769, 24, 96 }, -6553, 14636, 263, 324, 96, 154 }, /* region 283 */ + { { 32769, 36, 96 }, -7730, 26028, 1839, 1901, 21, 155 }, /* region 284 */ + { { 32769, 24, 108 }, -7273, 20675, 494, 534, 69, 156 }, /* region 285 */ + { { 1, 24, 58 }, -7851, 14636, 0, 29, 140, 157 }, /* region 286 */ + { { 32769, 59, 96 }, -7851, 14636, 0, 29, 140, 157 }, /* region 287 */ + { { 1, 12, 83 }, -6020, 13045, 0, 83, 125, 158 }, /* region 288 */ + { { 1, 84, 90 }, -8482, 13045, 0, 20, 146, 158 }, /* region 289 */ + { { 32769, 91, 108 }, -9101, 13045, 6, 20, 148, 158 }, /* region 290 */ + { { 1, 21, 42 }, -4663, 26028, 1047, 1229, 34, 159 }, /* region 291 */ + { { 1, 43, 48 }, -5456, 29204, 1138, 1253, 33, 159 }, /* region 292 */ + { { 1, 49, 53 }, -5845, 26028, 559, 651, 60, 159 }, /* region 293 */ + { { 1, 54, 60 }, -6732, 26028, 508, 563, 64, 159 }, /* region 294 */ + { { 1, 61, 65 }, -7080, 32767, 819, 864, 51, 159 }, /* region 295 */ + { { 1, 66, 70 }, -6866, 26942, 981, 1032, 43, 159 }, /* region 296 */ + { { 1, 71, 76 }, -8166, 26028, 790, 814, 54, 159 }, /* region 297 */ + { { 1, 77, 82 }, -8766, 26028, 592, 609, 61, 159 }, /* region 298 */ + { { 1, 83, 87 }, -9517, 23197, 543, 554, 66, 159 }, /* region 299 */ + { { 1, 88, 96 }, -10071, 18426, 601, 609, 62, 159 }, /* region 300 */ + { { 32769, 97, 108 }, -10566, 18426, 523, 529, 70, 159 }, /* region 301 */ + { { 1, 48, 69 }, -6313, 14636, 0, 70, 128, 160 }, /* region 302 */ + { { 1, 70, 79 }, -7724, 18426, 0, 31, 138, 160 }, /* region 303 */ + { { 32769, 80, 96 }, -8030, 14636, 0, 26, 142, 160 }, /* region 304 */ + { { 1, 36, 72 }, -7134, 29204, 0, 87, 123, 161 }, /* region 305 */ + { { 32769, 73, 96 }, -7960, 29204, 0, 54, 129, 161 }, /* region 306 */ + { { 32769, 36, 96 }, -7730, 26028, 1839, 1901, 21, 162 }, /* region 307 */ + { { 32769, 12, 96 }, -4372, 32767, 818, 1033, 42, 163 }, /* region 308 */ + { { 32769, 36, 108 }, -8570, 26028, 472, 491, 74, 164 }, /* region 309 */ + { { 32769, 12, 96 }, -5004, 29204, 570, 719, 59, 165 }, /* region 310 */ + { { 1, 12, 83 }, -6020, 13045, 0, 83, 125, 166 }, /* region 311 */ + { { 1, 84, 90 }, -8482, 13045, 0, 20, 146, 166 }, /* region 312 */ + { { 32769, 91, 108 }, -9101, 13045, 6, 20, 148, 166 }, /* region 313 */ + { { 1, 21, 46 }, -5651, 32767, 236, 340, 92, 167 }, /* region 314 */ + { { 1, 47, 75 }, -6563, 26028, 824, 885, 49, 167 }, /* region 315 */ + { { 1, 76, 84 }, -7907, 23197, 719, 747, 57, 167 }, /* region 316 */ + { { 1, 85, 93 }, -8876, 20675, 83, 99, 122, 167 }, /* region 317 */ + { { 32769, 94, 108 }, -9689, 20675, 173, 183, 110, 167 }, /* region 318 */ + { { 1, 21, 46 }, -5651, 26028, 236, 340, 92, 168 }, /* region 319 */ + { { 1, 47, 71 }, -6563, 20675, 824, 885, 49, 168 }, /* region 320 */ + { { 1, 72, 88 }, -7907, 18426, 719, 747, 57, 168 }, /* region 321 */ + { { 1, 89, 93 }, -8876, 16422, 83, 99, 122, 168 }, /* region 322 */ + { { 32769, 94, 108 }, -9689, 16422, 173, 183, 110, 168 }, /* region 323 */ + { { 1, 21, 45 }, -4663, 26028, 1047, 1229, 34, 169 }, /* region 324 */ + { { 1, 46, 51 }, -5456, 29204, 1138, 1253, 33, 169 }, /* region 325 */ + { { 1, 52, 54 }, -5845, 26028, 559, 651, 60, 169 }, /* region 326 */ + { { 1, 55, 63 }, -6732, 26028, 508, 563, 64, 169 }, /* region 327 */ + { { 1, 64, 68 }, -7080, 32767, 819, 864, 51, 169 }, /* region 328 */ + { { 1, 69, 73 }, -6866, 26942, 981, 1032, 43, 169 }, /* region 329 */ + { { 1, 74, 79 }, -8166, 26028, 790, 814, 54, 169 }, /* region 330 */ + { { 1, 80, 88 }, -8766, 23197, 592, 609, 61, 169 }, /* region 331 */ + { { 1, 89, 99 }, -10071, 18426, 601, 609, 62, 169 }, /* region 332 */ + { { 32769, 100, 108 }, -10566, 18426, 523, 529, 70, 169 }, /* region 333 */ + { { 1, 21, 45 }, -4663, 26028, 1047, 1229, 34, 170 }, /* region 334 */ + { { 1, 46, 51 }, -5456, 29204, 1138, 1253, 33, 170 }, /* region 335 */ + { { 1, 52, 54 }, -5845, 26028, 559, 651, 60, 170 }, /* region 336 */ + { { 1, 55, 63 }, -6732, 26028, 508, 563, 64, 170 }, /* region 337 */ + { { 1, 64, 68 }, -7080, 32767, 819, 864, 51, 170 }, /* region 338 */ + { { 1, 69, 73 }, -6866, 26942, 981, 1032, 43, 170 }, /* region 339 */ + { { 1, 74, 79 }, -8166, 26028, 790, 814, 54, 170 }, /* region 340 */ + { { 1, 80, 88 }, -8766, 23197, 592, 609, 61, 170 }, /* region 341 */ + { { 1, 89, 99 }, -10071, 18426, 601, 609, 62, 171 }, /* region 342 */ + { { 32769, 100, 108 }, -10566, 18426, 523, 529, 70, 172 }, /* region 343 */ + { { 32769, 36, 108 }, -8570, 20675, 472, 491, 74, 173 }, /* region 344 */ + { { 32769, 12, 108 }, -7730, 20675, 1839, 1901, 21, 174 }, /* region 345 */ + { { 1, 12, 44 }, -5868, 18426, 163, 254, 102, 175 }, /* region 346 */ + { { 1, 45, 51 }, -6418, 20675, 261, 393, 85, 175 }, /* region 347 */ + { { 1, 52, 58 }, -7333, 23197, 190, 229, 104, 175 }, /* region 348 */ + { { 1, 59, 66 }, -8100, 23197, 168, 193, 108, 175 }, /* region 349 */ + { { 1, 67, 70 }, -8576, 23197, 138, 157, 115, 175 }, /* region 350 */ + { { 1, 71, 80 }, -9103, 23197, 166, 180, 112, 175 }, /* region 351 */ + { { 32769, 81, 108 }, -10074, 23197, 135, 151, 117, 175 }, /* region 352 */ + { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 176 }, /* region 353 */ + { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 176 }, /* region 354 */ + { { 1, 12, 48 }, -4798, 29204, 1132, 1301, 31, 177 }, /* region 355 */ + { { 32769, 49, 108 }, -5988, 29204, 1099, 1184, 36, 177 }, /* region 356 */ + { { 1, 12, 83 }, -7241, 20675, 419, 460, 76, 178 }, /* region 357 */ + { { 32769, 84, 108 }, -10123, 20675, 0, 31, 139, 178 }, /* region 358 */ + { { 1, 55, 60 }, -7053, 18426, 356, 402, 82, 179 }, /* region 359 */ + { { 1, 61, 69 }, -7574, 18426, 514, 548, 67, 179 }, /* region 360 */ + { { 1, 70, 79 }, -8174, 18426, 505, 529, 71, 179 }, /* region 361 */ + { { 32769, 80, 108 }, -9233, 23197, 178, 191, 109, 179 }, /* region 362 */ + { { 32769, 36, 96 }, -7730, -24285, 1839, 1901, 21, 180 }, /* region 363 */ + { { 1, 12, 83 }, -6006, 16422, 838, 922, 47, 181 }, /* region 364 */ + { { 1, 84, 93 }, -8406, 18426, 209, 230, 103, 181 }, /* region 365 */ + { { 32769, 94, 108 }, -10108, 16422, 0, 31, 139, 181 }, /* region 366 */ + { { 1, 12, 56 }, -5595, 23197, 1064, 1170, 38, 182 }, /* region 367 */ + { { 1, 57, 72 }, -5995, 23197, 930, 1014, 44, 182 }, /* region 368 */ + { { 32769, 73, 108 }, -7598, 23197, 726, 826, 52, 182 }, /* region 369 */ + { { 32769, 24, 108 }, -7600, 23197, 635, 735, 58, 62 }, /* region 370 */ + { { 1, 36, 83 }, -6006, 13045, 838, 922, 47, 183 }, /* region 371 */ + { { 1, 84, 93 }, -8406, 13045, 209, 230, 103, 183 }, /* region 372 */ + { { 32769, 94, 108 }, -10108, 13045, 0, 31, 139, 183 }, /* region 373 */ + { { 1, 12, 66 }, -6611, 23197, 437, 16584, 2, 184 }, /* region 374 */ + { { 1, 67, 87 }, -7202, 23197, 452, 16803, 0, 184 }, /* region 375 */ + { { 32769, 88, 108 }, -8473, 16422, 404, 16698, 1, 184 } /* region 376 */ +}; /* end Regions */ + +/*---------------------------------------------------------------------------- + * Programs + *---------------------------------------------------------------------------- +*/ +const S_PROGRAM eas_programs[] = +{ + { 7864320, 0 } /* program 0 */ +}; /* end Programs */ + +/*---------------------------------------------------------------------------- + * Banks + *---------------------------------------------------------------------------- +*/ +const S_BANK eas_banks[] = +{ + { /* bank 0 */ + 30976, + { + 291, 324, 314, 334, 202, 319, 95, 195, + 107, 92, 371, 89, 87, 85, 135, 82, + 200, 192, 130, 267, 193, 302, 207, 210, + 128, 125, 190, 120, 118, 213, 221, 271, + 80, 78, 308, 164, 220, 310, 166, 167, + 186, 182, 181, 179, 160, 178, 176, 115, + 155, 153, 151, 149, 75, 73, 374, 111, + 252, 254, 258, 305, 256, 157, 146, 137, + 249, 237, 245, 241, 274, 262, 260, 265, + 172, 171, 309, 277, 284, 307, 136, 344, + 173, 168, 345, 353, 346, 70, 110, 311, + 357, 144, 104, 67, 364, 367, 64, 288, + 142, 140, 98, 355, 133, 123, 61, 113, + 285, 280, 279, 278, 370, 286, 359, 283, + 101, 236, 163, 235, 234, 233, 232, 231, + 162, 363, 230, 281, 165, 229, 109, 228 + } + } +}; /* end Banks */ + +/*---------------------------------------------------------------------------- + * Samples + *---------------------------------------------------------------------------- +*/ + +const EAS_SAMPLE eas_samples[] = +{ + 0, 0, -3, -4, -6, -8, -10, -12, -12, -11, -8, -3, 3, 7, 10, 14, + 16, 16, 15, 12, 9, 4, -4, -12, -18, -21, -21, -19, -18, -15, -10, -3, + 10, 20, 34, 44, 51, 52, 48, 43, 38, 26, 8, -15, -37, -52, -61, -64, + -66, -64, -59, -47, -31, -13, 4, 18, 30, 37, 40, 36, 30, 24, 19, 11, + -2, -17, -24, -28, -28, -21, -18, -16, -10, -3, 12, 27, 39, 49, 53, 53, + 50, 43, 37, 25, 11, -11, -31, -46, -57, -63, -66, -63, -57, -46, -34, -19, + -3, 13, 27, 35, 39, 37, 32, 26, 20, 11, 0, -13, -20, -24, -25, -21, + -19, -14, -8, -2, 9, 23, 37, 47, 53, 52, 49, 42, 35, 25, 13, -6, + -28, -48, -60, -67, -67, -64, -60, -51, -39, -23, -7, 10, 23, 35, 39, 38, + 32, 26, 21, 15, 4, -9, -20, -22, -21, -19, -14, -11, -5, 1, 9, 19, + 31, 45, 51, 52, 47, 39, 35, 25, 15, -3, -23, -42, -58, -70, -71, -66, + -60, -51, -43, -30, -13, 6, 22, 32, 40, 40, 38, 33, 27, 19, 9, -5, + -17, -25, -26, -22, -16, -11, -8, -4, 7, 21, 35, 48, 53, 56, 50, 43, + 34, 22, 13, -2, -22, -44, -63, -75, -76, -69, -61, -51, -43, -29, -13, 6, + 23, 32, 41, 43, 41, 37, 26, 18, 7, -8, -19, -25, -25, -22, -15, -9, + -5, 0, 10, 24, 37, 44, 48, 52, 52, 46, 33, 20, 8, -5, -20, -38, + -59, -74, -79, -73, -67, -55, -43, -26, -11, 4, 18, 29, 41, 45, 45, 38, + 29, 21, 11, -3, -15, -25, -27, -22, -16, -11, -8, 0, 10, 25, 38, 44, + 47, 50, 53, 49, 37, 20, 7, -5, -17, -34, -58, -74, -82, -76, -67, -59, + -47, -29, -12, 3, 14, 25, 38, 50, 52, 46, 33, 23, 14, 3, -11, -25, + -28, -27, -21, -16, -13, -7, 8, 27, 41, 44, 45, 47, 54, 55, 44, 25, + 7, -7, -18, -32, -53, -71, -81, -81, -72, -67, -55, -37, -16, 3, 15, 23, + 34, 48, 57, 56, 44, 30, 19, 5, -12, -26, -33, -31, -25, -19, -16, -11, + 7, 25, 45, 49, 49, 52, 57, 59, 48, 32, 11, -5, -22, -39, -56, -73, + -82, -88, -84, -75, -60, -38, -16, 5, 21, 30, 39, 52, 59, 61, 53, 37, + 22, 7, -12, -28, -35, -36, -30, -22, -19, -16, -2, 21, 41, 52, 51, 52, + 57, 62, 54, 40, 18, -2, -18, -36, -54, -70, -80, -86, -87, -81, -69, -48, + -23, 0, 18, 28, 35, 45, 57, 64, 59, 46, 27, 9, -11, -24, -30, -32, + -29, -25, -20, -16, -5, 15, 36, 47, 50, 49, 53, 57, 54, 43, 24, 5, + -14, -32, -50, -65, -75, -82, -86, -86, -77, -58, -32, -8, 14, 25, 30, 41, + 56, 69, 69, 57, 36, 17, -4, -20, -29, -32, -27, -28, -27, -23, -13, 10, + 33, 46, 50, 48, 50, 54, 55, 48, 34, 16, -6, -29, -50, -68, -75, -78, + -82, -86, -84, -72, -47, -16, 11, 28, 34, 41, 51, 64, 70, 64, 49, 27, + 5, -17, -30, -33, -29, -29, -30, -30, -22, -2, 23, 41, 49, 51, 51, 54, + 56, 50, 42, 25, 4, -20, -44, -62, -70, -76, -83, -87, -89, -78, -56, -29, + 0, 19, 31, 38, 48, 63, 72, 71, 60, 40, 14, -12, -25, -29, -26, -27, + -33, -37, -30, -12, 11, 31, 41, 48, 51, 53, 55, 55, 51, 39, 17, -12, + -38, -58, -67, -74, -82, -92, -98, -89, -69, -41, -13, 10, 29, 41, 50, 64, + 72, 78, 74, 57, 29, 0, -18, -26, -28, -32, -38, -42, -38, -23, -3, 18, + 30, 42, 52, 58, 60, 61, 57, 48, 28, 2, -30, -51, -62, -70, -81, -94, + -101, -93, -75, -49, -23, -2, 18, 36, 50, 61, 69, 77, 78, 66, 42, 11, + -11, -22, -27, -32, -39, -46, -46, -36, -14, 8, 25, 41, 52, 59, 62, 63, + 62, 57, 38, 11, -20, -47, -61, -69, -78, -89, -98, -94, -80, -60, -37, -12, + 13, 33, 48, 62, 70, 78, 81, 72, 52, 23, 0, -14, -24, -33, -43, -49, + -49, -39, -23, -2, 15, 33, 47, 57, 63, 62, 62, 57, 40, 20, -7, -34, + -52, -65, -74, -83, -94, -92, -81, -63, -42, -22, 0, 21, 39, 54, 63, 73, + 79, 76, 61, 37, 12, -5, -19, -28, -37, -46, -51, -47, -32, -13, 7, 25, + 43, 54, 58, 60, 60, 61, 48, 27, 3, -25, -45, -60, -72, -81, -90, -92, + -84, -71, -52, -32, -9, 14, 33, 50, 61, 74, 80, 78, 67, 47, 24, 6, + -12, -26, -37, -50, -56, -52, -37, -19, -2, 16, 35, 52, 61, 63, 61, 59, + 51, 35, 12, -15, -38, -55, -66, -77, -83, -83, -80, -68, -55, -39, -19, 4, + 25, 41, 54, 66, 73, 75, 68, 52, 31, 11, -7, -22, -33, -46, -54, -51, + -39, -24, -5, 12, 32, 48, 56, 60, 61, 58, 50, 36, 17, -8, -30, -46, + -63, -74, -80, -80, -74, -69, -58, -43, -27, -5, 15, 31, 48, 60, 68, 72, + 68, 57, 39, 20, 2, -16, -30, -44, -51, -50, -41, -27, -10, 9, 28, 43, + 53, 57, 57, 54, 48, 37, 19, -3, -25, -41, -56, -69, -75, -73, -69, -63, + -59, -49, -32, -13, 9, 25, 37, 48, 58, 66, 65, 58, 42, 25, 8, -9, + -22, -36, -41, -43, -37, -26, -14, 4, 21, 37, 48, 52, 53, 47, 42, 34, + 21, 3, -18, -39, -51, -64, -67, -62, -60, -60, -58, -50, -36, -16, 3, 17, + 29, 41, 49, 58, 61, 60, 49, 29, 11, -7, -19, -28, -32, -33, -30, -25, + -14, 2, 19, 33, 41, 45, 42, 38, 36, 29, 20, 6, -14, -28, -43, -54, + -58, -55, -50, -51, -54, -51, -41, -22, -4, 11, 19, 30, 37, 47, 55, 56, + 51, 34, 16, 0, -15, -19, -23, -22, -22, -21, -14, 0, 15, 29, 39, 43, + 37, 31, 25, 21, 18, 6, -11, -28, -42, -50, -51, -48, -44, -41, -44, -43, + -41, -25, -8, 9, 16, 22, 26, 35, 43, 50, 48, 33, 16, -3, -13, -16, + -16, -15, -13, -11, -6, 5, 16, 28, 38, 41, 35, 24, 15, 12, 10, 4, + -11, -27, -39, -46, -46, -45, -40, -36, -36, -37, -38, -29, -13, 6, 16, 19, + 22, 27, 37, 43, 42, 32, 19, 2, -10, -13, -12, -7, -4, -2, 2, 10, + 18, 27, 36, 38, 32, 20, 9, 4, -2, -4, -11, -23, -34, -42, -42, -38, + -31, -28, -29, -32, -33, -30, -18, 0, 10, 12, 12, 17, 26, 35, 36, 31, + 19, 5, -6, -11, -9, -2, 7, 14, 13, 13, 16, 23, 31, 34, 29, 15, + -3, -8, -10, -10, -14, -20, -26, -30, -32, -30, -25, -18, -17, -24, -31, -32, + -26, -11, 2, 7, 8, 9, 17, 25, 29, 28, 21, 9, -2, -7, -5, 4, + 12, 21, 24, 23, 25, 26, 29, 31, 27, 15, -2, -15, -21, -23, -23, -23, + -28, -30, -31, -27, -19, -10, -9, -13, -21, -22, -20, -11, -4, -3, -5, -2, + 5, 13, 17, 17, 16, 10, 6, 0, 3, 11, 23, 32, 33, 30, 28, 27, + 24, 24, 19, 9, -6, -19, -29, -29, -26, -20, -19, -22, -24, -23, -16, -10, + -9, -14, -20, -24, -21, -16, -10, -6, -5, 1, 5, 11, 12, 13, 11, 8, + 6, 1, 4, 9, 23, 33, 39, 36, 32, 32, 28, 22, 17, 7, -7, -22, + -31, -33, -31, -24, -19, -18, -18, -16, -13, -7, -6, -8, -14, -21, -24, -20, + -15, -12, -9, -6, 0, 4, 6, 8, 8, 5, 5, 2, 7, 15, 27, 37, + 42, 45, 41, 39, 32, 22, 13, 3, -11, -26, -37, -41, -37, -29, -21, -18, + -15, -11, -6, -2, -2, -4, -7, -13, -16, -20, -21, -16, -14, -10, -6, -3, + -3, 0, 3, 2, 3, 3, 9, 18, 32, 41, 46, 49, 44, 43, 35, 24, + 12, 1, -14, -27, -39, -40, -36, -31, -22, -16, -13, -6, -3, -3, -4, -9, + -9, -13, -16, -20, -21, -16, -15, -11, -6, -4, -4, -5, -5, -3, -3, 0, + 10, 19, 33, 44, 51, 56, 52, 50, 40, 23, 11, -6, -19, -30, -40, -43, + -40, -35, -24, -16, -7, 2, 6, 5, 1, -6, -9, -9, -9, -12, -19, -21, + -21, -17, -9, -7, -9, -11, -15, -14, -9, -7, 7, 19, 36, 51, 57, 61, + 59, 56, 48, 33, 13, -8, -24, -35, -45, -51, -46, -38, -26, -14, -7, 3, + 11, 15, 12, 3, -5, -7, -6, -9, -15, -22, -25, -23, -17, -13, -12, -16, + -19, -21, -18, -12, 3, 21, 38, 50, 58, 67, 65, 64, 55, 41, 21, -4, + -25, -38, -46, -50, -49, -43, -33, -23, -11, 3, 14, 19, 16, 8, 0, -2, + -2, 0, -8, -19, -27, -30, -25, -22, -20, -20, -22, -25, -24, -16, 1, 22, + 43, 56, 62, 67, 68, 65, 60, 46, 24, -3, -25, -40, -45, -49, -50, -46, + -37, -23, -10, 1, 12, 20, 20, 14, 7, 2, 3, 3, -4, -15, -26, -31, + -30, -27, -26, -26, -29, -33, -33, -25, -8, 17, 41, 57, 65, 71, 73, 73, + 66, 53, 33, 5, -23, -41, -48, -50, -48, -48, -40, -30, -14, 1, 12, 21, + 24, 18, 13, 6, 5, 5, 0, -11, -25, -37, -39, -35, -31, -31, -33, -38, + -37, -29, -12, 15, 40, 59, 67, 71, 72, 73, 69, 59, 39, 14, -16, -38, + -50, -51, -50, -48, -45, -36, -21, -4, 12, 25, 30, 25, 18, 11, 11, 10, + 6, -8, -25, -39, -46, -42, -38, -37, -37, -40, -42, -34, -15, 13, 40, 57, + 66, 71, 72, 72, 69, 61, 45, 19, -10, -34, -46, -48, -47, -45, -45, -41, + -28, -12, 7, 23, 27, 25, 18, 15, 17, 17, 12, 1, -20, -37, -47, -50, + -46, -45, -44, -45, -46, -41, -21, 7, 37, 60, 69, 73, 72, 72, 72, 67, + 52, 25, -6, -33, -47, -50, -47, -47, -47, -45, -35, -16, 6, 23, 31, 30, + 24, 23, 24, 25, 18, 4, -15, -33, -50, -56, -57, -53, -48, -49, -49, -45, + -29, 2, 35, 58, 68, 71, 72, 74, 73, 68, 56, 34, 5, -26, -43, -48, + -45, -42, -46, -46, -41, -24, 0, 21, 33, 34, 31, 25, 27, 27, 19, 6, + -14, -36, -55, -64, -64, -60, -50, -47, -45, -44, -31, -4, 32, 58, 71, 72, + 68, 70, 70, 66, 57, 36, 11, -20, -43, -50, -48, -41, -37, -42, -40, -28, + -5, 21, 36, 38, 34, 26, 29, 28, 20, 8, -13, -33, -52, -68, -69, -65, + -55, -49, -47, -44, -31, -3, 30, 55, 67, 70, 68, 70, 70, 65, 57, 39, + 15, -13, -38, -49, -47, -40, -35, -39, -41, -30, -9, 17, 37, 44, 45, 38, + 32, 29, 22, 9, -10, -34, -54, -70, -75, -73, -64, -52, -45, -43, -31, -7, + 25, 53, 67, 72, 70, 72, 70, 62, 53, 38, 16, -10, -32, -49, -50, -43, + -35, -33, -36, -29, -10, 16, 35, 46, 46, 41, 35, 30, 23, 10, -10, -34, + -53, -69, -75, -74, -66, -53, -45, -42, -34, -13, 17, 46, 63, 68, 66, 63, + 65, 63, 54, 43, 24, 0, -20, -40, -43, -42, -36, -32, -32, -28, -16, 7, + 29, 47, 52, 47, 39, 31, 21, 10, -9, -30, -50, -66, -78, -77, -71, -59, + -49, -42, -34, -17, 9, 37, 56, 66, 66, 62, 62, 61, 56, 45, 30, 7, + -13, -31, -39, -40, -36, -33, -32, -28, -18, 1, 21, 41, 54, 52, 44, 36, + 26, 13, -8, -29, -48, -66, -76, -80, -74, -64, -55, -45, -34, -18, 5, 29, + 50, 65, 68, 66, 64, 60, 59, 47, 33, 15, -5, -23, -37, -43, -41, -37, + -35, -31, -21, -4, 16, 36, 52, 59, 54, 45, 33, 17, -5, -25, -45, -60, + -74, -83, -82, -71, -59, -49, -37, -23, -2, 22, 43, 59, 66, 65, 64, 60, + 58, 50, 39, 23, 2, -17, -32, -39, -40, -38, -35, -32, -23, -6, 14, 33, + 49, 59, 58, 49, 34, 16, -5, -25, -43, -60, -74, -83, -83, -76, -63, -53, + -40, -24, -5, 16, 36, 54, 65, 67, 65, 61, 57, 52, 43, 27, 9, -12, + -26, -37, -40, -39, -36, -32, -28, -13, 6, 27, 46, 58, 60, 52, 39, 23, + 5, -16, -36, -53, -66, -77, -84, -81, -72, -60, -45, -32, -15, 5, 25, 48, + 62, 69, 71, 69, 65, 58, 50, 34, 16, -6, -24, -36, -42, -45, -44, -39, + -33, -21, -2, 22, 43, 59, 64, 60, 47, 34, 17, -6, -28, -50, -66, -76, + -84, -86, -82, -72, -57, -40, -21, -2, 21, 42, 58, 66, 73, 76, 71, 64, + 53, 40, 26, 4, -17, -34, -45, -49, -48, -43, -38, -28, -10, 15, 40, 58, + 66, 64, 56, 42, 25, 4, -21, -44, -62, -73, -81, -87, -86, -78, -65, -47, + -31, -9, 15, 34, 52, 62, 72, 79, 80, 72, 61, 49, 34, 12, -12, -32, + -43, -49, -54, -55, -48, -36, -16, 10, 35, 56, 67, 71, 67, 54, 38, 15, + -10, -34, -57, -72, -85, -93, -97, -89, -76, -59, -40, -20, 8, 32, 50, 67, + 77, 87, 89, 81, 66, 52, 35, 16, -6, -30, -47, -58, -61, -57, -50, -37, + -19, 6, 29, 51, 65, 73, 73, 62, 44, 18, -6, -28, -49, -67, -81, -93, + -97, -94, -83, -65, -47, -28, -5, 19, 42, 61, 76, 87, 90, 88, 80, 66, + 48, 27, 3, -17, -40, -56, -65, -66, -58, -49, -30, -6, 17, 41, 59, 71, + 77, 70, 56, 36, 11, -13, -34, -53, -71, -89, -98, -100, -94, -79, -62, -44, + -21, 3, 27, 52, 74, 90, 98, 95, 86, 75, 59, 37, 12, -14, -35, -54, + -64, -67, -64, -51, -34, -10, 11, 32, 50, 65, 73, 71, 58, 37, 14, -10, + -29, -48, -64, -81, -93, -98, -94, -82, -63, -45, -26, -5, 16, 40, 65, 83, + 94, 94, 84, 75, 63, 46, 23, -3, -27, -47, -58, -64, -64, -56, -39, -17, + 3, 20, 38, 57, 71, 72, 61, 45, 24, 1, -19, -37, -56, -73, -91, -99, + -100, -92, -74, -53, -34, -16, 7, 31, 59, 82, 97, 101, 92, 78, 65, 48, + 29, 6, -21, -43, -55, -64, -66, -58, -40, -18, 3, 17, 32, 51, 69, 71, + 62, 45, 27, 6, -15, -34, -50, -64, -81, -93, -99, -96, -80, -59, -40, -23, + -4, 21, 50, 77, 94, 100, 93, 81, 67, 53, 36, 14, -12, -36, -53, -58, + -63, -56, -42, -22, -5, 10, 23, 42, 63, 70, 62, 47, 29, 13, -6, -27, + -43, -57, -72, -84, -98, -99, -87, -66, -44, -27, -11, 10, 38, 67, 91, 99, + 92, 82, 70, 57, 41, 21, -3, -27, -47, -58, -63, -58, -44, -23, -5, 7, + 17, 35, 55, 66, 61, 46, 29, 13, -4, -22, -39, -51, -65, -78, -90, -95, + -85, -69, -47, -30, -12, 9, 30, 57, 83, 96, 91, 81, 67, 57, 42, 26, + 6, -18, -39, -55, -62, -58, -43, -24, -8, 2, 14, 30, 47, 60, 60, 49, + 34, 17, 0, -16, -31, -43, -58, -71, -86, -93, -86, -72, -52, -32, -15, 3, + 22, 48, 76, 90, 89, 78, 69, 59, 46, 32, 14, -6, -27, -47, -57, -56, + -45, -29, -12, -5, 4, 18, 37, 54, 58, 51, 36, 21, 6, -8, -20, -33, + -52, -68, -84, -90, -85, -74, -58, -42, -22, 0, 20, 42, 67, 83, 87, 80, + 68, 58, 47, 34, 19, 0, -20, -40, -52, -53, -45, -27, -13, -4, 6, 17, + 33, 47, 53, 52, 38, 21, 3, -11, -24, -35, -50, -65, -80, -89, -85, -71, + -55, -39, -21, -2, 20, 39, 59, 74, 81, 75, 67, 57, 47, 38, 23, 4, + -17, -32, -43, -45, -39, -26, -14, -4, 4, 12, 26, 38, 47, 48, 35, 19, + 4, -10, -20, -29, -41, -56, -71, -78, -81, -71, -56, -43, -23, -6, 15, 35, + 49, 62, 72, 69, 63, 54, 45, 41, 28, 11, -11, -27, -37, -40, -35, -24, + -17, -7, 2, 9, 22, 35, 46, 49, 37, 21, 4, -9, -18, -27, -41, -55, + -71, -79, -79, -70, -53, -38, -23, -8, 9, 31, 46, 58, 63, 63, 59, 52, + 45, 40, 32, 14, -6, -24, -32, -31, -30, -23, -18, -12, 1, 9, 21, 31, + 41, 44, 33, 21, 5, -6, -20, -29, -43, -57, -69, -77, -73, -65, -52, -41, + -27, -8, 11, 32, 49, 57, 64, 61, 55, 47, 39, 36, 29, 13, -8, -25, + -36, -35, -26, -16, -9, -5, 1, 9, 22, 36, 45, 43, 33, 17, 1, -11, + -21, -32, -45, -57, -71, -78, -73, -61, -45, -33, -23, -8, 11, 31, 46, 53, + 57, 54, 48, 40, 34, 31, 27, 14, -4, -20, -29, -28, -22, -12, -4, 1, + 4, 8, 21, 34, 43, 43, 31, 17, 1, -11, -22, -31, -44, -59, -72, -78, + -70, -54, -40, -28, -19, -8, 10, 28, 45, 53, 57, 53, 43, 34, 28, 27, + 26, 18, 0, -18, -31, -29, -20, -11, -3, 2, 5, 10, 19, 31, 43, 44, + 34, 19, 2, -13, -23, -32, -43, -55, -68, -77, -73, -57, -41, -26, -15, -6, + 11, 28, 43, 52, 52, 49, 41, 33, 24, 22, 21, 14, 1, -14, -25, -24, + -18, -7, -2, 2, 7, 10, 20, 31, 40, 43, 33, 18, 3, -13, -24, -35, + -44, -55, -70, -78, -74, -59, -40, -26, -11, 1, 13, 29, 44, 53, 57, 54, + 45, 32, 24, 18, 13, 9, -4, -16, -26, -29, -22, -10, 1, 8, 13, 18, + 23, 35, 42, 45, 37, 21, 5, -14, -30, -41, -49, -57, -69, -77, -76, -61, + -39, -20, -5, 9, 20, 34, 47, 53, 55, 48, 39, 27, 14, 8, 3, 2, + -4, -15, -23, -24, -16, -3, 6, 11, 19, 24, 30, 34, 41, 43, 35, 18, + 1, -17, -31, -44, -52, -59, -68, -75, -73, -61, -38, -19, 1, 13, 23, 30, + 42, 52, 52, 47, 36, 23, 14, 7, 4, 0, -6, -11, -20, -24, -18, -5, + 7, 15, 18, 22, 28, 36, 43, 43, 38, 24, 4, -13, -30, -44, -55, -64, + -69, -77, -76, -65, -44, -19, 1, 15, 27, 35, 46, 53, 53, 46, 36, 23, + 11, 3, -5, -7, -9, -14, -20, -23, -19, -7, 11, 18, 21, 25, 30, 40, + 43, 43, 38, 24, 7, -14, -30, -41, -55, -65, -73, -77, -74, -66, -49, -24, + -2, 17, 29, 35, 44, 51, 54, 49, 35, 23, 11, 1, -6, -12, -15, -16, + -20, -24, -21, -10, 8, 21, 27, 33, 35, 42, 48, 47, 37, 23, 7, -12, + -28, -44, -60, -69, -75, -78, -74, -65, -49, -25, -2, 17, 30, 40, 48, 54, + 55, 48, 36, 20, 6, -4, -9, -14, -20, -22, -24, -21, -15, -6, 7, 21, + 32, 39, 43, 44, 49, 50, 38, 21, 4, -13, -28, -47, -62, -74, -77, -78, + -77, -65, -48, -26, -4, 15, 28, 40, 50, 56, 54, 46, 33, 20, 9, -2, + -10, -16, -21, -21, -23, -21, -15, -5, 9, 19, 30, 38, 42, 44, 46, 47, + 36, 22, 6, -10, -23, -39, -57, -74, -78, -79, -75, -65, -51, -33, -11, 9, + 25, 37, 46, 55, 56, 48, 34, 21, 10, 4, -4, -14, -20, -25, -24, -21, + -12, -3, 8, 17, 26, 36, 47, 50, 50, 47, 36, 25, 10, -5, -21, -40, + -57, -75, -82, -79, -75, -64, -51, -37, -16, 5, 25, 40, 48, 55, 55, 49, + 37, 25, 15, 6, -6, -18, -26, -29, -25, -20, -16, -7, 5, 17, 29, 39, + 49, 56, 56, 51, 39, 28, 15, 0, -17, -38, -58, -75, -86, -86, -80, -70, + -54, -37, -16, 7, 25, 42, 50, 55, 58, 52, 40, 25, 11, 2, -5, -14, + -21, -26, -26, -18, -12, -5, 4, 13, 25, 34, 45, 53, 55, 48, 39, 25, + 16, 3, -13, -31, -54, -70, -83, -85, -78, -68, -55, -38, -20, 1, 20, 36, + 46, 51, 55, 48, 39, 27, 17, 7, -5, -13, -20, -23, -23, -18, -10, -4, + 3, 10, 21, 29, 40, 48, 52, 50, 40, 28, 20, 10, -5, -24, -48, -67, + -82, -87, -81, -73, -56, -44, -25, -5, 15, 34, 46, 52, 55, 51, 39, 27, + 18, 7, -2, -13, -22, -25, -24, -16, -9, 1, 8, 13, 22, 30, 42, 48, + 50, 47, 38, 26, 15, 6, -8, -22, -41, -61, -77, -86, -81, -70, -54, -40, + -27, -8, 12, 31, 42, 49, 50, 48, 38, 26, 16, 7, -4, -11, -18, -22, + -21, -16, -9, 0, 9, 15, 21, 26, 35, 47, 50, 46, 36, 28, 18, 7, + -7, -22, -37, -53, -70, -81, -83, -72, -58, -43, -30, -14, 5, 22, 37, 44, + 46, 44, 37, 26, 17, 8, 2, -7, -12, -17, -16, -12, -6, 3, 8, 13, + 17, 22, 31, 42, 43, 43, 35, 29, 25, 14, 2, -17, -35, -51, -65, -77, + -80, -75, -63, -47, -34, -18, 4, 21, 32, 38, 41, 41, 36, 28, 17, 8, + 1, -9, -12, -16, -15, -9, -2, 8, 13, 15, 17, 23, 28, 39, 43, 38, + 30, 21, 17, 11, 4, -12, -28, -45, -60, -68, -71, -66, -58, -49, -38, -23, + -5, 15, 27, 34, 34, 32, 28, 23, 18, 13, 4, -2, -7, -9, -7, -4, + 5, 14, 16, 16, 14, 15, 24, 35, 39, 35, 23, 17, 15, 11, 8, -4, + -19, -37, -53, -62, -65, -62, -57, -53, -43, -31, -14, 5, 19, 27, 31, 28, + 26, 23, 20, 18, 11, 5, -2, -5, 0, 3, 8, 14, 16, 15, 11, 7, + 12, 23, 32, 32, 21, 12, 10, 13, 12, 6, -9, -27, -43, -50, -55, -53, + -51, -52, -44, -38, -23, -6, 7, 18, 22, 19, 16, 15, 16, 19, 17, 12, + 6, 3, 7, 10, 16, 20, 23, 20, 14, 8, 9, 17, 27, 26, 17, 6, + 3, 7, 10, 7, -5, -18, -32, -41, -46, -45, -45, -45, -44, -40, -30, -16, + -3, 8, 15, 12, 10, 11, 16, 19, 19, 16, 12, 10, 11, 15, 20, 25, + 26, 24, 18, 11, 6, 11, 17, 21, 15, 3, -6, -2, 4, 7, 2, -14, + -25, -32, -36, -38, -37, -37, -35, -33, -33, -25, -15, -4, 3, 4, 0, -3, + 2, 13, 21, 21, 20, 17, 19, 23, 27, 31, 33, 31, 24, 16, 4, 2, + 7, 13, 13, 3, -10, -9, 0, 8, 7, -3, -15, -22, -24, -30, -32, -37, + -39, -38, -37, -34, -28, -17, -8, -2, -4, -4, 4, 16, 26, 30, 26, 22, + 22, 25, 29, 31, 30, 29, 24, 17, 6, -2, 7, 10, 13, 4, -11, -15, + -10, 3, 8, 2, -10, -17, -17, -17, -23, -29, -35, -37, -34, -36, -35, -28, + -19, -10, -11, -14, -8, 8, 21, 26, 26, 21, 24, 31, 38, 40, 38, 37, + 33, 26, 15, 4, 1, 2, 1, -6, -19, -24, -18, -7, 2, 5, -4, -10, + -9, -6, -7, -16, -27, -33, -35, -38, -41, -38, -32, -22, -20, -18, -10, 4, + 20, 29, 31, 30, 28, 32, 38, 43, 42, 39, 34, 28, 14, 4, 1, 3, + 4, -5, -21, -30, -26, -14, 1, 3, -4, -8, -8, 0, 0, -8, -15, -26, + -29, -35, -40, -40, -36, -30, -28, -29, -22, -10, 9, 22, 28, 28, 27, 30, + 39, 46, 50, 50, 43, 33, 21, 9, 3, 3, 1, -10, -22, -35, -34, -22, + -8, 2, 0, -6, -7, 0, 5, -2, -9, -18, -28, -34, -41, -43, -39, -35, + -33, -33, -25, -12, 5, 19, 26, 29, 31, 31, 39, 46, 51, 52, 47, 38, + 27, 18, 10, 5, -3, -13, -22, -33, -36, -28, -16, -4, -2, -4, -6, 0, + 8, 7, 0, -12, -22, -33, -40, -42, -39, -37, -38, -39, -32, -17, 2, 15, + 24, 25, 28, 33, 39, 47, 51, 53, 51, 44, 35, 23, 15, 8, 1, -12, + -25, -37, -41, -33, -22, -11, -4, -5, -3, 3, 10, 13, 6, -5, -17, -28, + -38, -43, -44, -44, -44, -43, -36, -23, -7, 7, 20, 26, 29, 35, 43, 51, + 54, 58, 56, 52, 44, 29, 18, 9, -2, -12, -28, -39, -45, -38, -26, -16, + -7, -3, 1, 6, 12, 15, 12, 3, -11, -25, -37, -41, -43, -46, -47, -46, + -39, -28, -15, 0, 11, 21, 25, 31, 38, 46, 53, 60, 62, 59, 53, 42, + 32, 19, 6, -10, -27, -41, -47, -47, -39, -31, -21, -9, -2, 5, 11, 16, + 19, 13, 2, -15, -30, -35, -37, -43, -47, -49, -42, -32, -21, -11, 0, 8, + 19, 27, 38, 47, 51, 58, 63, 63, 59, 50, 41, 28, 10, -9, -26, -37, + -43, -44, -40, -33, -23, -11, 0, 6, 9, 14, 15, 13, 1, -15, -25, -32, + -34, -43, -49, -50, -43, -30, -20, -13, -9, 0, 10, 23, 36, 46, 52, 55, + 62, 65, 66, 61, 51, 36, 15, -7, -24, -34, -42, -45, -46, -42, -34, -20, + -5, 5, 11, 14, 16, 13, 2, -10, -18, -24, -31, -39, -49, -48, -42, -34, + -24, -18, -15, -8, 2, 13, 29, 42, 51, 57, 62, 65, 70, 69, 60, 45, + 20, -3, -24, -37, -43, -46, -49, -48, -39, -24, -6, 5, 12, 17, 20, 16, + 6, -9, -15, -21, -26, -38, -50, -56, -50, -37, -26, -23, -19, -14, -4, 11, + 27, 42, 54, 58, 63, 65, 68, 70, 63, 50, 26, 1, -21, -37, -43, -44, + -44, -44, -40, -28, -11, 5, 10, 16, 18, 14, 5, -12, -19, -22, -24, -33, + -47, -52, -52, -38, -25, -17, -17, -16, -10, 4, 22, 39, 53, 59, 62, 63, + 66, 68, 66, 55, 32, 9, -17, -34, -43, -42, -39, -38, -38, -31, -19, -3, + 10, 17, 19, 12, 3, -12, -21, -24, -24, -31, -40, -49, -52, -41, -30, -18, + -15, -17, -10, 0, 16, 33, 47, 59, 65, 64, 65, 67, 63, 56, 38, 13, + -12, -32, -41, -39, -35, -33, -32, -27, -17, -4, 8, 15, 16, 13, 4, -11, + -20, -25, -27, -32, -40, -48, -52, -46, -37, -25, -18, -16, -10, 1, 16, 33, + 49, 59, 66, 67, 65, 66, 62, 51, 38, 15, -9, -30, -38, -41, -33, -29, + -26, -23, -17, -5, 7, 16, 15, 14, 5, -9, -19, -27, -31, -34, -40, -47, + -52, -49, -40, -30, -22, -16, -8, 4, 19, 32, 46, 59, 67, 71, 69, 64, + 57, 49, 36, 17, -7, -27, -38, -40, -35, -28, -23, -19, -12, -5, 6, 12, + 16, 15, 10, -5, -19, -28, -32, -36, -39, -46, -53, -52, -45, -34, -25, -18, + -7, 6, 20, 33, 46, 60, 67, 74, 71, 65, 56, 46, 37, 18, -2, -20, + -33, -38, -38, -30, -22, -16, -12, -6, 2, 6, 15, 15, 11, 1, -11, -19, + -31, -37, -42, -46, -51, -54, -53, -46, -35, -26, -14, 3, 17, 33, 45, 57, + 67, 75, 77, 71, 62, 50, 36, 18, 0, -19, -31, -36, -37, -31, -23, -17, + -11, -6, 1, 6, 11, 15, 14, 8, -3, -16, -27, -37, -41, -47, -52, -58, + -60, -55, -46, -32, -16, 0, 17, 32, 46, 59, 70, 79, 80, 75, 65, 51, + 35, 20, 2, -15, -27, -38, -42, -36, -27, -17, -10, -4, 3, 7, 12, 18, + 19, 14, 5, -7, -22, -37, -46, -53, -57, -62, -67, -65, -58, -43, -22, 1, + 20, 35, 48, 60, 69, 79, 82, 79, 68, 53, 36, 21, 4, -11, -24, -36, + -40, -38, -31, -21, -14, -5, 1, 5, 11, 17, 22, 19, 14, -2, -17, -35, + -48, -55, -63, -67, -73, -72, -64, -49, -27, -4, 19, 36, 52, 64, 73, 81, + 85, 82, 72, 56, 36, 20, 3, -14, -24, -33, -36, -35, -32, -22, -13, -6, + 2, 7, 10, 15, 19, 19, 17, 6, -10, -29, -48, -58, -67, -71, -75, -78, + -72, -58, -35, -10, 16, 35, 52, 65, 74, 80, 86, 87, 79, 62, 39, 21, + 5, -11, -22, -33, -39, -39, -34, -25, -15, -7, 3, 8, 16, 17, 21, 22, + 19, 9, -6, -27, -47, -60, -71, -77, -80, -81, -73, -61, -39, -12, 16, 36, + 52, 63, 73, 80, 85, 87, 76, 59, 41, 23, 8, -7, -18, -29, -36, -38, + -33, -23, -13, -8, 1, 6, 14, 18, 19, 23, 23, 17, 1, -20, -43, -57, + -67, -78, -83, -89, -81, -67, -45, -19, 9, 35, 55, 67, 74, 80, 87, 91, + 83, 68, 44, 24, 6, -9, -21, -29, -36, -39, -39, -31, -20, -10, 1, 13, + 20, 26, 26, 27, 28, 22, 8, -16, -40, -60, -75, -86, -93, -95, -89, -75, + -52, -24, 7, 37, 57, 69, 77, 83, 90, 93, 85, 70, 48, 27, 8, -8, + -19, -26, -32, -35, -39, -37, -28, -17, -2, 9, 19, 21, 27, 31, 32, 29, + 12, -9, -32, -54, -71, -86, -94, -96, -90, -82, -62, -33, 2, 34, 56, 69, + 78, 87, 94, 94, 85, 69, 49, 29, 9, -10, -21, -27, -30, -33, -37, -36, + -29, -17, -5, 9, 19, 25, 27, 31, 33, 33, 21, -2, -25, -51, -71, -86, + -95, -95, -92, -85, -69, -42, -8, 27, 52, 67, 74, 83, 92, 95, 89, 75, + 56, 35, 16, -6, -17, -26, -28, -34, -41, -39, -37, -25, -9, 6, 20, 28, + 31, 37, 37, 34, 24, 3, -20, -46, -69, -85, -96, -99, -97, -89, -73, -47, + -11, 21, 45, 61, 73, 84, 92, 95, 89, 77, 61, 41, 20, -2, -13, -20, + -28, -36, -43, -46, -40, -30, -16, 0, 12, 24, 30, 38, 43, 41, 33, 13, + -14, -39, -63, -80, -93, -98, -100, -94, -76, -52, -19, 14, 38, 56, 70, 80, + 90, 94, 88, 75, 58, 40, 22, 6, -8, -19, -25, -33, -39, -41, -38, -31, + -19, -5, 7, 21, 31, 39, 45, 42, 32, 15, -8, -32, -55, -77, -93, -102, + -101, -94, -80, -57, -29, 5, 34, 54, 70, 78, 88, 96, 92, 80, 62, 41, + 24, 8, -9, -21, -32, -35, -38, -41, -39, -35, -22, -6, 6, 21, 31, 39, + 46, 44, 35, 18, -5, -27, -49, -70, -86, -97, -102, -96, -84, -58, -30, -2, + 26, 45, 62, 74, 82, 89, 89, 80, 66, 46, 28, 12, -3, -14, -26, -36, + -39, -42, -40, -36, -28, -15, 0, 17, 30, 37, 45, 48, 40, 23, 3, -20, + -43, -64, -81, -93, -98, -96, -85, -65, -38, -8, 20, 40, 55, 68, 80, 88, + 88, 82, 68, 54, 35, 18, 2, -12, -24, -35, -40, -45, -45, -41, -33, -20, + -4, 15, 31, 41, 49, 52, 48, 32, 13, -14, -38, -59, -77, -92, -101, -102, + -91, -70, -45, -15, 15, 38, 53, 65, 77, 89, 91, 85, 71, 52, 38, 21, + 5, -12, -26, -36, -42, -45, -45, -43, -34, -22, -7, 9, 26, 39, 50, 56, + 50, 34, 14, -7, -29, -50, -69, -84, -96, -98, -90, -72, -50, -24, 7, 32, + 48, 57, 68, 84, 91, 88, 74, 58, 44, 30, 11, -9, -26, -38, -41, -46, + -45, -44, -38, -23, -7, 9, 24, 36, 49, 55, 51, 35, 18, -3, -24, -45, + -64, -78, -89, -93, -90, -75, -54, -29, 0, 23, 42, 54, 67, 80, 90, 91, + 81, 65, 48, 31, 13, -5, -24, -41, -50, -53, -51, -46, -42, -28, -10, 8, + 23, 36, 50, 59, 56, 44, 26, 8, -13, -35, -56, -77, -89, -94, -92, -80, + -61, -39, -11, 14, 33, 50, 63, 77, 88, 89, 81, 67, 54, 38, 21, 1, + -23, -39, -50, -54, -53, -46, -42, -31, -17, 1, 17, 33, 46, 56, 56, 46, + 33, 16, -4, -24, -46, -67, -82, -92, -94, -87, -67, -45, -19, 4, 22, 43, + 62, 76, 87, 90, 87, 76, 59, 40, 20, 1, -22, -40, -55, -62, -58, -50, + -40, -29, -17, -3, 14, 33, 49, 59, 58, 49, 35, 21, 2, -17, -39, -59, + -76, -90, -93, -86, -70, -49, -29, -8, 12, 33, 57, 75, 84, 87, 84, 78, + 65, 47, 28, 6, -18, -39, -58, -65, -64, -57, -44, -33, -22, -10, 6, 26, + 44, 56, 56, 48, 40, 27, 11, -8, -30, -49, -65, -80, -86, -87, -72, -51, + -31, -13, 5, 24, 48, 70, 81, 86, 83, 79, 69, 51, 30, 8, -16, -37, + -55, -65, -67, -61, -48, -36, -21, -10, 5, 22, 40, 55, 58, 53, 43, 31, + 16, -2, -23, -45, -60, -74, -82, -86, -75, -56, -36, -16, 1, 21, 44, 65, + 81, 88, 85, 81, 72, 54, 33, 8, -18, -41, -58, -71, -74, -70, -56, -41, + -23, -6, 8, 23, 38, 53, 60, 59, 50, 37, 22, 1, -20, -41, -56, -69, + -79, -83, -78, -62, -42, -20, 2, 22, 41, 59, 77, 86, 87, 79, 67, 50, + 31, 10, -15, -36, -52, -63, -69, -69, -59, -41, -23, -9, 4, 15, 29, 44, + 55, 56, 53, 43, 27, 12, -8, -27, -44, -57, -68, -78, -77, -67, -48, -29, + -12, 12, 32, 52, 70, 79, 84, 82, 73, 59, 38, 15, -9, -33, -52, -63, + -71, -72, -66, -50, -30, -13, 2, 12, 27, 42, 50, 54, 54, 46, 34, 19, + -2, -19, -35, -47, -61, -71, -72, -66, -51, -36, -19, 5, 27, 46, 63, 74, + 79, 79, 70, 58, 41, 21, 3, -24, -44, -58, -66, -66, -65, -52, -36, -22, + -10, 4, 18, 34, 43, 49, 52, 48, 43, 31, 14, -4, -21, -35, -51, -61, + -66, -64, -56, -43, -29, -8, 16, 37, 54, 67, 72, 74, 70, 61, 46, 27, + 7, -19, -40, -56, -62, -62, -63, -55, -43, -26, -10, 3, 13, 26, 38, 44, + 47, 43, 39, 30, 19, 5, -12, -24, -40, -47, -51, -53, -51, -44, -32, -14, + 6, 24, 41, 54, 61, 63, 61, 56, 47, 32, 13, -9, -31, -46, -56, -53, + -54, -54, -48, -37, -18, -3, 8, 17, 27, 33, 38, 39, 39, 37, 30, 18, + 1, -16, -29, -35, -39, -42, -47, -47, -39, -22, -3, 14, 29, 42, 51, 57, + 56, 54, 45, 36, 20, -2, -23, -41, -50, -51, -52, -53, -51, -42, -27, -8, + 5, 12, 19, 28, 35, 40, 39, 40, 37, 28, 12, -7, -23, -28, -30, -37, + -43, -49, -45, -32, -15, 3, 19, 34, 45, 49, 49, 51, 47, 41, 26, 6, + -18, -34, -43, -45, -45, -48, -51, -49, -33, -15, -2, 8, 12, 19, 26, 33, + 38, 38, 38, 34, 25, 8, -11, -19, -20, -23, -32, -43, -48, -41, -24, -8, + 10, 21, 31, 38, 43, 47, 48, 45, 34, 16, -9, -31, -41, -42, -42, -46, + -52, -52, -40, -23, -6, 6, 11, 17, 24, 30, 35, 38, 39, 40, 29, 14, + -3, -14, -14, -15, -24, -36, -47, -45, -33, -15, 3, 14, 23, 29, 35, 39, + 44, 45, 38, 22, -3, -26, -38, -37, -37, -41, -50, -56, -45, -26, -8, 5, + 12, 16, 22, 27, 32, 39, 41, 41, 33, 17, 1, -9, -8, -8, -16, -30, + -41, -45, -35, -21, -5, 10, 18, 24, 28, 31, 38, 42, 39, 25, 2, -23, + -36, -36, -37, -39, -47, -53, -47, -31, -11, 3, 12, 16, 23, 27, 32, 37, + 40, 41, 33, 18, 2, -7, -8, -6, -10, -23, -36, -41, -35, -20, -6, 7, + 14, 17, 24, 29, 36, 42, 40, 28, 5, -20, -35, -38, -38, -39, -45, -51, + -46, -33, -15, 2, 13, 22, 27, 28, 27, 30, 37, 41, 35, 20, 5, -4, + -4, -2, -3, -13, -28, -35, -32, -23, -10, 3, 11, 14, 14, 20, 28, 37, + 40, 27, 7, -16, -31, -36, -37, -36, -41, -44, -45, -35, -18, 1, 12, 19, + 25, 26, 27, 31, 34, 39, 34, 20, 8, 0, 0, 1, 0, -9, -23, -33, + -34, -24, -10, 2, 8, 8, 10, 16, 27, 34, 35, 27, 10, -10, -27, -35, + -35, -34, -39, -46, -47, -38, -22, -3, 10, 19, 26, 31, 32, 32, 35, 41, + 39, 25, 9, -2, -3, -2, -2, -7, -19, -30, -33, -26, -14, -3, 6, 6, + 7, 12, 26, 37, 37, 26, 10, -8, -25, -35, -39, -39, -42, -47, -49, -42, + -27, -4, 12, 20, 29, 33, 36, 35, 35, 38, 37, 27, 10, -3, -6, -3, + -2, -7, -16, -24, -28, -24, -13, -4, 4, 5, 7, 9, 19, 30, 33, 28, + 12, -6, -24, -35, -40, -39, -42, -47, -47, -41, -26, -8, 10, 22, 31, 36, + 41, 39, 34, 33, 33, 29, 15, 2, -7, -8, -6, -6, -10, -18, -24, -24, + -15, -5, 6, 7, 7, 10, 17, 23, 23, 18, 9, -7, -23, -36, -42, -41, + -41, -45, -45, -39, -28, -11, 7, 21, 31, 36, 39, 39, 34, 31, 33, 29, + 19, 7, -5, -6, -6, -4, -6, -13, -17, -20, -16, -8, 1, 6, 7, 7, + 11, 16, 20, 18, 9, -7, -24, -37, -43, -42, -42, -42, -45, -41, -28, -11, + 7, 19, 28, 35, 40, 42, 38, 33, 29, 27, 21, 10, -2, -8, -8, -6, + -8, -11, -13, -16, -14, -8, 1, 5, 8, 9, 15, 19, 20, 18, 9, -4, + -18, -34, -42, -46, -47, -45, -47, -45, -36, -20, 0, 13, 26, 36, 45, 48, + 42, 35, 29, 28, 26, 20, 6, -6, -10, -10, -6, -7, -8, -10, -14, -10, + -7, 0, 6, 8, 13, 14, 16, 13, 7, -3, -13, -27, -37, -44, -49, -44, + -42, -40, -37, -25, -9, 9, 23, 31, 41, 44, 44, 37, 30, 27, 28, 27, + 15, 2, -7, -9, -6, -7, -9, -8, -13, -12, -8, -3, 4, 9, 13, 14, + 14, 11, 6, 0, -9, -23, -34, -43, -49, -46, -42, -40, -35, -29, -13, 3, + 19, 31, 41, 45, 43, 37, 31, 29, 30, 28, 19, 4, -5, -7, -7, -5, + -8, -7, -9, -11, -9, -4, 0, 6, 12, 14, 13, 9, 5, -3, -9, -19, + -28, -37, -48, -48, -45, -39, -34, -30, -18, -5, 12, 23, 34, 42, 44, 39, + 34, 32, 31, 33, 30, 18, 8, 1, -5, -6, -5, -5, -8, -13, -16, -14, + -7, 2, 7, 11, 10, 7, 4, -2, -7, -12, -22, -32, -45, -50, -45, -38, + -33, -30, -24, -13, 2, 20, 31, 39, 43, 42, 38, 36, 33, 33, 33, 24, + 14, 1, -8, -9, -7, -4, -5, -11, -16, -16, -11, -4, 2, 9, 8, 7, + 3, -3, -6, -9, -15, -24, -38, -47, -48, -42, -35, -32, -29, -21, -9, 11, + 27, 35, 42, 42, 42, 40, 40, 38, 36, 30, 19, 8, -4, -9, -8, -5, + -5, -12, -18, -20, -15, -5, -2, 3, 4, 5, 6, 1, -3, -8, -12, -19, + -31, -43, -47, -43, -36, -35, -36, -32, -19, 2, 19, 30, 38, 42, 46, 49, + 50, 47, 43, 39, 28, 16, 1, -10, -13, -11, -9, -14, -21, -25, -20, -10, + -4, 1, 3, 4, 7, 4, -3, -7, -7, -10, -23, -38, -47, -46, -41, -37, + -38, -37, -27, -11, 11, 24, 33, 38, 45, 50, 53, 52, 48, 43, 37, 25, + 10, -3, -11, -11, -11, -13, -20, -27, -29, -22, -14, -7, -2, 2, 6, 3, + -2, -3, 0, 0, -11, -28, -41, -45, -39, -35, -36, -39, -37, -24, -7, 11, + 22, 32, 41, 51, 55, 56, 54, 53, 50, 40, 23, 6, -5, -10, -11, -14, + -20, -28, -34, -33, -25, -16, -10, -5, 0, 0, 1, 2, 4, 5, -4, -16, + -29, -35, -37, -37, -35, -39, -39, -32, -19, 0, 13, 23, 36, 46, 54, 58, + 57, 59, 56, 47, 33, 16, 3, -5, -9, -11, -19, -29, -36, -39, -33, -26, + -18, -12, -7, -5, -2, 4, 11, 15, 10, -3, -18, -29, -32, -35, -36, -41, + -44, -40, -30, -18, 0, 13, 28, 41, 50, 59, 63, 66, 66, 60, 44, 26, + 11, 2, -6, -12, -19, -29, -38, -44, -41, -33, -25, -16, -9, -8, -6, 1, + 11, 18, 16, 8, -6, -17, -27, -32, -36, -39, -43, -44, -37, -30, -12, 8, + 26, 39, 46, 56, 64, 70, 72, 66, 51, 36, 18, 7, -4, -11, -18, -29, + -42, -50, -51, -45, -35, -23, -14, -10, -9, 0, 14, 27, 29, 20, 7, -5, + -15, -23, -30, -38, -45, -50, -49, -43, -30, -9, 13, 31, 41, 52, 65, 75, + 79, 77, 66, 50, 30, 13, 3, -6, -14, -26, -41, -53, -57, -54, -44, -32, + -23, -17, -13, -5, 10, 24, 31, 28, 20, 9, -5, -17, -26, -35, -40, -48, + -54, -53, -44, -23, 0, 21, 35, 46, 60, 73, 81, 83, 77, 60, 42, 25, + 11, 1, -11, -25, -42, -57, -64, -62, -54, -43, -33, -24, -17, -6, 9, 23, + 37, 37, 33, 19, 6, -9, -20, -30, -41, -49, -57, -59, -54, -38, -16, 10, + 31, 46, 58, 70, 78, 85, 84, 73, 54, 32, 16, 5, -5, -22, -41, -60, + -72, -71, -66, -54, -43, -30, -19, -6, 10, 25, 41, 47, 43, 32, 20, 7, + -10, -25, -40, -52, -61, -68, -65, -54, -34, -11, 16, 39, 57, 72, 80, 88, + 91, 83, 67, 46, 28, 13, 1, -18, -40, -62, -77, -77, -70, -63, -54, -43, + -30, -12, 7, 25, 40, 51, 51, 42, 31, 19, 3, -13, -32, -48, -60, -68, + -71, -63, -49, -28, -2, 23, 46, 66, 77, 86, 92, 89, 82, 62, 43, 22, + 7, -12, -39, -59, -74, -80, -78, -72, -63, -50, -35, -17, 5, 22, 35, 45, + 49, 49, 42, 31, 13, -7, -25, -38, -49, -59, -66, -65, -57, -42, -20, 8, + 34, 55, 69, 79, 84, 84, 84, 77, 64, 42, 18, -6, -29, -49, -69, -82, + -87, -87, -78, -66, -48, -27, -4, 17, 33, 47, 56, 60, 58, 49, 31, 8, + -18, -36, -47, -57, -67, -75, -74, -60, -36, -3, 25, 48, 65, 76, 83, 87, + 90, 88, 77, 52, 24, -4, -26, -42, -61, -77, -91, -94, -85, -70, -54, -34, + -11, 12, 30, 44, 56, 63, 66, 61, 43, 19, -8, -27, -39, -49, -62, -74, + -80, -71, -49, -20, 9, 34, 56, 70, 79, 86, 93, 96, 91, 70, 41, 11, + -18, -39, -58, -77, -91, -99, -95, -83, -65, -42, -17, 7, 27, 43, 57, 66, + 69, 67, 55, 32, 5, -21, -32, -42, -56, -73, -84, -79, -60, -33, -5, 21, + 44, 61, 72, 80, 92, 100, 99, 82, 54, 23, -10, -31, -51, -71, -87, -101, + -101, -92, -76, -49, -24, 1, 21, 37, 52, 66, 72, 72, 64, 44, 18, -7, + -23, -31, -45, -64, -79, -83, -71, -46, -18, 7, 27, 46, 62, 72, 85, 97, + 100, 92, 65, 35, 2, -22, -40, -60, -78, -92, -100, -96, -82, -59, -29, -6, + 15, 28, 44, 57, 65, 67, 65, 49, 27, 2, -17, -23, -35, -53, -70, -79, + -73, -52, -27, -4, 16, 35, 54, 65, 77, 88, 95, 93, 73, 44, 12, -17, + -38, -54, -74, -86, -97, -98, -89, -69, -37, -11, 9, 27, 42, 56, 65, 68, + 71, 59, 39, 13, -9, -20, -30, -45, -62, -74, -75, -60, -41, -18, 3, 23, + 43, 60, 74, 83, 91, 91, 78, 52, 22, -8, -30, -46, -66, -82, -90, -92, + -85, -70, -44, -17, 5, 22, 33, 45, 56, 60, 63, 56, 39, 21, 5, -9, + -20, -33, -49, -62, -70, -62, -47, -28, -9, 11, 29, 47, 60, 73, 83, 87, + 81, 62, 32, 4, -21, -39, -60, -78, -88, -90, -86, -73, -55, -28, -2, 18, + 30, 42, 50, 57, 58, 53, 44, 27, 15, 4, -10, -24, -40, -53, -59, -57, + -49, -38, -21, -3, 17, 34, 49, 62, 75, 81, 76, 63, 39, 15, -11, -31, + -50, -69, -79, -84, -82, -73, -57, -34, -7, 12, 26, 35, 42, 50, 56, 53, + 42, 31, 20, 13, 1, -16, -30, -43, -50, -51, -49, -42, -28, -11, 7, 23, + 38, 52, 65, 75, 73, 62, 43, 20, -2, -24, -43, -60, -69, -74, -74, -69, + -59, -42, -19, 2, 19, 27, 34, 41, 48, 50, 45, 39, 33, 25, 13, -3, + -18, -32, -42, -47, -49, -47, -40, -27, -8, 11, 28, 43, 57, 69, 73, 65, + 50, 31, 8, -16, -36, -53, -63, -70, -72, -70, -62, -46, -25, -6, 11, 23, + 30, 38, 45, 49, 50, 46, 42, 33, 22, 6, -13, -25, -37, -43, -48, -50, + -45, -35, -18, 2, 21, 39, 51, 61, 64, 63, 53, 38, 19, -6, -30, -49, + -59, -63, -65, -66, -64, -52, -31, -14, 2, 13, 25, 35, 42, 46, 46, 47, + 48, 44, 33, 15, -6, -21, -32, -37, -42, -48, -46, -39, -26, -8, 12, 31, + 45, 55, 58, 57, 51, 39, 22, 2, -21, -39, -49, -56, -59, -62, -59, -52, + -38, -22, -9, 5, 16, 25, 32, 40, 46, 51, 54, 52, 40, 24, 5, -11, + -20, -28, -35, -44, -48, -43, -33, -17, 0, 18, 32, 44, 48, 49, 48, 40, + 28, 11, -10, -26, -37, -45, -52, -58, -57, -51, -41, -29, -19, -10, 3, 15, + 27, 36, 40, 50, 59, 60, 51, 33, 15, 2, -11, -21, -34, -45, -49, -45, + -36, -25, -11, 8, 26, 38, 43, 42, 41, 39, 31, 16, -5, -24, -31, -37, + -43, -51, -54, -49, -40, -31, -24, -13, -3, 12, 22, 29, 33, 43, 55, 60, + 53, 37, 18, 5, -4, -12, -23, -35, -44, -42, -35, -26, -15, -2, 15, 26, + 33, 31, 31, 29, 28, 21, 6, -13, -27, -30, -37, -44, -48, -45, -39, -34, + -28, -18, -8, 4, 17, 23, 31, 40, 51, 58, 56, 42, 25, 12, 2, -7, + -16, -27, -36, -39, -37, -31, -21, -12, 3, 14, 21, 25, 23, 23, 25, 23, + 11, -4, -16, -21, -26, -34, -39, -40, -34, -31, -30, -23, -17, -3, 9, 16, + 23, 31, 42, 54, 57, 49, 29, 14, 7, 4, -3, -15, -26, -32, -32, -31, + -24, -16, -5, 5, 8, 10, 9, 10, 16, 19, 14, 4, -8, -14, -16, -21, + -29, -34, -33, -30, -29, -26, -20, -10, 2, 11, 20, 28, 40, 51, 55, 51, + 33, 17, 9, 6, 4, -9, -20, -28, -32, -29, -25, -20, -11, -2, 3, 4, + 1, 6, 12, 18, 16, 8, -5, -10, -14, -17, -20, -23, -25, -26, -28, -26, + -21, -12, -2, 6, 13, 20, 29, 40, 48, 48, 37, 23, 13, 8, 7, 3, + -6, -15, -22, -24, -24, -21, -16, -10, -6, -11, -15, -10, 1, 12, 15, 9, + 4, 3, 1, -5, -11, -18, -18, -22, -25, -29, -27, -19, -7, 4, 10, 14, + 21, 35, 46, 48, 40, 27, 16, 13, 11, 11, 5, -5, -14, -19, -21, -24, + -19, -14, -13, -17, -21, -21, -11, 1, 11, 12, 5, 3, 2, 5, 6, 0, + -6, -16, -20, -25, -26, -20, -12, -4, 1, 5, 11, 25, 38, 46, 41, 33, + 21, 17, 15, 15, 14, 8, -3, -14, -23, -27, -26, -21, -20, -22, -26, -25, + -20, -7, 5, 10, 10, 8, 5, 6, 6, 5, 1, -7, -14, -20, -23, -21, + -17, -11, -4, 2, 7, 17, 29, 38, 40, 37, 30, 23, 21, 20, 17, 14, + 5, -6, -19, -26, -29, -25, -24, -27, -28, -28, -26, -18, -4, 6, 9, 8, + 4, 5, 10, 12, 11, 3, -8, -15, -18, -18, -15, -11, -10, -5, 1, 8, + 16, 26, 35, 35, 31, 24, 22, 21, 22, 21, 16, 5, -12, -24, -30, -31, + -29, -31, -32, -31, -32, -22, -12, 0, 7, 11, 12, 10, 11, 15, 13, 10, + 2, -10, -13, -16, -17, -14, -14, -12, -6, 0, 10, 20, 26, 32, 30, 29, + 27, 26, 28, 26, 22, 13, -2, -16, -25, -30, -32, -33, -35, -35, -34, -28, + -19, -12, -5, 1, 5, 9, 11, 16, 17, 18, 11, 3, -4, -10, -12, -13, + -12, -13, -14, -10, -4, 8, 20, 27, 31, 31, 28, 29, 31, 30, 26, 17, + 5, -9, -23, -32, -37, -36, -34, -35, -34, -32, -24, -16, -7, 2, 4, 6, + 10, 16, 17, 15, 12, 8, 3, -5, -11, -11, -10, -11, -12, -11, -5, 3, + 13, 22, 30, 32, 27, 25, 25, 28, 27, 19, 7, -8, -22, -31, -34, -32, + -30, -28, -31, -31, -29, -21, -12, -4, 1, 1, 3, 10, 16, 18, 18, 14, + 12, 3, -5, -8, -7, -8, -10, -12, -12, -5, 6, 16, 26, 30, 29, 24, + 25, 26, 29, 23, 13, -2, -16, -26, -32, -33, -30, -30, -30, -30, -29, -25, + -18, -12, -5, -2, 2, 8, 14, 18, 16, 18, 14, 10, 4, 0, -5, -4, + -7, -9, -14, -10, -3, 9, 19, 26, 26, 23, 23, 26, 29, 28, 21, 7, + -10, -19, -25, -26, -27, -27, -29, -30, -32, -31, -27, -19, -13, -9, -7, 0, + 9, 18, 24, 26, 21, 13, 9, 8, 4, -2, -6, -9, -11, -11, -7, 4, + 16, 24, 26, 21, 19, 22, 26, 29, 23, 7, -10, -17, -19, -19, -23, -25, + -25, -25, -26, -26, -29, -26, -17, -14, -9, -7, 1, 12, 21, 26, 23, 18, + 13, 11, 11, 6, -4, -6, -10, -10, -9, -2, 9, 20, 25, 23, 18, 18, + 23, 26, 24, 10, -5, -13, -17, -14, -15, -17, -20, -24, -25, -29, -31, -32, + -28, -22, -16, -13, -8, 2, 14, 25, 27, 27, 22, 17, 15, 13, 10, 5, + -3, -6, -8, -6, 1, 11, 18, 20, 13, 11, 15, 19, 20, 14, 4, -4, + -12, -12, -12, -12, -14, -17, -23, -30, -35, -37, -31, -26, -20, -16, -12, -4, + 9, 22, 28, 26, 22, 17, 14, 15, 11, 8, 6, 2, 0, -2, 4, 11, + 16, 16, 12, 7, 8, 13, 13, 10, 1, -5, -8, -8, -8, -7, -7, -10, + -20, -26, -34, -36, -33, -31, -29, -25, -19, -12, 4, 18, 27, 28, 23, 22, + 18, 19, 17, 14, 9, 7, 4, 0, 2, 8, 14, 16, 12, 2, 0, 2, + 5, 6, 2, -4, -7, -6, -2, -2, -3, -5, -11, -19, -28, -37, -37, -37, + -34, -29, -24, -18, -8, 7, 20, 25, 25, 25, 22, 21, 21, 21, 19, 15, + 11, 6, 6, 6, 10, 11, 6, -2, -5, -5, -2, 0, 0, 0, -4, 0, + 2, 4, 2, -2, -8, -16, -25, -34, -39, -42, -39, -33, -26, -21, -16, -4, + 11, 22, 25, 27, 25, 23, 23, 24, 25, 22, 17, 13, 10, 9, 12, 10, + 4, -5, -12, -12, -11, -9, -8, -6, -5, 1, 4, 8, 10, 7, 4, -7, + -18, -26, -34, -39, -43, -42, -34, -28, -22, -13, 2, 14, 18, 21, 23, 27, + 30, 32, 31, 28, 23, 20, 20, 15, 14, 10, 2, -5, -13, -15, -16, -16, + -12, -12, -5, 1, 5, 8, 8, 10, 8, 0, -13, -23, -27, -33, -40, -44, + -41, -32, -24, -17, -6, 3, 9, 17, 22, 25, 29, 34, 39, 36, 32, 26, + 25, 23, 19, 11, 1, -9, -16, -18, -17, -19, -21, -17, -8, 0, 4, 7, + 8, 10, 11, 6, -4, -13, -21, -25, -35, -40, -41, -37, -26, -21, -13, -8, + -3, 6, 15, 23, 27, 35, 40, 41, 38, 33, 31, 29, 24, 16, 5, -5, + -16, -23, -23, -23, -18, -14, -6, 2, 3, 4, 7, 11, 13, 7, -5, -13, + -21, -25, -32, -40, -42, -37, -28, -21, -14, -13, -9, 1, 11, 22, 27, 33, + 39, 43, 42, 41, 33, 29, 25, 18, 7, -6, -17, -25, -24, -23, -21, -16, + -9, 2, 6, 5, 5, 10, 15, 12, 3, -8, -16, -22, -29, -39, -44, -42, + -34, -27, -22, -21, -17, -8, 4, 19, 29, 40, 48, 53, 51, 49, 43, 38, + 28, 19, 6, -9, -19, -27, -30, -30, -24, -16, -10, -3, 3, 6, 5, 6, + 9, 11, 7, 2, -7, -16, -25, -34, -37, -37, -33, -31, -28, -27, -24, -20, + -10, 8, 22, 35, 46, 52, 53, 54, 49, 46, 37, 23, 9, -7, -18, -24, + -30, -32, -28, -22, -12, -5, 1, 6, 4, 8, 9, 11, 9, 3, -3, -13, + -21, -32, -37, -38, -35, -34, -32, -32, -32, -27, -14, 5, 24, 38, 48, 55, + 56, 56, 54, 50, 40, 23, 4, -10, -18, -24, -26, -29, -29, -24, -17, -5, + 2, 9, 9, 6, 6, 7, 12, 11, 6, -7, -18, -30, -36, -36, -37, -35, + -38, -40, -41, -36, -24, -2, 20, 35, 47, 55, 60, 62, 62, 61, 47, 26, + 7, -12, -18, -22, -24, -28, -33, -31, -24, -12, -2, 7, 9, 5, 4, 5, + 11, 14, 13, 7, -8, -24, -37, -41, -38, -34, -37, -44, -50, -46, -33, -10, + 16, 36, 49, 57, 61, 64, 66, 65, 55, 34, 11, -14, -24, -26, -26, -24, + -30, -34, -33, -24, -7, 5, 12, 10, 5, 6, 9, 16, 22, 21, 10, -10, + -32, -45, -44, -38, -38, -47, -61, -60, -48, -21, 11, 34, 51, 60, 63, 66, + 70, 69, 63, 45, 18, -10, -27, -27, -23, -20, -28, -36, -37, -32, -17, -2, + 8, 9, 5, 6, 8, 15, 24, 30, 25, 5, -22, -41, -44, -40, -38, -50, + -64, -72, -62, -37, -3, 29, 52, 62, 66, 69, 73, 78, 72, 54, 26, -5, + -25, -32, -29, -24, -27, -34, -37, -36, -26, -11, 5, 15, 15, 11, 9, 15, + 26, 35, 33, 14, -14, -37, -49, -47, -45, -51, -63, -72, -66, -42, -10, 22, + 49, 64, 69, 69, 70, 75, 73, 59, 34, 4, -20, -30, -30, -25, -24, -29, + -36, -40, -35, -22, -2, 16, 20, 17, 14, 15, 27, 39, 41, 27, -4, -32, + -48, -54, -53, -59, -65, -73, -71, -55, -23, 16, 49, 67, 70, 68, 71, 77, + 78, 65, 40, 10, -17, -31, -34, -28, -24, -26, -31, -40, -40, -30, -10, 10, + 21, 18, 15, 16, 26, 40, 48, 40, 13, -20, -44, -55, -61, -63, -69, -76, + -76, -63, -35, 6, 41, 66, 75, 71, 71, 75, 77, 67, 44, 17, -10, -25, + -34, -35, -29, -27, -28, -35, -40, -35, -18, 1, 16, 21, 20, 19, 25, 38, + 47, 43, 23, -9, -34, -50, -59, -65, -72, -76, -74, -66, -43, -9, 27, 58, + 71, 69, 70, 71, 73, 67, 48, 25, 2, -18, -28, -33, -29, -25, -25, -31, + -39, -41, -28, -10, 8, 19, 20, 23, 27, 36, 45, 45, 31, 4, -22, -45, + -58, -67, -74, -75, -73, -66, -50, -21, 16, 49, 67, 73, 72, 72, 74, 69, + 53, 33, 9, -11, -25, -34, -35, -31, -27, -30, -38, -43, -33, -16, 6, 18, + 24, 27, 30, 38, 45, 46, 34, 10, -16, -40, -61, -70, -77, -76, -72, -66, + -52, -31, 2, 36, 60, 71, 72, 69, 71, 68, 57, 44, 20, 2, -17, -32, + -36, -33, -31, -31, -40, -46, -41, -29, -5, 16, 27, 34, 35, 41, 49, 51, + 41, 17, -11, -34, -56, -71, -79, -80, -76, -68, -57, -36, -10, 21, 48, 64, + 71, 71, 73, 69, 61, 48, 32, 11, -5, -21, -31, -34, -34, -37, -43, -48, + -45, -34, -14, 8, 25, 34, 41, 43, 49, 51, 43, 26, -2, -27, -49, -65, + -74, -77, -74, -70, -58, -42, -20, 9, 38, 56, 64, 67, 69, 71, 66, 53, + 37, 16, 1, -15, -30, -33, -39, -38, -41, -45, -42, -35, -15, 7, 25, 36, + 41, 45, 49, 49, 40, 23, 1, -20, -41, -59, -71, -75, -73, -65, -57, -45, + -28, -6, 22, 42, 56, 63, 67, 71, 70, 59, 44, 28, 12, -3, -19, -32, + -40, -41, -46, -47, -46, -37, -20, -2, 20, 34, 45, 48, 52, 53, 42, 26, + 4, -15, -35, -51, -65, -70, -70, -68, -61, -50, -34, -15, 9, 28, 45, 54, + 64, 71, 72, 67, 53, 40, 24, 8, -10, -27, -37, -41, -49, -53, -53, -42, + -25, -8, 14, 31, 43, 52, 56, 56, 46, 30, 11, -8, -26, -43, -59, -70, + -69, -68, -62, -55, -44, -25, -4, 17, 36, 48, 62, 69, 69, 67, 57, 47, + 33, 17, -2, -21, -33, -41, -47, -52, -53, -43, -25, -10, 9, 23, 36, 46, + 52, 54, 47, 31, 14, -4, -19, -32, -49, -57, -62, -60, -57, -58, -51, -39, + -19, 6, 23, 38, 51, 60, 68, 71, 67, 58, 44, 27, 7, -17, -32, -41, + -47, -52, -54, -46, -31, -12, 7, 22, 35, 45, 51, 53, 46, 33, 18, 2, + -12, -26, -42, -55, -61, -60, -56, -57, -55, -46, -29, -8, 10, 27, 42, 55, + 65, 70, 69, 61, 49, 34, 16, -5, -23, -36, -45, -51, -54, -50, -35, -17, + 3, 17, 29, 37, 44, 51, 47, 39, 21, 6, -8, -20, -31, -44, -52, -58, + -60, -58, -58, -51, -39, -22, -4, 14, 31, 48, 62, 70, 69, 65, 57, 45, + 28, 7, -15, -31, -44, -50, -53, -50, -39, -24, -6, 11, 24, 33, 43, 46, + 45, 35, 25, 14, 1, -13, -23, -35, -44, -53, -57, -59, -59, -57, -47, -33, + -15, 3, 21, 39, 56, 69, 72, 69, 60, 49, 36, 17, -5, -25, -42, -52, + -52, -48, -40, -26, -9, 9, 20, 29, 34, 39, 40, 34, 25, 16, 6, -6, + -16, -27, -34, -44, -50, -55, -58, -57, -52, -41, -27, -11, 11, 31, 51, 67, + 70, 68, 61, 53, 43, 30, 7, -14, -35, -49, -54, -50, -40, -26, -13, -2, + 9, 22, 30, 38, 41, 36, 28, 20, 12, 4, -5, -15, -26, -41, -52, -58, + -60, -60, -59, -55, -41, -25, -5, 19, 42, 62, 74, 75, 70, 63, 55, 43, + 22, -3, -24, -42, -51, -50, -45, -32, -22, -14, -2, 14, 28, 35, 34, 33, + 30, 25, 21, 11, 4, -6, -18, -32, -46, -56, -61, -61, -62, -60, -51, -39, + -16, 11, 37, 58, 70, 75, 72, 67, 58, 46, 31, 10, -17, -35, -48, -49, + -41, -28, -17, -14, -7, 4, 18, 28, 32, 29, 27, 21, 19, 16, 7, 2, + -11, -22, -35, -48, -57, -61, -60, -60, -56, -47, -30, -5, 23, 48, 63, 72, + 75, 71, 64, 53, 39, 20, -2, -22, -40, -48, -45, -34, -21, -17, -10, -4, + 10, 22, 27, 28, 29, 26, 26, 22, 14, 7, -3, -14, -30, -46, -59, -65, + -65, -65, -64, -56, -41, -17, 15, 42, 62, 73, 77, 75, 69, 57, 43, 25, + 6, -12, -31, -44, -46, -37, -24, -16, -11, -3, 6, 20, 24, 23, 24, 23, + 25, 23, 16, 9, 1, -10, -23, -41, -56, -63, -67, -67, -66, -59, -47, -25, + 3, 32, 54, 70, 75, 76, 70, 62, 47, 32, 15, -3, -21, -38, -44, -41, + -31, -21, -15, -11, -2, 8, 18, 24, 27, 28, 29, 29, 24, 17, 8, -2, + -17, -35, -54, -66, -73, -74, -71, -66, -55, -35, -6, 24, 50, 69, 77, 79, + 74, 63, 51, 38, 22, 2, -17, -35, -42, -39, -32, -24, -17, -11, -5, 6, + 13, 20, 28, 31, 33, 29, 23, 15, 10, 3, -12, -30, -51, -65, -73, -75, + -71, -67, -58, -41, -18, 11, 38, 60, 75, 77, 74, 64, 53, 42, 31, 15, + -7, -25, -38, -40, -37, -29, -24, -15, -11, -2, 9, 17, 28, 33, 36, 33, + 27, 18, 13, 4, -8, -26, -48, -65, -75, -76, -72, -68, -58, -43, -18, 11, + 37, 58, 72, 76, 73, 63, 51, 40, 28, 13, -6, -23, -35, -41, -40, -33, + -24, -16, -9, -2, 7, 18, 29, 38, 42, 38, 31, 21, 11, 3, -10, -26, + -47, -65, -75, -79, -75, -69, -58, -39, -19, 7, 33, 54, 71, 77, 75, 66, + 52, 39, 27, 15, -2, -22, -35, -41, -41, -36, -27, -17, -8, 1, 11, 22, + 33, 41, 47, 45, 35, 21, 11, 4, -7, -24, -46, -66, -77, -81, -79, -73, + -62, -44, -24, -2, 23, 47, 69, 79, 79, 70, 57, 45, 33, 20, 5, -18, + -36, -43, -41, -37, -32, -23, -14, -3, 8, 20, 34, 45, 53, 52, 41, 27, + 16, 7, -5, -24, -47, -69, -83, -86, -84, -74, -62, -44, -22, 1, 24, 47, + 66, 78, 76, 69, 57, 43, 31, 17, 5, -13, -33, -43, -46, -41, -31, -22, + -12, 0, 11, 24, 39, 49, 57, 58, 48, 30, 15, 4, -8, -26, -52, -74, + -86, -89, -83, -74, -60, -43, -21, 1, 22, 45, 65, 78, 79, 68, 54, 40, + 26, 17, 7, -9, -31, -45, -46, -40, -31, -21, -11, 0, 8, 21, 39, 51, + 60, 60, 52, 36, 19, 4, -9, -25, -49, -71, -87, -92, -89, -79, -63, -45, + -24, 0, 22, 43, 65, 75, 80, 70, 57, 44, 30, 16, 2, -14, -31, -46, + -52, -47, -35, -21, -9, 1, 12, 26, 44, 59, 68, 68, 59, 42, 22, 6, + -11, -29, -49, -72, -87, -96, -95, -86, -67, -46, -23, -4, 16, 38, 59, 76, + 82, 74, 61, 45, 31, 20, 3, -14, -30, -44, -51, -51, -41, -26, -11, 3, + 13, 25, 44, 61, 71, 72, 59, 45, 28, 9, -10, -33, -53, -70, -83, -93, + -96, -91, -74, -53, -27, -6, 15, 35, 53, 71, 80, 77, 66, 51, 34, 20, + 3, -15, -30, -45, -53, -55, -48, -32, -17, 1, 16, 29, 47, 62, 73, 77, + 67, 50, 30, 9, -10, -32, -55, -73, -86, -93, -94, -90, -76, -54, -27, -4, + 17, 32, 48, 64, 74, 78, 68, 55, 38, 17, 1, -15, -28, -39, -47, -52, + -49, -37, -21, -3, 16, 31, 46, 61, 70, 75, 70, 55, 36, 13, -9, -32, + -56, -72, -84, -89, -93, -91, -81, -61, -30, -5, 18, 32, 45, 58, 71, 76, + 70, 57, 40, 18, 1, -17, -28, -35, -45, -52, -50, -39, -25, -7, 15, 33, + 48, 60, 67, 73, 70, 60, 42, 19, -8, -34, -57, -69, -77, -83, -87, -92, + -85, -66, -39, -10, 12, 27, 39, 52, 62, 73, 72, 61, 46, 25, 4, -14, + -27, -34, -41, -46, -48, -43, -30, -11, 14, 38, 53, 63, 66, 69, 72, 65, + 48, 23, -4, -31, -56, -72, -81, -83, -87, -91, -87, -72, -46, -15, 11, 28, + 40, 50, 60, 71, 75, 69, 54, 32, 8, -13, -29, -39, -45, -48, -50, -48, + -40, -21, 9, 37, 57, 66, 71, 74, 75, 71, 55, 32, 2, -29, -55, -73, + -81, -84, -87, -89, -88, -75, -49, -19, 10, 29, 39, 48, 53, 62, 72, 68, + 58, 35, 9, -11, -27, -34, -39, -42, -44, -46, -41, -26, 5, 35, 56, 65, + 69, 72, 73, 72, 59, 37, 9, -22, -50, -71, -83, -83, -83, -86, -88, -81, + -55, -24, 5, 24, 37, 48, 54, 59, 64, 66, 59, 41, 17, -9, -27, -36, + -38, -39, -42, -45, -41, -28, -2, 28, 53, 65, 68, 71, 71, 70, 58, 40, + 16, -14, -46, -67, -79, -81, -80, -83, -87, -83, -64, -36, -4, 19, 35, 46, + 51, 58, 65, 69, 64, 49, 26, -2, -25, -38, -41, -39, -40, -43, -45, -33, + -8, 24, 52, 65, 72, 74, 72, 66, 55, 40, 20, -7, -38, -65, -80, -85, + -80, -82, -84, -82, -65, -38, -9, 13, 29, 41, 49, 57, 62, 64, 59, 48, + 29, 6, -19, -36, -39, -37, -35, -38, -39, -31, -11, 19, 47, 63, 70, 71, + 71, 65, 55, 38, 17, -4, -33, -58, -76, -83, -79, -79, -80, -82, -70, -46, + -19, 8, 25, 36, 43, 51, 59, 63, 62, 50, 34, 14, -9, -27, -35, -38, + -36, -38, -39, -30, -15, 10, 34, 52, 67, 73, 74, 68, 54, 37, 21, 2, + -21, -45, -68, -78, -81, -81, -80, -79, -70, -51, -28, -4, 17, 32, 40, 48, + 56, 59, 57, 46, 34, 18, 3, -20, -34, -39, -35, -31, -30, -26, -13, 8, + 31, 48, 61, 67, 69, 66, 53, 38, 16, -4, -23, -41, -58, -72, -78, -80, + -76, -74, -64, -50, -33, -8, 12, 28, 35, 41, 50, 57, 53, 44, 31, 20, + 10, -8, -24, -34, -34, -30, -25, -21, -13, 5, 22, 38, 52, 61, 66, 65, + 53, 36, 15, -4, -18, -33, -45, -61, -73, -79, -78, -72, -62, -49, -33, -13, + 3, 19, 29, 38, 48, 52, 49, 41, 29, 22, 14, 2, -11, -25, -27, -25, + -20, -15, -8, 4, 19, 30, 42, 53, 57, 61, 50, 32, 15, -7, -18, -27, + -37, -50, -65, -73, -72, -66, -57, -49, -37, -19, -3, 13, 23, 32, 41, 44, + 41, 35, 29, 26, 21, 10, -2, -13, -21, -18, -14, -8, -4, 3, 12, 21, + 29, 42, 51, 54, 49, 32, 14, -5, -15, -22, -28, -39, -55, -69, -68, -62, + -52, -44, -37, -25, -11, 4, 16, 24, 32, 37, 35, 28, 23, 23, 23, 18, + 8, -4, -12, -12, -8, -2, 5, 9, 14, 18, 23, 31, 41, 45, 43, 29, + 11, -8, -18, -23, -21, -29, -43, -60, -65, -58, -50, -39, -32, -26, -17, -6, + 8, 18, 25, 31, 29, 24, 17, 20, 24, 25, 19, 8, 0, -5, -3, 4, + 11, 13, 12, 14, 16, 22, 31, 38, 37, 27, 9, -11, -22, -24, -22, -25, + -36, -50, -57, -53, -46, -37, -30, -24, -17, -9, 1, 10, 16, 20, 19, 17, + 13, 14, 21, 24, 24, 19, 10, 8, 9, 13, 18, 20, 15, 12, 11, 14, + 21, 27, 30, 21, 8, -12, -23, -24, -22, -20, -29, -40, -49, -47, -41, -33, + -26, -23, -20, -16, -11, -2, 7, 12, 14, 14, 13, 14, 19, 26, 30, 26, + 20, 11, 11, 16, 21, 26, 22, 18, 15, 14, 15, 19, 20, 16, 4, -15, + -29, -32, -27, -21, -24, -34, -40, -41, -33, -28, -24, -21, -20, -15, -14, -10, + -5, 1, 7, 10, 10, 12, 18, 26, 36, 34, 27, 21, 17, 20, 23, 25, + 24, 19, 11, 10, 9, 12, 16, 14, 3, -16, -32, -34, -27, -19, -20, -27, + -34, -35, -31, -27, -22, -18, -18, -19, -19, -20, -15, -7, 2, 6, 8, 9, + 18, 26, 38, 41, 37, 28, 21, 23, 25, 27, 25, 20, 13, 7, 3, 5, + 9, 11, 4, -14, -31, -35, -29, -20, -18, -23, -26, -32, -29, -25, -23, -15, + -17, -18, -21, -25, -23, -15, -6, 0, 5, 6, 16, 25, 37, 45, 43, 36, + 27, 25, 28, 30, 29, 26, 16, 7, -2, -2, 2, 3, -2, -15, -31, -38, + -35, -23, -15, -15, -19, -23, -26, -23, -21, -15, -12, -18, -24, -27, -25, -19, + -9, -3, 2, 5, 12, 19, 32, 42, 45, 41, 31, 28, 31, 33, 37, 33, + 26, 14, 4, -2, -3, -3, -5, -18, -34, -43, -42, -31, -20, -18, -17, -19, + -18, -16, -13, -9, -8, -13, -22, -32, -32, -28, -19, -11, -6, -2, 7, 18, + 31, 42, 46, 46, 41, 36, 32, 35, 39, 39, 30, 17, 5, -3, -3, -3, + -7, -19, -32, -39, -41, -36, -26, -17, -12, -13, -18, -20, -14, -7, -6, -11, + -23, -32, -34, -28, -23, -15, -9, -2, 9, 17, 28, 37, 44, 48, 45, 38, + 32, 35, 41, 45, 37, 23, 10, 1, -3, -5, -8, -20, -35, -44, -44, -42, + -34, -24, -14, -10, -12, -14, -11, -6, -2, -5, -15, -25, -32, -29, -24, -19, + -15, -10, 1, 10, 20, 31, 40, 45, 48, 43, 39, 39, 45, 51, 43, 28, + 15, 2, -4, -8, -13, -20, -34, -42, -45, -45, -36, -26, -13, -8, -11, -13, + -8, -2, 1, -4, -13, -22, -30, -33, -28, -25, -18, -12, -5, 3, 13, 25, + 37, 46, 47, 45, 40, 41, 47, 53, 49, 35, 21, 10, 2, -6, -11, -22, + -32, -43, -50, -50, -47, -34, -17, -9, -9, -12, -9, 3, 7, 4, -8, -18, + -25, -31, -31, -27, -21, -16, -11, -8, 2, 17, 31, 45, 47, 44, 40, 43, + 54, 60, 58, 42, 26, 14, 4, -5, -14, -26, -37, -47, -54, -53, -49, -38, + -22, -13, -9, -7, -3, 6, 11, 6, -5, -14, -22, -28, -31, -30, -29, -24, + -18, -15, -2, 14, 29, 42, 45, 47, 45, 48, 56, 63, 59, 46, 29, 17, + 5, -4, -11, -23, -36, -49, -53, -52, -48, -40, -29, -21, -16, -11, -2, 5, + 6, 3, -5, -10, -13, -17, -21, -25, -26, -23, -19, -15, -8, 5, 20, 31, + 38, 42, 41, 46, 55, 62, 63, 50, 36, 24, 12, 5, -7, -20, -33, -46, + -51, -51, -48, -40, -33, -27, -20, -15, 0, 9, 7, 1, -6, -10, -11, -16, + -22, -25, -30, -28, -25, -21, -11, 2, 17, 28, 32, 41, 47, 55, 64, 66, + 64, 54, 41, 32, 19, 4, -9, -24, -37, -48, -54, -55, -51, -41, -33, -29, + -24, -15, 0, 13, 14, 8, 1, -5, -6, -10, -17, -24, -30, -32, -33, -32, + -22, -9, 9, 21, 25, 35, 45, 56, 67, 71, 71, 63, 49, 37, 25, 11, + -5, -19, -32, -45, -54, -59, -54, -43, -36, -31, -27, -18, -3, 11, 13, 9, + 2, -3, -6, -9, -13, -20, -25, -29, -33, -30, -23, -9, 2, 11, 19, 28, + 40, 51, 63, 68, 71, 66, 55, 44, 31, 16, 1, -15, -30, -41, -50, -57, + -56, -46, -37, -32, -30, -21, -7, 8, 17, 12, 5, 3, -2, -6, -11, -19, + -23, -27, -33, -34, -28, -19, -6, 3, 13, 24, 38, 51, 62, 70, 72, 68, + 60, 48, 38, 22, 6, -13, -27, -39, -46, -53, -52, -48, -42, -37, -36, -25, + -9, 4, 11, 9, 7, 8, 6, 2, -6, -13, -20, -24, -28, -31, -30, -27, + -19, -10, 4, 19, 33, 45, 57, 67, 74, 74, 70, 60, 47, 31, 10, -8, + -25, -36, -42, -51, -56, -56, -51, -40, -35, -28, -16, -4, 7, 7, 10, 12, + 13, 11, 3, -8, -18, -21, -25, -29, -33, -33, -30, -20, -8, 11, 27, 42, + 54, 64, 72, 77, 76, 69, 56, 34, 14, -5, -20, -32, -43, -50, -57, -59, + -57, -47, -39, -31, -17, -5, 6, 8, 9, 17, 19, 16, 5, -9, -13, -18, + -21, -26, -33, -37, -35, -28, -15, 1, 18, 34, 47, 58, 68, 76, 77, 76, + 65, 47, 25, 6, -12, -24, -37, -49, -57, -62, -64, -58, -50, -40, -24, -12, + 3, 9, 13, 22, 26, 26, 17, 4, -9, -21, -25, -30, -36, -41, -44, -41, + -27, -8, 12, 31, 44, 57, 68, 77, 81, 80, 72, 56, 34, 12, -6, -19, + -30, -41, -53, -65, -68, -65, -56, -44, -30, -17, -8, 2, 10, 23, 31, 32, + 25, 10, -4, -14, -20, -25, -31, -39, -45, -45, -35, -17, 2, 22, 37, 51, + 63, 72, 79, 78, 74, 62, 43, 20, 2, -12, -24, -34, -49, -61, -69, -70, + -63, -48, -35, -23, -11, 0, 9, 20, 31, 36, 32, 20, 7, -9, -18, -24, + -30, -38, -47, -50, -44, -29, -9, 10, 27, 45, 60, 71, 78, 80, 78, 68, + 54, 33, 13, -5, -18, -29, -44, -57, -68, -74, -66, -54, -41, -30, -18, -5, + 8, 19, 26, 33, 32, 24, 13, -4, -15, -22, -24, -29, -40, -44, -42, -29, + -14, 0, 15, 31, 48, 63, 69, 74, 74, 72, 64, 47, 27, 11, -4, -17, + -33, -50, -66, -78, -78, -68, -54, -38, -25, -11, 4, 18, 31, 38, 40, 34, + 21, 5, -12, -23, -28, -34, -43, -50, -51, -39, -22, -6, 10, 26, 46, 61, + 70, 75, 79, 76, 67, 52, 34, 18, 4, -11, -27, -45, -63, -76, -78, -70, + -57, -44, -29, -15, 0, 14, 26, 35, 39, 34, 23, 9, -7, -18, -23, -30, + -40, -49, -51, -41, -24, -9, 5, 19, 39, 55, 67, 74, 77, 79, 72, 56, + 39, 24, 12, -5, -23, -42, -60, -73, -78, -74, -62, -48, -33, -18, -6, 10, + 25, 34, 37, 34, 26, 16, -2, -15, -23, -28, -32, -42, -46, -44, -31, -16, + -4, 11, 28, 44, 56, 64, 69, 75, 73, 63, 50, 37, 22, 6, -10, -27, + -47, -68, -81, -80, -68, -52, -39, -25, -13, 2, 17, 29, 36, 37, 32, 23, + 4, -14, -24, -26, -26, -36, -44, -45, -36, -20, -7, 9, 25, 38, 49, 58, + 66, 75, 77, 67, 52, 39, 26, 14, -3, -21, -43, -65, -81, -84, -74, -56, + -40, -27, -15, -2, 15, 27, 37, 38, 35, 26, 8, -11, -23, -26, -27, -34, + -42, -45, -40, -27, -13, 4, 19, 33, 45, 54, 60, 67, 72, 67, 57, 44, + 32, 20, 5, -11, -32, -55, -72, -82, -76, -62, -46, -31, -21, -5, 6, 19, + 29, 34, 33, 26, 12, -6, -17, -22, -23, -28, -38, -42, -38, -27, -14, 1, + 14, 27, 40, 48, 53, 62, 68, 67, 58, 44, 32, 21, 9, -5, -22, -43, + -63, -76, -75, -62, -46, -30, -24, -13, 0, 10, 20, 28, 31, 27, 12, -5, + -16, -20, -19, -21, -29, -35, -35, -27, -16, -6, 9, 21, 33, 41, 47, 53, + 61, 63, 60, 51, 39, 27, 15, 3, -13, -33, -55, -72, -75, -67, -52, -37, + -26, -18, -7, 4, 15, 26, 27, 25, 14, 0, -10, -15, -16, -19, -24, -31, + -32, -27, -17, -5, 5, 15, 26, 35, 43, 49, 54, 57, 57, 52, 42, 29, + 18, 10, -3, -23, -46, -64, -71, -66, -53, -39, -27, -19, -11, 0, 5, 16, + 22, 23, 15, 1, -10, -15, -18, -17, -17, -20, -24, -22, -14, -4, 7, 16, + 25, 31, 36, 41, 47, 49, 49, 46, 41, 32, 21, 13, 3, -14, -33, -51, + -60, -60, -52, -39, -28, -20, -14, -7, 1, 9, 14, 16, 10, 1, -10, -15, + -14, -15, -15, -15, -17, -14, -11, -4, 5, 13, 22, 29, 33, 35, 39, 43, + 45, 45, 42, 35, 26, 17, 7, -10, -25, -38, -48, -53, -53, -46, -33, -23, + -16, -13, -8, -3, 4, 9, 7, 1, -6, -10, -13, -12, -12, -8, -7, -6, + -2, 3, 6, 10, 14, 23, 28, 29, 30, 29, 34, 39, 40, 36, 30, 21, + 13, 1, -15, -27, -36, -44, -48, -45, -36, -26, -17, -13, -10, -6, -2, 2, + 3, -3, -6, -10, -14, -13, -12, -7, -3, 1, 2, 5, 6, 10, 15, 19, + 25, 25, 26, 26, 29, 34, 35, 32, 29, 20, 13, 4, -12, -20, -27, -33, + -38, -41, -36, -27, -19, -13, -10, -8, -8, -7, -5, -5, -7, -9, -13, -18, + -15, -12, -5, 3, 7, 10, 10, 11, 13, 20, 27, 27, 23, 20, 20, 24, + 27, 25, 26, 23, 17, 7, -6, -13, -16, -20, -26, -32, -33, -28, -20, -13, + -12, -12, -16, -15, -15, -12, -10, -13, -13, -16, -12, -7, 0, 9, 14, 18, + 18, 14, 11, 14, 18, 21, 17, 10, 11, 15, 20, 21, 20, 20, 17, 9, + 2, -5, -10, -14, -21, -25, -29, -27, -23, -17, -13, -13, -16, -18, -20, -20, + -12, -8, -9, -15, -16, -10, -2, 9, 14, 18, 18, 18, 14, 14, 17, 20, + 18, 12, 8, 11, 13, 16, 18, 19, 16, 9, 3, 1, 1, -6, -13, -20, + -23, -21, -19, -15, -15, -14, -17, -21, -22, -22, -17, -11, -11, -13, -18, -14, + -4, 12, 21, 22, 23, 21, 20, 17, 16, 16, 12, 7, 1, 5, 7, 8, + 12, 15, 15, 10, 3, 0, 3, 1, -5, -12, -19, -19, -16, -11, -9, -11, + -14, -23, -28, -29, -24, -17, -13, -15, -19, -18, -10, 7, 22, 29, 30, 24, + 22, 18, 17, 17, 11, 4, -2, -3, 2, 4, 8, 13, 16, 13, 7, 4, + 9, 8, 2, -7, -16, -15, -14, -12, -10, -12, -12, -19, -25, -29, -25, -18, + -15, -18, -21, -19, -12, 1, 16, 28, 34, 32, 29, 23, 18, 15, 11, 4, + -3, -10, -8, -5, 0, 7, 12, 14, 10, 6, 10, 15, 13, 3, -7, -11, + -13, -13, -13, -12, -14, -20, -28, -31, -29, -20, -13, -14, -18, -18, -15, -3, + 12, 24, 33, 32, 29, 25, 22, 16, 11, 3, -3, -6, -7, -8, -3, 2, + 8, 11, 11, 9, 10, 13, 13, 8, 0, -6, -9, -9, -9, -10, -11, -18, + -26, -30, -29, -22, -17, -18, -20, -21, -17, -7, 6, 21, 34, 38, 34, 29, + 21, 17, 13, 8, 1, -8, -13, -15, -10, -3, 5, 10, 11, 10, 11, 15, + 16, 11, 3, -4, -7, -9, -8, -10, -13, -19, -26, -26, -23, -17, -15, -16, + -17, -17, -15, -9, -2, 10, 26, 31, 31, 24, 21, 18, 13, 6, 1, -6, + -8, -9, -8, -4, 0, 6, 10, 12, 15, 14, 13, 9, 5, -2, -7, -8, + -9, -8, -10, -18, -25, -25, -23, -18, -16, -19, -22, -18, -16, -10, 0, 10, + 24, 33, 35, 29, 22, 17, 13, 7, -3, -8, -12, -14, -12, -7, -3, 4, + 10, 14, 16, 17, 16, 16, 11, 3, -7, -11, -10, -7, -10, -19, -26, -27, + -23, -17, -14, -14, -17, -18, -16, -12, -3, 7, 20, 26, 28, 24, 20, 16, + 15, 10, 2, -8, -13, -11, -7, -2, -2, 4, 6, 9, 14, 17, 19, 15, + 8, -4, -12, -15, -11, -5, -8, -18, -25, -24, -17, -9, -6, -7, -11, -15, + -15, -13, -6, 4, 11, 15, 16, 15, 16, 13, 9, 5, 1, -3, -7, -5, + -2, 3, 5, 6, 8, 10, 14, 17, 18, 14, 3, -8, -15, -13, -9, -6, + -9, -19, -22, -19, -13, -6, -4, -5, -8, -13, -15, -10, -5, 5, 8, 8, + 8, 11, 14, 14, 8, 2, 1, 1, 2, -2, 1, 5, 6, 7, 7, 6, + 11, 13, 16, 13, 3, -6, -13, -14, -8, -5, -6, -15, -20, -15, -10, -5, + -2, -6, -6, -8, -12, -10, -8, -3, 5, 3, 3, 5, 7, 10, 6, 2, + -3, -2, 2, 8, 9, 12, 11, 8, 9, 8, 11, 13, 11, 10, 0, -12, + -20, -21, -13, -10, -11, -14, -16, -10, -3, 4, 8, 5, 2, -2, -4, -4, + -7, -4, -4, -5, -7, -8, -5, 0, 2, 2, 0, 1, 6, 11, 15, 19, + 19, 18, 14, 10, 12, 12, 11, 6, -6, -16, -23, -23, -17, -13, -12, -12, + -13, -8, -2, 8, 13, 13, 8, 4, 1, -3, -3, -3, -4, -11, -16, -16, + -13, -9, -5, -4, -2, 1, 6, 13, 17, 21, 24, 23, 18, 14, 10, 11, + 12, 8, -3, -16, -26, -27, -20, -17, -21, -21, -17, -7, 2, 10, 16, 19, + 18, 13, 10, 5, 2, -2, -5, -14, -22, -26, -21, -15, -11, -11, -6, -2, + 6, 16, 22, 27, 28, 28, 23, 17, 13, 10, 12, 7, -4, -18, -29, -32, + -24, -20, -21, -22, -18, -5, 5, 14, 19, 21, 20, 17, 13, 8, 5, -2, + -9, -18, -26, -26, -21, -14, -12, -11, -8, -2, 10, 16, 21, 24, 25, 27, + 24, 16, 11, 6, 7, 6, -4, -16, -25, -29, -25, -19, -19, -22, -18, -7, + 6, 15, 17, 18, 19, 18, 15, 10, 8, 3, -5, -15, -24, -30, -27, -19, + -15, -15, -13, -8, 5, 14, 20, 25, 28, 31, 30, 26, 18, 11, 9, 7, + -2, -14, -27, -33, -30, -25, -25, -27, -26, -15, 2, 17, 22, 23, 23, 22, + 22, 18, 14, 7, -4, -14, -24, -31, -30, -25, -19, -16, -16, -11, -3, 8, + 17, 24, 29, 31, 31, 29, 22, 17, 12, 8, 2, -12, -26, -36, -35, -30, + -26, -26, -29, -20, -5, 13, 24, 26, 26, 26, 28, 23, 19, 11, 1, -9, + -24, -34, -33, -30, -24, -21, -21, -17, -11, 1, 9, 19, 27, 33, 34, 30, + 28, 24, 21, 16, 7, -6, -23, -35, -40, -36, -33, -31, -32, -27, -13, 3, + 17, 25, 29, 34, 34, 30, 23, 17, 11, 0, -14, -27, -32, -33, -30, -26, + -21, -18, -15, -9, 1, 11, 22, 29, 32, 33, 30, 28, 23, 21, 13, 3, + -15, -30, -37, -38, -35, -35, -33, -28, -18, -5, 10, 22, 30, 37, 36, 32, + 26, 21, 14, 7, -6, -19, -28, -34, -32, -27, -21, -20, -21, -20, -11, 5, + 17, 25, 29, 30, 33, 35, 31, 27, 19, 8, -7, -25, -37, -42, -41, -39, + -35, -30, -22, -11, 4, 21, 32, 38, 39, 36, 29, 22, 15, 9, -4, -15, + -24, -32, -35, -31, -24, -18, -18, -19, -14, -3, 11, 21, 27, 31, 32, 34, + 34, 31, 27, 18, 1, -19, -33, -39, -38, -40, -39, -35, -28, -17, -3, 14, + 28, 37, 41, 40, 34, 30, 24, 18, 7, -6, -20, -30, -36, -34, -30, -26, + -26, -27, -26, -16, 0, 16, 26, 30, 33, 36, 42, 43, 38, 27, 10, -10, + -27, -39, -43, -43, -43, -40, -34, -26, -14, 2, 21, 36, 42, 40, 36, 33, + 30, 24, 16, 5, -11, -25, -34, -35, -32, -29, -30, -31, -31, -27, -15, 5, + 21, 27, 30, 34, 42, 51, 48, 40, 20, -3, -21, -32, -38, -40, -43, -42, + -38, -30, -18, -3, 15, 29, 40, 41, 39, 34, 31, 28, 20, 10, -4, -18, + -29, -33, -34, -34, -35, -37, -38, -34, -21, -6, 12, 22, 26, 33, 44, 55, + 56, 46, 26, 5, -11, -25, -36, -42, -47, -47, -43, -37, -24, -11, 9, 25, + 36, 38, 38, 40, 39, 39, 28, 17, 3, -10, -23, -30, -37, -38, -42, -44, + -43, -40, -30, -16, 3, 17, 26, 34, 44, 57, 61, 52, 34, 9, -7, -21, + -30, -38, -46, -49, -48, -39, -27, -13, 5, 22, 32, 35, 35, 37, 41, 43, + 33, 19, 4, -8, -16, -25, -32, -39, -42, -44, -42, -41, -33, -20, -4, 11, + 21, 28, 38, 49, 58, 54, 36, 16, -6, -16, -21, -28, -36, -46, -49, -42, + -29, -17, 0, 13, 26, 30, 30, 35, 41, 47, 41, 25, 9, -4, -12, -17, + -28, -38, -46, -52, -51, -49, -39, -23, -9, 4, 12, 23, 39, 54, 66, 62, + 43, 23, 2, -10, -16, -26, -36, -45, -51, -50, -37, -20, 0, 16, 27, 28, + 29, 38, 47, 50, 44, 28, 13, -2, -10, -16, -26, -35, -45, -55, -57, -56, + -44, -27, -13, -4, 5, 17, 34, 53, 64, 64, 46, 29, 13, 1, -8, -17, + -28, -39, -48, -51, -42, -26, -8, 9, 18, 20, 24, 34, 46, 53, 47, 33, + 15, 4, -4, -13, -22, -35, -47, -56, -59, -56, -48, -32, -18, -8, 3, 14, + 33, 52, 65, 64, 49, 31, 17, 5, -3, -13, -25, -36, -45, -49, -44, -31, + -14, 7, 16, 21, 21, 31, 48, 57, 53, 38, 20, 8, -3, -9, -21, -35, + -47, -57, -62, -62, -54, -38, -22, -12, -5, 7, 26, 49, 66, 69, 56, 37, + 24, 15, 6, -4, -17, -30, -43, -53, -47, -34, -18, -2, 9, 14, 17, 29, + 46, 58, 56, 43, 25, 13, 2, -5, -15, -30, -45, -59, -66, -65, -57, -43, + -28, -16, -10, 2, 21, 44, 66, 71, 62, 43, 28, 19, 13, 3, -12, -25, + -42, -51, -50, -38, -18, -3, 5, 12, 17, 30, 48, 59, 58, 45, 26, 11, + 0, -6, -15, -29, -45, -63, -71, -68, -58, -41, -28, -19, -12, -4, 16, 42, + 62, 70, 61, 43, 29, 21, 16, 8, -6, -20, -35, -45, -45, -37, -21, -6, + 3, 8, 14, 24, 42, 54, 58, 47, 29, 16, 3, -3, -12, -27, -42, -62, + -73, -74, -66, -52, -34, -23, -14, -5, 12, 38, 60, 72, 68, 49, 34, 23, + 17, 10, -3, -18, -31, -42, -42, -36, -20, -4, 5, 9, 11, 22, 37, 51, + 55, 46, 29, 13, 2, -9, -14, -25, -38, -53, -67, -72, -67, -53, -35, -23, + -17, -10, 6, 32, 55, 69, 67, 53, 36, 26, 19, 12, 2, -13, -26, -37, + -40, -36, -24, -7, 3, 9, 13, 20, 36, 49, 52, 47, 32, 17, 3, -12, + -19, -29, -38, -52, -66, -75, -72, -56, -36, -20, -15, -10, 2, 25, 48, 63, + 63, 52, 39, 28, 20, 14, 5, -6, -19, -30, -38, -35, -25, -8, 4, 8, + 11, 17, 33, 47, 54, 47, 34, 18, 4, -9, -19, -28, -40, -53, -65, -75, + -74, -60, -41, -22, -15, -12, -2, 18, 43, 59, 63, 55, 41, 31, 27, 20, + 13, 3, -11, -24, -35, -34, -26, -11, 2, 8, 9, 11, 22, 37, 47, 49, + 39, 22, 6, -7, -19, -26, -36, -48, -60, -74, -77, -66, -47, -26, -13, -8, + 1, 15, 36, 53, 63, 56, 45, 30, 22, 16, 10, 5, -7, -19, -32, -34, + -25, -7, 8, 16, 17, 17, 23, 37, 48, 51, 40, 22, 4, -14, -24, -33, + -39, -49, -61, -72, -77, -66, -47, -27, -13, -5, 1, 13, 30, 47, 59, 57, + 47, 31, 23, 17, 15, 6, -5, -18, -26, -30, -24, -10, 8, 19, 21, 20, + 22, 30, 40, 48, 41, 25, 3, -17, -29, -32, -37, -46, -59, -70, -73, -65, + -46, -27, -14, -4, 3, 15, 29, 41, 52, 54, 45, 31, 19, 15, 15, 9, + 1, -14, -26, -27, -21, -8, 10, 17, 23, 23, 23, 32, 39, 45, 44, 29, + 7, -16, -32, -40, -42, -49, -61, -72, -76, -69, -50, -28, -12, -2, 5, 17, + 31, 43, 48, 49, 44, 34, 24, 15, 13, 9, 5, -8, -24, -27, -21, -7, + 10, 20, 25, 29, 29, 32, 36, 41, 41, 34, 14, -12, -35, -46, -49, -52, + -61, -74, -78, -73, -56, -31, -14, 2, 10, 19, 31, 44, 54, 53, 47, 34, + 24, 16, 9, 4, -2, -12, -25, -28, -22, -7, 9, 23, 32, 36, 36, 36, + 37, 42, 42, 33, 15, -14, -36, -50, -57, -56, -62, -74, -81, -77, -59, -36, + -15, 2, 11, 20, 31, 44, 56, 56, 51, 39, 26, 15, 7, 1, -3, -13, + -26, -33, -31, -14, 9, 25, 36, 41, 40, 41, 40, 44, 44, 35, 17, -13, + -39, -54, -61, -64, -69, -76, -81, -78, -63, -39, -15, 4, 14, 24, 35, 45, + 54, 56, 53, 41, 25, 14, 7, 3, -4, -14, -26, -34, -31, -15, 9, 25, + 36, 41, 43, 44, 43, 46, 45, 35, 16, -9, -31, -49, -63, -69, -75, -78, + -84, -79, -66, -45, -22, 0, 13, 23, 35, 48, 56, 58, 53, 43, 30, 19, + 10, 4, -7, -18, -26, -33, -30, -17, 4, 24, 37, 44, 50, 50, 49, 46, + 43, 35, 16, -7, -30, -52, -65, -75, -78, -83, -85, -82, -70, -50, -26, -4, + 14, 26, 39, 53, 63, 64, 59, 49, 35, 18, 6, -2, -13, -25, -35, -40, + -36, -22, 3, 26, 38, 47, 54, 60, 61, 57, 50, 39, 20, -5, -26, -49, + -66, -80, -87, -91, -93, -88, -74, -54, -34, -12, 8, 24, 40, 55, 68, 70, + 66, 55, 41, 26, 14, 6, -9, -25, -37, -43, -39, -28, -9, 15, 32, 41, + 48, 59, 65, 65, 58, 45, 25, 5, -17, -38, -61, -77, -91, -97, -100, -94, + -79, -64, -44, -23, -2, 24, 42, 57, 72, 77, 74, 63, 48, 33, 21, 10, + -7, -27, -43, -45, -41, -29, -14, 4, 26, 40, 49, 58, 66, 69, 64, 48, + 29, 7, -13, -31, -53, -73, -89, -100, -102, -95, -83, -67, -51, -29, -7, 17, + 37, 55, 72, 81, 77, 67, 55, 40, 25, 12, -4, -22, -40, -45, -42, -31, + -19, -4, 15, 34, 48, 55, 63, 67, 66, 57, 41, 20, -4, -25, -46, -69, + -88, -104, -110, -106, -95, -79, -63, -39, -13, 15, 39, 60, 75, 88, 91, 81, + 66, 44, 27, 13, -3, -22, -41, -50, -48, -38, -26, -13, 6, 29, 46, 55, + 62, 66, 69, 63, 48, 26, 5, -14, -33, -57, -84, -105, -115, -113, -102, -88, + -73, -53, -26, 1, 31, 57, 78, 91, 95, 88, 75, 60, 41, 22, 1, -19, + -38, -51, -53, -48, -36, -22, -6, 19, 39, 53, 62, 65, 69, 67, 55, 36, + 14, -6, -28, -54, -79, -100, -111, -116, -110, -98, -83, -61, -35, -6, 26, 53, + 75, 89, 96, 96, 87, 71, 50, 29, 10, -9, -30, -44, -53, -50, -45, -32, + -19, 2, 23, 43, 55, 62, 66, 66, 62, 49, 30, 11, -12, -39, -70, -95, + -112, -118, -118, -109, -94, -74, -48, -18, 17, 47, 70, 88, 98, 99, 95, 80, + 61, 37, 14, -9, -26, -43, -51, -52, -48, -40, -25, -6, 17, 37, 52, 57, + 63, 64, 62, 55, 36, 17, -8, -34, -62, -86, -106, -117, -118, -110, -99, -83, + -57, -27, 10, 42, 67, 85, 96, 101, 101, 91, 69, 46, 21, 1, -21, -38, + -49, -54, -49, -44, -35, -18, 2, 24, 44, 55, 64, 67, 63, 59, 46, 29, + 7, -21, -51, -79, -104, -117, -122, -117, -108, -94, -70, -40, 0, 34, 63, 85, + 96, 104, 105, 99, 82, 59, 31, 4, -20, -37, -46, -51, -51, -50, -44, -28, + -8, 17, 38, 53, 60, 65, 67, 64, 54, 40, 18, -10, -40, -71, -98, -115, + -121, -118, -113, -103, -82, -52, -14, 22, 53, 77, 94, 106, 109, 104, 93, 76, + 50, 21, -11, -33, -43, -48, -53, -56, -56, -46, -27, 2, 29, 48, 58, 62, + 63, 62, 58, 49, 33, 5, -27, -57, -87, -108, -119, -118, -114, -106, -91, -68, + -31, 8, 42, 69, 88, 102, 110, 110, 100, 83, 60, 33, 3, -23, -39, -46, + -52, -57, -57, -51, -35, -14, 15, 38, 54, 63, 65, 66, 58, 51, 40, 17, + -11, -44, -76, -101, -114, -116, -111, -106, -96, -77, -47, -11, 28, 58, 81, 97, + 109, 112, 105, 95, 77, 53, 23, -9, -30, -45, -52, -58, -64, -61, -52, -35, + -9, 20, 44, 62, 67, 67, 65, 62, 54, 35, 7, -24, -60, -91, -110, -119, + -116, -112, -105, -90, -65, -31, 8, 43, 73, 94, 109, 117, 113, 105, 91, 68, + 39, 4, -24, -43, -56, -64, -67, -67, -61, -47, -21, 9, 35, 55, 63, 66, + 66, 61, 56, 46, 23, -10, -46, -81, -100, -111, -115, -112, -107, -94, -75, -48, + -12, 28, 59, 84, 103, 116, 120, 114, 103, 81, 56, 22, -10, -35, -53, -64, + -71, -73, -71, -59, -39, -10, 19, 43, 60, 66, 68, 67, 64, 53, 33, 7, + -27, -64, -91, -108, -115, -113, -108, -97, -82, -59, -27, 11, 46, 75, 98, 112, + 119, 117, 109, 89, 64, 34, 4, -24, -50, -62, -69, -69, -70, -65, -49, -23, + 8, 32, 52, 61, 64, 65, 64, 55, 39, 15, -16, -46, -76, -97, -109, -110, + -107, -102, -91, -71, -42, -4, 34, 66, 90, 106, 116, 121, 118, 101, 78, 47, + 15, -15, -44, -60, -70, -73, -75, -74, -63, -39, -7, 23, 45, 60, 66, 69, + 69, 62, 49, 29, 1, -32, -65, -94, -108, -112, -109, -102, -97, -83, -58, -22, + 18, 54, 84, 103, 116, 121, 120, 112, 91, 63, 29, -6, -34, -54, -66, -75, + -79, -81, -72, -50, -22, 9, 33, 50, 59, 67, 70, 70, 60, 43, 13, -20, + -51, -78, -97, -107, -111, -109, -105, -94, -72, -37, 5, 42, 72, 96, 114, 124, + 127, 118, 100, 75, 42, 10, -22, -47, -62, -72, -79, -84, -82, -64, -35, -2, + 23, 39, 50, 61, 69, 71, 66, 51, 27, -6, -36, -62, -81, -96, -104, -105, + -106, -101, -83, -52, -11, 27, 57, 82, 103, 120, 127, 122, 107, 82, 53, 19, + -12, -39, -55, -65, -73, -81, -81, -67, -40, -8, 16, 30, 41, 52, 62, 68, + 66, 56, 34, 3, -28, -53, -71, -86, -96, -102, -106, -103, -88, -62, -25, 15, + 47, 72, 90, 109, 120, 123, 115, 93, 63, 31, 1, -24, -40, -52, -64, -76, + -82, -73, -50, -22, 1, 18, 27, 39, 51, 63, 67, 61, 44, 18, -13, -38, + -53, -69, -83, -96, -105, -103, -93, -69, -36, -3, 30, 56, 77, 95, 111, 116, + 113, 97, 72, 42, 13, -12, -25, -38, -54, -70, -79, -74, -57, -32, -11, 4, + 15, 26, 40, 55, 65, 62, 51, 28, 1, -24, -40, -56, -73, -89, -101, -102, + -95, -79, -50, -17, 16, 47, 68, 88, 104, 114, 115, 102, 80, 53, 24, 0, + -18, -31, -45, -60, -73, -74, -63, -42, -21, -6, 6, 16, 28, 45, 56, 59, + 51, 35, 14, -9, -26, -41, -57, -73, -87, -97, -95, -85, -62, -32, -2, 26, + 50, 71, 91, 105, 111, 105, 89, 64, 40, 16, -4, -20, -35, -49, -64, -70, + -68, -53, -35, -18, -6, 5, 14, 29, 45, 55, 54, 39, 21, 4, -13, -25, + -42, -63, -77, -89, -90, -80, -66, -44, -19, 10, 35, 57, 76, 93, 104, 104, + 91, 68, 48, 29, 13, -6, -24, -42, -56, -63, -61, -54, -42, -27, -17, -6, + 5, 18, 33, 44, 47, 39, 25, 10, 0, -14, -29, -50, -67, -79, -85, -81, + -70, -53, -32, -5, 24, 47, 67, 84, 98, 103, 95, 77, 56, 37, 22, 6, + -14, -34, -48, -56, -57, -52, -48, -37, -28, -17, -6, 8, 23, 34, 41, 38, + 28, 15, 4, -4, -16, -38, -59, -73, -78, -75, -66, -54, -37, -19, 7, 32, + 53, 72, 87, 95, 92, 78, 58, 44, 32, 20, 2, -21, -38, -47, -48, -47, + -46, -42, -36, -26, -14, -5, 9, 20, 32, 35, 30, 19, 12, 8, -5, -25, + -48, -63, -71, -70, -63, -58, -44, -26, -6, 20, 40, 59, 79, 92, 93, 83, + 60, 47, 37, 29, 13, -10, -28, -40, -44, -44, -48, -47, -41, -33, -22, -13, + 0, 14, 29, 36, 34, 24, 18, 15, 4, -13, -39, -60, -69, -72, -68, -62, + -51, -34, -13, 9, 31, 52, 73, 88, 95, 87, 70, 55, 45, 35, 20, -2, + -23, -36, -42, -47, -48, -51, -50, -40, -30, -17, -8, 7, 23, 36, 37, 30, + 22, 19, 13, -3, -24, -49, -65, -71, -71, -64, -54, -40, -20, -3, 21, 44, + 65, 85, 92, 87, 72, 57, 48, 39, 29, 11, -12, -27, -36, -41, -42, -47, + -49, -45, -37, -28, -17, -4, 13, 28, 33, 29, 26, 23, 17, 6, -11, -33, + -53, -64, -66, -62, -55, -44, -29, -12, 10, 31, 51, 71, 84, 85, 77, 61, + 50, 41, 36, 22, 2, -17, -33, -38, -42, -45, -48, -46, -41, -34, -23, -9, + 7, 24, 35, 32, 28, 23, 17, 10, -4, -26, -49, -64, -68, -64, -58, -46, + -32, -13, 8, 28, 45, 65, 78, 82, 76, 62, 52, 45, 37, 23, 6, -10, + -26, -35, -41, -45, -46, -48, -48, -39, -27, -11, 3, 14, 23, 27, 28, 25, + 23, 15, 2, -17, -34, -52, -60, -61, -56, -44, -32, -17, -3, 16, 34, 54, + 66, 73, 68, 58, 47, 42, 37, 29, 17, 3, -14, -25, -31, -36, -39, -44, + -48, -44, -33, -20, -9, 2, 13, 22, 26, 24, 20, 14, 5, -7, -22, -39, + -50, -55, -51, -43, -32, -20, -7, 10, 28, 44, 57, 65, 67, 64, 54, 44, + 36, 28, 18, 4, -9, -23, -32, -39, -42, -46, -44, -38, -29, -19, -12, -4, + 10, 22, 27, 22, 14, 8, 1, -6, -17, -30, -43, -49, -47, -38, -26, -18, + -10, 3, 17, 34, 45, 54, 59, 57, 53, 45, 37, 30, 22, 11, -3, -14, + -24, -34, -40, -45, -43, -39, -29, -21, -14, -6, 3, 16, 20, 17, 10, 3, + 0, -6, -15, -25, -33, -38, -37, -31, -21, -12, -6, 5, 15, 27, 39, 46, + 50, 51, 47, 44, 36, 29, 20, 10, 1, -10, -18, -27, -36, -40, -42, -37, + -29, -21, -14, -7, 1, 10, 16, 10, 3, -2, -3, -6, -12, -22, -28, -30, + -28, -23, -16, -11, -7, 0, 7, 19, 31, 42, 47, 47, 46, 46, 40, 33, + 21, 10, 2, -6, -12, -24, -33, -37, -38, -36, -31, -21, -14, -7, -2, 2, + 7, 8, 4, -2, -7, -12, -14, -19, -23, -24, -20, -16, -11, -6, -2, 3, + 9, 16, 24, 33, 37, 40, 44, 44, 40, 33, 22, 13, 5, -3, -8, -21, + -30, -35, -34, -32, -30, -23, -13, -6, -3, -3, -2, -2, -4, -7, -9, -12, + -13, -13, -14, -14, -11, -12, -4, -2, 2, 0, 3, 10, 18, 27, 32, 35, + 38, 40, 37, 32, 23, 13, 8, 2, -4, -11, -22, -27, -31, -30, -29, -24, + -14, -7, -8, -7, -10, -10, -10, -10, -11, -12, -13, -12, -11, -11, -7, -2, + 4, 5, 3, -2, 0, 8, 15, 21, 26, 30, 32, 37, 37, 32, 26, 16, + 10, 4, -4, -9, -16, -21, -26, -29, -28, -23, -15, -11, -9, -11, -13, -14, + -14, -13, -13, -12, -13, -12, -8, -3, 3, 6, 8, 10, 7, 1, -3, 2, + 8, 17, 22, 22, 27, 32, 37, 35, 29, 18, 11, 2, -4, -8, -14, -17, + -21, -23, -25, -22, -17, -11, -9, -11, -16, -16, -16, -16, -14, -15, -14, -11, + -5, 0, 4, 5, 6, 7, 6, 4, 0, 3, 8, 16, 21, 20, 24, 28, + 34, 35, 29, 17, 8, 3, 1, -3, -9, -15, -20, -21, -23, -22, -21, -17, + -13, -14, -18, -23, -22, -17, -13, -10, -9, -8, 0, 6, 9, 10, 8, 6, + 6, 4, 0, -2, 1, 10, 17, 20, 22, 25, 29, 31, 29, 20, 10, 2, + -2, 0, -5, -11, -18, -20, -19, -19, -19, -18, -16, -14, -18, -26, -26, -22, + -16, -13, -9, -6, 1, 7, 10, 10, 7, 7, 7, 5, 0, -4, -2, 7, + 14, 19, 22, 26, 30, 32, 30, 22, 13, 6, 1, -2, -7, -13, -16, -18, + -19, -19, -21, -21, -19, -17, -16, -23, -25, -23, -17, -10, -9, -4, 2, 8, + 10, 12, 9, 7, 5, 4, 2, -3, -2, 3, 9, 18, 23, 28, 29, 28, + 27, 26, 19, 12, 6, 0, -7, -11, -15, -17, -20, -21, -20, -22, -23, -25, + -24, -26, -27, -25, -20, -13, -5, 3, 9, 11, 15, 17, 15, 10, 4, 0, + -4, -5, -4, 2, 5, 13, 19, 25, 29, 28, 26, 25, 20, 16, 11, 2, + -5, -10, -10, -10, -14, -17, -21, -24, -26, -29, -27, -28, -28, -26, -23, -17, + -8, 1, 12, 15, 16, 14, 13, 10, 6, 0, -5, -6, -5, 1, 6, 12, + 20, 27, 30, 28, 24, 23, 21, 17, 11, 4, -6, -9, -10, -10, -11, -16, + -18, -21, -24, -26, -29, -28, -27, -25, -23, -18, -11, -2, 11, 15, 15, 12, + 11, 9, 6, 1, -6, -6, -2, 3, 7, 11, 19, 26, 28, 26, 22, 21, + 23, 24, 17, 10, 4, 0, -2, -5, -10, -15, -20, -25, -32, -36, -36, -35, + -32, -30, -26, -19, -10, 2, 14, 21, 21, 17, 13, 10, 7, 1, -5, -5, + -6, -4, 0, 6, 12, 19, 22, 24, 20, 21, 24, 29, 28, 20, 13, 8, + 3, 2, -4, -9, -16, -27, -34, -41, -44, -41, -38, -35, -31, -27, -18, -3, + 13, 26, 29, 23, 18, 14, 11, 8, 4, -2, -8, -11, -9, -6, 4, 9, + 16, 17, 16, 16, 23, 33, 37, 33, 26, 19, 12, 8, 1, -7, -15, -30, + -41, -50, -53, -50, -43, -38, -34, -28, -17, -3, 13, 26, 30, 26, 19, 14, + 12, 9, 4, -2, -10, -14, -13, -7, 4, 9, 12, 13, 13, 17, 25, 32, + 40, 39, 32, 24, 15, 11, 8, 1, -10, -27, -43, -51, -55, -52, -49, -45, + -40, -32, -21, -8, 9, 23, 31, 30, 24, 19, 17, 16, 11, 4, -7, -15, + -18, -14, -6, 2, 5, 7, 9, 14, 24, 35, 45, 48, 45, 34, 25, 16, + 8, 2, -11, -27, -46, -59, -64, -61, -53, -46, -40, -35, -24, -9, 8, 23, + 30, 31, 27, 24, 21, 17, 12, 4, -6, -15, -19, -17, -12, -3, 3, 4, + 6, 12, 25, 37, 45, 47, 47, 43, 35, 23, 12, 2, -10, -24, -42, -60, + -71, -71, -63, -55, -45, -36, -22, -7, 9, 22, 30, 35, 34, 31, 24, 19, + 13, 6, -3, -13, -20, -21, -16, -9, -3, -2, 4, 11, 26, 38, 45, 50, + 49, 48, 42, 31, 16, 4, -9, -21, -38, -59, -72, -77, -70, -61, -53, -41, + -26, -9, 7, 17, 26, 34, 41, 41, 35, 25, 17, 9, 0, -10, -21, -24, + -22, -15, -9, -7, -2, 10, 25, 39, 44, 47, 49, 52, 50, 39, 22, 6, + -8, -20, -34, -54, -70, -78, -77, -68, -61, -49, -33, -15, 3, 16, 25, 32, + 43, 49, 47, 37, 25, 16, 3, -10, -22, -29, -27, -22, -15, -12, -7, 7, + 25, 42, 47, 50, 53, 57, 57, 46, 31, 11, -5, -22, -39, -56, -72, -81, + -85, -81, -71, -56, -36, -16, 4, 19, 29, 37, 48, 55, 56, 48, 34, 20, + 7, -10, -25, -32, -34, -28, -21, -17, -14, 0, 20, 40, 50, 51, 53, 58, + 61, 53, 39, 18, -2, -18, -36, -53, -70, -80, -85, -86, -79, -67, -46, -23, + -2, 17, 27, 35, 44, 55, 62, 57, 44, 26, 9, -10, -23, -29, -32, -28, + -24, -20, -15, -4, 15, 35, 47, 50, 49, 53, 57, 53, 43, 24, 5, -14, + -32, -50, -64, -5, 0, -2, -3, -3, -3, -3, -2, -2, 1, 2, 3, 5, + 8, 11, 11, 10, 8, 5, 1, -6, -13, -19, -21, -18, -15, -13, -10, -7, + -2, 4, 8, 12, 17, 28, 33, 29, 23, 14, 7, -5, -19, -33, -42, -36, + -28, -24, -17, -13, -8, 1, 7, 15, 23, 33, 42, 42, 35, 26, 15, 0, + -16, -30, -44, -45, -34, -27, -20, -16, -13, -4, 4, 12, 21, 29, 40, 45, + 40, 30, 20, 6, -13, -25, -38, -45, -38, -31, -24, -18, -15, -10, -4, 5, + 17, 27, 35, 44, 43, 37, 27, 15, -4, -19, -31, -44, -44, -35, -30, -22, + -19, -16, -8, 2, 15, 25, 32, 42, 47, 42, 32, 18, 0, -16, -26, -39, + -45, -38, -31, -25, -19, -18, -14, -5, 11, 23, 29, 39, 46, 45, 38, 25, + 7, -8, -18, -31, -44, -43, -35, -30, -25, -25, -20, -9, 7, 21, 27, 36, + 48, 51, 44, 32, 14, -3, -16, -28, -42, -46, -41, -33, -27, -24, -23, -15, + 1, 16, 27, 33, 42, 47, 46, 38, 21, 5, -9, -21, -34, -44, -45, -39, + -31, -28, -26, -20, -8, 9, 25, 34, 41, 49, 51, 47, 31, 11, -6, -18, + -30, -42, -48, -45, -36, -28, -26, -23, -12, 6, 23, 33, 38, 43, 51, 50, + 36, 15, 0, -12, -22, -35, -50, -50, -40, -31, -29, -27, -18, 1, 20, 32, + 36, 43, 52, 56, 45, 23, 2, -10, -20, -33, -48, -56, -49, -36, -30, -26, + -18, -5, 17, 33, 39, 40, 46, 52, 49, 32, 9, -8, -18, -26, -40, -54, + -53, -39, -30, -28, -23, -12, 10, 31, 39, 38, 42, 54, 54, 41, 17, -5, + -15, -22, -35, -53, -59, -47, -36, -30, -24, -14, 6, 27, 40, 42, 43, 51, + 56, 46, 26, 3, -13, -22, -33, -49, -61, -55, -41, -32, -26, -18, 0, 22, + 38, 45, 43, 48, 55, 50, 33, 11, -10, -21, -29, -43, -59, -60, -46, -35, + -28, -18, -6, 15, 35, 45, 46, 45, 52, 53, 41, 20, -6, -19, -26, -38, + -54, -62, -53, -39, -29, -19, -11, 6, 29, 44, 48, 45, 47, 52, 49, 32, + 5, -18, -26, -32, -45, -61, -61, -48, -35, -23, -14, -2, 22, 42, 52, 50, + 46, 50, 50, 38, 12, -15, -26, -31, -43, -59, -65, -53, -37, -25, -16, -6, + 16, 40, 53, 53, 47, 49, 51, 42, 22, -10, -27, -31, -38, -54, -67, -63, + -46, -27, -18, -7, 10, 31, 52, 59, 53, 48, 50, 46, 32, 3, -24, -34, + -39, -50, -66, -68, -54, -35, -20, -8, 6, 23, 47, 62, 59, 52, 50, 48, + 37, 13, -18, -35, -40, -46, -62, -72, -63, -43, -25, -10, 6, 20, 41, 59, + 63, 55, 49, 46, 39, 21, -9, -31, -39, -42, -52, -68, -68, -52, -32, -17, + -4, 9, 31, 54, 66, 63, 54, 51, 44, 32, 6, -26, -40, -44, -51, -65, + -72, -61, -41, -23, -5, 9, 25, 48, 64, 66, 59, 54, 46, 33, 12, -17, + -36, -45, -51, -62, -73, -67, -48, -31, -11, 8, 21, 44, 64, 70, 64, 57, + 49, 36, 20, -8, -34, -47, -52, -58, -68, -73, -59, -40, -19, 4, 17, 36, + 58, 72, 73, 65, 56, 41, 26, 4, -24, -44, -55, -63, -69, -73, -66, -51, + -28, -2, 18, 32, 51, 67, 75, 72, 62, 46, 29, 11, -13, -37, -54, -64, + -70, -71, -70, -58, -38, -13, 14, 30, 48, 64, 73, 76, 69, 52, 34, 15, + -7, -31, -50, -62, -69, -71, -71, -66, -47, -19, 8, 26, 40, 58, 73, 81, + 76, 57, 39, 23, 2, -22, -45, -62, -71, -73, -71, -69, -57, -32, 0, 26, + 41, 55, 70, 81, 83, 64, 41, 24, 6, -15, -39, -60, -71, -73, -69, -69, + -62, -40, -11, 20, 39, 51, 65, 78, 86, 75, 50, 29, 11, -8, -30, -53, + -70, -77, -71, -66, -67, -53, -22, 13, 37, 49, 60, 75, 89, 84, 58, 33, + 16, -2, -22, -47, -68, -77, -72, -67, -68, -60, -34, 0, 29, 47, 56, 69, + 85, 88, 69, 40, 20, 4, -13, -35, -61, -76, -74, -65, -66, -65, -47, -15, + 20, 43, 53, 64, 81, 89, 77, 50, 26, 9, -10, -29, -51, -71, -78, -71, + -66, -64, -52, -27, 9, 38, 54, 62, 73, 85, 82, 60, 34, 13, -3, -19, + -40, -65, -80, -74, -68, -69, -61, -40, -4, 29, 49, 61, 72, 86, 86, 70, + 45, 21, 3, -16, -33, -56, -80, -78, -70, -70, -65, -50, -18, 20, 48, 62, + 68, 80, 88, 78, 53, 26, 5, -12, -26, -45, -72, -81, -71, -67, -64, -56, + -34, 4, 37, 57, 63, 73, 85, 83, 63, 37, 16, 0, -17, -36, -63, -79, + -74, -70, -69, -63, -44, -10, 26, 52, 62, 69, 81, 84, 69, 45, 22, 3, + -15, -28, -52, -75, -76, -69, -67, -64, -52, -24, 14, 45, 60, 65, 74, 82, + 75, 54, 32, 12, -6, -21, -44, -68, -78, -74, -71, -69, -60, -34, 2, 34, + 55, 66, 73, 79, 78, 61, 39, 20, 2, -16, -34, -56, -72, -74, -70, -71, + -66, -47, -14, 21, 48, 61, 68, 76, 80, 69, 46, 27, 11, -7, -26, -50, + -68, -72, -70, -70, -69, -54, -24, 10, 39, 57, 66, 72, 76, 70, 52, 33, + 16, -4, -20, -39, -59, -70, -71, -69, -67, -60, -37, -6, 27, 50, 62, 67, + 72, 74, 61, 41, 25, 10, -10, -31, -51, -67, -74, -73, -73, -68, -48, -16, + 17, 45, 60, 66, 73, 75, 66, 48, 29, 15, -3, -24, -45, -62, -70, -72, + -74, -70, -55, -26, 7, 32, 51, 63, 70, 73, 67, 51, 35, 24, 9, -16, + -38, -54, -64, -68, -75, -75, -62, -36, -5, 22, 45, 60, 69, 74, 68, 57, + 43, 29, 15, -9, -29, -45, -60, -67, -75, -76, -64, -44, -16, 10, 32, 52, + 63, 68, 66, 59, 48, 36, 24, 6, -17, -35, -51, -60, -70, -78, -72, -55, + -27, 1, 20, 39, 56, 65, 68, 60, 51, 41, 31, 15, -9, -27, -44, -58, + -67, -75, -73, -58, -35, -8, 11, 32, 50, 60, 61, 57, 53, 47, 37, 25, + 4, -19, -35, -48, -60, -73, -76, -67, -46, -18, 2, 20, 40, 56, 64, 62, + 56, 49, 43, 34, 15, -10, -31, -45, -57, -70, -78, -69, -52, -27, -4, 13, + 34, 52, 60, 57, 53, 52, 46, 36, 22, 1, -19, -35, -50, -65, -73, -70, + -58, -41, -17, 4, 22, 42, 55, 58, 57, 55, 50, 43, 32, 12, -11, -30, + -47, -61, -71, -72, -63, -46, -26, -6, 13, 30, 47, 53, 54, 56, 52, 46, + 38, 24, 5, -20, -39, -52, -63, -67, -66, -57, -37, -15, 3, 18, 37, 50, + 55, 59, 55, 49, 45, 32, 15, -10, -34, -50, -61, -66, -66, -58, -42, -24, + -4, 11, 27, 44, 50, 54, 57, 53, 49, 39, 23, 2, -23, -43, -57, -64, + -67, -62, -50, -33, -14, 4, 18, 37, 48, 53, 57, 55, 52, 44, 30, 13, + -14, -38, -54, -62, -65, -62, -54, -42, -24, -2, 13, 28, 41, 48, 56, 57, + 52, 45, 37, 23, 0, -28, -47, -57, -62, -63, -59, -50, -34, -14, 1, 16, + 35, 48, 56, 59, 59, 54, 45, 31, 8, -20, -42, -56, -62, -64, -60, -52, + -40, -23, -5, 10, 28, 43, 52, 56, 57, 56, 49, 38, 21, -8, -33, -46, + -56, -60, -59, -56, -47, -32, -15, 0, 17, 34, 47, 55, 58, 57, 53, 43, + 30, 8, -24, -42, -52, -59, -58, -57, -51, -42, -26, -8, 11, 29, 42, 50, + 57, 59, 55, 48, 34, 15, -15, -36, -45, -52, -55, -58, -55, -43, -31, -17, + -2, 16, 37, 50, 56, 58, 58, 54, 43, 23, -8, -33, -40, -47, -54, -57, + -58, -48, -34, -23, -10, 9, 31, 48, 54, 55, 55, 57, 50, 32, 3, -28, + -37, -41, -49, -55, -58, -49, -36, -27, -17, 1, 21, 41, 50, 52, 51, 54, + 55, 41, 13, -18, -32, -35, -42, -50, -57, -55, -41, -32, -24, -10, 10, 33, + 47, 50, 51, 54, 59, 49, 24, -8, -26, -30, -37, -46, -56, -59, -46, -35, + -29, -18, 2, 25, 44, 48, 47, 51, 57, 56, 36, 5, -20, -28, -31, -40, + -51, -58, -52, -39, -33, -25, -8, 15, 38, 49, 47, 50, 56, 60, 46, 15, + -11, -25, -30, -36, -49, -60, -54, -39, -33, -30, -14, 8, 32, 47, 44, 44, + 51, 59, 52, 26, -4, -20, -24, -29, -41, -54, -55, -43, -34, -33, -26, -8, + 17, 37, 43, 42, 48, 59, 60, 42, 13, -11, -21, -25, -36, -51, -59, -51, + -38, -34, -32, -17, 10, 33, 43, 43, 44, 55, 60, 46, 21, -6, -18, -22, + -28, -42, -54, -52, -39, -30, -32, -25, -4, 20, 36, 39, 39, 48, 60, 57, + 36, 10, -11, -19, -22, -34, -51, -58, -48, -35, -36, -34, -13, 13, 35, 41, + 38, 46, 59, 61, 44, 20, -5, -20, -22, -30, -46, -56, -53, -39, -34, -36, + -22, 1, 25, 39, 39, 42, 53, 60, 54, 34, 10, -10, -17, -21, -39, -57, + -59, -48, -38, -43, -35, -11, 16, 37, 43, 42, 52, 61, 58, 41, 19, -3, + -16, -21, -31, -50, -59, -53, -40, -39, -39, -22, 5, 30, 40, 38, 45, 58, + 64, 52, 28, 5, -12, -17, -23, -44, -58, -56, -46, -40, -43, -33, -7, 22, + 39, 41, 44, 55, 64, 60, 40, 13, -7, -16, -21, -35, -56, -60, -52, -44, + -43, -40, -21, 11, 34, 40, 40, 50, 61, 64, 53, 29, 6, -10, -16, -25, + -47, -62, -61, -53, -49, -47, -35, -5, 26, 42, 45, 49, 58, 65, 59, 39, + 15, -5, -16, -22, -37, -56, -61, -56, -50, -47, -42, -21, 11, 33, 40, 44, + 53, 63, 66, 54, 29, 8, -6, -15, -28, -52, -64, -60, -57, -53, -49, -31, + 1, 28, 40, 42, 51, 63, 66, 56, 36, 14, -3, -13, -25, -45, -61, -61, + -58, -54, -47, -38, -11, 20, 36, 41, 44, 55, 64, 60, 47, 28, 9, -4, + -15, -32, -56, -67, -64, -62, -55, -48, -27, 8, 29, 41, 47, 57, 66, 65, + 56, 39, 17, 0, -13, -27, -49, -66, -68, -67, -58, -48, -36, -8, 22, 38, + 45, 53, 63, 65, 61, 51, 28, 11, -4, -20, -40, -62, -70, -71, -68, -55, + -44, -24, 9, 30, 42, 52, 66, 69, 64, 58, 42, 20, 4, -14, -34, -57, + -71, -73, -73, -63, -51, -35, -5, 23, 38, 48, 62, 71, 69, 65, 54, 32, + 14, -6, -26, -48, -68, -79, -82, -72, -57, -42, -18, 11, 33, 48, 63, 73, + 72, 68, 62, 46, 22, 0, -21, -42, -63, -76, -83, -80, -65, -49, -28, -2, + 23, 42, 58, 71, 75, 72, 68, 56, 33, 10, -12, -32, -54, -73, -84, -87, + -73, -54, -36, -15, 11, 34, 52, 67, 73, 73, 72, 66, 48, 21, -6, -26, + -47, -67, -80, -88, -81, -62, -41, -23, 0, 27, 47, 65, 74, 74, 71, 67, + 57, 33, 4, -20, -42, -64, -77, -88, -88, -72, -49, -27, -7, 16, 40, 63, + 75, 75, 74, 69, 64, 46, 16, -13, -35, -57, -74, -87, -93, -81, -58, -35, + -17, 6, 33, 59, 73, 76, 76, 71, 68, 58, 29, -4, -29, -48, -68, -83, + -94, -92, -70, -42, -22, -4, 21, 51, 73, 78, 76, 73, 70, 63, 40, 7, + -24, -42, -60, -79, -91, -92, -76, -52, -30, -12, 9, 39, 66, 76, 76, 75, + 74, 70, 54, 24, -12, -36, -52, -72, -93, -100, -90, -64, -38, -21, -5, 25, + 61, 81, 81, 77, 78, 76, 63, 33, -5, -33, -49, -67, -90, -100, -92, -71, + -44, -21, -8, 14, 49, 75, 82, 77, 76, 75, 66, 45, 10, -27, -45, -59, + -80, -98, -98, -81, -52, -26, -12, 2, 34, 71, 86, 80, 75, 77, 71, 54, + 23, -17, -44, -57, -74, -93, -99, -87, -65, -36, -14, -4, 20, 55, 79, 82, + 78, 78, 75, 65, 41, 1, -34, -52, -67, -88, -104, -98, -76, -47, -23, -12, + 6, 45, 81, 90, 81, 79, 81, 72, 50, 11, -28, -50, -61, -81, -102, -103, + -84, -57, -30, -13, 1, 30, 70, 92, 88, 81, 80, 75, 59, 27, -15, -48, + -62, -76, -97, -106, -94, -69, -39, -16, -4, 17, 59, 92, 94, 87, 86, 83, + 67, 36, -4, -38, -61, -77, -96, -111, -102, -80, -53, -26, -8, 14, 50, 89, + 101, 93, 87, 83, 73, 46, 7, -31, -58, -72, -87, -106, -106, -88, -59, -31, + -12, 5, 33, 74, 99, 99, 90, 84, 78, 57, 22, -18, -49, -70, -84, -100, + -108, -96, -72, -43, -21, -3, 24, 61, 95, 106, 99, 90, 82, 65, 34, -6, + -40, -66, -83, -96, -106, -102, -82, -52, -27, -8, 15, 48, 86, 107, 105, 94, + 85, 73, 45, 6, -32, -61, -80, -91, -102, -106, -92, -63, -35, -15, 8, 37, + 74, 102, 109, 98, 87, 76, 54, 21, -16, -50, -76, -89, -98, -104, -98, -76, + -46, -23, -2, 25, 60, 93, 111, 106, 92, 82, 65, 35, -5, -39, -66, -83, + -95, -105, -105, -86, -57, -33, -11, 15, 50, 86, 111, 115, 102, 88, 71, 43, + 7, -32, -64, -86, -96, -100, -102, -92, -67, -40, -13, 13, 42, 75, 103, 116, + 106, 90, 74, 49, 16, -21, -54, -80, -94, -98, -100, -94, -75, -50, -23, 4, + 30, 62, 95, 117, 115, 100, 81, 57, 28, -10, -46, -75, -95, -102, -101, -97, + -83, -61, -32, -2, 24, 55, 87, 111, 118, 106, 88, 65, 35, 0, -36, -67, + -89, -101, -102, -98, -89, -68, -43, -13, 16, 46, 80, 107, 121, 116, 98, 75, + 47, 11, -27, -62, -87, -101, -104, -100, -93, -77, -51, -18, 13, 36, 67, 99, + 119, 119, 103, 81, 53, 21, -16, -52, -79, -96, -106, -102, -93, -82, -60, -30, + 3, 30, 59, 88, 111, 121, 111, 89, 61, 30, -4, -41, -74, -94, -106, -104, + -95, -87, -70, -41, -8, 22, 49, 81, 106, 120, 118, 98, 73, 41, 8, -30, + -64, -87, -104, -111, -100, -91, -77, -51, -21, 13, 41, 73, 100, 117, 122, 107, + 83, 52, 19, -18, -55, -82, -101, -111, -105, -93, -83, -60, -29, 5, 35, 64, + 92, 112, 121, 112, 88, 61, 29, -7, -45, -75, -94, -108, -108, -96, -87, -67, + -37, -5, 26, 52, 83, 105, 116, 116, 97, 70, 41, 7, -33, -67, -91, -105, + -110, -99, -88, -73, -48, -18, 15, 45, 74, 98, 114, 118, 104, 79, 51, 17, + -21, -58, -86, -102, -109, -103, -90, -77, -54, -23, 9, 36, 62, 88, 107, 114, + 107, 88, 63, 30, -8, -46, -77, -96, -107, -108, -97, -81, -63, -36, -4, 30, + 59, 84, 104, 115, 112, 95, 69, 38, 5, -33, -69, -94, -104, -105, -99, -87, + -72, -44, -11, 21, 47, 71, 97, 113, 113, 99, 77, 49, 17, -19, -57, -87, + -101, -105, -103, -90, -72, -54, -24, 10, 41, 64, 86, 104, 111, 104, 85, 57, + 25, -7, -42, -75, -96, -101, -98, -92, -79, -61, -36, -4, 28, 51, 74, 98, + 110, 107, 94, 70, 38, 5, -30, -64, -89, -101, -101, -95, -79, -63, -43, -14, + 21, 48, 68, 90, 105, 108, 97, 74, 44, 12, -20, -52, -83, -96, -96, -92, + -82, -67, -49, -24, 10, 39, 59, 79, 99, 107, 101, 83, 54, 21, -11, -41, + -71, -92, -98, -95, -84, -68, -54, -35, -5, 28, 54, 73, 92, 103, 103, 90, + 64, 31, -4, -34, -63, -85, -94, -92, -84, -70, -56, -38, -11, 19, 44, 64, + 83, 95, 98, 90, 66, 39, 9, -22, -50, -73, -86, -89, -84, -72, -59, -45, + -23, 6, 35, 58, 75, 89, 96, 92, 75, 49, 19, -14, -42, -63, -80, -88, + -84, -74, -60, -48, -30, -5, 23, 52, 70, 82, 91, 91, 79, 57, 29, -3, + -33, -54, -70, -84, -87, -79, -65, -50, -35, -16, 10, 41, 68, 80, 85, 88, + 82, 64, 36, 3, -28, -49, -60, -72, -83, -81, -66, -49, -37, -22, -2, 28, + 58, 74, 78, 83, 81, 69, 45, 14, -18, -42, -55, -66, -77, -79, -68, -53, + -39, -25, -8, 17, 46, 67, 72, 75, 74, 70, 53, 24, -9, -34, -48, -55, + -64, -74, -70, -55, -40, -28, -17, 3, 33, 61, 70, 71, 69, 68, 61, 37, + 3, -28, -44, -50, -57, -70, -73, -58, -41, -30, -21, -8, 21, 52, 67, 69, + 66, 66, 64, 44, 10, -22, -39, -48, -52, -61, -72, -62, -43, -29, -20, -12, + 7, 38, 62, 68, 61, 56, 60, 51, 23, -12, -36, -43, -44, -49, -65, -65, + -45, -29, -22, -19, -7, 24, 52, 65, 57, 52, 58, 57, 36, 0, -30, -38, + -37, -39, -55, -66, -52, -33, -23, -21, -14, 10, 40, 60, 59, 49, 51, 54, + 43, 11, -21, -35, -37, -33, -42, -55, -49, -29, -19, -20, -19, -5, 23, 49, + 54, 43, 42, 50, 49, 23, -12, -30, -34, -29, -31, -49, -54, -35, -19, -16, + -18, -11, 10, 39, 55, 45, 35, 41, 47, 31, -3, -26, -33, -28, -23, -36, + -47, -36, -18, -11, -16, -16, -3, 21, 42, 42, 32, 32, 40, 35, 13, -13, + -25, -24, -17, -22, -37, -38, -25, -16, -16, -19, -11, 7, 30, 42, 34, 27, + 33, 35, 19, -6, -21, -23, -17, -14, -23, -29, -21, -11, -10, -17, -16, -4, + 14, 30, 31, 20, 21, 29, 24, 6, -11, -16, -11, -5, -10, -20, -22, -15, + -12, -17, -21, -15, 0, 20, 29, 22, 17, 23, 25, 16, -2, -14, -14, -7, + -2, -9, -14, -12, -9, -11, -17, -17, -11, 3, 18, 17, 9, 13, 19, 17, + 7, -5, -5, 3, 8, 3, -7, -10, -12, -14, -20, -22, -17, -7, 9, 17, + 10, 8, 15, 18, 11, 2, -3, 1, 8, 9, 5, -3, -9, -12, -18, -21, + -21, -19, -4, 10, 9, 2, 5, 14, 16, 11, 4, 5, 13, 16, 14, 6, + -8, -14, -19, -23, -24, -21, -13, -2, 7, 3, -2, 8, 12, 11, 9, 10, + 14, 19, 20, 16, 4, -9, -17, -23, -26, -27, -24, -14, -2, 1, -5, 3, + 15, 17, 14, 14, 17, 22, 25, 20, 9, -8, -19, -25, -30, -29, -26, -22, + -11, 0, -3, -3, 9, 16, 19, 20, 21, 24, 28, 28, 20, 2, -16, -25, + -30, -34, -33, -32, -23, -9, -6, -8, 2, 15, 21, 24, 26, 29, 33, 34, + 30, 14, -11, -26, -33, -38, -38, -37, -34, -23, -12, -7, 0, 11, 21, 29, + 34, 35, 37, 39, 35, 21, -5, -26, -34, -39, -40, -42, -42, -31, -17, -9, + -4, 7, 19, 31, 38, 38, 41, 42, 40, 28, 3, -22, -36, -42, -45, -46, + -46, -37, -23, -14, -6, 6, 20, 32, 40, 40, 44, 46, 41, 31, 13, -12, + -32, -44, -47, -48, -49, -44, -32, -20, -8, 3, 15, 27, 40, 45, 47, 50, + 47, 39, 21, -6, -29, -42, -46, -51, -56, -52, -41, -24, -13, -4, 11, 27, + 41, 51, 52, 53, 52, 45, 29, 2, -25, -45, -50, -52, -57, -56, -49, -32, + -16, -4, 9, 22, 36, 49, 55, 56, 56, 50, 35, 11, -14, -37, -51, -57, + -61, -61, -56, -41, -23, -8, 8, 21, 33, 48, 61, 64, 60, 54, 40, 17, + -8, -34, -52, -59, -62, -63, -60, -49, -30, -14, 2, 19, 33, 47, 60, 66, + 67, 65, 50, 25, -3, -26, -47, -59, -68, -72, -66, -57, -38, -20, -5, 14, + 30, 44, 61, 71, 71, 68, 57, 34, 7, -20, -43, -58, -68, -72, -69, -62, + -45, -25, -10, 7, 24, 42, 59, 70, 74, 73, 65, 46, 16, -15, -38, -53, + -65, -77, -77, -70, -54, -34, -19, 0, 20, 41, 60, 74, 82, 80, 71, 54, + 27, -8, -36, -55, -68, -78, -82, -76, -61, -40, -20, -2, 17, 36, 57, 74, + 83, 82, 74, 62, 39, 3, -31, -49, -62, -75, -84, -84, -69, -47, -27, -13, + 6, 31, 56, 73, 82, 86, 80, 68, 49, 14, -24, -46, -60, -74, -83, -86, + -76, -54, -32, -15, 3, 23, 48, 71, 85, 87, 80, 71, 57, 27, -12, -41, + -57, -68, -78, -88, -84, -64, -41, -23, -5, 16, 40, 65, 84, 90, 87, 77, + 63, 36, -3, -34, -57, -69, -76, -85, -87, -73, -48, -27, -8, 13, 34, 60, + 83, 91, 86, 77, 66, 44, 9, -26, -53, -68, -74, -83, -88, -80, -56, -33, + -13, 9, 29, 55, 79, 93, 89, 76, 67, 52, 21, -15, -46, -69, -74, -77, + -84, -86, -67, -42, -20, 4, 23, 43, 71, 94, 95, 80, 67, 56, 32, 0, + -37, -66, -74, -73, -78, -87, -76, -50, -25, 1, 21, 37, 61, 88, 97, 84, + 67, 57, 38, 8, -25, -59, -77, -77, -76, -81, -80, -61, -34, -6, 20, 36, + 55, 80, 96, 91, 70, 54, 39, 17, -14, -51, -75, -79, -75, -77, -80, -68, + -40, -11, 15, 33, 48, 71, 92, 91, 73, 57, 45, 24, -3, -38, -68, -79, + -77, -76, -80, -74, -51, -19, 12, 32, 46, 65, 88, 96, 83, 59, 40, 24, + 4, -31, -67, -83, -80, -73, -73, -72, -55, -24, 9, 31, 44, 58, 78, 90, + 84, 63, 42, 28, 10, -18, -53, -77, -82, -76, -73, -74, -65, -37, -2, 27, + 42, 55, 73, 88, 90, 72, 47, 28, 13, -12, -45, -74, -84, -78, -70, -68, + -63, -43, -9, 23, 42, 52, 64, 78, 84, 75, 52, 32, 17, -3, -32, -62, + -79, -78, -71, -67, -65, -52, -19, 15, 38, 50, 61, 73, 80, 79, 59, 34, + 18, 3, -21, -51, -75, -81, -72, -64, -61, -54, -31, 4, 31, 48, 55, 63, + 73, 78, 67, 40, 21, 8, -12, -39, -65, -80, -76, -65, -58, -52, -38, -8, + 25, 45, 56, 61, 67, 74, 69, 47, 22, 7, -10, -31, -56, -75, -77, -66, + -57, -49, -37, -14, 16, 40, 53, 57, 61, 67, 69, 55, 30, 11, -6, -25, + -47, -69, -78, -70, -59, -51, -40, -20, 10, 34, 51, 58, 59, 63, 66, 59, + 36, 14, -2, -19, -40, -61, -75, -71, -59, -51, -41, -27, -2, 26, 47, 58, + 58, 59, 64, 63, 46, 19, -2, -17, -35, -56, -71, -75, -64, -50, -40, -26, + -6, 21, 43, 55, 57, 56, 58, 59, 47, 23, 1, -13, -29, -48, -63, -69, + -61, -48, -40, -29, -11, 13, 35, 48, 53, 51, 53, 57, 50, 33, 9, -10, + -25, -42, -56, -65, -64, -51, -40, -29, -13, 9, 30, 44, 50, 48, 47, 50, + 46, 35, 13, -8, -20, -33, -47, -57, -56, -48, -38, -30, -16, 1, 21, 35, + 44, 46, 42, 44, 44, 39, 21, -3, -18, -30, -40, -51, -57, -51, -37, -26, + -14, 0, 16, 33, 42, 43, 37, 34, 37, 35, 22, 1, -17, -27, -34, -41, + -48, -45, -36, -25, -11, 0, 11, 24, 34, 38, 35, 30, 29, 30, 24, 8, + -11, -24, -31, -36, -42, -42, -35, -25, -12, -2, 9, 21, 29, 33, 32, 27, + 25, 26, 23, 9, -8, -21, -31, -34, -36, -37, -33, -26, -13, -2, 8, 18, + 24, 28, 29, 27, 22, 20, 21, 14, -2, -17, -27, -30, -31, -33, -32, -26, + -14, -3, 6, 15, 22, 27, 26, 25, 22, 17, 17, 13, 3, -12, -25, -30, + -31, -30, -27, -24, -14, 0, 8, 16, 20, 22, 22, 21, 16, 11, 13, 13, + 3, -8, -21, -27, -26, -25, -25, -23, -12, 0, 6, 12, 18, 20, 22, 20, + 15, 9, 9, 10, 3, -9, -21, -29, -28, -23, -20, -19, -10, 3, 13, 17, + 19, 19, 21, 17, 11, 4, 1, 4, 0, -8, -17, -25, -24, -21, -19, -16, + -9, 4, 13, 17, 19, 20, 22, 19, 11, 3, -4, -3, -4, -12, -18, -26, + -28, -23, -16, -10, -5, 5, 18, 25, 25, 22, 21, 19, 9, 0, -9, -11, + -10, -13, -16, -24, -27, -22, -14, -8, -2, 7, 17, 25, 25, 22, 20, 17, + 10, -2, -10, -12, -13, -15, -18, -20, -24, -22, -16, -8, 3, 11, 17, 25, + 27, 23, 21, 17, 9, 0, -10, -12, -13, -18, -19, -20, -24, -23, -17, -10, + 0, 11, 19, 26, 30, 26, 24, 20, 12, 3, -8, -15, -18, -22, -25, -25, + -25, -24, -20, -12, 2, 15, 20, 25, 31, 33, 29, 23, 12, 3, -5, -15, + -23, -28, -28, -25, -22, -22, -18, -10, 2, 15, 19, 23, 30, 32, 28, 24, + 15, 7, 1, -13, -23, -27, -29, -28, -26, -24, -20, -14, -2, 13, 20, 24, + 32, 34, 32, 29, 22, 9, -2, -10, -21, -30, -34, -34, -29, -22, -20, -18, + -5, 14, 23, 25, 31, 36, 35, 30, 22, 10, 0, -8, -21, -34, -39, -36, + -32, -27, -20, -15, -5, 14, 27, 28, 32, 36, 35, 33, 25, 14, 0, -11, + -21, -34, -40, -41, -39, -30, -20, -13, -6, 10, 27, 30, 32, 35, 34, 36, + 29, 17, 5, -7, -16, -33, -45, -45, -43, -33, -24, -18, -9, 8, 26, 32, + 33, 39, 38, 36, 31, 20, 10, -6, -19, -32, -45, -47, -46, -39, -25, -12, + -3, 8, 22, 32, 32, 35, 35, 32, 31, 23, 14, 0, -15, -26, -43, -51, + -50, -43, -29, -17, -6, 5, 19, 34, 36, 33, 37, 37, 34, 25, 16, 5, + -11, -26, -41, -51, -55, -51, -36, -21, -7, 7, 16, 28, 37, 35, 35, 36, + 34, 30, 20, 9, -7, -22, -37, -49, -56, -54, -42, -25, -11, 2, 13, 24, + 35, 38, 37, 38, 37, 32, 25, 16, 1, -21, -38, -47, -56, -58, -50, -34, + -14, 4, 13, 20, 31, 40, 39, 35, 36, 34, 28, 20, 5, -15, -33, -44, + -55, -63, -54, -38, -19, -2, 10, 17, 30, 40, 41, 36, 38, 41, 33, 22, + 9, -13, -36, -50, -55, -63, -61, -44, -22, 2, 18, 22, 28, 38, 42, 39, + 34, 35, 34, 27, 14, -7, -29, -43, -51, -60, -63, -50, -30, -10, 8, 16, + 21, 32, 40, 40, 38, 39, 41, 35, 24, 6, -20, -41, -54, -62, -65, -58, + -39, -16, 7, 18, 22, 29, 39, 43, 40, 35, 38, 37, 27, 12, -14, -37, + -51, -58, -64, -64, -47, -22, -2, 14, 18, 24, 36, 44, 45, 41, 43, 43, + 32, 17, -8, -35, -54, -63, -67, -68, -56, -29, -4, 16, 24, 26, 35, 44, + 47, 43, 38, 38, 36, 24, 0, -30, -50, -57, -59, -63, -61, -40, -11, 11, + 20, 20, 26, 39, 48, 46, 40, 39, 42, 33, 12, -20, -47, -58, -60, -62, + -61, -49, -23, 2, 17, 21, 22, 33, 48, 51, 45, 43, 43, 38, 20, -10, + -41, -58, -61, -64, -62, -55, -35, -9, 10, 21, 23, 32, 50, 57, 49, 45, + 45, 43, 26, -6, -38, -58, -62, -65, -67, -61, -44, -15, 10, 23, 26, 28, + 44, 59, 55, 46, 42, 41, 33, 6, -30, -57, -64, -62, -64, -62, -50, -26, + 2, 18, 26, 28, 39, 59, 60, 48, 43, 43, 37, 14, -22, -53, -67, -63, + -65, -66, -55, -33, -2, 19, 28, 31, 37, 55, 64, 53, 41, 39, 37, 20, + -16, -48, -66, -65, -62, -66, -60, -43, -12, 15, 26, 31, 37, 53, 69, 63, + 46, 39, 38, 27, -5, -44, -72, -73, -65, -65, -63, -52, -24, 11, 31, 36, + 38, 48, 65, 70, 53, 38, 34, 28, 5, -35, -69, -78, -70, -65, -63, -53, + -30, 2, 26, 38, 43, 49, 62, 69, 58, 40, 33, 28, 9, -25, -61, -78, + -75, -69, -64, -55, -37, -7, 22, 36, 43, 49, 57, 66, 62, 44, 31, 29, + 15, -16, -52, -76, -77, -69, -63, -57, -44, -16, 14, 33, 42, 48, 54, 65, + 68, 52, 33, 27, 19, -6, -41, -72, -82, -74, -65, -59, -48, -24, 7, 29, + 43, 50, 53, 60, 67, 58, 39, 28, 22, 2, -31, -64, -82, -79, -71, -61, + -49, -31, -2, 22, 40, 51, 55, 58, 65, 63, 46, 29, 21, 9, -21, -56, + -79, -83, -77, -65, -54, -37, -10, 16, 36, 50, 57, 60, 65, 64, 50, 33, + 22, 11, -13, -47, -73, -82, -80, -70, -57, -42, -19, 8, 30, 49, 58, 61, + 62, 64, 56, 41, 24, 11, -6, -35, -66, -80, -82, -75, -61, -45, -25, -2, + 22, 43, 57, 63, 64, 63, 58, 49, 31, 15, -2, -26, -58, -79, -85, -81, + -66, -49, -31, -9, 17, 39, 55, 64, 69, 67, 61, 53, 35, 16, 1, -20, + -49, -75, -86, -85, -74, -54, -34, -11, 11, 33, 53, 64, 70, 68, 59, 51, + 40, 22, 5, -15, -40, -66, -79, -81, -78, -63, -41, -19, 4, 25, 44, 58, + 67, 72, 65, 57, 47, 29, 11, -8, -31, -61, -81, -85, -82, -68, -47, -25, + -3, 21, 44, 59, 68, 73, 68, 56, 47, 33, 15, -7, -27, -52, -76, -82, + -82, -72, -52, -30, -7, 13, 36, 57, 67, 74, 72, 61, 48, 36, 20, -4, + -25, -47, -71, -81, -81, -75, -56, -33, -10, 11, 30, 49, 63, 73, 74, 63, + 48, 37, 25, 6, -20, -41, -63, -79, -81, -77, -65, -43, -19, 4, 25, 45, + 63, 73, 76, 70, 55, 41, 28, 10, -15, -38, -59, -77, -83, -79, -70, -49, + -25, -4, 20, 40, 59, 74, 76, 73, 62, 46, 33, 16, -10, -34, -51, -68, + -83, -85, -75, -58, -34, -11, 14, 35, 55, 73, 79, 76, 69, 51, 33, 20, + -2, -30, -53, -67, -81, -84, -76, -61, -39, -14, 11, 32, 49, 67, 77, 74, + 68, 55, 37, 23, 5, -22, -45, -59, -73, -84, -82, -68, -46, -24, 3, 26, + 43, 62, 75, 74, 72, 61, 42, 25, 10, -15, -40, -57, -70, -83, -84, -71, + -49, -28, -6, 20, 41, 59, 72, 72, 69, 63, 48, 29, 13, -8, -31, -51, + -66, -79, -84, -75, -56, -37, -16, 12, 36, 55, 71, 74, 72, 69, 54, 34, + 16, -5, -28, -47, -61, -75, -85, -80, -60, -38, -20, 4, 30, 53, 68, 71, + 69, 67, 57, 39, 20, 0, -21, -41, -58, -71, -79, -79, -66, -45, -25, -3, + 23, 45, 61, 68, 69, 70, 63, 47, 29, 8, -16, -37, -56, -71, -80, -81, + -71, -52, -30, -7, 17, 41, 60, 67, 67, 68, 65, 50, 30, 10, -14, -31, + -47, -65, -77, -79, -70, -53, -33, -14, 8, 34, 56, 62, 62, 66, 64, 54, + 36, 15, -8, -27, -42, -61, -73, -75, -70, -56, -36, -14, 5, 26, 49, 60, + 59, 61, 60, 54, 42, 23, -2, -22, -35, -53, -69, -75, -70, -58, -41, -20, + -3, 18, 43, 59, 57, 57, 60, 56, 44, 28, 7, -17, -32, -47, -63, -73, + -72, -62, -46, -23, -6, 12, 35, 55, 60, 57, 59, 56, 49, 35, 14, -13, + -28, -40, -58, -72, -73, -62, -50, -31, -13, 5, 30, 51, 59, 56, 58, 61, + 56, 38, 17, -9, -26, -37, -52, -68, -74, -63, -50, -32, -14, 1, 22, 45, + 57, 56, 51, 54, 54, 41, 21, -4, -22, -31, -44, -59, -69, -63, -48, -36, + -21, -7, 11, 35, 52, 56, 53, 54, 58, 48, 30, 8, -17, -32, -43, -57, + -68, -69, -56, -39, -22, -8, 6, 28, 49, 57, 54, 51, 55, 52, 35, 13, + -13, -29, -36, -49, -64, -70, -58, -39, -23, -11, 0, 19, 43, 57, 55, 47, + 49, 55, 43, 18, -9, -28, -35, -42, -57, -69, -65, -45, -25, -11, 1, 14, + 37, 55, 60, 50, 45, 48, 42, 21, -4, -25, -35, -40, -50, -60, -61, -46, + -27, -15, -6, 6, 25, 46, 56, 50, 43, 45, 47, 33, 9, -15, -30, -37, + -45, -58, -64, -56, -36, -18, -8, 4, 18, 40, 58, 59, 47, 39, 41, 35, + 12, -15, -32, -38, -39, -46, -57, -55, -37, -17, -7, 1, 11, 27, 48, 56, + 47, 37, 38, 38, 21, -6, -24, -32, -37, -43, -54, -57, -44, -25, -9, 2, + 11, 24, 44, 57, 51, 38, 32, 31, 21, -5, -28, -35, -36, -36, -45, -51, + -41, -25, -8, 3, 8, 17, 33, 48, 49, 37, 31, 30, 25, 7, -18, -30, + -34, -37, -40, -48, -47, -33, -16, 1, 11, 16, 28, 42, 50, 43, 30, 25, + 22, 10, -12, -28, -33, -34, -35, -41, -44, -33, -18, -2, 9, 12, 20, 32, + 43, 41, 29, 24, 22, 14, -3, -21, -29, -30, -31, -35, -41, -35, -21, -6, + 9, 13, 18, 27, 38, 42, 29, 18, 16, 13, 4, -15, -27, -28, -27, -28, + -34, -34, -23, -10, 5, 11, 14, 22, 32, 37, 31, 20, 16, 12, 6, -9, + -22, -25, -27, -26, -32, -34, -27, -15, 0, 10, 12, 18, 28, 36, 35, 23, + 14, 11, 8, -3, -19, -28, -28, -25, -27, -32, -28, -16, -2, 11, 14, 14, + 22, 30, 31, 24, 15, 11, 8, 2, -11, -22, -25, -25, -26, -30, -28, -18, + -7, 5, 12, 14, 19, 27, 30, 26, 19, 13, 9, 4, -6, -20, -26, -23, + -24, -27, -27, -19, -6, 4, 12, 12, 13, 22, 26, 22, 15, 11, 10, 6, + -2, -12, -19, -19, -21, -25, -25, -20, -11, -3, 5, 9, 13, 19, 24, 24, + 21, 15, 12, 7, 2, -9, -20, -22, -22, -23, -24, -22, -11, -2, 7, 11, + 13, 17, 21, 21, 18, 13, 11, 7, 1, -7, -15, -19, -19, -21, -20, -18, + -12, -4, 2, 8, 11, 15, 17, 16, 15, 13, 11, 8, 4, -3, -11, -16, + -15, -19, -20, -16, -12, -5, 2, 5, 8, 14, 17, 15, 11, 10, 9, 8, + 4, -2, -6, -11, -12, -14, -18, -13, -7, -6, -3, 2, 6, 10, 13, 13, + 9, 8, 9, 6, 1, 0, -5, -9, -12, -12, -13, -12, -4, 1, 3, 4, + 4, 7, 11, 10, 7, 3, 3, 4, 2, -2, -3, -6, -7, -6, -6, -8, + -5, 2, 1, 1, 0, 1, 5, 5, 3, 0, 0, 5, 5, 2, 3, 0, + -3, -5, -6, -8, -7, -2, -3, -4, -2, -2, 3, 6, 4, 1, -3, 1, + 5, 3, 2, 0, -2, -3, -4, -5, -5, 1, 2, -3, -3, -4, -3, 4, + 4, 0, -5, -3, 3, 3, 2, 1, 1, 0, 0, 0, -3, -2, 1, -2, + -4, -3, -4, 1, 5, 2, -5, -7, -2, 2, -2, -2, 0, 2, 3, 2, + 2, 3, 6, 4, -2, -5, -6, -2, 3, -2, -9, -11, -5, 0, -3, -4, + -2, 3, 7, 8, 4, 2, 4, 3, 0, -6, -8, -6, 2, 4, -3, -10, + -10, -5, -2, -4, -5, -3, 5, 11, 11, 8, 5, 5, 4, -2, -9, -9, + -2, 0, -5, -13, -14, -10, -5, -4, -2, 2, 6, 14, 15, 11, 8, 6, + 1, -5, -10, -12, -6, 1, -2, -10, -15, -11, -4, -3, -6, -5, 2, 14, + 19, 14, 10, 10, 8, 3, -6, -15, -12, -4, -4, -12, -18, -17, -10, -2, + 0, 1, 6, 16, 25, 21, 12, 8, 4, -2, -8, -18, -20, -11, -6, -9, + -14, -14, -10, -3, 0, 1, 6, 13, 23, 25, 17, 13, 9, 1, -6, -13, + -18, -14, -11, -13, -17, -19, -14, -8, -3, 1, 7, 14, 24, 30, 24, 16, + 12, 4, -5, -11, -18, -19, -15, -12, -14, -19, -18, -14, -9, 0, 8, 13, + 19, 27, 28, 22, 18, 9, -4, -11, -14, -16, -15, -16, -16, -17, -16, -14, + -13, -6, 4, 12, 19, 26, 31, 27, 19, 13, 3, -8, -12, -16, -18, -19, + -17, -16, -20, -18, -15, -10, 1, 10, 18, 24, 31, 30, 22, 18, 9, -4, + -10, -14, -17, -20, -22, -19, -19, -22, -18, -13, -2, 9, 16, 21, 29, 36, + 29, 19, 12, 1, -7, -10, -15, -22, -24, -20, -18, -21, -21, -17, -8, 7, + 16, 23, 27, 33, 35, 26, 17, 7, -5, -11, -14, -22, -27, -24, -19, -22, + -25, -19, -11, 5, 16, 21, 25, 33, 38, 31, 18, 9, -2, -10, -13, -22, + -29, -28, -21, -18, -24, -22, -15, -3, 14, 21, 24, 30, 38, 36, 24, 13, + 4, -5, -9, -16, -28, -32, -25, -21, -25, -27, -18, -7, 8, 18, 24, 31, + 40, 40, 29, 16, 6, -3, -8, -16, -27, -31, -27, -22, -24, -27, -21, -10, + 4, 16, 22, 28, 37, 40, 33, 19, 7, 1, -5, -12, -23, -32, -28, -23, + -23, -27, -26, -15, -2, 13, 21, 25, 34, 41, 38, 28, 14, 4, -3, -11, + -22, -34, -35, -30, -26, -28, -29, -20, -3, 14, 24, 27, 32, 41, 42, 34, + 17, 4, -4, -11, -20, -32, -38, -33, -28, -27, -27, -22, -9, 7, 20, 29, + 34, 39, 40, 37, 24, 10, 2, -7, -16, -28, -40, -40, -33, -29, -28, -27, + -16, 5, 21, 28, 32, 36, 41, 40, 30, 12, 1, -6, -11, -22, -37, -42, + -34, -30, -29, -27, -20, -3, 16, 27, 32, 34, 39, 41, 35, 20, 6, -4, + -11, -16, -32, -45, -41, -33, -31, -27, -23, -10, 13, 28, 33, 35, 38, 39, + 36, 25, 8, -6, -11, -14, -26, -42, -45, -34, -29, -25, -23, -15, 6, 26, + 36, 36, 36, 37, 36, 29, 14, -2, -12, -14, -23, -42, -50, -42, -32, -23, + -18, -15, 3, 25, 38, 39, 35, 35, 37, 33, 18, -3, -15, -18, -20, -34, + -48, -47, -34, -22, -14, -12, -4, 17, 35, 41, 37, 34, 33, 33, 24, 6, + -13, -22, -22, -30, -45, -51, -39, -23, -10, -6, -3, 13, 32, 41, 37, 30, + 29, 31, 27, 10, -10, -22, -23, -26, -38, -48, -44, -28, -12, -5, -3, 9, + 27, 38, 38, 32, 28, 29, 27, 17, -4, -21, -26, -27, -35, -47, -49, -33, + -12, 2, 5, 9, 23, 35, 40, 34, 21, 23, 25, 22, 5, -20, -28, -28, + -29, -39, -50, -43, -19, 3, 10, 7, 15, 29, 41, 43, 28, 22, 23, 22, + 12, -16, -33, -32, -32, -38, -46, -43, -21, 3, 15, 13, 16, 29, 35, 35, + 27, 19, 19, 19, 15, -8, -30, -31, -30, -32, -40, -44, -29, -2, 18, 17, + 11, 22, 34, 37, 32, 21, 18, 20, 17, -2, -28, -37, -34, -34, -38, -42, + -30, -7, 16, 22, 16, 20, 31, 31, 29, 23, 17, 18, 19, 6, -21, -37, + -35, -34, -35, -38, -35, -15, 14, 27, 21, 13, 23, 31, 31, 26, 16, 12, + 16, 12, -10, -35, -39, -35, -36, -36, -34, -21, 6, 24, 24, 16, 20, 29, + 28, 27, 22, 16, 17, 15, -4, -29, -41, -39, -40, -39, -36, -29, -6, 20, + 27, 21, 19, 28, 33, 31, 27, 18, 14, 13, 2, -22, -41, -43, -40, -39, + -34, -28, -12, 16, 28, 24, 19, 25, 29, 27, 24, 19, 15, 12, 4, -15, + -34, -41, -40, -37, -32, -26, -18, 5, 24, 24, 20, 21, 26, 27, 26, 24, + 18, 12, 6, -9, -30, -44, -45, -41, -33, -26, -19, -2, 23, 29, 24, 22, + 24, 28, 25, 22, 18, 13, 7, -7, -24, -40, -46, -42, -36, -28, -21, -6, + 15, 28, 25, 22, 25, 29, 28, 23, 20, 14, 6, -6, -22, -40, -47, -42, + -36, -28, -23, -10, 13, 30, 28, 21, 23, 27, 28, 21, 18, 16, 9, -2, + -17, -33, -44, -44, -38, -31, -23, -14, 5, 25, 32, 25, 23, 26, 29, 24, + 16, 13, 8, -2, -15, -31, -43, -44, -37, -30, -23, -14, 1, 21, 31, 27, + 22, 24, 28, 25, 17, 13, 10, 3, -10, -27, -40, -44, -38, -32, -26, -17, + -3, 16, 31, 31, 25, 25, 30, 29, 17, 8, 7, 3, -8, -25, -39, -43, + -37, -31, -27, -18, -4, 13, 29, 32, 26, 24, 27, 27, 17, 9, 8, 6, + -5, -20, -34, -39, -37, -34, -30, -21, -8, 6, 23, 34, 31, 29, 28, 27, + 22, 13, 6, 5, -4, -18, -34, -40, -37, -34, -29, -23, -10, 5, 21, 32, + 29, 27, 29, 26, 20, 12, 4, 3, 0, -12, -28, -37, -35, -31, -29, -23, + -13, 1, 16, 30, 33, 29, 27, 25, 21, 15, 5, -2, -3, -9, -22, -35, + -36, -31, -29, -24, -14, 0, 12, 27, 35, 31, 29, 26, 21, 16, 8, -2, + -3, -7, -19, -34, -36, -32, -31, -28, -18, -3, 11, 22, 32, 32, 30, 29, + 23, 16, 11, 2, -3, -6, -17, -32, -37, -32, -30, -31, -23, -6, 9, 18, + 30, 36, 32, 31, 25, 17, 13, 4, -6, -8, -14, -26, -36, -34, -31, -31, + -25, -11, 6, 16, 24, 34, 35, 33, 28, 17, 16, 10, -3, -9, -13, -23, + -34, -36, -32, -31, -27, -16, 2, 16, 22, 30, 35, 33, 30, 21, 15, 11, + 0, -7, -11, -20, -31, -35, -31, -31, -29, -21, -6, 13, 21, 25, 32, 34, + 33, 26, 18, 13, 4, -6, -10, -19, -29, -34, -34, -29, -27, -24, -12, 7, + 20, 25, 30, 33, 32, 29, 21, 13, 7, -5, -11, -18, -28, -35, -36, -29, + -25, -24, -16, 3, 21, 26, 28, 34, 37, 34, 26, 12, 4, -5, -13, -20, + -30, -35, -39, -35, -24, -19, -13, -2, 15, 27, 30, 32, 34, 31, 28, 18, + 5, -6, -15, -20, -24, -31, -37, -35, -24, -19, -16, -9, 8, 24, 30, 30, + 33, 35, 35, 24, 5, -5, -11, -20, -27, -34, -40, -39, -30, -21, -16, -9, + 4, 20, 32, 36, 36, 36, 35, 31, 13, -3, -13, -23, -27, -29, -41, -44, + -33, -19, -11, -10, -4, 14, 32, 38, 34, 33, 36, 33, 18, -4, -13, -20, + -25, -28, -37, -43, -34, -22, -14, -8, -4, 9, 26, 39, 38, 35, 35, 34, + 23, 3, -12, -21, -28, -28, -31, -41, -40, -27, -15, -7, -6, 2, 20, 37, + 42, 36, 34, 35, 28, 9, -10, -18, -24, -26, -29, -38, -42, -32, -21, -11, + -6, -3, 12, 33, 45, 41, 37, 37, 29, 13, -4, -17, -26, -28, -28, -33, + -39, -37, -26, -15, -8, -7, 6, 29, 47, 46, 39, 34, 30, 20, 1, -18, + -26, -26, -25, -29, -37, -40, -31, -17, -8, -7, 0, 20, 42, 51, 45, 38, + 30, 18, 7, -10, -24, -27, -26, -24, -29, -38, -37, -27, -14, -9, -6, 11, + 36, 51, 47, 42, 34, 24, 14, -3, -20, -25, -23, -22, -26, -37, -42, -33, + -17, -8, -7, 4, 28, 50, 54, 45, 35, 24, 15, 3, -16, -24, -25, -22, + -23, -32, -41, -37, -22, -11, -8, 0, 21, 44, 54, 46, 34, 26, 18, 7, + -11, -22, -21, -20, -21, -28, -40, -43, -30, -15, -10, -3, 16, 40, 56, 52, + 37, 24, 16, 9, -6, -21, -22, -18, -17, -22, -35, -43, -34, -21, -14, -9, + 7, 34, 53, 54, 40, 29, 21, 14, 4, -14, -21, -17, -17, -22, -33, -46, + -45, -31, -16, -8, 4, 25, 50, 60, 49, 31, 20, 15, 9, -5, -17, -18, + -15, -17, -26, -42, -50, -40, -24, -11, -2, 18, 43, 56, 52, 35, 21, 17, + 11, 0, -12, -18, -14, -15, -22, -36, -50, -46, -30, -15, -3, 12, 35, 53, + 55, 41, 24, 18, 12, 5, -4, -15, -18, -15, -20, -33, -46, -49, -37, -21, + -7, 7, 25, 46, 54, 45, 27, 18, 14, 10, 3, -8, -15, -16, -18, -28, + -41, -49, -44, -29, -12, 4, 17, 35, 49, 49, 34, 19, 16, 15, 9, 1, + -10, -14, -16, -24, -38, -50, -49, -36, -18, -3, 10, 26, 43, 49, 38, 22, + 18, 20, 16, 9, -5, -13, -16, -23, -36, -50, -53, -43, -25, -8, 6, 21, + 38, 48, 44, 27, 19, 21, 19, 13, -2, -13, -17, -21, -30, -45, -52, -46, + -29, -10, 3, 14, 29, 42, 44, 30, 17, 19, 21, 17, 6, -8, -14, -19, + -26, -39, -49, -48, -36, -18, -2, 11, 27, 37, 42, 37, 22, 18, 21, 19, + 9, -5, -13, -18, -24, -33, -45, -46, -39, -24, -8, 6, 20, 33, 40, 38, + 27, 19, 22, 23, 17, 4, -8, -14, -22, -29, -43, -48, -43, -32, -16, -2, + 13, 25, 34, 39, 33, 23, 21, 23, 20, 9, -4, -11, -19, -25, -33, -43, + -42, -34, -20, -7, 3, 14, 24, 32, 31, 22, 20, 26, 28, 20, 6, -5, + -11, -18, -28, -42, -44, -38, -28, -15, -5, 8, 19, 28, 31, 24, 21, 25, + 27, 22, 10, 0, -6, -12, -22, -34, -38, -34, -30, -20, -11, 0, 11, 20, + 26, 23, 19, 22, 27, 25, 17, 7, -2, -7, -17, -29, -35, -35, -34, -26, + -16, -5, 7, 15, 23, 28, 24, 21, 22, 24, 20, 11, -2, -8, -14, -24, + -29, -31, -31, -27, -18, -9, 0, 8, 15, 22, 23, 20, 21, 24, 24, 19, + 7, -4, -10, -19, -26, -32, -34, -33, -24, -12, -2, 6, 14, 22, 26, 23, + 22, 22, 22, 21, 10, 0, -6, -15, -21, -24, -28, -31, -28, -17, -7, 2, + 7, 13, 19, 23, 23, 21, 19, 21, 18, 8, -2, -11, -17, -21, -24, -30, + -33, -25, -11, 0, 4, 9, 16, 20, 21, 20, 18, 18, 20, 14, 4, -6, + -12, -15, -17, -25, -32, -32, -20, -6, -3, -3, 7, 18, 23, 19, 16, 19, + 26, 24, 11, 0, -6, -9, -15, -25, -33, -35, -26, -15, -9, -6, 5, 17, + 22, 21, 17, 18, 25, 26, 16, 4, -5, -7, -9, -18, -29, -38, -35, -21, + -11, -9, -4, 9, 22, 25, 20, 16, 22, 30, 24, 8, -4, -5, -5, -13, + -25, -36, -38, -26, -16, -11, -10, 2, 19, 25, 18, 12, 19, 30, 28, 14, + 1, -2, 3, -3, -17, -31, -36, -29, -21, -18, -19, -11, 7, 20, 16, 10, + 16, 30, 36, 24, 8, 4, 8, 6, -12, -32, -40, -35, -26, -21, -20, -14, + 2, 19, 20, 10, 12, 24, 35, 29, 13, 5, 7, 9, -3, -23, -37, -37, + -31, -23, -21, -19, -8, 12, 19, 10, 6, 19, 36, 37, 23, 11, 12, 16, + 7, -15, -35, -43, -38, -30, -27, -23, -16, 2, 18, 16, 7, 13, 30, 38, + 29, 17, 12, 16, 15, -4, -27, -40, -39, -32, -28, -28, -24, -8, 12, 14, + 5, 7, 26, 40, 36, 24, 18, 21, 21, 4, -20, -38, -41, -37, -34, -30, + -26, -15, 4, 14, 7, 3, 18, 37, 41, 33, 24, 22, 25, 14, -10, -33, + -44, -42, -36, -32, -29, -22, -6, 10, 9, 2, 9, 29, 40, 37, 32, 28, + 29, 21, 0, -24, -39, -44, -44, -38, -31, -24, -16, 0, 7, 3, 8, 24, + 38, 43, 41, 32, 28, 25, 9, -15, -34, -44, -44, -39, -31, -26, -20, -10, + 3, 2, 1, 14, 32, 44, 46, 39, 33, 31, 20, -7, -31, -45, -47, -44, + -38, -30, -26, -16, 0, 5, 4, 12, 30, 45, 52, 47, 36, 30, 22, 0, + -24, -40, -50, -49, -42, -31, -24, -19, -10, -3, 3, 11, 24, 39, 51, 55, + 49, 37, 27, 8, -18, -36, -50, -54, -47, -36, -29, -25, -16, -6, 4, 10, + 18, 34, 52, 59, 53, 39, 28, 15, -8, -29, -45, -53, -51, -43, -34, -29, + -23, -14, -4, 7, 17, 33, 52, 62, 61, 50, 37, 23, -4, -28, -44, -55, + -55, -48, -38, -30, -25, -18, -8, 5, 13, 25, 46, 61, 65, 57, 43, 30, + 8, -17, -36, -50, -55, -53, -47, -39, -32, -24, -15, -3, 11, 25, 45, 62, + 68, 63, 51, 37, 14, -14, -34, -46, -56, -57, -51, -44, -33, -25, -18, -6, + 8, 19, 36, 55, 67, 65, 53, 42, 23, -4, -26, -40, -50, -56, -54, -49, + -41, -31, -23, -12, 1, 15, 34, 53, 65, 68, 59, 49, 33, 6, -21, -37, + -47, -57, -60, -56, -48, -38, -28, -16, -2, 14, 33, 51, 64, 70, 63, 53, + 38, 13, -14, -34, -44, -53, -59, -59, -53, -42, -30, -19, -8, 5, 26, 47, + 61, 68, 64, 57, 48, 26, -3, -26, -39, -49, -58, -63, -59, -49, -37, -24, + -13, 1, 20, 42, 55, 65, 69, 64, 54, 34, 7, -18, -34, -44, -55, -65, + -64, -54, -42, -31, -19, -8, 12, 37, 54, 61, 67, 67, 60, 46, 22, -8, + -29, -40, -50, -64, -70, -63, -50, -34, -21, -13, 2, 28, 51, 62, 68, 68, + 61, 51, 32, 3, -23, -36, -47, -60, -70, -67, -58, -44, -27, -14, -2, 22, + 45, 58, 65, 70, 68, 56, 38, 16, -11, -32, -45, -58, -69, -70, -62, -52, + -34, -17, -6, 13, 38, 54, 64, 70, 67, 59, 47, 29, -2, -28, -40, -51, + -65, -74, -67, -54, -37, -20, -11, 5, 33, 53, 59, 63, 67, 62, 51, 34, + 7, -20, -35, -46, -59, -72, -70, -60, -46, -27, -12, 1, 24, 47, 60, 64, + 69, 66, 54, 39, 15, -13, -32, -44, -54, -68, -71, -60, -48, -32, -18, -7, + 14, 38, 54, 61, 68, 70, 60, 46, 26, -2, -23, -38, -50, -63, -72, -68, + -55, -39, -24, -13, 5, 31, 52, 61, 67, 71, 64, 53, 34, 7, -21, -36, + -46, -57, -69, -72, -60, -42, -27, -17, -2, 21, 45, 58, 65, 69, 66, 57, + 42, 15, -13, -30, -43, -54, -66, -72, -65, -47, -30, -18, -5, 15, 40, 57, + 64, 67, 62, 56, 46, 23, -6, -27, -39, -50, -58, -67, -67, -51, -32, -20, + -9, 9, 31, 51, 60, 64, 64, 58, 48, 27, 1, -20, -34, -46, -56, -65, + -70, -57, -37, -22, -14, 2, 26, 48, 62, 66, 64, 59, 51, 34, 8, -18, + -31, -42, -52, -61, -70, -63, -42, -24, -15, -3, 19, 43, 60, 63, 60, 57, + 52, 39, 14, -14, -28, -36, -46, -54, -65, -66, -49, -29, -17, -9, 10, 33, + 54, 64, 62, 58, 53, 42, 23, -5, -25, -35, -46, -54, -63, -67, -54, -33, + -17, -7, 7, 30, 51, 61, 58, 55, 51, 43, 28, 3, -21, -30, -37, -46, + -56, -63, -56, -39, -22, -12, -5, 16, 40, 57, 58, 55, 53, 48, 38, 19, + -10, -27, -35, -45, -56, -66, -65, -49, -28, -14, -6, 8, 34, 57, 60, 55, + 54, 50, 42, 26, -4, -28, -35, -42, -52, -62, -63, -51, -32, -14, -5, 3, + 24, 47, 57, 53, 50, 47, 41, 33, 11, -20, -35, -40, -46, -56, -65, -58, + -38, -17, -4, 1, 15, 41, 57, 55, 47, 45, 42, 35, 17, -13, -33, -38, + -41, -49, -58, -55, -41, -21, -4, 0, 7, 29, 50, 52, 45, 42, 40, 37, + 25, 0, -28, -38, -38, -44, -53, -58, -46, -26, -6, 3, 4, 18, 42, 53, + 47, 41, 39, 37, 30, 10, -21, -41, -43, -41, -47, -54, -46, -29, -8, 7, + 9, 13, 31, 46, 45, 37, 33, 33, 28, 15, -10, -35, -42, -38, -39, -45, + -46, -32, -10, 6, 9, 8, 19, 38, 44, 38, 30, 29, 30, 19, -3, -29, + -42, -38, -34, -40, -43, -32, -14, 3, 11, 11, 15, 30, 41, 39, 30, 25, + 25, 19, 4, -21, -40, -42, -32, -30, -33, -29, -15, 2, 11, 10, 8, 17, + 30, 35, 30, 23, 24, 23, 11, -11, -32, -43, -34, -26, -29, -29, -18, -3, + 9, 12, 9, 12, 26, 35, 32, 21, 18, 18, 12, -6, -29, -43, -36, -22, + -22, -25, -15, 1, 10, 11, 10, 8, 17, 29, 29, 21, 16, 17, 15, 2, + -21, -39, -39, -24, -17, -20, -16, -5, 9, 13, 10, 7, 12, 24, 28, 23, + 14, 12, 11, 4, -14, -33, -39, -28, -15, -14, -12, -6, 5, 11, 9, 7, + 7, 16, 26, 25, 16, 10, 11, 6, -8, -24, -37, -32, -17, -12, -11, -5, + 5, 11, 11, 10, 7, 12, 21, 21, 16, 7, 4, 3, -6, -20, -32, -32, + -20, -8, -5, 0, 5, 11, 11, 9, 8, 8, 13, 17, 16, 9, 3, 2, + -3, -13, -25, -31, -23, -9, -4, -2, 5, 11, 14, 11, 7, 6, 12, 15, + 12, 5, -2, -2, -3, -11, -22, -29, -24, -9, 0, 3, 8, 13, 13, 12, + 8, 4, 5, 7, 9, 6, -3, -5, -4, -5, -14, -24, -23, -13, 0, 4, + 6, 10, 14, 14, 9, 3, 3, 5, 6, 4, -4, -6, -5, -5, -9, -18, + -20, -15, -4, 6, 9, 11, 13, 13, 10, 5, 1, 0, -3, 0, -4, -6, + -6, -5, -4, -11, -16, -16, -9, 3, 8, 11, 11, 10, 11, 8, 3, -2, + -5, -4, -3, -5, -6, -6, -2, -5, -12, -15, -13, -2, 8, 9, 11, 11, + 11, 7, 4, 0, -6, -6, -4, -4, -6, -6, -2, 0, -7, -13, -15, -5, + 8, 13, 12, 9, 11, 9, 4, -5, -11, -11, -8, -5, -5, -5, 0, 4, + 3, -4, -11, -8, 3, 11, 12, 8, 7, 4, 2, -2, -10, -14, -13, -7, + -3, -4, -2, 3, 4, 1, -8, -8, 3, 13, 17, 12, 11, 7, 1, -6, + -16, -21, -19, -13, -7, -2, 3, 7, 10, 10, 1, -6, -2, 8, 14, 12, + 10, 4, -2, -6, -15, -21, -20, -15, -8, -2, 3, 5, 9, 14, 5, -6, + 1, 12, 18, 14, 9, 7, 2, -4, -18, -28, -27, -22, -12, -5, 3, 9, + 13, 18, 16, 5, 1, 7, 14, 13, 8, 5, -5, -9, -17, -26, -26, -23, + -15, -4, 5, 8, 11, 17, 17, 7, 2, 7, 16, 18, 10, 4, -2, -6, + -16, -31, -33, -27, -18, -9, 0, 7, 12, 18, 22, 16, 9, 9, 16, 20, + 13, 5, -2, -9, -18, -33, -37, -29, -22, -13, -4, 7, 15, 21, 25, 21, + 15, 13, 17, 20, 14, 5, -3, -8, -18, -35, -42, -36, -24, -16, -6, 5, + 13, 23, 27, 25, 20, 17, 19, 20, 15, 5, -3, -8, -21, -35, -45, -39, + -25, -18, -11, 3, 16, 25, 29, 27, 26, 24, 23, 21, 17, 8, -4, -12, + -23, -35, -46, -46, -34, -22, -15, -3, 13, 25, 31, 33, 34, 31, 28, 25, + 20, 11, -4, -12, -22, -38, -49, -51, -39, -26, -21, -11, 8, 24, 34, 35, + 36, 37, 35, 29, 21, 13, 0, -11, -20, -36, -48, -52, -46, -31, -22, -14, + 1, 19, 34, 38, 39, 40, 38, 34, 24, 15, 0, -14, -21, -34, -47, -53, + -50, -35, -22, -17, -5, 13, 31, 37, 38, 42, 41, 37, 28, 21, 9, -8, + -19, -30, -44, -50, -53, -46, -32, -23, -11, 7, 26, 39, 43, 49, 48, 42, + 32, 20, 9, -9, -21, -31, -46, -52, -54, -50, -35, -24, -13, 4, 23, 40, + 46, 48, 49, 46, 37, 26, 13, -4, -20, -29, -42, -50, -53, -54, -43, -31, + -21, -2, 17, 36, 47, 53, 56, 51, 42, 29, 17, 3, -16, -30, -41, -51, + -55, -57, -51, -35, -24, -9, 11, 30, 47, 53, 57, 55, 46, 34, 20, 6, + -12, -29, -43, -52, -55, -55, -55, -42, -29, -12, 8, 25, 41, 55, 62, 59, + 51, 37, 23, 10, -6, -24, -40, -51, -56, -58, -58, -48, -33, -19, 2, 22, + 41, 55, 61, 61, 56, 45, 28, 11, -3, -19, -37, -51, -57, -58, -58, -54, + -39, -23, -2, 20, 36, 52, 64, 65, 58, 48, 33, 19, 4, -13, -35, -51, + -58, -61, -62, -60, -47, -29, -7, 17, 34, 50, 67, 70, 62, 50, 35, 20, + 6, -8, -29, -47, -57, -62, -61, -60, -54, -37, -15, 10, 29, 44, 60, 68, + 66, 56, 42, 24, 12, 1, -19, -41, -55, -60, -62, -61, -57, -43, -21, 7, + 24, 36, 53, 66, 67, 59, 46, 30, 15, 5, -11, -32, -48, -58, -63, -62, + -59, -50, -32, -3, 22, 35, 49, 60, 66, 63, 53, 38, 19, 8, -5, -25, + -43, -57, -64, -64, -62, -54, -39, -13, 16, 32, 46, 59, 65, 66, 56, 45, + 26, 11, 3, -17, -39, -56, -65, -67, -62, -56, -44, -21, 10, 29, 40, 54, + 63, 68, 61, 49, 33, 13, 2, -14, -34, -50, -64, -67, -63, -56, -44, -26, + 2, 27, 38, 49, 57, 64, 61, 50, 36, 17, 6, -7, -27, -44, -60, -67, + -63, -57, -48, -32, -7, 22, 36, 44, 53, 60, 62, 55, 41, 21, 7, -3, + -20, -40, -58, -68, -65, -57, -47, -34, -14, 16, 37, 42, 47, 55, 59, 53, + 42, 27, 10, -2, -14, -30, -47, -60, -63, -57, -49, -38, -20, 5, 30, 40, + 44, 52, 57, 57, 46, 31, 13, -2, -12, -27, -44, -57, -64, -61, -50, -38, + -20, 2, 25, 39, 41, 49, 55, 54, 45, 32, 17, 0, -12, -23, -37, -50, + -59, -61, -52, -38, -22, -6, 17, 35, 39, 42, 48, 53, 48, 36, 22, 4, + -9, -18, -30, -45, -56, -59, -54, -42, -27, -10, 12, 29, 37, 38, 44, 50, + 47, 37, 25, 9, -5, -13, -23, -38, -50, -55, -54, -45, -32, -17, 5, 25, + 34, 35, 39, 46, 48, 40, 29, 13, -3, -11, -21, -33, -44, -51, -54, -47, + -34, -17, 2, 21, 32, 34, 34, 38, 42, 39, 27, 15, 1, -7, -13, -25, + -36, -45, -49, -46, -36, -23, -6, 15, 27, 31, 31, 34, 39, 38, 30, 18, + 3, -6, -10, -19, -32, -40, -46, -45, -36, -24, -11, 8, 24, 29, 27, 29, + 34, 36, 30, 18, 4, -5, -5, -12, -25, -34, -39, -41, -37, -24, -11, 4, + 18, 24, 25, 25, 29, 29, 26, 19, 5, -6, -6, -6, -18, -28, -33, -37, + -34, -24, -11, 2, 15, 24, 23, 20, 24, 27, 22, 14, 4, -4, -4, -5, + -15, -24, -26, -29, -32, -27, -13, 2, 14, 21, 21, 18, 21, 23, 20, 13, + 5, -3, -5, -4, -9, -16, -21, -25, -28, -25, -14, 1, 10, 16, 19, 16, + 16, 18, 16, 11, 5, -2, -5, -4, -6, -12, -17, -20, -22, -22, -17, -4, + 8, 13, 16, 15, 13, 15, 14, 10, 4, -4, -6, -6, -5, -7, -11, -15, + -17, -17, -15, -3, 10, 13, 14, 11, 7, 8, 9, 5, -3, -8, -7, -4, + -2, -2, -6, -10, -9, -10, -12, -5, 11, 15, 13, 11, 5, 6, 7, 3, + -6, -10, -8, -6, -6, -2, 1, -2, -6, -6, -7, -5, 8, 14, 10, 7, + 4, 0, 1, -2, -6, -12, -11, -6, -2, 4, 8, 4, -2, -2, -4, -5, + 3, 12, 8, 5, 4, 0, 0, -2, -8, -13, -15, -12, -7, -3, 6, 10, + 7, 5, 6, 4, 6, 14, 10, 3, 0, -6, -10, -7, -10, -16, -19, -15, + -8, 0, 11, 17, 13, 10, 11, 7, 5, 8, 9, 2, -4, -7, -12, -10, + -10, -16, -21, -19, -13, -4, 10, 21, 22, 17, 17, 14, 9, 9, 9, 3, + -7, -12, -17, -16, -14, -20, -25, -21, -15, -5, 10, 23, 27, 25, 22, 18, + 11, 8, 4, -2, -9, -14, -18, -19, -14, -15, -23, -25, -20, -10, 9, 22, + 29, 29, 26, 23, 16, 12, 6, 1, -6, -14, -18, -22, -20, -19, -27, -28, + -25, -18, 0, 19, 32, 36, 33, 31, 23, 14, 7, 1, -4, -15, -23, -25, + -24, -19, -25, -32, -29, -20, -3, 16, 31, 40, 38, 36, 29, 16, 9, 1, + -4, -12, -23, -26, -28, -24, -26, -34, -33, -24, -8, 12, 29, 41, 44, 44, + 37, 22, 11, 4, -4, -11, -24, -31, -32, -31, -30, -36, -39, -30, -11, 11, + 29, 43, 51, 50, 44, 32, 15, 4, -4, -11, -24, -32, -33, -33, -34, -38, + -42, -35, -17, 4, 24, 42, 56, 60, 52, 38, 19, 7, 1, -13, -28, -37, + -37, -35, -37, -39, -43, -37, -19, 3, 22, 41, 57, 64, 57, 44, 26, 7, + -2, -11, -24, -35, -41, -40, -38, -39, -43, -40, -24, 0, 20, 37, 55, 65, + 63, 50, 32, 9, -4, -10, -24, -36, -42, -42, -41, -41, -41, -39, -26, -2, + 19, 34, 51, 64, 66, 55, 38, 15, -3, -8, -20, -34, -42, -44, -43, -44, + -45, -45, -35, -12, 14, 31, 50, 66, 73, 65, 49, 28, 7, -6, -18, -35, + -45, -49, -51, -53, -51, -47, -37, -16, 10, 30, 49, 69, 78, 72, 56, 35, + 14, -4, -17, -33, -46, -51, -55, -56, -54, -51, -40, -20, 5, 26, 44, 64, + 76, 77, 64, 41, 19, 1, -14, -30, -43, -50, -57, -60, -58, -54, -43, -24, + -2, 21, 39, 61, 76, 79, 72, 52, 28, 9, -10, -26, -41, -49, -54, -61, + -62, -59, -51, -33, -10, 14, 34, 55, 75, 81, 79, 63, 39, 19, -2, -23, + -40, -51, -56, -64, -67, -64, -56, -39, -16, 9, 29, 51, 73, 83, 82, 73, + 50, 27, 9, -18, -40, -52, -56, -63, -69, -69, -61, -43, -20, 2, 21, 42, + 66, 81, 82, 76, 59, 36, 19, -6, -33, -50, -57, -61, -71, -76, -68, -52, + -28, -2, 17, 36, 62, 83, 86, 82, 69, 43, 22, 2, -28, -51, -60, -63, + -67, -76, -74, -57, -34, -7, 14, 29, 53, 76, 87, 84, 75, 54, 33, 14, + -18, -46, -58, -62, -69, -80, -84, -68, -44, -18, 7, 26, 49, 75, 91, 92, + 82, 64, 42, 21, -8, -43, -63, -68, -68, -75, -86, -76, -48, -22, 4, 23, + 41, 66, 87, 92, 83, 69, 51, 31, 6, -31, -59, -67, -69, -74, -88, -87, + -62, -34, -7, 17, 36, 62, 87, 96, 90, 76, 60, 39, 14, -23, -58, -70, + -71, -73, -83, -89, -68, -37, -13, 9, 26, 51, 79, 94, 91, 80, 68, 52, + 28, -8, -48, -67, -70, -73, -84, -96, -83, -49, -22, 0, 20, 44, 75, 96, + 98, 88, 75, 61, 40, 6, -39, -67, -72, -75, -83, -95, -91, -60, -29, -7, + 13, 36, 66, 89, 97, 92, 78, 65, 50, 22, -21, -58, -71, -73, -78, -91, + -98, -79, -45, -15, 4, 25, 56, 84, 101, 99, 86, 73, 60, 35, -9, -53, + -72, -77, -80, -90, -98, -85, -51, -20, -2, 18, 48, 77, 96, 99, 87, 75, + 62, 46, 9, -39, -68, -75, -75, -83, -95, -94, -67, -30, -7, 8, 34, 68, + 92, 102, 93, 82, 72, 58, 26, -24, -61, -75, -78, -85, -97, -99, -78, -42, + -12, 6, 28, 59, 87, 102, 99, 86, 74, 62, 38, -7, -52, -76, -81, -83, + -93, -100, -90, -57, -23, -2, 18, 48, 80, 102, 103, 92, 81, 71, 51, 9, + -41, -72, -83, -85, -93, -100, -92, -65, -32, -7, 13, 39, 72, 97, 103, 95, + 85, 73, 55, 25, -21, -61, -79, -83, -90, -99, -97, -77, -45, -17, 1, 24, + 59, 93, 107, 103, 92, 85, 72, 42, -6, -54, -80, -86, -91, -104, -105, -87, + -56, -23, 0, 18, 48, 85, 106, 106, 96, 87, 77, 52, 13, -35, -71, -84, + -88, -98, -106, -96, -70, -40, -14, 6, 31, 70, 103, 111, 103, 95, 88, 68, + 29, -19, -61, -84, -91, -99, -106, -101, -80, -51, -22, 2, 23, 56, 91, 109, + 108, 98, 89, 76, 45, 1, -44, -76, -87, -92, -102, -104, -90, -64, -34, -11, + 8, 37, 78, 108, 113, 106, 96, 85, 61, 19, -29, -68, -88, -94, -102, -104, + -93, -73, -46, -21, 2, 28, 63, 98, 113, 109, 100, 89, 70, 33, -14, -55, + -81, -91, -98, -104, -98, -79, -54, -30, -9, 18, 52, 89, 108, 110, 104, 96, + 79, 46, 2, -40, -71, -90, -100, -104, -100, -86, -67, -44, -19, 7, 40, 77, + 105, 115, 109, 99, 86, 58, 17, -29, -63, -86, -97, -101, -101, -92, -74, -50, + -26, -4, 28, 66, 98, 114, 113, 102, 90, 68, 33, -15, -53, -76, -93, -101, + -104, -96, -79, -57, -34, -15, 15, 56, 90, 110, 115, 105, 93, 75, 44, 0, + -43, -68, -86, -98, -101, -98, -83, -65, -42, -22, 4, 41, 79, 104, 113, 107, + 96, 81, 57, 16, -31, -59, -79, -95, -101, -100, -90, -71, -49, -30, -9, 28, + 67, 97, 110, 107, 97, 86, 65, 30, -14, -47, -67, -84, -98, -102, -96, -79, + -59, -41, -22, 14, 53, 90, 110, 111, 101, 90, 75, 45, 2, -39, -64, -79, + -93, -102, -101, -87, -64, -44, -28, 0, 39, 81, 108, 110, 102, 93, 82, 58, + 18, -25, -54, -70, -85, -101, -103, -94, -72, -53, -39, -14, 25, 70, 104, 112, + 103, 96, 88, 70, 34, -13, -48, -65, -78, -97, -108, -101, -79, -55, -42, -24, + 11, 56, 96, 111, 103, 94, 90, 77, 46, 5, -34, -56, -71, -92, -109, -109, + -91, -64, -46, -30, 0, 44, 89, 112, 108, 95, 88, 80, 57, 16, -27, -54, + -66, -82, -104, -112, -100, -71, -46, -34, -13, 29, 80, 111, 112, 97, 86, 84, + 69, 32, -15, -48, -61, -72, -94, -109, -106, -82, -54, -37, -23, 11, 61, 101, + 113, 101, 85, 80, 75, 48, 4, -37, -56, -64, -84, -107, -112, -90, -60, -37, + -29, -7, 43, 91, 111, 103, 86, 80, 77, 58, 20, -24, -52, -61, -75, -100, + -111, -99, -72, -44, -27, -12, 29, 77, 105, 106, 91, 80, 75, 64, 33, -9, + -43, -58, -69, -94, -111, -104, -78, -49, -28, -18, 11, 62, 97, 107, 94, 80, + 75, 69, 47, 6, -36, -55, -62, -81, -105, -108, -87, -59, -33, -18, 1, 46, + 86, 103, 97, 83, 75, 69, 52, 19, -23, -50, -59, -74, -97, -106, -91, -64, + -38, -21, -9, 26, 70, 95, 95, 80, 71, 69, 60, 35, -6, -40, -53, -64, + -87, -102, -96, -72, -45, -25, -14, 13, 56, 87, 95, 86, 75, 69, 60, 41, + 6, -32, -54, -62, -77, -95, -99, -79, -51, -23, -8, 6, 39, 75, 92, 87, + 72, 64, 62, 49, 21, -17, -47, -57, -67, -86, -97, -87, -59, -32, -16, -4, + 25, 63, 89, 92, 78, 67, 63, 53, 27, -10, -40, -55, -63, -78, -93, -89, + -65, -36, -17, -7, 11, 44, 77, 89, 79, 65, 61, 58, 41, 8, -26, -50, + -59, -67, -83, -90, -76, -47, -25, -13, 3, 30, 63, 85, 82, 70, 63, 58, + 45, 14, -18, -43, -56, -63, -74, -84, -78, -52, -26, -13, -2, 19, 46, 73, + 81, 68, 57, 55, 49, 27, -5, -32, -48, -54, -63, -77, -80, -60, -34, -17, + -5, 10, 34, 62, 79, 71, 57, 52, 48, 31, 2, -26, -45, -50, -53, -65, + -75, -63, -37, -16, -6, 4, 19, 45, 68, 70, 57, 49, 49, 39, 16, -11, + -33, -45, -49, -56, -70, -71, -51, -26, -8, 2, 13, 35, 63, 76, 63, 48, + 43, 38, 23, -7, -32, -45, -47, -47, -58, -67, -55, -30, -8, 0, 4, 20, + 46, 68, 65, 47, 38, 38, 31, 8, -19, -37, -44, -42, -48, -63, -62, -41, + -16, -2, 5, 16, 37, 61, 68, 53, 38, 34, 31, 14, -14, -33, -40, -38, + -41, -54, -60, -46, -20, -5, -3, 6, 25, 49, 63, 55, 38, 32, 33, 24, + 1, -23, -34, -35, -36, -45, -59, -55, -30, -9, -3, 2, 16, 39, 59, 59, + 44, 32, 30, 26, 7, -20, -33, -33, -32, -40, -53, -54, -35, -12, -3, -2, + 10, 29, 48, 55, 45, 32, 28, 27, 14, -10, -27, -30, -28, -34, -46, -53, + -41, -17, -5, -5, 5, 24, 44, 54, 46, 32, 25, 25, 18, -4, -25, -31, + -24, -27, -39, -47, -42, -21, -4, -2, 1, 15, 35, 46, 44, 31, 22, 23, + 20, 6, -15, -26, -23, -20, -29, -41, -42, -29, -11, -4, -4, 7, 26, 42, + 47, 37, 25, 21, 19, 9, -10, -25, -25, -18, -24, -38, -40, -29, -11, 1, + 0, 3, 19, 34, 42, 33, 19, 14, 15, 10, -5, -21, -24, -15, -13, -26, + -35, -31, -17, -2, 0, -2, 11, 26, 37, 34, 20, 14, 13, 12, 2, -17, + -25, -17, -12, -21, -31, -30, -19, -4, 4, 1, 9, 22, 32, 32, 19, 9, + 9, 10, 4, -11, -21, -16, -9, -14, -23, -26, -20, -8, 0, -2, 3, 15, + 26, 31, 24, 12, 9, 10, 6, -5, -17, -19, -12, -11, -18, -25, -22, -10, + 1, 2, 2, 11, 22, 29, 24, 10, 3, 5, 4, -4, -13, -15, -8, -5, + -10, -16, -18, -14, -5, -2, 0, 6, 13, 20, 23, 16, 6, 5, 5, 0, + -7, -12, -12, -8, -7, -12, -19, -18, -7, 0, 2, 7, 13, 18, 20, 13, + 3, -2, 1, -2, -6, -8, -6, -3, -2, -2, -10, -14, -10, -6, -4, 0, + 4, 9, 14, 15, 6, -2, -2, -2, -4, -4, -5, -3, 2, 3, -3, -10, + -9, -5, 0, 0, 0, 3, 8, 10, 3, -5, -7, -6, -4, 0, -2, -2, + 3, 7, 7, 2, -5, -6, -3, 2, 2, 0, 0, 2, 2, -4, -9, -9, + -7, -3, 2, 4, 8, 9, 6, 2, -3, -4, -3, -2, -2, -2, 0, 1, + -3, -8, -11, -8, -6, -4, 2, 6, 9, 10, 9, 8, 5, -4, -7, -3, + 1, 1, -6, -7, -6, -6, -11, -14, -10, -5, 3, 9, 12, 14, 13, 10, + 9, 1, -6, -5, -4, -3, -4, -6, -8, -12, -12, -13, -13, -11, -3, 9, + 16, 18, 15, 13, 14, 11, -2, -6, -4, -3, -5, -11, -13, -12, -14, -15, + -14, -10, -4, 6, 15, 22, 21, 16, 13, 12, 3, -7, -8, -7, -7, -10, + -14, -17, -16, -13, -12, -10, -7, 3, 15, 24, 26, 19, 16, 18, 12, -3, + -9, -10, -9, -11, -18, -22, -21, -17, -14, -14, -10, 0, 14, 26, 32, 28, + 23, 22, 21, 5, -9, -12, -16, -18, -22, -27, -27, -23, -17, -13, -8, 2, + 12, 25, 35, 36, 29, 21, 20, 11, -6, -14, -17, -19, -22, -27, -28, -24, + -20, -15, -11, -4, 7, 19, 32, 39, 35, 28, 25, 19, 4, -10, -17, -24, + -28, -31, -33, -30, -26, -19, -11, -3, 8, 19, 31, 42, 42, 34, 27, 21, + 9, -9, -19, -26, -31, -35, -34, -30, -26, -23, -13, -4, 4, 14, 25, 42, + 49, 41, 31, 27, 20, 3, -15, -28, -37, -38, -39, -38, -35, -29, -16, 0, + 9, 17, 26, 41, 52, 48, 36, 26, 19, 6, -16, -30, -39, -43, -41, -39, + -33, -29, -22, -5, 7, 13, 21, 36, 55, 56, 46, 34, 24, 15, -8, -29, + -44, -54, -50, -44, -39, -35, -27, -7, 11, 20, 25, 34, 54, 63, 53, 38, + 22, 14, 0, -27, -45, -56, -56, -46, -39, -36, -31, -14, 8, 19, 23, 29, + 46, 63, 61, 47, 30, 20, 8, -15, -39, -56, -62, -54, -44, -41, -38, -23, + -2, 16, 23, 28, 42, 63, 69, 58, 41, 25, 13, -7, -34, -56, -68, -64, + -50, -45, -43, -29, -7, 15, 26, 29, 40, 58, 72, 67, 48, 30, 16, 0, + -26, -53, -68, -69, -57, -47, -46, -36, -16, 9, 25, 30, 38, 53, 71, 74, + 58, 37, 17, 2, -21, -49, -70, -76, -64, -49, -43, -38, -21, 3, 25, 33, + 37, 49, 65, 74, 65, 45, 24, 8, -11, -40, -68, -79, -72, -57, -48, -42, + -29, -6, 20, 34, 39, 48, 63, 77, 74, 56, 31, 11, -8, -33, -61, -79, + -80, -68, -53, -45, -34, -16, 11, 31, 41, 51, 61, 75, 78, 64, 42, 19, + -3, -27, -55, -78, -84, -73, -59, -48, -37, -20, 5, 27, 40, 49, 58, 71, + 80, 71, 49, 23, 2, -20, -47, -72, -86, -82, -66, -52, -39, -26, -5, 20, + 39, 51, 59, 69, 79, 77, 61, 34, 7, -16, -42, -68, -88, -90, -75, -58, + -41, -26, -8, 17, 39, 52, 59, 65, 74, 77, 65, 41, 12, -12, -35, -60, + -81, -89, -79, -60, -45, -33, -17, 6, 31, 49, 59, 64, 73, 80, 74, 51, + 22, -5, -29, -54, -78, -92, -90, -70, -49, -35, -18, 3, 26, 48, 60, 64, + 68, 75, 75, 58, 31, 1, -25, -48, -73, -88, -90, -77, -56, -41, -23, -3, + 21, 43, 58, 64, 70, 75, 77, 64, 40, 12, -18, -44, -70, -87, -94, -87, + -64, -42, -22, -4, 16, 39, 58, 65, 66, 67, 74, 68, 46, 18, -12, -38, + -62, -82, -92, -89, -67, -45, -28, -9, 13, 31, 52, 64, 67, 66, 72, 71, + 53, 29, -3, -34, -59, -79, -94, -96, -77, -50, -29, -8, 12, 30, 49, 63, + 68, 67, 68, 70, 56, 34, 6, -29, -57, -77, -92, -99, -84, -56, -32, -10, + 11, 29, 45, 61, 69, 69, 68, 70, 60, 37, 12, -20, -50, -73, -90, -100, + -91, -64, -37, -14, 7, 25, 42, 57, 66, 67, 65, 67, 64, 45, 21, -9, + -41, -66, -84, -98, -95, -74, -47, -21, 3, 23, 39, 54, 64, 69, 69, 67, + 63, 50, 27, 0, -33, -63, -83, -94, -95, -79, -54, -26, -2, 18, 35, 49, + 61, 67, 67, 65, 64, 55, 33, 6, -25, -55, -82, -95, -98, -84, -60, -32, + -6, 17, 36, 48, 56, 64, 66, 65, 62, 55, 39, 14, -16, -46, -76, -92, + -96, -88, -69, -41, -9, 15, 33, 46, 54, 62, 68, 66, 59, 54, 44, 20, + -12, -41, -72, -92, -97, -90, -71, -46, -14, 15, 34, 48, 55, 59, 62, 63, + 60, 51, 42, 24, -6, -34, -63, -87, -95, -89, -75, -52, -23, 10, 31, 45, + 54, 58, 62, 66, 63, 51, 42, 30, 1, -32, -59, -84, -96, -93, -80, -58, + -28, 7, 32, 45, 53, 60, 64, 67, 62, 52, 41, 31, 9, -25, -55, -78, + -92, -91, -82, -65, -39, -2, 30, 43, 49, 56, 61, 65, 63, 54, 44, 33, + 16, -15, -47, -72, -88, -91, -84, -70, -45, -12, 22, 42, 48, 54, 58, 61, + 63, 56, 43, 32, 20, -4, -36, -65, -82, -87, -82, -72, -53, -23, 15, 40, + 46, 48, 55, 61, 62, 55, 43, 32, 21, 4, -26, -57, -75, -82, -80, -73, + -58, -30, 5, 35, 46, 47, 51, 57, 61, 57, 46, 34, 22, 9, -15, -47, + -71, -81, -80, -75, -62, -36, -4, 28, 46, 47, 49, 56, 60, 57, 48, 35, + 23, 12, -9, -39, -67, -78, -76, -71, -65, -45, -13, 21, 45, 50, 46, 50, + 58, 59, 49, 35, 23, 12, -4, -31, -62, -78, -74, -70, -65, -49, -18, 18, + 43, 51, 45, 48, 56, 56, 45, 30, 20, 12, 0, -24, -53, -71, -69, -63, + -60, -51, -25, 9, 36, 50, 47, 44, 50, 52, 45, 32, 21, 12, 1, -18, + -44, -66, -70, -64, -59, -51, -31, 2, 32, 50, 51, 46, 47, 52, 47, 32, + 17, 9, 0, -14, -34, -57, -67, -62, -56, -50, -33, -6, 24, 44, 51, 48, + 47, 48, 46, 34, 21, 12, 2, -13, -32, -51, -62, -62, -56, -51, -38, -13, + 18, 40, 51, 50, 45, 47, 46, 36, 20, 9, -2, -14, -28, -45, -59, -61, + -54, -48, -37, -15, 14, 36, 49, 52, 48, 44, 42, 33, 19, 10, 0, -13, + -26, -39, -52, -58, -54, -47, -37, -19, 9, 30, 44, 52, 48, 40, 38, 31, + 19, 7, -3, -12, -22, -31, -42, -51, -49, -43, -36, -22, 1, 22, 35, 45, + 47, 41, 37, 31, 23, 13, 3, -11, -22, -28, -36, -48, -53, -46, -35, -23, + -4, 17, 31, 45, 49, 41, 33, 29, 23, 13, 2, -11, -22, -26, -29, -38, + -46, -45, -34, -21, -6, 14, 25, 38, 46, 43, 35, 27, 19, 10, 3, -7, + -20, -28, -28, -32, -38, -41, -35, -23, -8, 10, 23, 33, 44, 44, 36, 27, + 18, 10, 0, -9, -22, -28, -28, -28, -33, -37, -32, -21, -7, 8, 20, 28, + 38, 41, 36, 27, 17, 8, -2, -6, -17, -28, -31, -28, -27, -30, -30, -22, + -7, 9, 19, 26, 35, 41, 37, 26, 16, 6, -5, -11, -18, -28, -31, -28, + -22, -23, -23, -18, -4, 11, 19, 24, 27, 33, 33, 24, 14, 3, -8, -11, + -15, -23, -29, -29, -21, -18, -19, -15, -5, 9, 16, 21, 26, 30, 32, 25, + 13, 2, -9, -13, -16, -21, -27, -27, -20, -12, -13, -14, -7, 9, 17, 20, + 24, 25, 26, 27, 15, 2, -9, -17, -17, -20, -25, -28, -23, -11, -6, -8, + -5, 7, 19, 23, 24, 24, 24, 25, 16, 0, -13, -22, -22, -22, -26, -28, + -22, -8, 2, 1, 0, 8, 18, 24, 24, 20, 18, 20, 15, 1, -12, -22, + -24, -22, -23, -25, -22, -13, 2, 7, 3, 8, 16, 25, 28, 21, 15, 15, + 15, 4, -13, -25, -29, -24, -20, -24, -21, -12, 1, 12, 10, 9, 16, 23, + 27, 21, 14, 12, 10, 3, -10, -21, -28, -27, -22, -22, -20, -14, -4, 10, + 14, 11, 17, 23, 29, 26, 15, 11, 10, 4, -12, -25, -33, -33, -26, -23, + -22, -12, 0, 13, 22, 19, 20, 25, 29, 25, 12, 5, 3, 0, -12, -25, + -32, -34, -27, -21, -20, -11, -2, 7, 18, 21, 22, 26, 30, 29, 21, 11, + 4, -5, -14, -29, -38, -38, -33, -27, -23, -10, 4, 12, 22, 29, 30, 30, + 31, 30, 21, 10, 0, -11, -19, -30, -39, -40, -36, -28, -20, -9, 4, 12, + 20, 29, 32, 30, 32, 32, 23, 12, 3, -8, -18, -27, -39, -44, -40, -32, + -25, -15, 1, 13, 22, 30, 37, 38, 36, 34, 26, 14, 2, -11, -22, -31, + -40, -45, -42, -35, -26, -14, 0, 12, 19, 26, 35, 39, 36, 33, 28, 18, + 6, -7, -18, -28, -37, -43, -43, -37, -30, -19, -6, 8, 20, 25, 34, 42, + 41, 37, 32, 22, 8, -7, -19, -32, -40, -44, -44, -38, -30, -20, -6, 8, + 19, 24, 30, 40, 41, 36, 29, 23, 13, -3, -16, -28, -39, -43, -44, -41, + -34, -23, -11, 2, 16, 25, 32, 41, 46, 42, 34, 26, 15, 0, -16, -29, + -40, -45, -45, -40, -32, -24, -12, -2, 12, 22, 26, 37, 45, 44, 34, 24, + 18, 6, -12, -24, -37, -41, -40, -40, -36, -30, -17, -4, 9, 18, 25, 37, + 45, 45, 40, 29, 19, 8, -8, -22, -38, -43, -42, -42, -35, -28, -17, -4, + 7, 17, 23, 33, 43, 43, 38, 28, 19, 12, -3, -19, -34, -40, -38, -40, + -38, -31, -22, -8, 5, 14, 21, 31, 44, 47, 41, 31, 20, 13, 3, -15, + -33, -45, -45, -41, -38, -31, -24, -10, 4, 15, 21, 29, 42, 47, 41, 33, + 22, 13, 4, -13, -29, -40, -41, -41, -41, -36, -26, -14, -2, 8, 17, 29, + 42, 50, 46, 37, 27, 17, 7, -9, -27, -41, -48, -45, -42, -38, -29, -15, + -2, 10, 18, 26, 38, 50, 51, 40, 28, 17, 6, -7, -24, -36, -43, -45, + -41, -38, -31, -18, -8, 2, 13, 26, 38, 44, 49, 42, 33, 22, 8, -4, + -20, -32, -41, -46, -44, -37, -32, -21, -8, 2, 14, 25, 35, 42, 47, 44, + 31, 19, 7, -4, -15, -28, -36, -42, -40, -34, -31, -24, -9, 0, 7, 18, + 30, 40, 44, 42, 32, 22, 12, 2, -10, -23, -31, -38, -42, -38, -31, -26, + -13, -3, 2, 14, 29, 40, 41, 40, 36, 26, 13, 1, -10, -19, -26, -35, + -43, -41, -33, -27, -17, -6, 1, 12, 27, 43, 47, 42, 37, 29, 14, 0, + -10, -21, -29, -34, -40, -42, -33, -26, -18, -5, 3, 10, 23, 39, 45, 39, + 33, 30, 18, 3, -8, -15, -22, -29, -37, -43, -36, -27, -22, -13, -4, 6, + 19, 36, 47, 47, 37, 33, 25, 6, -8, -15, -25, -31, -36, -43, -42, -32, + -21, -11, 0, 5, 15, 32, 46, 45, 35, 31, 28, 12, -6, -13, -20, -24, + -31, -41, -46, -38, -26, -18, -9, 1, 14, 31, 43, 48, 42, 33, 28, 15, + -5, -15, -18, -24, -31, -38, -41, -34, -26, -19, -8, 1, 10, 23, 37, 43, + 41, 32, 26, 19, 3, -12, -15, -18, -24, -34, -42, -38, -28, -20, -13, -4, + 6, 21, 37, 44, 43, 36, 28, 21, 8, -9, -16, -19, -25, -34, -42, -39, + -29, -21, -13, -3, 8, 19, 34, 42, 41, 36, 28, 20, 8, -7, -15, -16, + -19, -30, -41, -42, -31, -23, -15, -8, 3, 19, 36, 43, 39, 36, 30, 23, + 13, -6, -19, -21, -20, -26, -38, -43, -35, -25, -15, -7, 3, 14, 30, 42, + 40, 35, 28, 23, 16, 0, -14, -20, -19, -22, -34, -42, -37, -26, -15, -8, + 0, 12, 27, 40, 41, 35, 29, 22, 16, 4, -9, -19, -20, -20, -29, -39, + -39, -30, -19, -10, -3, 10, 24, 37, 42, 37, 31, 25, 18, 7, -7, -17, + -21, -20, -28, -38, -40, -33, -22, -11, -5, 9, 25, 37, 44, 40, 32, 24, + 17, 10, -5, -18, -24, -23, -28, -35, -38, -35, -26, -14, -5, 5, 19, 34, + 44, 42, 33, 23, 18, 13, 0, -15, -20, -22, -26, -33, -39, -35, -28, -18, + -10, 1, 18, 33, 43, 45, 38, 28, 20, 11, 2, -12, -22, -24, -28, -31, + -36, -35, -29, -21, -11, 0, 15, 30, 40, 44, 39, 31, 21, 13, 8, -5, + -17, -20, -25, -28, -32, -36, -34, -27, -18, -7, 9, 26, 39, 46, 45, 36, + 25, 14, 10, -2, -16, -24, -29, -31, -31, -36, -36, -27, -16, -7, 6, 23, + 37, 45, 44, 36, 26, 14, 8, 1, -14, -22, -23, -29, -32, -35, -36, -29, + -21, -14, 0, 16, 35, 46, 45, 39, 33, 20, 8, 3, -9, -21, -28, -32, + -34, -35, -36, -32, -25, -15, 1, 17, 32, 45, 49, 44, 35, 23, 7, 0, + -7, -17, -25, -30, -31, -32, -34, -31, -25, -18, -7, 10, 27, 43, 50, 45, + 35, 24, 13, 3, -7, -17, -24, -28, -30, -30, -33, -34, -26, -19, -11, 5, + 22, 39, 50, 48, 37, 26, 16, 5, -7, -18, -23, -27, -28, -28, -33, -34, + -24, -16, -11, 2, 17, 33, 48, 48, 37, 27, 18, 7, -5, -14, -20, -25, + -30, -31, -32, -37, -31, -20, -15, -3, 15, 30, 46, 53, 43, 31, 20, 11, + 0, -12, -21, -27, -31, -30, -30, -36, -33, -20, -10, -5, 9, 25, 41, 52, + 46, 34, 23, 15, 6, -9, -21, -27, -30, -31, -31, -37, -39, -25, -12, -7, + 1, 18, 36, 52, 53, 40, 28, 22, 13, -2, -18, -29, -32, -35, -34, -39, + -40, -28, -13, -7, -2, 12, 33, 50, 56, 44, 30, 24, 18, 4, -15, -29, + -32, -33, -33, -35, -40, -35, -20, -7, -2, 8, 25, 43, 54, 49, 35, 25, + 18, 8, -7, -23, -32, -32, -34, -34, -37, -36, -24, -11, -5, 2, 18, 36, + 51, 51, 39, 30, 24, 14, 0, -19, -32, -35, -35, -37, -38, -39, -29, -12, + -2, 3, 14, 29, 47, 54, 45, 33, 26, 17, 5, -12, -31, -37, -36, -38, + -38, -38, -32, -17, -3, 3, 9, 25, 42, 53, 49, 39, 31, 23, 10, -9, + -27, -38, -40, -41, -41, -41, -36, -23, -5, 5, 8, 18, 36, 51, 51, 43, + 34, 26, 16, 1, -20, -36, -40, -41, -42, -40, -38, -28, -10, 4, 7, 14, + 30, 48, 51, 45, 39, 31, 21, 4, -16, -33, -41, -43, -43, -39, -38, -32, + -15, 1, 7, 13, 25, 42, 52, 48, 39, 31, 22, 9, -10, -29, -40, -40, + -40, -38, -35, -34, -20, -2, 5, 9, 17, 33, 49, 50, 43, 34, 25, 13, + -4, -21, -36, -44, -44, -40, -35, -34, -26, -8, 5, 11, 17, 26, 43, 51, + 46, 36, 27, 16, 1, -16, -31, -42, -46, -43, -37, -35, -29, -12, 3, 11, + 17, 23, 37, 50, 52, 41, 29, 20, 4, -15, -30, -43, -49, -46, -39, -37, + -33, -15, 3, 13, 19, 23, 35, 52, 55, 44, 29, 20, 8, -12, -28, -40, + -48, -45, -39, -35, -32, -20, -2, 12, 16, 19, 28, 45, 55, 49, 35, 24, + 14, -3, -20, -36, -49, -53, -45, -38, -35, -27, -9, 8, 19, 23, 26, 40, + 55, 55, 41, 25, 15, -2, -19, -33, -46, -53, -47, -39, -35, -29, -14, 6, + 19, 24, 25, 35, 53, 59, 47, 29, 17, 7, -12, -30, -47, -58, -56, -47, + -39, -35, -22, -2, 17, 28, 30, 34, 50, 63, 56, 35, 19, 8, -9, -26, + -43, -56, -58, -49, -42, -38, -27, -9, 12, 26, 33, 34, 44, 60, 62, 44, + 23, 9, -4, -20, -40, -56, -63, -56, -44, -39, -30, -14, 8, 26, 35, 35, + 43, 60, 64, 50, 28, 13, 2, -16, -37, -53, -62, -61, -50, -42, -32, -17, + 2, 18, 32, 40, 44, 54, 63, 55, 37, 17, 4, -10, -31, -48, -61, -67, + -59, -45, -36, -24, -5, 17, 33, 43, 47, 54, 64, 59, 42, 20, 3, -10, + -28, -49, -63, -68, -63, -50, -37, -25, -7, 13, 31, 44, 48, 54, 61, 59, + 48, 27, 6, -10, -24, -43, -59, -67, -67, -56, -39, -28, -13, 8, 24, 42, + 51, 54, 58, 58, 52, 37, 14, -6, -20, -38, -54, -65, -70, -63, -45, -29, + -17, 2, 18, 37, 52, 56, 58, 56, 51, 42, 23, -2, -19, -34, -50, -62, + -70, -69, -52, -30, -17, -3, 15, 33, 50, 58, 58, 56, 52, 46, 29, 3, + -15, -31, -45, -58, -68, -71, -60, -38, -20, -5, 11, 25, 42, 58, 62, 58, + 51, 44, 36, 15, -10, -29, -43, -53, -64, -72, -67, -45, -21, -8, 4, 20, + 40, 60, 65, 57, 53, 48, 42, 21, -8, -27, -40, -50, -62, -71, -71, -54, + -29, -9, 3, 18, 34, 54, 68, 65, 57, 48, 40, 28, 2, -23, -41, -52, + -60, -71, -75, -60, -34, -12, 0, 13, 31, 52, 69, 66, 56, 50, 44, 33, + 7, -21, -38, -47, -55, -65, -75, -67, -41, -15, 2, 11, 23, 41, 61, 68, + 59, 49, 40, 34, 17, -11, -35, -47, -48, -55, -69, -72, -50, -21, 0, 8, + 15, 33, 56, 69, 62, 52, 44, 40, 26, -4, -30, -44, -48, -56, -69, -77, + -59, -28, -7, 7, 15, 30, 52, 68, 66, 55, 45, 38, 30, 6, -24, -43, + -49, -52, -64, -75, -65, -35, -10, 4, 11, 25, 45, 65, 67, 55, 48, 43, + 34, 13, -18, -39, -45, -49, -61, -75, -72, -45, -17, -2, 9, 20, 39, 61, + 70, 62, 52, 45, 36, 18, -9, -34, -47, -52, -58, -69, -72, -52, -23, -5, + 7, 17, 35, 54, 65, 63, 55, 45, 37, 23, 0, -27, -45, -49, -53, -63, + -71, -59, -31, -8, 7, 15, 28, 47, 61, 65, 58, 47, 38, 27, 6, -21, + -41, -49, -53, -62, -69, -62, -39, -14, 3, 14, 28, 46, 59, 64, 62, 51, + 39, 29, 11, -16, -40, -52, -55, -58, -65, -65, -47, -20, 1, 14, 24, 39, + 52, 59, 64, 56, 43, 33, 16, -8, -32, -49, -55, -58, -63, -65, -54, -29, + -3, 12, 21, 36, 51, 60, 65, 59, 46, 35, 21, -4, -28, -48, -56, -57, + -59, -60, -55, -37, -12, 9, 19, 32, 46, 54, 58, 58, 48, 36, 26, 7, + -18, -41, -53, -53, -52, -57, -58, -45, -19, 6, 15, 26, 42, 54, 59, 59, + 52, 39, 28, 10, -16, -40, -56, -56, -52, -51, -53, -45, -22, 4, 17, 24, + 35, 46, 56, 57, 52, 40, 30, 18, -7, -33, -54, -58, -52, -49, -53, -51, + -33, -5, 17, 26, 34, 43, 54, 58, 53, 42, 31, 19, 0, -24, -47, -60, + -55, -46, -46, -50, -39, -13, 13, 25, 32, 38, 48, 56, 52, 41, 30, 20, + 7, -15, -41, -58, -55, -44, -41, -44, -40, -19, 10, 25, 28, 32, 41, 53, + 52, 42, 31, 21, 13, -5, -32, -55, -60, -47, -36, -38, -40, -26, 2, 24, + 29, 28, 32, 46, 48, 40, 29, 21, 14, 1, -23, -48, -56, -46, -34, -33, + -36, -29, -7, 20, 28, 25, 26, 37, 46, 42, 30, 19, 15, 7, -13, -39, + -58, -54, -37, -27, -27, -29, -17, 13, 29, 28, 24, 31, 42, 42, 34, 21, + 11, 5, -10, -32, -51, -52, -40, -28, -24, -24, -18, 6, 27, 30, 26, 28, + 36, 38, 33, 22, 11, 6, -7, -26, -44, -49, -42, -30, -21, -17, -16, -5, + 18, 29, 26, 25, 29, 33, 33, 25, 13, 7, 0, -18, -36, -46, -45, -31, + -20, -16, -16, -9, 12, 28, 29, 24, 25, 29, 31, 26, 13, 2, -5, -15, + -26, -39, -46, -37, -19, -9, -9, -11, 1, 21, 31, 26, 21, 23, 26, 25, + 15, 4, -4, -10, -20, -32, -41, -38, -22, -10, -7, -9, -6, 11, 26, 29, + 22, 20, 21, 24, 19, 7, -6, -12, -17, -23, -30, -36, -27, -12, -3, 0, + -5, 3, 18, 28, 25, 18, 15, 16, 15, 7, -4, -10, -14, -19, -24, -30, + -26, -13, -3, 2, -3, -2, 12, 23, 26, 18, 13, 13, 14, 9, 0, -11, + -14, -15, -18, -24, -26, -16, -4, 4, 0, -5, 6, 17, 25, 21, 11, 7, + 8, 8, 1, -11, -14, -11, -10, -13, -20, -18, -7, 5, 7, -3, -2, 8, + 21, 23, 12, 4, 4, 8, 7, -5, -15, -14, -11, -9, -15, -20, -13, 1, + 8, 3, 0, 6, 17, 24, 16, 3, -2, 1, 0, -10, -17, -14, -8, -4, + -5, -11, -12, 0, 9, 6, -3, 1, 10, 18, 16, 5, -3, 0, 3, -4, + -13, -15, -10, -6, -4, -8, -13, -8, 5, 8, 5, 3, 9, 17, 18, 13, + 0, -7, -5, -5, -11, -14, -11, -6, 2, 2, -6, -9, 1, 8, 5, -2, + 1, 8, 14, 12, 2, -6, -5, -2, -6, -12, -10, -2, 3, 4, -5, -11, + -6, 5, 6, 0, 0, 7, 12, 14, 6, -7, -8, -6, -6, -9, -10, -5, + 4, 8, 4, -7, -11, -2, 6, 3, -2, 2, 9, 15, 12, -2, -8, -6, + -3, -5, -11, -9, 2, 10, 7, -5, -15, -10, 4, 6, -2, -2, 8, 14, + 14, 3, -9, -8, -5, -4, -8, -10, 0, 8, 9, 3, -9, -12, -3, 6, + 3, -3, 1, 8, 13, 5, -9, -13, -7, -2, -2, -6, -2, 9, 13, 6, + -6, -13, -10, 2, 4, -3, -2, 7, 13, 9, -6, -12, -11, -6, 0, -5, + -5, 7, 15, 13, 1, -10, -13, -4, 5, -2, -7, -2, 9, 9, -3, -11, + -11, -8, 2, 1, -3, 7, 15, 12, 4, -7, -13, -11, -2, 1, -4, -3, + 7, 11, 3, -8, -11, -10, 0, 1, -5, 2, 12, 17, 11, -2, -11, -11, + -3, 4, -4, -9, 1, 10, 3, -9, -11, -8, 0, 5, 1, 2, 11, 14, + 9, 1, -11, -15, -11, -3, 1, -3, 3, 12, 11, 1, -7, -9, -6, -3, + -5, -5, 5, 12, 9, 4, -3, -8, -8, -5, 0, -4, -3, 5, 6, -3, + -10, -7, -3, 0, 2, 3, 10, 14, 11, 4, -3, -11, -15, -15, -9, -5, + -5, 5, 13, 5, -2, 0, 2, 4, 1, -3, 4, 12, 11, 2, -5, -10, + -13, -13, -11, -6, -4, 3, 13, 9, 1, -2, 4, 5, 1, -5, 3, 12, + 13, 4, -9, -12, -14, -16, -17, -12, -5, 5, 16, 17, 6, 3, 9, 9, + 2, -8, -7, 2, 7, 4, -8, -12, -10, -13, -14, -13, -6, 4, 13, 19, + 10, 0, 6, 14, 8, -6, -9, 0, 7, 5, -8, -17, -13, -9, -14, -18, + -13, 2, 15, 23, 16, 4, 5, 16, 15, 0, -10, -6, 3, 6, -4, -15, + -15, -10, -11, -16, -16, -5, 10, 21, 18, 7, 2, 12, 18, 6, -7, -9, + 1, 7, 1, -14, -19, -15, -13, -16, -18, -8, 7, 19, 24, 16, 5, 8, + 16, 9, -4, -9, -5, 3, 4, -9, -19, -18, -13, -12, -17, -12, 2, 16, + 22, 17, 6, 4, 14, 13, 1, -8, -6, 2, 6, -5, -18, -20, -16, -14, + -18, -17, -5, 12, 23, 24, 14, 9, 15, 19, 9, -5, -8, -3, 2, -6, + -17, -23, -19, -14, -16, -17, -8, 7, 19, 24, 19, 10, 11, 17, 13, 3, + -5, -3, -2, -4, -14, -24, -25, -20, -18, -16, -10, 3, 16, 26, 28, 18, + 11, 15, 17, 9, -4, -7, -6, -6, -12, -24, -29, -22, -16, -15, -10, 0, + 13, 24, 27, 22, 14, 13, 16, 13, 2, -6, -7, -9, -12, -21, -29, -27, + -21, -15, -10, -3, 8, 21, 29, 26, 17, 13, 17, 19, 9, -5, -10, -9, + -12, -21, -30, -29, -22, -14, -10, -4, 7, 17, 26, 23, 17, 13, 12, 18, + 16, 5, -6, -10, -11, -19, -29, -32, -27, -18, -10, -4, 4, 13, 25, 26, + 21, 16, 11, 16, 17, 8, -5, -12, -12, -16, -25, -30, -27, -19, -10, -6, + 0, 10, 21, 24, 18, 15, 13, 16, 20, 14, 1, -10, -12, -15, -26, -31, + -29, -22, -12, -5, 0, 8, 19, 25, 22, 17, 14, 14, 19, 17, 4, -10, + -15, -15, -22, -30, -30, -26, -16, -6, 1, 7, 15, 23, 23, 18, 17, 17, + 17, 17, 8, -6, -15, -18, -24, -31, -29, -26, -19, -8, 2, 7, 15, 23, + 24, 21, 17, 15, 15, 17, 13, -4, -16, -20, -23, -30, -32, -27, -19, -8, + 3, 7, 14, 23, 24, 20, 16, 16, 15, 14, 10, 0, -12, -20, -24, -31, + -32, -25, -19, -10, 0, 9, 14, 22, 27, 23, 17, 17, 18, 12, 8, 1, + -12, -18, -23, -31, -34, -26, -17, -9, -2, 6, 14, 22, 27, 22, 16, 15, + 18, 17, 10, 3, -9, -17, -21, -31, -38, -32, -23, -13, -5, 4, 14, 21, + 30, 30, 21, 17, 18, 17, 10, 3, -8, -20, -23, -29, -38, -34, -25, -12, + 0, 3, 11, 17, 26, 31, 23, 15, 13, 16, 14, 5, -4, -15, -19, -23, + -35, -38, -32, -19, -7, -5, 6, 16, 25, 36, 32, 22, 19, 19, 15, 3, + -7, -16, -23, -26, -35, -42, -34, -19, -3, 1, 6, 18, 26, 37, 34, 20, + 15, 14, 14, 5, -7, -15, -21, -23, -28, -39, -37, -22, -5, 1, 3, 15, + 25, 35, 40, 27, 14, 14, 14, 6, -7, -14, -20, -25, -27, -36, -41, -28, + -8, 2, 4, 14, 24, 33, 40, 32, 17, 13, 12, 5, -7, -14, -17, -24, + -28, -34, -40, -32, -14, 1, 4, 13, 26, 33, 41, 40, 26, 15, 12, 4, + -9, -17, -20, -25, -31, -34, -41, -38, -20, 0, 7, 12, 24, 32, 40, 41, + 30, 17, 11, 4, -10, -18, -19, -21, -27, -31, -35, -36, -24, -5, 5, 9, + 21, 31, 37, 41, 36, 21, 11, 4, -8, -15, -18, -21, -26, -31, -34, -37, + -30, -12, 3, 9, 18, 30, 38, 44, 42, 29, 15, 7, -6, -18, -23, -24, + -25, -31, -34, -36, -33, -15, 3, 9, 17, 28, 38, 44, 42, 34, 20, 8, + -5, -18, -23, -22, -24, -30, -35, -35, -35, -24, -6, 6, 14, 25, 36, 42, + 45, 42, 28, 13, 1, -15, -26, -27, -26, -29, -35, -39, -38, -28, -10, 5, + 13, 21, 36, 47, 48, 45, 36, 21, 6, -11, -25, -31, -30, -29, -35, -41, + -41, -34, -18, 1, 15, 24, 35, 47, 52, 51, 42, 26, 8, -9, -25, -32, + -34, -32, -34, -40, -41, -35, -22, -5, 11, 21, 30, 44, 52, 51, 45, 32, + 15, -3, -19, -28, -33, -34, -36, -42, -44, -41, -30, -13, 6, 20, 29, 43, + 54, 56, 50, 37, 22, 4, -17, -31, -39, -39, -38, -40, -44, -41, -31, -14, + 4, 18, 26, 37, 52, 57, 54, 44, 29, 11, -9, -26, -38, -42, -40, -41, + -45, -46, -39, -24, -2, 17, 25, 35, 49, 59, 59, 52, 36, 19, -2, -22, + -38, -46, -45, -43, -44, -47, -41, -28, -7, 12, 22, 32, 45, 58, 60, 52, + 40, 26, 9, -14, -36, -46, -47, -44, -44, -50, -47, -34, -14, 8, 21, 30, + 42, 58, 65, 58, 46, 32, 14, -7, -30, -47, -51, -50, -45, -50, -51, -38, + -20, 4, 19, 28, 38, 53, 67, 63, 50, 40, 23, 2, -22, -43, -54, -55, + -50, -53, -57, -48, -31, -6, 17, 28, 39, 53, 69, 72, 60, 47, 29, 7, + -18, -39, -54, -59, -56, -53, -55, -52, -37, -16, 10, 25, 36, 48, 65, 75, + 68, 54, 40, 20, -6, -31, -52, -61, -61, -59, -63, -62, -46, -24, 2, 20, + 33, 50, 67, 79, 75, 62, 49, 30, 2, -29, -50, -63, -66, -65, -64, -64, + -50, -28, -6, 18, 34, 48, 62, 74, 79, 70, 54, 38, 14, -19, -45, -62, + -70, -71, -67, -68, -61, -39, -15, 10, 28, 45, 63, 77, 82, 77, 62, 47, + 25, -9, -40, -61, -70, -73, -69, -70, -66, -47, -23, 2, 23, 41, 57, 71, + 79, 83, 72, 55, 37, 6, -27, -51, -67, -76, -78, -77, -75, -60, -35, -12, + 13, 37, 59, 75, 82, 86, 81, 66, 48, 17, -23, -50, -66, -77, -83, -83, + -78, -66, -43, -18, 7, 31, 54, 73, 83, 87, 87, 74, 55, 29, -10, -41, + -61, -76, -85, -88, -84, -72, -53, -28, -3, 22, 51, 75, 84, 88, 92, 87, + 67, 40, 0, -38, -60, -77, -89, -94, -89, -77, -59, -34, -7, 17, 44, 73, + 88, 90, 91, 88, 74, 49, 12, -29, -57, -73, -84, -93, -94, -84, -68, -44, + -17, 8, 33, 64, 85, 90, 92, 91, 83, 63, 30, -15, -50, -71, -82, -92, + -96, -90, -74, -52, -26, 0, 24, 56, 82, 92, 93, 92, 89, 74, 42, 0, + -41, -67, -80, -93, -100, -97, -83, -62, -35, -8, 16, 43, 74, 91, 96, 96, + 93, 83, 56, 16, -28, -61, -79, -92, -99, -99, -90, -71, -45, -16, 9, 36, + 66, 88, 98, 97, 93, 87, 68, 31, -16, -52, -75, -89, -98, -103, -98, -81, + -54, -23, 1, 25, 56, 83, 97, 98, 92, 88, 76, 46, 1, -42, -68, -81, + -91, -99, -97, -82, -58, -30, -6, 15, 44, 73, 91, 94, 89, 85, 78, 55, + 16, -28, -59, -77, -87, -93, -95, -85, -65, -40, -16, 6, 33, 62, 85, 94, + 90, 86, 81, 66, 32, -15, -52, -73, -84, -90, -93, -87, -69, -45, -22, 0, + 22, 48, 75, 88, 88, 85, 80, 67, 42, 4, -36, -62, -77, -87, -90, -85, + -72, -52, -30, -11, 11, 36, 63, 83, 86, 86, 82, 74, 54, 17, -25, -55, + -72, -81, -88, -87, -77, -57, -34, -16, 4, 26, 54, 77, 84, 84, 82, 75, + 58, 27, -12, -45, -65, -76, -84, -84, -76, -61, -41, -24, -7, 15, 41, 67, + 78, 81, 80, 76, 67, 42, 5, -30, -54, -67, -79, -85, -79, -67, -50, -32, + -16, 6, 32, 58, 73, 77, 81, 78, 68, 49, 16, -19, -45, -63, -74, -80, + -77, -67, -53, -35, -20, -3, 20, 45, 65, 72, 76, 75, 68, 56, 29, -6, + -33, -52, -65, -75, -77, -70, -57, -42, -28, -13, 9, 34, 57, 70, 73, 75, + 72, 63, 41, 7, -24, -46, -60, -70, -75, -72, -59, -45, -31, -18, 0, 25, + 48, 63, 68, 70, 71, 65, 47, 17, -13, -33, -49, -62, -73, -73, -61, -48, + -37, -25, -10, 14, 39, 57, 64, 67, 70, 69, 54, 28, -3, -27, -44, -57, + -68, -74, -66, -50, -39, -26, -13, 5, 30, 50, 60, 62, 64, 65, 58, 38, + 9, -17, -35, -46, -59, -69, -67, -52, -40, -31, -20, -6, 18, 42, 55, 58, + 60, 65, 62, 47, 20, -10, -28, -39, -51, -66, -70, -58, -44, -34, -23, -10, + 11, 34, 51, 57, 58, 62, 63, 51, 29, 2, -21, -34, -46, -60, -69, -63, + -49, -37, -27, -15, 3, 26, 45, 55, 56, 58, 62, 55, 37, 11, -14, -29, + -39, -52, -65, -66, -52, -40, -30, -18, -5, 17, 39, 52, 54, 55, 58, 57, + 44, 21, -8, -24, -33, -45, -59, -66, -57, -43, -31, -20, -11, 7, 30, 47, + 53, 51, 52, 55, 51, 33, 4, -20, -29, -36, -49, -64, -63, -50, -36, -24, + -14, 0, 22, 43, 55, 53, 49, 52, 51, 39, 12, -16, -27, -33, -45, -60, + -66, -53, -37, -25, -16, -6, 16, 40, 53, 53, 47, 49, 51, 43, 22, 0, + 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, -2, -2, -2, -2, 0, -2, + 0, 0, 1, 2, 3, 4, 4, 4, 5, 6, 7, 6, 3, 1, 0, -3, + -5, -11, -17, -20, -20, -18, -16, -17, -17, -14, -10, -9, -13, -18, -19, -15, + -13, -12, -13, -8, 1, 12, 25, 32, 40, 45, 50, 49, 41, 32, 24, 16, + 9, 1, -12, -20, -23, -24, -20, -20, -18, -12, -11, -12, -7, 0, 10, 17, + 23, 25, 24, 21, 22, 23, 21, 10, 1, -5, -8, -11, -19, -29, -33, -32, + -26, -19, -16, -14, -12, -8, -7, -11, -19, -27, -29, -27, -25, -25, -24, -17, + -4, 13, 26, 34, 43, 54, 59, 56, 46, 33, 23, 15, 5, -11, -23, -32, + -35, -32, -30, -27, -23, -16, -11, -5, 3, 11, 23, 31, 36, 33, 28, 27, + 26, 21, 11, 1, -9, -14, -18, -23, -28, -35, -33, -26, -18, -12, -11, -7, + -4, -2, 0, -8, -19, -29, -33, -32, -30, -30, -25, -17, -4, 13, 26, 36, + 47, 55, 59, 53, 43, 32, 23, 12, 0, -14, -23, -30, -35, -35, -35, -33, + -28, -19, -11, -6, 3, 11, 22, 33, 39, 38, 34, 30, 27, 20, 11, 0, + -9, -17, -21, -26, -31, -34, -29, -19, -8, -3, 0, -3, 1, 4, 1, -11, + -25, -35, -37, -39, -35, -32, -27, -17, 0, 15, 29, 42, 55, 63, 62, 55, + 47, 38, 27, 14, -4, -20, -31, -40, -44, -46, -45, -41, -34, -25, -14, -3, + 8, 22, 32, 43, 44, 40, 36, 34, 26, 18, 8, -2, -11, -20, -25, -29, + -33, -31, -21, -10, -2, -2, -2, 4, 6, 9, 0, -14, -28, -35, -39, -38, + -38, -36, -30, -16, 0, 16, 29, 41, 55, 65, 67, 59, 49, 39, 28, 13, + -3, -19, -32, -42, -48, -51, -53, -47, -36, -22, -12, 0, 10, 24, 38, 46, + 48, 43, 39, 32, 26, 17, 6, -7, -16, -21, -26, -31, -34, -28, -16, -2, + 3, 1, 2, 8, 16, 12, 2, -15, -27, -34, -37, -41, -47, -44, -33, -16, + 1, 16, 31, 47, 65, 75, 73, 63, 52, 41, 27, 9, -14, -34, -47, -54, + -55, -58, -57, -50, -35, -17, 0, 8, 20, 34, 47, 54, 49, 42, 36, 29, + 21, 9, -4, -14, -21, -26, -30, -33, -28, -18, -5, 4, 6, 6, 8, 13, + 17, 12, -4, -21, -33, -39, -44, -49, -50, -46, -35, -15, 4, 22, 36, 55, + 72, 81, 78, 69, 54, 42, 27, 6, -19, -38, -52, -57, -62, -65, -64, -52, + -35, -17, -3, 8, 19, 33, 45, 50, 48, 42, 35, 29, 18, 7, -5, -11, + -20, -26, -29, -27, -20, -13, -4, 3, 8, 9, 11, 12, 12, 5, -8, -22, + -33, -42, -50, -53, -51, -42, -27, -11, 9, 27, 45, 62, 75, 78, 73, 60, + 48, 32, 14, -8, -30, -46, -54, -60, -64, -62, -53, -39, -23, -8, 5, 17, + 30, 41, 46, 44, 38, 30, 22, 11, 4, -5, -12, -20, -25, -26, -24, -17, + -7, 3, 8, 11, 12, 14, 15, 14, 9, -4, -17, -32, -44, -54, -57, -56, + -48, -36, -22, -5, 18, 41, 61, 74, 79, 75, 67, 55, 39, 20, -2, -20, + -37, -47, -56, -62, -63, -57, -44, -31, -18, -5, 7, 16, 28, 35, 38, 37, + 32, 25, 16, 8, 3, -2, -5, -11, -19, -21, -16, -7, 3, 6, 8, 7, + 8, 10, 9, 5, -4, -13, -23, -37, -49, -54, -54, -47, -38, -25, -9, 9, + 30, 50, 67, 77, 75, 69, 58, 42, 26, 7, -12, -31, -46, -52, -56, -59, + -58, -49, -36, -19, -5, 8, 14, 22, 28, 33, 35, 30, 23, 13, 4, 3, + 3, 0, -8, -12, -13, -10, -6, 2, 8, 11, 12, 11, 9, 4, -2, -5, + -12, -23, -35, -46, -52, -54, -48, -36, -22, -8, 9, 28, 46, 61, 70, 72, + 68, 58, 45, 27, 9, -8, -22, -35, -43, -48, -48, -46, -39, -33, -23, -12, + 1, 8, 11, 14, 16, 19, 19, 17, 11, 7, 8, 11, 13, 7, 5, 2, + 2, 2, 4, 6, 6, 5, 2, -3, -5, -9, -11, -17, -23, -29, -34, -40, + -45, -41, -32, -18, -5, 7, 19, 36, 54, 64, 67, 61, 55, 48, 36, 18, + 3, -11, -23, -36, -45, -46, -42, -39, -34, -27, -20, -11, 0, 10, 13, 14, + 12, 13, 13, 10, 7, 6, 9, 11, 11, 11, 10, 10, 8, 9, 9, 9, + 6, 1, -4, -12, -16, -22, -25, -28, -29, -30, -39, -43, -39, -26, -11, 0, + 8, 19, 33, 48, 58, 63, 61, 56, 50, 40, 25, 8, -5, -15, -24, -35, + -41, -42, -39, -32, -29, -25, -21, -13, -6, 0, 4, 2, 2, 3, 6, 6, + 7, 11, 17, 20, 22, 23, 24, 23, 21, 17, 12, 4, -5, -13, -22, -29, + -37, -41, -40, -36, -31, -32, -34, -34, -22, -6, 8, 14, 20, 29, 41, 50, + 56, 56, 49, 45, 39, 30, 17, 5, -8, -19, -28, -34, -35, -32, -27, -25, + -25, -23, -19, -12, -7, -4, -6, -10, -11, -7, 0, 4, 10, 14, 19, 26, + 32, 35, 34, 31, 25, 16, 6, -5, -17, -29, -39, -47, -51, -50, -44, -35, + -28, -27, -25, -18, -6, 10, 18, 21, 25, 31, 40, 46, 49, 48, 44, 42, + 37, 29, 19, 8, -5, -14, -21, -29, -30, -30, -27, -28, -32, -33, -31, -22, + -17, -15, -17, -19, -19, -9, 5, 16, 22, 25, 31, 38, 44, 47, 43, 34, + 20, 6, -9, -21, -35, -49, -59, -62, -60, -53, -42, -30, -22, -15, -6, 4, + 14, 23, 27, 28, 27, 30, 35, 38, 39, 42, 38, 35, 30, 25, 20, 12, + 4, -6, -18, -23, -22, -20, -22, -30, -37, -39, -34, -29, -27, -27, -26, -23, + -16, -3, 10, 21, 29, 35, 43, 46, 50, 49, 41, 28, 15, -2, -19, -35, + -50, -62, -67, -67, -60, -50, -36, -23, -14, -6, 3, 11, 21, 27, 27, 24, + 25, 27, 29, 31, 36, 41, 42, 39, 33, 27, 22, 17, 8, -3, -11, -15, + -15, -18, -25, -35, -42, -45, -42, -41, -41, -40, -38, -28, -12, 7, 22, 34, + 43, 51, 59, 62, 59, 49, 37, 20, 1, -19, -38, -54, -65, -73, -74, -69, + -55, -35, -19, -10, -2, 8, 18, 23, 25, 25, 22, 20, 19, 20, 22, 30, + 39, 44, 42, 39, 35, 32, 29, 18, 4, -8, -13, -15, -17, -24, -33, -43, + -47, -44, -42, -40, -40, -39, -32, -17, 3, 16, 28, 39, 47, 53, 56, 56, + 52, 40, 24, 5, -12, -29, -43, -54, -65, -72, -71, -56, -36, -20, -13, -4, + 5, 12, 18, 21, 23, 20, 18, 14, 16, 19, 27, 38, 45, 45, 42, 41, + 42, 37, 27, 15, 1, -8, -12, -13, -17, -30, -40, -47, -48, -47, -46, -46, + -45, -41, -28, -9, 11, 26, 38, 45, 51, 55, 58, 55, 47, 31, 10, -12, + -27, -39, -49, -58, -67, -69, -62, -46, -26, -13, -4, 2, 7, 14, 18, 21, + 20, 15, 11, 12, 14, 21, 32, 40, 44, 42, 42, 40, 37, 33, 22, 11, + 1, -7, -11, -11, -19, -30, -39, -43, -43, -42, -43, -44, -44, -36, -20, 0, + 14, 25, 35, 42, 46, 50, 50, 48, 36, 17, -3, -18, -30, -36, -43, -52, + -59, -60, -49, -35, -20, -12, -7, -4, 2, 8, 12, 12, 9, 9, 12, 16, + 23, 29, 39, 45, 46, 46, 43, 41, 37, 30, 20, 7, -5, -10, -11, -15, + -25, -39, -46, -45, -43, -42, -45, -46, -39, -26, -8, 8, 20, 31, 41, 45, + 48, 46, 44, 36, 21, 1, -20, -31, -33, -36, -44, -53, -59, -54, -41, -26, + -17, -12, -6, -3, 5, 7, 9, 11, 11, 12, 15, 20, 29, 36, 42, 46, + 45, 42, 40, 38, 33, 25, 13, 4, -7, -10, -11, -17, -29, -38, -38, -34, + -35, -39, -41, -39, -31, -16, -6, 4, 14, 24, 30, 34, 34, 35, 32, 22, + 8, -9, -16, -16, -17, -22, -33, -43, -46, -41, -34, -30, -25, -19, -14, -9, + -6, -2, 5, 9, 13, 15, 21, 29, 36, 43, 47, 46, 46, 42, 39, 37, + 31, 20, 10, 0, -6, -9, -14, -22, -29, -33, -31, -30, -34, -37, -37, -30, + -21, -12, -5, 1, 10, 20, 28, 31, 31, 28, 20, 12, 0, -8, -10, -10, + -16, -24, -33, -39, -44, -42, -35, -28, -23, -18, -14, -10, -4, 6, 12, 16, + 17, 22, 29, 33, 35, 38, 41, 43, 41, 38, 34, 30, 24, 16, 9, 3, + -4, -10, -15, -21, -23, -23, -23, -24, -28, -32, -31, -28, -22, -15, -10, -6, + 2, 11, 20, 23, 25, 19, 14, 9, 5, 3, 2, -2, -8, -19, -28, -36, + -42, -44, -39, -33, -28, -26, -20, -11, 0, 8, 15, 22, 28, 33, 35, 36, + 37, 38, 41, 40, 38, 32, 27, 21, 17, 11, 4, -3, -8, -12, -17, -18, + -16, -16, -15, -18, -22, -25, -26, -25, -23, -19, -15, -9, -2, 8, 13, 17, + 18, 17, 16, 15, 13, 10, 6, 0, -9, -21, -32, -42, -47, -46, -43, -36, + -30, -22, -15, -6, 4, 14, 22, 28, 33, 36, 37, 36, 35, 37, 36, 36, + 32, 27, 23, 16, 10, 5, 0, -7, -10, -12, -11, -11, -11, -10, -9, -11, + -16, -22, -27, -30, -30, -30, -25, -19, -9, 0, 7, 13, 18, 23, 27, 27, + 26, 20, 12, 1, -13, -27, -40, -50, -54, -54, -49, -42, -33, -21, -10, 1, + 14, 24, 30, 39, 44, 43, 38, 36, 38, 37, 34, 31, 28, 22, 13, 7, + 5, -2, -7, -11, -14, -13, -13, -8, -6, -6, -10, -12, -14, -19, -26, -34, + -38, -33, -26, -15, -7, 2, 7, 17, 26, 35, 40, 37, 29, 19, 7, -12, + -31, -44, -53, -56, -61, -62, -59, -46, -27, -9, 5, 14, 25, 36, 47, 53, + 51, 45, 37, 34, 32, 29, 26, 23, 18, 13, 5, 0, -3, -4, -6, -10, + -12, -12, -6, 2, 6, 2, -6, -12, -17, -21, -31, -41, -47, -43, -32, -20, + -11, -4, 9, 21, 40, 50, 48, 42, 34, 22, 5, -16, -36, -53, -58, -63, + -69, -73, -63, -43, -19, -2, 9, 19, 34, 50, 60, 61, 53, 42, 37, 32, + 30, 24, 21, 16, 11, 4, -4, -7, -6, -5, -5, -10, -14, -11, -4, 3, + 2, -2, -8, -13, -19, -26, -36, -42, -40, -33, -21, -9, 1, 10, 22, 36, + 49, 53, 47, 36, 19, 1, -18, -36, -51, -60, -65, -67, -67, -63, -47, -24, + -4, 11, 20, 33, 48, 57, 57, 52, 42, 33, 30, 28, 25, 19, 16, 12, + 8, 3, -2, -2, -2, -2, -5, -8, -10, -5, -2, 0, 0, -5, -8, -15, + -23, -32, -39, -38, -33, -24, -15, -7, 5, 16, 30, 45, 52, 49, 40, 23, + 4, -14, -29, -42, -55, -63, -67, -67, -61, -50, -35, -19, 0, 16, 31, 46, + 56, 59, 56, 47, 38, 34, 31, 28, 23, 16, 10, 4, 0, -2, -2, 0, + -5, -9, -12, -11, -7, -3, -3, -4, -5, -4, -7, -14, -26, -33, -32, -27, + -20, -15, -7, 2, 13, 21, 34, 42, 46, 40, 25, 7, -13, -27, -35, -44, + -54, -62, -64, -60, -51, -39, -26, -10, 8, 24, 40, 51, 58, 60, 54, 44, + 36, 29, 24, 19, 13, 8, 0, -6, -5, 0, 1, 0, -4, -3, -2, 0, + 1, -2, -5, -5, -4, -7, -17, -27, -31, -29, -24, -19, -15, -9, -3, 7, + 18, 27, 34, 39, 37, 26, 9, -9, -24, -32, -39, -47, -55, -60, -57, -51, + -42, -32, -20, -6, 14, 31, 48, 57, 60, 58, 52, 45, 35, 25, 21, 17, + 9, 0, -8, -10, -8, -7, -6, -9, -9, -6, -2, 0, -3, -6, -6, -2, + 1, -6, -15, -25, -25, -20, -17, -13, -11, -7, 1, 8, 16, 24, 31, 34, + 29, 16, -3, -17, -28, -35, -41, -47, -54, -56, -54, -46, -37, -27, -15, 4, + 23, 40, 50, 58, 60, 58, 50, 42, 34, 26, 19, 14, 4, -6, -13, -13, + -13, -14, -16, -15, -12, -9, -7, -7, -4, -4, 2, 7, 5, 0, -8, -11, + -13, -13, -11, -10, -11, -11, -9, 0, 8, 14, 22, 24, 19, 9, -3, -14, + -23, -29, -32, -38, -47, -54, -52, -44, -32, -23, -9, 8, 23, 39, 52, 59, + 58, 51, 46, 43, 33, 25, 16, 9, 4, -4, -11, -15, -16, -16, -15, -14, + -15, -16, -13, -7, -5, 2, 5, 5, 5, 6, 3, -4, -6, -4, -5, -10, + -16, -16, -13, -6, 4, 12, 15, 17, 14, 10, 4, -8, -17, -23, -30, -38, + -46, -52, -51, -41, -30, -20, -8, 9, 29, 47, 56, 57, 55, 52, 50, 45, + 34, 20, 10, 2, -2, -9, -16, -22, -24, -22, -21, -22, -19, -14, -7, -4, + 1, 5, 11, 15, 20, 17, 9, 3, 3, 0, -6, -15, -21, -23, -16, -9, + -3, 4, 10, 13, 15, 13, 4, -9, -15, -20, -27, -39, -48, -51, -47, -38, + -29, -21, -7, 16, 36, 48, 51, 52, 55, 60, 59, 49, 33, 20, 12, 7, + -2, -13, -24, -28, -27, -26, -30, -32, -29, -20, -9, 0, 3, 8, 16, 25, + 28, 23, 17, 12, 6, -2, -14, -26, -31, -27, -18, -10, -3, 7, 15, 22, + 24, 18, 9, 0, -9, -19, -34, -46, -57, -57, -51, -44, -38, -26, -5, 21, + 42, 48, 53, 58, 67, 75, 71, 57, 37, 23, 12, 3, -12, -27, -39, -43, + -43, -45, -47, -42, -28, -12, 2, 7, 12, 20, 32, 38, 37, 30, 21, 13, + 1, -13, -26, -34, -33, -26, -17, -10, -3, 9, 20, 25, 22, 13, 5, -3, + -13, -28, -43, -53, -56, -51, -46, -40, -31, -14, 10, 31, 41, 47, 56, 67, + 76, 73, 63, 46, 30, 19, 9, -7, -25, -39, -47, -50, -54, -52, -50, -38, + -22, -9, 4, 12, 22, 30, 39, 41, 39, 31, 22, 12, -3, -19, -30, -32, + -29, -23, -17, -9, 1, 12, 20, 24, 18, 10, 2, -7, -19, -35, -50, -59, + -59, -54, -49, -43, -31, -9, 15, 32, 41, 53, 70, 85, 87, 80, 64, 49, + 37, 23, 2, -23, -42, -52, -59, -66, -69, -68, -56, -38, -18, -2, 9, 19, + 31, 41, 49, 51, 44, 35, 21, 5, -9, -22, -29, -30, -26, -20, -14, -7, + 5, 15, 17, 14, 9, 2, -4, -16, -29, -45, -55, -56, -50, -46, -44, -36, + -19, 1, 19, 33, 46, 63, 79, 86, 84, 73, 60, 47, 32, 12, -10, -30, + -48, -59, -68, -72, -73, -64, -49, -30, -12, 2, 12, 26, 35, 45, 51, 51, + 44, 30, 15, 3, -9, -17, -20, -21, -19, -18, -14, 0, 10, 16, 15, 7, + -4, -10, -14, -24, -38, -51, -58, -55, -50, -44, -36, -23, -7, 10, 26, 41, + 57, 76, 89, 89, 81, 70, 59, 45, 25, 0, -24, -41, -56, -67, -75, -80, + -76, -63, -45, -26, -9, 6, 20, 32, 44, 52, 54, 53, 47, 35, 18, 3, + -6, -11, -14, -16, -19, -19, -12, -4, 5, 5, 0, -8, -12, -15, -21, -34, + -47, -51, -45, -39, -34, -30, -23, -12, 4, 17, 31, 45, 60, 72, 78, 75, + 69, 62, 53, 40, 18, -5, -24, -38, -50, -62, -73, -78, -74, -59, -41, -28, + -17, -4, 14, 33, 47, 55, 58, 55, 48, 39, 29, 16, 4, -5, -11, -18, + -21, -20, -15, -8, -7, -9, -13, -15, -16, -17, -23, -33, -43, -44, -41, -34, + -28, -23, -16, -8, 5, 21, 36, 50, 62, 73, 76, 73, 68, 59, 48, 30, + 9, -16, -35, -48, -59, -70, -77, -79, -72, -54, -38, -24, -8, 8, 29, 45, + 56, 61, 62, 56, 51, 39, 27, 16, 4, -8, -16, -22, -23, -25, -19, -16, + -17, -19, -20, -21, -18, -19, -25, -32, -38, -34, -24, -19, -15, -12, -7, 3, + 15, 28, 39, 48, 56, 63, 63, 63, 57, 47, 32, 14, -5, -22, -36, -46, + -58, -68, -73, -71, -61, -47, -35, -23, -9, 10, 29, 43, 52, 56, 56, 56, + 52, 45, 33, 19, 6, -5, -15, -22, -25, -26, -26, -29, -29, -26, -24, -20, + -19, -23, -27, -30, -27, -21, -18, -14, -10, -7, 0, 8, 18, 30, 40, 47, + 52, 54, 54, 55, 49, 39, 22, 7, -9, -24, -37, -50, -58, -65, -71, -67, + -59, -50, -39, -23, -6, 15, 32, 43, 51, 57, 61, 64, 61, 52, 37, 21, + 4, -11, -20, -26, -30, -35, -37, -39, -35, -29, -22, -17, -20, -22, -20, -18, + -17, -16, -13, -8, -3, 2, 7, 10, 17, 27, 35, 42, 43, 44, 45, 44, + 38, 28, 16, 3, -10, -22, -33, -46, -57, -64, -64, -59, -53, -46, -34, -17, + 3, 21, 32, 41, 48, 55, 60, 60, 54, 44, 31, 18, 3, -10, -19, -27, + -30, -32, -34, -35, -30, -23, -17, -17, -20, -20, -20, -17, -15, -13, -11, -8, + 1, 8, 12, 17, 23, 30, 39, 39, 37, 36, 35, 34, 27, 14, 0, -10, + -15, -23, -34, -46, -56, -60, -56, -49, -39, -32, -23, -8, 8, 23, 32, 38, + 44, 54, 58, 57, 48, 37, 29, 17, 4, -11, -21, -28, -29, -31, -34, -35, + -27, -20, -15, -16, -16, -17, -13, -10, -10, -11, -10, -4, 5, 11, 13, 15, + 21, 29, 33, 32, 28, 25, 25, 23, 16, 5, -6, -10, -16, -21, -30, -42, + -48, -48, -43, -34, -29, -21, -13, -3, 11, 22, 27, 34, 39, 48, 53, 48, + 42, 32, 23, 16, 4, -7, -18, -24, -24, -26, -28, -24, -19, -14, -13, -16, + -18, -18, -16, -14, -15, -16, -15, -7, 3, 11, 14, 21, 27, 33, 36, 33, + 30, 25, 22, 17, 9, -4, -15, -21, -24, -31, -39, -44, -44, -39, -30, -23, + -16, -8, 4, 14, 21, 23, 25, 29, 37, 43, 42, 36, 31, 25, 18, 11, + 4, -7, -11, -13, -16, -21, -22, -18, -14, -13, -16, -19, -21, -21, -19, -19, + -20, -18, -11, -2, 8, 14, 18, 23, 30, 34, 35, 31, 27, 21, 13, 2, + -11, -17, -23, -28, -36, -39, -40, -37, -31, -23, -14, -9, 0, 7, 13, 15, + 15, 16, 22, 27, 30, 28, 29, 32, 29, 23, 16, 9, 4, 1, -2, -7, + -14, -19, -14, -10, -10, -14, -18, -22, -24, -23, -26, -28, -27, -18, -8, -3, + 2, 9, 22, 33, 40, 40, 36, 30, 25, 20, 8, -8, -22, -29, -32, -39, + -48, -50, -42, -30, -19, -13, -8, 2, 11, 22, 25, 21, 17, 15, 20, 23, + 21, 20, 20, 19, 19, 16, 11, 9, 7, 7, 3, 0, -3, -5, -5, -5, + -7, -12, -22, -28, -32, -35, -35, -36, -30, -21, -12, -4, 3, 16, 29, 39, + 46, 45, 40, 34, 26, 13, -2, -17, -28, -37, -48, -57, -60, -52, -36, -19, + -12, -8, 2, 16, 28, 33, 28, 23, 21, 22, 21, 19, 18, 16, 14, 12, + 8, 6, 5, 5, 7, 5, 4, 5, 7, 9, 7, 3, -5, -13, -22, -28, + -35, -44, -49, -48, -38, -26, -14, -7, 4, 20, 38, 49, 54, 53, 49, 40, + 26, 8, -11, -24, -33, -46, -61, -70, -67, -52, -31, -14, -5, 4, 14, 27, + 36, 36, 33, 29, 26, 25, 21, 14, 10, 7, 8, 6, 5, 5, 6, 8, + 9, 10, 14, 18, 17, 13, 5, -4, -12, -20, -28, -37, -49, -56, -56, -48, + -36, -25, -15, -2, 16, 36, 51, 55, 57, 55, 48, 37, 20, 1, -17, -30, + -43, -60, -73, -76, -63, -43, -24, -14, -6, 7, 23, 39, 44, 38, 34, 31, + 32, 30, 24, 16, 8, 5, 6, 6, 5, 5, 6, 10, 10, 13, 16, 19, + 19, 14, 5, -7, -18, -25, -34, -45, -55, -61, -59, -51, -39, -25, -12, 5, + 27, 48, 58, 60, 61, 58, 49, 32, 14, -4, -20, -36, -54, -69, -79, -75, + -57, -35, -21, -15, -4, 12, 28, 39, 42, 41, 38, 38, 38, 33, 23, 13, + 8, 9, 11, 9, 5, 3, 6, 10, 13, 14, 15, 17, 16, 9, -6, -16, + -21, -27, -40, -56, -65, -67, -57, -45, -33, -23, -5, 21, 44, 60, 66, 67, + 65, 61, 47, 25, 2, -16, -34, -53, -72, -83, -82, -70, -51, -33, -20, -8, + 8, 25, 39, 46, 43, 43, 43, 43, 38, 27, 17, 9, 8, 10, 11, 9, + 5, 5, 8, 13, 14, 18, 20, 18, 12, -2, -13, -19, -25, -34, -48, -62, + -69, -67, -58, -46, -32, -14, 9, 30, 48, 60, 69, 72, 69, 57, 36, 13, + -6, -27, -47, -66, -79, -83, -77, -64, -46, -29, -13, 4, 17, 30, 39, 41, + 46, 48, 45, 40, 31, 20, 12, 10, 13, 14, 12, 11, 10, 10, 15, 17, + 20, 20, 17, 12, 0, -14, -24, -30, -37, -47, -60, -69, -68, -62, -51, -36, + -18, 5, 25, 45, 58, 65, 68, 67, 59, 42, 20, -2, -22, -42, -61, -75, + -81, -77, -66, -51, -35, -20, -4, 14, 28, 37, 38, 38, 42, 47, 43, 35, + 24, 17, 14, 14, 17, 20, 20, 17, 13, 14, 17, 18, 18, 17, 11, -2, + -15, -24, -31, -38, -46, -52, -58, -62, -61, -52, -38, -22, -4, 16, 35, 48, + 55, 60, 62, 57, 46, 26, 6, -17, -35, -53, -68, -76, -75, -66, -51, -38, + -23, -7, 10, 25, 35, 38, 37, 39, 40, 39, 30, 21, 16, 15, 15, 16, + 20, 24, 26, 27, 27, 26, 24, 21, 19, 11, -3, -16, -29, -40, -44, -50, + -54, -57, -58, -55, -48, -36, -21, -5, 13, 29, 41, 48, 52, 53, 50, 41, + 26, 7, -14, -33, -49, -62, -70, -69, -61, -48, -36, -21, -5, 16, 30, 35, + 35, 35, 32, 31, 29, 24, 17, 13, 13, 14, 15, 18, 26, 34, 39, 37, + 32, 29, 26, 22, 13, 1, -15, -29, -40, -46, -51, -54, -55, -52, -46, -40, + -32, -22, -10, 5, 19, 28, 33, 35, 37, 38, 33, 21, 8, -7, -20, -35, + -50, -57, -57, -49, -37, -28, -21, -8, 10, 25, 32, 32, 31, 27, 24, 22, + 20, 15, 13, 13, 15, 15, 19, 26, 36, 42, 43, 40, 33, 27, 22, 16, + 3, -13, -26, -37, -44, -50, -55, -54, -48, -42, -32, -24, -18, -10, -3, 8, + 20, 30, 31, 26, 22, 20, 15, 7, -7, -20, -32, -43, -52, -52, -46, -36, + -25, -16, -5, 9, 24, 38, 42, 39, 30, 23, 19, 15, 11, 8, 6, 6, + 6, 9, 18, 30, 42, 47, 45, 43, 38, 31, 22, 8, -9, -21, -33, -45, + -55, -59, -56, -47, -37, -29, -21, -13, -5, 2, 8, 13, 19, 22, 20, 15, + 9, 5, -3, -9, -20, -30, -39, -46, -45, -40, -31, -24, -16, -6, 7, 21, + 35, 39, 36, 31, 24, 22, 15, 10, 8, 5, 6, 3, 4, 12, 25, 40, + 48, 50, 48, 43, 37, 30, 17, -2, -18, -33, -45, -57, -64, -62, -53, -40, + -31, -23, -13, -3, 4, 11, 16, 19, 18, 17, 13, 7, -3, -10, -16, -22, + -31, -40, -45, -45, -41, -32, -24, -15, -5, 8, 24, 39, 47, 44, 38, 32, + 26, 20, 12, 3, -4, -4, -5, -4, 1, 11, 29, 41, 49, 51, 49, 45, + 38, 27, 9, -11, -27, -38, -52, -60, -64, -58, -45, -32, -21, -14, -5, 3, + 10, 13, 13, 14, 14, 12, 4, -6, -12, -17, -21, -25, -31, -35, -40, -39, + -33, -27, -19, -12, 1, 16, 29, 38, 42, 40, 36, 33, 30, 22, 11, 1, + -2, -2, -3, -2, 2, 16, 32, 44, 48, 46, 44, 39, 31, 19, 1, -21, + -36, -48, -58, -62, -59, -49, -38, -28, -20, -12, -2, 9, 16, 16, 15, 16, + 14, 9, 2, -7, -14, -19, -25, -31, -36, -38, -38, -36, -34, -28, -20, -7, + 8, 22, 33, 41, 46, 46, 42, 39, 33, 25, 14, 4, -4, -8, -8, -4, + 4, 16, 30, 38, 42, 46, 45, 38, 25, 10, -7, -24, -39, -51, -58, -59, + -53, -43, -34, -28, -21, -9, 5, 15, 17, 16, 15, 16, 15, 10, 2, -10, + -17, -21, -26, -33, -38, -40, -37, -34, -33, -28, -17, 0, 15, 29, 40, 48, + 50, 48, 44, 40, 34, 26, 15, 3, -6, -11, -11, -4, 7, 18, 24, 30, + 36, 38, 35, 31, 24, 13, -7, -25, -40, -50, -53, -51, -47, -41, -38, -33, + -25, -10, 4, 14, 19, 21, 22, 19, 19, 17, 7, -5, -15, -23, -31, -39, + -46, -49, -49, -46, -41, -33, -19, 0, 21, 39, 53, 61, 64, 63, 56, 50, + 42, 31, 15, -2, -13, -19, -19, -11, 0, 10, 15, 19, 27, 33, 37, 35, + 25, 9, -13, -28, -38, -44, -46, -50, -53, -51, -46, -38, -23, -7, 10, 20, + 21, 24, 25, 28, 28, 19, 8, -7, -18, -28, -36, -43, -52, -56, -57, -51, + -44, -31, -13, 7, 29, 46, 60, 66, 71, 68, 61, 54, 45, 32, 13, -5, + -17, -22, -20, -15, -8, -2, 8, 14, 24, 31, 35, 32, 21, 4, -13, -24, + -34, -42, -49, -55, -58, -54, -48, -38, -23, -4, 14, 26, 32, 31, 32, 36, + 34, 23, 7, -12, -25, -35, -47, -61, -68, -68, -61, -53, -42, -26, -7, 22, + 45, 61, 71, 75, 78, 74, 66, 56, 42, 24, 7, -13, -24, -29, -25, -18, + -11, -7, 2, 14, 27, 36, 38, 32, 19, 1, -14, -22, -33, -44, -56, -64, + -65, -60, -47, -32, -16, 3, 18, 31, 37, 37, 38, 41, 35, 20, 0, -18, + -31, -43, -56, -64, -69, -68, -60, -50, -36, -15, 6, 31, 50, 62, 71, 77, + 78, 74, 66, 54, 38, 20, 2, -15, -23, -26, -24, -22, -17, -7, 8, 20, + 29, 35, 33, 25, 13, -2, -14, -29, -42, -57, -67, -72, -67, -57, -42, -24, + -5, 13, 31, 43, 46, 47, 48, 43, 32, 14, -5, -22, -40, -55, -63, -68, + -69, -66, -57, -44, -25, -5, 18, 37, 55, 66, 75, 78, 75, 70, 62, 47, + 28, 9, -7, -19, -27, -30, -27, -21, -11, 5, 18, 28, 34, 36, 32, 24, + 12, -4, -20, -38, -55, -68, -75, -71, -65, -53, -35, -14, 6, 24, 39, 47, + 50, 48, 44, 36, 22, 5, -16, -34, -47, -56, -60, -60, -59, -54, -45, -28, + -9, 9, 25, 41, 53, 63, 67, 66, 65, 62, 54, 40, 22, 6, -8, -16, + -22, -23, -20, -11, 1, 13, 22, 27, 29, 26, 24, 15, 2, -15, -33, -49, + -64, -74, -74, -67, -55, -39, -20, -2, 16, 32, 45, 50, 49, 43, 35, 26, + 11, -9, -25, -35, -44, -49, -52, -54, -50, -39, -26, -12, 1, 14, 27, 39, + 48, 53, 55, 57, 56, 48, 36, 25, 15, 6, -5, -12, -17, -14, -8, 3, + 14, 21, 26, 23, 21, 21, 14, 3, -11, -26, -44, -61, -72, -72, -68, -56, + -42, -25, -11, 7, 24, 37, 44, 44, 40, 33, 25, 13, 0, -12, -24, -32, + -39, -41, -39, -36, -30, -24, -18, -10, 1, 11, 21, 29, 36, 41, 47, 51, + 51, 42, 35, 27, 19, 10, 1, -6, -10, -9, -2, 6, 11, 13, 13, 15, + 14, 10, 4, -9, -19, -31, -45, -58, -67, -68, -56, -43, -31, -20, -9, 7, + 21, 31, 35, 35, 33, 27, 18, 7, -3, -9, -13, -20, -27, -32, -33, -29, + -23, -19, -16, -12, -4, 6, 15, 23, 30, 39, 47, 49, 42, 35, 31, 27, + 22, 14, 2, -8, -9, -4, 5, 8, 8, 9, 7, 6, 3, 0, -5, -12, + -22, -35, -50, -58, -58, -50, -39, -32, -26, -19, -8, 7, 21, 26, 27, 25, + 22, 18, 11, 5, 2, 1, -3, -10, -19, -24, -23, -16, -15, -17, -20, -17, + -10, -2, 6, 12, 21, 32, 44, 45, 38, 30, 27, 31, 31, 21, 8, 1, + 0, 2, 8, 10, 7, 1, -3, -2, -4, -9, -12, -17, -25, -37, -47, -53, + -50, -42, -32, -27, -26, -22, -11, 5, 15, 18, 20, 22, 23, 22, 18, 15, + 14, 11, 7, -3, -14, -18, -17, -18, -22, -27, -27, -21, -14, -6, 3, 12, + 24, 34, 40, 39, 35, 32, 31, 34, 30, 19, 10, 4, 2, 5, 7, 7, + 1, -6, -10, -9, -8, -8, -11, -16, -25, -34, -41, -41, -36, -32, -33, -33, + -29, -22, -11, -2, 6, 13, 17, 22, 23, 22, 22, 24, 23, 20, 12, 0, + -7, -11, -14, -20, -26, -28, -26, -22, -15, -9, 2, 13, 25, 32, 33, 35, + 36, 37, 38, 35, 29, 19, 9, 5, 7, 6, 4, -3, -9, -12, -11, -6, + -4, -5, -10, -17, -26, -33, -37, -38, -38, -38, -41, -39, -31, -20, -9, -2, + 6, 15, 23, 31, 31, 31, 30, 29, 28, 21, 13, 2, -9, -17, -20, -23, + -26, -27, -26, -20, -14, -6, 6, 14, 22, 26, 32, 34, 35, 37, 37, 36, + 27, 15, 6, 6, 7, 5, -3, -13, -17, -17, -11, -5, -5, -6, -11, -18, + -24, -27, -30, -35, -40, -44, -44, -39, -28, -16, -6, 1, 9, 20, 31, 34, + 36, 37, 36, 33, 23, 14, 5, -3, -10, -17, -23, -30, -34, -31, -22, -14, + -8, 0, 7, 15, 20, 26, 30, 35, 40, 40, 34, 27, 18, 14, 9, 8, + 5, -2, -11, -15, -13, -8, -4, 0, 1, -6, -12, -18, -23, -29, -38, -45, + -52, -53, -47, -37, -28, -16, -5, 6, 17, 28, 37, 42, 43, 40, 37, 31, + 19, 8, 1, -7, -14, -22, -27, -33, -34, -28, -18, -8, 0, 5, 10, 14, + 19, 25, 33, 38, 39, 35, 27, 18, 13, 9, 8, 4, -3, -8, -12, -13, + -10, -4, 4, 4, -2, -7, -14, -21, -28, -36, -45, -53, -54, -50, -44, -34, + -20, -5, 7, 18, 28, 37, 39, 42, 40, 35, 28, 17, 7, 0, -7, -12, + -18, -23, -28, -28, -23, -17, -8, 2, 8, 9, 10, 12, 17, 25, 32, 33, + 28, 20, 13, 10, 10, 8, 6, 5, 1, -5, -6, -3, 3, 10, 10, 5, + -6, -15, -21, -28, -38, -49, -59, -62, -59, -51, -39, -25, -8, 7, 17, 28, + 37, 42, 44, 43, 38, 30, 17, 7, 0, -4, -10, -16, -24, -26, -27, -21, + -14, -9, -2, 5, 11, 14, 12, 13, 19, 26, 29, 26, 19, 13, 8, 8, + 9, 5, 2, 2, 4, 3, 1, 1, 5, 8, 7, 0, -10, -18, -25, -32, + -42, -52, -56, -53, -48, -38, -29, -14, 1, 14, 23, 30, 33, 33, 35, 33, + 26, 17, 9, 2, 1, 0, -5, -12, -19, -22, -21, -13, -8, -4, 5, 10, + 12, 10, 10, 14, 21, 25, 24, 15, 5, 3, 5, 7, 5, 2, 5, 10, + 12, 10, 9, 11, 13, 10, 2, -8, -18, -25, -32, -40, -50, -55, -53, -45, + -35, -27, -17, -4, 11, 20, 28, 30, 28, 29, 30, 28, 19, 10, 6, 6, + 5, 0, -10, -18, -20, -18, -14, -11, -10, -4, 6, 13, 13, 11, 13, 20, + 25, 24, 15, 7, 3, 4, 5, 4, 0, 3, 9, 14, 15, 11, 9, 8, + 8, 6, -5, -16, -24, -29, -35, -43, -48, -47, -42, -31, -23, -17, -7, 5, + 17, 24, 26, 22, 19, 19, 20, 17, 11, 5, 2, 2, 0, -4, -10, -14, + -14, -10, -8, -6, 1, 10, 19, 23, 22, 17, 16, 19, 18, 11, 1, -8, + -11, -10, -7, -4, 1, 7, 15, 22, 22, 18, 17, 16, 12, 4, -8, -21, + -29, -34, -39, -46, -49, -46, -37, -28, -19, -9, -2, 8, 19, 22, 20, 18, + 18, 19, 19, 12, 6, 3, 2, 0, -5, -10, -16, -18, -14, -9, -8, -3, + 6, 17, 25, 27, 26, 24, 25, 22, 15, 3, -8, -13, -13, -12, -11, -6, + 0, 9, 16, 19, 19, 16, 13, 10, 6, -5, -14, -22, -26, -32, -37, -41, + -39, -32, -23, -17, -14, -10, -3, 9, 17, 18, 10, 7, 10, 16, 18, 12, + 5, 1, 1, -4, -13, -18, -18, -15, -12, -11, -10, 1, 15, 29, 37, 35, + 31, 30, 30, 24, 11, -8, -18, -18, -15, -17, -20, -17, -6, 8, 15, 18, + 16, 15, 11, 12, 8, 0, -10, -16, -20, -28, -35, -38, -33, -27, -23, -21, + -19, -13, 0, 11, 14, 12, 9, 11, 18, 21, 19, 10, 2, -3, -5, -12, + -21, -28, -26, -20, -15, -12, -6, 9, 25, 38, 43, 42, 40, 38, 34, 23, + 6, -12, -18, -18, -18, -23, -25, -22, -13, 0, 7, 9, 8, 8, 11, 12, + 9, 6, 2, -5, -14, -21, -24, -24, -22, -22, -21, -22, -20, -12, -3, 4, + 5, 5, 6, 11, 15, 16, 10, 4, -2, -7, -11, -20, -25, -27, -21, -13, + -11, -5, 6, 22, 37, 46, 50, 49, 44, 39, 31, 16, -3, -15, -21, -24, + -27, -32, -33, -28, -17, -5, 5, 7, 7, 10, 15, 16, 15, 10, 4, -4, + -11, -18, -22, -22, -20, -22, -21, -21, -17, -10, 1, 6, 9, 10, 15, 19, + 18, 12, 5, 0, -9, -15, -23, -31, -36, -32, -24, -17, -11, -4, 12, 31, + 47, 53, 58, 60, 56, 49, 35, 15, -4, -16, -21, -25, -32, -42, -45, -35, + -23, -14, -8, 0, 6, 13, 20, 21, 19, 15, 9, 1, -6, -11, -13, -16, + -18, -20, -23, -20, -14, -8, 0, 2, 5, 11, 18, 18, 14, 6, -2, -10, + -18, -27, -34, -41, -40, -31, -20, -12, -7, 4, 23, 47, 64, 71, 71, 63, + 56, 46, 30, 12, -7, -22, -35, -42, -49, -52, -48, -34, -22, -14, -7, 3, + 15, 24, 27, 27, 24, 15, 6, -4, -8, -11, -13, -13, -15, -16, -14, -12, + -7, -2, 3, 10, 12, 14, 15, 7, 0, -7, -16, -25, -32, -40, -44, -44, + -36, -24, -11, 0, 6, 16, 36, 58, 72, 76, 71, 62, 51, 38, 24, 5, + -13, -30, -42, -50, -52, -53, -46, -33, -21, -15, -6, 7, 20, 25, 25, 21, + 18, 14, 7, 2, -5, -9, -9, -7, -8, -9, -10, -7, -3, 1, 6, 7, + 8, 9, 6, -2, -13, -23, -30, -35, -41, -45, -44, -38, -26, -15, -3, 11, + 19, 33, 52, 69, 75, 72, 65, 54, 42, 29, 13, -6, -25, -41, -49, -54, + -55, -48, -38, -26, -18, -8, 1, 13, 24, 29, 26, 19, 11, 5, 2, -2, + -6, -6, -6, -5, -7, -5, 1, 5, 9, 11, 8, 8, 7, 4, -6, -17, + -28, -35, -42, -47, -48, -45, -39, -29, -16, -5, 7, 18, 32, 45, 57, 64, + 67, 62, 54, 45, 35, 22, 5, -13, -28, -40, -47, -49, -46, -42, -32, -21, + -11, -4, 6, 15, 21, 21, 16, 12, 6, 1, -3, -5, -3, 3, 8, 9, + 8, 7, 7, 11, 12, 11, 6, -2, -9, -13, -20, -29, -40, -47, -47, -45, + -42, -37, -29, -16, -5, 7, 17, 27, 38, 48, 56, 59, 53, 44, 40, 37, + 30, 17, -2, -16, -25, -32, -35, -36, -35, -31, -23, -16, -10, -3, 4, 10, + 11, 8, 1, 0, 0, 0, 0, 1, 6, 14, 20, 21, 19, 15, 14, 13, + 11, 7, 0, -13, -21, -28, -37, -46, -51, -48, -43, -37, -32, -28, -21, -9, + 4, 17, 27, 32, 40, 45, 50, 51, 46, 40, 38, 35, 27, 12, -3, -13, + -23, -27, -29, -30, -29, -28, -23, -15, -10, -5, 2, 5, 5, 1, -2, -2, + 1, 4, 4, 8, 14, 19, 25, 26, 21, 15, 13, 12, 12, 5, -9, -21, + -30, -37, -43, -50, -51, -47, -42, -38, -34, -27, -17, -5, 10, 22, 30, 38, + 44, 49, 50, 46, 40, 37, 38, 33, 19, 4, -8, -14, -18, -22, -24, -24, + -22, -18, -16, -14, -10, -6, 1, 1, -6, -8, -9, -6, 0, 2, 8, 14, + 21, 28, 31, 27, 24, 21, 20, 16, 9, -3, -16, -26, -33, -42, -50, -55, + -56, -50, -43, -39, -38, -29, -13, 6, 18, 27, 33, 42, 51, 54, 53, 48, + 41, 39, 38, 29, 12, -5, -15, -19, -20, -23, -24, -22, -18, -17, -13, -12, + -10, -4, -3, -4, -7, -8, -9, -9, -7, 2, 9, 14, 21, 26, 27, 27, + 22, 20, 19, 17, 12, 1, -14, -25, -35, -41, -45, -50, -53, -54, -51, -47, + -41, -31, -18, -3, 12, 24, 35, 47, 55, 58, 57, 55, 49, 46, 40, 26, + 11, -5, -17, -22, -23, -23, -22, -21, -21, -18, -15, -9, -5, -3, -4, -6, + -7, -9, -12, -12, -8, 1, 7, 13, 14, 19, 23, 27, 26, 25, 25, 20, + 13, 4, -9, -22, -36, -42, -48, -55, -61, -62, -59, -54, -43, -32, -18, 0, + 18, 35, 49, 57, 60, 62, 63, 61, 57, 48, 33, 15, -2, -15, -24, -28, + -27, -22, -23, -24, -21, -13, -4, 3, 3, 1, -2, -4, -4, -9, -15, -16, + -13, -9, -5, 2, 7, 11, 19, 24, 28, 31, 29, 28, 24, 12, -4, -21, + -33, -38, -48, -61, -72, -76, -71, -61, -47, -34, -20, 2, 26, 45, 58, 65, + 69, 74, 75, 68, 55, 41, 28, 13, -7, -22, -32, -32, -29, -24, -23, -22, + -19, -7, 6, 7, 2, -2, -3, 0, -3, -10, -20, -24, -19, -12, -5, 1, + 5, 14, 23, 30, 33, 37, 39, 36, 24, 8, -10, -25, -33, -43, -55, -71, + -82, -82, -71, -57, -44, -29, -11, 13, 34, 52, 64, 70, 73, 77, 76, 65, + 50, 35, 20, 4, -13, -26, -31, -32, -27, -26, -25, -21, -10, 2, 8, 5, + 3, 0, 1, 2, -3, -12, -22, -24, -21, -16, -9, -3, 6, 14, 22, 28, + 34, 41, 42, 35, 23, 6, -10, -21, -32, -45, -61, -76, -85, -82, -70, -54, + -43, -29, -7, 18, 40, 55, 64, 71, 77, 81, 76, 62, 48, 32, 19, 6, + -10, -23, -30, -29, -28, -30, -27, -20, -10, -2, 3, 1, 0, 3, 6, 4, + -9, -18, -24, -22, -18, -14, -8, 0, 8, 16, 24, 32, 38, 42, 42, 31, + 15, -2, -14, -25, -38, -52, -67, -81, -85, -76, -63, -49, -37, -19, 3, 26, + 43, 57, 67, 75, 82, 79, 70, 56, 41, 28, 15, 1, -12, -22, -27, -27, + -28, -26, -21, -12, -3, 3, -2, -2, 1, 3, 1, -12, -22, -28, -29, -27, + -23, -18, -11, 3, 16, 25, 34, 44, 51, 52, 43, 27, 12, -2, -17, -34, + -51, -71, -82, -86, -83, -75, -61, -45, -27, -7, 16, 37, 53, 63, 72, 78, + 77, 68, 60, 45, 33, 20, 10, -2, -9, -15, -18, -22, -23, -19, -15, -8, + -5, -7, -8, -7, -4, -3, -10, -22, -29, -29, -24, -21, -18, -14, -3, 12, + 23, 27, 35, 44, 49, 47, 34, 18, 1, -11, -23, -40, -57, -73, -81, -80, + -74, -64, -50, -36, -19, 2, 22, 38, 49, 61, 69, 74, 69, 60, 50, 40, + 29, 20, 10, 2, -5, -9, -12, -16, -18, -14, -9, -6, -10, -13, -12, -10, + -11, -15, -23, -30, -31, -27, -25, -23, -19, -8, 8, 20, 28, 36, 45, 49, + 49, 41, 29, 15, -2, -15, -31, -49, -65, -76, -79, -77, -67, -55, -43, -30, + -13, 7, 25, 40, 51, 60, 66, 66, 62, 54, 45, 37, 29, 22, 14, 7, + 3, -3, -7, -10, -12, -10, -8, -12, -18, -19, -16, -13, -15, -23, -31, -33, + -29, -26, -25, -23, -15, 1, 14, 23, 31, 40, 50, 52, 46, 36, 21, 7, + -8, -24, -41, -58, -70, -75, -74, -67, -57, -43, -30, -18, -3, 13, 26, 39, + 48, 56, 60, 58, 51, 45, 42, 36, 29, 25, 20, 14, 9, 6, 3, 0, + -5, -6, -12, -17, -22, -21, -20, -24, -33, -37, -38, -35, -30, -28, -24, -17, + -3, 12, 24, 33, 43, 50, 52, 49, 40, 28, 13, -3, -18, -34, -51, -63, + -71, -72, -67, -59, -49, -37, -24, -10, 3, 16, 27, 37, 46, 50, 53, 51, + 49, 46, 43, 37, 32, 29, 25, 21, 17, 10, 4, -3, -8, -10, -11, -18, + -25, -29, -31, -34, -37, -40, -40, -37, -31, -25, -20, -13, 0, 17, 31, 41, + 48, 50, 49, 46, 36, 22, 8, -5, -20, -36, -49, -61, -67, -67, -61, -51, + -44, -36, -23, -9, 4, 13, 20, 30, 38, 46, 48, 47, 44, 44, 44, 46, + 42, 35, 31, 28, 24, 15, 5, -3, -6, -10, -18, -28, -35, -39, -41, -41, + -43, -45, -42, -36, -29, -23, -15, 1, 15, 28, 40, 47, 51, 51, 46, 37, + 27, 14, 2, -14, -29, -42, -49, -54, -62, -63, -57, -49, -41, -31, -21, -12, + -3, 6, 17, 25, 32, 40, 45, 49, 50, 48, 49, 49, 48, 44, 39, 34, + 26, 13, 4, -4, -11, -17, -23, -32, -41, -48, -48, -49, -48, -44, -39, -36, + -31, -21, -5, 13, 24, 35, 44, 51, 52, 47, 39, 30, 21, 8, -6, -18, + -34, -44, -50, -54, -59, -58, -53, -46, -38, -28, -18, -10, -4, 6, 16, 24, + 30, 37, 42, 48, 49, 47, 48, 51, 51, 49, 45, 35, 27, 17, 9, 0, + -12, -23, -32, -41, -48, -53, -55, -54, -53, -49, -43, -38, -27, -13, 5, 20, + 33, 44, 52, 58, 57, 50, 40, 29, 16, 5, -11, -29, -43, -53, -56, -62, + -65, -63, -54, -42, -33, -24, -16, -8, 3, 16, 23, 29, 33, 38, 44, 46, + 45, 43, 45, 49, 52, 48, 42, 37, 28, 19, 10, 0, -13, -25, -36, -42, + -47, -56, -58, -56, -53, -49, -48, -40, -26, -6, 13, 27, 39, 49, 59, 64, + 62, 53, 42, 29, 16, 2, -18, -37, -52, -60, -65, -71, -75, -68, -55, -41, + -30, -19, -10, 0, 14, 24, 33, 37, 38, 39, 42, 45, 45, 43, 45, 48, + 47, 46, 41, 35, 28, 19, 8, -6, -20, -30, -38, -44, -50, -55, -57, -59, + -57, -53, -46, -35, -19, 0, 17, 32, 45, 59, 66, 66, 59, 54, 46, 32, + 15, -5, -24, -43, -57, -65, -71, -76, -78, -71, -58, -41, -27, -16, -5, 5, + 15, 27, 37, 43, 43, 42, 42, 42, 43, 46, 46, 46, 45, 42, 41, 35, + 28, 18, 7, -6, -18, -29, -37, -44, -51, -56, -59, -61, -60, -55, -45, -33, + -18, -2, 18, 37, 50, 61, 67, 68, 65, 59, 47, 31, 10, -11, -32, -47, + -58, -71, -81, -86, -83, -70, -52, -36, -21, -9, 2, 13, 25, 35, 41, 44, + 43, 40, 39, 39, 40, 43, 43, 40, 39, 40, 40, 36, 28, 18, 9, -5, + -18, -28, -36, -44, -52, -57, -61, -64, -63, -56, -43, -27, -13, 6, 26, 44, + 56, 66, 71, 71, 64, 55, 42, 23, 3, -19, -38, -52, -66, -76, -82, -86, + -81, -67, -49, -32, -19, -8, 3, 15, 28, 36, 42, 43, 43, 41, 41, 40, + 40, 41, 40, 40, 41, 41, 36, 30, 24, 17, 10, -5, -19, -29, -37, -43, + -50, -57, -64, -66, -60, -50, -40, -28, -10, 12, 32, 45, 54, 59, 64, 67, + 63, 54, 35, 14, -6, -22, -35, -50, -64, -75, -82, -81, -73, -59, -46, -33, + -21, -8, 5, 19, 27, 33, 40, 44, 44, 42, 40, 42, 41, 40, 38, 39, + 38, 38, 35, 30, 21, 13, 4, -8, -16, -25, -35, -45, -53, -62, -65, -63, + -56, -47, -39, -25, -6, 15, 32, 45, 53, 58, 64, 65, 60, 48, 30, 9, + -7, -19, -31, -47, -60, -72, -79, -79, -73, -61, -50, -37, -24, -10, 3, 12, + 22, 33, 43, 47, 46, 44, 43, 45, 46, 45, 45, 43, 41, 38, 34, 26, + 16, 7, -2, -10, -19, -29, -39, -50, -59, -64, -62, -58, -51, -44, -34, -22, + -2, 16, 30, 41, 52, 56, 57, 58, 54, 42, 29, 13, 2, -12, -27, -42, + -56, -67, -71, -73, -70, -63, -55, -42, -26, -10, 2, 11, 20, 33, 41, 46, + 45, 43, 49, 53, 52, 48, 44, 43, 42, 38, 33, 22, 12, 4, -5, -13, + -23, -34, -43, -50, -57, -61, -60, -55, -49, -40, -29, -14, -2, 12, 25, 35, + 44, 51, 56, 56, 49, 39, 30, 20, 10, -2, -17, -32, -48, -60, -67, -74, + -77, -74, -66, -50, -36, -21, -9, 0, 14, 30, 43, 51, 53, 57, 62, 64, + 62, 58, 53, 48, 42, 36, 25, 12, 4, -4, -12, -21, -31, -38, -43, -45, + -47, -49, -47, -44, -40, -34, -28, -22, -11, 1, 11, 21, 28, 39, 49, 53, + 52, 49, 44, 38, 29, 16, -4, -24, -41, -57, -74, -86, -90, -86, -73, -59, + -44, -30, -16, 1, 21, 40, 54, 61, 66, 67, 71, 72, 65, 57, 49, 41, + 33, 24, 12, 1, -8, -12, -15, -22, -31, -37, -35, -31, -33, -36, -39, -40, + -38, -34, -32, -29, -24, -14, -2, 11, 24, 36, 48, 56, 61, 63, 59, 54, + 44, 27, 6, -19, -46, -68, -84, -94, -99, -98, -90, -72, -51, -30, -15, 1, + 22, 46, 64, 76, 78, 80, 81, 78, 72, 60, 45, 34, 24, 13, 0, -13, + -18, -18, -18, -22, -28, -29, -24, -19, -19, -26, -33, -38, -40, -40, -41, -42, + -41, -32, -15, 6, 22, 37, 50, 62, 74, 79, 76, 65, 50, 30, 6, -24, + -54, -78, -94, -106, -110, -103, -89, -69, -49, -29, -10, 11, 36, 57, 73, 78, + 80, 82, 83, 77, 66, 51, 37, 24, 14, 5, -5, -12, -17, -17, -17, -18, + -19, -17, -13, -13, -19, -28, -37, -44, -44, -48, -53, -59, -54, -35, -12, 11, + 29, 46, 61, 78, 88, 90, 84, 68, 49, 24, -6, -39, -71, -92, -104, -115, + -116, -108, -89, -66, -43, -21, 1, 24, 49, 68, 78, 82, 81, 81, 79, 71, + 56, 37, 24, 15, 6, -4, -9, -11, -9, -6, -6, -10, -11, -6, -4, -8, + -20, -33, -44, -55, -61, -65, -70, -68, -55, -31, -6, 15, 38, 61, 82, 97, + 101, 94, 80, 61, 37, 9, -25, -60, -88, -107, -119, -123, -116, -99, -77, -53, + -30, -5, 20, 47, 68, 80, 82, 82, 80, 77, 70, 57, 40, 23, 10, 3, + -2, -3, -4, -3, 2, 5, 7, 5, 5, 4, -4, -17, -32, -45, -60, -69, + -74, -79, -80, -70, -47, -20, 9, 32, 55, 76, 94, 104, 103, 91, 71, 46, + 16, -16, -48, -75, -97, -115, -121, -117, -101, -80, -57, -32, -8, 15, 39, 58, + 68, 73, 73, 73, 69, 61, 50, 39, 26, 15, 7, 4, 7, 12, 18, 19, + 20, 18, 17, 15, 10, -4, -20, -41, -57, -68, -77, -85, -91, -90, -76, -53, + -25, 2, 28, 55, 79, 97, 106, 104, 94, 77, 52, 22, -9, -39, -67, -92, + -111, -119, -115, -99, -79, -55, -33, -11, 15, 37, 55, 67, 71, 68, 61, 51, + 44, 40, 35, 24, 10, 3, 4, 13, 25, 36, 42, 41, 34, 29, 20, 12, + -2, -21, -43, -66, -84, -94, -96, -96, -93, -81, -55, -26, 4, 30, 56, 80, + 98, 107, 106, 95, 77, 53, 24, -8, -38, -64, -85, -101, -109, -109, -100, -80, + -55, -31, -8, 13, 31, 46, 56, 61, 59, 52, 43, 36, 30, 25, 16, 8, + 7, 11, 23, 37, 48, 56, 59, 56, 48, 33, 17, -5, -29, -54, -79, -96, + -106, -109, -105, -96, -82, -57, -25, 8, 38, 61, 79, 94, 103, 102, 92, 73, + 46, 19, -10, -36, -62, -81, -95, -101, -100, -90, -71, -47, -25, -3, 18, 31, + 41, 49, 53, 50, 42, 32, 21, 13, 9, 7, 8, 8, 12, 30, 49, 63, + 71, 76, 75, 67, 48, 25, -3, -30, -59, -87, -107, -120, -124, -117, -105, -89, + -63, -31, 5, 40, 63, 81, 92, 100, 100, 88, 69, 46, 20, -6, -31, -55, + -73, -87, -91, -88, -80, -64, -45, -22, 1, 16, 27, 34, 39, 45, 41, 31, + 20, 9, 4, 3, 1, 3, 6, 15, 32, 53, 71, 81, 85, 86, 78, 61, + 35, 3, -29, -63, -93, -113, -124, -128, -124, -110, -89, -64, -32, 5, 38, 62, + 80, 91, 98, 93, 80, 63, 42, 19, -5, -29, -51, -68, -78, -81, -79, -72, + -58, -40, -19, 0, 13, 21, 29, 35, 35, 29, 21, 14, 8, 2, -2, -3, + 1, 10, 20, 36, 56, 73, 84, 89, 89, 81, 65, 41, 6, -32, -63, -90, + -110, -124, -127, -123, -110, -89, -61, -30, 2, 33, 56, 71, 81, 86, 85, 74, + 58, 38, 17, -5, -21, -38, -52, -62, -69, -69, -64, -50, -34, -18, -5, 5, + 13, 23, 28, 27, 22, 15, 10, 6, 1, 0, -2, 2, 9, 23, 41, 56, + 72, 84, 88, 89, 81, 66, 45, 15, -20, -55, -84, -106, -119, -121, -116, -105, + -89, -67, -38, -7, 21, 44, 58, 69, 75, 74, 64, 50, 36, 22, 8, -10, + -26, -39, -47, -54, -56, -53, -47, -36, -25, -11, -2, 5, 14, 23, 24, 20, + 12, 7, 6, 6, 6, 4, 5, 10, 22, 39, 57, 72, 80, 82, 80, 73, + 62, 45, 18, -13, -48, -78, -96, -105, -105, -104, -97, -81, -64, -40, -15, 10, + 28, 40, 49, 54, 53, 49, 42, 31, 22, 13, 2, -9, -17, -22, -30, -38, + -40, -37, -33, -28, -22, -16, -10, -5, 5, 11, 11, 6, 3, 5, 11, 16, + 16, 18, 22, 29, 40, 54, 68, 75, 74, 72, 63, 49, 35, 15, -10, -37, + -63, -83, -94, -95, -89, -82, -73, -63, -46, -24, -2, 16, 25, 31, 35, 39, + 41, 37, 30, 22, 15, 11, 4, -3, -11, -18, -25, -31, -35, -33, -28, -22, + -18, -16, -13, -4, 5, 10, 11, 10, 5, 6, 14, 21, 23, 24, 27, 33, + 45, 59, 68, 72, 67, 57, 46, 34, 19, 0, -24, -49, -70, -81, -82, -77, + -70, -65, -60, -49, -34, -15, 2, 9, 13, 14, 18, 20, 21, 19, 18, 17, + 16, 15, 13, 10, 5, -3, -12, -20, -26, -28, -27, -24, -26, -25, -18, -9, + 3, 9, 10, 10, 11, 18, 27, 32, 33, 33, 35, 42, 51, 58, 59, 55, + 46, 36, 25, 16, 3, -15, -33, -50, -61, -65, -64, -59, -57, -56, -52, -42, + -29, -14, -5, -2, -3, 1, 8, 12, 13, 13, 16, 16, 18, 19, 19, 14, + 4, -3, -10, -19, -24, -24, -22, -20, -24, -23, -16, -2, 10, 16, 14, 13, + 16, 28, 35, 36, 35, 32, 33, 40, 45, 49, 47, 41, 31, 20, 12, 4, + -8, -16, -29, -41, -50, -53, -50, -49, -51, -51, -48, -40, -30, -20, -13, -13, + -12, -6, 2, 8, 12, 13, 16, 21, 26, 27, 23, 15, 8, 0, -10, -19, + -23, -24, -24, -26, -25, -21, -9, 5, 15, 19, 20, 22, 28, 36, 39, 38, + 36, 33, 33, 35, 37, 38, 36, 30, 20, 9, 4, -3, -10, -17, -26, -35, + -40, -45, -47, -51, -52, -49, -46, -39, -30, -23, -19, -17, -12, -5, 1, 4, + 7, 11, 18, 22, 22, 22, 20, 17, 12, 3, -8, -16, -18, -16, -17, -19, + -18, -12, 3, 13, 19, 20, 24, 29, 34, 35, 33, 32, 31, 31, 30, 26, + 24, 24, 25, 21, 14, 6, 0, -4, -5, -10, -19, -31, -37, -40, -47, -51, + -50, -49, -45, -39, -31, -25, -19, -12, -6, -3, 0, 2, 6, 13, 17, 18, + 16, 15, 16, 14, 7, -3, -10, -12, -13, -13, -14, -13, -6, 6, 18, 24, + 25, 26, 29, 33, 32, 26, 24, 23, 23, 22, 18, 14, 15, 21, 24, 22, + 14, 6, 4, 4, 1, -9, -21, -32, -41, -47, -50, -54, -54, -51, -47, -37, + -30, -21, -10, -3, 1, 4, 6, 7, 8, 7, 7, 7, 7, 6, 6, 5, + 2, -3, -8, -8, -6, -3, 1, 3, 9, 17, 25, 29, 32, 33, 29, 26, + 24, 23, 20, 17, 14, 11, 8, 8, 14, 21, 22, 17, 13, 9, 9, 7, + 1, -11, -25, -37, -44, -52, -53, -55, -55, -51, -43, -35, -24, -14, -4, 3, + 4, 4, 6, 7, 6, 3, -2, -2, 2, 6, 5, 1, -4, -8, -7, -5, + 3, 9, 9, 12, 17, 25, 32, 37, 37, 32, 25, 21, 19, 17, 15, 9, + 6, 6, 6, 8, 14, 23, 24, 20, 15, 14, 11, 3, -6, -18, -31, -44, + -53, -54, -57, -58, -55, -47, -37, -26, -16, -4, 7, 10, 10, 9, 7, 3, + -2, -6, -8, -6, -5, -4, -7, -10, -8, -6, 0, 6, 12, 16, 20, 27, + 33, 35, 35, 36, 34, 28, 21, 16, 10, 7, 7, 5, 3, 1, 5, 12, + 21, 25, 23, 17, 14, 13, 9, -3, -17, -30, -41, -50, -54, -59, -61, -55, + -46, -37, -26, -15, -4, 7, 14, 15, 12, 6, 1, -3, -7, -12, -14, -15, + -13, -12, -12, -12, -8, 0, 8, 15, 20, 25, 31, 36, 40, 41, 41, 38, + 33, 27, 21, 12, 4, 1, 0, -4, -5, -2, 5, 12, 17, 19, 19, 18, + 14, 11, 2, -9, -21, -32, -42, -49, -55, -57, -56, -49, -39, -30, -20, -8, + 3, 12, 17, 18, 12, 5, -2, -8, -14, -18, -21, -22, -21, -21, -19, -13, + -7, 4, 14, 24, 32, 39, 44, 48, 47, 44, 41, 38, 33, 27, 17, 7, + -3, -5, -5, -5, -5, -5, 3, 12, 17, 19, 16, 11, 7, 3, -6, -15, + -26, -36, -42, -48, -53, -54, -50, -40, -31, -22, -12, -2, 11, 19, 20, 13, + 6, 2, -5, -12, -21, -26, -29, -31, -30, -27, -21, -13, -2, 12, 25, 36, + 48, 57, 62, 60, 51, 46, 43, 37, 28, 15, 3, -8, -12, -14, -12, -10, + -7, -4, 8, 16, 20, 17, 14, 10, 6, -2, -12, -24, -32, -39, -45, -51, + -54, -52, -43, -32, -21, -12, -2, 11, 22, 28, 24, 13, 4, -6, -14, -23, + -32, -38, -41, -42, -39, -31, -20, -8, 6, 21, 37, 50, 63, 69, 68, 61, + 55, 48, 39, 29, 20, 9, -6, -15, -17, -13, -11, -7, -4, 3, 11, 13, + 16, 15, 10, 5, 0, -8, -15, -25, -31, -37, -42, -49, -52, -46, -37, -30, + -21, -12, 0, 14, 25, 28, 25, 15, 2, -11, -22, -29, -36, -44, -49, -49, + -43, -32, -18, -5, 13, 30, 50, 66, 74, 75, 71, 68, 61, 50, 37, 26, + 15, 3, -13, -22, -22, -20, -16, -14, -9, 1, 9, 11, 11, 9, 9, 9, + 6, -3, -15, -25, -32, -37, -41, -50, -53, -50, -41, -30, -20, -8, 6, 21, + 31, 33, 26, 15, 0, -12, -23, -34, -46, -56, -60, -54, -44, -31, -19, -2, + 21, 44, 66, 77, 81, 79, 75, 72, 63, 51, 35, 23, 10, -4, -16, -25, + -28, -26, -22, -16, -12, -7, -2, 4, 8, 10, 14, 14, 7, -3, -12, -20, + -28, -36, -42, -48, -53, -53, -43, -31, -19, -6, 12, 25, 31, 30, 26, 15, + -2, -17, -28, -40, -52, -60, -61, -53, -40, -25, -9, 11, 32, 56, 74, 84, + 85, 81, 76, 72, 61, 46, 29, 13, -2, -16, -23, -29, -33, -31, -25, -19, + -14, -8, 2, 10, 14, 18, 19, 17, 8, 1, -12, -24, -35, -42, -49, -54, + -57, -53, -43, -30, -13, 7, 22, 32, 34, 32, 26, 11, -8, -24, -40, -50, + -60, -66, -63, -53, -36, -17, 2, 23, 45, 67, 84, 90, 91, 85, 78, 72, + 62, 44, 24, 4, -9, -21, -32, -39, -41, -36, -30, -23, -17, -9, 2, 13, + 23, 27, 26, 19, 12, 2, -12, -26, -38, -47, -54, -59, -59, -53, -41, -23, + -5, 14, 28, 36, 36, 31, 21, 6, -13, -31, -46, -58, -66, -70, -65, -50, + -28, -7, 14, 35, 58, 76, 89, 96, 94, 90, 82, 72, 54, 35, 16, -5, + -21, -31, -40, -48, -47, -38, -28, -20, -13, 1, 15, 28, 33, 33, 27, 18, + 8, -6, -21, -37, -52, -64, -66, -65, -58, -47, -30, -9, 13, 28, 38, 43, + 40, 31, 15, -5, -24, -40, -57, -69, -75, -74, -65, -48, -26, -2, 24, 47, + 66, 83, 97, 102, 102, 101, 91, 73, 51, 28, 7, -15, -33, -45, -56, -60, + -54, -42, -28, -17, -4, 13, 26, 36, 38, 36, 29, 16, 2, -14, -34, -52, + -62, -66, -65, -63, -53, -36, -15, 9, 27, 36, 41, 40, 35, 25, 8, -16, + -37, -55, -68, -77, -81, -75, -60, -37, -12, 12, 35, 57, 75, 94, 105, 107, + 103, 97, 84, 64, 41, 18, -6, -25, -40, -51, -57, -56, -46, -32, -19, -6, + 7, 20, 30, 34, 32, 24, 12, 0, -17, -33, -47, -60, -65, -64, -58, -46, + -31, -12, 8, 26, 37, 43, 44, 41, 28, 11, -12, -31, -49, -67, -81, -87, + -85, -72, -52, -30, -6, 21, 45, 69, 87, 101, 110, 113, 110, 100, 77, 51, + 27, 8, -11, -32, -49, -59, -59, -53, -41, -27, -11, 3, 14, 24, 28, 28, + 24, 17, 5, -15, -32, -45, -54, -61, -58, -54, -44, -32, -13, 8, 26, 37, + 41, 40, 36, 29, 16, -3, -24, -47, -66, -81, -89, -88, -76, -58, -37, -16, + 10, 34, 58, 78, 94, 106, 111, 107, 97, 81, 58, 37, 17, 0, -17, -33, + -45, -51, -48, -38, -26, -14, -3, 9, 16, 19, 17, 14, 10, 0, -15, -30, + -42, -49, -52, -49, -44, -37, -25, -8, 9, 21, 29, 32, 35, 33, 29, 19, + 1, -18, -38, -58, -75, -85, -85, -79, -70, -52, -29, -6, 20, 44, 67, 89, + 101, 110, 114, 107, 93, 72, 49, 28, 10, -9, -25, -38, -48, -49, -42, -31, + -20, -11, 0, 9, 13, 12, 7, 5, 0, -11, -24, -36, -42, -44, -43, -38, + -28, -16, -4, 8, 16, 22, 29, 30, 29, 24, 13, 2, -14, -32, -51, -68, + -79, -83, -77, -69, -56, -41, -19, 6, 31, 53, 74, 90, 101, 108, 109, 101, + 83, 60, 38, 24, 9, -10, -25, -36, -40, -37, -29, -21, -13, -8, 0, 3, + 0, -5, -6, -8, -16, -27, -35, -39, -40, -33, -27, -21, -11, 3, 14, 21, + 24, 27, 26, 22, 19, 13, 3, -14, -32, -53, -66, -74, -80, -80, -75, -63, + -47, -28, -4, 19, 41, 66, 85, 99, 105, 106, 104, 95, 76, 51, 29, 13, + 2, -12, -27, -36, -38, -32, -22, -15, -12, -8, -3, -4, -9, -12, -14, -18, + -26, -31, -35, -36, -29, -20, -10, -2, 7, 16, 25, 25, 24, 19, 15, 10, + 4, -4, -16, -30, -44, -57, -67, -73, -75, -70, -60, -48, -34, -16, 5, 27, + 51, 71, 85, 92, 99, 101, 95, 82, 64, 44, 28, 14, 1, -12, -22, -28, + -27, -22, -18, -17, -15, -15, -15, -21, -23, -25, -24, -27, -31, -34, -30, -21, + -6, 7, 13, 17, 22, 27, 28, 24, 16, 7, -3, -10, -17, -27, -35, -43, + -50, -58, -68, -70, -65, -53, -42, -32, -22, -4, 15, 36, 54, 70, 83, 89, + 92, 91, 82, 68, 54, 42, 29, 14, 2, -9, -17, -21, -22, -20, -21, -20, + -23, -26, -30, -32, -32, -29, -27, -28, -30, -26, -15, 0, 15, 25, 25, 25, + 26, 27, 21, 11, 0, -9, -17, -24, -30, -38, -45, -47, -49, -55, -59, -56, + -48, -39, -28, -20, -9, 7, 26, 44, 55, 65, 72, 79, 80, 77, 66, 57, + 49, 41, 30, 19, 7, -2, -7, -12, -17, -22, -25, -29, -33, -36, -39, -41, + -36, -29, -26, -26, -22, -11, 2, 17, 28, 32, 31, 29, 28, 23, 11, -2, + -9, -17, -24, -36, -44, -48, -49, -50, -53, -54, -54, -47, -36, -25, -17, -7, + 7, 21, 36, 47, 55, 63, 70, 72, 69, 60, 52, 46, 42, 34, 23, 15, + 8, 3, 0, -7, -14, -21, -24, -27, -32, -39, -44, -43, -37, -29, -25, -23, + -16, -2, 14, 26, 32, 33, 32, 30, 25, 16, 4, -6, -16, -25, -36, -45, + -50, -54, -51, -51, -54, -54, -48, -36, -23, -15, -6, 5, 17, 31, 42, 51, + 59, 62, 63, 61, 56, 51, 43, 40, 38, 28, 20, 13, 9, 7, 2, -8, + -16, -23, -27, -31, -36, -40, -43, -39, -31, -23, -20, -15, -4, 11, 24, 31, + 32, 31, 30, 25, 17, 7, -3, -13, -23, -36, -48, -56, -58, -57, -53, -50, + -52, -51, -40, -25, -12, 0, 7, 16, 25, 36, 49, 58, 60, 59, 57, 54, + 49, 43, 36, 31, 26, 18, 13, 10, 6, 4, 0, -6, -12, -19, -22, -26, + -31, -35, -35, -32, -27, -22, -16, -7, 4, 13, 21, 26, 30, 29, 27, 22, + 15, 4, -7, -19, -31, -44, -55, -59, -59, -58, -54, -52, -49, -41, -28, -14, + 0, 10, 18, 26, 33, 44, 50, 53, 51, 50, 48, 46, 41, 37, 30, 24, + 21, 18, 15, 13, 8, 4, 0, -6, -9, -14, -19, -23, -27, -33, -33, -31, + -25, -19, -11, -3, 3, 11, 20, 28, 31, 28, 22, 14, 8, -3, -15, -29, + -40, -49, -57, -62, -60, -56, -50, -47, -42, -32, -18, -3, 11, 20, 25, 29, + 35, 43, 49, 51, 47, 43, 41, 37, 33, 29, 24, 18, 15, 14, 13, 11, + 8, 5, 1, 0, -5, -11, -19, -23, -24, -25, -25, -26, -22, -15, -9, -3, + 4, 12, 19, 25, 26, 24, 17, 11, 2, -11, -26, -37, -45, -53, -58, -59, + -57, -53, -47, -42, -35, -25, -10, 5, 15, 19, 22, 29, 37, 45, 48, 47, + 44, 44, 43, 40, 33, 24, 19, 14, 13, 12, 8, 2, -2, 1, 1, 1, + -4, -12, -15, -14, -13, -14, -18, -18, -15, -12, -8, -5, 2, 10, 18, 21, + 20, 15, 10, 3, -7, -18, -31, -42, -47, -50, -53, -57, -57, -51, -42, -34, + -25, -15, -5, 7, 16, 22, 30, 35, 40, 43, 42, 39, 39, 38, 38, 31, + 22, 16, 14, 15, 17, 16, 12, 6, 4, 5, 7, 6, 0, -8, -12, -13, + -15, -19, -21, -20, -17, -14, -11, -6, 2, 10, 18, 21, 21, 19, 11, -2, + -17, -29, -37, -42, -46, -52, -55, -58, -52, -42, -34, -24, -15, -5, 5, 12, + 17, 24, 32, 37, 37, 36, 33, 33, 35, 35, 32, 26, 22, 16, 17, 19, + 19, 14, 7, 5, 5, 6, 5, 0, -7, -10, -9, -6, -7, -13, -17, -15, + -11, -8, -7, -6, 1, 7, 12, 13, 11, 7, 0, -12, -25, -35, -40, -42, + -43, -44, -47, -49, -43, -34, -22, -12, -7, 0, 4, 9, 17, 25, 31, 33, + 33, 31, 30, 27, 28, 30, 29, 25, 20, 17, 20, 24, 22, 17, 11, 10, + 9, 9, 5, -6, -11, -13, -9, -5, -9, -16, -19, -16, -9, -6, -6, -2, + 4, 8, 11, 11, 6, -4, -11, -21, -34, -39, -41, -40, -38, -40, -44, -38, + -28, -17, -10, -6, -5, -3, 3, 10, 15, 17, 20, 23, 26, 25, 24, 26, + 28, 30, 30, 28, 25, 24, 23, 25, 22, 18, 14, 9, 5, 0, -7, -12, + -13, -12, -7, -6, -9, -12, -10, -4, 2, 2, 3, 3, 3, 6, 7, 3, + -9, -21, -28, -35, -40, -40, -37, -37, -36, -36, -29, -22, -11, -3, 2, 3, + 0, 1, 3, 6, 9, 10, 10, 10, 13, 16, 21, 24, 29, 31, 33, 33, + 33, 32, 30, 27, 23, 16, 12, 7, -2, -7, -14, -19, -16, -10, -5, -7, + -9, -9, -6, 2, 6, 8, 7, 4, 3, 1, -3, -9, -16, -25, -34, -39, + -41, -37, -33, -31, -31, -29, -22, -12, -4, 2, 7, 5, 1, -2, 0, 4, + 4, 2, 2, 5, 10, 14, 19, 24, 28, 32, 36, 38, 36, 34, 31, 27, + 23, 18, 11, 3, -5, -12, -15, -15, -11, -6, -5, -6, -8, -7, -3, 1, + 4, 6, 3, -2, -7, -9, -12, -19, -24, -30, -34, -36, -35, -32, -29, -26, + -22, -16, -10, -3, 4, 8, 9, 4, 0, -3, 0, 1, -5, -7, -5, 1, + 7, 13, 14, 17, 27, 35, 38, 37, 35, 33, 31, 29, 25, 19, 11, 3, + 0, -6, -10, -10, -7, -5, -5, -7, -7, -6, -3, 1, 4, 3, 0, -8, + -15, -18, -20, -23, -27, -30, -32, -33, -29, -28, -25, -20, -16, -13, -6, 1, + 6, 7, 4, 0, -5, -5, -5, -6, -7, -6, -2, 5, 10, 15, 20, 25, + 32, 34, 34, 34, 32, 29, 24, 22, 19, 14, 9, 6, 4, 2, 0, 0, + 2, 2, -2, -4, -6, -5, -5, -4, -4, -7, -12, -19, -25, -26, -26, -26, + -26, -29, -28, -28, -25, -22, -18, -14, -10, -5, 0, 3, 4, 5, 4, 3, + -2, -7, -10, -12, -9, -6, 0, 6, 11, 14, 16, 22, 30, 33, 34, 29, + 25, 23, 21, 22, 22, 20, 18, 16, 14, 13, 11, 11, 11, 6, -4, -12, + -16, -17, -16, -13, -16, -22, -26, -30, -30, -25, -21, -18, -17, -19, -18, -20, + -19, -15, -13, -9, -7, -6, -5, -2, 3, 5, 4, 0, -5, -8, -6, -6, + -6, -2, 4, 9, 11, 13, 15, 19, 23, 25, 22, 19, 16, 17, 20, 21, + 22, 23, 24, 25, 24, 23, 22, 21, 16, 7, -4, -14, -21, -23, -24, -24, + -28, -34, -38, -36, -31, -21, -13, -9, -8, -10, -11, -12, -14, -13, -12, -9, + -10, -12, -11, -9, -4, 3, 4, 1, -3, -4, 1, 4, 7, 10, 10, 11, + 12, 11, 8, 9, 11, 13, 11, 5, 4, 11, 20, 26, 29, 32, 35, 39, + 39, 34, 30, 23, 15, 5, -10, -23, -31, -34, -32, -33, -37, -42, -41, -32, + -21, -11, -6, -3, -3, -6, -8, -11, -14, -15, -14, -14, -14, -19, -20, -15, + -7, 0, -2, -3, 0, 4, 10, 17, 19, 18, 18, 20, 18, 11, 5, 1, + -2, -4, -7, -8, -4, 4, 14, 24, 32, 38, 46, 51, 52, 46, 37, 28, + 19, 5, -12, -29, -39, -44, -46, -46, -50, -48, -39, -29, -14, -4, 6, 9, + 8, 6, 0, -8, -13, -15, -18, -22, -28, -30, -26, -18, -9, -7, -4, 2, + 10, 18, 24, 26, 26, 23, 22, 21, 14, 3, -5, -9, -14, -16, -16, -11, + -4, 6, 14, 24, 37, 50, 58, 58, 53, 45, 36, 28, 17, 1, -18, -36, + -47, -53, -54, -53, -51, -43, -33, -20, -8, 5, 15, 17, 13, 5, -4, -12, + -14, -18, -23, -30, -34, -32, -24, -15, -10, -6, -3, 7, 18, 27, 32, 33, + 30, 28, 24, 19, 12, 2, -10, -18, -24, -26, -23, -16, -6, 4, 12, 25, + 39, 53, 60, 60, 58, 51, 42, 30, 16, 0, -20, -37, -49, -57, -61, -57, + -50, -40, -29, -17, -4, 9, 17, 17, 11, 5, -3, -8, -13, -21, -30, -35, + -34, -29, -22, -16, -11, -6, 1, 12, 24, 34, 39, 39, 35, 28, 21, 16, + 8, -3, -16, -29, -35, -34, -26, -16, -9, 1, 14, 30, 46, 56, 60, 62, + 59, 57, 46, 32, 15, -2, -17, -35, -51, -61, -61, -55, -46, -39, -30, -19, + -4, 10, 14, 13, 7, 3, -2, -6, -15, -24, -31, -33, -31, -26, -23, -19, + -11, -2, 6, 17, 30, 38, 41, 39, 34, 25, 18, 14, 6, -9, -24, -34, + -38, -34, -28, -18, -9, 0, 14, 32, 44, 52, 58, 63, 66, 59, 45, 31, + 18, 4, -17, -36, -53, -60, -59, -54, -46, -39, -30, -18, -3, 6, 8, 6, + 3, 1, -3, -11, -22, -29, -28, -23, -20, -20, -18, -10, -2, 7, 17, 27, + 34, 37, 38, 33, 26, 19, 15, 11, 0, -17, -31, -39, -40, -34, -27, -20, + -11, 1, 16, 31, 43, 52, 59, 67, 70, 62, 47, 32, 19, 4, -18, -39, + -53, -60, -57, -51, -44, -37, -30, -17, -6, 1, 2, 1, 0, -2, -7, -15, + -23, -27, -25, -19, -16, -15, -12, -4, 5, 15, 25, 33, 37, 34, 31, 27, + 22, 17, 11, 2, -11, -25, -35, -41, -41, -34, -23, -13, -4, 6, 18, 31, + 43, 54, 61, 65, 62, 53, 44, 34, 22, 2, -20, -38, -47, -50, -47, -43, + -42, -41, -32, -19, -13, -11, -10, -7, -5, -5, -9, -14, -18, -17, -12, -9, + -8, -6, 1, 6, 12, 16, 21, 25, 25, 23, 19, 18, 14, 11, 8, 0, + -10, -23, -34, -36, -32, -24, -16, -12, -6, 4, 15, 30, 42, 52, 59, 60, + 58, 53, 46, 39, 27, 5, -19, -35, -43, -44, -43, -45, -49, -48, -39, -31, + -27, -24, -19, -11, -6, -3, -4, -6, -8, -5, 3, 5, 7, 6, 7, 9, + 12, 13, 15, 14, 12, 11, 11, 9, 8, 5, 4, 0, -12, -22, -28, -26, + -21, -17, -13, -10, -5, 4, 14, 22, 32, 44, 56, 61, 59, 56, 48, 38, + 25, 7, -10, -24, -33, -38, -44, -50, -51, -47, -41, -41, -41, -37, -26, -14, + -6, 0, -2, -3, 5, 13, 19, 21, 16, 12, 9, 9, 10, 7, 3, 2, + 2, 1, -2, 0, 3, 4, 1, -4, -12, -16, -16, -9, -9, -10, -9, -5, + 2, 7, 11, 17, 27, 39, 51, 54, 52, 52, 49, 42, 28, 10, -4, -15, + -25, -36, -48, -56, -58, -56, -52, -53, -54, -45, -28, -11, -2, 3, 8, 15, + 24, 30, 34, 30, 22, 16, 12, 6, -4, -9, -9, -8, -12, -14, -12, -5, + 3, 4, 2, -3, -4, 0, 3, 2, -4, -6, -6, -5, -4, -5, -3, 8, + 21, 36, 44, 50, 55, 58, 55, 45, 33, 20, 5, -11, -27, -43, -55, -60, + -61, -62, -64, -66, -58, -40, -20, -6, 3, 8, 16, 26, 34, 39, 38, 30, + 21, 11, 2, -9, -14, -13, -13, -15, -16, -14, -6, 1, 4, 4, 3, 4, + 7, 10, 10, 5, -3, -7, -8, -9, -12, -14, -11, 0, 13, 28, 40, 51, + 58, 61, 60, 56, 47, 33, 15, -8, -28, -44, -55, -62, -72, -81, -83, -74, + -58, -39, -21, -6, 8, 18, 30, 40, 47, 49, 44, 33, 19, 6, -6, -14, + -19, -23, -26, -24, -19, -13, -5, -2, 2, 5, 8, 11, 14, 13, 9, 2, + -4, -8, -12, -15, -19, -18, -13, -3, 14, 30, 44, 53, 62, 66, 66, 59, + 48, 33, 12, -10, -31, -46, -58, -71, -79, -84, -81, -71, -54, -34, -14, 1, + 14, 26, 37, 44, 48, 49, 41, 29, 12, -3, -13, -17, -19, -24, -26, -22, + -16, -8, -3, -2, 3, 6, 10, 13, 12, 10, 6, 2, -4, -11, -18, -22, + -22, -19, -14, -3, 13, 30, 46, 61, 68, 71, 70, 64, 52, 32, 10, -12, + -31, -51, -67, -81, -88, -91, -84, -69, -51, -32, -12, 8, 25, 37, 43, 47, + 52, 50, 40, 23, 5, -8, -13, -18, -23, -28, -26, -19, -12, -6, -4, -2, + 2, 6, 11, 11, 5, 3, 4, 1, -9, -17, -21, -23, -22, -19, -14, 0, + 17, 37, 54, 65, 70, 75, 76, 67, 50, 30, 6, -15, -35, -56, -75, -88, + -93, -88, -78, -64, -47, -26, -3, 17, 31, 37, 42, 46, 48, 42, 27, 10, + 0, -3, -7, -14, -21, -21, -13, -4, 1, -2, -3, 1, 5, 7, 4, -3, + -8, -7, -7, -14, -19, -22, -23, -21, -20, -16, -6, 12, 32, 51, 63, 70, + 76, 78, 75, 63, 44, 20, -5, -26, -46, -67, -83, -94, -93, -83, -69, -55, + -40, -17, 8, 25, 34, 38, 43, 48, 45, 35, 20, 8, 2, 3, -2, -12, + -18, -15, -8, 0, 0, -5, -6, -4, -3, -5, -11, -15, -14, -12, -13, -16, + -19, -20, -20, -16, -10, -2, 11, 24, 42, 57, 64, 70, 73, 72, 64, 48, + 26, 4, -15, -35, -50, -68, -81, -88, -81, -68, -55, -44, -29, -10, 9, 22, + 25, 30, 37, 38, 35, 24, 14, 11, 13, 14, 9, 0, -5, -3, 3, 4, + -2, -10, -15, -15, -15, -19, -25, -24, -20, -18, -19, -20, -18, -16, -13, -9, + 1, 12, 25, 37, 53, 63, 69, 74, 73, 69, 56, 37, 15, -6, -25, -42, + -59, -75, -82, -81, -72, -61, -50, -35, -17, -2, 13, 20, 27, 31, 34, 34, + 28, 19, 14, 13, 15, 14, 8, 4, 3, 5, 5, 1, -6, -15, -18, -22, + -27, -33, -34, -31, -25, -24, -20, -19, -17, -10, -2, 9, 18, 28, 39, 51, + 60, 67, 71, 72, 67, 53, 35, 16, -4, -21, -40, -57, -70, -76, -74, -65, + -55, -44, -34, -21, -7, 6, 15, 18, 20, 24, 24, 21, 16, 15, 16, 17, + 17, 16, 13, 12, 13, 13, 9, 0, -12, -17, -22, -31, -40, -43, -40, -35, + -30, -26, -24, -20, -11, -2, 9, 19, 29, 39, 46, 54, 60, 66, 67, 66, + 58, 41, 21, 5, -11, -29, -47, -62, -68, -68, -65, -57, -49, -39, -27, -13, + -2, 6, 11, 18, 23, 24, 21, 19, 19, 21, 21, 18, 15, 11, 13, 15, + 15, 10, -2, -8, -14, -21, -30, -39, -44, -44, -40, -33, -29, -27, -21, -12, + -3, 6, 16, 28, 40, 48, 54, 56, 59, 61, 62, 57, 44, 28, 12, -3, + -22, -40, -55, -64, -63, -61, -56, -51, -41, -29, -15, -6, 1, 8, 15, 20, + 20, 18, 17, 18, 23, 23, 20, 17, 15, 18, 20, 20, 15, 4, -5, -11, + -20, -32, -43, -49, -48, -43, -36, -32, -29, -21, -13, 0, 11, 20, 30, 38, + 46, 50, 51, 53, 56, 53, 48, 41, 30, 19, 5, -10, -26, -42, -50, -56, + -57, -56, -53, -46, -38, -27, -18, -10, -2, 8, 16, 19, 24, 24, 22, 23, + 25, 23, 17, 16, 15, 16, 14, 10, 3, -5, -11, -20, -28, -35, -42, -44, + -42, -35, -29, -25, -19, -11, 0, 10, 20, 26, 31, 38, 45, 48, 46, 46, + 44, 41, 37, 30, 22, 13, 1, -15, -27, -36, -44, -49, -51, -52, -49, -44, + -37, -27, -20, -12, 1, 10, 19, 23, 28, 29, 28, 28, 24, 19, 17, 16, + 15, 14, 10, 4, -3, -10, -15, -23, -31, -36, -41, -41, -39, -32, -24, -19, + -11, -3, 5, 15, 24, 31, 36, 42, 45, 44, 41, 37, 33, 31, 29, 23, + 14, 2, -8, -16, -22, -31, -40, -44, -46, -46, -46, -44, -37, -28, -20, -10, + 2, 11, 20, 28, 32, 32, 29, 26, 22, 19, 17, 14, 12, 11, 8, 2, + -5, -14, -20, -24, -30, -34, -37, -38, -36, -30, -21, -14, -6, 2, 11, 19, + 26, 30, 34, 41, 44, 42, 38, 32, 27, 25, 24, 21, 11, 1, -9, -16, + -25, -34, -40, -43, -45, -48, -50, -49, -40, -27, -15, -6, 4, 15, 27, 36, + 40, 37, 32, 27, 22, 15, 11, 10, 8, 6, 0, -8, -14, -16, -17, -18, + -24, -31, -33, -33, -27, -22, -17, -10, -4, 6, 13, 17, 22, 27, 33, 38, + 39, 37, 35, 33, 31, 27, 23, 19, 11, 3, -7, -20, -30, -38, -42, -42, + -46, -53, -58, -53, -41, -27, -13, -2, 10, 19, 30, 39, 43, 38, 29, 23, + 18, 12, 8, 6, 6, 4, -3, -8, -12, -13, -10, -12, -17, -24, -25, -23, + -23, -23, -19, -12, -4, 2, 5, 9, 14, 22, 32, 37, 39, 39, 37, 37, + 33, 28, 27, 21, 12, 0, -14, -25, -33, -38, -43, -48, -54, -60, -59, -48, + -36, -20, -8, 2, 12, 26, 39, 44, 40, 32, 27, 23, 16, 8, 3, 3, + 2, 1, -4, -9, -9, -6, -6, -8, -13, -16, -18, -21, -22, -21, -16, -7, + -2, 0, -2, 2, 13, 25, 30, 34, 34, 34, 34, 33, 33, 31, 26, 21, + 11, -3, -15, -25, -31, -37, -48, -57, -62, -63, -56, -46, -35, -25, -12, 5, + 18, 32, 40, 40, 36, 32, 29, 22, 15, 7, 3, 0, 0, 0, 1, -2, + -2, 0, 0, -3, -4, -7, -13, -22, -28, -25, -17, -10, -10, -11, -10, -4, + 12, 26, 36, 39, 40, 41, 40, 37, 35, 33, 28, 19, 3, -11, -22, -30, + -37, -46, -56, -63, -65, -59, -52, -43, -29, -17, -4, 10, 23, 32, 36, 36, + 34, 29, 24, 19, 12, 5, -2, 0, 4, 7, 10, 9, 6, 5, 5, 5, + 0, -10, -20, -26, -29, -26, -20, -18, -19, -17, -9, 3, 16, 28, 36, 40, + 42, 43, 41, 40, 36, 33, 26, 16, 3, -10, -21, -31, -42, -53, -61, -65, + -63, -58, -52, -41, -31, -18, -4, 9, 21, 26, 29, 30, 31, 31, 28, 21, + 12, 6, 5, 10, 13, 13, 14, 9, 8, 7, 5, 0, -8, -17, -24, -28, + -27, -23, -17, -14, -12, -8, 2, 15, 26, 32, 36, 39, 38, 37, 36, 33, + 28, 21, 16, 10, 1, -13, -25, -34, -41, -50, -59, -62, -62, -53, -44, -37, + -28, -19, -6, 7, 14, 18, 22, 26, 28, 28, 21, 13, 6, 6, 15, 19, + 21, 20, 20, 18, 16, 13, 7, -3, -12, -21, -27, -31, -30, -24, -15, -11, + -8, 0, 10, 23, 29, 32, 34, 34, 34, 33, 32, 27, 23, 20, 17, 10, + -2, -15, -25, -34, -43, -52, -61, -63, -58, -49, -43, -41, -33, -22, -9, 3, + 11, 17, 21, 26, 30, 28, 23, 17, 15, 18, 22, 22, 20, 21, 21, 18, + 12, 4, -5, -11, -16, -22, -28, -32, -24, -14, -7, -5, 1, 11, 20, 27, + 30, 26, 25, 29, 30, 29, 22, 17, 18, 22, 20, 9, -8, -18, -25, -31, + -40, -53, -60, -58, -54, -46, -45, -42, -32, -20, -10, -2, 5, 12, 19, 25, + 27, 22, 18, 18, 21, 24, 25, 22, 24, 26, 27, 22, 10, 0, -7, -9, + -12, -21, -28, -28, -20, -9, -4, -2, 5, 14, 22, 24, 21, 15, 18, 24, + 28, 24, 19, 21, 26, 30, 22, 7, -6, -15, -23, -34, -50, -61, -66, -61, + -52, -50, -49, -45, -36, -22, -10, 1, 11, 15, 20, 26, 26, 24, 21, 21, + 27, 28, 24, 21, 22, 26, 24, 16, 5, -5, -7, -5, -11, -17, -22, -17, + -7, 0, 1, 4, 9, 16, 19, 18, 13, 12, 16, 22, 24, 23, 23, 28, + 33, 27, 16, 2, -12, -23, -33, -45, -57, -64, -64, -55, -51, -52, -49, -39, + -25, -13, -6, 1, 6, 12, 16, 18, 20, 18, 20, 25, 28, 28, 29, 31, + 36, 37, 28, 15, 7, 3, 0, -4, -14, -21, -23, -16, -7, -4, -3, 1, + 10, 16, 17, 10, 7, 9, 18, 24, 24, 24, 28, 34, 34, 26, 12, -3, + -15, -26, -40, -53, -61, -65, -62, -59, -57, -55, -49, -39, -27, -18, -6, 3, + 8, 14, 17, 21, 25, 26, 27, 28, 30, 32, 32, 31, 32, 28, 22, 14, + 6, 3, 0, -3, -8, -12, -12, -5, 0, 2, 1, 3, 6, 11, 11, 7, + 4, 6, 13, 20, 24, 28, 31, 32, 28, 19, 7, -7, -20, -32, -44, -53, + -58, -58, -55, -54, -53, -50, -46, -40, -27, -14, -6, -6, -5, 0, 8, 16, + 20, 23, 25, 30, 37, 42, 43, 41, 39, 34, 28, 18, 9, 4, 3, 0, + -10, -13, -12, -10, -5, 1, 1, 0, 4, 8, 7, 5, 6, 11, 19, 23, + 27, 32, 33, 27, 20, 10, 0, -15, -30, -41, -49, -52, -54, -55, -55, -53, + -50, -45, -40, -32, -24, -16, -11, -10, -8, -3, 6, 13, 17, 21, 29, 37, + 43, 48, 47, 43, 38, 35, 30, 19, 11, 7, 2, -5, -9, -9, -5, 1, + 1, 0, -2, 1, 3, 6, 5, 4, 5, 10, 16, 20, 24, 27, 25, 18, + 10, 3, -9, -21, -31, -39, -44, -47, -47, -44, -46, -48, -48, -45, -39, -36, + -30, -26, -25, -23, -19, -9, 4, 14, 24, 32, 41, 48, 54, 56, 57, 52, + 47, 40, 28, 17, 10, 4, -3, -8, -10, -8, -6, -5, -5, -5, -3, 0, + 3, 4, 4, 5, 7, 12, 19, 26, 27, 24, 18, 12, 5, -3, -12, -24, + -34, -43, -46, -48, -48, -46, -46, -45, -44, -42, -38, -33, -29, -26, -26, -22, + -14, -5, 5, 13, 23, 32, 40, 47, 52, 56, 57, 55, 52, 47, 36, 27, + 19, 11, 3, -5, -6, -8, -10, -13, -15, -14, -13, -11, -6, 1, 4, 7, + 11, 17, 21, 26, 28, 26, 19, 10, 2, -7, -17, -26, -36, -41, -45, -47, + -45, -44, -44, -41, -39, -40, -40, -37, -33, -34, -32, -26, -18, -9, 2, 12, + 26, 40, 47, 56, 63, 66, 66, 63, 60, 53, 40, 27, 14, 3, -8, -11, + -12, -15, -19, -19, -18, -15, -12, -8, 0, 6, 11, 13, 14, 17, 23, 29, + 27, 18, 9, 1, -7, -16, -25, -35, -43, -49, -47, -44, -43, -42, -40, -36, + -34, -33, -33, -33, -35, -34, -30, -23, -16, -9, 2, 14, 27, 39, 49, 58, + 66, 69, 68, 66, 61, 53, 45, 32, 18, 1, -11, -14, -17, -17, -20, -23, + -21, -17, -13, -3, 4, 10, 13, 14, 17, 18, 21, 24, 22, 15, 6, -4, + -12, -22, -28, -38, -49, -51, -48, -45, -43, -40, -38, -36, -35, -34, -33, -33, + -34, -35, -33, -29, -18, -6, 6, 19, 33, 46, 59, 71, 78, 78, 78, 74, + 67, 54, 39, 22, 6, -8, -16, -22, -25, -25, -26, -22, -17, -12, -3, 6, + 15, 17, 16, 14, 14, 16, 17, 16, 13, 6, -2, -11, -20, -27, -34, -43, + -49, -48, -44, -41, -39, -36, -33, -34, -33, -34, -32, -33, -35, -35, -30, -21, + -11, 0, 9, 23, 38, 52, 65, 74, 76, 76, 74, 70, 62, 47, 28, 13, + 2, -6, -14, -21, -23, -20, -18, -16, -13, -7, 1, 8, 10, 11, 9, 11, + 11, 13, 15, 16, 13, 8, -2, -11, -19, -27, -37, -47, -52, -51, -48, -46, + -43, -40, -38, -36, -35, -35, -38, -38, -33, -27, -21, -16, -7, 6, 21, 36, + 49, 61, 70, 75, 79, 78, 73, 62, 49, 35, 22, 8, -3, -12, -17, -20, + -18, -14, -13, -15, -12, -5, 4, 7, 8, 8, 9, 8, 9, 11, 14, 14, + 10, 4, -6, -15, -25, -35, -41, -48, -54, -53, -47, -42, -38, -37, -35, -31, + -31, -30, -30, -29, -26, -24, -19, -12, -2, 10, 22, 35, 48, 60, 70, 76, + 76, 73, 67, 57, 44, 28, 14, 5, -3, -8, -13, -14, -13, -10, -11, -11, + -8, -2, 4, 6, 5, 5, 5, 6, 10, 11, 10, 8, 4, -2, -9, -15, + -24, -35, -44, -50, -52, -49, -45, -42, -42, -40, -37, -37, -37, -33, -29, -26, + -24, -21, -16, -7, 6, 18, 30, 41, 54, 66, 75, 77, 79, 76, 67, 53, + 37, 21, 8, 2, -5, -10, -14, -14, -12, -12, -11, -10, -5, 4, 7, 4, + 1, 2, 6, 9, 9, 7, 5, 4, 0, -7, -14, -23, -32, -37, -43, -48, + -50, -51, -47, -42, -34, -32, -32, -34, -32, -26, -21, -18, -17, -14, -11, -4, + 5, 13, 24, 40, 55, 67, 72, 74, 76, 75, 67, 51, 37, 23, 11, 4, + -4, -11, -15, -17, -17, -16, -14, -13, -8, -2, 1, 1, 1, 3, 5, 9, + 7, 5, 4, 4, 3, -5, -14, -24, -32, -38, -41, -47, -52, -53, -49, -41, + -35, -34, -35, -33, -29, -24, -19, -13, -10, -9, -7, -2, 8, 17, 29, 43, + 56, 67, 74, 75, 75, 72, 64, 53, 38, 23, 13, 4, -5, -12, -16, -20, + -21, -18, -16, -14, -11, -8, -5, -3, 0, 2, 6, 6, 6, 5, 5, 6, + 3, -6, -19, -31, -37, -41, -45, -50, -52, -53, -48, -39, -32, -30, -26, -25, + -22, -16, -10, -7, -11, -10, -8, -2, 6, 17, 31, 45, 58, 68, 78, 80, + 76, 70, 65, 55, 37, 18, 5, -4, -10, -19, -25, -26, -24, -18, -13, -11, + -9, -6, -2, 4, 6, 5, 4, 3, 4, 2, 1, -3, -4, -11, -20, -29, + -38, -43, -45, -48, -51, -48, -44, -39, -35, -34, -31, -30, -25, -15, -8, -8, + -10, -8, 1, 11, 22, 33, 42, 54, 66, 76, 80, 75, 70, 66, 59, 42, + 23, 6, -4, -9, -17, -22, -27, -25, -19, -9, -7, -8, -5, 0, 4, 5, + 2, -2, -5, -5, -4, -6, -7, -6, -10, -16, -21, -29, -34, -37, -38, -41, + -44, -42, -36, -32, -33, -37, -39, -35, -27, -17, -12, -13, -12, -6, 6, 22, + 36, 44, 54, 66, 77, 82, 80, 75, 68, 59, 47, 29, 10, -3, -13, -18, + -23, -26, -27, -24, -16, -9, -5, -4, -2, 3, 6, 4, -2, -6, -8, -7, + -8, -8, -9, -10, -13, -16, -22, -29, -31, -30, -34, -36, -36, -32, -28, -30, + -36, -39, -38, -33, -28, -24, -24, -22, -15, -2, 13, 26, 38, 53, 67, 78, + 84, 88, 85, 81, 71, 59, 39, 13, -5, -14, -19, -26, -32, -34, -30, -22, + -13, -5, 0, 6, 7, 10, 8, 2, -4, -10, -12, -15, -18, -20, -20, -20, + -22, -24, -26, -26, -23, -23, -23, -24, -21, -17, -18, -25, -31, -35, -37, -37, + -36, -33, -29, -22, -10, 5, 19, 31, 45, 62, 75, 84, 86, 88, 87, 80, + 66, 45, 22, 4, -9, -18, -26, -34, -37, -33, -24, -15, -9, -3, 6, 13, + 15, 11, 2, -5, -10, -13, -20, -25, -27, -26, -25, -26, -29, -29, -23, -18, + -16, -19, -18, -15, -9, -6, -12, -21, -32, -36, -36, -40, -39, -36, -30, -21, + -10, 6, 20, 36, 55, 69, 79, 85, 90, 92, 88, 75, 56, 33, 12, -3, + -15, -24, -33, -37, -35, -28, -20, -12, -4, 6, 14, 18, 16, 9, 0, -8, + -15, -19, -27, -33, -35, -34, -34, -36, -36, -29, -19, -10, -10, -10, -8, -4, + -2, -2, -8, -18, -28, -36, -43, -48, -46, -36, -25, -14, -4, 10, 27, 46, + 65, 78, 86, 89, 87, 85, 78, 64, 42, 19, 0, -12, -20, -29, -34, -36, + -30, -22, -12, -6, 1, 8, 16, 18, 13, 2, -7, -12, -17, -24, -33, -38, + -39, -36, -36, -36, -34, -26, -18, -11, -7, -6, -5, -5, 1, 1, -5, -14, + -24, -33, -41, -42, -37, -28, -19, -10, 3, 16, 30, 47, 64, 76, 83, 85, + 83, 78, 69, 54, 37, 17, -2, -14, -21, -28, -32, -32, -27, -18, -11, -6, + 2, 12, 18, 16, 5, -5, -11, -14, -19, -30, -40, -47, -45, -38, -36, -34, + -33, -26, -15, -6, -2, 1, 1, 3, 5, 4, -3, -13, -26, -35, -41, -39, + -33, -23, -13, -5, 7, 21, 36, 53, 68, 79, 82, 78, 72, 66, 59, 47, + 30, 10, -6, -16, -21, -22, -25, -27, -25, -18, -10, -4, 4, 10, 11, 6, + -4, -11, -13, -18, -25, -34, -43, -45, -41, -36, -34, -32, -27, -19, -10, -5, + 0, 2, 5, 5, 5, 1, -7, -16, -25, -33, -38, -35, -25, -13, -6, 0, + 11, 27, 46, 60, 69, 70, 68, 69, 68, 62, 52, 39, 22, 8, -2, -11, + -18, -21, -22, -23, -24, -17, -10, -5, 1, 5, 5, 2, -3, -5, -9, -17, + -28, -41, -46, -48, -43, -42, -42, -39, -30, -19, -9, -3, 6, 11, 15, 16, + 12, 5, -2, -12, -23, -33, -37, -34, -25, -18, -8, 1, 15, 32, 48, 62, + 69, 68, 67, 63, 62, 58, 50, 34, 15, -2, -8, -10, -11, -16, -24, -24, + -19, -12, -6, -2, 2, 3, 1, 0, -6, -10, -17, -26, -37, -46, -48, -45, + -44, -42, -38, -32, -22, -12, -6, 4, 10, 14, 16, 15, 11, 5, -2, -11, + -23, -31, -29, -22, -18, -16, -11, 3, 17, 34, 50, 56, 59, 61, 63, 62, + 59, 53, 44, 32, 16, 3, -8, -9, -13, -20, -26, -27, -21, -16, -11, -9, + -6, 1, 7, 7, 0, -10, -15, -20, -30, -39, -45, -48, -48, -46, -41, -36, + -29, -20, -11, 3, 11, 14, 19, 21, 19, 15, 6, -3, -13, -18, -18, -17, + -20, -19, -12, 2, 15, 26, 36, 43, 51, 59, 61, 61, 57, 54, 49, 37, + 21, 9, 1, -8, -17, -25, -29, -28, -27, -23, -19, -13, -5, 2, 8, 5, + -4, -11, -13, -17, -27, -40, -49, -53, -53, -50, -44, -37, -28, -19, -7, 8, + 18, 22, 26, 26, 23, 17, 10, 0, -8, -15, -20, -25, -23, -19, -11, 0, + 13, 25, 34, 44, 54, 60, 62, 60, 58, 56, 52, 38, 21, 6, -6, -16, + -26, -32, -33, -30, -26, -24, -17, -8, 3, 13, 16, 10, 1, -7, -12, -18, + -34, -50, -61, -63, -58, -54, -50, -45, -33, -13, 6, 21, 27, 34, 37, 36, + 30, 20, 11, -2, -13, -24, -32, -37, -34, -24, -10, 2, 12, 25, 41, 55, + 61, 64, 65, 67, 64, 59, 48, 32, 16, 0, -12, -20, -27, -33, -33, -31, + -28, -23, -12, 0, 10, 13, 9, 2, -2, -7, -13, -25, -41, -56, -65, -66, + -62, -56, -53, -42, -25, -5, 13, 24, 34, 39, 42, 39, 32, 22, 11, -2, + -15, -27, -36, -37, -31, -22, -13, 0, 12, 27, 43, 55, 61, 64, 65, 63, + 60, 53, 42, 28, 10, -6, -20, -27, -28, -28, -25, -23, -20, -13, -2, 11, + 16, 14, 8, 2, -6, -14, -25, -38, -53, -67, -73, -73, -67, -58, -46, -32, + -14, 6, 24, 36, 43, 45, 44, 39, 30, 18, 5, -11, -25, -35, -39, -37, + -28, -17, -7, 4, 16, 32, 48, 58, 64, 66, 63, 61, 56, 46, 31, 18, + 3, -13, -21, -25, -23, -19, -15, -11, -7, -2, 6, 13, 14, 8, -3, -12, + -21, -32, -40, -55, -70, -78, -75, -67, -56, -47, -29, -12, 10, 29, 40, 47, + 49, 48, 43, 31, 15, 0, -16, -29, -39, -45, -41, -32, -18, -6, 3, 13, + 27, 43, 57, 64, 65, 61, 58, 52, 43, 32, 18, 6, -9, -18, -20, -17, + -12, -4, 1, 3, 7, 12, 17, 16, 9, -3, -15, -27, -39, -48, -60, -72, + -82, -82, -73, -58, -45, -33, -14, 7, 28, 42, 49, 51, 51, 48, 38, 22, + 2, -16, -30, -37, -42, -45, -40, -26, -11, 3, 11, 20, 34, 52, 65, 69, + 64, 54, 46, 38, 28, 16, 4, -11, -18, -16, -10, -4, 3, 13, 21, 23, + 22, 20, 18, 11, -2, -16, -34, -47, -59, -70, -76, -83, -83, -76, -64, -48, + -31, -12, 10, 30, 42, 50, 53, 51, 46, 37, 25, 8, -13, -30, -41, -45, + -43, -35, -23, -15, -5, 8, 17, 28, 40, 56, 64, 63, 55, 45, 34, 24, + 14, 7, -4, -12, -13, -9, -2, 11, 23, 31, 33, 33, 31, 26, 17, 4, + -14, -31, -48, -62, -75, -86, -90, -87, -79, -68, -54, -39, -18, 4, 23, 39, + 47, 52, 52, 47, 39, 29, 15, -5, -23, -35, -41, -40, -34, -26, -16, -8, + 2, 12, 22, 30, 43, 52, 58, 54, 45, 36, 25, 16, 7, -2, -7, -8, + -3, 4, 13, 24, 32, 39, 42, 39, 30, 19, 6, -10, -25, -44, -62, -79, + -88, -90, -85, -78, -70, -59, -45, -24, 0, 20, 35, 43, 48, 48, 46, 42, + 33, 20, 2, -19, -32, -38, -41, -37, -29, -19, -8, 1, 11, 19, 26, 35, + 43, 48, 48, 41, 35, 26, 16, 7, 0, 0, 3, 6, 10, 16, 24, 32, + 40, 44, 43, 33, 21, 8, -5, -19, -37, -54, -72, -84, -87, -81, -75, -68, + -61, -50, -33, -12, 8, 22, 29, 34, 40, 42, 41, 35, 24, 13, -2, -16, + -27, -33, -33, -27, -22, -17, -13, -4, 9, 18, 25, 31, 36, 42, 44, 40, + 32, 21, 12, 9, 7, 8, 9, 13, 17, 23, 29, 35, 40, 40, 35, 26, + 13, 0, -11, -24, -41, -60, -74, -80, -79, -73, -68, -63, -56, -43, -27, -10, + 6, 18, 24, 29, 34, 38, 37, 30, 20, 9, -3, -14, -24, -27, -27, -25, + -23, -18, -9, 2, 10, 19, 25, 30, 37, 40, 41, 33, 22, 16, 10, 6, + 6, 10, 16, 21, 28, 31, 35, 38, 44, 45, 34, 19, 5, -5, -17, -33, + -52, -68, -76, -78, -75, -71, -67, -62, -51, -37, -20, -7, 4, 13, 21, 29, + 34, 36, 33, 26, 17, 10, 0, -8, -13, -19, -21, -21, -17, -11, -6, 4, + 10, 13, 19, 25, 30, 31, 28, 20, 14, 10, 7, 7, 11, 20, 26, 32, + 36, 39, 41, 44, 46, 41, 30, 13, 0, -13, -27, -44, -62, -72, -74, -74, + -74, -71, -66, -57, -47, -32, -19, -9, 2, 14, 24, 28, 32, 34, 33, 25, + 17, 9, 2, -5, -10, -17, -22, -18, -13, -7, 0, 4, 10, 17, 23, 26, + 25, 21, 15, 9, 9, 7, 4, 7, 16, 27, 34, 39, 43, 48, 49, 52, + 49, 39, 24, 9, -3, -17, -32, -52, -67, -75, -75, -71, -70, -70, -66, -56, + -43, -31, -21, -12, -2, 11, 21, 27, 30, 33, 31, 29, 22, 15, 8, 0, + -6, -13, -14, -14, -11, -5, 0, 4, 8, 13, 16, 18, 15, 12, 10, 7, + 7, 6, 7, 14, 24, 36, 44, 46, 46, 49, 52, 53, 47, 35, 21, 9, + -6, -23, -43, -59, -68, -71, -74, -74, -76, -73, -64, -52, -39, -31, -25, -15, + 0, 12, 20, 24, 29, 32, 30, 26, 21, 16, 10, 4, -2, -7, -7, -5, + -3, 0, 3, 5, 6, 9, 8, 8, 6, 3, 2, 4, 5, 7, 14, 22, + 34, 43, 49, 57, 57, 55, 52, 48, 43, 31, 17, 2, -13, -33, -49, -59, + -63, -66, -72, -75, -76, -70, -61, -52, -44, -37, -30, -18, -4, 11, 20, 25, + 28, 32, 32, 30, 26, 19, 13, 5, 0, -4, -5, -3, 1, 2, 1, -3, + -2, 2, 6, 4, 2, -3, -2, 3, 10, 13, 18, 27, 40, 49, 56, 59, + 60, 56, 52, 47, 41, 30, 17, 1, -19, -39, -55, -64, -67, -70, -76, -81, + -78, -69, -56, -46, -40, -33, -24, -12, 3, 15, 22, 25, 26, 29, 27, 23, + 19, 14, 9, 4, 0, -2, 1, 5, 9, 7, 2, -3, -3, 3, 3, -2, + -10, -13, -10, -2, 7, 14, 22, 31, 45, 59, 65, 68, 65, 62, 58, 50, + 41, 28, 12, -9, -31, -49, -59, -65, -70, -76, -84, -84, -77, -63, -50, -45, + -40, -32, -21, -7, 7, 16, 24, 28, 29, 28, 23, 18, 15, 11, 6, 0, + -4, -3, 4, 11, 14, 11, 6, 5, 7, 7, 2, -7, -12, -16, -13, -6, + 1, 8, 17, 32, 50, 63, 68, 68, 69, 70, 65, 56, 43, 27, 7, -17, + -38, -52, -62, -71, -78, -86, -88, -84, -73, -59, -50, -43, -34, -25, -11, 2, + 11, 19, 23, 26, 26, 21, 17, 12, 9, 7, 5, 2, 2, 4, 11, 16, + 14, 10, 9, 10, 9, 1, -8, -16, -19, -16, -11, -6, 0, 8, 24, 43, + 57, 66, 70, 72, 72, 67, 63, 52, 37, 18, -5, -23, -41, -54, -62, -70, + -78, -81, -82, -76, -67, -56, -45, -36, -31, -22, -12, 0, 10, 16, 20, 21, + 17, 13, 7, 3, 3, 6, 6, 6, 9, 14, 20, 21, 20, 17, 17, 15, + 9, -3, -15, -23, -27, -20, -14, -9, -4, 9, 31, 49, 64, 70, 75, 78, + 76, 70, 60, 45, 31, 12, -11, -31, -46, -58, -66, -70, -73, -77, -74, -67, + -59, -52, -44, -36, -29, -22, -14, -6, 1, 11, 14, 14, 11, 6, 6, 7, + 10, 11, 12, 15, 18, 24, 23, 21, 19, 20, 18, 12, 0, -13, -20, -27, + -27, -22, -16, -11, 1, 19, 36, 52, 64, 73, 79, 81, 77, 69, 56, 43, + 26, 5, -16, -37, -54, -62, -66, -69, -72, -71, -65, -62, -56, -47, -39, -33, + -26, -19, -14, -12, -3, 9, 9, 3, -6, -4, 5, 11, 12, 11, 12, 20, + 29, 31, 29, 25, 25, 27, 24, 11, -6, -17, -25, -31, -32, -30, -26, -16, + 0, 17, 35, 51, 66, 78, 87, 88, 84, 73, 57, 40, 23, 3, -20, -42, + -57, -65, -69, -71, -70, -68, -63, -58, -52, -45, -38, -30, -26, -24, -23, -16, + -8, -2, -5, -9, -6, 1, 9, 12, 13, 17, 24, 32, 37, 37, 34, 32, + 33, 31, 19, 2, -15, -25, -31, -36, -38, -35, -27, -13, 4, 23, 40, 59, + 76, 91, 96, 91, 80, 69, 55, 35, 13, -12, -35, -52, -61, -66, -71, -70, + -63, -54, -48, -44, -42, -36, -31, -30, -34, -36, -33, -26, -20, -20, -21, -18, + -9, 5, 13, 18, 21, 29, 40, 47, 50, 49, 44, 40, 34, 23, 6, -14, + -27, -39, -45, -48, -45, -35, -23, -7, 11, 30, 51, 73, 89, 97, 96, 89, + 80, 63, 44, 25, 4, -18, -39, -53, -59, -63, -61, -58, -55, -52, -49, -45, + -39, -35, -37, -41, -46, -43, -38, -33, -29, -25, -18, -11, 3, 13, 20, 25, + 30, 38, 46, 51, 50, 47, 43, 37, 26, 9, -7, -19, -32, -45, -52, -51, + -40, -28, -12, 4, 19, 38, 61, 83, 94, 95, 89, 82, 67, 50, 30, 12, + -8, -26, -40, -52, -57, -56, -52, -48, -46, -44, -40, -34, -32, -32, -37, -44, + -47, -45, -41, -39, -35, -28, -17, -6, 7, 15, 23, 32, 40, 47, 52, 52, + 51, 46, 39, 32, 17, 1, -14, -26, -37, -46, -50, -45, -35, -25, -11, 5, + 24, 44, 62, 79, 88, 86, 79, 70, 59, 45, 25, 7, -13, -25, -36, -46, + -50, -51, -50, -46, -43, -41, -37, -34, -33, -36, -40, -43, -46, -46, -41, -36, + -31, -22, -10, 4, 13, 21, 30, 40, 47, 50, 53, 52, 47, 39, 30, 18, + 3, -12, -22, -33, -42, -47, -45, -36, -25, -14, -2, 14, 34, 52, 67, 76, + 77, 72, 65, 55, 43, 27, 12, -7, -21, -29, -36, -41, -44, -43, -39, -36, + -32, -27, -26, -26, -29, -33, -36, -43, -49, -48, -44, -38, -32, -22, -11, 4, + 15, 25, 34, 44, 50, 53, 54, 52, 44, 35, 23, 9, -4, -15, -27, -37, + -43, -45, -42, -34, -21, -9, 5, 19, 34, 50, 63, 70, 69, 63, 54, 46, + 35, 20, 4, -11, -23, -29, -33, -37, -41, -40, -33, -25, -20, -19, -21, -22, + -23, -26, -34, -42, -47, -46, -43, -36, -30, -22, -11, 5, 17, 28, 37, 45, + 52, 55, 53, 49, 41, 30, 19, 4, -12, -23, -33, -41, -45, -45, -40, -31, + -18, -3, 11, 23, 38, 51, 63, 64, 58, 51, 45, 36, 25, 10, -4, -15, + -24, -28, -32, -36, -35, -29, -19, -13, -13, -14, -13, -13, -13, -21, -33, -43, + -45, -45, -41, -38, -34, -25, -11, 4, 17, 29, 39, 49, 57, 60, 55, 48, + 39, 29, 16, 1, -14, -27, -35, -42, -47, -48, -42, -29, -15, -3, 10, 20, + 34, 48, 56, 57, 51, 45, 38, 30, 20, 7, -7, -17, -22, -26, -32, -36, + -31, -21, -9, -6, -8, -8, -4, 1, -4, -13, -26, -35, -39, -40, -42, -44, + -40, -29, -13, 3, 16, 29, 43, 58, 67, 67, 59, 49, 39, 27, 11, -9, + -28, -39, -47, -50, -53, -52, -44, -29, -12, 5, 13, 25, 38, 51, 57, 52, + 45, 38, 30, 21, 9, -4, -14, -21, -26, -29, -33, -28, -18, -7, 2, 2, + 2, 4, 8, 10, 5, -10, -25, -36, -42, -45, -49, -49, -45, -33, -14, 5, + 22, 35, 54, 69, 78, 76, 67, 53, 41, 27, 6, -17, -36, -50, -55, -60, + -63, -62, -51, -34, -16, -2, 9, 20, 34, 45, 50, 48, 42, 35, 29, 18, + 7, 0, 0, 0, 0, 0, 0, 7, 0, -1, -7, -18, -16, 3, 6, -18, + -29, -21, 6, 6, -12, -10, -10, -2, 4, 15, 21, 14, 4, 9, 29, 27, + 15, 9, 13, 20, 0, -21, -11, 3, -11, -37, -36, -7, 11, -4, -26, -23, + -4, 15, -4, -15, -11, -10, -1, 9, 23, 15, 8, 6, 24, 35, 19, 14, + 6, 17, 10, -15, -26, -7, -1, -23, -40, -24, 4, 10, -16, -25, -13, 11, + 10, -14, -15, -12, -6, 1, 19, 22, 6, 7, 15, 40, 31, 22, 7, 7, + 15, 5, -22, -21, -5, -9, -33, -32, -15, 5, -4, -19, -20, 1, 17, -4, + -15, -11, -12, -4, 9, 27, 13, 7, 11, 32, 44, 30, 14, 2, 7, 9, + -8, -25, -18, -9, -19, -30, -21, -4, 2, -10, -21, -13, 15, 8, -11, -13, + -16, -12, 0, 20, 24, 9, 9, 19, 44, 47, 25, 6, 2, 11, -1, -21, + -27, -19, -17, -20, -23, -17, -5, -5, -14, -20, 0, 15, -4, -7, -17, -17, + -8, 7, 25, 18, 7, 11, 31, 54, 41, 14, -1, 10, 3, -14, -27, -29, + -21, -16, -16, -18, -17, -11, -10, -16, -16, 10, 6, -3, -9, -19, -16, -2, + 18, 27, 16, 8, 19, 45, 54, 29, 5, 6, 4, -9, -18, -29, -30, -18, + -10, -9, -14, -20, -12, -13, -17, -5, 12, 7, 2, -16, -22, -13, 8, 25, + 23, 12, 11, 32, 53, 48, 17, 9, 9, -7, -16, -24, -37, -28, -12, -4, + -2, -18, -21, -18, -23, -17, 7, 11, 10, -4, -16, -22, -7, 21, 28, 18, + 9, 20, 43, 55, 37, 11, 11, 1, -14, -17, -31, -34, -21, -10, 4, -2, + -20, -23, -26, -29, -3, 6, 13, 8, -5, -23, -27, 7, 28, 27, 15, 12, + 32, 48, 50, 24, 9, 8, -12, -19, -26, -37, -35, -19, 3, 6, -12, -21, + -31, -38, -17, 6, 4, 14, 6, -8, -35, -15, 19, 26, 21, 7, 23, 43, + 52, 42, 14, 9, -2, -16, -21, -25, -33, -33, -4, 13, 3, -13, -30, -47, + -37, 1, 6, 7, 12, 6, -15, -31, -1, 22, 30, 14, 9, 37, 48, 50, + 26, 8, 6, -11, -22, -22, -25, -45, -22, 13, 15, 1, -22, -43, -56, -21, + 7, 6, 10, 15, -7, -25, -21, 7, 28, 21, 2, 25, 47, 53, 39, 11, + 10, 1, -20, -22, -18, -37, -42, 2, 15, 15, -8, -32, -57, -48, -9, 9, + 5, 14, 8, -14, -20, -13, 17, 33, 8, 9, 37, 52, 55, 25, 7, 8, + -11, -23, -15, -23, -47, -20, 12, 21, 10, -23, -50, -57, -31, 2, 10, 9, + 11, -8, -10, -18, -3, 30, 22, 1, 22, 45, 57, 45, 11, 11, 0, -23, + -22, -16, -36, -36, -6, 15, 18, -3, -43, -56, -49, -21, 5, 11, 12, -2, + -8, -9, -15, 12, 31, 9, 10, 34, 48, 60, 29, 16, 10, -17, -24, -21, + -27, -31, -17, 5, 14, 12, -22, -50, -48, -41, -9, 7, 13, -1, -8, -2, + -11, -5, 26, 19, 6, 21, 37, 55, 49, 25, 22, -5, -20, -24, -26, -29, + -23, -9, 8, 13, -1, -41, -48, -47, -30, -3, 12, 7, -12, -2, 1, -8, + 10, 20, 11, 16, 26, 40, 54, 42, 36, 7, -13, -18, -26, -29, -26, -14, + -2, 7, 8, -18, -45, -48, -45, -19, 6, 11, -10, -8, 5, -7, 2, 12, + 17, 15, 16, 23, 45, 55, 48, 27, -7, -12, -18, -30, -31, -17, -5, -3, + 4, 5, -24, -40, -50, -38, -8, 8, 1, -13, 1, -1, 3, 8, 15, 18, + 15, 15, 28, 52, 59, 47, 9, -9, -10, -25, -40, -29, -3, -5, -13, 1, + 3, -26, -47, -53, -23, -2, 5, -11, -6, 4, 6, 10, 10, 19, 11, 13, + 15, 42, 61, 61, 32, 3, -5, -12, -35, -43, -14, 1, -16, -13, 9, -1, + -33, -57, -46, -19, -3, -1, -16, -2, 5, 15, 6, 17, 9, 5, 9, 26, + 54, 65, 52, 21, 3, -6, -21, -48, -33, -4, -7, -22, -2, 18, -4, -47, + -58, -33, -11, 2, -13, -15, 3, 16, 15, 9, 15, -1, 5, 14, 48, 66, + 65, 37, 23, 2, -11, -42, -48, -20, -4, -23, -18, 18, 19, -17, -61, -52, + -27, -2, -5, -24, -7, 9, 20, 14, 18, 2, -3, 7, 34, 63, 68, 50, + 37, 19, -9, -25, -49, -38, -14, -14, -28, 6, 25, 9, -40, -62, -45, -17, + 3, -21, -16, -3, 12, 18, 18, 10, -6, 0, 16, 56, 69, 63, 43, 38, + 2, -20, -42, -44, -33, -14, -25, -10, 22, 18, -11, -55, -57, -37, -3, -10, + -26, -10, 2, 17, 21, 20, -3, -2, 5, 39, 67, 73, 56, 47, 22, -17, + -35, -43, -36, -28, -18, -20, 9, 22, 8, -33, -56, -53, -26, -2, -23, -24, + -11, 4, 23, 30, 4, -3, 0, 27, 60, 71, 69, 58, 43, -6, -35, -43, + -35, -36, -27, -18, -2, 19, 17, -9, -41, -51, -45, -10, -12, -31, -21, -9, + 8, 33, 17, 0, 2, 8, 50, 69, 75, 70, 64, 16, -31, -47, -35, -32, + -34, -25, -14, 10, 16, 5, -26, -42, -50, -32, -8, -22, -31, -22, -8, 22, + 32, 7, 6, 4, 28, 63, 69, 71, 78, 43, -20, -51, -41, -23, -34, -30, + -22, 2, 13, 9, -10, -31, -45, -44, -21, -19, -27, -36, -26, 2, 29, 24, + 12, 11, 13, 45, 69, 68, 81, 70, 6, -47, -52, -28, -23, -27, -26, -14, + 11, 10, -2, -18, -33, -43, -34, -25, -22, -36, -44, -14, 14, 29, 27, 22, + 18, 29, 60, 65, 71, 86, 41, -32, -57, -41, -23, -22, -22, -24, -4, 10, + 0, -11, -21, -31, -37, -37, -29, -29, -53, -33, -3, 16, 33, 31, 27, 23, + 46, 64, 65, 85, 71, -4, -48, -47, -31, -20, -15, -15, -19, 1, 0, -5, + -14, -21, -26, -40, -39, -28, -51, -50, -18, 4, 26, 38, 36, 30, 32, 61, + 64, 70, 80, 31, -35, -43, -40, -25, -19, -6, -17, -11, 0, -6, -11, -17, + -15, -31, -47, -39, -45, -62, -34, -8, 12, 36, 38, 41, 37, 51, 65, 60, + 71, 56, -7, -36, -38, -35, -27, -11, -5, -17, -8, -8, -9, -17, -13, -20, + -37, -47, -50, -62, -49, -16, 1, 25, 34, 43, 53, 49, 62, 58, 62, 65, + 22, -23, -31, -34, -35, -19, -3, -8, -18, -7, -4, -14, -17, -9, -27, -40, + -56, -68, -64, -27, -4, 9, 28, 37, 54, 60, 61, 59, 54, 63, 43, -1, + -25, -23, -37, -28, -8, 4, -10, -15, -3, -7, -26, -15, -11, -29, -51, -71, + -71, -49, -8, 5, 14, 30, 48, 66, 68, 63, 51, 56, 51, 18, -18, -20, + -25, -39, -23, -5, 3, -13, -6, -5, -21, -28, -10, -18, -43, -67, -78, -64, + -25, 1, 8, 15, 38, 60, 75, 74, 58, 54, 57, 28, -7, -18, -8, -31, + -34, -15, 4, -2, -4, 0, -15, -32, -21, -8, -28, -57, -77, -75, -44, -12, + 6, 8, 20, 49, 68, 77, 71, 53, 61, 41, 3, -18, -4, -14, -36, -28, + -7, 1, 7, 6, -8, -34, -35, -16, -15, -41, -66, -75, -59, -31, -4, 10, + 11, 31, 56, 72, 85, 63, 58, 55, 14, -17, -10, -1, -24, -30, -22, -6, + 11, 16, 9, -27, -43, -27, -15, -26, -53, -63, -66, -46, -21, 3, 13, 15, + 40, 63, 83, 78, 60, 67, 38, -9, -20, 4, -7, -23, -25, -22, 6, 24, + 20, -8, -48, -43, -24, -16, -39, -55, -57, -57, -36, -10, 9, 11, 22, 50, + 73, 88, 71, 65, 59, 14, -24, -9, -3, -15, -18, -31, -14, 25, 28, 10, + -36, -56, -41, -21, -29, -48, -47, -51, -50, -26, -2, 11, 6, 30, 57, 82, + 83, 69, 65, 35, -12, -16, -3, -10, -12, -21, -26, 11, 33, 26, -7, -56, + -54, -32, -26, -41, -39, -37, -52, -41, -16, 5, 7, 11, 37, 72, 91, 78, + 66, 55, 11, -19, -14, -15, -9, -7, -19, -8, 22, 30, 13, -32, -62, -44, + -31, -34, -40, -29, -40, -46, -29, -8, 2, 1, 18, 49, 84, 86, 72, 67, + 39, -6, -21, -25, -16, 2, -6, -12, 6, 23, 18, -7, -51, -56, -39, -33, + -41, -30, -24, -41, -36, -17, -8, -5, 7, 32, 66, 84, 78, 75, 58, 20, + -15, -29, -33, 2, 4, -1, 1, 11, 17, 4, -27, -56, -46, -36, -37, -39, + -22, -24, -38, -23, -16, -16, -7, 18, 46, 72, 82, 81, 72, 44, -1, -25, + -41, -18, 14, 8, 10, 0, 5, 2, -11, -40, -50, -42, -38, -37, -33, -11, + -27, -26, -20, -22, -13, 0, 31, 52, 73, 82, 80, 61, 26, -16, -37, -40, + 0, 18, 17, 12, -5, -8, -10, -21, -41, -43, -44, -36, -35, -20, -12, -23, + -14, -32, -21, -12, 15, 38, 58, 76, 82, 72, 46, 4, -26, -41, -23, 14, + 25, 18, 2, -23, -18, -14, -29, -35, -45, -42, -35, -29, -15, -19, -3, -23, + -32, -19, -1, 27, 40, 67, 81, 76, 61, 26, -11, -33, -36, -6, 28, 28, + 13, -15, -38, -19, -20, -26, -36, -46, -35, -32, -20, -21, -4, -4, -28, -25, + -16, 13, 31, 49, 74, 79, 69, 48, 8, -16, -33, -21, 7, 33, 24, 5, + -32, -38, -22, -21, -22, -41, -43, -32, -25, -23, -16, 6, -9, -29, -28, -5, + 20, 39, 58, 75, 71, 60, 22, 0, -18, -27, -10, 16, 30, 15, -14, -49, + -34, -19, -16, -27, -43, -31, -25, -27, -24, -1, 7, -15, -32, -22, 3, 28, + 50, 61, 67, 59, 38, 13, 5, -17, -16, -3, 21, 23, 3, -34, -49, -28, + -17, -19, -34, -34, -18, -26, -32, -16, 14, 6, -23, -34, -11, 14, 44, 54, + 56, 60, 44, 25, 18, 2, -18, -9, 3, 21, 9, -14, -45, -39, -24, -22, + -28, -32, -18, -17, -36, -30, 5, 21, -5, -31, -27, 1, 30, 56, 46, 50, + 47, 32, 29, 20, -4, -9, -9, 4, 10, -2, -28, -38, -31, -33, -26, -26, + -19, -9, -24, -38, -11, 24, 10, -17, -36, -14, 14, 48, 49, 37, 43, 39, + 33, 32, 11, 1, -5, -11, -6, -3, -16, -29, -28, -40, -38, -27, -20, -6, + -11, -31, -29, 15, 22, 0, -25, -25, 2, 31, 51, 38, 35, 41, 41, 34, + 27, 8, 6, -7, -20, -14, -7, -20, -19, -34, -52, -35, -23, -11, -5, -18, + -33, -5, 26, 5, -11, -27, -11, 17, 43, 43, 30, 29, 46, 45, 38, 17, + 6, 2, -22, -27, -16, -16, -18, -18, -53, -48, -23, -19, -3, -10, -21, -19, + 18, 12, -6, -20, -21, 6, 29, 42, 31, 23, 37, 54, 48, 31, 13, 13, + -13, -31, -25, -16, -16, -11, -38, -62, -33, -28, -7, -3, -12, -17, 6, 16, + 2, -11, -17, -5, 15, 35, 34, 25, 23, 44, 55, 41, 22, 14, 2, -29, + -32, -23, -11, -13, -18, -60, -50, -32, -16, -6, -11, -4, 3, 11, 3, -1, + -14, -8, 5, 20, 39, 31, 24, 26, 54, 57, 37, 16, 8, -19, -32, -27, + -17, -17, -17, -36, -58, -40, -32, -11, -11, -2, 6, 10, 2, 0, -4, -12, + 1, 8, 33, 42, 26, 17, 35, 63, 53, 26, 6, -9, -27, -30, -25, -17, + -23, -24, -47, -51, -38, -17, -11, -6, 12, 17, 8, -8, -1, -10, -7, 4, + 18, 40, 33, 18, 22, 49, 70, 46, 12, -11, -16, -23, -27, -19, -28, -26, + -36, -50, -48, -31, -13, -13, 10, 20, 21, 0, -6, -1, -7, 3, 15, 32, + 40, 24, 17, 31, 58, 67, 28, -2, -21, -14, -31, -18, -24, -33, -33, -49, + -49, -41, -18, -20, -2, 20, 23, 19, -12, -7, -2, -3, 10, 22, 33, 37, + 21, 23, 39, 72, 51, 10, -17, -18, -20, -29, -17, -33, -36, -49, -48, -47, + -24, -16, -15, 11, 24, 30, 6, -12, -2, -2, -1, 18, 29, 35, 27, 25, + 25, 56, 63, 23, -5, -19, -14, -23, -21, -21, -38, -52, -54, -40, -32, -15, + -23, -7, 18, 31, 22, -2, -7, 3, 0, 12, 21, 34, 31, 28, 22, 35, + 66, 40, 2, -19, -19, -15, -21, -16, -30, -60, -62, -42, -33, -18, -18, -22, + 4, 29, 29, 14, -2, -4, 5, 6, 16, 28, 36, 24, 29, 26, 52, 49, + 14, -13, -24, -19, -14, -15, -17, -53, -75, -54, -32, -18, -11, -26, -18, 18, + 28, 25, 13, -6, 4, 13, 9, 17, 37, 24, 28, 33, 37, 49, 26, 1, + -19, -26, -16, -11, -7, -33, -77, -71, -45, -15, -8, -18, -30, 1, 25, 21, + 26, 3, 5, 17, 14, 11, 33, 27, 17, 34, 38, 42, 33, 6, -11, -28, + -22, -12, -3, -16, -60, -81, -62, -25, -2, -14, -27, -17, 20, 18, 24, 18, + 6, 16, 21, 12, 24, 28, 12, 26, 44, 42, 35, 13, -5, -21, -31, -18, + -2, -2, -42, -77, -76, -47, -10, -6, -22, -24, 4, 16, 18, 25, 18, 18, + 24, 20, 20, 32, 14, 11, 40, 49, 41, 21, -6, -13, -27, -28, -5, 5, + -18, -59, -79, -63, -30, -6, -11, -28, -11, 8, 10, 23, 27, 17, 24, 25, + 25, 28, 19, 8, 25, 47, 46, 27, -5, -15, -18, -33, -20, -5, -3, -35, + -70, -66, -51, -22, -7, -21, -19, -3, 6, 17, 29, 26, 23, 28, 25, 32, + 23, 14, 11, 39, 50, 38, 3, -19, -10, -21, -29, -12, -3, -12, -55, -65, + -56, -42, -14, -10, -23, -11, -3, 10, 23, 32, 26, 28, 28, 35, 29, 22, + 13, 18, 41, 43, 18, -16, -18, -14, -29, -21, -11, -8, -32, -61, -52, -52, + -30, -11, -18, -16, -10, 2, 22, 35, 30, 25, 32, 34, 40, 27, 19, 11, + 23, 39, 32, -1, -22, -14, -22, -23, -14, -11, -17, -45, -52, -51, -51, -22, + -17, -19, -17, -10, 11, 35, 39, 29, 26, 34, 43, 43, 27, 16, 12, 25, + 31, 18, -13, -20, -19, -22, -12, -14, -15, -28, -44, -47, -53, -33, -15, -22, + -24, -20, 5, 27, 38, 31, 21, 27, 46, 51, 40, 18, 8, 13, 23, 24, + 3, -21, -22, -22, -8, -9, -22, -26, -31, -40, -51, -44, -17, -15, -26, -31, + -10, 24, 35, 37, 25, 21, 42, 57, 53, 30, 11, 7, 11, 21, 12, -11, + -23, -25, -12, 0, -18, -32, -31, -30, -45, -46, -26, -13, -25, -39, -25, 15, + 36, 29, 25, 20, 37, 58, 63, 46, 15, 3, -2, 19, 16, -2, -19, -25, + -23, 4, -4, -31, -36, -29, -32, -43, -37, -17, -16, -39, -43, -2, 34, 31, + 21, 17, 30, 62, 67, 62, 27, 9, -9, 3, 26, 8, -18, -26, -26, -5, + 9, -23, -44, -33, -26, -33, -40, -28, -12, -30, -52, -24, 23, 33, 15, 14, + 22, 54, 75, 68, 47, 14, -9, -12, 19, 23, -12, -20, -20, -13, 11, -6, + -40, -41, -19, -23, -34, -34, -14, -13, -48, -48, 4, 35, 23, 7, 13, 40, + 77, 78, 57, 31, -3, -18, 3, 27, 7, -24, -19, -16, 1, 5, -29, -49, + -28, -13, -26, -34, -26, -4, -30, -57, -24, 22, 30, 6, 7, 31, 63, 86, + 68, 42, 10, -19, -13, 15, 25, -10, -22, -14, -7, 6, -11, -45, -40, -14, + -24, -35, -31, -12, -8, -51, -44, -2, 29, 11, -1, 22, 47, 74, 78, 49, + 25, -8, -26, -4, 26, 12, -16, -19, -11, -1, -1, -28, -45, -22, -13, -29, + -29, -23, -1, -26, -55, -26, 14, 20, -3, 13, 39, 63, 80, 61, 33, 8, + -22, -25, 10, 22, -1, -14, -15, -7, -1, -14, -37, -26, -13, -25, -28, -26, + -2, -5, -48, -44, -7, 18, 3, 9, 30, 49, 71, 70, 45, 23, -13, -33, + -5, 22, 11, -7, -17, -14, -6, -8, -29, -29, -15, -19, -26, -31, -15, 6, + -25, -52, -30, 7, 7, 2, 21, 40, 60, 67, 52, 33, 7, -29, -19, 16, + 22, 4, -8, -15, -11, -6, -23, -24, -10, -11, -23, -27, -22, 1, 0, -34, + -45, -14, 2, 1, 15, 35, 52, 62, 49, 36, 21, -16, -26, 1, 20, 12, + -7, -10, -20, -10, -19, -28, -9, -8, -15, -26, -27, -11, 2, -15, -41, -34, + -10, -7, 6, 32, 48, 56, 51, 35, 26, 1, -24, -10, 15, 18, 2, -9, + -17, -18, -11, -32, -6, 2, -9, -18, -22, -17, -3, -2, -21, -34, -26, -13, + -8, 20, 47, 53, 52, 38, 24, 5, -14, -15, 9, 14, 4, -6, -14, -21, + -14, -28, -22, 12, 0, -10, -23, -24, -13, 2, -10, -23, -34, -26, -13, 4, + 39, 58, 51, 45, 28, 6, -9, -11, 3, 17, 7, -3, -10, -18, -15, -22, + -35, 2, 18, 2, -11, -23, -20, -1, 0, -15, -24, -39, -25, -6, 17, 52, + 56, 47, 35, 6, -10, -8, 0, 13, 13, -2, -9, -13, -13, -25, -43, -16, + 21, 19, -3, -21, -25, -10, 2, -5, -14, -30, -40, -13, -1, 34, 58, 51, + 44, 18, -10, -9, -2, 6, 12, 7, -7, -12, -12, -18, -40, -33, 9, 32, + 19, -9, -23, -15, 1, 3, -9, -18, -40, -28, -4, 7, 47, 59, 49, 24, + 1, -13, -5, 1, 10, 11, 5, -12, -12, -15, -35, -42, -9, 23, 33, 9, + -22, -24, -5, 1, -5, -12, -30, -40, -7, -3, 22, 56, 58, 35, 11, -12, + -9, -5, -1, 7, 13, -4, -13, -13, -25, -43, -29, 10, 34, 32, -6, -27, + -8, 3, -5, -13, -22, -40, -18, -3, -1, 37, 61, 46, 23, -5, -13, -4, + -4, -7, 12, 14, -10, -18, -22, -34, -35, -10, 22, 39, 23, -15, -14, 5, + 3, -8, -15, -36, -23, -1, -7, 14, 51, 57, 37, 8, -13, -7, -2, -14, + -6, 20, 3, -21, -26, -27, -30, -27, 1, 28, 36, 7, -10, 0, 5, -8, + -14, -30, -29, -3, -10, -5, 31, 56, 46, 19, -7, -10, 3, -11, -21, 9, + 19, -10, -30, -29, -19, -24, -20, 10, 35, 29, 8, -1, 5, -2, -13, -28, + -33, -3, -1, -13, 12, 49, 55, 31, -1, -12, 2, -3, -26, -2, 21, 2, + -28, -34, -21, -17, -29, -12, 23, 34, 19, 6, 7, 4, -4, -23, -40, -10, + 7, -12, -2, 34, 55, 36, 8, -10, 1, 3, -19, -18, 15, 15, -10, -33, + -30, -9, -19, -25, 4, 32, 30, 16, 11, 10, 3, -15, -35, -27, 9, -4, + -10, 16, 52, 42, 12, -7, -6, 4, -6, -21, -2, 17, 0, -20, -41, -13, + -9, -31, -16, 18, 34, 23, 14, 9, 10, -7, -26, -34, -3, 10, -10, 2, + 42, 51, 16, -8, -11, -2, -2, -11, -9, 9, 2, -8, -36, -31, 3, -23, + -30, -1, 27, 27, 23, 15, 18, 3, -17, -31, -19, 8, 1, -4, 24, 51, + 30, -11, -16, -6, -3, -5, -10, 3, 1, -10, -22, -41, -4, -6, -29, -18, + 12, 25, 26, 23, 20, 11, -10, -21, -27, -4, 7, 0, 13, 41, 40, 3, + -24, -11, -1, -2, -3, 5, 5, -14, -15, -35, -20, 0, -19, -24, -4, 11, + 23, 31, 24, 16, -3, -13, -23, -14, 2, 3, 18, 32, 38, 21, -20, -29, + -5, -2, 0, 5, 11, -14, -22, -25, -26, -3, -11, -26, -11, -2, 8, 32, + 34, 24, 2, -8, -16, -13, 1, 1, 10, 31, 31, 33, 1, -36, -22, 0, + 0, 8, 18, -3, -27, -22, -22, -10, -9, -24, -16, -5, -16, 16, 40, 34, + 8, -3, -13, -12, 1, 1, 3, 30, 30, 24, 18, -28, -35, -13, -2, 6, + 19, 10, -25, -28, -15, -9, -10, -19, -20, -3, -15, -8, 27, 42, 25, 1, + -14, -18, 7, 9, -1, 19, 37, 19, 23, -10, -41, -26, -9, 2, 20, 19, + -17, -35, -21, 0, -9, -18, -20, -7, -8, -24, 6, 37, 43, 14, -10, -22, + 3, 18, 4, 6, 36, 23, 16, 4, -32, -37, -19, -3, 17, 27, 0, -37, + -34, -3, 7, -17, -27, -19, -1, -20, -13, 17, 44, 35, 2, -22, -9, 19, + 20, 2, 26, 32, 15, 5, -17, -40, -29, -9, 10, 28, 17, -23, -41, -21, + 9, -2, -27, -30, -5, -7, -21, -4, 27, 47, 27, -14, -21, 11, 29, 14, + 15, 32, 20, 4, -11, -31, -38, -15, 2, 22, 22, -3, -32, -34, -6, 8, + -13, -38, -19, 0, -16, -14, 6, 37, 39, 11, -18, -4, 25, 25, 16, 24, + 27, 7, -10, -24, -38, -25, 0, 12, 23, 8, -16, -31, -23, 0, 0, -27, + -33, -2, -9, -16, -11, 17, 41, 32, 5, -15, 12, 25, 24, 21, 27, 14, + -4, -21, -31, -29, -4, 9, 19, 9, -9, -19, -25, -10, -5, -15, -38, -13, + -6, -13, -17, -1, 30, 36, 27, -2, 2, 20, 24, 25, 24, 19, 2, -16, + -32, -29, -13, 8, 18, 16, -6, -13, -21, -15, -14, -13, -26, -22, -6, -11, + -14, -14, 11, 30, 37, 17, 1, 13, 20, 23, 24, 21, 5, -10, -32, -31, + -15, 0, 17, 22, -3, -15, -17, -11, -15, -19, -23, -22, -8, -8, -13, -18, + -8, 18, 40, 38, 12, 12, 15, 21, 23, 24, 7, -9, -22, -34, -19, -6, + 11, 30, 9, -17, -20, -16, -11, -22, -30, -27, -8, -7, -10, -19, -16, -2, + 32, 52, 31, 17, 16, 13, 21, 19, 19, -9, -17, -30, -25, -7, 3, 29, + 25, -9, -21, -20, -11, -14, -29, -37, -14, 2, -5, -14, -22, -12, 13, 50, + 49, 27, 23, 15, 13, 9, 18, 7, -22, -22, -28, -11, -5, 19, 35, 13, + -20, -24, -18, -8, -22, -38, -31, 2, 3, -6, -26, -22, -3, 38, 56, 42, + 34, 21, 12, 6, 11, 17, -15, -24, -20, -15, -6, 9, 29, 29, -4, -28, + -23, -14, -13, -30, -39, -16, 9, 6, -12, -33, -16, 19, 57, 49, 41, 30, + 13, 4, -1, 6, -4, -27, -21, -13, -6, 2, 12, 34, 12, -24, -24, -20, + -16, -24, -38, -33, 2, 12, -2, -30, -31, 2, 45, 59, 46, 41, 24, 8, + -3, -6, 1, -15, -25, -16, -3, 5, 2, 21, 28, -11, -26, -23, -18, -20, + -32, -40, -14, 14, 11, -10, -40, -20, 30, 60, 55, 42, 34, 15, 6, -12, + -12, -4, -19, -21, -9, 8, 4, 10, 28, 6, -25, -22, -20, -22, -29, -38, + -27, 5, 16, 4, -24, -39, 12, 51, 61, 51, 41, 27, 10, -7, -25, -9, + -10, -17, -15, 0, 9, 5, 21, 15, -13, -27, -17, -21, -23, -38, -33, -11, + 10, 6, -4, -38, -17, 36, 55, 55, 45, 35, 21, 4, -27, -25, -2, -10, + -14, -13, 3, 5, 14, 16, 0, -24, -21, -18, -22, -36, -39, -17, -3, 5, + 3, -15, -28, 16, 50, 53, 52, 43, 29, 13, -14, -36, -10, -1, -15, -15, + -6, 6, 5, 13, 4, -11, -24, -17, -18, -27, -43, -18, -12, -7, 4, 3, + -17, -4, 38, 53, 52, 48, 41, 23, 0, -31, -30, 2, -7, -14, -13, -5, + 3, 11, 7, -4, -21, -25, -21, -19, -39, -23, -9, -19, -8, 5, -1, -10, + 24, 46, 48, 46, 44, 32, 10, -18, -37, -7, 0, -12, -14, -13, -4, 8, + 9, 1, -16, -29, -28, -17, -33, -31, -6, -21, -21, -4, 12, 3, 13, 41, + 46, 44, 46, 44, 20, -7, -36, -27, 6, -3, -18, -21, -12, 2, 12, 6, + -5, -27, -36, -21, -20, -34, -12, -8, -29, -16, 11, 15, 10, 28, 47, 46, + 41, 45, 35, 5, -24, -30, -5, 3, -14, -26, -16, -7, 7, 8, -3, -18, + -39, -32, -16, -28, -26, -8, -23, -26, 0, 19, 16, 20, 42, 55, 45, 38, + 39, 20, -11, -24, -13, -2, -6, -25, -22, -7, -5, 13, 0, -11, -36, -41, + -20, -16, -29, -16, -14, -28, -12, 13, 17, 15, 32, 50, 57, 41, 38, 30, + 2, -14, -9, -3, -3, -19, -33, -10, -7, 7, 7, -13, -30, -42, -28, -13, + -17, -26, -14, -22, -15, 7, 19, 15, 26, 46, 59, 51, 34, 33, 12, -7, + -11, -4, -5, -13, -38, -23, -3, 3, 15, -7, -32, -45, -34, -21, -11, -27, + -25, -21, -19, -1, 13, 15, 22, 37, 53, 62, 46, 34, 15, -2, 0, -4, + -8, -9, -34, -38, -8, 4, 17, 3, -25, -50, -44, -26, -12, -13, -32, -24, + -20, -7, 11, 18, 17, 33, 50, 65, 57, 41, 24, 0, 5, 5, -9, -11, + -25, -44, -25, -1, 17, 13, -18, -42, -51, -33, -20, -7, -27, -29, -23, -16, + 0, 14, 14, 28, 48, 60, 66, 51, 34, 4, 0, 15, -3, -14, -20, -35, + -37, -12, 12, 27, -7, -37, -50, -40, -29, -15, -15, -30, -24, -15, -7, 6, + 17, 25, 46, 59, 68, 63, 43, 20, -6, 14, 10, -8, -20, -30, -34, -22, + -2, 24, 15, -30, -49, -49, -37, -28, -15, -26, -28, -18, -11, -7, 7, 27, + 42, 58, 70, 70, 53, 35, 4, 0, 18, -1, -15, -32, -31, -26, -12, 12, + 28, -4, -44, -53, -44, -39, -25, -23, -28, -19, -11, -12, -16, 13, 42, 56, + 71, 71, 57, 45, 23, -3, 10, 11, -6, -27, -35, -25, -22, -1, 23, 17, + -29, -54, -46, -44, -39, -29, -28, -21, -15, -15, -26, -12, 39, 57, 70, 73, + 60, 49, 41, 13, 1, 11, 0, -16, -32, -25, -15, -14, 10, 23, -5, -48, + -46, -42, -49, -43, -31, -24, -15, -13, -24, -32, 18, 59, 71, 77, 67, 57, + 47, 33, 3, 5, 5, -9, -23, -33, -16, -14, -5, 17, 12, -29, -44, -35, + -50, -57, -43, -30, -18, -11, -22, -39, -9, 44, 68, 82, 69, 61, 49, 42, + 18, 5, 5, -8, -12, -26, -14, -7, -9, 5, 16, -6, -36, -32, -42, -62, + -55, -39, -29, -15, -14, -34, -30, 20, 59, 82, 79, 66, 58, 45, 38, 9, + 1, -7, -11, -16, -19, -3, -6, -6, 9, 5, -22, -32, -32, -58, -70, -56, + -42, -24, -16, -25, -39, -9, 41, 72, 86, 73, 65, 46, 40, 30, -4, -7, + -14, -12, -20, -3, 4, -5, 1, 8, -9, -27, -25, -40, -67, -67, -55, -38, + -24, -17, -25, -28, 16, 61, 81, 82, 71, 60, 37, 42, 17, -14, -17, -11, + -13, -8, 10, 2, -2, 1, -1, -17, -20, -26, -54, -69, -70, -58, -34, -25, + -16, -23, -9, 37, 70, 87, 80, 68, 44, 38, 39, -5, -27, -19, -12, -6, + 13, 10, 4, 1, 1, -5, -19, -20, -37, -59, -71, -71, -54, -35, -17, -9, + -20, 11, 49, 80, 86, 72, 54, 36, 45, 23, -25, -34, -16, -9, 11, 17, + 8, 5, -4, -2, -15, -19, -26, -50, -69, -77, -71, -51, -29, -7, -11, -6, + 26, 64, 87, 78, 60, 40, 42, 45, 2, -38, -34, -12, 10, 24, 10, 11, + 3, -1, -6, -20, -16, -31, -61, -81, -80, -69, -41, -16, -5, -8, 10, 47, + 81, 86, 70, 44, 36, 48, 32, -21, -48, -31, -3, 24, 24, 10, 15, 0, + 2, -17, -21, -18, -45, -81, -87, -80, -57, -33, -11, -6, 2, 30, 74, 86, + 77, 55, 34, 42, 48, 13, -39, -50, -20, 15, 34, 14, 16, 12, 4, -5, + -26, -16, -19, -64, -92, -91, -65, -43, -26, -12, -1, 16, 47, 83, 76, 66, + 40, 33, 45, 33, -8, -52, -41, -5, 32, 30, 15, 25, 13, 8, -22, -28, + -11, -34, -85, -101, -86, -52, -36, -25, -13, 15, 32, 69, 80, 69, 52, 32, + 37, 39, 19, -30, -54, -24, 10, 38, 25, 25, 22, 18, -6, -35, -20, -14, + -59, -98, -99, -68, -41, -30, -23, 5, 28, 52, 74, 67, 59, 43, 32, 35, + 32, -2, -47, -38, -13, 23, 33, 31, 26, 27, 16, -29, -37, -15, -33, -80, + -104, -89, -54, -35, -31, -11, 17, 42, 63, 68, 60, 59, 37, 27, 33, 22, + -28, -37, -26, 3, 32, 38, 30, 25, 30, -3, -41, -29, -23, -55, -90, -98, + -76, -39, -32, -21, 4, 36, 52, 61, 61, 63, 48, 24, 28, 34, -10, -31, + -29, -14, 15, 37, 37, 28, 31, 19, -27, -40, -24, -38, -69, -95, -96, -60, + -32, -26, -10, 19, 45, 53, 58, 59, 58, 29, 23, 39, 14, -21, -25, -23, + 1, 27, 43, 34, 34, 21, 0, -36, -32, -31, -49, -84, -102, -83, -41, -22, + -19, -1, 35, 49, 52, 53, 56, 39, 23, 34, 33, -3, -23, -22, -10, 17, + 36, 36, 39, 26, 8, -16, -34, -29, -36, -61, -93, -95, -58, -26, -18, -11, + 22, 48, 53, 53, 51, 41, 31, 33, 37, 16, -15, -24, -14, 4, 29, 34, + 41, 32, 8, -7, -19, -28, -30, -54, -83, -101, -76, -40, -20, -21, 1, 36, + 54, 55, 44, 33, 32, 35, 36, 30, 7, -26, -19, -5, 22, 36, 37, 37, + 15, -3, -5, -15, -24, -43, -75, -94, -87, -47, -29, -25, -14, 26, 48, 62, + 49, 29, 23, 35, 45, 38, 19, -16, -28, -7, 10, 29, 32, 38, 23, -2, + -10, -6, -12, -28, -67, -90, -98, -59, -32, -28, -25, 3, 43, 56, 59, 25, + 16, 24, 46, 43, 31, 0, -31, -14, 5, 25, 29, 32, 29, 6, -13, -6, + -3, -8, -49, -85, -97, -75, -31, -30, -30, -12, 31, 50, 61, 40, 12, 14, + 34, 53, 43, 20, -23, -20, -3, 21, 29, 23, 24, 15, -10, -8, -1, 2, + -25, -75, -98, -92, -42, -31, -35, -24, 14, 41, 50, 49, 22, 11, 20, 45, + 52, 39, 0, -26, -12, 9, 35, 25, 18, 14, 1, -13, -6, 4, 3, -49, + -89, -102, -61, -27, -30, -27, -4, 34, 46, 46, 32, 17, 13, 26, 47, 50, + 29, -19, -22, -4, 30, 37, 15, 7, 7, -5, -10, -4, 9, -20, -72, -100, + -86, -41, -33, -31, -16, 18, 43, 34, 32, 27, 23, 15, 31, 47, 48, 9, + -24, -16, 12, 43, 25, -2, 0, 9, -9, -15, 2, 8, -40, -87, -99, -69, + -37, -31, -19, 6, 38, 35, 25, 31, 35, 26, 18, 36, 49, 40, -10, -22, + -9, 29, 40, 6, -12, 6, 6, -16, -11, 9, -6, -61, -95, -90, -58, -35, + -26, -5, 23, 36, 18, 21, 36, 41, 28, 22, 38, 52, 23, -17, -17, 7, + 39, 21, -12, -13, 16, -8, -22, -5, 6, -25, -77, -93, -79, -46, -30, -11, + 15, 36, 22, 5, 29, 47, 47, 24, 22, 41, 48, 7, -15, -4, 22, 33, + 6, -23, 4, 8, -21, -15, -1, -5, -49, -79, -92, -71, -43, -20, 11, 31, + 29, 4, 16, 40, 55, 41, 22, 31, 50, 25, -9, -2, 8, 23, 16, -17, + -6, 8, -10, -15, -6, -4, -29, -56, -80, -86, -61, -42, 0, 30, 33, 12, + 2, 24, 47, 55, 37, 28, 39, 40, 4, -1, 6, 6, 16, -4, -13, 1, + -2, -9, -11, -11, -21, -35, -55, -82, -80, -64, -24, 27, 36, 23, 3, 10, + 35, 61, 55, 40, 35, 35, 19, 6, 12, 4, 1, 3, -12, -3, -2, -4, + -4, -14, -23, -30, -37, -58, -83, -84, -58, 8, 37, 33, 11, 3, 20, 46, + 62, 55, 50, 28, 16, 12, 15, 9, -4, -9, -9, -4, -5, -7, 2, -7, + -28, -35, -31, -36, -67, -90, -86, -23, 28, 38, 25, 5, 13, 34, 58, 58, + 69, 50, 15, 10, 20, 16, -3, -14, -14, -2, 1, -12, -3, 3, -20, -36, + -39, -26, -46, -81, -98, -61, 6, 27, 30, 16, 12, 25, 50, 57, 66, 74, + 31, 4, 16, 21, 8, -13, -21, -10, 8, -5, -11, 6, -8, -31, -40, -29, + -30, -66, -93, -84, -22, 17, 22, 26, 16, 20, 43, 56, 56, 70, 60, 17, + 8, 18, 15, -10, -26, -21, 6, 7, -12, -1, 1, -20, -33, -34, -31, -51, + -79, -92, -52, -6, 9, 19, 23, 21, 40, 57, 59, 60, 72, 43, 17, 13, + 18, 3, -23, -32, -5, 14, -7, -11, 7, -12, -26, -31, -37, -46, -66, -85, + -67, -21, -5, 3, 16, 22, 37, 54, 59, 55, 60, 58, 30, 16, 13, 11, + -15, -34, -23, 9, 7, -12, -2, -4, -19, -16, -31, -49, -64, -76, -72, -35, + -12, -14, 0, 15, 34, 53, 60, 58, 53, 57, 43, 30, 18, 12, -4, -27, + -28, -8, 14, -3, -9, -2, -13, -9, -17, -49, -66, -70, -69, -44, -15, -19, + -11, 2, 21, 53, 64, 68, 55, 48, 44, 36, 28, 15, -1, -18, -23, -19, + -4, 5, -3, 1, -9, -7, -1, -35, -70, -74, -70, -50, -21, -14, -22, -7, + -1, 39, 66, 77, 69, 46, 38, 36, 38, 22, 5, -12, -16, -12, -17, -8, + -5, 2, 1, -6, 5, -13, -64, -78, -73, -60, -31, -14, -17, -16, -10, 7, + 61, 79, 81, 57, 38, 28, 32, 24, 9, -4, -10, -4, -11, -20, -13, -2, + 11, 4, 4, -2, -41, -76, -76, -69, -43, -22, -12, -17, -14, -14, 25, 74, + 92, 79, 47, 31, 26, 26, 11, 3, -5, 0, 0, -20, -26, -11, 9, 14, + 9, 4, -24, -61, -76, -74, -53, -30, -13, -8, -12, -25, -8, 51, 90, 93, + 63, 42, 21, 18, 13, 6, 2, 1, 8, -12, -30, -27, -2, 14, 18, 11, + -13, -48, -68, -79, -70, -44, -19, -2, -5, -21, -31, 18, 77, 100, 81, 55, + 29, 7, 8, 6, 7, 4, 14, 0, -26, -34, -13, 9, 16, 17, 1, -35, + -58, -70, -82, -62, -29, -2, 1, -14, -36, -15, 50, 89, 95, 71, 46, 5, + -6, 4, 11, 3, 11, 14, -12, -31, -22, -2, 8, 16, 16, -15, -53, -56, + -80, -81, -41, -5, 9, -3, -30, -34, 17, 73, 97, 86, 63, 25, -12, -6, + 11, 13, 1, 15, 4, -19, -25, -5, 2, 9, 19, 10, -39, -48, -61, -95, + -67, -17, 12, 8, -23, -43, -9, 49, 85, 91, 76, 50, 1, -23, 2, 22, + 5, 2, 14, -5, -23, -12, 0, -2, 13, 17, -15, -48, -43, -83, -88, -38, + 5, 17, -11, -41, -28, 27, 67, 83, 82, 65, 29, -21, -18, 21, 19, -7, + 3, 6, -8, -14, 1, 0, 0, 13, 2, -34, -42, -59, -99, -63, -12, 17, + 0, -35, -42, 1, 53, 69, 79, 72, 53, -1, -34, 2, 32, 3, -8, 1, + 2, -2, -3, 8, -2, 3, 7, -18, -40, -39, -76, -81, -35, 9, 17, -22, + -46, -24, 34, 59, 68, 74, 66, 27, -26, -22, 31, 24, -10, -11, 0, 14, + 1, 5, 8, -5, -2, -10, -34, -35, -48, -77, -59, -13, 20, -4, -37, -35, + 8, 47, 55, 68, 74, 49, -4, -34, 10, 39, 1, -13, -11, 14, 14, 3, + 20, 6, -9, -14, -29, -37, -28, -56, -66, -42, 9, 9, -25, -38, -14, 27, + 45, 54, 72, 61, 21, -25, -14, 31, 19, -10, -15, -2, 22, 6, 22, 24, + -4, -20, -28, -38, -24, -28, -54, -57, -20, 14, -10, -29, -26, 2, 29, 39, + 61, 66, 39, -6, -25, 16, 30, 0, -16, -8, 12, 13, 18, 38, 10, -20, + -36, -34, -31, -16, -33, -56, -42, 0, 0, -21, -22, -12, 11, 25, 49, 68, + 53, 14, -20, -3, 29, 15, -11, -12, 3, 13, 13, 42, 34, -12, -39, -37, + -27, -22, -18, -44, -50, -21, 3, -12, -15, -18, -5, 9, 27, 60, 60, 32, + -6, -12, 21, 25, -4, -12, -2, 7, 8, 33, 53, 8, -37, -41, -25, -22, + -16, -27, -47, -34, -10, -10, -15, -15, -15, -5, 5, 41, 63, 44, 12, -11, + 10, 32, 10, -14, -8, 8, 5, 19, 53, 34, -24, -43, -25, -14, -15, -19, + -35, -35, -20, -12, -8, -14, -17, -19, -13, 19, 55, 53, 22, -8, 4, 31, + 26, -8, -13, 6, 10, 7, 39, 50, -2, -41, -31, -10, -13, -23, -31, -33, + -24, -15, -7, -13, -16, -22, -23, -6, 38, 55, 34, 1, -1, 23, 34, 9, + -18, -3, 14, 9, 20, 51, 24, -28, -37, -6, 2, -20, -30, -27, -21, -22, + -6, -12, -17, -21, -32, -27, 9, 49, 43, 12, -4, 14, 34, 24, -9, -12, + 12, 19, 13, 30, 37, -3, -35, -15, 12, -10, -31, -30, -15, -18, -13, -3, + -19, -20, -31, -35, -17, 28, 44, 22, 0, 7, 28, 27, 5, -15, 1, 20, + 20, 17, 28, 19, -21, -23, 12, 8, -22, -32, -20, -8, -15, 0, -13, -23, + -25, -43, -36, 4, 37, 30, 11, 4, 22, 28, 15, 0, -10, 9, 23, 14, + 11, 24, 5, -21, 2, 17, -8, -27, -27, -7, -10, -6, -1, -20, -26, -39, + -53, -20, 23, 36, 17, 7, 14, 28, 16, 12, -3, 2, 19, 16, 2, 14, + 19, -8, -5, 17, 4, -15, -26, -10, -4, -12, 1, -8, -23, -38, -58, -41, + 0, 29, 23, 11, 16, 21, 15, 9, 11, -6, 11, 20, 4, 3, 24, 5, + -5, 10, 17, -6, -15, -15, 6, -15, -8, 0, -11, -37, -54, -56, -24, 13, + 29, 12, 15, 20, 19, 6, 16, 5, -2, 10, 11, -3, 22, 18, 0, 6, + 20, 10, -6, -12, 1, -6, -23, 0, 1, -23, -56, -60, -43, -10, 19, 22, + 15, 22, 18, 6, 11, 17, -2, -5, 10, 4, 7, 23, 1, 3, 16, 22, + 5, -1, 0, 5, -21, -14, 6, -6, -46, -64, -54, -29, 1, 17, 18, 24, + 25, 10, 1, 17, 9, -8, -1, 15, 6, 20, 11, 2, 14, 25, 16, 9, + 5, 7, -11, -26, -5, 4, -27, -62, -62, -40, -17, 8, 11, 21, 29, 17, + -2, 10, 17, -8, -16, 6, 13, 11, 15, 3, 8, 24, 26, 14, 12, 12, + 4, -26, -15, 1, -12, -50, -64, -48, -27, -10, 5, 8, 32, 31, 1, -1, + 18, 0, -23, -6, 18, 14, 11, 5, 3, 17, 35, 25, 16, 18, 14, -11, + -27, -8, -6, -30, -55, -53, -36, -20, -5, 5, 14, 43, 13, -6, 11, 11, + -22, -22, 7, 19, 13, 10, 1, 7, 30, 36, 22, 23, 23, 6, -28, -20, + -6, -23, -43, -49, -43, -29, -19, 3, 1, 34, 29, -4, 3, 13, -13, -32, + -3, 20, 14, 11, 5, 2, 23, 42, 34, 22, 23, 21, -13, -26, -14, -19, + -32, -38, -43, -32, -29, -6, 4, 16, 35, 9, -4, 11, 0, -33, -22, 9, + 13, 12, 9, 3, 14, 35, 47, 34, 23, 27, 8, -22, -19, -16, -30, -29, + -42, -33, -32, -23, 4, 9, 24, 20, -1, 3, 10, -20, -36, -5, 13, 9, + 11, 8, 8, 21, 43, 48, 27, 22, 23, -7, -25, -20, -28, -25, -31, -36, + -28, -33, -8, 11, 14, 14, 6, -8, 7, -5, -39, -25, 7, 14, 9, 10, + 12, 15, 29, 55, 41, 23, 22, 9, -12, -23, -28, -24, -23, -34, -26, -31, + -21, 9, 19, 9, 1, -3, -1, 7, -32, -38, -9, 13, 11, 9, 11, 14, + 21, 46, 53, 32, 24, 12, -2, -16, -26, -24, -17, -34, -33, -25, -24, -4, + 17, 14, -3, -4, -7, 3, -13, -46, -25, 2, 17, 5, 8, 12, 18, 32, + 56, 38, 29, 15, 8, -4, -22, -30, -14, -22, -42, -25, -15, -10, 6, 17, + 1, -5, -7, -10, -2, -38, -37, -7, 15, 9, 2, 8, 21, 26, 43, 44, + 29, 18, 7, 12, -9, -25, -24, -11, -35, -43, -17, -5, 3, 10, 9, -3, + -3, -23, -9, -23, -45, -22, 7, 15, 2, 4, 17, 33, 31, 45, 35, 23, + 8, 17, 6, -16, -26, -14, -20, -48, -27, -2, 6, 11, 9, -1, 6, -15, + -28, -18, -39, -32, -7, 11, 7, 6, 7, 33, 30, 31, 41, 27, 7, 13, + 24, -3, -18, -22, -9, -40, -41, -10, 4, 9, 17, 3, 5, -4, -37, -29, + -29, -35, -19, 1, 10, 3, 7, 25, 41, 19, 31, 32, 13, 5, 27, 14, + -6, -19, -12, -23, -48, -22, 7, 8, 16, 11, 1, 6, -29, -46, -32, -32, + -20, -5, 7, 4, 3, 21, 43, 32, 15, 29, 16, 8, 19, 26, 3, -9, + -22, -13, -42, -37, -8, 11, 14, 25, 9, 4, -17, -50, -44, -30, -25, -14, + -1, 11, 1, 18, 36, 41, 12, 14, 18, 14, 15, 20, 17, 6, -14, -18, + -27, -39, -19, 5, 12, 24, 27, 8, -13, -49, -53, -32, -27, -19, -12, 7, + 7, 12, 31, 43, 26, 2, 8, 14, 22, 13, 17, 18, 6, -17, -26, -36, + -28, -6, 14, 25, 35, 20, -6, -42, -57, -37, -23, -23, -20, 0, 9, 8, + 25, 41, 40, 7, -4, 1, 23, 21, 14, 22, 20, -2, -24, -34, -31, -13, + 8, 24, 37, 33, 8, -32, -62, -44, -20, -22, -27, -9, 9, 7, 16, 31, + 42, 20, -10, -13, 10, 26, 7, 13, 25, 18, -11, -35, -39, -20, 0, 17, + 37, 37, 19, -17, -58, -55, -26, -18, -25, -21, 0, 14, 12, 20, 38, 35, + 0, -19, -9, 24, 19, 3, 21, 31, 17, -24, -42, -30, -3, 13, 34, 42, + 28, -2, -45, -62, -38, -22, -19, -20, -12, 12, 17, 11, 29, 42, 18, -16, + -20, 3, 24, 2, 4, 26, 36, 0, -38, -45, -13, 12, 27, 41, 34, 14, + -27, -62, -55, -30, -19, -15, -16, -2, 18, 11, 14, 37, 31, -6, -22, -12, + 15, 10, -10, 12, 36, 30, -19, -46, -33, 11, 24, 28, 35, 28, -5, -44, + -65, -44, -23, -11, -9, -8, 5, 14, 10, 25, 37, 14, -17, -18, -2, 14, + -7, -6, 23, 43, 10, -33, -38, -9, 24, 24, 28, 30, 11, -21, -57, -61, + -39, -12, -5, -5, -3, 7, 10, 17, 31, 30, -3, -20, -14, 6, 1, -16, + 2, 38, 38, -5, -30, -24, 13, 25, 21, 28, 15, 1, -34, -64, -62, -23, + 0, 2, -1, -1, 5, 14, 24, 33, 14, -12, -23, -4, 7, -18, -18, 18, + 43, 25, -9, -22, -2, 21, 19, 24, 20, 11, -13, -47, -69, -46, -7, 5, + 6, -1, -4, 9, 21, 31, 25, 5, -15, -20, 3, -8, -33, -7, 29, 37, + 20, -10, -10, 9, 15, 17, 14, 12, 1, -23, -55, -70, -30, 5, 13, 2, + -8, -1, 15, 25, 30, 15, -1, -20, -8, -3, -31, -28, 8, 31, 41, 15, + -6, 0, 9, 14, 12, 9, 8, -10, -28, -63, -55, -12, 17, 11, -7, -13, + 8, 22, 26, 19, 9, -7, -13, -5, -23, -39, -10, 17, 41, 38, 8, 0, + 5, 7, 12, 5, 7, -6, -8, -39, -60, -35, 7, 19, 6, -10, -6, 15, + 26, 22, 15, 9, -8, -13, -24, -45, -29, -1, 29, 48, 30, 2, 6, 5, + 9, 5, -1, -5, -4, -13, -51, -51, -16, 20, 13, 0, -11, 7, 25, 22, + 18, 17, 10, -8, -22, -50, -43, -13, 15, 46, 42, 16, 7, 8, 7, 7, + -1, -6, -10, -4, -27, -45, -36, 5, 16, 7, -5, -5, 20, 22, 19, 19, + 22, 7, -15, -43, -62, -29, 3, 35, 43, 27, 11, 9, 8, 4, 2, -9, + -13, -7, -15, -30, -43, -16, 12, 13, 4, -8, 12, 24, 17, 16, 24, 25, + -3, -38, -72, -52, -9, 25, 42, 30, 21, 8, 14, 4, 6, -3, -13, -12, + -13, -18, -36, -34, 3, 14, 9, -9, 5, 26, 18, 13, 26, 34, 13, -31, + -69, -68, -16, 19, 35, 29, 22, 6, 16, 3, 2, 6, -5, -15, -20, -19, + -21, -34, -17, 8, 16, -2, -3, 24, 27, 16, 23, 34, 32, -10, -56, -80, + -45, 6, 29, 29, 22, 10, 14, 13, -4, 6, 7, -8, -27, -27, -18, -20, + -28, -8, 14, 8, -7, 11, 29, 21, 17, 25, 35, 16, -36, -77, -67, -14, + 25, 30, 22, 11, 10, 19, 5, 2, 6, 5, -18, -34, -25, -13, -23, -19, + 4, 13, 0, 7, 24, 32, 24, 22, 31, 30, -12, -62, -76, -41, 9, 28, + 24, 15, 6, 18, 16, 6, 6, 7, -7, -32, -37, -16, -18, -24, -8, 11, + 7, 7, 20, 31, 35, 25, 24, 33, 9, -40, -72, -58, -16, 17, 27, 16, + 6, 10, 22, 12, 8, 8, 2, -23, -43, -26, -16, -24, -18, 2, 6, 7, + 21, 29, 36, 32, 21, 27, 22, -21, -57, -67, -38, -4, 26, 21, 9, 3, + 18, 25, 18, 10, 2, -11, -42, -36, -24, -27, -23, -9, 5, 2, 17, 32, + 42, 36, 27, 18, 25, -2, -39, -58, -51, -27, 11, 27, 11, 1, 9, 24, + 25, 21, 5, -8, -31, -37, -30, -33, -24, -15, 0, -2, 13, 31, 48, 47, + 33, 15, 18, 10, -27, -50, -52, -44, -12, 21, 21, 5, -1, 13, 33, 30, + 16, -6, -26, -39, -33, -35, -28, -20, -10, -8, 4, 27, 51, 61, 45, 21, + 13, 14, -11, -39, -40, -44, -36, 1, 25, 16, 1, 2, 27, 40, 28, 3, + -22, -38, -38, -32, -33, -21, -18, -14, -8, 18, 50, 66, 60, 27, 7, 12, + -3, -31, -36, -37, -46, -27, 18, 26, 5, -3, 8, 35, 43, 16, -14, -36, + -43, -32, -32, -25, -16, -23, -14, 6, 46, 64, 74, 49, 9, 4, 7, -23, + -37, -34, -41, -44, -8, 31, 19, -5, 0, 21, 47, 33, -2, -33, -43, -43, + -32, -29, -14, -22, -23, -6, 34, 62, 75, 71, 30, 0, 8, -13, -37, -34, + -35, -45, -34, 18, 31, 5, -5, 7, 35, 44, 12, -23, -45, -49, -40, -29, + -18, -18, -27, -15, 22, 57, 74, 80, 57, 15, 4, -1, -39, -34, -34, -40, + -46, -4, 25, 13, -3, 2, 22, 44, 25, -10, -38, -44, -50, -34, -20, -14, + -31, -21, 5, 47, 63, 81, 76, 38, 8, 9, -30, -45, -35, -36, -43, -20, + 9, 14, 5, 3, 7, 36, 32, 3, -32, -43, -50, -40, -28, -13, -24, -28, + -2, 35, 56, 73, 86, 58, 23, 21, -10, -49, -45, -33, -39, -25, -3, 5, + 5, 8, 5, 18, 32, 17, -19, -45, -49, -41, -35, -22, -19, -31, -12, 28, + 52, 59, 76, 74, 41, 31, 10, -39, -58, -41, -32, -27, -5, -3, 3, 8, + 8, 10, 24, 22, -4, -39, -52, -42, -35, -30, -18, -28, -22, 20, 53, 52, + 60, 73, 62, 43, 31, -18, -56, -61, -35, -28, -9, -6, -3, 3, 9, 10, + 12, 18, 8, -23, -53, -50, -31, -35, -24, -28, -26, 3, 48, 55, 52, 59, + 66, 57, 46, 7, -37, -67, -53, -24, -11, -4, -6, 0, 3, 13, 10, 7, + 10, -6, -38, -58, -36, -30, -30, -26, -26, -11, 33, 60, 56, 49, 59, 67, + 58, 32, -15, -58, -69, -34, -14, -8, -6, 1, -4, 7, 8, 2, 4, 4, + -21, -54, -49, -30, -30, -28, -29, -18, 13, 53, 60, 50, 44, 63, 61, 49, + 11, -33, -71, -49, -19, -9, -10, 5, 2, -1, 4, -1, 4, 5, -5, -38, + -55, -40, -28, -21, -25, -26, -2, 40, 61, 56, 39, 53, 66, 54, 33, -4, + -55, -63, -29, -18, -12, 3, 11, -4, -4, -9, -3, 4, 4, -18, -49, -49, + -35, -18, -18, -25, -16, 24, 51, 60, 42, 43, 66, 57, 42, 21, -23, -63, + -44, -26, -18, -10, 13, 9, -8, -18, -17, 5, 5, -4, -35, -47, -42, -24, + -11, -20, -21, 5, 36, 56, 53, 37, 60, 59, 40, 34, 11, -34, -52, -33, + -21, -15, 1, 21, 2, -19, -33, -10, 8, 3, -20, -42, -41, -33, -14, -16, + -18, -7, 21, 43, 54, 39, 47, 61, 44, 31, 27, -4, -41, -47, -28, -23, + -9, 11, 15, -9, -34, -34, 1, 10, -2, -30, -38, -34, -18, -15, -17, -10, + 10, 27, 43, 42, 42, 53, 54, 36, 24, 14, -15, -42, -36, -32, -22, 1, + 13, 7, -26, -48, -24, 11, 10, -14, -35, -32, -19, -16, -15, -11, 5, 18, + 31, 34, 41, 48, 51, 46, 28, 26, 8, -26, -36, -33, -35, -12, 7, 12, + -8, -45, -47, -9, 13, 5, -24, -32, -17, -14, -16, -11, 6, 14, 20, 26, + 27, 47, 49, 49, 34, 25, 22, -6, -31, -27, -39, -30, -10, 13, 6, -28, + -57, -31, -3, 12, -7, -28, -19, -8, -21, -18, -2, 18, 17, 17, 19, 34, + 47, 53, 42, 34, 30, 13, -22, -20, -30, -44, -32, -4, 15, -7, -45, -49, + -18, 4, 10, -14, -18, 0, -11, -26, -7, 15, 23, 10, 10, 20, 34, 51, + 49, 38, 41, 30, -8, -28, -15, -39, -47, -28, 5, 10, -26, -55, -34, -9, + 10, 3, -13, -4, 1, -21, -19, 3, 25, 13, 5, 9, 18, 36, 54, 39, + 40, 46, 16, -27, -17, -23, -47, -47, -18, 9, -2, -47, -51, -23, 0, 4, + 0, 1, 9, -11, -20, -9, 20, 23, 4, 2, 8, 20, 45, 46, 38, 53, + 41, -13, -30, -19, -36, -52, -40, -9, 5, -23, -53, -35, -6, 4, 3, 6, + 10, 5, -16, -17, 6, 30, 12, 0, -4, 9, 32, 47, 43, 55, 57, 16, + -27, -30, -28, -44, -52, -31, -6, -8, -43, -43, -15, -1, -1, 8, 10, 13, + 2, -18, -11, 21, 23, 6, -5, 0, 19, 33, 41, 56, 67, 44, -5, -34, + -35, -32, -46, -47, -27, -7, -30, -44, -23, -2, -2, 3, 7, 14, 18, -1, + -19, 4, 20, 16, -5, -9, 10, 27, 30, 46, 65, 63, 26, -22, -42, -34, + -41, -46, -40, -18, -25, -39, -28, -4, 1, -1, 5, 10, 24, 19, -8, -6, + 11, 20, 4, -13, 2, 22, 24, 36, 59, 70, 51, 5, -39, -39, -43, -47, + -45, -31, -30, -39, -33, -7, 1, -2, 1, 4, 19, 25, 5, -5, 1, 12, + 13, -12, -12, 18, 25, 21, 46, 68, 69, 36, -17, -39, -44, -51, -43, -33, + -35, -41, -38, -15, 8, 0, 0, 0, 13, 26, 19, 5, 0, -1, 10, -2, + -14, 5, 25, 19, 29, 54, 71, 59, 9, -31, -43, -56, -50, -32, -38, -47, + -42, -26, 8, 10, -3, -3, 7, 20, 23, 16, 8, -5, 3, 2, -17, -6, + 22, 20, 18, 40, 66, 71, 37, -13, -36, -52, -61, -38, -32, -47, -51, -38, + -7, 19, 6, -6, 4, 14, 19, 21, 19, 2, -5, 0, -13, -12, 14, 21, + 13, 27, 53, 71, 57, 12, -25, -42, -61, -54, -33, -38, -52, -50, -22, 13, + 17, -4, 1, 16, 17, 19, 25, 11, -2, -2, -11, -18, 6, 21, 15, 18, + 43, 66, 67, 34, -7, -30, -49, -58, -42, -36, -42, -54, -36, -2, 20, 4, + -4, 11, 16, 17, 26, 17, 4, 1, -8, -22, -8, 17, 16, 17, 27, 55, + 66, 48, 10, -25, -36, -49, -52, -42, -39, -47, -46, -18, 13, 14, -1, 3, + 13, 19, 27, 18, 2, 5, 1, -14, -17, 6, 13, 16, 26, 44, 64, 54, + 27, -15, -30, -33, -49, -50, -43, -44, -45, -30, -1, 13, 3, 6, 10, 22, + 30, 21, 3, 2, 2, -3, -18, -9, 8, 11, 23, 35, 55, 58, 37, 1, + -25, -18, -33, -51, -48, -46, -41, -30, -17, 6, 3, 7, 9, 16, 30, 27, + 9, 3, 3, 1, -10, -18, 0, 3, 12, 37, 46, 52, 40, 15, -23, -16, + -14, -39, -48, -48, -45, -31, -20, -7, 1, 4, 14, 13, 21, 26, 16, 2, + 1, 1, 1, -16, -12, 1, 5, 29, 50, 47, 39, 21, -11, -21, -3, -23, + -41, -45, -47, -37, -21, -13, -6, 1, 16, 20, 22, 22, 18, 10, 2, 1, + 6, -7, -16, -10, 0, 16, 51, 53, 38, 22, -1, -21, -1, -4, -30, -41, + -45, -45, -28, -13, -13, -8, 13, 24, 26, 15, 13, 15, 8, -4, 1, -2, + -11, -15, -11, 2, 40, 56, 44, 21, 1, -16, -10, 5, -16, -32, -38, -41, + -36, -22, -14, -15, 4, 24, 32, 18, 7, 14, 14, 4, -2, -1, -8, -12, + -15, -6, 24, 50, 51, 28, 1, -13, -14, 4, 1, -18, -31, -35, -36, -33, + -21, -21, -5, 19, 38, 23, 3, 5, 17, 15, 2, -3, -7, -8, -18, -14, + 12, 39, 50, 35, 2, -14, -14, -3, 6, -6, -24, -27, -32, -40, -25, -22, + -12, 8, 35, 34, 10, 2, 5, 19, 9, -6, -4, -3, -15, -18, 4, 30, + 42, 40, 13, -17, -16, -7, 3, 5, -14, -21, -24, -41, -37, -23, -18, -1, + 22, 37, 17, 4, -1, 11, 17, 1, -7, -4, -12, -22, -6, 24, 35, 33, + 25, -7, -26, -15, 2, 14, 3, -16, -19, -33, -42, -27, -23, -10, 15, 28, + 27, 8, 2, 5, 20, 11, -4, -6, -7, -19, -11, 17, 31, 26, 25, 6, + -24, -25, -6, 11, 14, -3, -13, -25, -39, -33, -23, -17, 7, 19, 26, 19, + 4, 1, 15, 14, -1, -5, -10, -14, -22, 8, 33, 28, 20, 16, -13, -26, + -17, 9, 22, 5, -8, -18, -37, -35, -28, -23, -4, 12, 16, 28, 12, 1, + 12, 18, 3, -2, -9, -10, -27, -10, 29, 34, 18, 16, 2, -26, -29, -3, + 27, 19, -4, -10, -29, -36, -30, -29, -12, 9, 3, 18, 21, 7, 12, 17, + 3, -2, -7, -7, -19, -26, 15, 36, 21, 12, 9, -15, -30, -18, 19, 30, + 6, -5, -21, -32, -25, -29, -22, 6, 0, 3, 20, 14, 12, 18, 12, 0, + -9, -12, -9, -26, -4, 31, 28, 11, 10, -6, -24, -29, 3, 35, 19, -3, + -15, -26, -19, -23, -31, -6, 4, -7, 13, 19, 17, 20, 18, 9, -9, -19, + -5, -17, -20, 16, 34, 18, 9, 0, -16, -25, -10, 30, 29, 3, -10, -19, + -19, -16, -29, -19, 3, -9, -5, 13, 21, 24, 16, 13, 1, -23, -14, -12, + -19, -2, 28, 21, 8, 1, -11, -23, -19, 16, 41, 14, -8, -13, -9, -13, + -18, -27, -4, -5, -12, -1, 19, 31, 18, 10, 16, -20, -22, -13, -14, -12, + 18, 26, 12, 4, -4, -17, -18, -1, 38, 31, -5, -14, -7, -7, -14, -24, + -13, -3, -13, -12, 7, 30, 34, 14, 18, -5, -33, -18, -10, -14, 1, 19, + 14, 6, -8, -13, -15, -2, 19, 40, 8, -13, -9, -4, -8, -18, -20, -9, + -14, -16, -7, 22, 37, 23, 16, 10, -26, -28, -13, -9, -5, 14, 14, 9, + -9, -17, -13, -1, 8, 31, 26, -6, -10, -4, -2, -12, -19, -11, -11, -17, + -12, 6, 34, 29, 15, 16, -7, -35, -25, -9, -6, 8, 14, 12, 1, -15, + -14, 3, 10, 19, 29, 8, -10, -9, 1, -7, -20, -10, -9, -17, -17, -1, + 30, 35, 18, 15, 5, -28, -33, -17, -6, -4, 8, 13, 5, -14, -19, 1, + 14, 14, 20, 17, 0, -8, -2, -3, -14, -18, -9, -12, -18, -6, 21, 37, + 26, 7, 10, -13, -33, -24, -6, -2, 0, 9, 11, -5, -19, -7, 16, 18, + 13, 18, 11, -2, -6, -3, -6, -22, -10, -11, -16, -11, 17, 34, 32, 9, + 9, 2, -26, -30, -14, -2, -5, 3, 8, 3, -16, -12, 8, 21, 13, 13, + 15, 2, -3, -5, -5, -20, -16, -8, -16, -20, 6, 32, 34, 14, -4, 6, + -12, -26, -20, -7, -6, -4, 4, 7, -2, -15, 1, 17, 15, 9, 15, 10, + 0, -3, -7, -15, -22, -4, -7, -19, -7, 29, 36, 20, -6, -1, 0, -17, + -19, -12, -9, -7, -1, 2, 6, -3, -8, 10, 18, 9, 8, 21, 4, -2, + -8, -13, -20, -12, -2, -16, -14, 14, 39, 26, -3, -17, 1, -6, -16, -12, + -7, -9, -9, 0, 3, 11, -3, 0, 15, 13, 3, 19, 12, -8, -6, -14, + -19, -16, 0, -6, -17, 3, 33, 35, 5, -18, -9, 1, -15, -11, -8, -8, + -16, -8, 1, 15, 15, 3, 11, 19, 2, 12, 26, 0, -10, -13, -21, -11, + 1, -1, -18, -2, 23, 35, 17, -12, -21, -2, -8, -9, -8, -9, -12, -17, + -5, 10, 22, 8, 7, 18, 7, -1, 23, 13, -13, -19, -23, -14, 5, 2, + -15, -13, 17, 30, 22, -3, -24, -7, -2, -9, -6, -10, -8, -21, -19, 5, + 22, 22, 13, 15, 13, -3, 11, 18, -4, -20, -28, -20, 4, 11, -10, -18, + 6, 26, 17, 3, -20, -12, -2, -11, -7, -8, -8, -16, -27, -7, 19, 30, + 21, 19, 15, 4, 3, 18, 2, -17, -33, -24, 0, 17, 1, -16, -6, 24, + 19, 5, -17, -18, 1, -8, -12, -7, -11, -10, -22, -14, 10, 29, 29, 32, + 23, 13, 0, 9, 6, -12, -28, -36, -7, 13, 12, -8, -17, 12, 24, 6, + -10, -20, 1, 1, -13, -9, -12, -16, -20, -17, 0, 21, 27, 31, 35, 20, + 7, 0, 2, -13, -19, -37, -19, 8, 18, 9, -16, -9, 20, 11, -2, -25, + -13, 8, -4, -16, -13, -18, -23, -17, 0, 14, 29, 27, 43, 35, 17, -1, + -4, -13, -22, -29, -31, -2, 17, 20, -5, -21, 6, 16, 5, -16, -25, 4, + 11, -12, -17, -20, -27, -19, -2, 13, 26, 27, 36, 46, 32, 7, -8, -18, + -26, -25, -32, -16, 12, 26, 11, -18, -11, 4, 13, -1, -27, -12, 14, 2, + -21, -23, -31, -26, -11, 10, 24, 30, 29, 43, 50, 24, -4, -16, -34, -28, + -28, -27, -1, 27, 24, -5, -21, -12, 6, 16, -13, -28, 1, 13, -9, -23, + -33, -32, -18, 2, 24, 34, 33, 34, 50, 49, 12, -11, -34, -37, -28, -25, + -14, 14, 28, 10, -10, -25, -9, 21, 15, -27, -15, 12, 2, -18, -33, -36, + -24, -7, 13, 30, 39, 42, 35, 54, 36, 1, -29, -45, -35, -26, -17, -1, + 20, 19, 2, -23, -30, 1, 30, -5, -32, 1, 7, -8, -27, -37, -25, -12, + -1, 23, 37, 51, 38, 41, 49, 16, -15, -41, -40, -31, -21, -11, 4, 19, + 15, -8, -33, -19, 22, 20, -21, -13, 2, -6, -17, -36, -32, -11, -8, 9, + 28, 48, 54, 36, 48, 30, 3, -30, -41, -34, -24, -15, -6, 2, 17, 8, + -19, -37, 0, 31, 3, -20, -6, -4, -7, -31, -35, -9, -3, -4, 16, 37, + 62, 44, 41, 33, 13, -11, -36, -39, -29, -21, -11, -11, 6, 14, -2, -28, + -24, 15, 22, -5, -10, -11, -10, -20, -35, -13, 2, -5, 2, 21, 55, 64, + 46, 37, 19, 2, -23, -36, -28, -23, -17, -18, -17, 10, 11, -12, -32, -7, + 23, 16, -7, -14, -17, -8, -27, -23, 1, 1, 0, 6, 31, 63, 60, 46, + 21, 7, -12, -29, -24, -18, -24, -23, -27, -11, 11, 5, -16, -19, 11, 21, + 4, -9, -21, -15, -17, -30, -5, 7, 2, -1, 9, 48, 65, 59, 30, 13, + -4, -25, -19, -6, -22, -33, -32, -31, -3, 7, -3, -20, -4, 14, 11, -1, + -11, -19, -13, -20, -16, 9, 7, 2, -3, 27, 60, 69, 44, 12, 7, -18, + -20, 1, -4, -35, -38, -34, -22, -9, 4, -2, -11, 8, 8, 2, -6, -19, + -23, -14, -16, 3, 13, 2, 2, 12, 47, 65, 62, 22, 10, -3, -21, -9, + 9, -17, -46, -40, -34, -23, -6, 4, -1, 3, 7, 2, -4, -13, -25, -18, + -11, -4, 18, 3, -2, 5, 30, 58, 66, 39, 12, 9, -10, -18, 8, 5, + -41, -49, -38, -33, -18, -4, 2, 7, 8, 2, -7, -12, -18, -23, -12, -6, + 18, 15, -8, 0, 21, 44, 62, 48, 22, 14, 7, -16, -7, 18, -18, -52, + -44, -42, -32, -18, -1, 12, 10, 6, -8, -20, -11, -18, -19, -10, 14, 24, + 2, -5, 14, 34, 57, 51, 27, 19, 20, -1, -13, 15, -1, -42, -45, -49, + -38, -28, -15, 13, 19, 10, -1, -23, -16, -11, -24, -10, 6, 21, 14, -5, + 3, 24, 48, 58, 29, 17, 24, 18, -6, 4, 8, -28, -38, -46, -50, -36, + -29, 3, 22, 15, 4, -18, -31, -7, -20, -17, 5, 11, 18, 4, -2, 15, + 37, 58, 35, 11, 26, 31, 11, -2, 6, -13, -32, -39, -55, -45, -38, -17, + 21, 23, 11, -10, -31, -18, -11, -25, 1, 9, 14, 15, 0, 7, 26, 49, + 49, 13, 10, 33, 26, 8, 4, -5, -25, -35, -46, -53, -41, -35, 5, 24, + 17, 0, -25, -26, -14, -24, -9, 6, 5, 17, 6, 6, 20, 38, 55, 30, + 3, 25, 38, 18, 10, -4, -16, -30, -42, -51, -46, -41, -16, 21, 23, 14, + -16, -30, -16, -17, -17, 0, 2, 12, 16, 3, 17, 28, 46, 49, 14, 13, + 39, 30, 17, 4, -9, -20, -38, -49, -50, -50, -34, 4, 21, 20, 4, -29, + -23, -15, -15, -8, -3, 7, 19, 8, 9, 26, 35, 47, 29, 6, 29, 35, + 26, 13, -5, -18, -29, -42, -49, -51, -50, -16, 11, 23, 18, -17, -34, -14, + -15, -9, -10, -2, 17, 14, 5, 21, 33, 44, 38, 14, 23, 37, 30, 20, + 6, -8, -26, -34, -47, -52, -54, -34, 0, 16, 19, 5, -29, -20, -13, -10, + -9, -10, 4, 19, 11, 13, 29, 37, 36, 22, 22, 39, 32, 23, 10, 2, + -18, -32, -40, -54, -56, -49, -23, 8, 17, 11, -15, -26, -11, -13, -9, -15, + -11, 14, 17, 10, 23, 34, 36, 24, 21, 35, 42, 26, 12, 2, -4, -23, + -31, -47, -57, -50, -33, -7, 17, 11, -2, -18, -12, -12, -11, -10, -21, -6, + 18, 19, 21, 33, 35, 28, 23, 34, 51, 40, 12, -2, 1, -9, -27, -43, + -59, -53, -39, -23, 4, 15, 1, -10, -14, -9, -8, -10, -22, -18, 5, 19, + 16, 27, 34, 28, 23, 27, 47, 53, 27, -3, -4, -1, -13, -33, -53, -57, + -45, -31, -13, 14, 4, -4, -11, -9, -9, -11, -19, -28, -16, 10, 24, 23, + 35, 24, 26, 26, 38, 60, 44, 2, -13, -3, -5, -19, -44, -58, -49, -33, + -26, 1, 14, 1, -4, -5, 0, -7, -14, -29, -26, -11, 20, 27, 30, 32, + 21, 27, 34, 59, 58, 22, -11, -10, -6, -10, -29, -55, -53, -38, -34, -16, + 12, 9, -5, -8, 5, 1, -16, -31, -32, -28, 0, 26, 26, 33, 23, 24, + 33, 49, 61, 37, 3, -15, -8, -11, -19, -43, -56, -44, -34, -25, -2, 17, + 5, -11, 2, 12, -2, -23, -32, -35, -23, 14, 26, 27, 35, 23, 32, 45, + 58, 47, 19, -5, -9, -10, -16, -27, -46, -48, -41, -34, -18, 11, 20, -6, + -10, 12, 9, -18, -34, -38, -29, -7, 17, 27, 32, 30, 30, 46, 52, 51, + 28, 6, -8, -9, -15, -24, -32, -41, -45, -40, -30, -1, 23, 10, -12, 2, + 17, -2, -31, -39, -32, -18, -6, 18, 29, 38, 32, 45, 54, 54, 33, 11, + 2, -9, -11, -19, -32, -33, -41, -45, -40, -18, 16, 19, 2, -6, 13, 12, + -20, -43, -35, -21, -18, -5, 21, 35, 36, 46, 58, 52, 38, 17, 9, -5, + -9, -13, -29, -32, -28, -41, -43, -36, 0, 22, 18, -4, -3, 17, 2, -33, + -43, -25, -18, -16, 4, 27, 38, 47, 64, 57, 40, 18, 10, 5, -7, -10, + -22, -39, -24, -30, -42, -39, -22, 13, 28, 14, -9, 3, 17, -16, -51, -36, + -17, -23, -18, 8, 35, 50, 66, 68, 43, 23, 12, 13, -1, -11, -17, -32, + -27, -22, -40, -38, -37, -10, 22, 34, 1, -10, 8, 6, -39, -48, -27, -19, + -25, -10, 18, 49, 66, 78, 54, 26, 17, 16, 3, -7, -15, -25, -29, -12, + -32, -37, -35, -28, 3, 38, 26, -7, -4, 11, -15, -46, -42, -26, -23, -24, + -2, 34, 66, 81, 70, 30, 19, 21, 10, -5, -11, -25, -29, -12, -20, -37, + -33, -39, -17, 25, 46, 6, -11, 2, 0, -29, -44, -41, -30, -27, -17, 12, + 58, 79, 84, 46, 19, 22, 19, 2, -7, -26, -35, -12, -1, -29, -33, -39, + -36, 3, 46, 31, -11, -6, -1, -14, -38, -46, -39, -32, -22, -5, 40, 76, + 88, 64, 23, 22, 30, 12, -8, -20, -39, -22, 0, -13, -29, -33, -43, -20, + 24, 49, 13, -12, 2, -6, -26, -45, -45, -39, -32, -15, 19, 68, 85, 77, + 32, 22, 35, 27, 0, -18, -36, -38, -6, 3, -17, -29, -44, -37, -2, 40, + 34, -8, -6, 3, -18, -44, -47, -44, -43, -21, 3, 49, 76, 80, 53, 21, + 35, 39, 15, -18, -35, -42, -23, 2, -3, -19, -33, -42, -23, 16, 46, 16, + -8, 2, -6, -37, -45, -47, -51, -33, -8, 31, 68, 74, 66, 33, 35, 45, + 36, -3, -33, -40, -34, -7, 5, -8, -18, -35, -39, -13, 32, 32, 3, -1, + 5, -26, -46, -50, -52, -44, -20, 15, 59, 68, 69, 50, 32, 42, 48, 21, + -26, -42, -42, -24, 2, 2, -8, -20, -38, -35, 6, 33, 17, -2, 5, -6, + -41, -55, -57, -46, -33, -6, 40, 64, 62, 63, 45, 38, 54, 40, -4, -42, + -50, -40, -11, 6, -2, -8, -24, -41, -19, 17, 28, 10, 0, 1, -26, -52, + -64, -51, -40, -23, 19, 54, 56, 61, 60, 38, 52, 55, 24, -30, -50, -47, + -27, 4, 8, -6, -11, -30, -36, -6, 19, 25, 4, 1, -9, -38, -64, -61, + -42, -36, 0, 44, 55, 51, 66, 50, 49, 62, 46, -5, -48, -51, -40, -11, + 11, 4, -14, -15, -36, -25, 1, 19, 15, -1, -2, -18, -53, -69, -48, -42, + -20, 21, 51, 45, 56, 62, 51, 60, 59, 23, -32, -53, -49, -28, 5, 17, + -12, -18, -22, -32, -12, 9, 20, 1, -6, -5, -29, -70, -62, -48, -32, 2, + 36, 45, 44, 62, 62, 60, 64, 47, -10, -45, -54, -42, -11, 21, 5, -19, + -18, -23, -20, -1, 15, 4, -6, -2, -6, -51, -72, -57, -44, -13, 19, 40, + 41, 51, 65, 66, 69, 63, 14, -32, -47, -50, -30, 10, 14, -12, -16, -18, + -16, -14, 7, 8, -6, -8, -1, -21, -65, -67, -54, -29, 1, 26, 38, 44, + 53, 69, 77, 73, 37, -17, -41, -46, -37, -10, 13, -1, -11, -14, -14, -10, + -6, 9, -5, -6, -11, -3, -43, -67, -68, -42, -15, 12, 27, 40, 47, 65, + 80, 83, 55, 7, -34, -43, -34, -22, -5, 2, -3, -2, -13, -10, -11, 3, + -2, -4, -13, -5, -15, -51, -72, -63, -31, -3, 16, 29, 42, 55, 78, 91, + 68, 25, -11, -40, -32, -22, -21, -9, -1, 8, -1, -19, -11, -3, 1, -5, + -11, -12, -3, -29, -58, -70, -48, -18, 6, 15, 35, 50, 68, 89, 84, 37, + 11, -27, -38, -19, -20, -23, -8, 10, 18, -10, -19, -8, 4, 0, -11, -14, + -7, -20, -42, -63, -60, -37, -4, 7, 23, 41, 67, 82, 90, 53, 19, -4, + -34, -23, -20, -31, -22, 5, 25, 8, -17, -20, 0, 10, -5, -20, -9, -12, + -31, -47, -60, -53, -26, -3, 12, 32, 58, 81, 85, 70, 27, 9, -19, -26, + -19, -28, -31, -8, 24, 21, -2, -26, -11, 14, 10, -20, -18, -8, -24, -33, + -53, -56, -44, -23, 3, 22, 44, 77, 85, 74, 40, 17, -3, -21, -21, -24, + -36, -25, 11, 22, 15, -13, -28, 5, 23, 0, -28, -12, -19, -26, -42, -56, + -48, -39, -17, 12, 34, 62, 84, 73, 52, 26, 9, -12, -21, -22, -31, -30, + -1, 15, 16, 6, -25, -14, 23, 19, -17, -21, -13, -24, -34, -54, -44, -39, + -36, -9, 27, 46, 79, 79, 59, 38, 16, -2, -17, -25, -25, -27, -10, 5, + 10, 15, -4, -24, 5, 29, 5, -24, -18, -19, -28, -48, -50, -35, -38, -28, + 10, 33, 62, 82, 62, 46, 27, 4, -8, -23, -24, -25, -15, -3, 0, 8, + 6, -12, -9, 22, 25, -6, -21, -22, -28, -45, -53, -39, -30, -37, -11, 20, + 43, 75, 66, 53, 41, 10, -8, -16, -25, -23, -15, -2, -4, -5, 4, 1, + -7, 8, 29, 19, -9, -21, -24, -42, -55, -48, -30, -31, -19, 5, 23, 61, + 74, 58, 53, 26, -7, -11, -18, -25, -14, 0, 1, -16, -8, 4, 0, 3, + 20, 28, 11, -16, -19, -38, -58, -55, -35, -27, -16, -1, 5, 32, 63, 61, + 56, 44, 3, -17, -13, -22, -19, -4, 5, -8, -21, -6, 7, 8, 12, 25, + 25, 2, -17, -26, -54, -64, -47, -32, -11, 5, 3, 16, 40, 60, 58, 56, + 26, -16, -19, -16, -20, -8, 0, -4, -20, -22, 1, 12, 9, 17, 30, 20, + -2, -15, -42, -68, -57, -44, -19, 11, 6, 10, 19, 42, 58, 58, 45, 6, + -23, -18, -13, -13, -3, -3, -10, -26, -14, 9, 15, 12, 26, 27, 10, -7, + -25, -61, -68, -54, -36, 10, 15, 13, 16, 19, 42, 55, 52, 31, -9, -25, + -18, -15, -7, -3, -9, -23, -26, -2, 15, 19, 19, 26, 18, 7, -10, -41, + -72, -60, -51, -8, 25, 22, 20, 13, 19, 45, 51, 44, 19, -15, -28, -15, + -7, -4, -9, -19, -28, -14, 6, 18, 18, 24, 22, 12, 1, -17, -55, -67, + -56, -35, 19, 33, 30, 20, 9, 23, 44, 48, 39, 6, -22, -25, -9, -8, + -9, -15, -29, -21, -3, 10, 16, 20, 23, 13, 7, -4, -31, -63, -61, -50, + -11, 33, 37, 30, 12, 7, 24, 44, 48, 28, -4, -28, -14, -4, -14, -14, + -27, -27, -8, 5, 13, 15, 19, 19, 11, 3, -12, -44, -64, -58, -31, 17, + 40, 39, 24, 8, 3, 30, 46, 42, 16, -18, -21, -6, -16, -18, -26, -32, + -15, 1, 6, 10, 10, 15, 12, 10, -3, -23, -51, -63, -50, -4, 34, 41, + 33, 17, -4, 10, 35, 42, 32, 5, -15, -8, -10, -18, -21, -30, -22, 0, + 3, -2, -2, 6, 5, 4, 3, -7, -25, -45, -45, -18, 25, 33, 32, 21, + 7, 8, 20, 30, 31, 20, 3, -7, -10, -14, -17, -23, -29, -12, 6, -2, + -11, -11, -4, 2, 3, -7, -10, -27, -33, -21, 13, 27, 23, 19, 8, 15, + 17, 18, 21, 23, 19, 2, -12, -10, -9, -15, -27, -28, -2, 9, -8, -18, + -17, -4, 9, -6, -7, -10, -17, -13, 2, 21, 20, 14, 4, 15, 25, 15, + 11, 14, 19, 13, -13, -17, -6, -5, -20, -36, -23, 4, 6, -18, -28, -20, + 6, 6, 0, 3, 5, 5, 28, 31, 31, 49, 55, 35, 11, 27, 26, 4, + 7, 11, 31, 54, 38, 26, 34, 35, 20, -10, -32, -43, -47, -43, -20, -7, + -37, -55, -62, -61, -63, -34, -21, -35, -28, -10, 15, 24, 23, 5, -31, -38, + -6, 23, 19, 15, 24, 20, 31, 57, 54, 28, 13, 33, 20, 1, 4, 17, + 38, 44, 33, 31, 43, 36, 10, -14, -34, -53, -53, -46, -22, -22, -38, -46, + -54, -60, -58, -29, -25, -39, -29, -12, 11, 25, 27, 6, -31, -33, -3, 27, + 32, 21, 13, 16, 38, 60, 53, 26, 18, 28, 11, -2, 8, 26, 37, 34, + 36, 42, 47, 31, 6, -14, -41, -61, -54, -49, -26, -30, -41, -40, -44, -54, + -48, -23, -28, -41, -33, -7, 14, 26, 29, 3, -32, -27, 6, 33, 35, 18, + 5, 21, 45, 61, 49, 25, 30, 22, 0, -5, 9, 37, 39, 27, 33, 47, + 50, 31, 1, -22, -51, -65, -59, -45, -31, -40, -36, -29, -35, -49, -41, -28, + -39, -44, -26, -8, 6, 27, 31, -5, -31, -18, 14, 33, 31, 17, 4, 25, + 48, 57, 45, 32, 27, 9, -6, -5, 14, 43, 36, 29, 39, 51, 50, 31, + 0, -32, -65, -73, -62, -37, -36, -46, -36, -23, -26, -37, -32, -35, -46, -42, + -22, -11, 2, 30, 28, -8, -29, -12, 22, 33, 32, 15, 4, 25, 49, 58, + 50, 36, 20, 2, -9, -3, 21, 43, 37, 32, 44, 55, 53, 33, -7, -42, + -67, -72, -64, -43, -43, -46, -35, -17, -17, -24, -31, -40, -47, -39, -18, -15, + 0, 33, 22, -14, -22, 5, 29, 29, 28, 11, 7, 23, 49, 54, 50, 37, + 13, -6, -11, -6, 25, 44, 38, 26, 40, 57, 54, 28, -12, -48, -70, -73, + -66, -43, -43, -43, -29, -12, -15, -16, -32, -48, -51, -38, -24, -19, 4, 31, + 12, -16, -14, 21, 34, 24, 24, 13, 10, 27, 49, 53, 53, 33, 6, -9, + -16, -4, 33, 48, 37, 24, 45, 61, 54, 23, -15, -60, -76, -76, -60, -48, + -45, -38, -26, -11, -3, -5, -33, -49, -52, -35, -25, -21, 7, 24, 1, -15, + -1, 34, 30, 23, 29, 17, 5, 26, 49, 55, 53, 26, -3, -16, -16, 4, + 38, 43, 33, 33, 49, 59, 45, 19, -18, -63, -78, -79, -58, -50, -39, -31, + -21, -11, -2, -3, -30, -49, -51, -35, -29, -20, 8, 12, -10, -11, 17, 37, + 27, 29, 29, 13, 2, 33, 56, 55, 38, 18, -7, -19, -17, 13, 40, 42, + 33, 35, 52, 58, 40, 10, -28, -68, -84, -78, -56, -47, -36, -30, -17, -7, + 5, -4, -30, -49, -51, -34, -30, -18, 10, 1, -18, -9, 30, 39, 26, 32, + 28, 9, 7, 38, 51, 45, 35, 16, -13, -28, -11, 27, 41, 41, 34, 45, + 58, 54, 29, 7, -33, -69, -80, -78, -59, -43, -31, -24, -15, -3, 9, -4, + -29, -51, -51, -33, -27, -8, 8, -13, -24, -1, 40, 41, 29, 31, 22, 7, + 15, 46, 48, 38, 33, 11, -19, -28, -7, 26, 42, 36, 39, 54, 54, 48, + 20, 3, -39, -68, -79, -78, -54, -37, -32, -27, -16, 5, 11, -6, -31, -50, + -49, -33, -24, -3, -3, -29, -26, 13, 44, 36, 30, 32, 17, 7, 28, 43, + 37, 31, 28, 4, -17, -27, -5, 24, 46, 43, 48, 56, 50, 41, 20, -1, + -47, -64, -82, -78, -48, -35, -34, -26, -14, 6, 9, -10, -31, -46, -43, -33, + -21, 1, -16, -38, -15, 24, 38, 35, 44, 33, 10, 15, 37, 43, 30, 22, + 18, 4, -20, -29, 0, 30, 43, 48, 54, 52, 46, 35, 19, -9, -41, -60, + -83, -73, -44, -29, -37, -27, -12, 6, 8, -10, -28, -45, -43, -25, -9, -3, + -33, -43, -4, 32, 35, 37, 49, 24, 7, 26, 47, 35, 17, 11, 14, 3, + -21, -30, 6, 30, 44, 60, 56, 44, 37, 33, 15, -11, -40, -63, -82, -61, + -36, -33, -39, -26, -13, 0, 4, -9, -29, -42, -37, -18, -7, -13, -39, -34, + 2, 30, 34, 45, 49, 16, 11, 37, 45, 26, 11, 8, 9, -1, -26, -25, + 17, 31, 46, 62, 52, 42, 29, 26, 15, -12, -45, -64, -71, -48, -34, -35, + -33, -27, -16, 1, 2, -10, -23, -41, -32, -12, -6, -29, -46, -28, 12, 26, + 36, 54, 43, 10, 23, 52, 43, 18, -2, 5, 5, -7, -25, -11, 19, 22, + 49, 61, 50, 40, 24, 20, 15, -10, -47, -62, -62, -45, -34, -30, -30, -23, + -16, -6, -1, -8, -25, -38, -29, -9, -10, -39, -42, -19, 5, 23, 48, 57, + 33, 7, 32, 57, 39, 8, -7, 3, -2, -16, -16, 1, 20, 22, 48, 55, + 46, 39, 17, 16, 17, -9, -48, -58, -54, -40, -37, -28, -26, -22, -23, -5, + 2, -11, -28, -37, -27, -10, -18, -44, -35, -18, 3, 31, 54, 52, 25, 13, + 45, 61, 29, -4, -10, 0, -5, -16, -8, 4, 21, 21, 50, 54, 45, 31, + 4, 20, 18, -15, -43, -48, -48, -39, -33, -28, -25, -22, -21, 0, -1, -19, + -29, -29, -22, -11, -29, -42, -30, -17, 3, 38, 61, 46, 24, 25, 53, 58, + 20, -10, -9, -5, -16, -12, 4, 11, 22, 17, 48, 51, 43, 16, 2, 18, + 13, -15, -35, -46, -43, -38, -31, -23, -27, -24, -13, 3, -8, -25, -29, -27, + -22, -18, -36, -38, -31, -19, 6, 46, 60, 36, 24, 33, 56, 44, 10, -8, + -9, -12, -24, -7, 14, 23, 18, 11, 45, 47, 39, 13, 5, 16, 1, -19, + -22, -39, -45, -45, -31, -20, -24, -16, -6, -3, -19, -24, -25, -26, -22, -24, + -39, -35, -25, -13, 8, 54, 64, 36, 29, 41, 56, 36, 5, -12, -11, -14, + -26, -6, 24, 33, 7, 12, 45, 44, 30, 13, 10, 17, -4, -17, -16, -34, + -46, -50, -30, -20, -23, -12, 1, -11, -26, -27, -24, -21, -19, -34, -48, -32, + -23, -10, 13, 66, 65, 33, 32, 48, 55, 25, 0, -8, -1, -18, -36, -4, + 40, 33, -1, 17, 37, 35, 25, 10, 14, 10, -13, -15, -9, -26, -46, -51, + -32, -18, -15, -4, 3, -17, -31, -28, -25, -20, -26, -48, -48, -27, -20, -13, + 19, 71, 61, 28, 33, 56, 50, 12, -8, -2, 5, -24, -41, 2, 52, 29, + -1, 24, 36, 26, 16, 14, 19, 6, -19, -12, 1, -21, -49, -50, -28, -12, + -3, 2, -2, -25, -32, -29, -24, -14, -31, -61, -44, -17, -15, -9, 28, 72, + 61, 25, 38, 61, 41, 7, -7, 4, 3, -32, -36, 9, 45, 21, 4, 30, + 33, 15, 11, 18, 17, -1, -18, -7, -4, -22, -47, -45, -24, -6, 2, 5, + -7, -27, -34, -28, -21, -14, -42, -69, -40, -11, -16, -3, 41, 68, 53, 29, + 48, 61, 32, 0, -5, 8, 2, -33, -28, 9, 31, 16, 16, 34, 22, 0, + 10, 24, 10, -9, -19, -6, -8, -26, -38, -34, -20, -10, 1, 11, -9, -33, + -31, -32, -25, -18, -50, -65, -40, -15, -8, 13, 47, 65, 50, 33, 54, 62, + 24, -2, 2, 12, -6, -31, -20, 12, 21, 10, 28, 34, 9, -5, 20, 20, + -2, -13, -10, -4, -18, -33, -26, -16, -19, -14, 6, 8, -14, -31, -32, -29, + -29, -31, -51, -69, -47, -12, 2, 21, 49, 56, 43, 45, 62, 54, 16, -2, + 7, 9, -13, -22, -4, 12, 7, 13, 37, 33, 7, -4, 23, 9, -8, -8, + -2, -8, -33, -38, -7, -1, -22, -19, 11, 7, -21, -29, -29, -29, -31, -32, + -55, -80, -49, -7, 16, 31, 43, 45, 44, 56, 66, 45, 12, 2, 10, 3, + -18, -13, 7, 9, -2, 17, 38, 22, 1, 5, 17, 4, -14, -12, -1, -11, + -43, -38, 6, 5, -22, -15, 12, 0, -23, -26, -28, -31, -32, -36, -60, -82, + -46, 3, 24, 35, 38, 41, 46, 59, 62, 41, 13, -1, 3, -6, -18, 3, + 22, 2, -9, 20, 36, 18, 10, 7, 4, -5, -17, -9, -2, -18, -55, -30, + 17, 6, -20, -10, 6, -5, -16, -26, -32, -27, -30, -42, -69, -84, -41, 13, + 31, 42, 37, 38, 45, 63, 65, 41, 12, 3, 1, -18, -10, 23, 27, -2, + -12, 17, 36, 26, 13, 4, -2, -5, -14, -14, -11, -26, -54, -19, 21, 8, + -16, -8, 6, -7, -20, -30, -33, -24, -33, -50, -74, -82, -32, 18, 34, 42, + 38, 34, 50, 69, 58, 34, 16, 7, -9, -29, -2, 41, 32, -7, -15, 11, + 34, 30, 9, 2, -3, -7, -23, -21, -15, -30, -52, -10, 18, 10, -8, -4, + 5, -4, -25, -33, -26, -22, -42, -59, -79, -72, -20, 23, 36, 41, 37, 34, + 54, 74, 53, 22, 17, 15, -17, -34, 10, 52, 37, -8, -11, 12, 33, 23, + 8, 4, -1, -16, -31, -25, -18, -38, -49, -3, 19, 11, -4, 0, 7, -8, + -34, -31, -19, -26, -52, -62, -79, -55, -7, 23, 41, 47, 41, 33, 61, 75, + 43, 22, 21, 13, -26, -33, 17, 58, 39, -6, -8, 13, 27, 10, 5, 13, + -2, -32, -43, -32, -19, -38, -36, -3, 12, 4, 4, 13, 6, -22, -41, -31, + -13, -33, -59, -71, -76, -35, 2, 20, 39, 53, 47, 39, 60, 62, 37, 26, + 22, 5, -33, -29, 26, 64, 40, 0, -5, 12, 21, 8, 16, 10, -13, -39, + -49, -37, -25, -41, -30, -6, 9, 9, 13, 23, 0, -30, -44, -26, -13, -45, + -67, -76, -68, -20, 10, 19, 39, 55, 50, 46, 57, 50, 37, 30, 16, -3, + -34, -22, 34, 65, 40, 13, -2, 6, 19, 12, 21, 5, -23, -49, -52, -38, + -33, -36, -24, -9, 10, 12, 25, 23, -11, -29, -43, -27, -21, -55, -73, -77, + -50, -2, 19, 19, 35, 59, 59, 49, 45, 40, 36, 27, 4, -10, -24, -12, + 31, 59, 44, 22, -5, 4, 19, 20, 12, -4, -27, -52, -50, -45, -39, -24, + -23, -13, 16, 20, 30, 15, -16, -28, -37, -30, -36, -64, -79, -73, -28, 17, + 24, 14, 36, 65, 68, 45, 33, 39, 40, 22, -2, -5, -11, -11, 28, 58, + 57, 20, -13, 0, 27, 23, 1, -15, -35, -58, -55, -52, -39, -20, -22, -9, + 20, 29, 30, 10, -15, -31, -39, -32, -48, -72, -86, -59, -4, 27, 19, 17, + 44, 77, 69, 31, 26, 40, 38, 14, -6, 0, 1, -11, 26, 67, 62, 10, + -18, 6, 31, 20, -5, -22, -44, -66, -61, -50, -31, -17, -24, -7, 24, 34, + 31, 3, -17, -31, -36, -40, -61, -73, -76, -46, 11, 34, 20, 22, 56, 83, + 60, 22, 24, 46, 32, 5, -4, 9, 0, -8, 31, 73, 53, 0, -13, 16, + 28, 14, -15, -31, -51, -74, -64, -43, -25, -22, -25, -1, 30, 37, 20, -2, + -20, -36, -39, -55, -69, -75, -69, -32, 21, 36, 22, 31, 63, 76, 50, 22, + 25, 49, 29, 3, 4, 9, 2, 0, 43, 74, 37, -8, -1, 28, 24, 8, + -22, -42, -65, -80, -60, -31, -25, -31, -24, 8, 41, 37, 10, -3, -22, -40, + -45, -60, -69, -69, -55, -15, 32, 37, 25, 42, 72, 70, 37, 21, 32, 41, + 20, 5, 15, 8, 0, 9, 46, 62, 26, -7, 8, 28, 21, 4, -29, -53, + -79, -82, -57, -25, -27, -32, -21, 14, 48, 35, -1, -7, -24, -44, -52, -70, + -69, -60, -38, 1, 34, 33, 32, 57, 70, 58, 34, 26, 31, 31, 16, 14, + 14, 3, 8, 25, 47, 47, 18, -2, 13, 25, 19, -2, -33, -64, -87, -83, + -53, -24, -29, -32, -17, 21, 46, 27, -4, -12, -30, -51, -61, -73, -60, -46, + -17, 9, 25, 32, 47, 69, 61, 48, 41, 30, 26, 24, 18, 24, 15, 2, + 14, 37, 42, 34, 17, 9, 19, 20, 11, -7, -35, -79, -97, -79, -45, -21, + -29, -33, -12, 26, 43, 27, -3, -15, -43, -58, -66, -69, -52, -37, -2, 16, + 24, 38, 61, 72, 56, 43, 41, 32, 28, 22, 22, 26, 12, 1, 23, 45, + 34, 21, 8, 17, 22, 19, 4, -18, -47, -93, -97, -70, -40, -29, -33, -22, + -5, 24, 44, 19, -6, -23, -53, -60, -74, -63, -41, -20, 10, 18, 19, 40, + 70, 70, 47, 41, 43, 37, 27, 14, 24, 32, 10, 1, 29, 44, 27, 12, + 7, 28, 32, 9, -11, -27, -56, -100, -94, -64, -43, -38, -31, -7, 0, 27, + 41, 11, -7, -35, -60, -62, -75, -54, -29, -5, 17, 22, 14, 46, 80, 72, + 46, 42, 44, 42, 24, 16, 31, 32, 9, 4, 33, 45, 22, 5, 8, 41, + 34, 0, -22, -36, -69, -100, -92, -65, -40, -44, -25, 0, 5, 28, 36, 4, + -12, -50, -64, -64, -68, -46, -19, 2, 25, 28, 19, 44, 72, 67, 46, 45, + 44, 39, 21, 21, 38, 29, 1, 9, 39, 39, 13, -4, 9, 54, 41, -11, + -38, -51, -76, -91, -92, -65, -44, -47, -17, 12, 11, 21, 27, 6, -24, -59, + -65, -67, -61, -40, -17, 8, 31, 26, 20, 49, 74, 65, 45, 48, 47, 36, + 25, 28, 36, 25, 5, 19, 42, 28, 6, -2, 21, 56, 27, -22, -45, -62, + -83, -92, -84, -65, -49, -37, -8, 15, 16, 22, 23, -1, -38, -65, -66, -65, + -51, -35, -15, 20, 42, 26, 25, 51, 70, 60, 45, 52, 47, 25, 25, 39, + 33, 24, 16, 31, 37, 14, 3, 2, 33, 55, 14, -35, -55, -67, -84, -88, + -84, -68, -47, -28, -1, 17, 22, 24, 17, -14, -54, -66, -64, -61, -46, -32, + -10, 26, 45, 24, 29, 52, 66, 57, 49, 56, 41, 16, 29, 46, 31, 22, + 24, 37, 30, 12, -1, 5, 40, 39, 1, -41, -63, -72, -89, -89, -77, -62, + -48, -17, 5, 13, 26, 31, 10, -29, -62, -64, -65, -54, -41, -25, -4, 32, + 52, 29, 32, 55, 61, 55, 56, 57, 35, 17, 33, 40, 28, 27, 37, 36, + 26, 14, -3, 13, 41, 22, -13, -45, -65, -78, -90, -87, -70, -56, -47, -12, + 9, 18, 35, 27, -5, -41, -63, -61, -65, -52, -37, -17, 5, 35, 52, 34, + 38, 55, 58, 53, 60, 54, 31, 21, 33, 34, 30, 35, 40, 32, 29, 15, + -4, 18, 30, 11, -25, -53, -69, -85, -91, -82, -66, -54, -36, -7, 6, 20, + 40, 19, -17, -52, -63, -60, -65, -50, -32, -11, 9, 34, 50, 40, 46, 51, + 56, 60, 60, 50, 28, 23, 33, 33, 31, 40, 43, 38, 38, 13, -6, 13, + 19, -2, -34, -57, -78, -91, -85, -73, -63, -55, -28, -1, 6, 26, 39, 13, + -28, -56, -61, -55, -61, -43, -27, -13, 12, 38, 48, 49, 54, 46, 52, 64, + 64, 48, 27, 22, 28, 33, 36, 44, 42, 39, 44, 15, -3, 10, 6, -19, + -46, -60, -81, -92, -83, -73, -52, -44, -22, -5, 5, 38, 37, -6, -41, -55, + -54, -49, -53, -45, -28, -9, 19, 41, 47, 56, 57, 41, 56, 69, 64, 42, + 26, 23, 27, 36, 39, 44, 39, 48, 53, 12, -4, 2, -8, -33, -61, -72, + -84, -87, -80, -73, -49, -36, -12, -5, 9, 42, 24, -15, -44, -50, -51, -51, + -51, -45, -26, -4, 20, 40, 47, 64, 58, 38, 61, 71, 55, 37, 32, 23, + 30, 34, 39, 50, 43, 58, 53, 9, 4, -3, -27, -49, -71, -79, -79, -79, + -82, -70, -44, -26, -7, -5, 16, 36, 9, -18, -40, -47, -49, -45, -42, -43, + -20, 1, 21, 40, 53, 72, 54, 36, 64, 66, 41, 30, 36, 26, 28, 31, + 44, 57, 48, 62, 45, 13, 3, -14, -47, -65, -77, -87, -78, -71, -75, -68, + -43, -16, -2, -1, 18, 20, -4, -18, -37, -46, -50, -36, -39, -46, -15, 7, + 23, 41, 62, 72, 49, 41, 69, 59, 33, 29, 38, 24, 28, 31, 52, 59, + 49, 61, 45, 21, 2, -31, -64, -73, -78, -89, -79, -71, -77, -62, -36, -8, + 3, 5, 15, 5, -10, -17, -34, -49, -50, -27, -37, -43, -12, 14, 25, 45, + 67, 68, 48, 48, 64, 48, 27, 33, 41, 25, 24, 32, 64, 66, 51, 62, + 41, 21, -7, -43, -77, -81, -83, -87, -74, -71, -77, -54, -29, -1, 7, 13, + 12, -6, -9, -18, -38, -54, -44, -21, -37, -41, -8, 16, 28, 53, 73, 61, + 46, 52, 60, 35, 25, 34, 38, 20, 25, 42, 73, 62, 60, 58, 39, 22, + -19, -54, -85, -88, -95, -88, -65, -69, -73, -47, -22, 3, 14, 15, -5, -14, + -6, -23, -42, -52, -34, -19, -42, -38, 0, 18, 30, 62, 76, 61, 49, 52, + 49, 26, 23, 34, 33, 22, 21, 50, 78, 68, 66, 47, 40, 22, -23, -66, + -95, -102, -97, -74, -61, -77, -68, -36, -12, 9, 15, 13, -18, -14, -5, -31, + -50, -44, -21, -25, -49, -25, 8, 16, 30, 70, 82, 56, 45, 55, 39, 21, + 25, 31, 24, 21, 28, 64, 81, 68, 64, 47, 44, 15, -30, -77, -101, -104, + -96, -71, -66, -76, -53, -22, -9, 6, 22, 10, -22, -15, -13, -38, -48, -32, + -9, -33, -49, -14, 10, 11, 37, 77, 85, 51, 44, 48, 30, 18, 21, 26, + 16, 21, 36, 71, 76, 73, 68, 48, 35, 4, -38, -81, -103, -109, -91, -67, + -71, -69, -40, -15, -12, 3, 23, 7, -23, -17, -24, -41, -45, -24, -11, -46, + -46, -1, 10, 8, 49, 84, 83, 48, 50, 48, 27, 16, 18, 20, 14, 26, + 44, 72, 75, 82, 71, 47, 26, -6, -45, -80, -107, -110, -88, -70, -69, -58, + -28, -9, -12, 2, 23, 2, -21, -19, -35, -38, -33, -13, -17, -50, -35, 8, + 9, 10, 57, 89, 74, 45, 52, 41, 24, 15, 11, 14, 13, 22, 54, 72, + 74, 86, 72, 41, 13, -14, -47, -86, -113, -111, -88, -72, -67, -42, -18, -11, + -11, 2, 18, -2, -17, -27, -44, -37, -28, -12, -26, -49, -22, 9, 3, 21, + 69, 87, 63, 46, 49, 36, 24, 13, 11, 11, 8, 26, 64, 68, 76, 89, + 74, 38, 3, -17, -44, -86, -117, -114, -86, -65, -58, -38, -19, -7, 0, 8, + 9, -5, -20, -37, -45, -29, -19, -15, -36, -39, -10, 6, 4, 33, 79, 81, + 55, 48, 42, 30, 23, 10, 13, 10, 3, 27, 62, 60, 76, 88, 68, 30, + -5, -21, -49, -89, -120, -115, -81, -54, -46, -34, -14, -1, 7, 9, 1, -6, + -18, -45, -52, -29, -16, -17, -35, -36, -12, 5, 11, 47, 81, 72, 53, 51, + 39, 28, 24, 9, 13, 7, 5, 36, 57, 55, 82, 90, 62, 31, -10, -29, + -55, -91, -121, -115, -76, -47, -38, -34, -13, 1, 13, 9, -4, -9, -17, -49, + -56, -26, -9, -12, -33, -40, -17, 12, 25, 57, 71, 62, 52, 50, 35, 22, + 21, 14, 11, -2, 10, 41, 50, 48, 85, 87, 66, 29, -15, -34, -64, -97, + -121, -108, -73, -43, -37, -28, -7, 7, 16, 6, -7, -5, -15, -59, -56, -19, + -4, -14, -37, -42, -10, 21, 38, 66, 63, 57, 52, 49, 28, 22, 28, 16, + 5, -3, 22, 47, 38, 45, 79, 85, 68, 23, -16, -34, -70, -100, -122, -107, + -62, -39, -38, -25, -4, 15, 18, 2, -3, 0, -27, -70, -51, -17, -3, -16, + -44, -40, -1, 27, 45, 67, 57, 54, 48, 39, 17, 18, 28, 17, 3, -3, + 27, 49, 37, 42, 69, 86, 66, 16, -17, -37, -72, -99, -117, -101, -55, -39, + -36, -24, 1, 20, 13, 4, 4, -5, -46, -74, -43, -9, -4, -28, -49, -33, + 6, 33, 63, 68, 54, 53, 49, 33, 18, 21, 24, 15, 7, 9, 33, 42, + 35, 39, 70, 85, 55, 10, -16, -40, -75, -98, -113, -92, -47, -38, -35, -21, + 1, 21, 15, 8, 7, -14, -62, -70, -30, -11, -15, -34, -49, -23, 9, 39, + 64, 58, 51, 56, 42, 20, 16, 19, 16, 16, 4, 13, 40, 46, 33, 31, + 65, 83, 49, 3, -24, -41, -73, -98, -105, -77, -45, -41, -30, -13, 7, 19, + 12, 13, 8, -26, -68, -61, -22, -14, -25, -38, -40, -18, 12, 47, 68, 59, + 49, 51, 42, 19, 17, 17, 12, 13, 5, 18, 41, 47, 26, 26, 67, 78, + 44, -2, -31, -47, -71, -97, -96, -67, -44, -42, -29, -11, 13, 21, 13, 17, + 8, -34, -68, -54, -17, -18, -36, -43, -35, -12, 14, 50, 69, 56, 49, 44, + 35, 16, 13, 17, 13, 13, 6, 27, 46, 50, 24, 28, 66, 64, 28, 0, + -25, -49, -75, -99, -87, -54, -42, -38, -28, -8, 20, 19, 11, 17, 1, -41, + -62, -49, -18, -27, -41, -39, -29, -8, 15, 55, 73, 55, 42, 42, 33, 16, + 12, 12, 9, 6, 14, 40, 52, 48, 21, 31, 60, 50, 23, 0, -32, -60, + -76, -90, -73, -44, -39, -36, -32, 1, 29, 20, 6, 13, -3, -41, -53, -43, + -21, -34, -47, -38, -22, -2, 22, 54, 65, 49, 38, 42, 32, 17, 12, 7, + 6, 3, 21, 48, 53, 42, 24, 39, 53, 38, 15, -3, -38, -65, -76, -85, + -59, -36, -35, -40, -26, 15, 26, 12, 6, 10, -12, -40, -49, -33, -26, -41, + -53, -36, -12, 5, 28, 50, 61, 46, 34, 37, 31, 20, 12, 1, 0, 5, + 32, 53, 56, 41, 23, 39, 48, 35, 13, -10, -44, -72, -81, -79, -50, -27, + -34, -41, -18, 20, 27, 12, 5, 1, -19, -36, -40, -22, -34, -50, -55, -33, + -3, 14, 33, 52, 54, 35, 27, 36, 37, 25, 7, -13, 1, 19, 41, 50, + 50, 38, 32, 43, 41, 32, 6, -17, -46, -69, -79, -75, -43, -20, -34, -38, + -8, 23, 26, 12, 6, -8, -23, -30, -30, -23, -46, -56, -52, -29, 6, 23, + 35, 44, 47, 31, 25, 33, 40, 26, -4, -22, 3, 28, 39, 40, 50, 40, + 28, 34, 37, 28, 0, -22, -50, -70, -81, -72, -34, -22, -36, -33, 2, 24, + 25, 12, 4, -15, -24, -26, -25, -23, -46, -56, -50, -24, 10, 33, 36, 40, + 35, 21, 25, 43, 47, 25, -13, -25, 11, 40, 36, 40, 56, 38, 27, 31, + 33, 24, -4, -24, -53, -71, -80, -59, -34, -27, -31, -27, 8, 24, 25, 17, + 2, -22, -25, -26, -19, -24, -51, -58, -40, -9, 14, 37, 36, 35, 27, 14, + 28, 48, 46, 19, -19, -24, 18, 40, 29, 41, 50, 29, 29, 27, 33, 18, + -12, -29, -53, -71, -75, -48, -33, -32, -25, -14, 13, 24, 19, 17, 2, -25, + -28, -28, -18, -28, -55, -59, -30, -3, 20, 41, 34, 24, 15, 15, 36, 49, + 39, 17, -17, -17, 22, 41, 33, 45, 38, 26, 30, 24, 27, 10, -11, -34, + -58, -70, -66, -38, -32, -36, -21, -2, 14, 28, 19, 14, 0, -25, -29, -28, + -17, -30, -57, -51, -22, 3, 23, 39, 34, 15, 11, 17, 38, 46, 39, 15, + -18, -14, 27, 40, 37, 45, 32, 28, 30, 29, 28, 1, -16, -38, -55, -65, + -62, -37, -31, -34, -17, 9, 18, 27, 18, 9, -1, -22, -35, -29, -17, -32, + -57, -45, -17, 15, 30, 30, 25, 8, 10, 19, 35, 46, 37, 4, -19, -8, + 31, 33, 33, 42, 28, 22, 24, 29, 23, -6, -21, -43, -54, -59, -55, -32, + -34, -39, -10, 19, 30, 25, 9, 2, -2, -20, -38, -30, -23, -41, -51, -35, + -12, 24, 32, 22, 12, 8, 16, 23, 32, 48, 33, 1, -16, 0, 29, 30, + 33, 36, 24, 23, 22, 33, 14, -14, -20, -42, -55, -50, -44, -27, -38, -41, + -3, 31, 35, 23, 5, -2, -4, -15, -34, -33, -38, -47, -40, -26, -3, 31, + 31, 9, 2, 13, 14, 20, 38, 53, 27, -6, -14, 11, 30, 23, 32, 28, + 25, 22, 24, 32, 5, -20, -26, -45, -49, -40, -36, -37, -48, -40, 8, 40, + 37, 16, -3, -6, -2, -9, -27, -42, -52, -48, -32, -21, 8, 39, 28, -2, + -5, 13, 17, 23, 40, 45, 19, -4, -3, 18, 15, 19, 33, 30, 29, 22, + 21, 22, 0, -17, -27, -46, -48, -33, -31, -38, -53, -33, 23, 43, 31, 11, + -7, -5, -3, -8, -26, -49, -59, -48, -25, -14, 15, 41, 23, -8, -6, 11, + 10, 26, 49, 41, 12, 0, 10, 19, 4, 22, 31, 25, 25, 24, 20, 12, + -4, -10, -37, -50, -37, -23, -26, -43, -55, -18, 34, 41, 28, 10, -9, -6, + -3, -8, -27, -57, -62, -37, -15, -8, 24, 44, 23, -10, -6, 3, 8, 39, + 55, 30, 12, 11, 20, 8, 3, 27, 26, 20, 21, 24, 19, -1, -10, -14, + -42, -47, -25, -14, -28, -49, -50, -5, 38, 38, 23, 9, -11, -9, -1, -5, + -33, -64, -59, -34, -14, -2, 32, 49, 17, -11, -6, -2, 11, 46, 46, 19, + 16, 23, 24, -3, 3, 29, 29, 16, 17, 22, 11, -12, -12, -18, -50, -43, + -15, -11, -30, -53, -38, 10, 31, 31, 25, 3, -16, -3, 3, -8, -41, -67, + -53, -24, -14, 3, 35, 46, 17, -2, -7, -9, 16, 49, 41, 20, 22, 34, + 21, -5, 5, 31, 29, 12, 14, 18, 8, -22, -17, -20, -52, -38, -13, -19, + -32, -48, -25, 11, 23, 29, 26, 1, -14, 1, 1, -18, -47, -60, -47, -31, + -11, 13, 45, 39, 8, -2, -2, -11, 16, 43, 35, 25, 34, 40, 18, -7, + 6, 34, 28, 14, 7, 11, 2, -23, -25, -29, -51, -30, -11, -24, -38, -40, + -15, 9, 18, 29, 32, -1, -10, 0, -9, -27, -48, -52, -46, -30, -2, 27, + 47, 30, 10, 7, -6, -15, 12, 35, 28, 30, 45, 42, 19, -4, 11, 29, + 21, 6, 1, 3, -3, -27, -31, -34, -40, -22, -18, -31, -35, -30, -18, 5, + 19, 32, 28, -9, -7, 1, -14, -30, -42, -45, -47, -28, 7, 38, 45, 23, + 14, 20, -2, -24, 7, 32, 30, 37, 43, 41, 22, 7, 18, 22, 14, 4, + -7, 4, -7, -36, -37, -37, -27, -15, -26, -34, -34, -29, -18, 4, 19, 31, + 20, -4, 0, -3, -21, -32, -37, -41, -40, -25, 14, 49, 44, 18, 19, 25, + -1, -19, 5, 26, 35, 38, 46, 41, 18, 18, 16, 13, 12, 2, -5, -3, + -23, -44, -37, -32, -20, -20, -33, -28, -32, -32, -16, 1, 17, 31, 17, -2, + 2, -3, -22, -33, -39, -40, -34, -23, 15, 56, 44, 15, 27, 23, -4, -14, + 2, 22, 38, 37, 48, 40, 25, 24, 15, 11, 2, -2, -3, -15, -31, -40, + -37, -33, -17, -17, -28, -29, -41, -34, -7, 1, 13, 31, 17, -2, 4, 1, + -20, -35, -47, -37, -24, -10, 22, 52, 38, 26, 35, 26, -2, -9, 4, 23, + 40, 38, 46, 39, 32, 31, 16, 2, -7, -8, -2, -21, -38, -44, -38, -31, + -18, -15, -29, -35, -45, -32, -1, -3, 4, 30, 16, 3, 8, 4, -20, -42, + -48, -30, -17, -8, 21, 49, 41, 30, 38, 23, -2, -5, 1, 21, 35, 37, + 44, 40, 40, 33, 17, 1, -13, -10, -9, -35, -41, -41, -39, -33, -19, -12, + -27, -40, -48, -28, -4, -10, 10, 28, 15, 9, 12, 5, -24, -43, -43, -23, + -18, 0, 26, 47, 43, 35, 40, 20, -1, 1, 4, 20, 28, 37, 42, 42, + 46, 31, 22, 8, -17, -15, -15, -42, -41, -37, -44, -37, -16, -13, -33, -41, + -41, -20, -11, -17, 10, 18, 13, 16, 17, 1, -24, -38, -38, -27, -21, 9, + 29, 46, 44, 43, 38, 18, 3, 6, 6, 12, 19, 38, 41, 47, 44, 28, + 29, 11, -26, -25, -27, -45, -39, -39, -48, -41, -18, -13, -33, -38, -36, -21, + -19, -14, 13, 11, 11, 26, 17, -6, -25, -32, -32, -35, -14, 21, 31, 38, + 49, 49, 34, 19, 13, 10, 4, 9, 20, 37, 41, 45, 39, 29, 35, 6, + -28, -28, -35, -43, -37, -42, -50, -44, -20, -20, -37, -37, -27, -16, -23, -11, + 10, 5, 17, 36, 16, -16, -23, -21, -33, -38, -5, 23, 28, 35, 55, 55, + 31, 17, 18, 12, 3, 4, 21, 33, 41, 45, 31, 32, 39, 3, -29, -35, + -41, -40, -38, -45, -55, -45, -26, -31, -36, -26, -22, -22, -29, 1, 9, -1, + 24, 39, 8, -19, -17, -14, -32, -34, 5, 29, 29, 35, 58, 51, 32, 29, + 23, 11, 1, 6, 29, 37, 38, 36, 24, 43, 39, -2, -32, -44, -45, -36, + -36, -45, -55, -51, -37, -35, -30, -22, -20, -32, -24, 6, 2, 3, 30, 36, + 3, -17, -16, -18, -29, -24, 10, 31, 25, 34, 58, 44, 33, 37, 26, 8, + 5, 10, 37, 36, 35, 29, 22, 47, 36, -6, -36, -51, -49, -34, -38, -48, + -58, -53, -46, -42, -24, -23, -22, -32, -13, 4, -7, 8, 35, 30, 6, -14, + -20, -19, -21, -20, 14, 34, 29, 43, 52, 37, 39, 43, 24, 8, 7, 15, + 45, 33, 36, 24, 25, 43, 25, -10, -39, -53, -47, -34, -39, -53, -56, -54, + -56, -42, -21, -23, -29, -25, -5, 1, -10, 12, 35, 27, 7, -14, -25, -19, + -11, -10, 13, 31, 37, 44, 42, 37, 45, 44, 24, 14, 13, 24, 40, 28, + 35, 23, 31, 35, 15, -16, -38, -53, -45, -37, -48, -56, -54, -63, -63, -40, + -23, -24, -27, -19, 3, 1, -11, 14, 33, 24, 5, -16, -28, -17, -6, -1, + 15, 38, 39, 38, 29, 36, 54, 42, 20, 20, 19, 32, 38, 30, 31, 23, + 33, 23, -1, -17, -35, -44, -43, -47, -51, -51, -56, -71, -67, -45, -28, -23, + -23, -13, 12, -1, -15, 15, 33, 20, -2, -22, -25, -17, -3, 10, 24, 46, + 44, 31, 26, 41, 53, 42, 23, 23, 26, 39, 37, 32, 24, 28, 36, 11, + -7, -19, -38, -39, -37, -49, -54, -51, -62, -76, -68, -51, -28, -19, -21, 1, + 22, -3, -11, 14, 25, 16, -5, -25, -25, -15, -2, 20, 36, 51, 42, 19, + 19, 43, 58, 43, 25, 21, 35, 46, 41, 34, 17, 26, 33, 5, -15, -25, + -39, -34, -37, -55, -50, -49, -69, -80, -67, -50, -31, -18, -12, 12, 17, -5, + -5, 14, 17, 6, -15, -27, -22, -14, 3, 37, 49, 48, 40, 22, 22, 36, + 51, 44, 29, 22, 42, 49, 41, 29, 16, 29, 31, -9, -30, -33, -35, -29, + -38, -55, -45, -54, -79, -80, -65, -51, -34, -16, -2, 18, 18, 5, 7, 8, + 6, 3, -19, -21, -22, -19, 12, 51, 53, 48, 39, 22, 18, 36, 46, 42, + 35, 31, 44, 46, 42, 31, 24, 35, 21, -25, -39, -33, -30, -24, -41, -53, + -47, -60, -81, -81, -63, -53, -40, -14, 6, 24, 20, 8, 7, 0, -1, -4, + -21, -23, -29, -16, 30, 60, 55, 50, 37, 19, 19, 35, 43, 46, 37, 29, + 43, 49, 43, 32, 27, 31, 13, -35, -46, -36, -26, -28, -44, -52, -47, -65, + -84, -84, -68, -49, -27, 0, 10, 15, 19, 15, 9, -3, -10, -16, -20, -26, + -28, -2, 41, 59, 62, 56, 37, 16, 15, 31, 43, 50, 42, 30, 41, 49, + 49, 38, 28, 23, 5, -42, -55, -42, -21, -22, -40, -49, -54, -71, -86, -81, + -62, -44, -21, 5, 17, 16, 25, 23, 0, -13, -17, -17, -24, -32, -21, 15, + 45, 58, 66, 52, 33, 15, 9, 35, 42, 44, 44, 36, 38, 50, 52, 40, + 28, 16, -11, -48, -60, -43, -22, -21, -40, -53, -58, -78, -90, -79, -61, -42, + -9, 14, 15, 16, 22, 21, -4, -20, -21, -19, -30, -31, -10, 26, 54, 63, + 69, 51, 33, 12, 13, 40, 42, 45, 42, 33, 36, 53, 57, 44, 24, 3, + -24, -53, -63, -45, -21, -15, -39, -57, -63, -78, -89, -76, -55, -34, 3, 18, + 9, 16, 21, 15, -8, -26, -28, -25, -32, -24, 4, 34, 56, 67, 75, 48, + 22, 7, 23, 44, 39, 40, 40, 35, 40, 59, 59, 44, 18, -6, -31, -54, + -58, -44, -20, -13, -43, -63, -69, -80, -88, -71, -48, -21, 12, 16, 12, 18, + 13, 6, -12, -27, -32, -30, -34, -20, 13, 46, 63, 74, 73, 40, 15, 13, + 39, 46, 33, 32, 35, 36, 48, 58, 61, 43, 16, -13, -36, -57, -62, -41, + -22, -16, -42, -66, -73, -79, -85, -65, -38, -7, 13, 9, 7, 16, 11, -2, + -18, -36, -39, -26, -25, -16, 21, 53, 64, 74, 68, 36, 19, 22, 38, 44, + 32, 28, 32, 38, 52, 60, 56, 43, 13, -25, -39, -54, -52, -35, -30, -27, + -46, -70, -79, -80, -79, -58, -26, 3, 15, 6, 0, 12, 6, -8, -27, -45, + -39, -17, -16, -13, 28, 57, 67, 71, 57, 37, 22, 25, 41, 46, 29, 24, + 34, 44, 56, 55, 52, 44, 7, -27, -38, -48, -44, -35, -31, -29, -46, -77, + -83, -73, -70, -48, -15, 6, 9, 1, 1, 9, -3, -20, -41, -48, -30, -5, + -14, -9, 39, 63, 70, 66, 47, 36, 25, 32, 40, 43, 26, 21, 36, 47, + 59, 50, 49, 35, 0, -26, -36, -44, -41, -36, -35, -33, -50, -79, -79, -66, + -63, -36, -8, 6, -3, -9, 2, 3, -13, -30, -49, -46, -18, -2, -15, 4, + 42, 58, 65, 61, 50, 38, 28, 37, 40, 38, 28, 30, 38, 48, 50, 42, + 46, 28, -3, -28, -37, -36, -36, -39, -36, -37, -59, -79, -69, -62, -52, -24, + -2, 3, -12, -11, 4, -5, -29, -42, -53, -39, -12, -4, -4, 14, 37, 52, + 63, 58, 50, 37, 34, 37, 36, 37, 38, 36, 35, 47, 46, 44, 42, 18, + -7, -30, -34, -32, -34, -41, -37, -45, -66, -74, -64, -57, -36, -12, 1, -8, + -23, -7, 6, -18, -39, -49, -53, -29, -5, -1, 10, 19, 30, 46, 59, 58, + 50, 36, 37, 37, 32, 40, 46, 38, 34, 44, 42, 41, 36, 9, -9, -27, + -29, -26, -34, -40, -40, -56, -69, -66, -56, -46, -22, -7, -7, -19, -21, 3, + 1, -35, -48, -53, -49, -22, -3, 12, 23, 18, 22, 46, 66, 59, 47, 38, + 43, 35, 30, 46, 51, 39, 33, 41, 37, 42, 24, 2, -8, -22, -23, -24, + -33, -39, -50, -66, -69, -59, -49, -31, -13, -10, -17, -25, -16, 1, -17, -50, + -55, -58, -42, -17, -1, 20, 31, 14, 15, 48, 70, 59, 42, 38, 45, 33, + 33, 51, 53, 36, 35, 37, 36, 37, 12, 0, -9, -16, -18, -22, -33, -42, + -59, -67, -62, -52, -40, -20, -11, -15, -23, -23, -11, -3, -28, -51, -59, -61, + -38, -14, 4, 26, 30, 10, 18, 53, 71, 56, 40, 42, 45, 32, 34, 53, + 52, 37, 36, 32, 37, 32, 10, -3, -10, -10, -11, -17, -31, -46, -62, -63, + -54, -44, -30, -14, -14, -23, -27, -22, -11, -11, -35, -51, -65, -59, -32, -11, + 11, 29, 25, 8, 24, 63, 73, 51, 38, 46, 44, 29, 34, 51, 51, 39, + 34, 27, 34, 23, 3, -5, -9, -6, -10, -18, -33, -51, -66, -60, -50, -35, + -20, -10, -21, -33, -29, -17, -9, -20, -39, -55, -71, -57, -26, -7, 11, 23, + 22, 11, 35, 70, 71, 46, 39, 48, 42, 29, 33, 51, 47, 38, 31, 28, + 35, 17, 0, -12, -7, 0, -4, -15, -36, -56, -67, -56, -42, -26, -15, -12, + -29, -36, -28, -15, -13, -25, -40, -58, -70, -49, -23, -6, 8, 19, 17, 18, + 49, 76, 66, 40, 42, 49, 39, 25, 35, 51, 43, 40, 30, 31, 32, 15, + -1, -14, -7, 1, -2, -17, -40, -59, -61, -51, -38, -21, -10, -17, -34, -35, + -28, -18, -17, -24, -40, -64, -65, -40, -18, -8, 5, 13, 17, 31, 61, 75, + 60, 41, 43, 47, 34, 20, 36, 47, 43, 41, 31, 32, 26, 7, -7, -16, + -6, 0, -3, -22, -44, -60, -56, -47, -34, -19, -8, -20, -39, -40, -27, -18, + -20, -29, -44, -63, -56, -38, -23, -11, 4, 14, 21, 42, 65, 71, 59, 45, + 42, 34, 21, 20, 42, 48, 44, 41, 31, 34, 24, 6, -10, -20, -11, 4, + 0, -20, -48, -57, -47, -39, -30, -17, -4, -24, -43, -40, -26, -19, -24, -29, + -45, -59, -51, -37, -25, -14, 3, 15, 27, 51, 72, 76, 61, 44, 38, 23, + 12, 21, 43, 46, 45, 40, 31, 35, 21, 5, -17, -22, -13, 3, 1, -24, + -51, -52, -43, -37, -28, -8, -7, -38, -46, -36, -21, -21, -31, -33, -45, -51, + -47, -40, -30, -13, 4, 14, 33, 60, 76, 76, 61, 47, 30, 16, 8, 20, + 40, 45, 48, 37, 37, 37, 22, 3, -19, -20, -10, 4, -6, -30, -49, -44, + -41, -38, -23, -1, -14, -41, -44, -36, -22, -26, -35, -33, -45, -52, -48, -40, + -32, -9, 6, 18, 35, 65, 85, 80, 62, 46, 24, 6, -1, 23, 41, 48, + 45, 31, 42, 40, 23, -6, -21, -15, -6, 0, -13, -31, -44, -41, -38, -32, + -15, 0, -22, -40, -41, -36, -24, -31, -28, -32, -46, -49, -47, -43, -30, -6, + 9, 19, 46, 77, 87, 77, 61, 42, 18, -2, -7, 22, 39, 51, 41, 32, + 43, 35, 13, -18, -18, -10, -5, -8, -21, -29, -39, -42, -41, -23, -3, -3, + -32, -39, -38, -34, -31, -35, -23, -32, -46, -50, -51, -46, -26, 0, 12, 20, + 54, 87, 91, 72, 60, 38, 13, -10, -11, 24, 44, 52, 43, 39, 45, 34, + 2, -19, -8, -1, -8, -19, -19, -25, -35, -42, -39, -17, 7, -7, -38, -36, + -36, -37, -37, -31, -20, -34, -49, -53, -50, -43, -19, 6, 10, 25, 66, 91, + 84, 67, 60, 36, 1, -18, -10, 27, 48, 52, 42, 42, 38, 25, -3, -18, + -5, -2, -13, -22, -24, -28, -35, -45, -35, -4, 14, -17, -41, -36, -33, -35, + -41, -29, -20, -38, -51, -54, -46, -33, -14, 6, 14, 37, 74, 87, 76, 65, + 64, 29, -9, -22, -7, 23, 52, 55, 46, 42, 25, 17, -5, -12, -4, -3, + -17, -25, -33, -36, -33, -39, -30, 5, 12, -25, -37, -33, -34, -42, -41, -25, + -22, -41, -52, -53, -40, -25, -10, 11, 21, 43, 72, 78, 74, 69, 58, 15, + -13, -15, -4, 22, 54, 58, 53, 41, 15, 6, -2, -1, -3, -6, -18, -24, + -42, -40, -29, -32, -20, 13, 8, -25, -35, -34, -29, -42, -43, -27, -27, -42, + -51, -50, -30, -14, -5, 17, 26, 46, 70, 72, 72, 69, 48, 2, -13, -9, + -3, 19, 55, 59, 53, 30, 1, -1, 5, 8, -7, -15, -19, -25, -48, -45, + -31, -28, -10, 15, 1, -24, -35, -35, -22, -37, -43, -36, -35, -41, -47, -45, + -18, -6, -1, 24, 32, 51, 65, 65, 67, 63, 37, -3, -13, -9, 1, 29, + 54, 60, 50, 18, -4, -4, 13, 9, -10, -15, -17, -30, -54, -47, -29, -20, + -8, 4, -8, -15, -29, -35, -21, -37, -43, -46, -37, -33, -48, -39, -10, 3, + 13, 31, 34, 54, 56, 57, 63, 56, 32, -3, -16, -6, 14, 38, 48, 53, + 40, 11, -3, 1, 6, -2, -11, -9, -11, -28, -54, -54, -29, -8, 2, -8, + -16, -13, -27, -31, -21, -32, -45, -54, -36, -27, -44, -33, 1, 16, 25, 29, + 39, 56, 48, 51, 57, 48, 22, 3, -14, 0, 22, 39, 42, 46, 36, 7, + -7, 0, 0, -3, -8, -8, -15, -34, -50, -49, -27, -3, 0, -15, -14, -16, + -28, -26, -21, -34, -56, -55, -32, -30, -41, -23, 8, 20, 31, 33, 45, 53, + 38, 42, 54, 40, 18, -3, -9, 14, 33, 37, 34, 34, 27, 8, -5, -1, + -9, -3, -1, -8, -19, -35, -43, -42, -28, -7, 1, -18, -13, -17, -29, -24, + -21, -34, -55, -52, -34, -30, -26, -9, 15, 28, 28, 32, 55, 50, 29, 38, + 45, 35, 17, -3, -1, 18, 36, 40, 27, 24, 19, 0, -5, -1, -14, -7, + -2, -12, -20, -30, -40, -42, -25, -5, -5, -24, -14, -16, -25, -20, -26, -38, + -52, -49, -35, -31, -13, 8, 16, 28, 29, 42, 57, 40, 23, 32, 35, 30, + 12, -5, 9, 22, 40, 38, 19, 17, 16, -1, -9, -7, -12, -6, -5, -13, + -18, -29, -39, -39, -18, -3, -19, -26, -11, -18, -24, -19, -30, -40, -51, -45, + -30, -24, 0, 19, 22, 28, 36, 49, 54, 41, 22, 30, 31, 26, 10, 2, + 10, 26, 43, 28, 14, 16, 7, -6, -12, -9, -9, -5, -12, -19, -16, -29, + -35, -34, -8, -8, -35, -20, -7, -26, -23, -23, -30, -39, -53, -38, -25, -12, + 11, 24, 24, 29, 47, 50, 48, 36, 20, 29, 24, 15, 5, 8, 12, 32, + 40, 21, 17, 11, 0, -3, -15, -14, -7, -4, -13, -17, -16, -28, -31, -23, + -6, -20, -37, -15, -12, -29, -22, -28, -30, -38, -54, -34, -20, -4, 21, 33, + 24, 33, 50, 45, 40, 33, 27, 28, 14, 8, 8, 11, 11, 30, 33, 26, + 20, -1, -8, -4, -17, -16, -2, -7, -22, -20, -20, -26, -26, -15, -10, -27, + -35, -12, -19, -31, -21, -23, -23, -42, -57, -31, -11, 9, 35, 33, 23, 39, + 53, 47, 40, 31, 31, 21, 10, 9, 11, 10, 13, 26, 35, 33, 13, -11, + -10, -4, -19, -22, 3, -2, -28, -26, -16, -21, -24, -12, -12, -31, -34, -17, + -27, -34, -25, -17, -19, -48, -59, -29, -2, 27, 46, 26, 22, 43, 54, 44, + 38, 30, 29, 16, 6, 15, 15, 6, 9, 22, 36, 37, 9, -20, -10, -5, + -21, -21, 2, -5, -29, -31, -18, -11, -17, -11, -15, -32, -34, -23, -30, -30, + -25, -15, -22, -52, -50, -17, 9, 36, 42, 26, 29, 50, 53, 40, 33, 32, + 27, 14, 7, 9, 7, 4, 12, 22, 36, 36, 3, -27, -16, -9, -20, -21, + -1, -12, -31, -27, -13, -12, -18, -12, -17, -33, -39, -29, -34, -35, -23, -7, + -25, -55, -42, -10, 20, 43, 40, 27, 33, 51, 51, 37, 34, 31, 21, 9, + 8, 5, 2, 11, 16, 18, 34, 35, 3, -22, -17, -16, -20, -17, -7, -20, + -32, -28, -14, -12, -10, -8, -17, -34, -41, -35, -34, -31, -19, -8, -27, -48, + -29, -4, 26, 50, 44, 32, 37, 50, 49, 40, 36, 22, 11, 11, 12, 5, + 3, 14, 12, 13, 34, 37, 9, -23, -24, -16, -21, -16, -17, -30, -27, -27, + -20, -10, -10, -9, -18, -39, -46, -42, -35, -31, -14, -9, -33, -42, -19, 1, + 36, 55, 41, 32, 46, 55, 47, 35, 32, 18, 6, 7, 9, -2, 7, 17, + 8, 13, 34, 32, 10, -22, -27, -14, -20, -21, -26, -31, -23, -27, -22, -6, + -5, -11, -21, -39, -46, -46, -37, -30, -14, -12, -33, -31, -8, 6, 41, 55, + 40, 38, 54, 57, 39, 30, 33, 17, 2, 1, 4, 7, 14, 14, -2, 11, + 37, 31, 11, -26, -30, -16, -20, -18, -21, -27, -32, -28, -12, 0, -4, -11, + -23, -40, -46, -43, -33, -26, -16, -15, -29, -19, -1, 13, 44, 58, 41, 49, + 68, 59, 36, 28, 36, 18, -9, -9, 4, 17, 20, 7, -6, 18, 36, 22, + -1, -30, -26, -19, -25, -26, -31, -35, -33, -21, -3, -8, -10, -14, -24, -40, + -45, -43, -35, -20, -18, -20, -22, -12, 0, 15, 48, 58, 41, 58, 77, 57, + 30, 27, 33, 7, -23, -16, 11, 23, 21, 2, -5, 24, 33, 10, -10, -24, + -19, -25, -37, -30, -30, -34, -29, -14, -5, -16, -8, -8, -26, -50, -47, -41, + -30, -16, -25, -24, -14, -6, 3, 23, 50, 51, 49, 69, 81, 56, 29, 33, + 30, -2, -29, -14, 15, 26, 18, 2, -1, 31, 28, 0, -20, -21, -21, -32, + -43, -34, -33, -36, -23, -4, -8, -20, -8, -11, -25, -44, -41, -39, -32, -17, + -30, -22, -4, 1, 6, 31, 48, 47, 63, 80, 82, 52, 31, 38, 23, -13, + -33, -11, 20, 29, 14, -1, 9, 34, 19, -12, -26, -13, -23, -46, -46, -38, + -39, -35, -24, -3, -7, -17, -15, -16, -25, -45, -37, -37, -33, -26, -36, -20, + 5, 3, 4, 32, 42, 50, 76, 83, 75, 49, 34, 36, 17, -24, -33, -12, + 23, 32, 10, 1, 23, 30, 7, -17, -22, -8, -27, -49, -50, -42, -38, -28, + -18, -3, -8, -13, -14, -15, -24, -43, -35, -33, -29, -27, -34, -15, 16, 8, + 5, 32, 43, 62, 84, 84, 73, 53, 40, 30, 6, -26, -34, -15, 25, 28, + 8, 9, 38, 27, -4, -26, -21, -12, -33, -54, -47, -48, -38, -21, -14, -2, + -3, -11, -25, -18, -26, -32, -34, -34, -29, -31, -35, -10, 18, 11, 7, 33, + 47, 68, 83, 81, 71, 58, 42, 20, -5, -25, -36, -15, 23, 23, 7, 20, + 40, 21, -14, -35, -21, -16, -40, -58, -52, -52, -31, -11, -9, -6, -1, -15, + -26, -15, -29, -31, -36, -31, -29, -36, -32, -4, 17, 8, 15, 36, 48, 66, + 77, 83, 77, 59, 38, 9, -11, -20, -34, -12, 22, 20, 14, 33, 39, 16, + -22, -36, -23, -21, -40, -56, -52, -47, -24, -10, -4, 3, 1, -17, -22, -18, + -28, -26, -32, -30, -32, -30, -22, 1, 15, 15, 27, 42, 52, 62, 75, 85, + 80, 59, 35, 1, -16, -20, -35, -12, 18, 17, 18, 40, 34, 5, -34, -38, + -27, -28, -42, -60, -58, -48, -18, -4, 0, 3, -4, -18, -20, -22, -35, -29, + -27, -34, -42, -28, -12, 3, 8, 19, 31, 40, 45, 60, 75, 79, 76, 62, + 37, -2, -20, -22, -31, -11, 13, 15, 31, 43, 27, 0, -28, -33, -36, -37, + -43, -58, -61, -47, -13, 1, 1, 3, -5, -12, -17, -25, -36, -27, -25, -39, + -45, -24, 1, 0, 8, 25, 43, 45, 42, 57, 76, 76, 73, 60, 37, -8, + -25, -22, -25, -6, 9, 21, 41, 41, 15, -6, -18, -33, -48, -40, -38, -57, + -64, -46, -6, 9, -4, 1, -1, -9, -18, -28, -33, -24, -27, -42, -45, -18, + 2, 3, 13, 31, 49, 43, 37, 60, 74, 68, 68, 60, 30, -12, -28, -23, + -19, -8, 5, 26, 48, 37, 11, -12, -17, -37, -54, -40, -41, -58, -65, -42, + 5, 12, -8, 0, 2, -6, -22, -29, -30, -28, -37, -44, -42, -9, 6, 7, + 17, 33, 44, 42, 40, 61, 72, 57, 63, 61, 24, -16, -34, -21, -15, -12, + 3, 31, 47, 28, 7, -10, -15, -43, -51, -38, -45, -61, -61, -31, 10, 8, + -3, 6, 5, -8, -24, -27, -28, -31, -44, -42, -29, -3, 6, 10, 24, 40, + 44, 45, 46, 57, 62, 56, 65, 56, 16, -13, -32, -18, -12, -10, 11, 32, + 39, 25, 6, -10, -19, -48, -44, -38, -49, -63, -61, -19, 12, 3, 4, 6, + 3, -9, -25, -26, -27, -38, -46, -39, -18, 1, 12, 20, 29, 33, 36, 49, + 47, 54, 59, 49, 63, 51, 8, -12, -25, -18, -18, -6, 20, 33, 28, 19, + 4, -9, -27, -43, -41, -45, -55, -64, -51, -13, 7, -3, 0, 7, 3, -12, + -28, -27, -33, -46, -51, -33, -10, -5, 15, 31, 34, 26, 32, 47, 51, 53, + 47, 50, 61, 41, 1, -8, -12, -21, -20, 5, 27, 29, 16, 13, 8, -9, + -28, -40, -40, -44, -55, -62, -40, -8, 5, -2, 4, 11, 4, -15, -26, -26, + -37, -49, -47, -27, -8, -3, 22, 45, 38, 22, 34, 47, 55, 52, 39, 44, + 58, 32, 2, 0, -7, -25, -21, 10, 29, 30, 9, 0, 0, -7, -26, -38, + -40, -53, -61, -53, -30, -5, 1, -2, 5, 10, 3, -18, -25, -33, -43, -51, + -46, -20, -10, -8, 26, 52, 35, 19, 32, 47, 56, 46, 33, 44, 48, 20, + 10, 11, -7, -29, -20, 15, 35, 28, 2, -9, -8, -6, -26, -32, -36, -54, + -64, -52, -22, 1, 3, 2, 3, 15, 2, -22, -24, -34, -41, -45, -39, -19, + -9, 1, 35, 57, 37, 18, 27, 46, 52, 41, 37, 44, 40, 18, 16, 13, + -7, -29, -14, 23, 36, 17, -6, -17, -2, 1, -24, -38, -43, -59, -62, -44, + -22, -4, 7, 2, 5, 16, -2, -24, -27, -36, -43, -48, -37, -20, -5, 14, + 40, 52, 36, 20, 26, 43, 46, 40, 41, 42, 28, 19, 19, 9, -4, -21, + -10, 27, 32, 10, -6, -16, -4, -5, -14, -37, -48, -59, -58, -36, -24, -1, + 13, -3, 7, 16, -5, -19, -32, -38, -46, -43, -32, -22, -7, 22, 49, 57, + 37, 22, 20, 37, 41, 36, 46, 41, 21, 19, 16, 9, -2, -25, -9, 27, + 24, 8, -12, -11, -2, -9, -10, -39, -51, -59, -59, -35, -21, 2, 15, -5, + 10, 11, -12, -19, -35, -39, -46, -35, -29, -26, -5, 37, 60, 53, 36, 26, + 19, 33, 37, 33, 48, 41, 18, 17, 19, 11, -8, -23, -3, 30, 21, -5, + -14, -2, -6, -9, -9, -42, -59, -64, -54, -33, -16, 6, 14, 0, 15, 4, + -14, -17, -35, -45, -46, -33, -27, -22, 2, 42, 56, 49, 37, 26, 19, 26, + 23, 36, 58, 44, 11, 8, 23, 10, -7, -15, 3, 26, 12, -10, -8, 3, + -10, -7, -13, -46, -58, -60, -57, -40, -11, 9, 9, 3, 13, -6, -12, -17, + -42, -53, -45, -28, -23, -14, 11, 49, 60, 49, 40, 27, 14, 16, 13, 43, + 62, 46, 6, 8, 22, 7, -9, -10, 11, 23, 4, -17, 2, 6, -6, -7, + -21, -51, -58, -58, -55, -38, -12, 12, 10, 13, 1, -15, -7, -14, -47, -62, + -45, -29, -19, -2, 21, 51, 63, 46, 37, 31, 16, 0, 4, 43, 64, 43, + 6, 9, 24, 4, -15, -2, 14, 9, -9, -15, 14, 7, -11, -10, -29, -53, + -54, -57, -48, -35, -9, 13, 9, 11, -5, -6, -2, -22, -57, -60, -39, -24, + -11, 5, 30, 52, 62, 49, 42, 38, 11, -9, 7, 45, 61, 44, 10, 15, + 21, -4, -15, 3, 13, 1, -13, -9, 13, 7, -9, -13, -32, -51, -53, -56, + -44, -35, -9, 15, 11, 7, -8, 0, -2, -34, -65, -56, -31, -24, -7, 20, + 37, 49, 56, 47, 47, 39, -3, -16, 12, 40, 53, 45, 16, 23, 17, -7, + -8, 7, 8, -5, -12, -7, 7, 7, -4, -17, -38, -56, -60, -50, -37, -33, + -8, 7, 9, 0, -6, 7, -8, -47, -71, -50, -25, -23, 0, 33, 41, 46, + 52, 53, 54, 35, -6, -9, 13, 32, 50, 48, 23, 25, 13, -4, -3, 0, + -1, -7, -7, -8, 3, 6, -3, -22, -41, -55, -62, -46, -30, -24, -5, 0, + 5, 2, 3, 10, -20, -57, -69, -41, -19, -16, 5, 37, 47, 46, 49, 54, + 58, 29, -4, -6, 7, 21, 49, 49, 24, 24, 12, -2, -5, -9, 0, 0, + -10, -15, 2, 8, -4, -23, -42, -57, -66, -43, -22, -16, -11, -8, 3, 5, + 7, 4, -28, -61, -61, -36, -19, -11, 10, 45, 51, 43, 46, 52, 54, 26, + 3, -8, -3, 15, 52, 48, 27, 30, 15, -1, -9, -14, 0, -2, -15, -17, + -2, -1, -5, -23, -37, -62, -64, -34, -17, -15, -19, -8, 4, 7, 8, -8, + -37, -55, -50, -33, -19, -5, 16, 49, 54, 44, 45, 52, 53, 32, 3, -12, + -5, 14, 46, 46, 38, 34, 21, 6, -13, -21, -2, -3, -18, -19, -14, -9, + -2, -14, -44, -74, -56, -26, -15, -16, -18, -6, -1, 7, 6, -20, -43, -48, + -35, -32, -24, 1, 23, 51, 54, 41, 42, 52, 49, 32, 3, -14, -5, 19, + 42, 47, 43, 38, 27, 10, -18, -19, -5, -7, -18, -27, -23, -9, 2, -8, + -51, -75, -41, -19, -15, -13, -15, -11, -5, 10, 1, -30, -37, -40, -30, -33, + -24, 6, 30, 49, 49, 45, 43, 52, 39, 24, 7, -10, -7, 12, 33, 44, + 48, 43, 36, 7, -29, -18, -6, -14, -23, -36, -32, -12, 2, -16, -60, -65, + -27, -22, -22, -9, -6, -14, -6, 11, -10, -38, -35, -27, -26, -35, -15, 18, + 39, 47, 48, 51, 55, 51, 28, 22, 13, -5, -6, 5, 27, 46, 57, 49, + 39, 1, -29, -12, -7, -15, -28, -48, -39, -11, -1, -28, -61, -51, -22, -30, + -22, -3, -4, -21, -6, 8, -23, -45, -29, -18, -27, -32, -11, 24, 44, 40, + 46, 56, 61, 44, 17, 18, 19, 1, -11, -2, 24, 48, 57, 54, 45, 2, + -27, -12, -11, -18, -32, -49, -41, -16, -10, -32, -47, -33, -25, -34, -13, 6, + -5, -24, -13, -4, -29, -43, -29, -18, -25, -21, -1, 25, 44, 40, 49, 67, + 60, 31, 12, 18, 24, -2, -18, -5, 22, 45, 62, 65, 46, -5, -21, -12, + -12, -17, -36, -57, -48, -23, -15, -29, -35, -28, -33, -31, -3, 12, -16, -32, + -12, -19, -36, -33, -25, -22, -29, -10, 14, 30, 41, 35, 51, 73, 57, 27, + 16, 21, 14, -4, -12, -2, 21, 41, 62, 71, 43, -7, -12, -19, -22, -23, + -46, -57, -51, -35, -20, -17, -22, -26, -37, -27, 7, 12, -24, -31, -14, -29, + -34, -30, -22, -20, -21, 2, 15, 26, 40, 45, 55, 66, 52, 28, 20, 17, + 10, -1, -12, -4, 21, 43, 65, 74, 39, 1, -9, -25, -27, -24, -45, -61, + -55, -43, -22, -9, -12, -24, -32, -26, 9, 7, -25, -31, -30, -40, -31, -26, + -19, -20, -11, 14, 18, 27, 45, 54, 52, 61, 49, 33, 24, 15, 5, 0, + -14, -2, 24, 44, 62, 67, 37, 12, -9, -30, -29, -33, -49, -66, -58, -51, + -25, -2, -6, -19, -31, -24, 6, 3, -21, -37, -43, -42, -31, -25, -17, -19, + -5, 15, 19, 30, 52, 56, 45, 54, 52, 38, 22, 11, 8, 0, -16, 2, + 27, 44, 63, 60, 34, 16, -10, -25, -31, -38, -55, -68, -62, -53, -18, 5, + -2, -17, -31, -16, 5, -4, -22, -43, -50, -38, -32, -21, -16, -11, 8, 10, + 19, 32, 60, 60, 43, 46, 51, 37, 24, 13, 8, -6, -17, 4, 32, 52, + 56, 52, 39, 23, -5, -23, -41, -48, -64, -65, -63, -57, -14, 9, 3, -18, + -28, -9, 0, -11, -25, -47, -53, -38, -30, -19, -11, 0, 10, 11, 23, 42, + 66, 60, 42, 49, 53, 36, 24, 20, 9, -17, -18, 3, 39, 59, 49, 41, + 39, 26, 1, -24, -53, -59, -70, -61, -66, -58, -12, 17, 7, -20, -26, -7, + -7, -16, -30, -51, -60, -45, -26, -11, -5, 5, 8, 10, 23, 48, 66, 55, + 40, 48, 48, 33, 30, 25, 2, -21, -15, 10, 41, 51, 44, 37, 41, 27, + 6, -28, -60, -65, -70, -63, -70, -55, -6, 21, 1, -20, -15, -2, -15, -24, + -32, -54, -66, -45, -22, -8, 6, 13, 5, 15, 31, 51, 64, 58, 41, 42, + 44, 35, 36, 29, 0, -20, -9, 14, 43, 53, 46, 39, 39, 24, 7, -33, + -69, -75, -73, -70, -75, -46, 4, 17, -2, -18, -6, 3, -18, -32, -38, -61, + -65, -39, -17, -2, 10, 10, 5, 19, 33, 55, 61, 54, 39, 40, 41, 41, + 40, 30, -6, -25, -6, 22, 44, 48, 42, 42, 37, 23, 11, -42, -73, -77, + -75, -74, -75, -39, 4, 8, -5, -15, 1, -1, -30, -33, -38, -69, -66, -40, + -14, 3, 16, 8, 5, 21, 39, 60, 59, 48, 40, 38, 39, 42, 42, 30, + -8, -20, 0, 26, 48, 51, 48, 43, 29, 21, 1, -47, -70, -80, -83, -80, + -70, -25, 0, -2, -9, -6, 9, -7, -29, -33, -49, -72, -59, -29, -3, 3, + 11, 6, 14, 27, 47, 61, 54, 47, 43, 34, 42, 45, 39, 21, -10, -17, + 4, 29, 53, 54, 47, 39, 29, 22, -11, -53, -70, -83, -86, -77, -61, -19, + -6, -7, -12, -2, 9, -14, -29, -35, -61, -70, -54, -25, -8, 2, 11, 8, + 17, 27, 54, 60, 50, 45, 42, 40, 43, 39, 35, 18, -9, -7, 8, 28, + 55, 56, 49, 32, 30, 15, -21, -53, -71, -88, -87, -74, -45, -12, -11, -15, + -14, 6, 12, -12, -30, -48, -66, -60, -44, -18, -8, 5, 13, 15, 21, 31, + 51, 57, 48, 43, 42, 40, 43, 37, 29, 16, -3, -1, 7, 35, 60, 54, + 38, 26, 29, 5, -30, -54, -72, -93, -87, -69, -34, -14, -19, -25, -12, 13, + 6, -17, -37, -56, -66, -49, -38, -18, -11, 1, 17, 24, 26, 32, 47, 52, + 50, 49, 45, 39, 40, 33, 32, 13, 4, 3, 3, 47, 65, 52, 29, 27, + 20, -5, -35, -56, -76, -90, -79, -63, -27, -17, -26, -24, 0, 12, -2, -16, + -33, -61, -61, -42, -33, -17, -16, -6, 22, 30, 25, 29, 45, 50, 46, 53, + 41, 37, 37, 33, 28, 17, 15, 2, 15, 54, 64, 46, 21, 25, 9, -12, + -39, -58, -77, -87, -75, -46, -21, -23, -34, -24, 9, 9, -7, -17, -40, -67, + -53, -33, -27, -22, -26, -4, 34, 34, 25, 27, 46, 44, 52, 59, 37, 30, + 35, 32, 26, 25, 16, 2, 30, 62, 57, 33, 19, 17, -7, -25, -43, -58, + -80, -82, -64, -36, -26, -26, -33, -17, 11, 4, -9, -18, -45, -62, -44, -30, + -24, -28, -29, 5, 38, 32, 25, 30, 48, 41, 53, 57, 35, 28, 26, 27, + 31, 29, 14, 12, 47, 63, 48, 35, 24, 4, -19, -32, -46, -55, -76, -77, + -58, -31, -30, -33, -36, -8, 12, -4, -9, -22, -51, -57, -30, -23, -27, -40, + -31, 18, 36, 31, 30, 33, 39, 36, 56, 51, 32, 27, 20, 24, 39, 30, + 16, 29, 55, 53, 43, 36, 21, -5, -28, -39, -45, -55, -71, -70, -47, -27, + -35, -36, -25, -2, 1, -4, -6, -23, -48, -48, -25, -16, -25, -46, -23, 24, + 30, 35, 34, 29, 33, 37, 51, 41, 30, 21, 12, 27, 47, 33, 19, 38, + 51, 43, 39, 36, 15, -17, -35, -35, -42, -55, -68, -62, -45, -33, -40, -36, + -19, -5, -4, -3, -6, -24, -47, -38, -17, -13, -37, -48, -13, 26, 30, 36, + 32, 27, 29, 36, 48, 38, 27, 9, 5, 34, 47, 31, 30, 49, 47, 36, + 38, 28, 11, -21, -32, -32, -47, -56, -60, -54, -40, -39, -42, -31, -12, -5, + -7, -1, -4, -21, -39, -28, -11, -13, -45, -42, -2, 23, 25, 42, 33, 26, + 26, 33, 44, 34, 20, 1, 5, 36, 47, 38, 40, 47, 37, 35, 38, 20, + 1, -23, -26, -35, -49, -56, -55, -48, -40, -46, -42, -28, -12, -12, -10, 2, + -6, -25, -32, -25, -13, -22, -43, -30, 5, 18, 24, 45, 35, 29, 21, 27, + 39, 28, 16, 2, 9, 39, 40, 44, 55, 45, 25, 31, 34, 15, -1, -18, + -25, -41, -49, -50, -52, -46, -42, -48, -40, -23, -9, -18, -13, 9, -1, -24, + -27, -22, -14, -30, -41, -26, 8, 15, 25, 40, 36, 26, 15, 26, 35, 21, + 11, 2, 17, 44, 37, 54, 63, 37, 16, 31, 27, 12, -3, -12, -24, -45, + -47, -46, -45, -40, -44, -55, -40, -17, -12, -22, -7, 19, -2, -22, -24, -15, + -17, -36, -36, -11, 16, 10, 17, 38, 43, 25, 15, 25, 26, 14, 7, 2, + 25, 39, 38, 63, 67, 30, 16, 25, 18, 14, -5, -9, -26, -43, -45, -47, + -42, -38, -52, -57, -35, -14, -22, -27, 0, 23, -5, -24, -22, -12, -21, -40, + -31, 1, 19, 6, 11, 35, 44, 22, 18, 28, 14, 4, 4, 11, 32, 34, + 38, 70, 68, 22, 18, 17, 15, 17, 0, -10, -31, -45, -43, -42, -34, -36, + -62, -61, -25, -11, -28, -29, 3, 25, -3, -26, -15, -12, -28, -34, -21, 9, + 17, 2, 10, 31, 40, 24, 23, 28, 5, -3, 6, 19, 35, 33, 42, 72, + 59, 22, 22, 12, 17, 17, 2, -11, -31, -40, -40, -36, -28, -40, -66, -57, + -18, -15, -32, -22, 9, 22, -3, -23, -8, -12, -31, -32, -12, 18, 15, -1, + 9, 25, 36, 26, 27, 20, -7, -5, 12, 23, 29, 33, 45, 70, 48, 25, + 20, 8, 16, 9, 4, -11, -33, -39, -37, -34, -30, -46, -65, -50, -23, -22, + -30, -19, 13, 22, -4, -21, -6, -15, -32, -28, -3, 18, 9, 0, 9, 21, + 30, 28, 30, 12, -14, -1, 17, 19, 27, 41, 51, 63, 35, 28, 22, 12, + 10, 6, 9, -14, -31, -36, -31, -27, -38, -49, -62, -48, -29, -25, -27, -13, + 13, 13, -3, -9, -9, -21, -30, -20, 4, 12, 4, 5, 12, 19, 27, 33, + 29, 6, -12, 2, 21, 17, 31, 45, 54, 55, 31, 31, 25, 14, 3, 5, + 11, -14, -27, -33, -24, -27, -41, -49, -63, -53, -37, -26, -22, -7, 11, 8, + 0, -3, -14, -19, -27, -14, 8, 5, 2, 9, 12, 20, 25, 31, 18, 0, + -6, 8, 20, 14, 27, 43, 59, 48, 24, 28, 25, 14, 2, 8, 6, -15, + -26, -30, -16, -28, -44, -53, -61, -58, -37, -27, -21, -4, 8, 3, 1, -2, + -18, -21, -24, -11, 3, -4, 3, 15, 17, 20, 22, 29, 15, 3, -2, 8, + 17, 18, 30, 46, 56, 40, 21, 29, 26, 14, -1, 5, 4, -6, -22, -29, + -13, -27, -46, -51, -62, -61, -37, -28, -14, 2, 7, 0, 5, -2, -16, -17, + -19, -10, -7, -9, 11, 20, 22, 18, 17, 25, 19, 4, -1, 10, 19, 25, + 32, 44, 53, 36, 19, 29, 24, 10, -4, 5, 4, -2, -22, -24, -13, -31, + -48, -56, -63, -60, -40, -31, -11, 8, 8, 2, 8, -6, -20, -17, -12, -10, + -20, -12, 14, 30, 26, 10, 14, 24, 24, -1, -7, 12, 25, 27, 30, 40, + 52, 34, 17, 28, 24, 7, -9, 1, 8, 3, -20, -20, -16, -33, -53, -59, + -62, -61, -47, -29, -5, 15, 5, 1, 9, -8, -20, -14, -5, -12, -30, -11, + 20, 37, 25, 10, 19, 25, 19, -5, -2, 18, 28, 26, 29, 41, 49, 31, + 20, 30, 24, 1, -8, 4, 10, 3, -17, -12, -18, -40, -57, -61, -62, -59, + -48, -23, 0, 18, 5, 5, 12, -9, -19, -9, -2, -20, -37, -7, 25, 39, + 23, 11, 25, 26, 10, -10, 5, 23, 24, 26, 30, 40, 42, 27, 23, 31, + 18, -7, -5, 2, 7, -1, -10, -10, -22, -45, -59, -63, -62, -58, -45, -21, + -1, 17, 10, 13, 7, -18, -21, -5, -3, -27, -38, -7, 26, 38, 21, 20, + 31, 23, 0, -9, 15, 25, 21, 28, 33, 35, 35, 29, 28, 31, 12, -5, + 0, 0, 4, 0, -3, -14, -27, -48, -57, -69, -66, -61, -40, -19, 1, 16, + 13, 16, -3, -18, -17, -4, -9, -30, -33, -1, 24, 35, 28, 34, 31, 16, + -4, -2, 22, 29, 20, 27, 38, 33, 30, 30, 31, 33, 9, 1, -3, -7, + 2, 6, -1, -22, -31, -50, -61, -74, -67, -52, -34, -25, 1, 19, 21, 14, + -8, -18, -14, -10, -14, -27, -26, -5, 21, 35, 38, 40, 31, 12, -1, 5, + 22, 29, 19, 31, 41, 28, 30, 28, 31, 28, 12, 7, -13, -11, -2, 13, + -5, -26, -32, -52, -67, -80, -65, -46, -34, -26, 2, 15, 25, 9, -8, -14, + -16, -10, -18, -25, -25, -9, 20, 37, 46, 35, 26, 10, 7, 8, 18, 27, + 18, 31, 39, 25, 29, 29, 34, 26, 20, 2, -18, -10, -5, 12, -9, -22, + -31, -48, -74, -79, -66, -42, -34, -22, -1, 14, 25, 13, -6, -19, -16, -8, + -19, -22, -21, -5, 21, 41, 51, 32, 25, 14, 19, 13, 14, 21, 21, 32, + 34, 26, 26, 30, 32, 25, 25, -3, -19, -13, -2, 8, -12, -24, -32, -46, + -75, -79, -67, -43, -33, -18, -7, 12, 25, 18, 0, -23, -13, -7, -23, -18, + -15, -4, 21, 48, 51, 27, 27, 23, 22, 12, 12, 19, 22, 28, 28, 28, + 28, 31, 28, 23, 28, -3, -20, -22, -5, 0, -14, -23, -28, -50, -78, -81, + -63, -44, -34, -19, -14, 10, 25, 18, -6, -19, -5, -11, -30, -17, -8, 2, + 21, 54, 45, 25, 28, 33, 25, 9, 12, 21, 26, 23, 24, 33, 37, 35, + 20, 23, 32, -1, -21, -25, -12, -11, -12, -19, -27, -53, -78, -79, -55, -42, + -31, -26, -18, 12, 24, 13, -9, -12, 0, -20, -33, -13, 1, 6, 26, 55, + 38, 25, 33, 45, 26, 7, 13, 21, 26, 16, 18, 38, 44, 33, 14, 25, + 30, 4, -24, -32, -21, -18, -19, -19, -25, -54, -79, -78, -53, -43, -29, -28, + -20, 6, 20, 12, -3, 0, -3, -35, -28, 1, 9, 8, 25, 46, 34, 30, + 37, 44, 19, 13, 20, 17, 20, 12, 18, 49, 49, 23, 13, 28, 33, 3, + -34, -37, -28, -30, -21, -10, -26, -57, -77, -74, -52, -40, -25, -32, -22, 3, + 17, 12, 3, 8, -15, -40, -18, 10, 10, 4, 32, 39, 27, 38, 48, 39, + 11, 18, 28, 17, 15, 5, 23, 61, 46, 21, 23, 35, 26, -3, -31, -37, + -39, -38, -23, -3, -29, -60, -74, -68, -58, -37, -27, -35, -22, -7, 15, 23, + 14, 8, -27, -41, -6, 19, 14, 9, 35, 31, 31, 48, 54, 35, 11, 27, + 26, 4, 7, 11, 31, 54, 38, 25, 34, 35, 20, -10, 19, 3, -8, -45, + 64, -15, -41, 23, 40, -58, 22, 29, -27, -28, 42, -36, 21, -12, -19, 39, + -14, 3, -18, 32, -27, 18, -8, -43, 43, 25, -52, 6, 19, 13, -7, -50, + 55, 5, -46, -22, 94, -53, -33, 35, 27, -45, -2, 20, 19, -30, -23, 47, + 8, -58, 5, 76, -67, -22, 42, 30, -54, 8, 23, 11, -51, 3, 47, -33, + -7, 5, 27, -33, 34, -35, 17, 4, -26, 5, 17, -30, 33, 5, -29, -5, + 44, -18, -50, 60, -33, 10, -5, 10, -7, 1, -5, 19, -36, 3, 37, -17, + -51, 52, 37, -64, 9, 4, 37, -44, -13, 25, 45, -75, -9, 79, -34, -57, + 53, 24, -59, 18, 22, -3, -24, 10, -2, 18, -53, 29, 35, -20, -43, 37, + 18, -17, -31, 8, 45, -49, 8, 11, 9, -23, 30, -24, -22, 29, 14, -43, + 27, 13, -22, -1, 2, 22, -37, 5, -5, 38, -43, 6, 36, -21, -20, 20, + 0, -5, -27, 27, 21, -53, 4, 52, -2, -84, 70, 5, -29, -19, 36, -6, + -8, -12, 3, 35, -32, -25, 48, 6, -60, 49, 4, -27, -13, 31, -15, -9, + -4, 31, -13, -25, 29, 12, -34, -6, 30, -41, 36, -23, 6, 31, -30, 0, + 17, -45, 47, -5, -47, 19, 28, -8, -30, 27, -6, 15, -54, 34, 21, -27, + -9, 25, 3, -45, 26, 27, -52, 22, 20, -29, 34, -46, 22, 40, -69, -27, + 108, -49, -54, 69, -11, -3, -18, 3, 15, -12, -23, 29, -8, 4, -23, 50, + -38, -8, 33, -32, -2, 26, -27, 12, 13, -39, 56, -31, -22, 28, 2, -39, + 54, -20, -36, 51, -6, -34, 15, 2, 1, 2, -36, 42, 2, -10, -39, 64, + -36, -16, 24, 1, -1, -18, -10, 54, -27, -54, 80, -18, -61, 51, 27, -76, + 64, -30, -1, 9, -19, 24, 13, -29, -13, 49, -18, -46, 43, 6, -47, 42, + -28, 14, 18, -18, 2, 14, -39, 25, 16, -58, 33, 29, -49, 16, 41, -62, + 43, -17, -17, 25, -10, -28, 41, -5, -30, 27, 14, -53, 27, 35, -63, 16, + 30, 0, -30, -10, 22, 31, -57, 0, 68, -59, 2, 37, -30, 6, -3, -19, + 35, -29, 1, 20, 22, -68, 33, 39, -71, 21, 27, -22, -1, 3, 0, 18, + -16, -13, 17, 4, -37, 44, -15, -26, 48, -29, -11, 34, -25, -4, 25, -48, + 43, 4, -49, 28, 42, -72, 7, 59, -36, -28, 45, -9, -28, 25, -19, 23, + -9, -40, 47, 18, -85, 78, -2, -53, 39, -17, 2, 14, -36, 10, 63, -78, + 17, 59, -66, -8, 54, -49, 14, 1, 5, 2, -18, 16, -12, 30, -58, 22, + 53, -83, 17, 79, -84, 19, 17, -34, 44, -33, -27, 82, -62, -19, 91, -93, + 22, 49, -51, -25, 48, -12, -6, 1, -2, -1, 22, -32, -1, 59, -78, 12, + 58, -49, -26, 70, -40, -8, 16, -8, 12, 10, -65, 74, -1, -97, 90, 0, + -56, 23, 25, -17, 11, -23, 14, 9, -24, -31, 77, -41, -48, 95, -38, -46, + 59, -1, -57, 49, -33, 19, 18, -46, 34, 31, -79, 47, 11, -38, 10, 19, + -14, -10, 26, -29, 28, -17, -27, 48, -15, -51, 78, -14, -73, 64, 12, -55, + 29, 3, -24, 52, -65, 26, 50, -75, -5, 81, -76, 0, 42, -6, -26, 10, + 18, -14, 4, -24, 33, 2, -69, 61, 43, -101, 40, 54, -73, 22, 18, -41, + 44, -19, -43, 94, -69, -13, 65, -26, -46, 35, 24, -34, -2, 23, -13, 6, + -19, 4, 38, -56, 14, 40, -37, -19, 66, -57, -9, 50, -47, 21, 6, -31, + 55, -34, -50, 98, -44, -47, 44, 28, -51, 6, 31, -3, -34, 8, 11, 6, + -18, -27, 78, -48, -28, 55, -2, -60, 57, -37, 14, 15, -48, 49, 22, -96, + 74, 23, -83, 36, 18, -17, -25, 41, -12, -4, -2, 1, 9, -14, -18, 36, + 12, -77, 54, 32, -67, 20, 38, -67, 61, -53, 32, 21, -60, 27, 41, -74, + 27, 33, -30, -6, 22, -1, -30, 20, 1, -4, -22, 9, 8, 37, -65, 18, + 61, -69, -3, 37, -19, -15, 15, -16, 57, -78, 20, 66, -67, -27, 76, -37, + -16, 11, 11, -5, -18, 10, 16, -5, -38, 36, 9, -20, -32, 73, -41, -36, + 62, -33, -9, 34, -41, 35, -7, -40, 65, -35, -26, 33, 2, -43, 42, -4, + -9, 5, -11, 19, -10, -16, 11, 16, -28, -9, 41, 2, -70, 67, -3, -55, + 23, 33, -26, 6, -29, 43, 16, -85, 51, 28, -54, 7, 27, -9, 2, -18, + 27, -4, -42, 31, 10, -19, -9, 18, 8, -24, -3, 45, -57, 25, 0, -7, + 15, -28, 10, 33, -46, -6, 52, -36, -15, 46, -29, -4, 12, -14, 34, -57, + 16, 40, -41, 3, 16, 8, -32, 16, 15, -17, -27, 47, -30, -1, 14, -5, + 16, -17, -33, 70, -44, -42, 84, -34, -27, 18, 15, 3, -20, -22, 55, -35, + -22, 31, 10, -11, -27, 27, 13, -28, -10, 41, -21, -3, -22, 41, -21, -13, + 6, 34, -68, 46, 25, -65, 50, -21, -1, 10, -33, 34, 1, -43, 58, -34, + -2, 13, 8, -25, 0, -2, 34, -29, -26, 45, -12, 4, -34, 32, 15, -54, + 17, 53, -76, 41, 4, -17, 13, -26, 13, 31, -47, 1, 52, -53, 11, 8, + 14, -31, -7, 19, 30, -60, 26, 27, -22, -10, 0, 18, -13, -24, 52, -38, + -17, 68, -60, 26, -9, -25, 41, -29, -8, 40, -25, -9, 26, -28, 15, -9, + -3, 11, -21, -1, 44, -47, 19, 0, 3, -14, -12, 38, -22, -23, 37, -10, + -13, 9, -6, 21, -14, -39, 61, -4, -68, 60, 6, -43, 28, -14, 21, -22, + -13, 36, -7, -40, 46, -14, -5, -18, 20, 22, -49, 22, 10, -18, 21, -30, + 9, 34, -54, 19, 22, -34, 27, 7, -45, 30, 0, -20, 23, -23, 29, -10, + -21, 25, 3, -23, -1, 5, 16, -33, 14, 25, -21, -11, 16, 3, -22, 5, + 6, 32, -73, 27, 62, -72, 5, 26, -21, 30, -37, 4, 40, -45, 5, 18, + -18, -1, 12, -3, 0, -18, 28, -8, -14, 11, -11, 13, -15, -3, 27, -17, + -30, 65, -45, -5, 28, -25, 1, 20, -36, 38, -11, -20, 35, -23, -20, 27, + 11, -42, 13, 17, 1, -25, 20, 10, -33, 10, 6, -7, 9, -26, 40, -3, + -63, 74, -30, -11, 10, -10, 5, 17, -47, 53, -10, -47, 29, 31, -45, 4, + 16, 14, -15, -33, 40, -11, -3, -10, 2, 18, -20, 9, 22, -44, 19, 20, + -42, 25, -5, -11, 25, -25, -3, 47, -63, 28, 20, -42, 7, 39, -41, 2, + 13, 10, -24, -8, 41, -26, -1, -13, 9, 42, -60, 0, 61, -54, -4, 19, + -6, 11, -19, -13, 52, -37, -26, 66, -38, -30, 49, -18, -11, 5, 7, 10, + -30, 4, 17, 2, -12, -15, 38, -19, -20, 30, -16, -23, 38, -13, -16, 29, + -22, 26, -17, -35, 62, -30, -35, 51, -16, -27, 40, -16, 3, -8, -4, 9, + 4, -26, 11, 20, -11, -38, 56, -19, -29, 31, 7, -39, 17, 10, 6, -8, + -41, 45, 26, -79, 36, 42, -58, 21, 6, -10, 7, -19, 17, -1, -15, -12, + 53, -22, -32, 24, 25, -59, 24, 22, -36, 10, 18, -27, 44, -45, 0, 42, + -45, -2, 30, -27, 12, 23, -38, 13, 5, 4, -4, -20, 1, 43, -27, -36, + 43, 14, -51, 12, 40, -41, 5, 18, -11, -1, -5, -11, 53, -56, -29, 91, + -41, -45, 57, -7, -18, -3, -4, 29, -20, -19, 20, 26, -57, 31, 17, -22, + -13, 28, -31, 3, 36, -33, 9, 17, -39, 42, -9, -54, 58, 6, -69, 44, + 30, -50, 24, 3, -17, 9, -20, 17, 8, -23, 1, 46, -50, 1, 27, 1, + -49, 37, 5, -17, 4, -5, 7, 18, -55, 39, 36, -85, 37, 48, -63, 5, + 27, -13, -6, -4, 5, 24, -26, -12, 42, -25, -34, 33, 20, -33, -13, 29, + -2, 7, -34, 12, 37, -50, 1, 47, -46, -1, 56, -54, -18, 59, -35, -6, + 12, -16, 20, -2, -27, 43, -12, -34, 22, 25, -41, -7, 43, -20, -18, 19, + -1, 1, -6, -20, 54, -55, -12, 67, -24, -56, 56, -8, -12, -7, -3, 16, + 20, -48, 20, 32, -46, 8, 23, -17, -38, 54, 1, -34, 2, 30, -1, -21, + -18, 38, -14, -35, 41, 3, -36, 19, 22, -45, 40, -32, 12, 12, -26, 2, + 35, -54, 34, 14, -25, -30, 47, 10, -53, 24, 13, -4, -18, 3, 5, 27, + -61, 38, 15, -39, 6, 40, -36, 0, 2, -6, 28, -40, 7, 46, -37, -30, + 59, -21, -29, 6, 48, -55, 12, 30, -21, -6, 5, -2, 1, -14, -7, 46, + -41, -4, 35, -8, -33, 29, -20, 26, -31, -10, 63, -46, -4, 12, 7, -11, + -15, 26, -14, -22, 54, -47, 12, 9, -1, -8, -7, -8, 41, -12, -60, 77, + -21, -26, 11, 13, 1, -26, -9, 59, -45, -16, 38, -3, -27, -1, 28, -8, + -19, 11, 20, -41, 34, -23, 22, -20, -9, 6, 51, -79, 40, 18, -40, 23, + -5, -19, 13, 2, 3, -4, -35, 71, -39, 5, -30, 33, 6, -29, -3, 38, + -29, -5, 18, -9, -4, -11, 16, 15, -32, -14, 77, -83, 30, 10, -10, -19, + 20, 15, -17, -19, 29, 7, -32, 6, -1, 14, -14, -6, 5, 36, -58, 47, + -18, -14, 4, 8, 8, -24, -15, 60, -36, -20, 43, -32, 3, -2, 1, 9, + -5, -8, 30, -33, 6, 6, 2, -12, -11, 24, 1, -22, 9, 34, -61, 25, + 11, -5, -18, -1, 38, -19, -33, 49, -19, -21, 18, -7, 1, 5, -4, -3, + 13, -30, 25, -5, -12, 2, 8, 17, -37, 0, 50, -38, -26, 40, -15, 7, + -24, 31, -11, -8, 6, -6, -3, 1, 9, -8, 6, -20, 25, 0, -21, 7, + 22, -48, 29, -4, 10, -22, 7, 22, -9, -34, 45, -15, -31, 30, -2, 0, + -30, 46, -18, -6, -17, 31, -6, -7, -21, 8, 45, -47, -7, 31, -17, -11, + 25, -20, 17, -30, 47, -38, -2, 5, 16, -36, 24, -2, 3, -7, 6, 10, + -23, 5, -11, 35, -42, 17, 0, 21, -35, 11, 16, -18, -15, 36, -24, -3, + 9, 5, 13, -49, 36, -11, -2, -14, 37, -32, 13, -1, 0, -2, -2, -8, + 17, -11, -21, 30, -1, -1, -41, 72, -65, 14, 14, 12, -41, 21, 4, 15, + -32, -1, 25, -9, -18, 3, 29, -38, 35, -22, 14, -20, 16, -6, -6, -13, + 29, -4, -17, 7, 14, -6, -38, 54, -32, 3, -16, 36, -39, 42, -40, 36, + -22, -13, 17, 14, -36, 12, 23, -25, 6, -25, 53, -33, -12, 5, 37, -46, + 6, 20, 9, -53, 52, -16, -22, 24, -9, 10, -17, 12, -20, 48, -73, 40, + 18, -30, -20, 52, -34, 11, -6, 0, 1, -15, 24, -16, 16, -30, 44, -27, + -10, 0, 34, -52, 24, 3, 2, -6, 12, -25, 35, -38, -14, 72, -73, 7, + 31, 15, -50, 20, 12, -5, -25, 23, 3, -10, -9, 15, 9, -41, 28, 6, + -5, -36, 44, -13, 10, -19, 2, 14, -10, -29, 56, -27, -35, 58, -19, -27, + 17, 16, -30, 10, -7, 15, -12, -3, 11, 18, -30, -13, 38, -17, -16, 3, + 32, -37, 23, -24, 30, -12, -26, 40, -14, -52, 59, 12, -55, 16, 35, -20, + -30, 39, -24, 21, -26, 12, 13, -10, -19, 23, 2, -35, 17, 33, -30, -17, + 39, -15, 12, -53, 50, -13, -25, 2, 50, -42, -1, 25, -22, 6, -5, 3, + -4, 2, -18, 39, -25, -3, 1, 29, -57, 22, 26, -22, -18, 34, -10, -10, + -11, 13, 31, -77, 46, 23, -22, -35, 61, -24, -13, 7, -3, 0, 4, -24, + 27, 12, -50, 35, 13, -19, -37, 69, -46, -4, 13, 5, -8, 6, -25, 40, + -26, -13, 38, -12, -28, 21, 22, -57, 40, -15, 11, -19, 4, 19, 9, -36, + 3, 42, -35, -30, 46, 0, -50, 59, -26, 9, -16, 12, -10, 10, -33, 44, + -8, -29, 8, 42, -43, -6, 26, -19, 14, -30, 34, 4, -21, -17, 49, -31, + -24, 34, 14, -53, 32, 13, -26, 12, -22, 26, -3, -22, -11, 66, -59, 0, + 43, -27, -23, 42, -32, 7, -7, 11, 9, -19, -1, 15, 16, -58, 43, 1, + -32, 11, 36, -44, 18, 0, 4, -4, -7, -22, 50, -22, -44, 67, -14, -43, + 37, 2, -32, 15, 7, 8, -22, -1, 14, 19, -43, 0, 40, -30, -14, 28, + 10, -32, 11, 1, 21, -33, -9, 31, 15, -72, 61, 4, -40, 21, 14, -37, + 22, 4, -4, -9, 5, -8, 23, -16, -22, 35, -24, 0, 12, 3, -17, 15, + 2, -10, -6, -8, 21, 7, -58, 40, 43, -75, 25, 28, -25, -18, 28, -15, + 6, -5, -4, 22, -5, -39, 37, 1, -30, 12, 23, -27, -8, 34, -22, 0, + -12, 15, 10, -28, 2, 45, -45, -9, 36, -22, -7, 13, -7, 6, 2, -18, + 17, 10, -34, 9, 18, -22, -1, 22, -9, -17, 23, -1, -22, 21, -20, 20, + -17, -6, 38, -33, -18, 55, -32, -21, 26, -5, -9, 5, -8, 16, 9, -47, + 36, 11, -36, -3, 38, -7, -48, 44, -2, -11, 2, -16, 15, 11, -36, 33, + -3, -18, 9, 19, -46, 26, -1, -11, 20, -24, 12, 16, -16, -17, 37, -32, + -6, 13, 13, -33, 25, 14, -27, 8, 1, -18, 22, -5, -15, 32, -46, 37, + -2, -19, -13, 38, -32, 8, 2, -4, 15, -12, -4, 19, -25, -10, 37, -19, + -11, -10, 57, -54, 19, -17, 18, 3, -18, -9, 27, -6, -36, 57, -23, -21, + 14, 11, -23, 32, -53, 56, -24, -5, -3, 11, -16, 16, -7, -20, 17, 11, + -3, -31, 42, -33, 14, -6, -2, -8, 39, -56, 48, -21, -20, 30, -8, -20, + 12, 15, -32, 41, -36, 29, -25, 14, -22, 22, -19, 9, 4, 10, -31, 17, + 11, -14, -1, -7, 17, -16, 6, -18, 64, -88, 47, 6, -20, -5, 22, -13, + 18, -28, 2, 25, -19, -10, -3, 29, -23, 11, -22, 39, -25, 13, -27, 20, + -2, -18, 15, -3, 3, 9, -17, -8, 38, -57, 35, 1, -9, -24, 43, -32, + 30, -30, -3, 19, -3, -21, 12, 14, -12, 2, -5, 11, -37, 37, -3, -13, + -4, 10, 11, -4, -38, 41, -9, -27, 37, -37, 16, 17, -7, -15, 22, -40, + 33, -2, -16, 4, 3, 8, -4, -20, 21, -3, -10, 8, -26, 37, -21, 8, + 0, -3, -3, 0, -8, 20, -15, -32, 54, -10, -26, 17, -12, 10, 24, -71, + 51, 3, -21, 9, -3, 17, -22, 2, 15, -21, -11, 39, -25, 11, -27, 28, + 3, -11, -26, 45, -43, 24, 7, -39, 47, -24, -15, 27, -13, -15, 35, -27, + 15, -17, 9, 0, -7, 0, 4, -9, 13, -3, -16, 28, -29, 21, -23, 11, + -4, 10, -30, 64, -63, 13, 28, -30, 16, -13, 0, 25, -39, -2, 53, -40, + 5, -19, 41, -25, -6, -3, 37, -40, 6, 8, 0, 6, -34, 32, 4, -27, + 13, 15, -34, 52, -63, 40, -5, -22, 5, 24, -32, 22, 11, -26, 14, -22, + 26, -21, 10, -8, 5, -10, 46, -66, 44, -20, 14, -7, -27, 23, 30, -53, + 24, 10, -37, 44, -40, 21, -11, 3, 6, 20, -47, 27, 5, -2, -18, -4, + 29, -13, -20, 27, 9, -47, 43, -37, 55, -62, 14, 33, -13, -28, 24, -9, + 23, -35, -4, 32, -14, -13, 28, -10, -30, 46, -43, 43, -46, 13, 13, -10, + 7, -3, -20, 39, -19, -19, 14, -15, 39, -31, -10, 25, 2, -34, 41, -35, + 15, -4, -3, 22, -18, -27, 46, -1, -36, 10, -4, 42, -56, 13, 31, -19, + -18, 28, -29, 27, -32, 24, 10, -44, 20, 32, -32, -17, 32, -13, 13, -35, + 20, 32, -53, 20, 9, -16, 16, -36, 39, -3, -33, 43, -26, 2, 2, 2, + -17, 24, -22, 14, -3, -12, 31, -28, -8, 26, -29, 19, -4, -15, 33, -39, + 22, 16, -37, 6, 17, -4, -13, -12, 37, 9, -65, 34, 25, -27, -9, 7, + 5, 10, -36, 45, -11, -41, 42, -6, -21, 7, -5, 31, -5, -57, 62, -12, + -15, -16, 23, 4, -24, 12, 26, -35, -11, 44, -25, -8, -1, -4, 28, -11, + -37, 61, -48, 23, -1, -30, 29, -8, -2, 6, -19, 18, 15, -41, 30, -4, + -11, -11, 28, -10, -4, -37, 81, -45, -43, 61, -19, 1, -11, 0, 31, -30, + -25, 68, -43, -11, 0, 27, -1, -33, -7, 77, -54, -30, 44, -6, -5, -14, + 17, -6, -10, 6, 30, -68, 50, -16, 5, 5, -30, 30, 26, -69, 36, 8, + -34, 37, -28, 11, 0, -1, 9, 1, -41, 53, -22, -24, 23, 5, -9, -11, + 12, 28, -61, 28, 36, -68, 51, -33, 25, -6, -26, 7, 53, -65, 2, 47, + -25, -23, 17, 20, -4, -51, 38, 29, -67, 31, 1, 22, -35, -8, 40, -9, + -46, 47, -13, -8, 5, -15, 37, -27, -20, 45, -16, -45, 59, -37, 19, -6, + 2, 1, -11, -3, 34, -42, 0, 33, -30, 16, -13, 13, 2, -23, 18, -5, + -26, 43, -24, 15, -26, 4, 35, -15, -62, 64, 19, -75, 50, -8, 8, -14, + -12, 31, -19, -30, 45, -10, -12, -10, 36, 3, -53, 14, 45, -37, -22, 42, + -25, 21, -36, 21, 37, -61, 5, 47, -49, 19, -4, 5, 1, -12, 7, 3, + -11, 2, 18, -28, 13, -4, 18, -13, -20, 33, -22, -8, 21, -12, -10, 24, + -9, 2, -27, 15, 33, -41, -18, 56, -40, 9, -5, 6, 20, -44, 11, 39, + -35, -22, 50, -7, -36, -6, 41, -10, -30, 15, 20, -22, 7, -11, 16, 6, + -51, 59, -21, -26, 24, 12, -24, 8, -7, 12, 3, -36, 27, 18, -42, 22, + 9, -22, 11, -2, 15, -40, 38, -13, -16, 8, 24, -33, 15, -13, 4, 23, + -42, 17, 30, -34, -5, 28, -22, 11, -23, 30, -14, -28, 37, 12, -46, 11, + 31, -23, -12, -7, 36, -17, -6, -4, 25, -18, 4, -29, 53, -48, 4, 24, + -9, -21, 30, -1, -20, 2, -13, 51, -51, -1, 39, -23, -18, 33, -23, 3, + 3, 2, -13, 11, 4, -13, 15, -14, -3, 1, 24, -53, 55, -24, -17, 36, + -1, -49, 45, -7, -12, -2, -4, 24, -23, 1, 6, 23, -51, 30, -8, 14, + -29, 17, 12, -9, -21, 21, 1, 3, -32, 21, 30, -59, 27, 25, -21, -26, + 36, -24, 16, -23, 15, 10, -15, 11, -11, -3, 14, 1, -30, 32, -24, 27, + -25, 10, -12, 29, -33, 7, -5, 25, -29, 14, 15, -42, 20, 18, -27, 1, + 21, -19, 17, -18, 2, 19, -12, -34, 47, -21, -6, 9, -2, 14, -32, 32, + -23, 14, -21, 21, 0, -13, -8, 42, -35, -19, 33, 4, -34, 23, -5, -6, + 22, -31, 21, -8, -5, -3, 15, -22, 10, 2, 7, -17, 11, 3, -10, 2, + -1, -2, -9, 25, -20, 11, -18, 17, -3, -12, 2, 9, -1, -10, 5, 0, + 15, -40, 36, -5, -28, 16, 24, -34, 16, -1, 13, -32, 11, 9, 5, -26, + 5, 32, -32, 4, -1, 29, -38, 8, 7, -6, 5, -2, -5, 18, -26, -2, + 39, -42, 0, 26, 2, -43, 45, -30, 20, -11, -6, -3, 16, -7, -6, 3, + 12, -13, 5, -7, -21, 47, -29, -11, 9, 36, -45, 8, 0, 22, -28, -7, + 32, -22, -9, 20, 12, -40, 24, -8, 14, -28, 10, 9, 12, -29, 15, -7, + 15, -23, 5, 14, -24, 12, 8, 4, -38, 36, -4, -7, -30, 47, -13, -24, + 16, 23, -46, 29, -3, -10, 20, -43, 35, 0, -4, -30, 47, -18, -21, 16, + 19, -35, 11, 19, -21, -11, 27, -12, -9, 16, -21, 23, -32, 30, 3, -22, + -15, 51, -38, -1, -2, 11, 15, -28, -1, 16, 13, -42, 23, 4, -6, -32, + 61, -24, -35, 34, 29, -55, 4, 13, 9, -6, -26, 35, -6, -11, -11, 19, + -6, -3, -15, 43, -41, 4, 22, -1, -34, 18, 15, -35, 18, -1, 23, -35, + 18, -2, -9, 1, 10, -18, 17, -18, 21, -8, -17, 24, -1, -20, -7, 26, + -11, 6, -33, 42, 0, -40, 9, 46, -48, -6, 24, 13, -39, 8, 41, -43, + 3, 6, 6, -7, -6, -8, 42, -37, -11, 39, -16, -26, 25, 3, -24, 9, + 11, 6, -34, 17, 14, -12, -22, 20, 0, 14, -38, 27, 10, -37, 22, -1, + -5, -7, 11, 4, -3, -29, 38, -5, -26, 4, 20, -17, 6, 2, 11, -17, + -10, 40, -49, 10, 26, -8, -24, 11, 12, 5, -36, 21, 20, -22, -29, 28, + 30, -30, -24, 31, 25, -70, 39, 4, -16, 3, 9, -13, 16, -26, 23, 19, + -46, 1, 29, 6, -37, 8, 27, -8, -33, 36, -24, 5, 14, -8, -8, 1, + 4, 15, -27, -11, 44, -38, 6, 12, -3, -12, 20, -17, 16, -35, 28, -4, + 0, -13, 8, 23, -24, -16, 28, 11, -58, 48, 6, -39, 11, 24, -9, -8, + -25, 42, -16, -14, 12, 2, 13, -31, 6, 26, -10, -48, 64, -22, -21, 6, + 28, -15, -11, -2, 22, -30, 11, 15, -25, 13, 2, -1, -7, -4, 6, 17, + -37, 17, 0, 1, 14, -23, 4, 16, -23, 6, 12, -31, 30, 6, -18, -25, + 45, -7, -20, -15, 44, -38, 9, 22, -37, 24, 6, -20, 14, -17, -8, 44, + -27, -22, 16, 30, -33, -18, 20, 31, -50, 11, 27, -21, -4, -3, 26, -15, + -24, 15, 20, -27, 16, -12, 9, 5, -24, 3, 26, -27, 5, 15, -19, 9, + -9, 26, -25, -5, 10, -4, -6, 31, -45, 18, 24, -23, -23, 27, -3, 2, + -18, 9, 13, -18, 19, -17, 7, -1, -24, 31, 5, -49, 31, 32, -40, -7, + 10, 14, -12, -12, 5, 21, -30, 25, -12, 4, -18, 9, 11, -13, -20, 37, + -8, -3, -13, -3, 33, -21, -32, 44, -7, -22, 28, -24, 5, 12, -19, 2, + 6, 2, -16, 11, 10, -6, -23, 31, -25, 7, 6, -16, 18, 1, -35, 40, + -9, -18, 12, 4, -2, -25, 20, 19, -16, -35, 46, -14, -8, -3, -1, 24, + -12, -25, 26, -4, -6, 3, -12, 20, -24, 18, 9, -20, -2, 18, -13, -1, + -16, 8, 26, -35, 12, 10, -11, 6, 2, -30, 46, -43, 16, 6, 1, -20, + 26, -18, 8, -13, 9, -3, 3, 1, -25, 29, 13, -50, 12, 41, -47, 15, + 14, -12, 2, -3, -1, 14, -25, -3, 26, -23, 19, -35, 41, -5, -23, -1, + 31, -30, 8, -15, 32, -29, -7, 22, 10, -35, 12, 6, -2, 20, -50, 36, + 7, -17, -4, -1, 7, 2, -21, 19, -12, 1, 28, -25, -5, 9, -3, -12, + 32, -45, 16, 21, 0, -43, 21, 28, -19, -38, 45, -15, -8, 28, -43, 39, + -12, -23, 13, 19, -39, 23, -3, 17, -32, 6, 20, -5, -32, 23, 8, -15, + -1, 11, 9, -28, 5, 20, -18, -6, 9, -18, 50, -50, -8, 49, -30, -5, + -4, 14, -19, 28, -21, 2, 4, 11, -20, 6, 3, -5, -24, 54, -34, -14, + 26, -4, -2, -16, 5, 20, -23, 1, 6, -9, 32, -37, 1, 25, -22, -8, + 31, -6, -37, 31, 0, 3, -37, 24, 25, -27, -20, 27, 1, 4, -26, 13, + 3, -14, 12, -6, 6, -3, -6, 18, -14, -27, 38, 5, -36, 14, 13, -22, + 26, -13, -22, 36, -23, -5, 3, 18, -12, -23, 31, -5, -24, 23, -15, 17, + -7, -23, 20, 6, -4, -19, 20, -8, 15, -32, 13, 17, -30, 17, 13, -19, + -8, 4, 24, -18, -29, 36, 7, -21, -20, 28, 13, -17, -31, 36, -9, -7, + 7, 6, -9, -4, 7, -6, 10, -32, 41, -26, 12, -10, -12, 35, -10, -39, + 36, -9, -7, 7, 6, -9, -4, 11, -14, 5, -7, 9, -13, 24, -27, 4, + 14, 7, -31, 19, -14, 17, -5, -34, 57, -31, -7, -6, 28, -15, -11, 2, + 25, -21, -14, 15, 18, -35, 12, 1, 9, -20, -2, 32, -37, 26, -17, 7, + 1, -10, -18, 54, -37, -16, 23, 11, -13, -23, 34, -5, -16, -10, 25, -28, + 30, -10, -7, -5, 18, -24, 25, -24, 18, -11, 0, 3, -19, 34, -12, -12, + 2, 3, -13, 32, -37, 20, 4, -6, -25, 29, -3, -2, -11, -2, 28, -38, + 18, 7, -5, -7, 0, -4, 21, -36, 30, -19, 25, -29, -15, 48, -11, -43, + 33, 33, -64, 17, 26, -12, -18, 9, -1, 18, -33, 23, -13, 21, -18, -13, + 18, -2, -20, 20, 6, -15, 4, -12, 28, -27, 1, 10, -5, 3, 0, -17, + 15, 17, -30, 2, 5, -8, 17, -11, -2, 9, -20, 23, -27, 23, -10, -3, + 7, -3, -25, 31, 9, -28, -9, 30, -5, -28, 15, 29, -36, -9, 29, -11, + -20, 33, -27, 21, -14, -12, 21, -3, -9, -2, 12, -5, -27, 27, 7, -20, + -11, 32, -9, -15, -1, 9, 20, -42, 12, 9, -4, 3, -6, -3, 6, 0, + -12, 15, -25, 27, -6, -6, -6, 6, -2, -4, 5, 9, -20, 12, 8, -17, + -10, 30, -12, -24, 25, -15, 18, -21, 21, -8, -6, -9, 12, -6, 15, -33, + 26, 8, -32, 13, 21, -12, -28, 20, 11, -6, -28, 27, 11, -21, -10, 22, + -1, -11, -7, 24, -12, -27, 35, -8, 0, -20, 23, -10, 9, -30, 32, -15, + 3, -7, 6, -2, 10, -17, 1, 8, -4, -5, -3, 14, -9, 1, -11, 18, + -13, 15, -33, 22, 14, -32, 11, 9, -1, -17, 14, 0, -3, -16, 29, -21, + -4, -1, 28, -24, -2, -11, 41, -25, -23, 24, 6, -18, -13, 37, -21, -2, + -4, 29, -40, 11, 12, 4, -25, 12, -9, 23, -17, -14, 27, -2, -26, 9, + 18, -14, -1, -15, 29, -18, -4, 5, 12, -26, 18, -3, -7, 3, 13, -10, + -25, 44, -38, 11, 8, -2, -25, 28, -9, 12, -13, -13, 10, 27, -53, 19, + 16, -4, -20, 12, 12, -21, 5, 12, 3, -35, 22, 8, 0, -28, 18, 16, + -25, -3, 9, 8, -3, -19, 8, 24, -34, -4, 38, -16, -30, 29, -1, -2, + -25, 28, -1, -21, 11, 10, -18, -1, 10, 1, -7, 0, 1, -7, 15, -15, + -5, 16, 2, -22, 8, 0, -1, 26, -34, -22, 56, -26, -11, 12, 9, -9, + -9, 4, 7, -8, -1, 8, 0, -21, 10, 19, -8, -25, 17, 10, -18, 3, + -4, 26, -15, -29, 30, 9, -46, 36, 12, -33, 1, 18, -2, -16, 4, 16, + -10, -16, 11, 2, 8, -19, 5, 1, 10, -21, 20, -8, -1, -3, 1, 7, + -19, 7, 11, -12, 5, 5, -26, 29, -11, -5, -2, 12, -13, 9, -22, 23, + 3, -20, 4, 17, -16, -13, 17, 15, -16, -34, 37, -5, 8, -32, 23, 17, + -36, -2, 36, -25, -4, 28, -18, -20, 15, 4, 7, -12, -24, 43, -19, 0, + -11, 25, -9, -12, -7, 10, -1, 11, -2, -12, 13, -27, 30, -9, -15, 8, + 17, -28, 18, -9, 3, 7, -8, -10, 16, -26, 35, -22, -10, 37, -35, 1, + 11, 11, -19, -2, 9, 17, -37, 11, 10, 9, -16, -12, 27, -11, -22, 16, + 24, -48, 25, -1, -3, 4, -20, 13, 39, -72, 34, 1, 2, -6, 4, -1, + -8, 2, -8, 18, -10, -1, -5, 19, -30, 5, 30, -16, -26, 36, -26, 3, + 21, -27, 10, 4, -10, 0, -4, 15, 9, -41, 32, -11, 2, -11, 15, -3, + -7, -8, 16, -3, -21, 23, -2, -9, -4, -2, 20, -5, -37, 49, -20, -6, + -9, 17, 17, -36, -8, 40, -24, -5, 3, 8, 5, -12, -6, 15, 2, -27, + 28, -4, -23, 16, 5, -1, -26, 29, 11, -38, 22, -12, -8, 38, -34, -3, + 10, 4, -2, -5, -8, 24, -16, -20, 21, 1, -7, 11, -7, -4, -15, 15, + 15, -21, -6, 10, -1, 17, -45, 23, 29, -42, 2, 18, -5, -6, -1, 22, + -20, -19, 16, 21, -20, -18, 23, 2, 5, -41, 36, 10, -34, 12, 12, -25, + 11, 1, 6, -6, -11, 20, -11, 10, -11, -12, 13, 8, -21, 5, -1, 14, + 3, -26, 5, 27, -39, 18, 7, -27, 34, -20, 13, -20, 7, -4, 25, -23, + -16, 7, 47, -35, -29, 37, 10, -35, 4, 12, -1, 0, -15, 25, -23, -12, + 35, 7, -51, 28, -1, 16, -33, 5, 27, -21, 2, -5, 13, -3, 0, -20, + 27, -30, 8, 16, -4, -13, 14, -15, 19, -12, -6, 8, -9, 19, -27, 4, + 20, -9, -12, 21, -37, 41, -22, 1, 1, 13, -33, 20, 14, -30, -2, 22, + 21, -51, 3, 38, -7, -35, 17, 6, 11, -43, 33, 9, -36, 10, 31, -24, + -13, 16, -6, 24, -36, -1, 16, 19, -45, 20, 11, 2, -30, 31, -21, -14, + 29, -4, -12, 3, -6, 9, 15, -37, 20, -4, 8, -18, 12, -7, 17, -8, + -12, -9, 23, 8, -28, 1, 29, -19, -18, 27, -2, -8, -28, 44, -4, -36, + 15, 33, -30, -13, 13, 14, -20, -7, 25, -11, -5, -8, 21, -1, -8, -37, + 50, 1, -53, 27, 28, -21, -10, 4, 16, -24, 10, 6, -12, 0, 2, 6, + 1, -13, 2, 21, -26, 3, 13, -19, 10, 9, -18, -3, 22, -18, -1, -2, + 14, -1, -23, 21, -6, -2, -9, 20, 5, -35, 1, 34, -21, -16, 22, 1, + -8, -5, 1, 18, -12, -23, 18, 5, -17, -7, 37, -6, -35, 6, 47, -44, + -7, 20, 5, -10, -23, 35, -6, -12, -12, 39, -27, -10, 9, 21, -21, -6, + 2, 5, 1, 6, -28, 17, 20, -31, -3, 15, 7, -26, 31, -40, 43, -32, + 23, -19, 11, -22, 26, -6, -1, -25, 33, 2, -25, -7, 9, 26, -16, -30, + 29, 20, -47, 13, 16, -9, -19, 18, 23, -32, -17, 32, 21, -38, -13, 14, + 43, -66, 19, 23, 5, -50, 47, -20, 2, -11, 22, -5, -6, -21, 4, 38, + -15, -32, 12, 35, -35, -4, 7, 18, -17, -1, -7, 6, 5, 0, 0, -7, + 0, -8, 21, -10, 5, -28, 30, 3, -17, -29, 57, -16, -17, -10, 28, -9, + -20, 26, -12, 3, -20, 27, -3, -7, -42, 65, -9, -45, -3, 63, -33, -11, + -6, 28, -17, -1, -6, 6, 7, -12, 0, 25, -21, -30, 54, -9, -37, 1, + 28, 7, -42, 18, 11, 17, -46, 24, -9, 27, -38, 22, -20, 23, -21, 11, + -6, 42, -71, 20, 32, -11, -43, 44, -3, -4, -27, 12, 24, -8, -18, -8, + 30, -19, -23, 44, -8, -30, 0, 45, -39, 0, -1, 28, -16, -17, -15, 44, + -13, -11, -13, 36, -24, -11, 12, 17, -30, 8, 17, -10, -18, 9, 22, -18, + -15, 3, 25, -25, 11, -6, 5, 7, -18, -3, 15, -1, -17, 8, 28, -32, + -17, 36, 8, -41, 12, 7, 13, -22, -14, 18, 41, -57, -1, 25, 10, -40, + 18, 11, -8, -23, 25, -16, 37, -45, 17, 10, 2, -60, 64, -15, -3, -16, + 22, -9, 9, -27, 30, -7, -21, 3, 20, -10, 6, -12, 15, -19, 14, -19, + 3, 22, -8, -29, 37, -28, 29, -26, 11, -15, 15, -17, 21, -26, 18, 5, + -5, -11, 2, 16, -10, -10, -5, 29, -30, 4, 3, 18, -21, 4, 1, 8, + -13, -10, 1, 40, -35, -26, 44, 5, -38, 8, 30, -24, 0, -1, 0, 12, + -18, -1, 18, -8, -28, 39, -18, 24, -35, 24, -36, 46, -41, 12, -3, 24, + -37, 31, -28, 32, -16, 2, -27, 39, -34, 7, 24, -19, -6, 14, -10, -1, + 14, -16, -4, 25, -26, -4, 8, 22, -40, 33, -30, 22, -15, 36, -63, 39, + 1, 10, -54, 36, 9, 5, -51, 49, -13, 5, -7, -7, 15, -9, -10, 2, + 12, -18, 6, 3, 18, -29, 9, 10, -10, 1, -20, 20, -3, -1, -13, 21, + -26, 41, -36, 2, 23, -23, -10, 39, -41, 17, -10, 8, 7, -13, 23, -54, + 66, -26, -50, 54, 17, -66, 59, -46, 30, -10, 6, -8, -18, 19, 16, -32, + 12, 6, -2, 3, -36, 33, -6, -7, 12, -16, 6, 14, -21, 14, 16, -58, + 37, 3, 0, -35, 44, -16, 17, -38, 28, -14, 25, -45, 28, -21, 32, -31, + 11, 17, -24, 11, 5, -24, 18, -6, -3, 0, -3, 21, -33, 24, 20, -78, + 66, -8, -24, 3, 17, -14, 24, -41, 34, -25, 27, -32, 17, -5, 13, -26, + 28, -29, 22, -8, -16, 33, -30, 2, 25, -27, 1, 31, -36, -7, 31, -8, + -12, -5, 17, -7, 5, -26, 32, 1, -18, -16, 27, -7, -10, 2, 21, -42, + 30, -3, -19, 33, -40, 19, 6, -13, -5, 17, -10, 28, -63, 40, 6, -10, + -9, 7, -3, 12, -20, -1, 17, -1, -6, -14, 18, 1, -19, 12, 5, -9, + -2, -14, 33, -3, -44, 51, -17, -6, -16, 36, -35, 29, -31, 31, -24, 15, + -23, 33, -35, 20, -4, -1, -19, 27, -1, -29, 25, 1, -20, 25, -23, -13, + 62, -50, -18, 43, -20, 1, -4, 16, -18, 4, -16, 36, -42, 42, -42, 38, + -28, 9, -10, 31, -40, 30, -39, 30, 8, -28, 11, 9, -7, -6, -8, 10, + 22, -36, -5, 26, 4, -41, 30, 12, -11, -10, -14, 37, -29, 3, -6, 9, + -5, 15, -30, 40, -26, 12, -25, 25, -21, -12, 46, -17, -39, 47, 7, -57, + 45, -14, 1, -13, 21, -21, 14, -7, 7, -11, 18, -34, 25, 7, -28, 22, + 1, -12, 11, -24, 4, 38, -44, 17, 2, -12, 19, -17, 0, 9, 17, -55, + 29, 3, 3, -27, 48, -38, 16, -17, 24, -19, 26, -49, 29, 9, -18, -25, + 50, 2, -31, -20, 43, -3, -35, 23, 13, -34, 9, 20, -15, -8, 29, -37, + 29, -21, 4, -8, 36, -52, 29, -8, 6, -18, 35, -34, 22, -21, 10, 5, + -11, -13, 35, -26, -3, 12, -17, 13, 1, -12, -4, 24, -18, -6, 18, -7, + -13, 17, -4, -30, 48, -41, 10, 34, -39, -22, 73, -48, -12, 12, 22, -14, + -31, 18, 29, -17, -21, 22, -3, -8, -12, 25, -11, 13, -41, 36, -3, -2, + -27, 37, -6, -36, 17, 18, -7, -10, 4, -5, 10, -21, 13, 15, -21, 2, + -1, -5, 8, -1, -16, 29, -24, 14, -18, 26, -24, 17, -26, 21, -18, 24, + -49, 82, -52, -11, 36, -22, -17, 30, -21, 1, 1, -1, 8, -2, -7, 2, + 17, -9, -36, 37, -5, -15, -4, 27, -20, 11, -31, 46, -18, -13, -11, 58, + -67, 19, -4, 40, -43, 9, -14, 41, -32, -16, 46, -19, -13, 5, -5, 6, + 2, -16, 10, -9, 18, -13, 3, 24, -37, 11, 1, 0, -8, -9, 28, -1, + -41, 40, -10, 6, -13, 1, -11, 30, -28, -10, 30, 1, -36, 17, 28, -54, + 51, -24, 1, -6, 6, -12, 33, -48, 23, 18, -17, -23, 27, 11, -23, -13, + 27, -7, -1, -24, 35, 3, -48, 35, 8, -20, -3, 3, 16, -11, 8, -35, + 32, 7, -27, -22, 81, -85, 36, -7, 16, -16, 2, 0, 13, -28, 12, -16, + 24, 6, -25, -14, 47, -15, -25, 3, 37, -41, -5, 32, -25, 11, 6, -16, + 25, -34, 14, 8, 13, -52, 30, 6, 13, -56, 56, -27, 13, -11, -6, 16, + -12, -1, 18, -40, 18, 19, -13, -11, 7, -2, 9, 10, -39, 9, 46, -48, + -18, 59, -32, -3, 14, -10, 10, -13, 10, -13, 14, -11, -10, 5, 31, -43, + 10, 23, -16, 3, -29, 50, -23, -19, 16, 15, -19, 3, -20, 39, -19, -14, + -6, 54, -44, -12, 18, 30, -56, 28, -15, 22, -16, -15, 31, -8, -9, -1, + 1, 1, 2, -8, 9, 10, -43, 41, -9, 8, -48, 62, -30, -9, 13, 6, + -24, 32, -31, 8, -4, 16, -27, 27, -19, -1, -6, 37, -40, 14, -3, 0, + 25, -59, 34, 18, -18, -21, 17, 13, -11, -8, -11, 43, -40, 1, 6, 24, + -37, 10, 14, -4, -12, -2, 17, 11, -40, 10, 16, 17, -51, 24, 14, -4, + -31, 22, 18, -32, 15, -24, 46, -38, 9, 2, -2, 14, -15, -12, 15, 3, + -28, 29, -7, -6, 13, -7, -6, 2, 3, -17, 28, -28, -9, 37, -17, 0, + 3, 10, -19, -5, 19, -17, 12, -25, 30, -19, 8, -27, 49, -15, -27, 9, + 10, 7, -31, 6, 30, -12, -45, 41, 24, -42, -1, 28, -2, -38, 29, -18, + 23, -4, -43, 35, 26, -54, 23, 7, 6, -30, 17, -14, 32, -40, 24, -13, + 17, -15, -11, 16, 16, -20, -26, 47, -10, -26, -6, 41, -19, -22, 36, -41, + 33, 5, -32, 12, 28, -51, 19, 27, -40, 7, 35, -34, 9, -22, 42, -20, + -15, -3, 43, -55, 15, 23, -10, -11, 3, 14, -32, 31, -26, 21, 7, -44, + 15, 40, -22, -41, 54, -17, -17, 8, -6, 10, 11, -17, -6, 15, -2, -20, + 31, -19, 4, -17, 22, 0, 2, -36, 39, 0, -31, 23, -38, 59, -15, -29, + -13, 69, -50, -22, 43, -11, -16, 0, 16, -9, -10, 13, 5, -8, -18, 27, + -8, -2, -12, 13, -1, -16, 16, -18, 27, -11, -19, 39, -28, -26, 28, 36, + -85, 72, -40, 24, -10, 0, -9, 30, -29, -11, 22, -13, -7, 23, -10, -14, + 6, 13, -15, 22, -31, 12, 0, 0, -3, -15, 19, 14, -21, -22, 27, 35, + -72, 36, -3, 18, -54, 50, -29, 38, -47, 14, 19, -11, -25, 27, 9, -23, + -2, 2, 16, -6, -24, 22, 10, -27, 7, 16, -30, 11, 24, -40, 31, -28, + 29, 1, -28, 7, 17, 3, -45, 40, -11, -7, 4, 19, -45, 24, 24, -50, + 48, -35, 11, 9, -12, -14, 30, -23, 8, 7, -15, -7, 53, -59, 13, 5, + 15, -46, 49, -48, 57, -36, -20, 34, 1, -10, -15, 15, 20, -36, -9, 35, + 6, -39, 7, 14, 27, -81, 70, -21, 5, -22, 21, -6, 1, -13, 19, -19, + 4, -10, 35, -43, 31, -3, -7, -15, 40, -56, 33, -1, -33, 51, -35, -2, + 24, -18, 5, 0, 4, -16, 10, -6, 9, -28, 37, -38, 45, -35, 0, 37, + -38, 7, 19, -32, 3, 17, -2, -23, 19, 15, -23, 5, -2, 13, 1, -37, + 8, 59, -80, 26, 13, 15, -31, -8, 30, -7, -7, -19, 22, -2, -9, -2, + 12, -7, 3, 1, -25, 47, -53, 35, -5, -27, 21, 15, -25, 13, -24, 42, + -41, 19, 2, -13, 1, 23, -40, 37, -45, 46, -8, -41, 44, -11, -17, 23, + -9, -20, 22, -3, -15, 22, -23, 19, -7, 2, -34, 65, -56, 7, 28, -8, + -37, 37, 3, -8, -34, 39, -11, 9, -29, 6, 35, -14, -49, 48, 5, -25, + 5, -25, 66, -47, -9, 28, -7, -12, 0, 17, -20, -2, 21, -12, -23, 54, + -50, 20, 7, -20, 7, -2, 3, 4, -26, 26, -6, -14, 15, -3, -10, 12, + -10, -4, 23, -33, 14, -12, 38, -55, 36, 0, -6, -5, 0, -4, 7, 0, + -14, 2, 8, -11, 13, 5, -33, 41, 4, -62, 40, 8, -6, -8, -31, 52, + -4, -44, 25, 20, -18, -24, 32, -11, -9, -4, 30, -37, 34, -31, 7, 30, + -29, -14, 28, -10, -9, 6, 0, -5, 14, -9, -3, -2, 10, -22, 29, -22, + -2, 6, -5, 16, -25, 6, 27, -19, -9, -11, 29, -13, -5, -6, 16, 5, + -20, -1, 30, -20, -8, 7, -8, -2, 3, 14, -9, -24, 35, -7, -14, -12, + 32, -5, -18, -15, 35, -7, -13, -1, -4, 27, -20, -30, 58, -15, -29, 9, + 15, -16, -3, 1, 4, 5, -4, -11, 17, 3, -29, 28, -10, -18, 20, -7, + -2, 4, 2, -17, 22, -3, -31, 23, 23, -32, -14, 34, -3, -14, -13, 11, + 21, -26, -16, 36, -7, -13, 15, -8, -3, -1, -11, 15, -8, -4, -4, 24, + -21, 1, 11, 3, -22, 5, 15, -24, 0, 37, -31, 7, -18, 15, 16, -15, + -19, 26, 0, -10, -26, 31, 6, -19, -6, 21, -19, 20, -13, -3, 13, -2, + -32, 24, 2, -8, -10, 36, -29, -10, 19, 10, -25, 5, -9, 31, -23, -21, + 21, 26, -25, -9, -5, 35, -17, -34, 17, 42, -44, -11, 30, 11, -40, 18, + 8, -6, -11, 11, -26, 39, -18, -23, 37, -12, -32, 45, -8, -22, 5, 16, + -15, -10, 6, 17, -15, -3, 9, -22, 41, -22, -25, 29, 5, -30, 6, 12, + 17, -32, 7, 20, -26, 9, 9, -10, 7, -17, 10, 11, -16, -7, 12, 5, + -4, -26, 25, 24, -46, -4, 50, -39, -11, 8, 35, -36, 2, -9, 33, -7, + -22, -26, 76, -37, -41, 33, 28, -43, 14, 6, 2, -8, 2, -20, 34, -19, + -2, -4, 15, -6, -23, 28, -3, -32, 33, -16, 7, -11, 14, 9, -10, -30, + 35, -25, 17, -14, 1, 14, 12, -38, 16, 15, -7, -30, 15, 18, -24, -6, + 47, -38, 6, 7, -9, -2, -3, 1, 12, -8, -23, 20, 35, -47, -14, 51, + -9, -48, 19, 20, 0, -25, -2, 20, 16, -29, -25, 60, -17, -23, -8, 31, + -4, -30, 12, 20, -14, -4, -1, 17, -11, -9, 7, 7, -17, 1, -12, 25, + -5, -20, 15, 19, -29, 2, 5, 11, -19, -18, 31, 1, -27, 18, -17, 51, + -53, -2, 29, 4, -37, 17, 11, -11, -23, 41, -17, -10, 13, -4, -8, 18, + -27, 17, 1, -19, -7, 51, -37, -28, 53, 4, -47, 5, 18, 17, -32, -8, + 14, 36, -46, 3, 11, 11, -24, 4, 0, 16, -7, -26, 25, 20, -44, 7, + 20, -12, 2, -14, 4, 33, -38, 1, 8, 20, -34, -12, 61, -46, -19, 44, + -10, -4, -18, 12, 12, -8, -26, 16, 22, 2, -51, 18, 53, -56, -5, 30, + -9, -22, 32, -11, -18, 18, 13, -25, -7, 8, 9, 3, -20, 1, 32, -27, + -9, 5, 19, -20, -13, 18, 8, 3, -35, 22, 31, -47, -2, 16, -8, 15, + -10, -22, 54, -20, -23, -6, 51, -52, -13, 48, -23, -11, 28, -30, 38, -6, + -50, 28, 33, -58, 2, 34, 16, -53, -1, 55, -13, -42, 15, 23, -7, -33, + 13, 21, -14, -6, 2, -2, 27, -43, 27, 11, -19, -16, 26, -16, -4, 16, + -17, 1, 20, -17, 8, -17, 6, 26, -25, -24, 40, -13, 6, -14, -14, 29, + 3, -32, -5, 46, -21, -28, 38, -30, 6, 28, -47, 3, 65, -67, -5, 61, + -34, -27, 31, 12, -30, -7, 11, 19, 0, -43, 18, 47, -52, -20, 52, -14, + -9, -10, -5, 55, -45, -29, 55, 16, -83, 28, 36, -23, 6, -8, -13, 37, + -17, -30, 32, -9, -6, 10, -19, 16, 4, 9, -35, 22, -1, -17, 3, 8, + 10, -10, -21, 40, -27, -5, 16, -6, -27, 47, -23, -26, 48, -18, -19, 14, + -1, -9, 5, 1, -20, 58, -57, -14, 55, -16, -40, 37, -6, 11, -19, -22, + 43, 2, -55, 27, 37, -38, -29, 58, -6, -11, -22, 4, 26, -7, -67, 67, + 21, -56, 19, 15, -5, 0, 2, -41, 37, 10, -65, 49, 8, 1, -19, 1, + 9, 8, -20, -9, 22, -14, -3, 4, -1, 13, -6, -11, 15, -8, -15, 13, + 16, -38, 14, 24, -39, 20, 9, -17, 14, -15, 7, 3, -12, -3, 30, -25, + -24, 43, -1, -40, 18, 17, 0, -22, -14, 31, 20, -68, 35, 32, -43, -9, + 35, -16, 4, 2, -35, 35, 27, -81, 40, 31, -21, -30, 29, -12, 13, 10, + -42, 26, 17, -33, -1, 16, 12, -29, 6, 4, 21, -27, -9, 39, -6, -54, + 40, -14, 15, -4, -17, 20, 4, -18, -4, 23, -24, -3, 30, -41, 15, 17, + -4, -29, 19, 4, -9, -10, 12, 17, -21, -7, 26, -19, -17, 17, 3, 1, + -3, -30, 47, 16, -62, -4, 68, -29, -54, 43, -1, -4, 20, -42, 22, 34, + -32, -43, 63, -12, -26, 8, -6, 10, 22, -66, 55, 25, -65, 15, 9, 21, + -22, -28, 36, 5, -16, -51, 102, -49, -12, 6, 21, -12, -23, 24, -15, 11, + -14, -8, 31, 4, -53, 64, -35, 13, -28, 23, -23, 22, -16, 13, -22, 23, + 27, -51, -8, 41, 6, -66, 36, 13, 4, -26, 7, 11, 9, -34, 0, 35, + -21, -15, 10, 34, -57, 60, -69, 60, -22, 1, -27, 27, 14, -27, 1, -13, + 35, -2, -51, 36, 35, -49, 5, -1, 31, -42, 25, -26, 34, -7, -60, 98, + -46, -22, -1, 49, -45, -2, 10, 26, -33, 25, -36, 37, -19, 4, -3, -7, + 9, 7, -8, -29, 48, -23, 0, -33, 45, 0, -23, -16, 47, -7, -31, -9, + 38, -2, -36, 18, -8, 43, -55, 16, -1, 41, -72, 54, -35, 24, 4, -46, + 47, -11, 6, -40, 24, 10, 8, -38, 16, 16, 24, -98, 80, 2, -28, -28, + 44, 11, -47, 31, -7, 35, -42, -25, 41, 12, -64, 34, 14, -2, -21, 24, + -14, 11, -3, -24, 22, -28, 46, -51, 38, -22, 35, -40, 2, 11, 22, -48, + 23, -9, 34, -35, -24, 52, -7, -37, 9, 36, -21, 0, -32, 61, -44, 6, + -1, -16, 41, -28, 19, -37, 49, -11, -38, -8, 65, -53, 9, -21, 59, -37, + 8, -33, 59, -13, -80, 67, 19, -39, -28, 70, -21, -25, -3, 23, 17, -29, + -44, 83, -41, 0, -23, 53, -27, -12, 21, -19, 21, -21, 13, -4, -12, -5, + 38, -58, 34, 10, -22, -16, 47, -8, -39, 19, 12, 4, -46, 39, -24, 48, + -69, 45, -18, 10, -5, -2, -4, 10, -5, 7, -17, -3, 20, 0, -40, 26, + 40, -64, 11, 34, 1, -49, 11, 35, -22, -14, -32, 98, -47, -37, 9, 76, + -70, -8, 7, 63, -92, 56, -49, 77, -64, 2, 41, -28, -25, 37, 0, -26, + 35, -40, 16, 3, 14, -46, 22, 18, -6, -9, -11, 22, 26, -44, -46, 94, + -60, 18, -37, 69, -33, 5, -20, 42, -32, -20, 24, -1, -10, -12, 39, -31, + 13, 1, 9, -47, 42, -26, 39, -73, 48, 48, -73, -13, 56, 14, -78, 38, + 11, 12, -50, 8, 39, 3, -79, 73, 2, -25, -17, 23, 27, -58, 26, -37, + 67, -49, 11, -12, 62, -82, 64, -41, 3, 26, -17, -45, 55, -4, -22, 10, + -2, 38, -54, 8, 5, 47, -79, 7, 54, -7, -64, 41, 49, -73, 29, -24, + 54, -51, -4, 14, 33, -84, 82, -46, 17, -25, 57, -44, -2, 11, 8, 15, + -66, 46, 19, -25, -44, 58, 10, -38, -23, 77, -48, -3, -12, 24, 24, -70, + 37, 21, -15, -48, 81, -66, 44, -29, 6, 4, 9, -30, 31, -24, 5, 19, + -51, 34, 21, 11, -92, 78, 19, -44, -54, 104, -47, -8, -19, 29, 45, -78, + 6, 55, -11, -75, 66, -10, 8, -38, 24, 10, 4, -57, 66, -20, -25, 20, + 6, 9, -71, 100, -60, -6, 8, 28, -37, 29, -42, 78, -58, -22, 42, 10, + -69, 34, 33, -36, 29, -54, 81, -54, 0, 7, 1, -19, 22, -14, 4, -3, + 32, -13, -59, 86, -54, 4, 0, 21, -35, 43, -68, 91, -31, -53, 38, 48, + -72, -15, 50, 3, -11, -72, 96, -1, -49, -23, 81, -21, -57, 15, 63, -67, + 5, 25, -27, 34, -48, 49, -26, 12, -33, 66, -73, 14, 35, -20, -27, 45, + -24, 12, -12, 0, 24, -50, 33, -26, 45, -65, 47, -7, -4, -9, 19, -19, + -2, 15, -17, 30, -39, 25, 2, -3, -57, 109, -86, 10, 14, 31, -53, 7, + 32, 5, -44, -20, 84, -35, -34, -6, 99, -97, 1, 23, 40, -65, 15, 9, + 36, -45, -22, 55, 4, -55, -3, 73, -80, 63, -49, 28, 2, -10, -19, 24, + -13, 8, 1, -15, 5, 22, -4, -57, 72, -41, 16, -45, 76, -57, 30, -26, + 38, -16, -34, 32, 12, -53, 22, 47, -46, -4, 6, 45, -65, 32, -21, 45, + -44, -22, 69, -44, -16, 29, 19, -59, 40, -7, 42, -77, 39, -4, 29, -74, + 27, 38, -12, -60, 69, 7, -32, 1, -9, 50, -56, -15, 19, 47, -75, 44, + 5, -22, 27, -7, -22, 0, 23, -30, 1, 4, 33, -44, 29, -24, 57, -67, + 17, 18, 4, -59, 32, 48, -72, 28, -2, 13, -10, -21, 16, 58, -117, 85, + -14, -5, -34, 21, 29, -27, -20, 31, 23, -49, 16, -14, 51, -74, 24, 38, + -38, -16, 56, -33, -7, 3, 0, 36, -80, 49, 23, -19, -48, 76, -61, 43, + -41, 27, -11, 23, -30, 8, 3, 15, -14, -22, 16, 3, 15, -39, 11, 38, + -13, -70, 88, -41, 2, 4, -30, 80, -84, 15, 37, -6, -61, 58, -19, 27, + -72, 64, -6, -16, -30, 59, -21, -21, -12, 44, 22, -101, 78, -10, -16, -11, + 20, -21, 31, -36, 37, -18, -20, 46, -24, -23, 10, 21, -36, 32, -38, 68, + -50, 12, -6, 19, -33, 14, -16, 20, -11, -14, 47, -59, 56, -14, -27, 5, + 29, -43, 49, -96, 106, -35, -41, 28, 35, -30, -29, 37, 12, -11, -58, 79, + -31, -16, -11, 43, -13, -25, 3, 71, -76, -13, 64, -39, 3, -45, 66, -13, + -1, -45, 80, -40, 6, -29, 26, -12, 6, -19, 21, -4, 9, 0, -37, 44, + -28, 11, -22, 19, 7, 1, -45, 60, -13, -42, 32, -16, 31, -50, 35, 10, + -22, -23, 60, -62, 21, -2, 39, -49, -4, 24, 30, -53, -23, 66, -33, 2, + -34, 69, -33, -10, 7, 24, -51, 28, 0, 9, -24, -3, 38, -24, -16, -9, + 68, -81, 38, -16, 35, -34, -4, 16, 20, -43, 10, 7, -3, 14, -30, 38, + -39, 38, -20, -12, -20, 78, -79, 22, -4, 44, -48, -6, 37, -2, -25, -24, + 60, -41, 15, -30, 50, -43, 7, 9, 27, -64, 45, 5, -15, -17, 1, 49, + -56, 3, -11, 69, -78, 37, -5, 38, -60, 26, -2, 9, -51, 53, -20, -3, + 9, -1, 38, -74, 40, 6, -13, -54, 69, -24, 6, -22, 31, 0, -17, 12, + -13, 8, -9, 20, -53, 56, -27, 29, -63, 41, 8, 11, -73, 59, 15, -25, + -21, -1, 61, -69, 10, 17, 28, -59, 34, -14, 32, -54, 17, 22, -11, -47, + 63, 7, -56, 46, -28, 50, -96, 60, 2, 0, -37, 36, -11, 15, -38, 41, + -19, -31, 46, -12, -25, 9, 49, -67, 47, -48, 51, -30, -15, 23, 19, -43, + 8, 17, 4, -11, -29, 54, -48, 38, -28, 10, -9, 38, -48, 27, -47, 55, + 3, -59, 22, 41, -5, -59, 38, 5, 31, -101, 72, 11, -36, -18, 54, -25, + -1, -30, 54, -28, -34, 61, -27, 13, -46, 55, -21, -10, -21, 52, -34, -8, + 30, -21, 20, -11, -21, 22, -2, -46, 79, -84, 60, -9, 13, -57, 51, 2, + -16, -38, 34, 15, -23, -7, -6, 53, -38, -22, 29, 23, -63, 65, -34, -21, + 34, -7, -19, -8, 24, 13, -8, -63, 110, -56, -8, -37, 79, -56, -3, -3, + 62, -57, 19, 9, 8, -20, -29, 27, 13, -28, -19, 79, -80, 58, -31, 24, + -16, -35, 46, 0, -52, 36, 21, -29, 16, -23, 26, -29, 38, -42, 26, -41, + 60, -29, -16, -4, 42, 7, -85, 53, 47, -54, -29, 67, -53, 39, -58, 45, + -5, 5, -37, 61, -56, 27, 17, -40, 1, 15, 17, -43, 19, 4, 30, -49, + 12, -1, 49, -64, -27, 96, -41, -47, 45, 8, -38, 35, -50, 74, -81, 54, + -14, 24, -64, 57, -5, -25, -19, 27, 16, -27, 4, 16, 2, -25, 26, -31, + 22, -35, 56, -54, 0, 55, -23, -29, 9, 38, -38, 12, -41, 74, -28, -29, + -3, 61, -71, 36, -32, 43, -19, -14, 21, 0, -10, -19, 32, -42, 20, 11, + 23, -94, 107, -13, -53, 5, 35, -17, -11, -25, 32, 40, -76, 29, 32, -9, + -65, 80, -42, 6, -22, 42, -27, -2, 10, -2, 13, -41, 32, 10, -17, -26, + 53, -50, 40, -42, 30, -19, 41, -50, 33, -20, -1, 40, -67, 8, 29, 15, + -58, 25, 32, 15, -81, 46, 14, -8, -51, 24, 40, -44, 17, 10, 2, -26, + 47, -68, 49, -49, 50, -27, -3, -20, 84, -62, -32, 52, 12, -52, 0, 42, + -30, 24, -47, 45, -16, 11, -51, 74, -47, -9, 45, -19, -18, -5, 41, -39, + 11, -33, 56, -20, -14, -8, 64, -85, 60, -23, -13, -3, 33, -20, -25, 57, + -34, 2, -23, 42, -21, 3, -49, 85, -35, -27, 1, 54, -34, -31, 24, 15, + 6, -45, 54, -30, 12, -27, 40, -61, 39, 1, -5, -18, 17, 14, 7, -33, + -27, 83, -44, -40, 21, 66, -82, 32, -7, 33, -54, 27, 3, 2, -13, -15, + 52, -57, 14, 14, -6, -27, 54, -45, 23, -11, 16, -27, 27, -33, -3, 36, + -46, 47, -15, -8, -7, 67, -93, 12, 34, 17, -73, 32, 15, 29, -44, -17, + 47, 2, -40, -31, 81, -43, 3, -24, 52, -32, 4, 1, 20, -48, 20, 40, + -68, 23, 14, 19, -64, 46, -8, 17, -48, 55, -29, 23, -59, 48, -2, -27, + 11, 1, 21, -30, 25, -24, 29, -41, 21, 0, -15, -17, 64, -47, 1, 31, + -22, 2, -11, 22, -56, 69, -53, 32, -30, 31, -16, 32, -68, 29, 42, -39, + -49, 80, 17, -74, 17, 0, 55, -88, 25, 29, 14, -72, 56, 0, 0, -33, + 20, 5, -34, 35, -33, 45, -37, 23, -9, 10, -54, 67, -22, -13, -15, 41, + -14, -16, 8, 0, 19, -51, 56, -51, 39, -20, 19, -34, 26, -18, 19, -31, + 23, 0, 12, -31, 7, 45, -65, 22, 4, 24, -73, 74, -13, -34, 18, 23, + -16, -25, -2, 40, 5, -84, 76, -4, 6, -74, 75, -7, -10, -51, 60, -13, + 0, -45, 50, 18, -57, 20, 21, -7, -26, 47, -51, 28, -19, 12, -13, 3, + -1, 20, -23, 1, 28, -18, 3, -41, 67, -72, 34, -11, 33, -47, 47, -9, + -20, -2, 28, -21, -27, 11, 26, -15, -25, 57, -44, 46, -67, 49, -5, -30, + 1, 42, -36, -9, 22, 7, -13, -34, 67, -29, -16, -26, 84, -49, -21, -11, + 77, -53, -43, 62, 0, -3, -32, 23, 13, -5, -69, 88, -42, 7, -17, 37, + -35, 27, -6, -13, -11, 31, -17, -28, 45, -17, 8, -32, 41, -48, 39, -35, + 41, -16, -28, 41, -3, -13, -26, 23, 12, -22, -50, 104, -57, 9, -28, 67, + -53, -7, 0, 45, -41, -22, 50, -8, -21, -9, 38, -19, -18, -2, 55, -76, + 38, -12, 39, -49, -14, 64, -24, -45, 25, 50, -66, 23, -15, 32, -36, 32, + -46, 44, -14, 2, -16, 22, -7, -11, 14, -28, 21, 4, -10, -18, 63, -66, + 30, -20, 36, -35, -16, 26, 12, -37, 6, 50, -35, -15, 6, 48, -64, 4, + 12, 46, -85, 33, 12, 25, -49, -11, 77, -53, -18, 19, 29, -41, -1, 3, + 39, -70, 55, -6, -1, -23, 38, -22, -12, 1, -11, 36, -39, 5, 15, 33, + -55, 32, -8, 6, -37, 39, -32, 4, 27, -23, 11, -1, 10, -28, 19, -24, + 52, -69, 27, 21, 11, -72, 52, 17, -35, -13, 16, 33, -44, 4, 19, 18, + -60, 13, 35, 12, -93, 82, 9, -35, -20, 26, 40, -74, 14, 18, 28, -66, + 37, 4, 9, -43, 34, -15, 17, -35, 38, -11, -14, 14, -5, 2, -36, 54, + -35, 2, 1, 29, -35, 9, -4, 24, -32, -5, 31, -19, -17, 28, 34, -86, + 49, 13, -16, -52, 71, -29, 3, -30, 51, -1, -36, 6, 25, 4, -75, 56, + 10, -21, -18, 37, -16, 17, -53, 60, -7, -38, -9, 63, -18, -70, 67, 1, + -19, -32, 50, -20, 11, -23, 24, -10, -3, -21, 32, -26, 7, 12, -19, 35, + -29, 26, -41, 32, -22, 14, -43, 41, 7, -16, -24, 57, -20, -35, 25, 7, + -11, -20, 31, -18, 10, -34, 44, -7, -22, -9, 49, -33, -18, 26, -4, 12, + -63, 51, 11, -16, -40, 80, -28, -37, 5, 61, -78, 22, 16, -3, -10, -5, + 26, -8, -2, -43, 68, -42, -24, 39, 11, -31, 15, -9, 18, -20, -1, 7, + -17, 26, -30, 31, -31, 42, -28, -1, -15, 49, -51, -2, 26, 3, -12, -11, + 7, 22, -9, -51, 70, -27, -14, -13, 53, -37, -12, 9, 44, -57, -14, 51, + -6, -27, -10, 60, -55, 2, 14, 18, -45, 32, -19, 29, -27, -12, 31, 14, + -54, 17, 41, -62, 51, -40, 40, -40, 12, -8, 28, -39, 16, 10, 10, -46, + 37, 12, -42, 17, -4, 2, -17, 35, -34, 38, -30, 21, -6, -36, 36, 13, + -56, 14, 53, -36, -13, -1, 61, -64, 7, -3, 54, -63, 5, 14, 34, -67, + 10, 46, -27, -18, 26, 20, -41, 14, -13, 40, -66, 20, 38, -34, -11, 39, + -16, 11, -26, 7, 28, -58, 26, 0, 30, -61, 44, 11, -30, -17, 66, -40, + -33, 35, 6, -21, -2, 9, 16, -13, -39, 79, -71, 27, 9, -9, -29, 28, + 4, -17, 1, 14, 2, -20, -2, 16, 24, -67, 20, 37, -4, -80, 75, 18, + -46, 2, 10, 25, -31, -28, 43, 19, -75, 59, -13, 14, -40, 29, 7, -22, + -20, 44, -20, -16, 10, 32, -21, -42, 61, -19, -29, 12, 39, -55, 32, -4, + 0, -2, -24, 40, -19, -38, 34, 22, -33, 11, -3, 31, -49, 21, -16, 40, + -54, 12, 29, -19, -8, 17, 17, -52, 28, 22, -39, -2, 45, -42, 23, -46, + 51, 11, -68, 26, 55, -34, -44, 45, 9, -19, -43, 57, -16, -5, -9, 40, + -24, -12, 8, 29, -54, -4, 50, -37, 0, 11, 7, -4, 0, -25, 57, -62, + 19, 18, -7, -22, 12, 19, -27, 9, -5, 15, -19, 2, 15, 4, -45, 36, + -5, 8, -48, 60, -13, -35, 36, -19, 21, -24, -7, 23, -24, -22, 73, -58, + -5, 34, 25, -71, 19, 30, 0, -43, -4, 50, -9, -21, -21, 69, -28, -46, + 24, 29, -45, 12, 3, 21, -13, -28, 47, -9, -37, 21, 22, -46, 21, 8, + -1, -32, 42, -22, 14, -27, 19, 16, -29, 3, 17, -1, -39, 28, 21, -42, + 8, 47, -45, 2, -16, 50, -20, -54, 50, 9, -25, -12, 41, -29, 8, -3, + -5, -13, 25, -16, 19, -30, 15, 15, -2, -52, 38, 38, -69, 12, 37, 9, + -54, 10, 36, 5, -79, 27, 57, -35, -40, 48, 21, -41, 13, -3, 10, -29, + 4, 18, 4, -50, 52, 1, -28, -6, 41, -25, -22, 34, -22, 10, -5, 3, + -6, -1, 2, 26, -48, 24, 12, 5, -54, 36, 18, -32, -6, -3, 48, -28, + -21, 22, 35, -63, 6, 43, -28, -27, 42, -7, -22, 6, 21, 8, -56, 31, + 23, -10, -73, 76, 18, -49, -26, 70, -21, -23, -8, 35, 0, -42, 7, 42, + -26, -28, 47, -31, 0, 13, 11, -25, 14, -6, 10, -13, -26, 40, -14, -5, + -8, 42, -36, 1, 15, -10, -34, 47, -24, 5, -22, 38, 14, -39, -10, 53, + -26, -67, 72, 0, -15, -25, 29, 19, -29, -25, 50, -14, -31, 10, 42, -44, + -24, 81, -40, -32, 12, 45, -41, -5, -1, 47, -27, -54, 54, 32, -64, 4, + 26, 1, -1, -41, 44, 4, -22, -22, 47, -30, 7, 5, 3, -37, 45, 1, + -53, 44, -1, -20, 7, 12, -13, 9, -23, 26, -2, -47, 32, 37, -61, 6, + 42, 0, -25, -43, 76, -23, -38, -10, 73, -24, -57, 47, 45, -70, 3, 19, + 7, -19, -8, 10, 24, -12, -36, 66, -60, -1, 50, -32, -19, 8, 26, 2, + -44, 11, 53, -42, -26, 20, 42, -52, 14, 16, -26, -11, 42, -41, 16, 16, + -23, 13, 1, -6, 17, -18, -41, 71, -39, -23, 40, 13, -30, 2, 19, 0, + -39, 10, 24, -15, -25, 12, 66, -81, 6, 47, 9, -69, 12, 47, -9, -36, + -27, 76, 9, -107, 58, 53, -68, 19, -10, 39, -49, 8, 14, -11, -17, 21, + 18, -25, -17, 47, -4, -48, 32, -9, -4, -3, 8, -5, 29, -40, 13, 14, + -31, 24, 7, -48, 27, 37, -61, 22, 15, 7, -46, 17, 10, 22, -45, -9, + 56, 1, -73, 43, 34, -51, -15, 40, 2, -47, 35, 8, 27, -87, 31, 86, + -94, -27, 67, 10, -44, -15, 43, 11, -46, 6, 9, 33, -71, 35, 26, -30, + -18, 37, -18, -9, 20, -15, 1, 5, 9, -2, -23, -11, 50, -42, -3, 24, + 6, -21, 17, -5, -8, 11, -26, 24, -19, -9, 33, 22, -78, 38, 44, -48, + -53, 80, 6, -66, 14, 36, 8, -37, -15, 66, -24, -75, 87, -14, -27, -10, + 45, -12, -38, 13, 33, 7, -67, 20, 75, -55, -67, 85, 8, -52, -11, 45, + -10, 13, -34, 12, 26, -36, 7, -1, -1, -7, 23, -27, 18, 15, -12, -28, + 27, -6, 9, -52, 40, 26, -50, 3, 51, -10, -71, 67, 10, -59, 4, 56, + -27, -20, -19, 58, 6, -81, 38, 49, -39, -39, 47, 14, -25, -40, 54, -2, + -20, -38, 82, -25, -51, 44, 24, -60, 8, 51, -47, -2, 6, 22, 9, -34, + -20, 78, -56, -25, 36, 19, -49, 17, 32, -50, 44, -29, 4, -11, 14, 3, + -13, -11, 19, 13, -24, 28, -32, 33, -37, 39, -61, 119, -76, 120, -70, 99, + -122, 89, -113, 91, -123, 122, -123, 77, 86, -116, 6, -118, 123, -23, 64, -93, + 17, 24, -125, 124, -125, 124, -24, -12, 56, 87, -54, 38, -91, 64, -2, -41, + 126, -127, 20, 8, -48, -62, 127, -128, 88, -43, -18, 86, -100, 44, -32, -26, + 71, -13, 6, 51, -33, -50, 106, -59, 33, 5, -20, 69, -56, 54, -48, -6, + 38, -5, -38, 35, -1, 12, -1, 4, 23, -56, 19, -7, 5, -4, 31, -38, + 3, -12, -9, -25, -7, 24, -32, 17, -21, -22, 24, -20, 6, -18, 0, -15, + 5, -16, 15, 3, 2, -10, 3, 27, -31, 37, -12, 32, -5, 2, -21, 27, + -14, 20, -8, 5, 15, -7, -11, 20, -37, 7, -23, 17, -22, 11, -14, 8, + -44, 39, -52, 26, 3, 14, -10, 51, -45, 29, -19, 19, -3, 41, -21, 46, + -23, 10, 16, -25, 3, 7, -30, 19, -9, -5, -1, 1, -19, 1, -24, -23, + 51, -48, -10, 17, -34, -38, 60, -71, 26, -43, 65, -59, 70, -26, 61, -51, + 63, -51, 42, -25, 58, -36, 31, 10, -14, -9, 8, -18, 8, 4, 8, 7, + 31, -52, 39, -53, 53, -56, 24, 11, 1, -20, -8, -32, -18, -10, -25, 4, + 1, 37, -37, 42, -42, 53, -57, 52, -18, 30, 11, 20, -52, 55, -61, 56, + -50, 24, -26, 38, -42, 36, -1, -43, 58, -46, 6, 18, -35, 31, -36, 28, + -55, 55, -98, 52, -41, 26, -24, 48, -31, 48, -26, 30, 19, -17, 23, -8, + 13, 15, 19, -7, -23, 41, -36, 20, -39, 65, -64, 66, -38, -9, 7, -14, + -10, -3, 6, 15, -19, -40, 53, -67, -11, -12, -25, 23, -11, -12, 46, -48, + 39, -20, 20, -14, 31, -54, 71, -25, 2, -8, -5, -9, 1, 7, 27, 17, + -14, 43, -31, 27, 11, -33, 20, -2, -33, 45, -38, 17, -9, -11, -17, -22, + -19, 20, -25, 4, 29, -35, 14, -17, 1, -7, 19, 2, 16, 32, -3, -17, + 4, 0, -9, 17, 5, -8, 52, -32, 40, -39, -5, -18, 14, -21, 31, 10, + -17, 8, -34, -7, 1, -44, 7, 10, -8, -6, -18, -25, -1, -19, 16, -29, + 62, 6, 9, 21, 0, -14, 4, 5, 20, 13, 27, -1, 18, -5, 21, -31, + 11, 2, -9, -4, 21, -27, 8, -21, -28, -19, 14, -12, 5, -20, 20, -36, + 4, -18, -27, -4, -4, 15, 4, 48, -7, -11, 20, -6, 7, 20, 1, 20, + 0, 35, -35, 28, -37, 7, -43, 21, -22, 23, -18, 12, -22, -13, -20, -11, + 7, 23, -10, 19, -18, 17, -41, 4, -16, -8, 21, 11, -4, 10, 30, -24, + 32, -15, 15, -13, 28, -5, 38, -10, 0, -22, -13, -12, 24, -18, 30, -7, + 4, -16, 27, -28, -3, -1, 18, -14, 31, -24, -3, -13, -19, -36, -2, -31, + 9, -2, -12, 17, 12, -50, 46, -49, 43, -15, 13, 22, 15, -25, 10, -8, + -6, 14, -2, 24, 15, 9, 17, -13, 5, 14, -15, 7, 20, 4, 4, 18, + -16, 3, -47, 31, -46, 19, -24, 5, -19, -1, -42, 14, -44, 18, -7, -1, + 15, 9, -35, 32, -44, 39, -46, 23, -16, 36, -25, 45, -34, 32, -8, 10, + 5, 28, 0, 12, 11, 3, 20, -23, 6, -8, 16, 7, 17, -19, 32, -44, + 3, -8, -21, -8, -5, 2, -29, 2, -3, -19, -14, 3, 7, -23, 10, 1, + 3, 8, 13, -44, 20, 21, -16, 23, 3, 5, 10, -11, 32, -11, 13, -7, + 30, 4, 16, -7, -6, -7, 14, -40, 4, -16, -26, 3, -1, 0, -6, 5, + -50, 37, -27, 18, -16, -14, 6, -1, -4, -15, 8, -12, 14, 9, -22, 42, + -10, 23, -11, 36, -15, 13, 30, 1, 47, -20, 33, -14, -12, 1, -20, -9, + -9, -11, -13, 7, -37, 25, -47, 14, -13, 4, -12, 9, -32, 18, -48, -1, + -35, -1, -7, 35, -20, 53, -4, 34, -7, 13, 19, 9, 30, 6, 45, -22, + 23, -18, -6, -1, 3, -30, 14, -15, 9, -39, 10, -33, -13, -24, 10, 14, + 14, -10, 2, -34, -4, -20, -21, -14, 40, -10, 17, -14, 28, -17, 37, -26, + 69, -15, 38, 2, 21, -25, 37, -61, 13, -9, 5, -17, 18, -41, 22, -57, + -1, -9, -13, 24, -10, 38, -5, 8, -16, -2, 1, 12, -25, -2, -13, 2, + 2, -16, -19, 32, -30, 22, 20, -4, 12, 11, -17, 19, -17, -3, 20, -33, + 65, -27, 32, -14, 8, -8, 13, -19, 9, -2, 7, 33, -40, 18, -18, -18, + 6, -23, -11, -11, -28, 4, -11, -15, -14, -8, -5, 34, -6, 19, 1, -3, + 9, -1, 5, 5, 14, -11, 40, -3, 18, -20, 16, -7, 2, -5, 9, -16, + 9, -17, 0, -17, 4, -17, -3, 3, 8, -14, -19, 12, -21, -7, 1, -2, + -8, 16, 3, -6, 35, -23, 33, -13, 11, 12, 3, -7, 26, -11, 19, -18, + 23, -22, 39, -49, 39, -50, 11, -38, 26, -29, 10, -6, -22, 15, -8, 15, + -37, 36, -43, 39, -43, 18, -26, 1, 11, 4, -2, 9, 7, 2, 7, 19, + 1, 1, -4, 16, -5, 16, -9, -3, 4, -4, -1, -17, 0, 11, 16, -27, + 12, -15, 15, -3, 0, 10, -3, -5, 12, -13, -7, -13, -31, -1, -3, -17, + 15, -31, 25, -10, 15, -1, 2, 4, 10, 7, 32, -13, 7, -22, 2, -10, + 16, 1, -15, 19, -24, 16, -18, -12, 18, -9, 9, 24, -8, 8, 11, 0, + -31, 17, -55, 21, -43, 40, -40, 29, -54, 44, -34, 22, 11, 16, 7, 19, + 21, -6, 2, -7, -16, 22, 0, -1, -4, 5, -8, 26, -42, 4, -6, -21, + 35, -16, 8, 0, -22, -13, 11, -31, 7, -28, 4, 17, -12, -18, -2, -23, + 23, -1, 19, 34, 7, 7, 35, -19, 11, -8, -17, 8, 4, 16, -16, -13, + 9, -15, -5, -1, -6, 7, 3, 11, 1, -7, -24, 21, -31, 36, -3, -10, + 8, 2, -17, 12, -24, 6, -3, 9, 15, 3, 13, -8, -13, -3, 6, -19, + 14, -33, 16, -17, -5, -31, 3, -29, 24, -7, -6, 35, -20, -5, 34, -20, + 25, -3, 10, 25, 8, 14, -13, 0, 1, 17, -33, 51, -38, 45, -32, 39, + -3, -2, -24, 3, -18, 14, -4, -44, 2, -25, -15, -2, -23, 3, -2, -2, + 20, -14, 8, -10, -4, 21, 11, -13, 32, -4, 8, 19, -16, -2, -2, -2, + 14, -2, -1, 27, -26, 20, 11, -13, 10, -3, -7, 12, -13, -3, -30, -16, + 10, -26, -3, -10, -2, -9, 15, -17, 1, -2, -7, 14, -8, 12, -3, -1, + 2, 47, -26, 22, -19, 16, 2, 13, -3, 21, -10, 22, -32, 43, -24, 16, + 0, 5, -2, 12, -44, -12, 1, -26, 1, -36, 5, 2, 9, -17, 20, -37, + 14, -9, -5, 6, -3, -13, 23, -19, 25, -33, 6, 17, 10, 19, 15, -4, + 12, 5, -9, 33, -20, 26, -9, 11, -2, 11, -21, -7, -13, -4, -8, -12, + 0, -10, -9, 8, -33, 9, -26, 8, 6, -8, 12, 7, -8, 0, 7, -16, + 25, -8, 27, 12, 0, 9, -9, 4, -17, 14, -16, 11, -8, 18, -2, 4, + 2, -20, -18, 22, -16, -5, 3, -24, 13, -10, -12, -10, 2, -16, 33, -15, + 21, -15, -4, -19, 29, -22, 18, 2, 20, 12, 18, -22, -7, -16, 7, -19, + 14, 1, -17, 33, -22, 38, -8, 3, -3, 21, -17, 51, -43, 15, -22, -23, + -6, -12, -14, 14, 9, 6, 4, -31, 3, -16, -14, 22, -22, 5, 13, -25, + 17, -2, -18, 7, 1, 5, 36, -16, 23, 4, -15, 29, -20, 10, 1, 24, + 17, 16, -4, -16, -37, -11, 1, -33, 27, -36, 17, -22, 2, -33, 16, -29, + 32, -7, 24, -12, 14, -12, 22, -16, 15, -20, 19, 9, 14, 12, -1, -24, + 13, -6, -1, 32, -19, 24, 12, -26, 4, -31, -38, 18, -16, -13, 3, -14, + -1, 11, -15, 15, 0, -2, 30, -6, 35, -23, 10, -35, 5, -14, 17, -21, + 20, 4, 7, 8, -5, -15, 20, -25, 26, 6, -3, 3, 5, -24, 26, -35, + 4, 0, -6, 13, -23, 8, -25, 1, -2, 9, 3, 17, 4, 0, 13, -15, + 3, -21, -16, 4, -5, -10, 11, -2, 7, 23, -22, 25, -19, 18, 25, -9, + 14, -21, -7, 11, -24, 22, -12, -7, 6, 9, -33, 11, -20, 2, -9, 2, + 3, -13, 12, -15, 23, -21, 16, -16, -2, 8, 13, -12, 18, -10, 16, -12, + 20, -18, 18, -1, 21, -21, 20, -30, -6, 10, -2, 13, -6, -15, 6, 2, + -1, 1, -19, 9, -15, -3, -11, 0, -5, 1, 5, 1, -4, -8, 1, -16, + 23, 0, -23, 2, 8, -6, 38, -4, 2, 13, -17, 31, -4, -8, 22, -14, + 0, 12, -22, 7, -7, 11, 4, -4, -12, -9, -22, 2, -17, -17, -11, 7, + -17, 19, -24, 9, -8, -6, 29, -4, 10, 4, 4, 23, -1, 9, -6, -12, + 23, 16, -6, 33, -29, 12, -7, -10, 17, -4, -18, 21, 0, -14, -2, -20, + -21, 10, -28, 5, -18, -4, 0, -11, 1, 5, -17, 3, 9, 20, 6, 1, + -7, 2, -7, 3, 9, -22, 29, 6, -1, 25, -10, 6, -1, 4, 12, 18, + -13, 28, -11, 6, -15, -14, -22, -7, 5, -14, 1, -16, -12, -5, 5, -9, + 4, -1, -14, 21, -10, -5, 0, -17, -7, 2, -10, 6, 11, 1, 37, -17, + 6, 21, -24, 41, 2, 23, 0, 10, -18, 16, -26, 14, -21, -19, 18, -9, + -14, -1, -9, -14, -3, -7, -10, 7, -7, 19, -11, 15, -25, -3, -6, 2, + 8, -10, 4, 12, -3, 11, -2, -2, 5, 31, -9, 39, -21, 14, -23, 18, + -16, -1, -3, -6, 0, 22, -9, -5, -17, -4, -12, 2, -3, -7, 10, -10, + 7, -20, -19, -10, 0, -14, 32, -15, -18, 13, -9, 2, 17, -14, 6, 36, + -9, 28, 1, 0, 17, -10, 5, 17, -8, 12, -2, 3, 2, -22, -6, -14, + 6, 8, -11, -14, 2, -23, 25, -35, 3, -18, 1, -14, 22, -1, -12, -7, + -9, 13, -4, 12, 4, -3, 18, 0, 1, 8, -14, 14, -2, 1, 17, -3, + -14, 35, -17, 19, -14, -6, 1, -9, 18, -17, -4, -13, -2, -14, 10, -10, + -6, 0, 3, 5, -12, -13, -3, -6, -6, 11, -13, -7, 13, -2, 6, 13, + -7, 11, -5, 23, 1, 29, -17, 23, -10, 18, -16, 12, -20, 10, 7, -9, + -5, -21, -9, 5, -13, -2, 0, -15, -11, 3, 0, -18, 5, -25, -2, 3, + -2, -3, 4, 8, 14, -7, 15, 4, 8, 19, 9, 11, 7, -3, 14, -11, + 1, 15, -35, 3, 3, -10, -16, 0, -15, 2, 3, -12, 27, -23, 32, -15, + 10, -14, 3, -27, 10, -15, 12, -24, 7, 2, 9, -2, -2, -1, 3, 1, + 1, 8, -4, 0, 6, -6, 1, 1, -1, 8, -11, 31, -27, 13, 4, -3, + 5, -1, 0, 2, 9, 0, 12, -31, 4, -27, 1, -25, 20, -21, -14, 12, + -14, 0, -5, -23, 18, -1, 15, 19, -5, 20, -8, 14, -7, 16, 3, 0, + 8, 10, 0, -8, -10, 3, -8, 9, -12, 4, 15, -6, 2, -12, -29, -3, + -16, -11, 35, -18, -1, -28, 7, -12, 0, 7, -5, 22, 10, 10, -4, 6, + -13, 21, -23, 20, 8, -13, 11, 15, -6, -6, -22, -1, 3, 14, 7, 11, + -27, 12, -17, -12, 8, -15, 3, -8, 12, -12, 5, -30, 12, -18, 9, -2, + 3, 4, 15, 1, 5, -9, 0, -8, 24, -2, 21, 5, -4, -4, 14, -15, + 0, -1, 3, 17, -5, 13, -19, -10, -4, -6, -4, -7, 18, -27, 8, 1, + -12, -21, -13, 1, -9, 11, 1, -3, -1, 22, -21, 9, 6, -3, 20, -2, + 17, 7, -12, 1, 4, 4, -9, 9, -20, 24, 7, -9, -3, -7, -6, 10, + 7, 3, 9, -2, -3, -4, 1, -19, -8, -16, 0, -12, 0, -25, 4, -22, + 10, -9, 0, -3, 15, -1, 8, 11, -15, 10, 13, 1, 22, -5, 15, 1, + 24, 6, 0, -6, 5, 5, 10, 8, -1, -11, -14, 3, -31, 2, -22, -4, + -8, -15, -2, -31, -12, 6, -7, 5, 2, 3, -4, 19, 3, 4, 7, 7, + -8, 31, -6, 26, 1, -2, 2, -3, -10, -4, -4, 9, 3, 12, -16, 16, + -9, -1, 5, 4, -7, 13, -17, 0, -11, -13, -22, 1, -9, 4, -7, 7, + -10, 5, -1, -6, -3, -21, 7, -10, 18, -3, 1, -7, -11, 11, -8, 12, + 20, 3, 13, 16, -1, 3, 13, -3, 23, 16, -3, 15, -14, 12, -6, -8, + -28, 0, -33, 4, -11, -12, -13, -21, -17, -16, -5, -12, 16, -7, 15, -6, + -5, 3, -9, 21, 17, 13, 14, 11, 21, -12, 31, -18, 7, 12, 8, 9, + 7, 1, -3, -7, -14, 17, -35, -10, -2, -18, -8, -10, -20, -22, 2, -10, + -3, 1, -1, 4, -5, 11, -20, 11, -6, 27, 7, 18, 8, -1, 2, 3, + 11, -9, 5, 5, -7, 29, -6, 20, -21, 23, -15, 19, -19, 2, -22, 11, + -26, -7, -10, -30, -1, -3, -6, 15, -22, 16, -7, -9, -2, -7, -5, 11, + 17, -13, 2, 8, -5, 6, 27, -6, 12, -6, 4, 15, 3, 14, -3, -12, + 11, -2, 6, 5, 4, -6, -12, 0, -32, 2, -22, 22, -12, -5, -7, -11, + -7, 6, -1, -3, -3, -16, 2, -1, 0, 0, -7, -2, 1, 12, -4, 5, + 20, 1, 16, -2, 14, -1, 19, 8, 29, -8, 7, -14, -2, 3, -13, 8, + -40, 22, -18, 2, -14, -8, -11, -8, 12, -21, -1, -10, -12, -6, -4, -14, + 6, -19, 7, 14, 1, 11, 11, -11, 25, 1, 14, -5, 31, 0, 22, 4, + 1, 3, 6, -3, 4, -2, -20, -7, -26, 1, -12, -7, -10, 2, -1, -5, + -7, -8, -10, 6, -7, -6, 10, -17, 6, 3, 15, -8, 15, -7, 12, 1, + 9, -4, -2, 10, 9, -1, 10, -4, 9, -8, 17, 0, -13, -7, -2, -11, + 3, -2, -15, -4, -11, -5, -9, 1, 8, -10, 8, -8, -6, -18, 21, -19, + 26, -19, -1, -11, 10, 4, 12, -10, 16, -10, 17, 8, 13, -1, 17, 1, + 5, -1, 11, -8, 9, 16, -17, 3, -26, -17, -14, 6, -17, 4, -20, 0, + -1, -6, -4, 2, -15, 13, -3, -1, 0, -2, -8, 11, 7, -3, -8, 5, + 14, -1, 28, -19, 13, -4, 8, 1, 11, 7, 6, -8, -2, -13, -10, -22, + 6, 11, -1, -1, -5, -13, 18, 3, -10, 9, -17, -8, 9, -9, 1, -17, + -4, -16, 18, -6, 15, -10, 17, 5, 0, -5, 0, -11, 12, 15, 4, 8, + 5, -4, 0, -2, 3, -17, -2, -1, 11, -6, -7, 2, -33, 23, -6, -1, + -2, -2, -1, -8, 3, -29, -2, -34, 16, -3, 16, 1, 10, -12, 23, 0, + -3, 16, 12, 19, 23, -1, 8, -26, 16, -32, 26, -13, 2, -11, 5, -1, + -15, -9, -16, 7, -6, 14, -15, 5, -10, -7, -9, -9, 6, -17, 13, 18, + -5, -3, -4, -4, -18, 28, -6, 13, 17, 24, -2, 9, -14, 1, -11, 7, + 17, 1, -15, 10, -23, -4, -12, 5, -20, 17, -10, 6, 0, -9, 4, -8, + -15, 6, -16, 7, 9, 3, 6, -12, -17, 0, 4, 13, 22, -4, 10, -8, + 7, -12, 5, 5, 1, 11, 2, 10, -3, -2, 3, -10, -5, -7, -4, -18, + 17, -2, -14, -16, -7, -10, -3, 6, -1, 14, -11, 15, -18, 2, -6, 0, + -1, 0, 20, -17, 1, 6, 2, 6, 12, -3, 7, 25, -5, 17, -14, 0, + -6, 0, -2, -5, -1, -10, 8, 2, -9, -19, -7, -17, 5, 3, -7, 4, + -15, -5, 9, -12, -1, -5, 3, -5, 26, -2, 3, -4, 5, 3, 7, 10, + 5, 6, 6, 26, -17, 0, -1, 3, -3, 10, -7, -7, -9, 11, -18, 0, + -16, -6, -5, 3, 7, -14, -14, 0, -21, 14, -8, -1, -12, 2, 1, 2, + -3, -1, -3, 18, 5, 5, 9, 12, 7, 18, 8, 5, -25, 16, -15, 16, + -7, 9, -22, 1, 14, -13, -5, 2, -6, -8, 13, -17, 6, -16, 1, -5, + -14, -6, -6, -15, -2, 9, -9, -18, 15, -19, 12, 7, 4, 8, 14, 15, + 6, 10, -3, 9, -7, 23, -17, 21, -20, 7, 0, -9, 8, -10, 1, 4, + 2, 3, -9, -9, -15, -6, -21, -16, -6, 0, -11, 19, -8, -9, 5, -6, + 0, 5, 14, 7, 1, 12, 8, 7, -5, 12, 8, -4, 19, 4, -7, 2, + 3, -12, -8, -1, 0, 5, 7, -5, -8, -22, -8, -21, -2, -9, 10, -20, + 13, -6, 8, -17, -9, -6, 2, 5, 8, 6, -3, 10, -9, -2, 15, -6, + 20, 7, 11, 10, -3, -4, -8, 25, -25, 18, -12, 17, -6, 20, -22, -1, + -17, -10, 5, -10, 9, -13, -9, -6, 10, -25, -5, -2, -5, 13, 2, -5, + -8, -10, 11, -27, 10, -4, 11, 0, 33, -4, 10, -14, 1, 12, -2, 27, + -8, 6, 11, 9, -12, -4, -10, -13, 12, 5, 1, -10, -14, -15, -8, -7, + -9, 3, -5, 10, 3, -11, -12, -13, -3, -3, 3, 2, 9, 17, -6, 25, + -3, -3, -8, 19, 3, 30, -10, 12, -22, 7, -5, -10, -3, 21, -8, 12, + 6, -5, -13, -13, -9, -9, -1, -23, 13, -17, 15, -22, -11, -18, 8, -14, + 20, 1, 4, -5, 3, 3, 5, 11, 1, 2, 27, 1, 10, -7, -8, -2, + -2, 7, -1, 17, -5, 24, -7, 5, -10, -20, -6, 5, -4, -5, -1, -18, + -5, -14, -1, -20, 1, 7, -7, 12, -4, -2, -4, 2, 8, 0, 7, 1, + 6, -2, 18, -5, -7, 4, 3, -2, 13, 4, 0, 2, -3, 2, -10, -6, + 1, -6, 6, -7, -3, -21, -2, -12, 5, -1, -9, 7, -3, 13, 5, 5, + -8, 0, -8, 19, -5, 13, 13, -7, 3, 0, -10, 0, -8, 20, -8, 13, + -20, -5, -7, 3, 5, -7, 2, -5, -4, -14, 11, -23, -13, 2, -1, 12, + 13, 5, -6, 23, -9, 9, -6, -9, 18, -13, 16, -3, -7, -17, 3, -13, + 12, -9, 4, 0, 0, 13, -18, -1, 3, -13, 20, -5, 1, -20, 15, -23, + 18, -4, -8, 5, -7, 16, 4, 6, -3, 7, -21, 19, -17, -7, 9, 5, + 3, -5, -3, -16, -9, 25, -9, 12, -5, 10, -5, 9, -4, -6, -3, 4, + 10, -2, 11, -12, -2, -14, 8, -23, -5, 0, -8, 9, -2, -11, -3, -9, + 9, 2, 2, 4, -5, 7, 11, -16, 0, -6, 7, 6, 25, 5, 6, -4, + 3, 4, 3, 2, -8, -3, 5, -1, -11, -4, -9, -3, -15, 10, -12, -5, + 11, -4, -7, 6, -29, -5, 6, 11, 3, 9, -18, 13, -14, 19, -1, -2, + 4, 5, 12, 1, 5, -8, 3, 1, 20, -6, 2, 3, -16, 10, -10, -18, + -11, -7, -7, 9, -4, -8, 9, -15, 13, -13, -3, -7, 3, 8, 11, -6, + -16, 1, -8, 20, 4, 15, -5, -3, 11, -5, 6, 0, -5, 10, 13, 0, + -6, -11, 0, 11, -11, 10, -7, -8, 1, 16, -9, 2, -22, -9, 0, 4, + 5, -12, -22, 2, -8, -8, 14, -16, 0, 13, 0, 9, -7, 2, -1, 7, + 8, -3, -3, 2, 15, 5, 10, -7, 12, -4, 22, -4, -3, -12, -2, -15, + 8, -2, -22, 7, -10, 5, 12, -20, -9, -11, -2, -12, 2, -9, 5, -3, + 11, 7, -9, 4, -4, 24, -7, 21, -15, -3, 2, 14, -1, 5, 18, -12, + 13, 3, 5, -10, -11, 0, -8, -2, -4, 2, -15, 9, -10, -16, -9, -7, + 0, -1, 3, -8, -10, 5, -8, 4, -3, 8, -2, 20, 1, 6, -4, -9, + 4, 14, 7, -1, 3, -5, 18, -7, 20, -6, -10, 8, 1, -2, 3, -4, + -5, -3, -6, 0, -16, -7, 12, 0, -17, 4, -31, -7, 1, 1, -4, 8, + -11, 6, -1, 11, -5, -7, -4, 2, 4, 15, -3, 21, -5, 20, 3, -12, + 21, -1, 10, 5, 6, -20, -1, -18, 2, 3, -4, -5, -1, 6, -2, -11, + -17, -15, -13, 0, 6, -18, 7, -18, 7, -7, 6, 7, -10, 18, 16, 2, + -1, 3, -11, 6, 14, 1, 15, -2, 29, -8, 17, -14, 2, -19, 12, 8, + -6, -1, -23, 6, -11, 7, -19, -18, 0, 1, -8, -8, -4, -20, 8, -8, + 4, 10, -12, 13, 0, 18, -10, -3, -4, 6, 4, 17, 7, -2, 18, -9, + 14, -10, -4, -11, 4, 3, 23, -17, -6, -2, -7, -7, 9, -10, 1, 2, + -4, -14, -7, -6, -8, -4, 7, 2, -3, 3, 0, 13, -10, -4, -9, -6, + 18, 11, -4, 16, -8, -4, 1, -1, 7, 3, 3, 3, 10, -15, -2, -9, + 9, 0, 2, 2, -9, 12, -7, 0, -23, -7, -19, 2, -1, 0, 4, -15, + 7, 3, -3, 0, 9, -12, 19, 4, 8, -13, -6, 5, -1, 14, 10, 9, + 13, -3, 16, -18, 13, -18, 7, -10, 13, -6, -11, -3, 7, -23, -6, -11, + -21, 9, -1, 4, -3, -16, 0, -12, 7, 14, -5, 15, 0, 6, -5, -3, + -9, 9, 4, 10, 4, -2, -7, 10, -1, 10, -6, -14, 15, -4, 13, -4, + -4, -14, 5, -2, 4, -9, 3, -14, 2, 3, -10, -1, -9, 0, 3, -6, + 12, -16, 0, 4, 10, -25, 6, -5, 2, 8, 3, -2, -4, 15, 4, 7, + 2, -1, -6, 10, 11, 2, -2, -14, 6, -3, 0, -3, -9, -10, 1, -1, + -15, 9, -29, 9, -10, 7, -3, -3, -10, -2, 14, 4, -6, 0, 1, 12, + 4, 18, -15, 19, 1, 15, 1, 1, 3, -10, 8, -1, 7, -30, 8, -19, + -2, -5, -9, -10, 0, -1, 6, -4, -12, 1, -18, 10, -1, -12, 2, 7, + 12, 11, 0, -4, -1, 6, 10, 17, -8, 1, -12, 5, -2, 1, -7, -1, + 4, 3, -3, -1, -18, 8, -9, 0, -2, 8, -12, 12, 7, -5, -2, -16, + -7, 9, -5, 11, -9, -4, 3, 1, -9, -1, -2, -6, 7, 12, 0, -8, + 9, -10, 3, 0, 2, -3, 11, 14, 4, 3, -12, 3, -3, 2, 12, -4, + -2, -2, 9, -21, -5, -28, -6, -10, 6, 7, -6, -3, -24, 7, -11, 10, + 0, 8, 13, 10, 6, -7, -2, -5, 7, -1, 9, 18, -2, 12, -4, 7, + -26, 13, -6, 19, 6, 6, -5, -16, -6, -8, -18, -2, 1, -11, 3, 4, + -16, -8, -10, -3, 2, -3, 5, 5, 0, 11, 0, -14, 0, 1, 14, 11, + 13, 0, -2, 5, -1, -4, -2, -4, 5, 21, 3, 14, -5, -22, 5, -11, + -3, -6, -3, -11, 0, -5, -13, -10, -18, 3, 9, -10, 2, 3, -11, 11, + -11, 5, -19, 23, -1, 20, 18, 4, -3, -6, 9, 4, -3, 8, 4, 6, + 2, 5, -14, -6, -3, 2, -6, -4, -3, -11, 0, -5, 0, -21, -2, -10, + 11, 5, -4, -5, -5, -8, 10, -10, 4, -1, 6, 12, 9, 2, 8, -20, + 8, -2, 11, -11, 1, -4, 5, 6, -6, 6, -14, 14, 4, -2, 12, -3, + -10, 8, -5, -15, -9, -1, 5, 8, -3, 0, -23, -9, -11, 4, -12, 3, + -4, 4, 1, 15, -12, 3, 13, 2, 5, 8, -8, 7, 11, -3, 17, -11, + 5, 3, 19, 13, 3, -11, -11, -2, -9, -7, -4, -24, -1, -17, -3, -17, + 0, -15, 2, -1, -5, -4, 3, 2, 2, 11, -4, 3, -6, 11, 8, 3, + 6, 3, 7, 7, 6, -6, 2, 0, 14, 14, 3, 8, -6, 4, -3, 6, + -13, -2, -9, -4, 5, -13, -5, -21, -1, -6, -1, -5, -14, 8, -7, 5, + -7, -17, -11, 7, 3, 20, 7, 1, -3, 4, 5, 14, -3, 5, 3, 10, + 8, 6, -6, -2, 6, 3, 7, -6, -3, -3, -6, -1, -27, -11, -17, 0, + 11, 7, 1, -7, -9, -13, 5, -11, 0, -10, 15, 2, 5, -2, -5, 1, + 6, 6, -6, -5, 6, 2, 5, 3, 10, -16, 11, 8, 18, 3, 13, -11, + 7, 5, -7, -6, -20, 15, -1, 10, -1, -13, -17, -11, -3, -13, -4, -14, + -3, -2, -6, 6, -28, 9, -8, 10, 0, 12, -2, 10, 9, 1, 3, -6, + 5, 17, 24, 18, 3, 4, -9, -4, 2, -8, -4, -2, -11, 1, -8, -12, + -9, -10, 5, 0, -7, -9, 7, -18, 6, -10, -12, -1, -1, 13, 1, 18, + 2, -3, 4, 3, 3, -3, 3, 10, 9, 7, 5, -8, -7, 0, 3, -7, + 7, -2, -2, 5, -10, 2, -5, -3, -1, 4, 1, -2, -10, 4, -9, -5, + -12, -18, 3, 6, -3, 3, -15, -1, -13, 6, -2, 8, 0, 8, 16, -2, + 17, -4, 8, 3, 23, -1, 11, -8, 10, -4, -5, -3, -13, -2, -1, -2, + 2, -9, -13, -13, -2, -11, -2, -20, -5, 0, 3, 2, -1, -10, 1, 8, + 3, 9, 6, 4, -3, 13, 3, 4, 11, 2, 11, 8, -2, -1, -2, -2, + -2, -1, -21, -1, -14, 8, 6, -8, -10, 2, -16, 4, -3, -1, -10, 7, + -1, 4, -4, -12, 3, -2, 13, 2, -3, -9, -2, 6, -7, 8, -8, -5, + 12, 7, 8, -3, 6, -1, 16, 0, 7, -8, 3, -7, -1, 0, -6, -4, + -8, 6, -1, 4, -19, 2, -3, -8, -3, -12, 4, -6, 2, -7, 1, -13, + 2, 9, -1, 17, -19, 3, -3, 23, 9, 6, 3, 6, 6, -5, 11, -11, + 1, 0, -5, 6, -6, -4, -5, -7, 3, -4, -14, -9, -7, -1, 5, -11, + 4, -19, 14, -4, 3, 4, 2, 0, 9, -2, -3, 2, -2, 10, 15, -3, + 14, -6, -4, 6, 1, -8, 11, -9, 4, 3, -9, 2, 2, -2, 2, -2, + -9, -2, -2, 1, -6, -6, -22, -16, -10, 12, 0, 5, -8, -2, -4, -2, + 5, -1, 7, 7, 9, 1, 7, 6, -1, 10, 11, 5, -3, 8, 1, -1, + 8, -15, -6, -10, 12, 0, 2, -5, -9, -12, -7, -4, -14, -4, 0, -1, + 5, -7, -8, -12, 0, 2, 16, -3, 11, -4, 16, 11, 2, -3, 2, 8, + -1, 7, -13, 4, -3, -1, 3, -10, -2, -11, 3, 2, 3, -7, -10, -5, + -10, 12, -8, 5, -7, 15, 1, -10, 7, -16, 1, 3, 4, -5, 7, -7, + 4, -2, -1, -8, 0, -2, 17, 10, -2, 6, -5, 3, 10, -7, 2, -3, + 4, 5, 5, -3, -8, -8, -1, 1, 7, -5, -11, -2, -10, -4, -15, -7, + -10, -2, 2, -4, -10, -8, 0, 2, 6, 3, 2, 3, 10, 14, 8, 7, + 3, 5, -5, 20, -6, -1, -2, 0, 1, -2, -2, -8, 3, -3, 10, -14, + 3, -3, -2, 0, -5, 0, -15, 4, -2, 0, 4, -7, 3, -8, 7, -14, + -2, -6, 4, 2, 3, -10, -2, 5, -3, 12, -2, -5, -9, 1, 4, 1, + 11, -12, 15, 5, 20, 10, -5, 1, 5, 3, -13, 6, -16, 5, 1, -5, + -8, -3, -14, -6, -2, -5, -8, -17, -9, 3, -6, -2, -3, -3, 1, 14, + 2, 4, 5, 3, 8, 7, 12, 0, 11, 4, 16, 2, -3, -9, -1, 1, + -1, -3, -6, -14, 4, -6, 2, -14, -9, -11, -1, 0, 0, -5, -6, -10, + 5, -5, 2, -3, 2, 2, 17, -2, -1, -3, 3, 11, 1, 10, 2, 7, + 6, 5, -5, -3, -3, -2, 7, 2, 1, -18, -5, -2, -3, -5, 0, -2, + 0, 8, -9, -10, -15, -7, -2, -1, 6, -8, 16, -10, 13, -4, 2, -4, + 4, 7, 9, 6, -5, -2, 8, -1, 11, -6, -1, 5, 8, 0, 9, -20, + 0, -9, 4, -3, 1, -4, -11, 2, -6, 0, -12, 0, 1, 5, -2, 1, + -7, -4, 3, -1, -10, 3, -3, 7, 4, 8, -9, -6, -10, 0, 0, 2, + -4, 6, 9, 10, 2, 0, -1, 2, 14, 3, 7, -7, 2, -2, -2, -6, + -9, 2, -3, 6, -3, -7, -9, -10, -2, 2, -1, -11, 2, 1, 7, -4, + -7, -19, 3, -1, 6, 6, 6, 6, 0, 6, 7, 3, -1, 3, 8, 3, + 4, -10, -5, -7, 5, -4, -14, 2, -8, 5, -2, 2, -16, -4, -11, 2, + 4, -1, 2, -1, 0, 5, 4, -12, 3, 9, 7, 13, -3, -7, 2, 6, + -1, 7, -1, -1, 5, -5, 7, -11, -9, -13, 2, 5, 2, -2, -7, 5, + 4, -4, -2, -15, -4, 3, 0, 0, -5, 2, -7, -1, 9, -2, -1, 5, + 1, 1, -4, -5, -4, 6, 8, 7, -5, 4, -7, 4, 0, 1, -6, -5, + -2, 5, -1, 0, 1, 1, 3, 9, -4, -2, -4, -9, -1, 4, -17, 1, + -13, 11, -1, 6, -9, -1, 5, 1, 8, -3, 4, -5, 1, 7, -5, 1, + -3, 5, 3, 4, -7, -11, -7, 1, 5, -13, 11, -11, 1, 3, 6, -9, + 6, -5, -7, 4, -13, 5, -7, 10, 5, 6, -15, -1, 6, 4, 18, -7, + -7, -3, -4, 2, -5, 3, -4, 9, -4, 3, 3, -3, -10, 0, -1, 2, + 5, -3, 7, 3, 2, -6, -11, -2, -1, 4, -5, 4, -5, 0, -5, 5, + -5, -4, 2, 4, 2, 5, -8, -13, -3, 0, -1, -2, 4, 6, 9, 1, + 3, -7, -1, 1, 12, 1, 1, -1, -5, -1, 2, -8, -9, -7, -2, 3, + 10, -6, -7, -12, -7, -4, -5, 6, 0, 10, 5, 7, -4, -2, -8, 10, + 5, 9, 4, -1, -1, -1, -1, -1, -2, -3, 3, 9, -2, 9, -14, -13, + -8, -10, 1, 1, 3, 3, 1, -3, -12, -5, -7, 1, 6, 6, -2, -7, + -3, -3, 2, 2, 4, -9, 14, 8, 11, -3, 5, -11, 1, -1, 5, 3, + 8, 2, 8, -2, -6, -13, -10, 0, 4, 3, 4, -3, -9, 1, -5, -5, + -6, 1, -2, 2, -10, -6, -15, 1, -5, 4, -1, 2, 2, 4, 10, 4, + 2, -13, 0, 4, 8, 17, 2, 5, 4, 2, -6, 5, -5, 0, 8, -2, + -1, -5, -4, -5, -1, -5, -4, -5, 0, 0, 1, -9, -15, -3, -12, 1, + -1, -7, 10, 2, 5, -1, 2, -6, 2, 2, 10, 10, -1, 2, -2, 4, + 5, 0, -6, 12, 5, 3, -1, -8, -8, -4, -4, 3, -11, 0, -1, -1, + 0, -2, -14, -6, -9, 2, 1, 7, -4, 3, -1, 0, -3, 1, 2, 7, + 5, 4, 3, -2, -3, 1, 6, -1, 6, -11, 7, 2, -6, 2, -4, 0, + 2, 3, -7, -9, 3, 0, 4, -6, 0, -21, 0, -5, -1, 0, -1, 1, + -6, -1, -1, 0, -7, 5, 7, -2, 8, -4, -1, 3, 9, -6, 10, -6, + 7, 9, 10, 9, -6, 5, -14, 6, -5, 1, 2, -3, 0, -9, -10, -14, + -2, -3, 6, -8, -15, 3, -9, 0, -3, 0, -6, -1, 3, 9, 10, 3, + 3, -10, 6, 1, 3, -1, 9, 12, 4, 4, -9, -7, -5, 8, 6, 1, + 1, -4, -5, -5, -1, -11, -3, -4, 1, -1, 1, -10, -7, -2, -3, -4, + -3, -6, 11, 5, 3, 2, -8, -5, -2, 3, 9, 13, 5, 4, 4, 0, + -5, -1, -5, 9, 2, 3, -9, -4, 3, -6, 2, 1, -9, 5, -2, 3, + -2, -9, -8, -15, -5, -3, 3, -13, 11, 6, -3, 1, -6, -6, -1, 6, + 4, 6, 7, 1, 5, 0, 8, -6, 7, 2, 6, 2, -5, 0, -3, -1, + 3, -7, -1, -3, 5, 7, 6, -18, -10, -11, -7, -3, 10, -4, 3, -4, + -8, -5, -12, -3, -4, 12, 10, 2, -4, 6, 3, 1, 2, 0, -3, 3, + 7, 7, -5, 2, -4, 1, 3, 11, 2, 3, 4, -2, -7, -5, -17, -11, + 4, -3, 5, -7, -7, -6, -1, -8, -5, -5, 1, 7, 1, 2, -1, -9, + 7, 1, 7, 3, 3, 6, 9, 6, 1, -6, -4, 2, 5, 7, 4, -2, + 1, 3, -11, -1, -16, -2, -6, 1, 3, -8, -15, -11, 4, -1, 9, -2, + -5, 0, 6, 0, -7, 0, -8, 4, 2, 6, 2, 0, 2, 6, 2, -2, + 4, -2, 4, 14, 2, 2, -6, -6, -3, 4, -4, -1, -4, 1, -3, -6, + -1, -13, -1, -2, 7, -8, -7, -10, 0, 4, 3, -8, -3, 1, 4, 6, + 4, 6, -3, 5, 3, 4, 0, 6, 1, 4, 7, -3, -10, 8, -1, 9, + -1, 1, -11, -7, -3, -3, -6, -8, -9, -6, 1, -3, -6, -6, -5, 0, + 0, 2, -3, 0, 6, 4, 3, 2, 7, 4, 11, 14, 5, -1, -5, 1, + -2, 7, 3, 0, 1, 2, -5, -7, -10, -12, -10, -5, -5, -6, -6, -9, + 1, -8, -2, -1, -9, 1, 8, 2, -5, -2, -5, 0, 5, 6, 6, 7, + 8, 10, 2, 0, -3, -1, 2, 13, 3, 0, -6, 0, 1, -3, 0, -12, + -2, 4, -4, 4, -8, -11, -1, -2, 1, -1, 2, -12, 3, -6, 1, -12, + -7, -7, 3, 0, 9, 0, 1, 6, 1, -1, 2, 1, 2, 8, 9, -3, + -1, 0, 7, 3, 8, -1, -4, -1, 1, 3, -9, -1, -17, -3, -2, -4, + -4, -3, -4, -6, -11, -15, -2, -5, 6, 10, 1, 3, -1, -3, 13, 7, + 1, 6, 4, 4, 9, 5, -3, -5, 9, 3, 5, -3, 1, -3, 3, 0, + -7, -5, -7, 0, -5, 0, -1, -15, -11, -4, -5, -10, 2, -7, 5, -4, + 1, -9, 2, 1, 8, 7, 10, 2, 2, 0, 4, 3, -2, 0, 4, 2, + 6, 8, -2, 4, 4, -2, 5, -3, -6, 3, -3, -5, -9, -8, -11, -5, + -1, -1, -5, -7, -5, -8, 0, -3, 5, -7, 11, 1, 0, 2, -3, -1, + 3, 9, 6, -3, 8, 1, 11, 2, 8, -3, -3, 6, 2, 1, 2, -7, + -3, -2, -4, -8, -3, -3, 5, -10, -10, -4, -12, -2, 3, -5, 3, -6, + -8, -2, 5, -3, 0, 1, 4, 8, 4, 5, 0, 4, 8, 1, 7, -3, + 0, 3, 4, 4, -5, -2, -7, -3, 0, 5, -5, -9, 3, -2, -1, -2, + -5, -1, -4, -3, -11, -4, -5, -6, 0, 5, 0, -5, 5, 3, 8, -1, + 3, 3, 2, 5, 7, -4, 3, 1, 3, 10, 2, -7, 1, 0, 6, -4, + -3, -5, -7, -2, -4, -3, -6, 0, -10, 4, -6, -4, -7, -2, 1, -4, + -1, -3, -1, 2, 6, 2, 4, -2, 2, 4, 2, 5, -3, 4, 2, 1, + 0, 8, -3, 2, 5, -5, 3, -5, -2, 5, -5, 3, -1, -4, -3, 4, + -10, -5, -7, -4, -4, 0, 0, -7, -1, -1, 2, 1, -2, -12, -4, -1, + 0, 4, -5, 2, 0, 3, 12, 11, 3, 11, -1, -3, 6, -6, 1, 1, + 7, 6, -7, -1, -7, -4, -4, -7, -8, -1, -6, -6, -2, -3, -5, 0, + -4, 8, -7, 1, 4, -3, 6, 1, -7, 3, 5, 6, 5, 13, 2, 2, + -4, 4, -3, 1, 4, -4, 2, -3, -10, -10, -7, -2, -2, -2, 0, -6, + -2, 1, -3, -4, -2, -5, -2, 7, 1, 6, -5, 6, -1, -1, 2, -3, + 4, 11, 2, -1, 2, -7, -5, 8, 0, 3, -3, -5, -1, -2, 3, 1, + -4, 4, 7, 0, 2, 3, -3, 0, 1, -5, -15, -5, -3, 1, 3, -3, + -11, -4, -7, 1, -2, -1, -1, 0, 1, 1, -5, -1, 3, -2, 7, 1, + -4, -1, 0, 4, 5, 3, 3, -1, 8, 11, 1, 4, 1, -5, 7, -6, + -4, -2, -4, -2, 3, -8, -3, -13, -6, 3, -3, -7, -4, -7, 3, 3, + -3, 2, -1, 1, -4, -2, -2, -5, 1, 11, 9, -2, 6, -3, 7, 7, + 1, 1, -7, 2, -3, 1, 4, -4, -4, 5, 1, 0, -3, -6, 2, -3, + 0, -8, -12, -6, -2, -3, 6, -1, -9, 0, -1, 1, 3, -2, -1, 0, + 1, 6, 0, -3, 5, 1, 6, 1, -1, 4, 1, 7, -3, -1, -1, -4, + 4, 14, -1, -1, 2, -4, -1, -6, -8, -8, -3, -2, 2, -9, -5, -7, + -12, 5, 0, -3, -4, -3, 5, 4, 3, -2, -6, 4, 7, 3, 5, 7, + -3, 8, 0, -5, -1, -1, 11, 10, 3, 4, -8, -3, -3, 1, -3, 0, + -4, -3, 1, -7, -8, -16, -7, -6, -2, 3, -7, -2, 1, -4, 0, -5, + -5, 1, 5, 10, 5, 0, 3, 0, 1, 13, 0, 5, 9, 6, 8, -1, + -4, 0, -3, 6, 4, -4, 0, -3, -15, -2, -12, -15, -3, -6, 2, 1, + -3, -4, -9, -9, -3, -3, -2, 3, 4, 9, 0, 2, 1, 2, 14, 5, + 3, 8, 2, 7, 4, -4, -4, -1, -9, 9, -5, -1, -7, -10, -2, -7, + -4, 0, -5, 2, 5, 1, 0, -5, -5, -1, -1, -3, 4, -8, 5, 3, + -4, 4, -5, -3, 9, 4, 8, 0, 0, 2, 0, -2, 0, -2, -7, 12, + -1, 5, -4, 2, -3, 0, 2, -2, -4, -2, 2, -5, 3, -7, -9, -4, + -3, -2, -6, -6, -2, -6, -1, -7, -8, 1, 3, 6, 10, 4, 5, 0, + 5, 8, 1, 3, 8, 5, 11, 12, -7, 4, 0, -3, 2, -1, -8, -7, + -4, -2, -6, -9, -6, -13, -4, -1, 0, -9, -5, -3, -4, -2, 3, 1, + 1, 9, 4, 2, 6, -1, 3, 6, 2, 0, -3, 3, 2, 6, 3, -1, + -4, 4, 1, 2, 2, -5, -8, -1, -3, -1, -9, -4, 1, -5, 5, -7, + -4, 0, 3, -10, 3, -3, -5, 1, 5, 4, 1, -5, 1, -5, 4, 1, + -6, 0, 5, 8, 8, 1, 6, 0, 3, 4, 2, -3, 1, -3, -3, 3, + -10, -6, -8, -2, -1, -3, -6, -6, -5, -6, -6, -5, 5, -3, 5, 6, + -2, -1, -1, -4, 6, -2, 6, 6, 2, 12, 8, -2, 3, -6, -2, 5, + 4, -3, -2, -5, -4, -7, -6, 1, -5, 2, 2, 0, 1, -7, 0, -4, + -2, -1, -2, -5, 7, -5, -2, -3, -2, -3, 4, 4, 9, 0, 1, 1, + -5, -3, -4, -4, 4, 3, 6, 1, -2, -2, -7, 4, 1, 1, -3, 3, + -1, 2, 0, -7, 0, 0, -1, -3, -2, -1, -5, -2, -3, -8, -5, -5, + -1, 5, 5, 2, 2, -3, 4, 3, 4, 6, 3, -1, 10, -4, -3, -2, + -3, 0, -4, 0, -2, -2, 0, 2, -5, -2, -5, -9, 8, -2, -1, -1, + -3, -3, -2, -6, 2, 1, 2, 9, 0, 1, 4, -5, 2, 4, -6, -1, + 2, -1, 6, 3, 0, -5, -3, -1, 0, 3, -3, 0, -6, -2, -3, -4, + -2, 0, 3, 2, 2, 0, -10, 1, -6, -5, -1, -2, 5, 3, 6, -2, + -6, -1, -3, 2, 4, 1, -1, 0, 1, 1, 3, -1, 5, -1, 7, 6, + 1, -2, 0, -6, -2, -2, -8, -2, -2, -3, -5, -5, -8, -3, -1, 5, + -3, 1, 2, 1, 2, -3, -2, -3, 2, 6, 2, 6, 0, 0, -2, 9, + -1, 3, -2, 3, 0, 0, 0, -6, -6, -1, -5, -7, 1, -3, -6, 2, + -2, -1, -5, -2, 1, 4, 2, 2, -3, -1, 6, -2, 2, 4, -3, 2, + 2, 2, -3, 1, 0, -4, 2, -1, -2, 3, 1, 1, -1, -5, -8, -2, + -5, 0, 1, -6, 3, -4, 2, 3, -6, 3, 0, 2, -2, -1, -4, -2, + -4, 4, 0, -3, 0, -6, -3, 10, -3, 3, 0, 4, 7, 3, 0, 5, + 1, 5, 1, -3, -2, 0, -6, 3, -1, -7, -5, -7, -1, -2, -2, -2, + -3, -2, 2, -2, -1, -3, -3, 2, -2, -6, -3, -3, 4, 3, 2, 0, + -1, 5, 5, 8, 2, 2, -2, 4, 0, 5, -5, -3, -1, -3, -3, -6, + -4, -2, 3, 0, -2, -2, -5, 5, -1, 3, -1, -1, -3, 0, 0, -5, + -4, -3, -2, 5, 0, -4, -4, 1, 2, 6, 0, -3, -1, 2, 3, 7, + -3, 0, -4, -2, 4, 3, 0, 1, 3, -3, 1, -7, -4, 0, 1, 1, + -4, -4, -4, -9, -1, -2, -3, -2, -3, -3, 4, 3, -1, -4, 2, 4, + 4, 3, 2, -1, 0, 9, -1, 4, 2, 7, -1, 6, -2, -2, -5, -1, + -9, -2, -2, -6, -1, -1, 1, -8, -6, -5, -1, -1, 1, -4, -5, 3, + 1, 5, 3, -3, 0, -2, 7, 0, 1, -2, 3, -1, 5, -1, -5, 7, + -1, 3, 2, -5, -6, -2, 4, 2, -1, -3, -1, -1, -1, -1, -2, -4, + 1, -5, 3, -1, -3, -5, 2, 6, -6, -1, -5, -4, 4, -1, -1, -2, + -1, 2, 0, 3, 1, 4, 2, 7, -1, 2, 0, -2, 1, 4, -5, -3, + -7, -2, 0, -1, -1, -3, 0, 0, -2, -6, 2, -4, 2, -4, 1, -7, + -2, -1, 5, 3, -2, -7, -4, 1, 6, 4, 5, 1, 4, 0, 5, 1, + -1, 2, 0, -3, -3, -5, -6, 3, -1, 5, -1, -2, 1, 1, 4, 2, + -6, -3, -4, -3, 2, -2, -8, -3, -6, -4, -2, -11, 0, 0, 1, 6, + -3, -2, 1, 2, 10, 8, 4, -2, -1, 2, 2, 1, -2, 3, 1, 5, + 3, -1, 0, -4, 4, -7, -2, -7, -8, -4, -3, -2, -7, -7, -3, -1, + 5, -2, 0, -7, 2, -1, 3, 1, 4, 6, 5, 8, 3, 2, -1, 3, + -3, 0, 0, -5, -1, 1, 1, -5, -3, -2, 6, 4, 5, -4, -8, -4, + -3, -2, -5, -4, -4, -4, 2, -3, -2, -4, -4, -4, 6, 1, 0, 1, + 3, 3, 5, 2, 1, 0, 6, 2, -1, 1, -3, -3, 2, -1, 0, 1, + 3, 1, 4, -4, -5, -10, -8, 1, -6, -3, -4, -6, -3, 0, 2, -3, + -1, 2, 0, 8, 1, 4, 4, 3, 6, 3, 1, 3, 5, 1, 2, -4, + -7, -3, -3, 3, 0, -7, -5, 0, -3, -1, -2, -4, 0, -5, 1, -6, + -1, -5, -3, 1, 4, -1, -3, 3, 3, 5, -1, -2, 2, -1, 2, 1, + -1, -5, 5, 1, 2, 2, -4, 0, -1, 3, 0, -2, -1, 2, 1, 5, + 4, -3, -5, 0, -2, -2, -6, -3, -3, -4, -1, -5, -4, -1, -2, 0, + 2, -2, -6, -3, 1, 1, 1, -1, 3, 4, 7, 2, 3, 4, -1, 7, + 2, 3, 1, -1, 1, -2, 0, -4, -5, -6, 0, -2, -7, -2, -5, -5, + 1, -4, -5, -5, 3, -1, 1, 2, -2, 0, 1, 4, 1, -4, 2, 2, + 0, 9, 2, 0, 4, 3, 1, 2, -4, -2, -4, 3, -4, -2, -6, 0, + -1, 5, 2, -4, 0, -4, -4, -1, -5, -4, -7, -3, 1, 0, -2, -1, + -5, 1, 0, -1, 0, 2, 4, 0, 3, -2, 1, 2, 6, 0, 1, 5, + 0, 3, 3, 2, -5, -2, 1, 5, 2, -2, -5, -9, 0, -6, -1, -6, + -7, -5, -4, 0, -2, -5, -3, 2, -2, 3, 2, 0, 9, 2, 0, 4, + -3, 4, 5, 8, 6, -2, -4, -1, 0, -2, -2, 1, -5, 2, -5, -1, + -4, -3, -4, 0, -2, -7, -3, -1, 0, -1, 0, -6, 3, -2, 5, 2, + -1, -2, 1, 0, 1, -1, -3, 2, 3, 1, 2, -4, -3, -1, 5, 5, + 3, -4, 0, 1, 2, 5, -5, 1, -5, 2, -2, 2, -4, -3, 0, -4, + -3, -9, -7, -4, 2, -2, 1, -6, -3, 0, 1, 5, 1, -5, 0, 0, + 2, 1, 2, 0, 6, 4, 6, 3, 2, 3, 1, -2, -2, -9, -4, -1, + 4, 0, -1, -5, -8, -5, -4, 0, -4, -1, -3, 0, 0, -4, -3, -1, + 1, 2, 0, -2, -3, 1, 3, 2, 3, 3, 0, 8, 2, 7, -1, 3, + -2, 4, 0, 0, 1, -4, 5, -1, -3, -3, -6, -4, 2, 1, -5, -4, + -7, -4, -4, -7, -2, -10, 1, 0, 1, -3, 4, -2, 5, 2, 1, -3, + -1, 2, 8, 4, 5, 0, 1, 4, 5, 2, 2, -2, 1, -4, 0, -3, + -3, -1, 0, 2, -4, -4, -5, -1, -7, 0, -4, -5, -1, -3, 2, -2, + 0, 3, 0, 2, 0, 1, -2, 2, 4, -1, 0, -3, -1, 1, 3, 2, + -3, 2, 0, 2, 2, -1, 2, -2, -3, 0, 0, -2, 2, -2, 4, -3, + -6, -7, -6, 2, -1, -4, -1, -7, -1, -3, 3, -1, 0, -2, 2, 2, + -3, 3, -4, 5, 7, 6, 3, 1, -1, 6, 2, 1, 0, -1, -1, 1, + -3, 1, -3, -5, -5, -3, -8, -3, -11, -1, -1, 0, -8, -2, -5, 3, + 4, 0, 1, -2, 2, 0, 6, 4, 1, 4, 1, 5, 0, 0, 1, 2, + 5, 0, 1, -10, 0, -5, 2, 0, -6, -6, -2, -2, 2, -3, 0, -4, + 2, -4, 1, -3, -4, 1, -2, 2, 1, -2, 0, 3, 2, -3, -1, -5, + -3, 4, 2, 3, -1, 4, 1, 5, -1, 2, -3, 2, -3, 0, -3, -2, + 1, 1, 5, 1, -2, -5, 1, -1, -4, -3, -7, 0, -5, -4, -4, 0, + -4, 4, 0, -1, 1, -8, 1, 0, 9, 1, 2, -2, 5, 5, 1, 6, + -1, 6, 3, 1, 1, -2, -2, -4, -3, -2, -3, -7, -4, -4, -1, -3, + -8, -1, -8, 4, -5, 0, -3, 1, 0, 4, -1, 0, 1, 3, 3, 4, + -4, 6, -2, 2, 5, 4, -3, 4, -3, 5, 0, -4, 0, 0, -1, 0, + -4, -4, 3, -1, -2, -4, -8, -9, -5, -4, 4, -4, 1, -4, 1, 1, + -1, -1, -1, 3, 2, 3, 0, 1, 2, 1, 5, 3, 1, 0, 5, 3, + 3, 0, -5, -4, -2, 5, 0, -2, -5, -2, -6, -2, -5, -8, -2, 1, + -1, -3, -7, -8, -6, 0, 4, 7, -2, 7, -1, 7, 3, 2, -5, 0, + 2, 0, 1, -3, 2, 2, 3, 3, -3, 0, -2, 3, -1, -1, -4, -6, + -2, -3, 4, -4, 0, -4, 6, -2, -6, -2, -7, 1, 2, -1, -3, -2, + -2, 3, -1, 0, -3, -1, 4, 7, 4, 0, 2, -1, 0, 6, -2, 1, + 1, 5, 4, 1, -3, -3, -2, 2, 2, 1, -6, -6, -3, -4, -2, -6, + -5, -4, -5, -2, -8, -8, -3, 0, 4, 0, 1, -1, 2, 5, 4, 2, + 2, 3, 3, 4, 10, 0, 2, 0, 3, 1, 1, 0, -3, 1, -3, 1, + -7, 0, 1, -2, 1, -6, -4, -10, -1, -4, -2, -2, -3, 2, -4, 1, + -5, -4, -4, 2, 1, 1, -4, -1, 3, 1, 6, 2, -2, -2, 3, 3, + 2, 7, -5, 5, 0, 8, 1, -1, 2, 3, -1, -6, 0, -10, 3, -1, + -1, -5, -6, -8, -2, 0, -3, -5, -8, -4, 2, -3, -1, -2, 0, -1, + 7, -1, 3, 2, 4, 7, 3, 4, -1, 5, 1, 9, 1, -2, -1, -1, + 1, -3, -2, -6, -7, 1, -3, -1, -9, -4, -6, 0, 2, -3, -2, -4, + -3, 0, -4, -1, -4, 0, 1, 6, -1, 1, -1, 3, 5, -1, 3, 4, + 5, 7, 4, -2, 0, -2, 0, 3, 1, -1, -8, -2, -1, -2, -5, -1, + -2, -2, 2, -5, -7, -9, -2, -3, -2, 1, -5, 4, -4, 5, -1, -1, + -3, 2, 3, 7, 3, -1, 3, 4, -1, 5, -4, 0, 4, 4, 3, 4, + -9, 1, -5, 2, -2, -2, -3, -7, -1, -2, -2, -5, -3, -1, 1, -2, + -1, -4, -4, 1, -1, -7, 0, -1, 2, 5, 4, -4, -5, -4, 0, 2, + 1, -1, 3, 5, 4, 0, 0, -1, 3, 8, 3, 3, -4, 0, 1, 0, + -2, -6, -2, -4, 3, -2, -3, -5, -6, -3, -1, -1, -7, 0, 0, 3, + -5, -4, -11, 0, 0, 3, 3, 1, 1, 1, 4, 6, 1, 1, 2, 9, + 3, 3, -4, -4, -3, 2, -1, -6, 1, -5, 2, 0, -1, -8, -5, -6, + 1, 0, -2, -1, -2, -1, 2, 0, -9, 0, 5, 4, 7, -3, -3, 3, + 4, 2, 4, 0, -1, 3, 1, 5, -5, -6, -7, 0, 3, 0, -2, -4, + 3, 3, -3, -4, -7, -2, 4, 1, -1, -4, -1, -6, -2, 3, -2, -3, + 1, 4, 1, -1, -4, -3, 3, 4, 5, -2, 2, -3, 4, 0, 3, -3, + -3, 0, 3, 1, -2, -1, -3, 2, 4, -2, -2, -3, -1, -1, 3, -11, + -2, -8, 5, -1, 3, -5, -2, 2, -1, 3, -3, 0, -1, -1, 5, -2, + 0, -2, 3, 2, 3, -2, -6, -3, 2, 4, -6, 5, -6, 1, 2, 3, + -6, 2, -3, -4, 3, -9, 2, -6, 3, 4, 2, -9, -1, 1, 2, 8, + -3, -4, -1, -2, 2, -2, 2, -3, 3, -1, 1, 2, -1, -6, 1, 2, + 2, 1, -2, 2, 3, 1, -3, -6, -3, 0, 1, -3, 0, -3, -1, -4, + 2, -4, -3, -1, 4, 0, 5, -6, -7, -1, 0, 0, -3, -1, 2, 4, + 0, 3, -4, -1, 1, 7, 4, 2, -1, -4, 0, 2, -4, -5, -5, -1, + 1, 4, -5, -4, -6, -3, -2, -3, 2, -2, 5, 2, 3, -4, -2, -5, + 6, 3, 4, 2, -3, 1, 0, 0, 1, -3, -1, 1, 7, 0, 6, -6, + -7, -2, -7, 0, -1, 0, 2, 1, -2, -7, -2, -5, 0, 2, 0, -3, + -5, -1, -3, 0, -1, 0, -6, 8, 4, 5, -1, 1, -4, 1, 1, 4, + 2, 5, 3, 6, 0, -2, -9, -4, -1, 0, 0, 1, -1, -4, -1, -5, + -5, -5, 0, 0, 1, -6, -5, -9, 0, -3, 0, -2, 0, 0, 3, 4, + 2, 1, -7, 1, 3, 4, 9, 1, 4, 4, 2, -4, 2, -2, 1, 5, + -2, 0, -3, -4, -3, -2, -4, -4, -4, 1, -1, 2, -6, -8, -3, -8, + -1, -2, -4, 5, 2, 3, -1, 0, -4, 2, -1, 5, 5, -1, 3, 0, + 3, 3, 0, -4, 9, 4, 2, -1, -6, -4, -2, -2, 2, -7, 0, 0, + -2, -2, -2, -10, -4, -7, 0, -2, 2, -2, 2, 1, 0, -3, 0, 1, + 6, 3, 2, 0, 0, -1, 2, 3, -1, 4, -5, 6, 2, -3, 0, -3, + 0, 1, 0, -5, -6, 1, 0, 1, -5, -2, -14, 0, -4, -1, -1, -1, + 1, -3, 0, -2, -1, -4, 4, 5, -1, 5, -1, 3, 3, 5, -3, 5, + -3, 5, 5, 6, 4, -6, 2, -9, 4, -4, 0, 1, -2, -1, -8, -6, + -11, -2, -3, 3, -6, -8, 3, -5, 1, -3, 1, -3, 1, 3, 5, 6, + 2, 1, -6, 4, -1, 1, 0, 7, 7, 2, 3, -6, -4, -4, 3, 3, + 0, 1, -1, -2, -4, 0, -8, -2, -3, 1, -2, 1, -5, -2, -1, -3, + -3, -4, -3, 7, 4, 1, -1, -6, -5, -3, 2, 5, 8, 3, 3, 2, + 1, -4, -1, -2, 6, 3, 2, -4, -1, 1, -5, -1, -1, -5, 2, -2, + 1, -2, -7, -5, -11, -4, -3, 3, -8, 8, 4, -2, -2, -4, -4, -1, + 4, 3, 5, 5, 2, 4, -1, 6, -3, 6, 2, 3, 0, -4, 0, -2, + -2, 0, -5, -2, -1, 4, 3, 1, -13, -8, -8, -5, -3, 7, -2, 3, + -2, -5, -3, -8, -2, -3, 8, 6, 1, -2, 5, 3, 1, 2, 0, -1, + 2, 4, 3, -5, 1, -3, 0, 1, 7, 1, 2, 3, -1, -4, -4, -10, + -7, 3, 0, 2, -5, -5, -4, -1, -7, -3, -3, 1, 3, 0, 0, -1, + -6, 6, 1, 4, 1, 2, 5, 6, 4, -1, -4, -3, 1, 2, 5, 2, + -1, 1, 3, -8, -1, -10, -2, -5, 0, -1, -6, -10, -7, 2, -2, 6, + -1, -2, 1, 4, -1, -5, -1, -5, 4, 1, 4, 2, 1, 3, 4, 0, + -2, 1, -1, 3, 8, 2, 1, -4, -3, -3, 3, -3, -1, -4, 0, -4, + -6, -2, -8, 1, -2, 5, -6, -5, -6, 0, 3, 1, -6, -3, 1, 2, + 4, 2, 4, -2, 3, 3, 3, 1, 5, 1, 2, 3, -2, -6, 6, -1, + 6, -2, 1, -7, -5, -2, -3, -6, -6, -6, -4, 0, -2, -4, -4, -3, + 0, -1, 1, -3, -1, 3, 1, 1, 0, 6, 4, 8, 10, 5, 0, -3, + 1, -2, 5, 2, 1, 1, 1, -4, -6, -8, -8, -8, -5, -4, -5, -4, + -5, 0, -5, -3, 0, -7, 0, 4, 1, -4, -1, -4, -2, 4, 4, 5, + 6, 6, 7, 0, 0, -1, 0, 2, 9, 2, 1, -3, 0, 1, -3, 1, + -9, -1, 3, -4, 3, -6, -7, -2, -1, -1, -1, 1, -9, 2, -5, 1, + -8, -6, -6, 1, -1, 6, 0, 2, 5, 2, 0, 2, 1, 2, 6, 5, + -2, -1, 0, 4, 1, 6, 0, -2, 1, 0, 3, -7, -1, -13, -4, -3, + -3, -3, -2, -3, -5, -9, -11, -2, -3, 4, 7, -1, 2, 0, -2, 8, + 5, 1, 4, 3, 2, 7, 3, -2, -4, 7, 2, 3, -2, 1, -1, 2, + 0, -5, -4, -4, 0, -4, 0, -1, -10, -9, -3, -5, -8, 1, -5, 3, + -3, 0, -7, 1, 0, 5, 4, 7, 1, 1, 0, 2, 2, -2, -1, 2, + 1, 4, 6, -1, 4, 3, -1, 4, -2, -3, 3, -1, -2, -6, -6, -7, + -3, -1, 0, -4, -6, -5, -6, 0, -3, 3, -5, 7, 0, -1, 1, -3, + -1, 1, 6, 3, -3, 7, 1, 10, 1, 6, -1, -2, 5, 2, 1, 1, + -4, -2, 0, -3, -7, -2, -4, 4, -8, -8, -4, -10, -2, 2, -4, 1, + -5, -7, -1, 3, -1, 1, 1, 4, 6, 2, 2, 0, 4, 7, 0, 5, + -2, 0, 3, 3, 3, -3, -1, -5, -2, 0, 3, -4, -6, 2, -1, 0, + -2, -4, 0, -4, -3, -9, -3, -4, -4, 0, 3, -1, -4, 3, 1, 5, + -2, 1, 2, 2, 4, 5, -3, 2, 1, 3, 7, 1, -5, 1, 0, 5, + -3, -2, -3, -4, 0, -3, -2, -5, 0, -8, 3, -6, -4, -6, -2, 2, + -4, -2, -3, -2, 1, 4, 2, 3, -2, 2, 4, 1, 4, -2, 3, 2, + 1, 1, 7, -1, 2, 4, -4, 2, -4, -2, 5, -4, 3, -1, -3, -2, + 3, -8, -4, -6, -3, -3, -1, 0, -6, -1, 0, 1, 1, -2, -10, -3, + -1, 0, 2, -5, 1, 1, 2, 10, 8, 2, 8, -1, -2, 4, -5, 2, + 2, 7, 6, -6, -1, -5, -4, -3, -6, -7, 0, -5, -5, -1, -2, -5, + 0, -4, 6, -6, 0, 3, -3, 4, 0, -6, 2, 5, 5, 4, 10, 0, + 2, -3, 3, -2, 0, 3, -3, 2, -3, -8, -8, -5, -1, -1, -1, 0, + -5, -2, 0, -3, -4, -1, -5, -2, 5, 0, 5, -4, 4, -1, -1, 1, + -3, 3, 9, 2, -1, 1, -6, -3, 7, 1, 3, -2, -4, 0, -1, 3, + 1, -3, 4, 6, 0, 1, 2, -3, 0, 0, -5, -13, -4, -2, 1, 2, + -3, -10, -4, -7, 1, -2, -2, -1, 0, 1, 1, -4, -1, 2, -2, 7, + 1, -3, 0, 0, 4, 5, 2, 2, -1, 6, 9, 1, 3, 1, -5, 5, + -6, -5, -2, -4, -2, 2, -7, -4, -11, -5, 3, -3, -6, -4, -6, 3, + 3, -3, 2, 0, 1, -3, -1, -2, -4, 1, 10, 8, -2, 4, -3, 6, + 6, 1, 0, -7, 2, -2, 1, 3, -4, -4, 4, 1, 0, -2, -5, 2, + -2, 0, -7, -11, -5, -2, -2, 5, -1, -8, -1, -1, 1, 2, -2, -1, + 1, 1, 5, 0, -3, 5, 1, 6, 1, -1, 3, 1, 6, -3, -1, -1, + -3, 4, 12, -1, -1, 2, -4, -1, -6, -8, -7, -3, -2, 1, -9, -5, + -6, -10, 5, 1, -2, -3, -2, 5, 4, 3, -1, -5, 4, 6, 3, 4, + 6, -2, 7, 0, -4, -1, -1, 9, 8, 2, 2, -8, -3, -3, 0, -2, + 0, -4, -2, 0, -6, -7, -14, -6, -5, -1, 3, -6, -2, 1, -3, 0, + -4, -5, 1, 5, 9, 4, 0, 3, 0, 1, 12, 0, 4, 8, 5, 7, + -1, -4, 0, -3, 5, 4, -4, 0, -3, -13, -2, -10, -14, -3, -5, 2, + 1, -3, -4, -8, -8, -3, -2, -2, 3, 4, 8, 0, 2, 1, 2, 12, + 5, 3, 8, 2, 6, 3, -4, -4, -2, -8, 8, -5, -2, -6, -10, -2, + -6, -4, 0, -4, 2, 5, 1, 0, -4, -4, -1, -1, -3, 4, -7, 4, + 3, -3, 4, -4, -3, 8, 4, 7, 0, 0, 2, -1, -2, -1, -2, -7, + 11, -1, 5, -4, 2, -2, 0, 2, -2, -4, -2, 1, -5, 3, -6, -9, + -3, -3, -2, -5, -5, -2, -6, -2, -7, -8, 1, 3, 5, 9, 4, 4, + 0, 5, 8, 1, 3, 7, 5, 10, 11, -7, 3, 0, -3, 1, -1, -7, + -7, -3, -2, -6, -9, -6, -12, -4, -1, 0, -8, -5, -3, -3, -2, 3, + 1, 1, 9, 4, 2, 5, -1, 2, 6, 2, 0, -3, 2, 2, 5, 2, + -1, -4, 4, 1, 1, 2, -5, -8, -1, -3, -1, -9, -4, 1, -4, 5, + -6, -4, 0, 3, -9, 3, -3, -5, 1, 4, 4, 1, -4, 1, -4, 4, + 1, -6, 0, 5, 7, 8, 1, 6, 0, 3, 4, 2, -3, 1, -3, -3, + 3, -9, -6, -7, -2, -1, -3, -5, -6, -5, -5, -6, -5, 4, -3, 5, + 5, -2, -1, -1, -3, 6, -2, 5, 6, 2, 11, 8, -1, 3, -6, -2, + 5, 4, -3, -3, -5, -3, -7, -5, 0, -5, 2, 1, 0, 1, -7, 0, + -3, -2, -1, -2, -5, 7, -4, -2, -3, -2, -3, 4, 4, 9, 0, 1, + 1, -5, -3, -4, -4, 4, 3, 6, 0, -2, -2, -6, 4, 1, 1, -3, + 3, -1, 2, 0, -7, 0, 0, -1, -3, -2, -1, -5, -2, -3, -8, -5, + -5, -1, 5, 5, 2, 2, -3, 4, 3, 3, 6, 3, -1, 10, -4, -3, + -2, -3, 0, -4, 0, -2, -2, 0, 1, -4, -2, -5, -9, 8, -2, -1, + -1, -3, -3, -2, -6, 2, 1, 2, 9, 0, 1, 3, -4, 2, 4, -6, + -1, 2, -1, 6, 3, 0, -5, -3, -1, 0, 3, -3, 0, -6, -2, -3, + -4, -2, 0, 3, 2, 2, 0, -10, 1, -6, -5, -1, -2, 5, 3, 6, + -2, -6, -1, -3, 2, -1, 0, 0, -1, 0, 0, 0, 1, -2, 2, -2, + -5, -1, -2, 16, 12, -18, -10, 3, -14, -10, 16, -1, -3, -16, 28, 3, + -1, -1, 12, -5, -6, 6, 7, -7, -18, -28, 11, 0, 6, -2, 26, -21, + -10, -1, 24, -3, 20, -19, 15, -14, -3, -3, 15, -35, -2, 6, -14, 30, + 6, -36, -8, 17, 0, -27, 26, 16, -38, 8, -14, 57, 3, -31, -14, 34, + -20, 33, 2, -6, -7, -28, 20, -24, 8, 13, 8, -39, 17, 40, -42, -11, + 13, -46, 1, 28, -22, 11, -3, -14, 5, 20, -12, -4, 49, -22, -24, 39, + -11, -1, -9, 37, -30, 13, 34, 4, -11, -25, 18, -22, 1, 29, -17, -3, + -26, -16, -21, 12, -18, 7, -17, -6, 51, 0, -21, 10, 24, -45, 8, 14, + 31, -10, -37, 6, 0, 24, 3, -18, -13, 14, 11, 0, 7, -1, -38, -29, + -21, 32, -30, 22, -26, 14, -40, 55, -36, 30, -12, 8, 31, -16, 19, -15, + 23, -48, 36, 1, 63, 3, 24, 0, -3, 14, 26, -21, 15, 47, -21, -80, + 14, -4, -25, -33, 11, 25, -35, -44, 13, -2, -48, -11, -23, -7, 27, -4, + -15, -22, 5, 26, -36, 50, 23, 11, -23, -14, 19, 32, 14, 38, -66, 56, + -11, 26, 18, -12, 17, -30, -6, -54, 22, 77, -62, -12, -16, 34, -25, 2, + 14, -62, 12, 20, -22, -50, 58, -29, -58, 4, 28, 30, 13, 25, -78, 38, + 45, -19, -7, 52, -61, 27, 17, -21, -4, 6, 37, -24, -38, 73, 8, -16, + 21, -2, -15, -19, -19, 18, 3, 7, -48, -10, -10, 10, 4, 13, -13, -4, + 0, 46, -12, 6, -18, -25, 4, 14, 27, -22, -37, 14, -6, -17, 55, 40, + -111, 63, 9, -38, -16, 46, -35, 4, 0, -10, -8, -12, 58, -69, 1, 66, + -38, 21, -33, -6, 10, 0, 10, -11, 18, -16, 32, -7, -10, -25, 65, -42, + 42, -62, 18, -3, -2, -8, 21, 4, -71, 13, 40, -3, 18, -19, -29, 15, + -66, 60, -50, -6, 67, -80, 17, 66, -21, -20, -15, 68, -16, 72, -4, -23, + 4, 53, -8, 8, -4, 0, 27, -26, -22, 25, -31, 7, -39, -18, 27, -43, + -25, -33, -6, 17, -16, 0, -55, 6, 26, -3, -67, 7, 60, -83, 25, 15, + 45, -8, 51, -55, 28, 42, 42, -17, 37, -6, 17, 8, 11, -1, 59, -7, + -45, 14, -41, 107, -49, -50, -25, 63, -58, -27, -57, 19, 13, -13, -27, 19, + -42, 63, -113, -1, 44, 8, 1, -10, -33, 0, 55, -41, 15, 0, 76, -17, + -39, 60, -20, 28, 54, -93, 15, 83, -30, 4, -56, 49, -58, 30, -28, 2, + 54, -64, 83, -128, 86, 24, -40, -27, -66, 51, 11, -51, 59, 6, 20, -58, + -24, 78, -7, -23, -27, 1, -3, -24, 10, -6, -16, 34, 39, -37, -17, 26, + 52, -69, -7, 11, 24, -62, 38, -13, 41, 5, -2, -5, -12, 15, 77, -49, + -10, 74, -12, -11, -38, 32, -24, 25, -6, 19, -24, -2, -38, 63, -91, 64, + -27, -11, -56, -43, 27, -41, -55, -15, 1, -4, 27, 8, 37, -57, 3, 28, + -11, -4, 46, -39, 3, 12, 100, -33, 39, 17, 6, 49, 5, 38, -12, 10, + 21, -35, 23, -6, -36, 10, -9, 3, -1, 13, -65, -40, 36, -25, -28, 5, + -37, -20, -14, 31, -16, -32, -16, 4, 15, -11, 26, -16, 29, -42, 46, 7, + 39, -1, -5, -9, 33, -31, 35, -33, -7, 17, 56, -24, 22, 14, -22, -34, + 44, 16, 11, -46, 43, -48, -27, 43, 36, -45, 21, 11, 0, -98, -22, 87, + -126, 52, -45, 34, -28, -17, -31, 23, -38, 23, 25, -11, 25, -63, 21, 13, + 19, 47, 28, -23, 20, 21, -5, -14, 112, -30, -67, 37, 43, -12, -57, 34, + -9, -29, 52, -19, 14, -51, 0, 26, -69, 3, -18, -24, -34, 31, -15, -33, + -36, 10, -20, -38, 63, 0, 44, -50, 72, 25, -16, -6, 6, 15, 23, 31, + 3, -20, -9, 19, 63, 17, -18, -5, -12, -87, 31, 26, -37, -29, 49, -42, + -15, 14, 11, -16, -31, 46, -19, -13, -37, 59, -91, 47, 4, -11, -26, 39, + -29, -24, 48, 10, 39, -11, 45, -51, -1, -24, 47, -19, 39, -34, -29, -17, + 1, 56, -25, -16, -13, 0, 48, -71, 49, 2, -2, -45, -10, 59, -17, -25, + 9, 9, 44, 42, -32, -23, -49, 46, -11, -50, 76, -43, -45, -1, 41, -8, + 2, 71, -36, -61, 35, 21, -13, -36, 44, -45, 26, -45, -21, 28, -37, 39, + -29, 15, 4, -5, 24, -7, 7, 3, 68, -80, 26, 24, -22, 8, 26, 28, + 10, -26, -3, 16, -51, 85, -8, -14, -54, 39, -28, -9, -25, 46, -39, -20, + 34, 11, -25, -7, -12, -41, 12, -17, -5, -43, -8, 0, 18, 13, 9, 28, + -40, 34, 0, 13, 40, -20, 5, 22, -25, -13, 51, 9, -34, 43, -16, -18, + 2, 35, -4, -28, 14, -37, 6, -8, 31, -49, 9, -31, 61, -55, 35, -46, + -37, -12, 32, 74, -59, -30, -21, 5, 38, 3, 48, -35, -42, 2, 29, 81, + -8, -37, 24, 42, -31, 18, -11, -21, -67, 98, -18, 11, -26, -14, -76, 11, + 71, -70, 30, -52, 37, -45, 61, 6, -33, -44, 58, 24, -16, -51, 49, -28, + 51, -6, -15, 46, 10, -24, 36, -4, 6, -30, 46, -66, 54, 27, -16, -34, + -23, 90, -61, -49, 22, -3, -22, 17, -35, -11, -59, 23, 2, -25, 69, -24, + -26, -28, 37, 12, 11, -63, 27, 18, 3, 34, -25, 9, -14, 29, 4, 24, + 21, -77, 12, 14, 37, 1, 45, -63, 1, 49, -14, -23, -7, -4, -42, 48, + -57, 18, -36, 17, 15, -37, 47, 1, -41, -14, 11, 49, -32, 32, -36, -19, + 21, -11, 39, -31, 43, 0, -24, 15, 6, 9, -46, 5, 21, -23, 2, -28, + -15, 59, -13, -29, 50, -7, -45, -12, 23, -1, 27, 6, -17, 7, -4, -3, + -3, 53, -10, 17, -52, 19, 24, -8, -7, 19, -51, -30, 55, -22, -22, 29, + -38, -25, 39, 3, 34, -84, 26, -37, 42, 15, 4, -4, -16, -33, 29, 17, + 43, -93, 24, -6, -20, -14, 107, -29, -36, 69, -21, 10, -7, 74, -67, 38, + -23, -8, 27, -35, -49, 29, -8, -4, 7, -8, 5, -38, -28, -33, 22, 70, + -37, -10, -56, 26, 5, 7, 59, -21, -58, 10, -2, 6, 49, -16, -9, -38, + 60, 13, 43, -43, 23, -14, -9, 38, 17, -38, -15, 29, 6, -5, -11, -3, + -4, -65, 45, -13, 26, -13, -4, -5, -38, 48, 0, 4, -40, 40, -48, 23, + 21, 23, -42, 5, -17, 13, -9, 12, -3, 5, -25, 34, -24, -3, -18, 16, + -44, 13, 27, -30, 44, -54, 6, -18, -3, 4, 21, -25, -13, 22, -20, -12, + 37, -10, -10, 5, 24, -17, 23, 9, 0, 4, 3, 12, 26, -27, 17, 9, + -41, 69, -1, 15, -37, 15, -6, 0, -1, 3, -13, -23, -18, 27, -5, 21, + -16, -41, -2, 20, 13, -27, 6, -21, 8, 6, 0, 6, -5, -21, -22, 73, + -40, 4, 6, 21, -8, -5, 29, -47, -1, 1, 19, 3, -10, -1, 2, -48, + -11, 45, -27, 11, -33, -21, 21, 7, 12, -22, 21, -40, 13, 27, -20, 37, + 5, -18, -18, 35, 40, -11, 20, -25, 10, -4, 33, 12, -29, 9, -20, -30, + 34, 24, -9, -10, -24, -16, 8, 22, 6, -58, -5, -13, 18, 5, -43, 10, + -16, -25, 13, 70, -25, -7, -25, -19, 16, 58, -46, -5, 6, -5, 40, -24, + 22, 50, -73, -7, 7, 32, 39, -27, -23, -23, 56, -35, 21, 17, -40, 40, + -52, 4, 0, 49, -29, -42, 24, 9, 31, 2, -46, 0, -9, -5, 9, -31, + 64, -5, -45, -26, 42, -4, -34, -8, -3, 32, -15, -8, 22, -24, 13, -31, + -2, 31, 10, -10, -18, 8, 24, 20, -29, 2, 14, 23, 25, -4, -19, 20, + -25, -5, -3, 23, -8, 52, -42, -17, -7, 29, -26, 2, -19, 55, -50, -28, + 1, -10, -7, 7, -41, 16, 21, 1, -20, 0, 16, -19, 14, -39, 86, -17, + -34, -64, 73, 0, 20, -28, 30, -22, 9, 58, -4, -8, -18, -20, 31, -21, + 1, 26, -49, 5, 41, -25, -13, -6, -7, 6, 10, 42, -30, -26, -43, 11, + 44, -54, 31, -10, -11, -17, 25, 32, -43, 64, -23, 3, -37, 33, -30, -4, + -35, 47, -29, 9, 23, -34, -5, 64, -37, 32, -11, -44, 21, 25, -19, 8, + 6, -25, 34, 2, -18, -23, 38, 20, 7, 21, 1, -32, -37, 50, -9, -25, + 34, -61, 55, -32, 7, -48, 20, 13, 0, -35, 17, 9, -42, -28, 14, 42, + -33, -25, -5, 21, 41, -60, 32, -7, 38, -9, -3, 20, -4, 29, -69, 62, + -16, 35, -64, 45, 10, 5, -1, -18, -18, -1, 5, 32, 0, -21, -12, -23, + 29, -15, 13, -39, -3, -3, 6, 35, -24, -23, -7, -2, 44, -10, -37, 25, + 25, -25, -23, 7, 40, 4, -40, -18, 21, -2, -3, 1, -16, 45, -26, -2, + -16, 18, 41, -64, 8, -26, 40, 5, -32, 8, 18, -1, 15, -1, 9, 2, + 2, -13, -12, 35, -9, 13, -62, -29, 72, 18, 7, -30, 26, -7, -29, 39, + -38, 31, -56, -25, -3, 17, 2, -3, -46, 35, 6, 27, -39, -3, 3, 31, + -25, -19, -2, 38, 26, -77, 22, 18, 40, 3, -22, 65, -48, 33, -16, -37, + 78, -34, 1, -52, 23, 16, 1, -37, 17, 12, 1, -4, 8, -27, -1, -11, + -18, 27, -23, -10, -11, -19, -6, -7, 51, -74, 16, 20, 17, -14, 7, 7, + -13, -8, -5, -11, 39, 21, -5, -44, 31, 64, -38, -18, 20, 40, -4, -10, + 10, -23, 23, -6, -20, 11, 9, 10, 6, -23, -11, 1, 17, -56, 56, -40, + 0, -17, -60, 84, -80, 16, -13, 4, -25, 12, 17, -42, -26, 54, -29, 12, + -5, 37, 16, -62, 94, -5, -2, -2, -2, -9, 5, 51, -25, -5, -11, 5, + 16, -14, -9, 43, -44, -8, 27, 2, -1, 9, -18, -6, 5, 23, -46, -9, + 13, 16, -10, -10, -23, 59, -47, -14, 23, 29, -15, -14, -30, 21, -21, 0, + 14, -3, 25, -16, -35, -2, -8, 32, -19, 22, -23, -37, 30, -33, -19, 11, + 12, -32, 47, -4, 27, 11, 9, -35, 39, 29, -18, -2, -11, 27, -2, 13, + 0, 18, -26, 15, -25, 26, -4, 21, -29, -33, 18, -8, -31, -5, 21, -1, + -38, -28, 41, -18, -4, -22, 47, -12, -44, 55, -79, -5, 19, -10, 25, 4, + 21, 15, -28, 13, -6, 45, -24, 25, 10, -26, 4, 2, 31, 3, -7, 3, + 5, -23, 51, -9, -32, -5, 35, -32, -21, -20, 35, -40, -10, 20, -8, 7, + -5, -38, -1, -24, 39, -26, 20, -16, -9, -27, 25, 34, -32, 1, 12, -13, + 3, 37, 13, 3, -31, 27, 30, 5, -15, -21, 2, 10, -13, 16, 36, -9, + -59, 41, -10, 61, -60, -35, -11, 7, 5, -28, 30, 5, -23, -66, 34, 50, + -26, -19, -10, 11, 8, 8, -35, -5, -11, 56, -24, 10, 35, 16, -10, -19, + 30, 4, -11, 23, 0, -6, 6, 36, -15, 0, 15, -14, -26, -8, -5, 15, + -31, -45, 42, -30, 0, -9, 6, -22, 9, -22, 7, -8, 15, -19, -3, -13, + 29, -14, 9, -16, 3, -5, -10, 63, 0, 4, 4, 20, 16, -21, 18, 31, + -24, -19, 31, 54, -39, -7, -16, 5, -3, 0, -29, 16, 6, -29, -25, -52, + 49, -9, -66, -3, 50, -3, -2, -14, 4, -8, 33, -40, 2, 15, -6, -17, + -4, 10, 48, -16, 14, -9, 27, 10, 2, 2, 40, -35, 5, -10, 7, 28, + 1, 4, -30, -4, 0, 1, -14, -13, -11, 26, -17, 13, -44, -9, -6, -23, + 17, 11, 11, -21, -11, 0, 9, 8, 8, -30, 29, 10, -26, -12, 15, 17, + 4, -26, 14, 19, 20, -9, -24, 39, 23, -10, -35, 8, -6, 18, -25, 15, + -17, 41, -48, -31, -5, 47, -14, -20, -4, -7, 5, -19, 3, 21, 12, -23, + 15, -24, 8, 3, -25, 2, 28, 14, 21, 25, -72, 15, 26, -6, 45, -27, + 29, -30, -17, 23, 6, -2, 27, -46, 13, 9, 15, -57, 27, 1, -18, 1, + -11, -2, -20, -16, -23, 24, 18, -21, -5, -15, -14, 26, -12, 30, -48, 37, + -24, -3, 23, 9, -5, 9, 8, -43, 23, 26, 6, 28, -29, 30, -8, -12, + 25, -18, 33, -48, -4, 29, 1, -8, -4, -20, 41, -22, 1, 12, -33, 0, + -17, -16, 29, -3, -2, -36, 6, -1, -11, 4, -24, 40, -24, -5, 26, -2, + -28, 13, -11, 35, -9, -2, -3, -6, 13, 10, 1, 11, -22, 22, -27, -5, + 20, 11, -1, 8, -23, 8, 7, -7, 17, -6, 16, -9, -10, 3, 13, -3, + -17, 19, -21, 6, -13, -15, -7, 22, -15, -7, 11, -20, -19, -6, 0, 28, + -10, -7, -13, 9, 7, 1, -11, -6, 21, -33, -4, 52, -11, -1, -2, -2, + -4, 32, 17, -31, 7, 12, 2, -5, 11, -1, -6, 1, 3, -11, 5, 4, + -15, -8, 10, 5, -18, 5, -26, -11, 22, -15, -23, 22, 19, -30, 3, 1, + -5, 10, -17, 10, -2, 10, 7, -17, -5, 36, -12, -24, 27, 22, -3, -11, + -6, -7, 20, 5, -21, 0, 23, -31, -27, 14, 2, 8, 7, -15, 0, 13, + -7, -3, -21, 33, -4, -26, 7, 5, -7, -7, 1, 3, 4, 11, -24, 6, + 11, -7, 14, -9, -11, -1, 34, -22, 11, 1, -18, 17, 4, -19, 28, -15, + -7, -11, 12, 1, -7, -9, -12, 17, -20, 6, 5, 2, -10, 12, -23, -3, + 26, -1, 4, 6, -25, 12, -3, -26, 2, 15, 14, -18, -6, -17, 14, 4, + -10, 21, -13, 5, -15, -20, 27, 6, 8, -11, 18, 15, -34, 17, -2, -13, + 41, -9, -10, -6, -2, 7, -11, -4, 28, -26, -6, 25, 17, -36, -2, 33, + -39, -15, 11, -2, 26, -32, -31, 21, 26, -11, -24, 12, -17, 4, -33, 24, + 14, -10, 12, -19, -3, 28, 11, -8, 0, 26, -17, -7, 8, -6, 20, 26, + -29, -27, 25, -14, -2, 10, -16, 39, -24, -17, -4, -13, 24, -10, -3, -20, + 25, -1, -24, 24, -20, -5, 21, -26, 7, 21, -26, 15, 17, 6, -34, 5, + 11, -27, 20, 17, -13, -8, -16, 9, 33, -36, 19, 5, 4, -2, -33, -12, + 38, -17, -10, -4, 19, 14, -4, -32, -41, 64, 5, -38, 28, 6, -2, -11, + -22, 11, 17, 17, -24, 23, -7, 9, 10, -38, 0, 25, -9, -6, -27, 20, + 2, -27, 34, -23, 17, -22, 4, 12, -43, 29, -8, 25, -19, 13, -17, -11, + 27, -8, 14, -19, 12, 9, -22, -6, 11, -10, 17, -4, 2, -3, 15, -47, + 32, -18, 11, 14, 0, 8, -33, -14, -12, 23, 17, -12, -4, 13, -27, 10, + -17, 20, -2, -11, -11, 27, 18, -21, -6, 26, -18, 9, -7, 27, -12, 3, + -9, -9, 22, 7, -38, -2, 14, -16, 12, -21, -10, 22, 1, -28, 20, 31, + -11, -49, 9, 16, -4, -7, -4, -5, 46, -39, 9, -18, 16, 22, -24, -13, + 14, 29, -10, 3, -23, 4, 11, -33, 30, 18, -9, 5, -11, 4, -20, 30, + -9, -14, -7, -9, 4, 0, 4, -15, -11, 23, 5, -24, 26, -6, -8, -17, + 21, 0, 3, 13, -10, -13, 19, -16, -10, -5, 10, 8, 22, -19, 4, -8, + 0, -24, 38, 12, -33, 10, -9, 5, -13, 11, 3, 7, -18, -12, 11, -4, + 8, -17, -7, 16, -9, -2, -9, 0, 10, -2, -1, -1, 12, -6, 13, -18, + 18, -6, 10, 1, -3, 9, -2, -30, 23, -9, 29, -11, -31, 10, 6, -21, + -19, 54, -30, 18, -12, -26, 23, -10, -31, 23, -5, 49, -34, 4, -18, 3, + 11, -24, 27, 12, -24, 3, -13, 3, 16, -6, -7, 1, 19, -8, -3, -11, + 13, -14, 19, 10, 17, -21, 14, -40, 12, 13, -5, -3, 21, -14, -29, 16, + -24, 1, 10, -1, -3, 6, -15, -16, 16, -4, 2, 23, -32, -1, 7, -5, + 13, 4, -15, 33, 1, -7, -7, -12, 13, 6, -8, 2, 21, 2, -21, 17, + -14, -19, 36, -2, -16, -4, 3, 9, 15, -39, 3, 9, -10, -3, -12, -7, + 28, -19, 8, -18, 22, -18, -11, -2, 17, 23, -15, -24, 11, 13, -14, -10, + 9, 4, 14, -10, -13, 13, -3, -12, 25, 6, -12, 12, -19, -3, 19, -10, + -13, 19, 10, 18, -31, -15, 19, -9, -14, -6, 25, -18, 2, 17, -41, 11, + 16, -20, 3, -10, 16, 9, 14, -27, -1, -3, 9, -19, 36, -6, -4, -4, + -16, 5, -7, 24, -1, -30, 13, -8, -4, -9, 47, -37, 3, 21, -24, 1, + 3, 11, 5, -10, -8, 20, -31, 16, 10, -1, 0, -9, -1, -6, 14, -6, + 6, -17, 20, 3, -23, 10, -14, 17, -16, -2, 26, 7, -20, -10, 9, -18, + 31, -35, 3, 14, -8, 13, -27, -4, -4, 26, -20, -9, 14, 22, -27, -4, + 18, 9, 9, 3, -13, -20, 15, -13, 6, 12, -5, -6, -12, 0, 4, -10, + 18, -7, -8, -15, 1, -11, 17, 5, -11, 14, -6, -11, 4, 10, -5, 13, + 0, -7, 15, -2, -16, 2, -3, 9, -6, 2, 34, -11, -17, -8, 21, 13, + -21, -4, 14, -7, -7, -19, 13, -7, 4, -25, 7, 16, -14, -40, -11, 36, + 3, -10, 4, -10, 7, -1, -1, 4, 14, 6, -14, -14, 17, 23, -13, -2, + -1, -12, 9, 8, 1, -7, 22, -29, 7, 7, 0, -24, 13, -10, 18, -1, + -3, 13, -24, 30, -32, -5, 18, -2, -6, -8, 11, -18, -12, 17, -11, 0, + 5, -4, -14, 31, -15, -16, 13, 12, -4, 4, -4, -1, -11, -15, 26, -18, + 29, -15, -3, -8, 6, 6, -34, 22, 0, 11, -18, 16, 20, -19, -21, -5, + 11, 21, 10, 10, -27, -5, 3, 2, -5, 9, -9, -1, 1, -11, -3, 8, + 4, 1, -1, -11, 19, -1, -21, -5, -2, 11, -2, -8, 10, -7, -1, 2, + -18, 3, 0, 7, 2, 7, 1, 1, -28, -14, 10, 19, 12, -21, 7, -19, + 20, -2, -3, -1, 17, -11, -13, -16, 32, 4, -5, -3, 4, -4, 18, -2, + -17, -6, 16, -3, 4, -12, 4, -2, 2, 6, -18, 20, -24, 17, -10, 19, + -16, -17, 8, -7, -5, 16, -12, -18, 11, 9, 2, -8, 17, -9, -3, -13, + 7, -6, 30, -15, -11, 5, 14, -2, -15, -5, 14, 13, -12, -24, -10, 22, + -2, -8, -1, 21, -5, -19, -16, 8, 42, -6, -27, -12, 23, 10, -17, -14, + 16, 14, -16, -2, 9, -2, 16, -9, -31, 22, 0, -2, 3, 4, -5, 20, + -24, -5, 13, -1, -5, -10, -6, 8, -11, 2, 8, -8, -5, -9, 1, -6, + 16, -1, -18, 4, 9, -3, 6, -4, 6, 9, -7, -9, -1, 10, -7, 4, + 3, -3, 4, -8, -5, 3, -4, 10, 6, -15, 2, 3, -5, -2, -3, -12, + 18, 2, -16, 7, 13, 0, -19, -8, 11, -6, -1, -9, 5, 13, -8, -6, + 6, 7, 11, -11, -6, 13, -2, -5, -1, 9, -2, -7, -15, 10, 5, -1, + -13, 8, 0, -6, -2, -2, 18, -16, -7, 2, 3, -4, 6, -11, 4, 6, + 1, -5, 22, -11, -5, -6, -3, 11, -1, -1, 4, 1, -4, -13, -4, 11, + -9, 1, 9, -1, -8, 1, -5, -7, 5, -14, 18, -1, -12, 11, -12, 16, + -5, -11, 11, -2, 15, -7, -18, -10, 0, 18, -12, 8, 3, 6, -16, -3, + 3, 6, 0, -1, -3, 4, 9, 3, -17, -7, 11, 11, -19, 5, 15, -12, + -3, -12, 4, 11, -19, 0, 0, -14, 21, -15, 2, 8, 3, 8, -8, 5, + -18, 9, -2, -8, 23, -5, -16, 5, 3, -20, 13, 11, -6, -15, 5, 4, + -12, 2, 10, -5, -12, 5, -14, -2, 18, 11, -14, 0, 28, -10, -20, 4, + 7, 9, -13, -6, 15, 11, -9, -6, 14, -8, 10, 4, -12, 11, -18, 13, + -17, -9, 16, -4, -14, -7, 17, -24, -5, 4, 6, -6, 14, 2, -24, -22, + 11, 13, 8, -16, 6, 13, -28, 10, -2, 11, 8, -1, -8, -14, 22, 3, + -5, -13, 18, 7, -26, 15, 20, -6, -10, 4, 11, 5, -8, -3, -5, 0, + -1, -6, 0, 4, 4, -14, -1, 1, 8, -14, -10, -4, 6, 4, -8, 3, + -9, 0, 11, -4, -7, 5, 4, 6, -29, 18, 22, -19, -16, -11, 17, 7, + -4, 3, -23, 20, 8, -19, 3, 13, 13, -16, -18, 15, -6, 0, 3, 17, + -7, -4, 2, -22, 21, -1, -2, -1, -15, 13, 3, -7, 4, 0, -7, 8, + -7, 11, 3, -2, -8, 10, -15, 0, 9, -14, -8, 8, -2, -9, 10, -13, + 9, 7, -6, 2, -12, -4, 6, -12, 8, 12, 3, -10, 6, 7, 1, -2, + -11, -1, 7, -7, 8, -13, -10, 11, -9, -10, -8, 20, 9, -11, 8, -5, + -4, 6, -3, 5, 13, -13, -7, -7, 6, 19, 0, -9, 9, -1, -3, 4, + -7, 0, -2, -4, -5, 5, 0, -5, 14, -19, -14, 18, -1, -5, 3, -12, + 18, -19, 4, -15, -10, 10, 10, -17, -4, 19, -6, -2, 5, 11, -4, -3, + 9, -22, 28, -6, -5, 0, -1, 11, -11, -13, 22, 3, -8, -9, 1, 3, + 0, 1, 2, 7, -5, -25, 10, 6, 6, 2, -11, 8, -16, 15, -20, 5, + 9, -6, -13, -5, 14, 6, -21, 22, -7, -14, 4, 26, -8, -13, 8, 1, + -10, -13, 11, 10, -10, 2, -13, -9, 15, 0, 10, -30, 14, 7, -13, -5, + -12, 8, 10, -4, 10, 12, -15, -7, 5, 2, 2, 10, -13, -3, 0, 21, + -2, -16, 9, 3, -1, 6, 15, -3, -21, 10, -8, 5, 1, 1, 2, -19, + 10, -7, -3, -1, 8, 6, -26, -10, 18, -28, -3, -3, 4, 0, -7, 6, + -10, -2, 25, -19, 5, -11, -2, 14, 4, -5, -3, 4, -5, 6, -2, -3, + 11, -1, 13, -12, 5, 20, -15, -3, 17, 4, -14, -5, 11, 3, 1, 6, + 11, -20, 10, -4, -4, -4, -4, -18, -7, 5, 10, -25, 7, -9, -15, 1, + -4, 4, 4, -4, -1, -18, 9, -6, 4, 7, -19, 10, 0, 3, -6, 12, + 18, -5, 2, 4, -4, 11, 2, 5, 2, 1, 3, -4, 3, 4, -3, -2, + -8, 11, 5, -10, -12, 12, -6, 6, -9, -6, 4, 9, 0, -9, 4, 3, + -7, -5, -12, 19, 2, -28, 1, 0, 9, -10, -6, 3, 3, -11, -4, 6, + 7, -7, -3, 5, -12, 9, 10, -12, 7, 5, 5, -6, -9, 16, 6, -16, + 3, 8, -17, 12, -5, 2, 1, 21, -25, -10, 5, -2, 15, -6, 1, 3, + 5, -16, -2, -16, 32, -17, 7, -13, 6, -1, -4, 0, -4, 10, -2, -17, + -7, 29, 0, -13, -1, -1, 2, 12, -4, 3, -2, 4, -19, -1, 18, 2, + -3, -15, -2, 10, -4, 1, -2, -5, 20, -5, -6, -7, 9, 0, -2, -24, + 5, 15, -2, -11, 1, 0, -2, -14, -2, -4, 7, 4, -4, -9, 2, 4, + -8, 8, -1, 2, 10, -13, 4, 10, -4, 27, -22, 17, -18, -2, 5, 8, + -1, 4, -6, 2, -1, 9, 1, -3, 16, -21, -18, 2, 10, -14, 9, 3, + -14, -9, 0, -16, 9, -10, 11, -12, -3, 1, -10, 3, -2, 2, -13, 13, + 10, -1, 4, 4, 1, -3, 9, 0, 4, 8, -14, 10, -4, 0, 8, 11, + -2, 2, -11, 3, -13, -8, 11, 4, 1, -7, 4, -21, 0, 1, -4, -22, + 17, -8, -16, 10, 4, -2, 0, -4, 2, -2, 2, -6, 10, 3, 3, 5, + -1, 6, 5, 2, -6, -3, -2, 7, -4, -4, 12, 1, -30, 12, -7, 3, + 4, -6, -7, -9, 9, -1, 7, -10, 12, -16, 2, -8, 23, -5, -5, -1, + -8, 10, 3, -14, -12, 25, 7, -13, -6, 4, 15, -3, -23, 9, 12, -9, + -13, 18, -9, 5, 1, -17, -4, 13, -10, 11, -10, -1, 6, 0, -7, -2, + 9, -4, 9, -24, 7, 6, -5, 4, 15, -15, 11, -5, -24, 9, 11, -16, + 2, 0, -9, -2, 10, 7, -12, 8, -12, -6, 10, 6, 10, -14, -5, 20, + -16, 7, 8, -1, -19, 24, 2, -10, 15, 6, -6, -21, 3, -3, 15, -9, + -3, 3, -2, -4, -3, -9, 5, 0, -5, -3, -15, -4, -1, 1, -14, 33, + -12, -18, 9, -2, -10, 9, 9, -1, -1, -5, 10, -3, 2, 4, 2, -9, + -1, 25, -2, -3, 15, -17, -7, 8, -7, 0, 10, -13, 9, -11, 0, -3, + 18, -15, -11, 5, 0, -12, -2, 7, -6, -4, -9, 11, -6, 8, 1, -14, + 3, 16, -10, -3, 2, 6, 4, 9, -9, -2, 0, 2, -3, 15, 3, -10, + -4, -8, -1, 10, -13, -9, 16, -9, -3, -2, 5, -6, -6, -9, 10, 8, + -4, 14, -7, -19, 12, 1, 2, 1, 4, -1, -6, -3, -3, 5, 7, -2, + 0, 0, -5, 0, -6, 1, 6, -5, -4, 5, -6, 5, -4, -8, 15, -5, + -7, 0, 3, -8, 0, 3, -8, -4, 6, -4, -4, 15, -5, -8, -7, 4, + 7, -10, -6, 15, -4, -13, 7, 2, 2, 1, -4, 5, 0, 0, 1, 4, + -7, 4, 4, -2, 4, 5, 1, -18, 12, 4, -3, -6, 11, 0, -13, -1, + 1, -12, 3, 13, -9, -15, 7, 0, -4, -8, 0, 5, 0, -9, 1, 1, + -3, 0, 3, 5, -10, 6, -1, -4, 4, 15, -15, -5, -9, 18, -2, 0, + 15, -11, -9, 0, 6, -2, 8, 1, -8, -9, 7, 3, -7, -3, 6, 1, + -5, 0, -5, -5, 0, -3, 11, 1, -3, -8, -4, -4, 5, 9, -6, -7, + 4, 15, -13, 5, -4, 2, -6, -2, 0, 5, 4, -4, 0, -6, 8, 3, + -2, -4, -4, -11, 4, 10, -1, -4, -2, -1, -3, 1, -4, -2, 3, 1, + -4, -11, 12, -4, 5, -2, 7, -12, -2, 4, -4, 5, 8, 1, -8, 14, + -11, -1, 1, 4, 0, 5, -5, 2, -7, -7, 10, 3, 1, -13, 0, -4, + 5, -9, -1, 1, -11, -5, 5, 2, -6, 5, -5, -8, 12, -2, 7, -1, + -10, -5, -7, 14, 9, 3, -5, -2, 5, 4, -2, 0, -5, 2, 3, 3, + -12, 6, 3, 2, -9, -1, 24, -13, -9, -1, -2, 0, 7, -6, -17, 14, + -12, -5, 10, 1, -4, -1, -1, 1, -3, 2, -2, -11, 1, -1, -1, 1, + 10, -3, 2, 1, 5, -7, 1, -1, -5, 7, 1, 7, -4, 5, -11, -8, + -8, 7, 8, 6, 0, -15, -1, 7, 0, -6, -3, 7, -4, -3, -2, 1, + 5, 8, -6, -4, 11, 3, -14, -6, -3, -6, 9, -5, 4, -5, 2, 3, + -13, -3, 1, -4, -3, 11, -1, 0, 7, -16, -6, 11, 5, 0, 4, 5, + -2, -3, -2, 8, 7, -16, 1, 2, 6, 3, -17, 11, -2, -2, -9, 6, + 0, -7, 6, -22, -2, 14, 3, -11, 0, -6, -2, -7, -7, 1, 4, 14, + -1, -6, 0, 7, 3, -14, 4, 15, -4, -9, -2, 12, 14, -10, 5, 9, + -11, -2, -9, 2, -9, 11, 2, -21, 7, 6, -11, -1, 0, 0, 1, -9, + 4, 0, -10, 1, 3, -3, -7, 12, -9, -2, 4, 6, 3, -8, 0, 1, + -2, -14, 12, 11, -5, 10, -3, -1, 3, -6, 1, 0, -3, 8, -1, -18, + 12, 5, -13, -4, 17, -1, -6, 1, -11, 0, -6, 2, -2, -2, 5, 3, + -17, 2, -5, 11, -4, 8, 8, -19, -6, 14, -6, -6, 0, 5, 0, -8, + 7, 13, -6, -5, 6, -2, -9, -1, 8, 3, -4, -4, 10, -10, -9, 7, + 2, -6, 14, 0, -15, 3, 5, -4, -10, 8, 0, -6, -11, 3, 10, -9, + 1, 8, -7, 2, -1, -6, -8, 6, 2, -8, -2, 16, -3, -3, -1, 5, + -3, -8, 6, 9, -6, 1, -1, -1, 2, -6, 6, -1, -9, 3, 9, -10, + 1, 5, -4, -14, 2, 1, 7, -5, 3, -2, -13, 5, 10, -9, -8, 14, + -6, -19, -3, 19, -3, -3, 6, -4, -10, 3, -1, -4, 5, 5, 1, 0, + -1, 11, 4, -10, 3, -5, 4, -7, 1, 8, -3, 1, 2, 0, -10, 2, + 5, -15, -3, 8, -8, -6, 5, -2, -5, -5, 11, 0, -12, -7, 5, 2, + -5, 2, -1, -4, 2, 7, -12, 5, 6, -3, 5, -1, 12, 7, -13, -3, + 0, 3, 0, 13, -1, -4, 0, -9, 5, -6, 5, -2, -10, -6, -2, 9, + -8, 5, -6, -10, 5, 4, -6, -2, 1, 1, 6, -14, 10, -3, -4, -5, + 1, 8, -16, 7, 7, -1, 0, 3, -5, 2, -1, -3, 11, -11, 9, 8, + -18, 3, 8, 13, -4, -5, -9, 4, -2, -4, 9, 5, -6, -5, -15, -3, + 17, -6, 2, -8, 4, 4, -4, -12, -3, -2, -2, -4, 5, -4, 1, 7, + -12, -6, 8, 6, -2, 1, -3, 3, 10, -3, 7, -11, 12, 4, -1, -1, + 1, 0, -11, 11, 4, 0, -2, -9, -2, -2, -8, -1, 5, -4, -5, -5, + 1, 10, -8, -11, -5, -4, 5, -1, 1, 6, -2, -5, -5, 3, 6, -2, + 6, -3, 0, 4, 5, 2, 4, -2, 1, 5, -2, -6, 11, -1, -5, 8, + -14, 6, -2, -6, -11, 4, 2, -14, 6, -9, 5, -4, -3, 4, -12, -2, + 2, -5, 4, 7, -5, 3, 6, -1, -3, -6, 0, 7, 0, 1, 6, 9, + 4, -2, -7, -4, 7, 4, 4, -5, -5, 0, 3, -6, -1, 7, -2, -18, + -1, 3, -15, 5, -2, -2, 0, 4, -10, -4, 3, 4, -10, 4, -1, 5, + 4, -7, 8, -7, 0, 3, 2, -7, 13, 0, -2, -6, -6, 5, 10, -10, + 4, -1, 2, -1, -5, 7, 5, -3, -7, 1, -5, 10, 1, -11, 7, 6, + -10, -15, 12, 2, -4, 1, 0, -5, 3, 0, -2, 6, -5, -4, -13, -2, + 3, 1, 4, 3, 3, -10, -7, -7, 11, -2, 2, 2, -7, 4, -1, 6, + 2, 0, 8, 3, 0, -7, 8, 3, 5, -8, -3, -2, 2, 3, -12, -4, + -3, 12, -12, -4, 7, -3, -10, -10, -4, 6, -2, -8, 9, 1, 1, 1, + -3, -6, 12, -5, -6, -1, 11, -7, 5, 6, 2, 9, -11, 6, -2, 8, + 1, -6, 4, 3, -6, -3, 5, -4, 4, 1, -19, -1, 3, 4, 0, 0, + -10, -1, -3, -5, -3, 0, 11, -1, -12, -2, 6, 0, -3, 3, 4, -1, + -7, 1, -2, -1, 2, -1, 0, 2, -2, 4, -5, -4, 11, -4, -5, -3, + 7, 5, -8, 3, 6, -9, 0, 9, -5, -2, 5, -4, -6, 0, 7, -1, + -2, 0, -1, -6, -9, -6, -1, 8, 4, -1, -9, -5, 13, 2, -11, -5, + 9, 0, -8, -1, 5, -2, -5, -3, -2, 7, 5, -4, -13, 3, 11, -8, + 3, 0, 2, 5, -12, -6, 6, 3, -4, -1, 8, 1, -5, -7, -6, 2, + 8, 5, -2, -9, 7, -6, -2, 13, -7, 2, 1, -1, -5, 3, 7, -1, + -11, 9, -6, -4, -2, -5, -1, 2, -1, 3, 8, -7, -1, -9, 0, 0, + -1, 2, 5, -2, 1, -2, -3, 6, 6, -3, -6, -5, 4, -1, 1, 5, + 1, -1, -2, -3, -4, 4, 3, 1, -7, 5, -1, 0, -8, -6, 1, 7, + -3, -6, -2, 3, -1, -3, 2, 2, 0, -9, 1, -2, 4, 4, -5, 1, + -1, 1, 6, -2, 2, -5, -4, -1, 14, -3, 2, -9, 1, -2, -4, 1, + -1, 7, -9, 5, 2, -3, 2, -2, -9, -2, 4, -1, 2, -2, -2, 0, + -1, -1, -2, 3, 1, -1, -3, -6, 3, 7, -5, -3, 9, -5, -4, -5, + 8, -4, 2, 2, 8, -10, -1, 8, -14, 0, 6, -7, -1, 2, -3, 2, + -4, 5, 2, -5, -4, 5, 1, -6, 3, 6, -4, -1, -3, 3, -7, 0, + 1, 0, -4, 7, 6, -13, -3, 3, 2, -15, 8, 3, -3, -6, 9, -4, + -1, 9, 1, -6, -6, 7, 1, 1, -2, 6, -1, -4, -1, -1, -7, 5, + 3, 0, -5, -2, 8, -2, -8, 6, 7, -16, -5, 6, -6, -1, 1, 7, + -4, -3, -6, 3, -10, -3, 8, -9, -1, 5, -1, -7, 5, 2, -1, 1, + 5, 1, 2, -4, -5, 1, 1, 3, 1, -5, -2, 3, 2, -7, -1, 7, + 5, -5, -7, 5, 0, 3, -1, -4, -4, 4, 0, -4, 1, 6, -3, -7, + 0, -3, -3, -1, 0, -2, -4, 2, 1, -2, 3, -1, 0, -1, -6, 9, + -5, 4, -1, -1, 4, -2, 5, -8, 2, -3, -2, 2, -3, 10, 2, -3, + -5, 2, -4, -1, -3, -7, 9, 1, 0, 0, -5, 1, -2, -12, 6, 8, + -18, 4, -1, 4, -1, 5, -5, -3, 3, -1, 4, -5, 9, -5, -4, -5, + 2, 5, -1, -4, 0, -3, -2, 8, -5, 2, 1, -13, 3, 1, 4, 5, + -8, 2, 8, 1, -1, 1, -9, 1, -2, -4, 1, 4, -3, 4, -4, -5, + 6, 5, -6, -3, -3, 1, 1, -7, 1, 2, 1, -5, -4, -2, 2, -6, + 6, 3, 7, -10, -9, 4, 1, -5, 6, 9, 3, 1, -2, -4, 3, 4, + -1, -6, 3, 1, -2, -9, 4, 4, -5, 4, -10, 2, -4, -5, -1, 1, + 2, 0, 2, -8, 1, 3, -4, -13, 0, 10, -1, -4, 5, 0, -4, 5, + -3, 2, -5, 2, 1, 2, 4, 2, 2, -10, 5, 3, -11, -2, 3, 3, + 0, -6, -2, 1, 1, 2, -1, -8, -1, -5, -4, -3, 5, 8, -4, -4, + 2, 0, -2, -2, 1, -5, 0, 13, -8, -6, 4, 8, -6, -1, 6, -2, + 4, -5, 3, 5, -7, -8, -2, -3, 7, 8, -8, -3, 1, 5, -5, -5, + 9, -4, -7, -5, 4, 3, -6, 5, 1, -1, 3, 0, -6, -9, 0, -6, + 1, 4, 10, 5, -13, 0, 6, -2, -4, 2, -2, 6, -1, -4, 0, -11, + 6, 3, -1, -3, 14, -1, -15, 1, 2, 3, -1, 4, -3, -6, 0, 3, + 0, -6, 10, -3, -14, -2, 10, -3, -9, -4, 0, 6, -1, 7, -3, -5, + -6, 1, 0, -5, 11, -2, 1, -2, 5, -1, -4, -1, -3, -4, 2, 11, + 2, -4, 1, 2, -12, 7, 3, -1, -11, 3, 15, -8, -11, 0, 0, 2, + -7, 1, -3, -4, -3, -5, -4, 6, 11, -7, -8, -1, 6, -5, -3, 6, + 8, 3, -6, 1, -1, -1, -1, -5, -3, 8, 7, 4, -9, 1, -2, -4, + -6, 9, -4, 3, -8, 0, 6, -2, -4, -2, -2, -6, 8, -7, 3, 1, + 3, -1, -3, 2, 1, -6, -9, 3, -5, 8, 5, -10, 7, 5, -3, -2, + -1, -3, -1, -4, -7, 6, 6, 3, -7, 0, 0, 1, 0, -7, 3, -1, + 0, 1, 2, 2, 2, -11, -8, 9, 6, 2, -6, -1, 1, -3, 3, 1, + -6, 2, -3, -2, -1, 2, -4, 0, -4, -2, 0, -3, -2, -6, 5, 2, + 0, -1, -3, -1, 3, 1, -2, 0, 2, 2, 0, 1, 7, 1, -4, -2, + -6, 4, 3, -1, -4, -1, 3, 3, -9, -2, 0, -2, -1, -5, 6, 1, + -5, 1, -5, 9, -10, -4, 0, -4, 6, 1, -3, -5, 9, -2, -5, 2, + 0, 6, -6, 2, 5, 10, -8, -3, -2, -1, 4, -3, -1, -4, 0, -1, + 1, -4, 0, 5, -8, -1, -5, -1, -1, 3, 3, 3, 2, -14, -5, 1, + 2, 3, 1, -1, 2, 5, -2, 2, -5, 2, 3, -2, -2, -3, 4, 4, + 4, -6, 3, 1, -10, 1, -6, 6, -2, -3, 0, -3, 1, -3, 1, -1, + -4, -5, -4, 7, -2, -2, -3, 6, -5, -5, 2, -6, 1, 4, 3, -8, + 11, 4, -4, -1, 2, 3, -5, -2, 1, 7, -4, 2, 4, -10, 7, -7, + -1, 0, -3, 5, -4, -1, -4, 5, -7, 3, 3, -11, -2, -1, 5, 1, + -1, 0, 6, -11, 0, 1, -2, 1, 0, -1, -4, 2, 9, -2, -9, -4, + 2, 0, 2, -1, 1, 1, -7, 5, -3, 4, -1, -3, -8, 5, 7, -1, + -1, -3, 3, -7, 0, 4, -3, -3, 1, 6, 0, -1, 0, -5, -1, 0, + -4, 0, 0, -3, 1, -4, 1, 7, -3, -13, -2, -2, -1, 3, 5, 2, + -6, 1, 6, -2, -6, 8, -1, -6, 0, 4, 6, -2, 0, -2, -4, 3, + 5, -4, -7, 2, 5, -3, -3, 3, 1, -10, -7, 3, 1, -3, 2, 4, + -7, -3, 0, 2, -5, -3, 3, -2, 0, 3, 5, -6, -1, 4, -2, 0, + 5, 1, -2, -2, 3, 2, -1, -3, -3, -7, 7, 3, -1, -2, 0, 0, + 1, -2, 1, 0, -15, -1, 3, 2, -3, 4, 0, -7, 0, -1, -1, -4, + -3, 2, -1, -1, 11, -3, -1, -5, -1, 2, 2, 0, 1, 2, 3, 4, + -6, -3, -2, 1, 0, -4, 2, 1, -1, -5, 1, -1, -7, 2, -2, -5, + 0, 2, -2, 3, 5, 0, -2, -6, 6, -7, 3, -4, -6, 1, 6, 3, + 1, -2, -3, -4, -6, -1, 7, -2, 0, -3, 0, 9, -3, -5, -1, 3, + 0, -1, -3, 6, 1, -6, -3, 3, 6, 0, -6, -4, 2, 1, -1, 2, + -5, 4, 1, -2, -5, 0, 7, -9, 3, -1, 1, -6, 0, -5, -1, 1, + -1, 0, -4, 2, -2, -2, 1, 6, -1, -5, 0, 0, 0, 1, 3, 2, + 2, -1, -3, 0, 1, 5, 1, -5, -7, 2, 6, -3, -3, -3, 2, -7, + -5, 5, 0, 0, -3, -4, -1, 3, -4, -5, 1, 5, -1, -2, -4, 0, + 5, 2, 0, 2, 2, -1, -1, -5, 5, 3, -1, -4, 1, 0, -1, -2, + -1, 2, 2, -4, -4, 2, -2, -3, -4, -3, 0, 3, -3, -2, -2, 4, + 1, -2, -2, 1, 2, -6, -1, 2, 6, 1, -2, 0, 4, -3, -1, -2, + -1, 5, 1, -11, 4, 3, -1, -6, 2, -2, 3, -4, -8, -2, -1, 4, + 0, 3, -2, -1, -2, -2, 1, 3, 3, -7, 0, 2, 10, 0, -4, 3, + -3, 0, 0, 3, -4, 6, -4, -8, 2, 1, 3, -14, 1, -1, -2, 0, + 0, -5, -1, 2, -6, -1, 3, 0, -5, -3, 3, 1, 6, -2, 0, 6, + 2, -7, 1, 3, -5, 5, 8, 0, -1, 1, -4, -6, -2, 6, 4, -4, + -1, 1, -10, 0, -4, 0, -3, 2, 0, -8, 3, -3, 0, 2, -1, 1, + -8, -1, -1, -3, -1, 4, 1, 6, 1, 0, 0, -2, 0, -2, 7, -4, + 3, -1, 2, 0, -2, -2, -8, 3, 2, -1, -4, 3, 0, -3, -5, 2, + -3, -3, -2, 5, 2, 1, 1, -4, 1, -1, 4, 6, -4, 0, -6, -4, + 1, 3, 3, -1, -2, -7, -1, -3, 6, -6, 2, 1, 5, -8, -5, -1, + 2, -1, -3, -1, -1, 5, -7, 3, 3, 1, 4, -4, -3, -3, 8, 1, + -2, 4, 4, -2, -8, 2, 1, 0, 2, 0, -6, 3, -2, -8, -2, 5, + -1, -6, 0, 2, -1, -5, -2, -2, 6, 0, -5, -2, 3, 0, -5, -1, + 6, 7, 2, -8, -4, 6, 2, -6, -4, 12, 2, -5, -2, -6, 1, 1, + -3, -7, -3, 11, -3, -6, -1, 3, -2, -4, -4, 4, -3, 4, -2, -3, + 1, 7, 0, -8, 7, 1, -2, -4, -6, 13, 0, -3, 1, 2, -1, -4, + -3, 1, 3, -2, -3, -1, 0, 3, -1, -10, -1, 2, -8, -3, 3, 2, + 1, 4, -6, -2, 1, -3, -1, -4, 6, 5, -1, -5, -1, 9, -2, 0, + -4, 0, 1, -3, 4, -5, 1, 3, -4, -6, 0, 4, -2, -6, 9, -1, + -3, 2, -4, 0, 4, -7, -4, -1, 1, 4, 0, -1, 6, -2, -2, 4, + -3, -1, -6, -2, 2, 3, 1, -3, 8, -10, -10, 7, 0, -2, -1, -4, + 3, -6, 0, -5, -5, 5, 3, -6, 1, 5, 0, -1, 1, -1, 0, 0, + 0, -5, 7, -2, -1, 2, -1, 3, 0, -6, 4, -3, -2, -3, -2, 1, + 3, 3, 0, -2, -1, -9, 2, 2, -1, 4, -4, 4, -10, 7, -8, 2, + 1, -1, 0, -1, 4, 2, -7, 7, -6, -4, 3, 11, -5, -6, 1, 3, + -4, -6, 2, 2, -2, -3, -7, -4, 6, 0, 7, -13, 6, 2, -9, -2, + -5, 3, 8, 0, 0, 5, -5, -4, 3, 0, 2, 4, -7, 0, -1, 10, + -3, -6, 7, 2, -1, 0, 6, -2, -7, 4, -2, -1, -2, 1, -3, -9, + 6, 0, -4, 0, 3, 3, -11, -4, 7, -16, -2, 0, 2, 1, -2, 2, + -5, -1, 12, -6, 2, -7, 2, 6, 0, -4, -1, 1, -3, 2, -1, 0, + 7, -2, 2, -6, 2, 7, -9, -4, 8, 2, -9, -3, 8, 1, -1, 4, + 5, -11, 2, 1, -1, 0, 0, -6, -2, 2, 6, -13, 2, -3, -8, 1, + 1, 3, -2, -3, -2, -7, 4, -6, -2, 3, -10, 5, -2, 1, -3, 5, + 8, -4, -1, 2, -1, 6, 2, 3, 2, -2, 0, -1, 0, 4, 1, -1, + -2, 7, 1, -7, -5, 7, -5, 2, -5, -4, 0, 3, 3, -2, 0, -1, + -9, -4, -9, 10, 1, -14, 0, -1, 6, -8, -3, 3, -1, -6, -1, 5, + 3, -5, -1, 3, -6, 5, 7, -10, 5, 5, 2, -4, -3, 9, 4, -11, + 0, 5, -11, 7, -6, 2, 2, 12, -15, -8, 2, -3, 7, -5, 3, 3, + 1, -10, 0, -9, 17, -11, 7, -6, 2, 1, -3, 0, -1, 5, -2, -10, + -4, 16, -1, -7, -1, -3, 1, 11, -3, 1, -3, 2, -12, -2, 12, 3, + -1, -10, -2, 6, -3, 1, -1, -4, 12, -1, -2, -7, 6, -1, -1, -16, + 5, 11, -3, -7, 1, -1, -2, -6, -4, -5, 3, 4, -3, -8, -1, 3, + -5, 3, 1, 2, 6, -10, 1, 7, 0, 21, -15, 11, -12, 0, 1, 4, + 1, 4, -4, -1, 3, 7, 0, -5, 10, -15, -14, 2, 6, -11, 5, 3, + -10, -6, -1, -11, 4, -9, 6, -9, -2, 2, -8, 3, 0, 2, -9, 7, + 7, 2, 2, 0, 3, 1, 6, 0, 3, 6, -10, 6, -4, 1, 7, 9, + -1, 0, -7, 1, -11, -8, 9, 4, 0, -6, 2, -16, 0, 1, -2, -16, + 10, -7, -12, 7, 4, -1, -1, -4, 2, -1, 2, -5, 8, 3, 3, 4, + -2, 4, 3, 2, -4, -2, -1, 5, -5, -3, 9, 2, -22, 8, -6, 1, + 3, -5, -4, -6, 7, 0, 5, -8, 9, -13, 0, -6, 18, -3, -3, -1, + -6, 7, 3, -11, -9, 19, 6, -10, -6, 3, 12, -2, -18, 7, 8, -7, + -10, 14, -8, 5, 1, -15, -4, 11, -6, 9, -8, -1, 5, 1, -6, -2, + 7, -3, 7, -20, 6, 5, -4, 3, 12, -12, 11, -4, -22, 7, 9, -13, + 1, 0, -8, -1, 9, 6, -10, 5, -9, -5, 8, 5, 8, -12, -4, 16, + -14, 7, 6, -1, -16, 21, 2, -9, 13, 5, -4, -19, 2, -3, 12, -7, + -2, 3, -2, -4, -3, -8, 4, 1, -4, -4, -14, -3, -1, 1, -11, 30, + -11, -16, 8, -2, -9, 8, 8, -1, -1, -5, 10, -4, 1, 4, 3, -8, + -1, 23, -2, -2, 14, -15, -7, 7, -7, 0, 9, -12, 8, -10, 0, -3, + 16, -13, -11, 5, -1, -10, -2, 6, -5, -4, -9, 10, -6, 7, 1, -13, + 2, 14, -9, -3, 2, 6, 4, 8, -8, -2, 0, 2, -3, 14, 3, -10, + -4, -8, -1, 10, -13, -8, 15, -9, -3, -2, 5, -5, -6, -9, 9, 7, + -4, 14, -7, -18, 12, 1, 2, 1, 4, -2, -6, -3, -2, 5, 7, -2, + 0, 0, -4, 0, -6, 1, 5, -5, -4, 5, -6, 5, -4, -8, 15, -5, + -6, 0, 3, -8, 0, 3, 0, -1, 0, -4, 6, -16, 22, -7, 3, -5, + 2, 2, 1, -3, 4, -8, 4, 4, 0, -5, -9, 4, -5, -4, 3, 2, + 1, 3, -4, 6, -15, -1, 4, 1, -9, 3, 1, -8, 3, -6, 11, -5, + 6, -11, 17, -15, -2, -19, -11, 1, -4, 8, 0, 5, 18, -11, 0, 13, + -4, 6, -13, 4, -11, -1, -7, -7, 11, 10, -9, 17, -11, 20, -6, 7, + -14, 23, -7, -2, -2, 7, -10, 2, 0, 2, 5, 6, -8, 5, -4, -10, + 9, -4, 6, 0, -7, 8, -7, 1, -20, -4, -1, -3, 6, -10, -6, -15, + -11, 10, -5, 19, 3, 1, -19, -11, -1, -9, 9, 22, 24, 10, -5, -18, + -8, -23, 14, 11, 0, 31, 43, -9, 0, -7, -15, -28, -35, -30, 3, 5, + -5, 11, 52, 55, 7, -5, -10, -12, -25, -43, -12, 4, -37, -47, -21, -5, + 4, -11, 1, 31, 27, 34, 46, 48, 61, 10, 16, 8, 7, -14, -40, -47, + -36, -51, -42, -15, 4, 12, -32, -42, -10, -4, 10, 1, 15, 50, 31, 5, + 15, 38, 37, 29, 15, 22, 11, -4, -35, 10, 3, -18, 1, -14, -33, -5, + -47, -25, -13, -2, 15, -6, 5, -29, -17, -19, -1, 3, 7, 2, 17, 28, + -8, -23, 7, 7, 36, 15, 2, 1, -2, -9, 1, 6, 20, 6, 14, -3, + 21, -11, -12, -35, 11, -20, -18, -36, -23, -27, -19, 1, 10, 14, 27, 6, + 44, 14, -9, 3, 20, 27, 45, -8, -13, 16, -16, 24, -10, -9, -3, -38, + -19, -14, -38, -38, -41, 13, 40, -37, 5, -7, -7, -4, 4, -31, 32, 22, + 15, 9, 13, 10, 10, -17, 22, 30, 9, -6, 27, 66, 47, -17, -21, -20, + -9, -36, -73, -3, 22, -35, -12, 6, 7, 4, -17, -45, 22, 17, -17, 3, + -9, -4, 11, -10, 13, -4, 8, 38, 3, 20, 42, -22, 9, 23, -28, -21, + 3, 10, 1, 26, -28, -18, -9, 7, -30, -41, -24, -9, 10, -6, 31, -5, + 2, 29, -9, 1, -27, -24, 7, -19, -5, 10, -13, 21, 21, 3, 30, -11, + -17, 34, -11, 8, 7, -8, 1, 11, -1, 7, -13, 1, -3, 23, -12, 8, + -19, -3, 20, -78, 42, -23, 4, -29, -16, -5, 38, -49, 30, -26, 26, 16, + 8, -33, 53, 19, -20, 12, 5, 23, -11, 4, -6, 42, -111, 67, -40, 29, + -32, -20, -77, 113, -46, -12, 8, -5, -14, 35, -52, 94, -5, -61, 58, -36, + 41, -83, 21, -19, 61, -68, 37, -37, 12, 66, -69, -16, 100, -88, 48, 21, + -39, 73, -24, -2, 45, 65, -59, 53, -103, 95, -97, 1, -14, -4, -41, 9, + -13, -18, 16, -26, 9, 26, -15, 25, -16, 6, 8, 26, -52, 35, -21, 4, + -2, -11, -4, 22, 0, 21, -40, 65, -6, -13, -11, -7, 32, -46, -48, 16, + -26, -3, 0, -42, 87, -68, 34, 17, -14, 43, 23, -15, 30, 20, 47, -19, + -33, -12, 15, 1, -37, 15, -12, -11, -7, 15, -75, 36, -41, 27, -8, -7, + -12, 10, -4, 49, -6, 42, -32, 4, 20, 33, -65, 24, -52, 10, 13, -17, + -15, 60, -14, -55, 35, -16, 50, -83, -3, 29, 58, -75, 71, -46, 47, -32, + 44, -57, 10, -43, 33, 22, -48, 51, -41, 6, 7, 39, -3, -41, 7, -9, + 37, -66, 22, 26, -13, 74, -87, 127, -39, -16, -29, -11, -8, -57, -15, -45, + 52, -74, -5, -2, 103, -126, 85, 20, 28, -7, 53, -38, 58, -10, -11, 33, + -70, 20, 1, 40, -36, 26, -58, 58, -23, 61, -71, -7, -39, 43, 22, -18, + -1, -61, 90, -37, 35, -58, 30, -62, 27, -45, 47, -59, -6, -35, 70, -49, + 9, -30, 92, -15, 21, 1, 26, 6, -19, 90, -43, 49, -46, 10, 6, 15, + -90, 67, -51, -11, 4, 28, -36, 24, 41, -68, 24, -34, 63, -40, 17, -30, + 18, -39, 14, -38, 15, 9, -54, 54, -20, 36, -21, -14, -13, 11, 23, 11, + -54, 56, -25, 37, -46, 49, -74, 81, -40, 51, -44, 57, -69, 51, -50, 61, + 27, -112, 111, -114, 106, -85, 49, -61, 75, -18, 26, -68, 32, -15, -25, 21, + -15, 38, -46, 80, -119, 126, -85, 41, -40, 77, -65, 28, -6, -39, 45, -87, + 39, -63, 81, -32, 4, -32, 44, -25, 42, -12, -15, 21, -1, -56, 21, 23, + -30, 33, -28, -3, 32, 4, -36, 60, -20, 13, -3, 22, -43, 101, -88, 59, + -53, 18, 8, 22, -33, -52, 34, -32, 35, -90, 112, -107, 56, -59, 43, -60, + -18, -4, -21, 45, 11, -48, 11, 38, -27, 58, -49, 65, 19, 54, -38, 35, + -37, 24, -11, 44, -62, 41, -16, -48, -8, 31, -68, 17, -3, -5, 52, -51, + -10, 16, -26, 18, -29, 56, -41, 3, 5, -10, -37, 61, -14, -10, -9, 20, + -8, 8, -2, -16, 44, -17, 14, -33, 30, -2, -27, 16, 3, 0, 51, -42, + 32, -20, 8, -11, -24, 10, 12, -15, 6, -32, 10, 21, -38, -11, -12, 23, + 13, -64, 19, 34, -23, -23, 16, 10, 39, 2, -36, 55, -31, 0, -29, 18, + 8, 12, -61, 73, -28, 54, -34, 21, 9, 7, 53, -34, -29, 19, -7, -44, + 7, 15, -16, -18, -31, 10, -29, 36, -69, 7, 4, 33, -72, 45, 14, 0, + -8, 35, -13, 26, 16, -28, -3, -32, 45, -4, 8, -20, 65, -24, 2, -24, + 40, -16, -16, 20, 8, 2, -3, -2, 23, -15, -11, -30, 19, -51, -19, -5, + -36, 18, 24, -4, -1, 46, -90, 60, 4, 23, -17, 16, 60, -24, 0, 18, + 0, 5, -6, -24, 27, -34, -28, -7, -4, 22, -30, -11, -3, -1, -44, 36, + -38, -6, -9, 55, -34, 16, 27, 28, -65, 62, 22, -32, 36, 7, 2, 27, + -19, 50, -71, 44, -19, -67, 13, -3, -14, -30, 33, 5, -12, -48, 60, -47, + -28, 9, -6, 24, -11, -1, 13, 62, -53, 26, 7, -9, 6, 58, -38, -10, + 0, 5, -23, 23, 8, -14, -19, 21, -9, 35, -17, -28, 14, 27, -17, -14, + -29, 24, 6, -85, 74, -16, -18, -2, -19, 47, -29, -18, -15, 52, 0, 7, + -10, -23, 45, 13, -11, 12, -28, 27, -26, 19, -69, 74, -55, 35, -21, 41, + -24, -11, 39, -19, 7, 0, 7, -31, 10, 7, -45, -17, 25, -12, 9, -19, + 3, 28, -53, 76, -19, -25, 49, -2, 6, -11, 24, -12, -23, 17, -1, -15, + -10, -36, 26, -25, 0, -44, 59, -67, 45, -31, 5, 15, 56, -12, -14, 12, + 10, 24, -52, 37, 5, -35, 52, 23, -55, -6, 24, -49, 26, 31, -24, 10, + -33, 33, -11, 1, -49, 8, 7, 6, -78, 12, -22, 10, -11, 13, 13, -18, + 38, 50, -18, -5, 64, -52, 59, 33, 3, -9, -6, -6, 26, -64, 18, -38, + -47, 18, -33, 4, -39, 40, -31, -1, -23, 48, -30, 18, 17, 32, -20, 32, + 19, 24, -58, 49, -38, -9, 15, -28, 16, -3, -2, -28, 33, -22, 23, -1, + -34, 33, -48, 67, -55, 21, 51, -66, -2, 21, -5, -17, 24, -63, 53, 8, + -19, 9, -11, 36, -37, -35, 43, -35, -3, -44, 68, -43, 53, -24, -5, 45, + -16, -7, 14, 49, 3, -16, 22, -10, 2, -28, -9, -6, -5, 32, -76, -22, + 35, -26, -35, -12, 0, 3, 13, 6, 36, 7, -32, 69, -15, 45, -20, -21, + 35, 35, 1, -25, 11, 34, -24, -33, -9, 5, -25, -49, 31, -41, 15, -42, + 25, -30, 42, -80, 32, 2, -18, 33, -12, -9, 43, -1, 4, -12, 54, -51, + 22, -1, 18, 28, -29, 18, 7, 10, -19, 8, -1, 12, -21, -6, -11, 4, + 4, -28, -8, 22, -27, -5, 9, -25, 20, -19, -36, 41, -8, 20, -32, 16, + -29, 29, -13, 13, 4, 1, 17, 8, 0, 9, 22, -1, -3, 28, -11, -39, + 36, -31, 5, -11, -27, 22, -39, 7, 15, -24, 19, 8, -37, 75, -52, 54, + -65, 22, -13, 23, -26, 32, -19, 10, -8, -3, 12, 16, -44, 25, -23, 14, + 9, -46, 20, 2, -4, -8, -6, 18, 4, -2, -3, -15, 4, 16, -9, -5, + 34, -29, 27, -54, 98, -65, 11, -18, 16, -13, 0, -2, 0, 22, -43, 31, + -46, 58, 2, -25, -2, 16, -2, -29, 17, 18, -26, 21, -17, 5, -4, -9, + 0, -34, 50, -27, -3, 4, 31, -3, -47, 32, -25, 36, 6, -47, 33, -28, + 39, -36, 42, -28, 5, -3, -2, 25, 27, -47, 20, 22, -5, -15, 1, -9, + 16, -25, -10, -43, 40, -12, -19, 22, -24, -5, 14, -44, 42, -32, 32, -45, + 40, 41, -17, 27, -44, 38, -16, 15, -36, 39, -13, -19, -4, 34, 1, -9, + 9, -16, -2, -29, 31, -31, -4, 35, -21, -52, 63, -41, 2, -7, 30, -35, + 13, 9, 15, -4, 14, -36, 18, -14, 55, -50, -6, 22, -23, -11, -5, 12, + 17, -13, -43, 44, -33, 41, -42, 45, 3, -12, 26, 11, -11, 35, -76, 39, + 2, 0, 3, -4, 15, -19, -6, -33, 11, 5, 16, -25, -2, 19, -7, -43, + 30, 20, -27, -18, 12, 14, 33, -50, 14, -15, 23, 8, 2, -10, -4, 53, + -86, 24, -9, 41, -34, -21, 22, 24, -54, 27, 13, 2, -9, 14, -29, 21, + 40, -43, -9, -3, 27, -3, -22, 18, 10, -23, -15, 1, 14, -12, 3, -30, + 30, -22, -28, 36, -15, 39, -57, 21, 3, -3, 33, -13, -2, 6, 20, -6, + 4, -13, -5, -18, 13, -7, 7, 26, -26, 16, 7, -64, 37, -7, 10, -20, + 12, -11, 7, -34, 37, -12, -24, 34, -18, -18, 39, 9, -42, -24, 43, 2, + -16, 25, 12, -16, 8, 12, -44, 32, -9, 23, 1, -37, 40, -23, -17, 18, + -42, 23, -12, -7, 10, -6, 6, -13, -13, 30, -23, 36, -4, 7, 17, -18, + 18, -3, 8, 5, -1, -13, -15, 2, -5, -16, 7, -52, 23, -38, 30, -30, + 16, -26, 21, -22, 24, 3, 20, -28, 22, 22, -31, 42, -16, -11, 32, -26, + 0, 31, -14, 11, -15, 14, -17, -9, 10, 11, 27, -38, -4, 14, -18, 36, + -44, 0, -11, 16, -14, -2, 16, -34, -23, 22, 4, -24, 14, -13, 16, 31, + -28, -10, -6, 51, -27, 13, -49, 3, 68, -38, 1, 8, -27, 26, -16, 0, + 15, -36, 7, -6, 38, -11, 0, -14, 10, -4, 22, -48, 31, -1, 23, -38, + 1, 15, -7, 10, -1, -3, 4, -1, 10, -2, -12, 3, -22, 5, 9, 8, + 4, -14, 12, -3, -7, 22, -20, 3, -6, 13, -15, -8, -7, 16, -14, -1, + -3, 6, -17, 12, 22, -44, 68, -67, 50, 13, -20, -11, -4, -20, -3, 22, + -13, -20, 28, -7, 2, 11, -9, -23, 5, 5, -26, 24, -31, 2, 20, 15, + 2, -7, 4, 19, -6, 41, -51, -3, 24, 27, -30, 25, -37, 1, -7, -2, + -4, -26, -1, 12, 5, -12, 9, -30, 5, 11, 26, -18, -32, 42, 7, 0, + -23, 10, 10, -20, 53, -49, 6, -39, 18, 3, -27, 41, -21, 16, 28, 14, + -24, -15, 19, 5, 16, -31, -1, 45, -25, -6, -16, -4, -19, 37, -47, 21, + 2, -14, -7, 30, -35, 13, -30, 14, 21, 11, -18, -28, 37, 12, -18, 9, + 5, -1, 33, -41, 3, -7, -19, 8, -14, 12, 15, -18, -4, 44, -25, 22, + -46, 19, 40, -25, -12, -5, 17, 7, -53, 25, 4, -10, 14, 16, -31, 40, + -27, -11, -4, 28, -40, -5, -9, -3, 34, -47, 33, -5, 11, -33, 33, 0, + -14, 35, -18, -27, 11, 14, -37, 35, -20, 7, 15, 2, 27, -17, 15, -31, + -1, 11, -27, 24, -26, 14, 13, -35, 20, -13, -2, 16, 16, -6, 2, 15, + -7, -22, 51, -36, -2, 20, -19, 23, -20, -19, -9, -14, 8, -4, -13, 35, + -66, 36, -37, 3, 19, -1, 15, 32, -45, 71, -15, -5, 12, 34, -33, 24, + -5, 20, -43, 42, -59, 13, -12, -69, 66, -29, -34, 17, 7, -28, 24, 5, + -27, 51, -40, -9, 46, 3, -17, 36, -56, 63, -7, -31, -19, 53, -12, -10, + 4, 19, -47, 35, 0, -40, 17, -14, 13, -11, 11, 3, -39, 22, 5, 21, + -19, -11, 25, -4, -5, 20, -13, 25, -6, -16, -16, 29, -61, 25, -33, 12, + -17, 7, -19, 34, -27, 15, -19, 32, -26, 54, -46, 6, 9, 14, -6, -6, + 23, -32, 58, -19, -5, 15, 46, -42, 39, -7, -23, -7, -14, -22, 42, -66, + 0, 4, -8, -11, -4, -3, -7, 7, -23, 30, -14, 19, 8, -9, 20, 36, + 5, -24, 25, 12, -20, 16, -53, 60, -49, -26, 24, -87, 67, -49, 13, -7, + 5, -14, 5, 11, 38, -3, -15, 27, 26, -36, 20, 30, -47, 29, -5, 9, + -10, 38, -65, 47, -49, -4, -10, -6, 1, -1, -28, 16, -14, 3, -14, 27, + -8, 1, 2, 23, 21, -53, 40, 24, -16, -12, -2, 11, 17, -8, -18, 8, + -25, 28, -10, -12, 13, -51, 10, 35, -10, -8, -9, 8, 10, 14, -20, 4, + -9, 37, -5, -2, 2, 4, -9, -5, 16, -16, -23, 13, 7, -9, 14, -49, + 13, 8, -3, -13, -9, 22, -8, 12, -13, 36, -36, 35, -17, 23, -12, 0, + -37, 50, -31, -8, -31, 43, -4, -11, 0, 3, -7, -19, 16, -16, -28, 46, + -28, 27, -13, 33, -21, -1, 39, -13, 3, -4, 4, -39, 74, -30, -17, 33, + -3, -20, -12, 24, -94, 75, -63, 54, -62, 23, 4, 12, -33, 22, -35, 16, + 12, -28, 34, 2, -12, -3, 22, 23, -31, -6, 26, 4, -41, 8, 37, -15, + 21, -7, 18, -51, 42, -27, 35, -45, 35, -30, 18, 9, -20, 1, 18, -12, + -51, 61, -61, 24, -20, 1, 11, -5, -2, -12, 11, 20, -35, -2, 37, -21, + 23, -15, -2, 19, -51, 82, -50, 20, 29, -26, -34, 49, -2, -16, 11, -17, + -4, 6, 15, -35, 13, -15, -10, -17, 15, 4, -42, 43, -31, 34, -30, 53, + -43, 40, -22, 9, 9, -24, 64, -41, 29, -17, 8, -15, 8, 2, -27, 7, + 10, -28, 0, 30, -50, 6, -13, -14, -21, 11, 9, 13, -47, 35, -11, 32, + 28, -28, 1, 32, 2, -19, 28, -24, 9, 0, 19, -6, 16, -33, 6, -23, + 33, -31, -1, -4, 26, -22, -22, -10, -11, 18, -26, 19, -8, -4, 21, -14, + 36, -2, 12, -48, 49, -1, -13, -5, 8, -3, 9, -4, -18, 15, 28, -50, + 10, 4, -7, 4, -39, 37, -39, 11, 2, -20, 13, 4, -6, 0, 35, -17, + -9, 6, 38, -21, -1, -1, 12, -2, -16, 15, 7, -22, 18, -23, 11, 3, + -9, -39, 29, -31, 44, -41, 0, 5, 21, -9, -25, 25, -6, 38, -55, 38, + -14, 6, -26, 38, -24, 39, -39, -15, 17, 16, -20, -27, 17, 24, -20, -20, + 33, 8, -31, 2, 2, 27, 11, -4, -7, 31, -20, -9, 4, -4, 17, -32, + 2, -18, 31, -35, 38, -52, 42, -1, -28, -26, 25, 3, -51, 42, -35, 35, + -39, 44, -38, 20, 20, -51, 34, 45, -10, -7, 27, -19, 33, -49, 22, 2, + -7, -5, -27, 59, -24, -20, 21, -8, -15, 24, -51, 3, 9, -23, 24, -30, + 2, 29, -26, -2, 4, 10, 0, -18, 50, 3, 9, -14, 17, -18, 24, -13, + -33, 7, 25, -50, 2, -2, 30, -58, 31, -8, 23, -11, -1, -24, 21, 1, + -41, 47, -30, 28, -39, 56, -16, -20, 51, -45, 33, 6, 23, -12, -19, -2, + 7, 1, -14, -5, -11, -20, 25, -17, 7, -22, 21, -19, 34, -47, -2, 1, + 33, -30, 14, 20, 6, -9, 17, 13, -22, 19, -58, 23, 26, -15, -52, 2, + 18, 10, -13, 46, -5, -8, -6, 4, -14, 5, 11, -13, -7, 42, -25, 8, + -37, 35, -10, 6, -25, 16, 15, -15, -9, -20, 18, -23, 26, -34, 35, -22, + -10, 9, 14, -6, -21, 27, -8, 4, 1, 3, -19, 28, 2, -7, 30, -8, + -13, 11, -9, -9, -19, 12, 0, -23, -1, -23, -6, 27, -31, 41, -28, 13, + 5, 9, -21, 6, 2, -2, 18, -16, 31, -25, 40, -38, 39, -13, 8, 14, + -3, 9, -30, 6, -12, -7, -15, 30, -64, 6, -22, 13, -8, 14, -40, 9, + 32, -35, 14, -1, 12, -25, 63, -25, 35, -2, 19, -5, -3, 20, -29, -1, + 35, -37, 53, -46, 4, -14, 22, -27, 23, -64, 8, 5, -25, 41, -18, 14, + -42, 53, -56, 35, -42, 71, -63, 45, -38, 29, -12, 33, -22, 0, 24, -13, + 3, 13, 1, -10, -19, 11, 19, -38, 5, -2, -18, -21, 33, -54, 41, 9, + 4, -1, -21, 3, 3, 37, -31, 34, -40, 34, -19, 30, -26, 23, -53, 55, + -8, -13, -16, 7, -13, 46, -38, 2, -3, 17, -1, -26, 18, -57, 68, -27, + 23, -19, 32, -39, 2, 2, -18, 12, -16, 4, -23, 38, -65, 40, -5, 13, + 19, -26, -13, 60, -25, 7, 1, 10, 22, -24, 23, -20, -16, -17, 14, -32, + 26, -4, 17, -15, 9, -29, 4, -29, 11, 36, -18, -19, -2, 5, 28, -23, + 31, 6, 4, 18, -14, 4, -7, 0, -45, 61, -31, 5, -15, -23, -21, 52, + -62, 4, 22, 1, -9, 15, -24, -27, 60, -49, 38, 0, -6, 1, 13, 7, + 4, 19, 6, 0, 27, -28, -14, -21, 17, -1, -30, 23, 10, -36, 18, -19, + 2, -18, 0, 6, -1, 7, -1, -37, 26, 15, -35, 41, -24, 10, 10, -9, + -12, 12, 7, 3, 10, -11, 11, -14, 27, -49, 71, -55, 25, 8, -11, 11, + -5, -22, 7, 15, -17, -11, 18, 4, -54, 43, -38, 27, -1, 7, -13, 19, + 10, -41, 50, -41, 13, 9, 10, -41, 38, -13, 13, -2, -2, -4, 9, -36, + -5, 22, -31, -18, 8, 21, -22, 21, -24, 12, 3, 16, -24, 25, -16, 22, + -35, 14, 3, 11, 12, -22, 40, -11, -25, 14, 0, 14, -2, 2, -10, -12, + 14, -51, 11, -21, 55, -27, 9, 3, 38, 7, -25, 5, -19, 6, -14, 0, + -10, 21, -57, 35, 18, -21, 21, -40, -13, 24, -24, -12, 10, -1, 11, 10, + -12, -5, 38, -45, 23, 26, -13, -9, 32, 6, -3, 30, -28, -28, 27, 3, + -10, -11, -10, 16, -28, 21, -12, -3, -1, -33, 14, -30, 12, -20, 40, -15, + 7, 19, -18, -1, -1, 9, 4, -23, 32, 17, -19, 12, 16, -45, 4, -6, + 18, -28, 36, -44, 44, -29, 10, 4, 14, -8, -13, 9, -30, 39, -17, -5, + 10, -10, 5, -1, -16, 17, -7, -9, -10, 15, -21, 9, 10, 8, -10, -6, + 3, -21, 34, -3, 6, -4, 15, 3, -2, 4, 26, -44, 30, -43, 2, 9, + -5, -7, -18, 16, -28, 0, 5, -7, 0, 7, 0, -7, 21, -14, 17, 15, + 2, -40, 7, 44, -30, 55, -33, -19, 40, -30, 17, -1, -20, -20, -20, 5, + 14, 1, -7, -32, 26, -11, -11, 24, -23, 17, 17, 8, -19, 18, 11, -6, + 17, -4, -13, 14, -9, 21, 9, -16, -8, 2, -16, 3, -9, -32, 6, -36, + -4, 0, 10, -36, 26, -11, 3, 31, -20, 1, 7, 4, 45, -35, 39, 0, + 4, 28, -21, 29, -39, 27, 15, -6, -14, 17, -25, -33, 16, -15, 18, -43, + 28, -61, 33, 1, -27, 13, -19, -20, 26, 11, -27, 16, -21, 33, -13, 43, + -44, 13, 24, -10, 35, -39, 36, 20, -39, 68, -68, 23, -16, -7, 0, 36, + -30, -13, -27, 42, -21, -4, -23, -2, 23, 0, -3, -3, 2, 4, -15, -5, + 28, -10, -20, 24, -7, 27, -58, 31, -7, -29, 39, -40, 41, -35, 8, -25, + 30, 31, -17, -9, 3, 36, -8, -18, -11, 29, -2, 6, -25, 21, -5, -8, + -17, -24, 20, -26, 20, -23, 46, -26, -13, 8, 13, 2, -15, 4, -9, 28, + -25, -19, 49, 18, -50, 45, -11, -17, 5, -61, 15, 4, -22, -1, 22, 23, + 33, -55, 46, -25, 37, 18, 2, -9, 11, -47, 23, -8, -25, 37, -32, 2, + 5, 12, -18, -5, 19, -27, -7, 20, -40, 32, -44, -21, -29, 58, 8, -9, + 57, -28, 29, -32, 14, -14, 4, 23, -33, 16, -4, -16, 21, 38, -37, 23, + 10, -32, 17, 17, -12, -59, 9, -3, -12, 22, -13, -8, -26, 16, 1, 33, + -9, -17, 16, -7, 21, -44, 26, 5, 35, -36, -1, 13, 36, -36, 39, -36, + 17, -13, 2, -33, 20, -13, -51, -2, 9, -2, 35, -21, 19, -20, 18, -19, + -5, 30, -39, 30, 22, -35, 74, -52, 33, -15, 17, -21, -13, 11, 6, -25, + 25, -31, 29, -18, 18, -52, 40, -11, -17, -26, 56, -56, 69, -53, -14, 32, + -10, -8, -2, 18, -14, 20, -18, 20, 22, -27, 0, -25, 56, -46, 16, -28, + 52, -5, -33, 76, -75, 36, -1, -42, 42, -46, 13, -13, 25, -7, 35, -55, + 5, 63, -56, 11, -24, 13, -8, -10, -27, 15, -15, 44, -66, 52, -3, -6, + 0, 23, -33, 79, -55, 30, -27, 37, -18, -6, -2, -19, 52, -22, -50, 60, + -32, 28, -56, 44, -28, 15, -37, -9, -28, 63, -75, 9, 39, 28, -21, 5, + -17, 15, 2, -13, 30, 13, -14, 10, -12, 30, -22, -10, 4, -8, -9, 14, + 6, -39, 34, -6, 4, 1, -5, 0, 33, -73, 34, -12, 23, -9, 53, -47, + 17, 3, -18, -6, 2, -19, -12, -7, -45, 72, -9, -71, 55, -58, 50, -18, + -36, 37, 19, -11, 13, -35, 32, 6, 5, 18, -6, 19, -26, 32, 16, 20, + -43, 20, -10, -7, 16, -7, -68, 21, -36, 7, 19, -22, 19, -3, -35, -37, + 25, 21, -57, 67, -9, 9, 32, -11, 28, -18, 35, -41, 60, -19, 29, 0, + -38, 29, -6, -35, 0, 25, -37, -1, -31, -42, 30, -19, -21, 36, -66, 53, + -33, 15, 16, -13, 20, -35, 73, -4, 18, 39, 4, 1, 3, 21, -2, -12, + -18, -51, 44, -17, -50, 48, -30, -16, -13, -35, -7, 25, -33, -14, 14, 0, + 8, -30, 45, -13, 50, -53, 28, 60, -33, 23, -7, -2, 15, 36, -11, 9, + 19, -44, 4, -21, 19, -5, -27, -45, 48, 9, -47, -23, 12, 3, -25, -8, + -21, 63, 1, -29, 31, -18, 19, 16, -24, -17, 50, -65, 65, -56, 93, -45, + -17, -25, 45, -18, 23, -53, 50, -15, -12, -39, 51, -11, 11, 13, -31, 54, + -14, -29, 22, -11, 10, -41, -19, 52, 10, -51, -60, 72, -13, 12, -38, 19, + -2, 31, -56, 37, -4, -10, 22, -14, -33, 48, -40, 38, -14, 27, -24, 19, + 29, 17, -31, -2, -41, 34, -17, 2, 5, 5, -13, -30, 14, 9, -9, 7, + -11, 15, 5, -28, -2, 0, 45, -30, -25, 1, 10, 29, -55, -24, 52, -5, + 5, 20, -25, 20, -15, 14, -64, 95, -53, 32, 13, -26, 31, -8, -27, 18, + 48, -57, -3, -10, 25, -24, -32, -9, 18, 18, -33, -15, 27, -22, 14, -5, + 10, 51, -21, -25, 19, 5, -15, -29, 16, 1, 33, -39, -12, 56, 14, -63, + 36, -2, -17, 52, -11, -37, 5, 19, -52, 38, -23, -60, 93, -75, 52, -30, + -2, -11, 49, -11, -25, 1, 42, -35, 26, -35, -9, 24, -1, 10, -6, -12, + 7, 4, 22, -10, 41, -25, -8, -4, -2, 28, -43, 19, -32, 4, -27, 9, + -47, 51, -16, 12, -52, 49, 8, 7, -37, 27, -33, 80, -44, 6, 5, 28, + -15, 16, 15, 2, -12, 50, -77, 38, -38, -45, 30, 8, -37, -13, -8, -18, + 50, 3, -54, 29, 29, -20, 4, 52, -57, 62, -52, -2, -9, 62, -64, -5, + 24, 23, 0, -7, -23, 48, 25, -78, -9, 38, 18, -46, 30, -51, 39, 4, + -48, 22, 15, 13, -39, 8, 10, 31, -20, -22, 21, -17, 17, -23, 22, 22, + -24, -36, 11, 31, -16, -28, 34, -4, 0, -20, 6, -2, 35, -13, -60, 36, + 24, -45, 21, -2, 36, 0, -73, 66, -37, 39, -66, -18, 22, 17, -17, -25, + 24, 36, -47, 3, 25, 7, 8, 0, 1, 14, 20, -21, 4, 21, 12, -77, + 17, -4, -12, 31, -57, 38, -11, -4, -31, -6, 29, -34, 11, 13, -20, 82, + -36, -36, 40, -28, 77, -68, 12, 2, 34, -23, 5, -31, 11, -5, 44, -105, + 79, -31, -29, -16, 37, 8, 18, -14, -9, 32, -10, -11, -7, 0, 41, 34, + -56, 7, 13, -2, -31, 33, -67, 42, -31, -2, 22, -49, 18, -34, -11, 38, + -40, 56, -16, 14, -2, 24, 0, 0, 41, -21, -8, 6, -11, 11, 11, -45, + 26, 4, -17, -7, -26, -30, 7, -21, -29, 56, -29, 37, -3, 2, -8, -3, + 22, 11, 40, -13, 58, -6, -38, 48, -23, 15, -52, -14, -6, 49, -66, -20, + -11, 34, -32, -44, 41, 4, 20, -59, -24, 77, 23, -24, -17, 42, 19, -3, + -19, -34, 54, 17, -22, -17, 46, -24, -9, 3, -22, 40, -47, -49, 72, 4, + -18, -48, -33, 55, -4, -41, -51, 105, -26, -3, -22, 64, 28, -51, 31, 2, + 15, 27, -62, 18, 21, 6, -15, -54, 52, -14, -46, 7, -30, 32, -1, 6, + -37, 39, -3, -23, -20, 24, 23, 17, -25, -6, 67, -36, -11, -37, 56, -79, + 3, 30, 45, -39, -17, -2, 21, 2, -4, -3, 3, 1, 16, -16, 9, 30, + -37, 8, -6, 46, -65, 3, 14, -59, 104, -60, 2, 46, -29, -30, -2, -10, + 24, -52, 63, -31, 81, -85, 18, 35, 16, -32, -18, -24, 45, -16, -15, -13, + 37, -15, -20, -42, 91, -45, -15, -9, -16, 64, -11, -23, 31, -18, 38, -42, + 3, 12, 1, 5, -5, 22, -44, 69, -31, -18, 15, 21, -64, -13, 34, -37, + 30, -26, -15, 6, -3, 44, -28, 11, -3, -1, 16, -18, 25, -14, -26, 69, + -56, -5, 31, -51, 24, 3, -36, 9, 52, -34, 31, 21, -11, -68, 31, -24, + 53, -25, -29, 31, 23, -20, 9, -15, -11, 19, 12, -47, 84, -60, -16, -11, + 17, -4, -15, 30, -45, 32, 34, -63, -7, 68, 0, -35, 17, 7, 33, -31, + -8, 7, -32, 43, -13, -18, 15, 31, -32, -34, 5, 8, -16, 20, -26, -29, + 32, -9, -20, 17, 33, -31, -13, -5, 86, -52, 23, -19, 2, 13, 14, -7, + -20, 36, -16, -3, 8, 0, 14, -69, 76, -77, 25, -14, -17, 3, 39, -14, + -46, 31, -2, -7, 37, -45, -6, 24, 28, -37, 22, 13, -35, 4, 8, 23, + 7, -43, 53, -59, 23, 16, 4, -25, -15, 23, -9, -20, 26, -18, -1, 25, + -3, -48, 53, 2, -43, 7, 14, -34, 15, 28, -33, 53, -2, -59, 31, -34, + 40, 19, -27, 20, -2, 8, 2, 3, -8, -8, 4, -57, 62, 24, -72, -4, + 17, -17, -3, -10, -26, 42, -30, 12, -29, 31, -10, 3, 24, 2, 21, -1, + -36, 52, -7, 21, 14, -32, -18, 73, -45, -6, 8, -12, -66, 21, 25, -17, + -6, -35, -14, 27, 26, -47, 40, -51, 56, -19, -24, 31, 6, 4, 11, -3, + 37, -47, 41, -32, 50, 0, -72, 25, 16, -19, -1, -2, -4, -41, 20, 6, + 9, -3, -44, 32, -54, 83, -30, -26, -8, 46, -47, 29, 5, -19, 37, -9, + -20, 65, -14, -21, -4, 10, 28, -28, 18, -29, 35, -25, 3, -17, -31, 4, + -4, 0, -9, 41, -42, -34, 40, -15, 8, -24, -8, 36, 22, -18, -27, 70, + -39, 39, 1, -5, 57, -54, 12, 36, 3, -13, -1, -32, 69, 6, -64, -50, + 13, -13, -34, 22, -13, 0, -10, -38, 41, -11, -22, -3, 11, 4, 38, 22, + -10, 24, 32, -23, 23, -6, 8, -4, 21, -61, 66, -35, -41, 7, 5, -29, + -19, -45, 23, -2, 46, -84, 78, -59, 40, -10, -18, 79, -35, -5, -1, 36, + 16, 13, -21, -31, 52, 2, -50, 34, -5, -36, -37, 65, -42, 1, 16, -42, + 35, -8, -50, -6, 41, -16, 27, -41, 22, 64, -50, -11, 31, -18, -17, 5, + -3, 34, 34, -40, -41, 66, -37, 20, -11, -20, 29, -5, -14, -15, 45, -33, + -37, -11, 36, -25, 18, -8, 20, 1, -23, 60, -32, 0, 34, -24, -32, 64, + -39, -35, 48, -7, -13, 4, -39, 32, 0, 1, -31, 2, -12, 43, -38, -8, + 26, 0, -57, 53, 19, -22, -10, 17, -30, 57, 6, -31, 33, 10, 0, -48, + 29, -4, -23, 6, -7, 31, -39, 15, -41, 38, -19, 5, -37, 23, 11, -28, + -14, 59, -48, 8, 22, -20, 50, 15, -34, -26, 67, -8, -15, -21, 53, -27, + -9, 13, -24, -35, -10, 9, -15, -13, 18, -38, 28, 22, -14, 2, -22, 42, + -20, 22, 12, -20, 45, -16, 17, -16, 22, 34, -27, -13, -7, 1, -21, -1, + 13, -44, 36, -51, -8, 16, -7, -30, -46, 90, -54, 35, 1, 11, 9, 5, + 1, -19, 20, 11, 21, -1, -49, 41, -6, 0, 37, -74, 9, 20, -12, -47, + 65, -68, 28, -5, -26, 15, 14, -3, -23, 8, 18, -22, 13, 3, 31, -21, + -5, 8, 24, -21, 48, -20, -21, 41, -43, 4, 18, 21, -60, 9, -27, 1, + 13, -15, -33, 15, 23, -48, -8, 53, -50, 1, 6, -40, 90, -10, -15, 51, + -52, 53, 29, -68, 50, 52, -30, -21, 7, -1, -8, -29, 11, -47, 6, 18, + -12, -25, 53, -34, -23, -6, 19, -7, -13, 7, 5, -2, 14, 11, -15, 51, + -29, 6, 12, 20, -27, 29, -12, 4, -18, -5, 2, -17, 10, -19, 2, -8, + -5, 56, -82, 49, 0, -42, 48, -25, 19, 6, -41, 17, 35, -18, -17, -29, + 26, 10, 4, -24, 26, -35, 47, -36, 2, 2, -23, 27, -42, 55, 0, -21, + 19, 21, -8, 1, -3, -15, 7, 12, -23, -29, 47, -12, 4, -28, 17, 16, + -7, -31, -8, 25, -6, 0, 13, -20, 6, 3, -7, 19, -21, -37, 27, 41, + 7, -14, 12, -59, 57, 6, -49, -2, -8, 0, 19, 13, -20, -5, 16, 23, + 4, -15, -33, 14, 2, 15, -26, -28, 10, 45, -17, -24, 14, 17, -39, 22, + -8, 48, -51, -1, -16, 52, -34, -21, 11, 13, 18, -57, 26, 15, 27, -36, + -12, 40, -7, -14, 15, -86, 91, -20, -13, -7, 53, -43, 33, -25, 13, 3, + -38, -19, 28, 28, -18, -74, 58, -3, 40, -27, -34, 30, 28, -1, -22, 2, + 9, -8, -12, 12, 21, -35, -2, -17, 17, 2, -27, 22, -36, 38, -11, 2, + -20, 7, 20, -29, 39, 11, -3, 9, -24, 47, -36, 28, -14, -16, 38, -37, + 12, -15, 18, -69, 56, -31, 17, -16, -18, -13, 21, -6, -9, -25, 37, 6, + -1, -2, 5, -1, -26, 39, 6, -3, -10, 0, 12, 30, -12, -31, 24, 13, + -14, 9, -23, 31, -43, -17, -2, 13, -23, -14, -21, 21, 19, -22, -12, 24, + 41, -26, 10, 12, 19, -3, 9, -12, 26, 12, -52, -4, 16, -3, 0, -43, + 7, 5, -14, -9, 12, -28, 15, -23, -2, 35, -12, -8, -10, 24, 57, -55, + 26, -18, 19, 44, -30, 0, -5, 50, -56, -1, 8, -5, -39, 9, 19, -39, + 38, -73, 30, -1, 2, 16, -24, 6, 29, -71, 70, -18, -6, 8, 31, 4, + -13, 23, -11, 31, -56, 57, -25, 10, 15, -44, -10, 16, -17, -44, 18, -28, + 10, 8, -21, -4, -9, 28, 20, -16, 17, -17, -6, 30, 0, 11, -21, 25, + 25, -1, 31, -56, 31, 14, -32, 2, -19, 4, -17, -26, -13, 42, -59, 15, + -29, 53, -4, 1, -23, 13, 31, 5, -22, 3, 30, -28, 2, -24, 37, 1, + -3, -18, 18, 41, -40, 3, -40, 48, -31, -5, -20, 5, 9, 0, -30, -1, + 26, -15, -5, -6, 51, -25, -27, 7, 44, -11, 10, -32, 14, 46, -31, 6, + -11, 37, -33, -14, 19, -4, 22, -50, 26, -45, 21, 1, -23, 10, -15, 17, + -63, 53, -14, -18, 56, -49, 21, 25, -7, 4, -21, 52, -33, 19, 3, 11, + -9, -7, 0, -49, 22, -17, 25, -10, -11, 5, -19, 35, -26, 20, -7, -21, + 37, -25, 29, -23, 3, 6, 17, -26, 27, 5, -16, 10, -9, -24, 11, -4, + -17, 9, -5, -13, 1, -2, 10, 5, -13, 21, 0, 8, 9, -22, 12, 13, + -24, -3, -22, 42, -18, 3, -4, -15, 1, -2, 8, -17, -13, -2, 1, 23, + 10, -2, -31, 23, 17, -15, -9, -24, 31, 2, 19, -24, 4, -22, 28, -5, + -20, 34, -57, 26, 71, -51, 28, -24, -12, 28, 10, -35, -4, -6, 7, -7, + 8, -52, 61, -52, 7, -9, -21, 9, 18, -19, 3, 34, -53, 56, -29, 20, + -11, 22, 4, -1, 23, 2, 1, 24, -15, 3, -32, 13, 21, -37, 6, -11, + -25, 22, 7, -2, -41, 4, 10, -30, 39, -24, -7, 8, 12, 9, -1, -35, + 13, 3, 9, -18, 21, 26, -14, 41, -8, -35, 31, -29, 17, -20, -12, 20, + -30, 27, -26, 21, -9, -6, 5, -14, 3, -11, 15, 2, 8, -14, -5, 20, + 4, 0, -31, 9, 4, 25, -24, 5, -5, -13, 27, -7, -32, 1, -5, -10, + 28, 7, -4, 11, 10, 22, -3, -22, -15, 6, -3, -3, -27, -25, 5, 8, + -10, -17, 18, -18, 12, 32, -18, 1, 25, -25, 50, 7, 2, 0, -3, -3, + 16, -20, 9, -14, -15, 21, -27, -3, -17, 23, -31, -4, -18, 31, -21, 6, + 0, 18, -16, 27, 3, -7, -17, 17, -15, -11, 19, -16, 6, 1, 12, -18, + 5, -6, 24, 0, -19, 22, -23, 43, -35, 18, 22, -40, 1, 12, -4, -18, + 26, -53, 34, 1, -10, 1, -18, 27, -25, -24, 33, -31, 9, -43, 53, -29, + 33, -17, 5, 23, -7, 2, 23, 29, 1, -8, 20, -10, -1, -22, -3, -17, + 4, 22, -61, -23, 31, -26, -29, -12, 2, -3, 12, 10, 26, 5, -29, 61, + -9, 32, -18, -14, 29, 31, 2, -19, 9, 31, -20, -31, -7, 5, -22, -47, + 31, -40, 15, -39, 22, -27, 40, -78, 31, 4, -19, 33, -13, -8, 41, -1, + 5, -12, 53, -51, 22, -1, 18, 28, -29, -1, 0, 0, 11, 13, -2, -7, + -5, -3, -3, 1, 2, -6, 0, 3, 8, 9, 5, 0, 14, -5, -28, -39, + -39, -36, -37, -27, -43, -49, -13, 4, 6, -7, 0, -1, 3, 23, 39, 29, + 35, 41, 21, 35, 0, 0, 21, 59, 67, 31, 21, 13, -3, 18, 34, 28, + 5, 3, 13, 3, 0, 12, -7, -33, -27, -39, -14, -34, -50, -30, -37, -35, + -53, -74, -70, -61, -62, -62, -50, -44, -61, -36, -3, -23, -15, -12, -17, -20, + -6, 11, -6, -12, -6, -17, 7, 46, 71, 87, 79, 70, 77, 104, 109, 66, + 37, 34, 27, 31, 40, 43, 31, 23, 17, 2, 10, 24, 32, 66, 56, 17, + -13, -55, -54, -21, 19, -19, -56, -77, -37, -27, -10, -6, -38, -36, -37, -3, + 23, 25, 25, 19, 35, 34, -7, -5, 28, 60, 66, 65, 51, 34, 22, 53, + 51, 15, 20, 11, 21, 21, 16, 24, -2, -23, -36, -35, -21, -29, -51, -51, + -47, -57, -85, -80, -70, -100, -97, -82, -78, -76, -64, -51, -56, -54, -49, -70, + -62, -53, -54, -60, -57, -65, -78, -76, -62, -39, 0, 31, 13, 6, 31, 54, + 55, 43, 30, 13, 9, 31, 23, 43, 28, 24, 36, 36, 24, 30, 54, 70, + 113, 103, 75, 4, -3, 40, 55, 50, 23, 9, 25, 29, 48, 41, 29, 14, + 6, 40, 63, 49, 39, 71, 80, 64, 21, 12, 17, 29, 68, 71, 52, 36, + 24, 37, 24, 1, 5, 3, -6, -4, 1, 13, -3, -22, -35, -31, -27, -58, + -59, -43, -55, -71, -76, -71, -88, -103, -95, -98, -85, -77, -68, -71, -58, -50, + -47, -52, -46, -40, -47, -44, -48, -56, -60, -91, -96, -68, -15, -6, -16, 9, + 3, 29, 31, 29, 8, 10, -6, 5, 10, -6, -4, -6, 15, 7, -2, 2, + -5, 30, 91, 107, 74, 8, -3, 14, 27, 32, 26, 17, 21, 18, 34, 49, + 20, -3, 2, 30, 42, 20, 36, 68, 79, 81, 52, 27, 22, 37, 80, 95, + 77, 77, 72, 74, 57, 55, 56, 41, 35, 22, 40, 58, 32, 23, 24, 26, + 0, -7, 6, -2, -16, -26, -31, -45, -46, -64, -77, -79, -73, -72, -75, -59, + -49, -56, -35, -48, -44, -50, -43, -59, -58, -40, -78, -119, -123, -95, -73, -40, + -52, -45, -29, -18, -3, -1, -11, -21, -28, -12, -24, -29, -21, -29, -16, -3, + -5, -30, -40, 1, 69, 96, 78, 31, 14, 23, 17, 19, 33, 20, 9, 9, + 45, 50, 14, 3, 12, 13, 16, 7, 14, 35, 54, 75, 56, 24, 1, 18, + 47, 47, 60, 62, 66, 69, 46, 54, 53, 38, 11, 18, 44, 41, 28, 33, + 37, 22, 14, 15, 13, 13, 1, -1, -13, -6, -11, -38, -33, -47, -40, -46, + -31, -29, -22, -9, -5, -9, 9, 4, -23, -14, -4, -3, -26, -69, -87, -74, + -60, -42, -49, -33, -28, -16, 9, 2, -16, -22, -25, -25, -33, -32, -44, -58, + -41, -11, -19, -51, -77, -43, 24, 47, 49, 34, 21, 5, -9, 5, 18, -10, + -14, 2, 23, 26, -3, -7, -4, 2, -3, -10, -4, -6, 38, 64, 50, 25, + 1, 11, 17, 21, 36, 58, 62, 46, 46, 61, 56, 27, 11, 20, 18, 27, + 15, 31, 26, 23, 17, 7, 16, 0, -9, -10, -3, -8, -14, -25, -36, -56, + -41, -39, -50, -30, -12, -23, -8, 10, 23, 17, -2, 3, 14, 26, 7, -33, + -48, -53, -52, -35, -30, -30, -23, 3, 21, 17, 8, 7, -8, -1, 0, -6, + -29, -50, -26, 10, 5, -38, -64, -41, 5, 22, 49, 63, 38, 20, 13, 26, + 15, -7, -9, -1, 28, 9, 1, -4, -12, -1, -5, -20, -38, -32, 6, 38, + 36, 16, 10, 0, -8, -13, 15, 41, 25, 30, 30, 52, 35, 17, 8, 3, + -5, -5, -6, 4, 7, 4, 4, 3, 3, -20, -25, -23, -28, -22, -18, -47, + -50, -54, -62, -67, -62, -48, -43, -44, -31, -10, 17, 10, -8, 1, 22, 24, + 17, -1, -21, -40, -39, -26, -38, -32, -21, 2, 17, 26, 29, 18, 5, 15, + 35, 19, -11, -37, -9, 33, 17, -6, -30, -23, -10, 22, 65, 73, 71, 47, + 57, 66, 38, 15, 16, 23, 34, 35, 27, 10, 11, 21, 32, -4, -26, -29, + 4, 29, 28, 38, 32, 17, -6, -6, 17, 32, 21, 31, 39, 49, 36, 27, + 25, 13, -1, -11, -8, -1, -15, -11, 4, -7, -9, -14, -38, -46, -35, -31, + -43, -53, -54, -72, -84, -88, -86, -79, -73, -86, -69, -40, -16, -23, -28, -13, + -9, 5, 5, -10, -34, -45, -48, -52, -61, -59, -42, -38, -9, 13, 19, 8, + -14, 18, 42, 28, -18, -31, -3, 11, 21, 13, -9, -17, -22, 9, 57, 71, + 62, 68, 83, 82, 65, 38, 38, 31, 52, 57, 45, 23, 25, 51, 56, 21, + -2, -8, 7, 21, 28, 55, 55, 37, 15, 17, 30, 30, 30, 48, 55, 65, + 55, 54, 61, 42, 24, 22, 13, 6, 6, 4, 4, 17, 19, 1, -20, -23, + -25, -27, -26, -44, -44, -62, -79, -91, -83, -76, -99, -104, -87, -63, -51, -40, + -42, -40, -29, -16, -6, -31, -40, -47, -63, -68, -81, -76, -81, -75, -49, -15, + -5, -34, -38, 2, 15, 8, -29, -43, -33, -18, -11, 8, -9, -42, -45, -14, + 25, 33, 41, 54, 67, 75, 71, 46, 30, 23, 52, 55, 38, 20, 25, 53, + 59, 35, 17, 6, 3, 5, 27, 64, 61, 49, 40, 40, 45, 36, 38, 63, + 69, 69, 77, 85, 78, 76, 63, 48, 38, 42, 28, 15, 30, 35, 41, 27, + 14, 0, -4, -2, -14, -16, -15, -35, -65, -63, -56, -64, -80, -94, -77, -71, + -46, -34, -42, -37, -21, -6, -5, -16, -20, -35, -44, -62, -66, -66, -96, -94, + -58, -26, -32, -44, -50, -14, 2, -9, -26, -41, -53, -49, -27, -5, -28, -59, + -65, -47, -20, -11, 7, 15, 28, 51, 57, 32, 7, 2, 30, 32, 15, 0, + 7, 30, 30, 24, 21, -2, -19, -20, 6, 37, 40, 31, 40, 45, 30, 29, + 35, 49, 52, 69, 74, 78, 89, 79, 72, 62, 60, 51, 37, 29, 29, 42, + 51, 46, 30, 32, 18, 2, 8, 13, 15, -13, -35, -35, -38, -40, -53, -71, + -70, -58, -34, -38, -32, -28, -9, 10, 10, 7, 11, -7, -28, -21, -26, -47, + -80, -84, -49, -18, -28, -38, -32, -8, -4, 4, 3, -23, -46, -44, -19, -5, + -22, -42, -55, -56, -35, -25, -12, -8, 11, 43, 51, 33, 1, 0, 24, 18, + 1, -5, 0, 1, 9, 15, 21, -2, -38, -36, -19, 2, 2, 19, 26, 19, + 20, 10, 11, 20, 31, 37, 49, 62, 64, 61, 60, 61, 50, 51, 32, 10, + 16, 27, 31, 33, 33, 36, 7, -6, 3, 14, 12, -10, -21, -40, -34, -33, + -47, -65, -67, -60, -40, -40, -44, -25, -10, -4, 14, 26, 22, 4, -7, 8, + 8, -22, -67, -65, -33, -19, -24, -20, -18, -8, 1, 26, 30, -2, -22, -25, + -6, 5, -1, -13, -38, -43, -31, -21, -16, -16, 9, 47, 61, 35, 22, 22, + 31, 24, 10, 13, 5, -2, 0, 28, 34, 1, -21, -30, -28, -18, -5, 5, + 18, 20, 14, 6, 6, 12, 9, 20, 33, 39, 51, 51, 42, 51, 51, 48, + 20, 9, 7, 5, 7, 15, 28, 19, -1, -16, -15, -4, 4, -16, -30, -41, + -45, -41, -50, -79, -77, -69, -65, -64, -56, -45, -40, -28, -4, 21, 17, -8, + -9, 21, 16, -18, -56, -58, -44, -39, -24, -22, -28, -22, -4, 29, 31, 13, + -9, -16, -3, 11, 13, 1, -18, -33, -15, -11, -23, -22, 11, 52, 58, 50, + 46, 50, 49, 36, 40, 40, 17, 6, 20, 37, 45, 29, 9, -7, -12, -11, + -6, 9, 30, 25, 26, 26, 17, 19, 15, 21, 24, 46, 55, 47, 43, 56, + 64, 52, 33, 25, 13, -3, 2, 10, 21, 26, 4, -15, -16, -13, -2, -11, + -32, -43, -37, -44, -61, -77, -78, -82, -82, -80, -71, -61, -72, -59, -21, 5, + -2, -27, -10, 15, 7, -14, -44, -59, -67, -55, -37, -38, -50, -45, -23, 5, + 23, 9, -6, -19, -15, 5, 14, 2, -22, -22, -10, -17, -35, -38, -3, 35, + 38, 43, 57, 51, 44, 49, 57, 46, 25, 14, 24, 35, 54, 41, 31, 22, + 1, -7, -4, 12, 23, 34, 37, 35, 35, 36, 26, 24, 33, 55, 62, 53, + 58, 70, 70, 73, 62, 51, 38, 14, 6, 20, 31, 32, 27, 4, -9, -1, + 9, -8, -21, -22, -27, -33, -53, -64, -67, -82, -86, -83, -67, -75, -97, -77, + -36, -15, -27, -32, -18, -1, -1, -6, -31, -62, -73, -68, -52, -52, -68, -69, + -50, -21, -2, 4, -10, -33, -29, -4, 2, -10, -29, -22, -8, -27, -55, -49, + -27, -6, 12, 31, 43, 31, 38, 44, 54, 48, 25, 11, 19, 30, 36, 41, + 41, 29, 11, -1, -9, 0, 15, 27, 34, 36, 46, 46, 26, 27, 39, 51, + 59, 62, 62, 73, 76, 77, 85, 78, 58, 35, 23, 21, 37, 53, 37, 22, + 15, 16, 20, 3, 0, -2, -2, -14, -33, -35, -45, -69, -77, -59, -53, -76, + -96, -74, -41, -30, -25, -26, -19, -4, 7, 11, -8, -40, -62, -62, -51, -55, + -69, -74, -71, -44, -15, -2, -14, -36, -38, -8, -7, -27, -33, -17, -12, -38, + -51, -57, -58, -41, -14, 8, 19, 15, 15, 31, 46, 40, 21, 9, 7, 10, + 20, 25, 33, 28, 16, 1, -18, -13, 0, 6, 12, 30, 39, 39, 26, 20, + 32, 41, 45, 53, 64, 63, 62, 80, 84, 87, 81, 51, 29, 21, 44, 52, + 41, 33, 29, 31, 27, 12, 8, 16, 10, -4, -7, -7, -29, -62, -57, -37, + -44, -68, -81, -70, -48, -33, -23, -22, -17, -5, 16, 31, 14, -15, -33, -42, + -41, -37, -53, -65, -74, -54, -16, 2, -12, -33, -19, -1, -10, -22, -17, -8, + -8, -18, -33, -48, -62, -57, -31, -1, 7, 0, 9, 22, 40, 40, 27, 14, + 4, 3, 10, 14, 21, 31, 20, 0, -13, -19, -17, -15, -7, 12, 29, 28, + 13, 20, 18, 18, 31, 38, 47, 49, 51, 56, 67, 87, 84, 56, 30, 20, + 31, 41, 31, 24, 32, 33, 20, 7, 14, 15, -2, -1, 13, 4, -28, -53, + -45, -34, -38, -59, -75, -72, -58, -44, -26, -26, -29, -8, 14, 34, 28, 10, + -9, -22, -26, -24, -30, -54, -78, -56, -13, -4, -17, -16, -5, 1, -6, -9, + -8, -1, 3, -2, -4, -28, -53, -58, -37, -10, 1, -1, 6, 20, 34, 46, + 40, 25, 19, 11, 7, 10, 23, 33, 28, 16, -3, -3, -17, -31, -14, 4, + 15, 20, 20, 16, 10, 14, 19, 23, 37, 45, 35, 37, 53, 76, 83, 62, + 34, 20, 27, 28, 13, 17, 29, 21, 7, 9, 13, -4, -17, -4, 13, 2, + -27, -53, -47, -39, -46, -56, -77, -87, -77, -58, -45, -46, -47, -33, -6, 17, + 22, 16, 1, -20, -25, -10, -21, -57, -79, -57, -32, -24, -23, -18, -3, -1, + -6, -4, -4, -5, 3, 13, 14, -6, -38, -51, -39, -22, -4, -1, 3, 14, + 32, 45, 46, 46, 33, 25, 15, 9, 28, 38, 32, 28, 26, 14, -9, -21, + -15, -5, 10, 24, 22, 22, 21, 15, 15, 23, 36, 42, 35, 31, 41, 72, + 87, 68, 46, 42, 34, 19, 14, 25, 25, 11, 14, 18, 14, -7, -24, -7, + 12, 4, -19, -41, -47, -44, -41, -52, -74, -92, -88, -72, -59, -63, -68, -53, + -34, -11, 12, 19, -7, -27, -15, -5, -22, -54, -76, -66, -52, -47, -41, -29, + -17, -12, -12, -10, -11, -19, -7, 12, 19, 3, -23, -42, -48, -31, -19, -14, + -6, 1, 20, 35, 39, 50, 51, 33, 16, 17, 30, 31, 32, 41, 39, 28, + 14, -7, -14, -5, 8, 18, 27, 34, 29, 22, 21, 26, 38, 51, 39, 27, + 43, 75, 84, 73, 75, 68, 46, 32, 31, 35, 27, 15, 23, 36, 26, 0, + -13, -4, 12, 14, 1, -23, -36, -36, -32, -36, -60, -83, -84, -70, -67, -70, + -66, -67, -62, -27, 8, 13, -11, -22, -7, 4, -16, -44, -63, -67, -63, -63, + -53, -42, -33, -25, -15, -10, -22, -27, -18, -1, 16, 9, -13, -32, -46, -42, + -31, -30, -24, -8, 5, 11, 25, 49, 50, 33, 25, 20, 21, 24, 29, 34, + 41, 41, 26, 5, -5, -7, -4, 12, 23, 33, 37, 29, 19, 24, 49, 53, + 33, 33, 49, 65, 73, 80, 89, 85, 63, 48, 50, 46, 30, 20, 35, 46, + 39, 17, 0, 2, 15, 23, 18, -2, -20, -24, -12, -19, -45, -60, -66, -70, + -66, -56, -61, -74, -74, -38, 0, 6, -8, -15, 3, 13, -1, -24, -42, -52, + -65, -64, -54, -54, -47, -31, -19, -12, -21, -32, -27, -12, 7, 13, -2, -24, + -36, -37, -44, -47, -32, -20, -18, -9, 12, 30, 38, 35, 26, 18, 17, 16, + 13, 25, 36, 37, 32, 18, 2, -11, -10, -5, 3, 28, 38, 20, 8, 25, + 42, 40, 28, 30, 40, 46, 54, 70, 87, 82, 66, 61, 59, 48, 28, 20, + 32, 43, 43, 24, 8, 1, 7, 23, 25, 3, -13, -9, -8, -15, -28, -40, + -58, -71, -60, -49, -58, -80, -82, -50, -17, -5, -13, -12, 6, 13, 8, -3, + -24, -42, -54, -59, -57, -60, -59, -43, -24, -15, -20, -30, -35, -25, 1, 11, + -2, -12, -18, -33, -48, -49, -41, -37, -32, -21, -8, 13, 27, 27, 27, 23, + 16, 8, 7, 15, 22, 32, 35, 22, 9, 0, -18, -26, -8, 20, 25, 11, + 4, 18, 32, 29, 22, 29, 30, 27, 38, 60, 75, 70, 68, 69, 67, 52, + 30, 19, 27, 36, 40, 34, 10, -2, 6, 21, 20, 4, -2, -4, -7, -9, + -12, -25, -52, -66, -53, -42, -53, -79, -86, -58, -33, -23, -16, -12, 0, 12, + 17, 13, -5, -24, -38, -44, -50, -59, -61, -51, -33, -15, -11, -28, -36, -23, + -4, 5, 5, 7, -3, -17, -31, -40, -38, -37, -36, -29, -14, 4, 15, 25, + 34, 30, 24, 19, 9, 8, 22, 33, 31, 30, 31, 16, -14, -26, -13, 14, + 17, 7, 8, 18, 24, 23, 28, 31, 23, 18, 30, 50, 62, 61, 63, 75, + 73, 59, 40, 23, 20, 30, 43, 35, 11, 0, 8, 15, 12, 6, 3, -6, + -10, -3, -1, -15, -46, -62, -47, -38, -54, -77, -84, -70, -53, -40, -30, -21, + -12, 1, 16, 20, 5, -12, -21, -33, -44, -52, -64, -64, -44, -17, -15, -27, + -30, -26, -15, -3, 6, 12, 9, -2, -17, -26, -29, -36, -41, -32, -21, -10, + 6, 18, 27, 34, 37, 25, 11, 14, 21, 26, 27, 37, 48, 33, -1, -19, + -8, 7, 8, 8, 16, 16, 17, 25, 34, 36, 23, 16, 28, 44, 53, 54, + 61, 74, 79, 75, 56, 30, 19, 31, 45, 35, 15, 9, 9, 9, 11, 9, + 5, -8, -14, 0, 9, -10, -40, -53, -44, -38, -51, -72, -84, -80, -69, -58, + -45, -38, -30, -13, 5, 13, 8, 0, -14, -25, -30, -46, -67, -72, -55, -34, + -26, -28, -31, -31, -26, -17, -4, 9, 11, 2, -4, -12, -22, -33, -38, -40, + -34, -18, -7, 2, 17, 33, 38, 29, 19, 20, 22, 17, 19, 38, 57, 43, + 15, 2, -1, 1, 3, 10, 18, 15, 14, 25, 38, 40, 27, 21, 28, 38, + 46, 50, 55, 66, 81, 90, 71, 40, 30, 37, 44, 39, 26, 18, 12, 8, + 14, 19, 8, -11, -13, 5, 15, -2, -28, -42, -36, -34, -45, -60, -76, -83, + -77, -65, -59, -55, -43, -28, -13, 5, 11, 2, -9, -11, -17, -37, -61, -71, + -65, -49, -38, -36, -34, -35, -36, -32, -16, -2, 1, 3, 0, -7, -13, -25, + -39, -46, -42, -30, -22, -15, 2, 21, 30, 24, 22, 28, 19, 5, 11, 33, + 50, 45, 31, 17, 6, -1, 0, 8, 16, 12, 11, 23, 37, 40, 33, 29, + 29, 33, 45, 48, 46, 58, 83, 97, 84, 59, 45, 46, 47, 46, 42, 31, + 16, 12, 23, 29, 16, -5, -9, 10, 21, 10, -12, -24, -25, -25, -29, -42, + -64, -73, -70, -66, -63, -58, -52, -42, -22, 0, 8, 4, 1, 3, -1, -19, + -44, -61, -63, -57, -50, -39, -33, -37, -39, -36, -27, -14, -4, 0, 0, 0, + -1, -13, -30, -42, -43, -37, -36, -30, -10, 8, 12, 15, 26, 31, 16, 1, + 4, 21, 37, 41, 38, 29, 13, 0, -1, 6, 8, 3, 7, 17, 26, 34, + 35, 27, 24, 32, 40, 37, 32, 45, 72, 89, 86, 70, 57, 48, 45, 49, + 50, 37, 16, 11, 25, 34, 20, -3, -7, 7, 18, 15, 2, -14, -20, -15, + -17, -32, -49, -61, -67, -65, -60, -61, -63, -54, -33, -12, -1, 1, 2, 10, + 12, -3, -26, -43, -57, -60, -54, -45, -38, -38, -39, -39, -35, -23, -13, -6, + -3, 2, 7, -2, -20, -30, -34, -42, -47, -38, -19, -9, -5, 7, 24, 31, + 19, 3, 0, 10, 23, 33, 40, 36, 18, 5, 4, 4, 0, 0, 0, 5, + 16, 29, 30, 22, 22, 31, 36, 27, 21, 32, 54, 74, 81, 77, 65, 49, + 44, 50, 55, 40, 16, 10, 24, 31, 20, 3, -6, -1, 11, 16, 5, -9, + -13, -12, -14, -22, -36, -53, -63, -62, -59, -63, -69, -67, -48, -25, -14, -10, + -1, 10, 16, 10, -6, -26, -45, -54, -55, -50, -42, -39, -39, -40, -39, -29, + -19, -15, -8, 4, 11, 3, -6, -11, -21, -38, -48, -40, -26, -21, -16, -3, + 18, 30, 24, 12, 6, 4, 11, 29, 41, 39, 28, 18, 11, 8, 5, 1, + -4, -2, 11, 25, 25, 19, 23, 33, 35, 25, 17, 23, 39, 57, 74, 81, + 72, 53, 47, 56, 60, 44, 23, 16, 22, 29, 25, 10, -4, -3, 7, 11, + 6, -3, -9, -11, -9, -12, -26, -42, -56, -59, -55, -61, -73, -75, -60, -42, + -32, -23, -12, 0, 12, 15, 7, -10, -30, -46, -53, -53, -46, -41, -43, -45, + -41, -32, -30, -26, -14, -1, 5, 2, 3, 3, -9, -30, -43, -40, -31, -31, + -28, -12, 8, 20, 25, 22, 9, 0, 6, 21, 34, 39, 35, 26, 18, 16, + 14, 4, -7, -5, 9, 21, 19, 16, 23, 35, 37, 28, 20, 20, 26, 43, + 67, 82, 74, 57, 54, 62, 63, 52, 33, 21, 23, 30, 28, 14, 1, -1, + 3, 8, 7, -1, -7, -9, -6, -5, -15, -34, -49, -51, -51, -60, -72, -76, + -70, -57, -46, -37, -25, -13, 3, 14, 14, 3, -15, -33, -48, -52, -47, -45, + -49, -49, -41, -37, -39, -35, -21, -10, -5, -2, 6, 12, 1, -19, -32, -34, + -36, -39, -34, -23, -9, 9, 23, 25, 14, 3, 2, 12, 25, 36, 37, 30, + 24, 25, 24, 10, -5, -4, 9, 18, 15, 14, 23, 34, 38, 36, 30, 19, + 15, 32, 61, 78, 75, 63, 60, 67, 71, 62, 42, 29, 30, 33, 32, 20, + 8, 4, 6, 8, 8, 3, -5, -9, -2, 3, -7, -25, -37, -42, -45, -54, + -66, -74, -74, -67, -58, -49, -40, -27, -9, 5, 13, 13, 0, -21, -39, -45, + -44, -49, -54, -50, -44, -44, -47, -42, -29, -21, -19, -11, 5, 12, 4, -8, + -18, -28, -36, -40, -40, -36, -24, -4, 14, 21, 17, 7, 0, 3, 17, 32, + 34, 29, 28, 34, 33, 17, 0, 0, 9, 13, 12, 14, 20, 27, 38, 46, + 39, 21, 11, 24, 51, 71, 74, 66, 64, 73, 78, 71, 54, 40, 38, 41, + 38, 28, 17, 11, 9, 12, 14, 7, -3, -5, 3, 9, 2, -12, -23, -28, + -35, -45, -55, -65, -71, -68, -62, -57, -50, -37, -22, -7, 10, 20, 12, -8, + -24, -32, -39, -48, -52, -49, -45, -49, -52, -44, -34, -33, -30, -18, -3, 5, + 5, 1, -8, -19, -29, -37, -43, -45, -37, -18, 0, 13, 18, 10, -1, -3, + 10, 24, 26, 23, 29, 38, 37, 21, 8, 5, 6, 8, 10, 12, 11, 16, + 34, 49, 46, 27, 10, 15, 38, 59, 67, 63, 63, 72, 81, 77, 61, 48, + 45, 45, 42, 35, 23, 13, 11, 17, 18, 9, -3, -5, 3, 10, 6, -3, + -12, -19, -24, -34, -46, -57, -64, -65, -66, -63, -56, -48, -39, -22, 1, 17, + 16, 3, -8, -17, -30, -44, -47, -44, -47, -53, -52, -44, -41, -41, -38, -28, + -14, -3, 3, 3, -2, -9, -17, -28, -42, -49, -46, -34, -17, 3, 14, 9, + -3, -6, 5, 15, 13, 15, 26, 36, 35, 25, 16, 8, 2, 4, 9, 6, + 1, 4, 22, 43, 48, 31, 11, 7, 24, 45, 55, 54, 55, 68, 79, 77, + 66, 54, 48, 47, 47, 41, 27, 14, 11, 18, 20, 10, -2, -6, 0, 7, + 8, 2, -6, -12, -14, -23, -38, -49, -55, -62, -66, -63, -60, -59, -53, -37, + -12, 8, 13, 10, 7, -4, -21, -35, -37, -39, -47, -53, -51, -45, -44, -44, + -42, -36, -24, -10, 0, 2, 1, 1, -3, -15, -30, -42, -49, -45, -30, -6, + 10, 7, -2, -3, 5, 9, 6, 11, 23, 32, 35, 33, 25, 14, 6, 9, + 12, 8, -2, -4, 13, 36, 48, 39, 18, 7, 17, 34, 43, 45, 50, 62, + 74, 78, 71, 59, 51, 49, 52, 48, 32, 16, 12, 19, 21, 13, 1, -6, + -5, 2, 6, 2, -4, -6, -9, -18, -29, -40, -51, -60, -65, -63, -63, -68, + -68, -53, -30, -12, 0, 10, 13, 3, -14, -25, -29, -35, -45, -52, -52, -49, + -47, -47, -47, -46, -35, -20, -10, -5, -1, 4, 4, -4, -15, -30, -47, -54, + -41, -15, 1, 0, -2, 2, 6, 4, 3, 7, 16, 26, 35, 38, 32, 20, + 12, 14, 18, 12, -1, -8, 3, 27, 46, 44, 26, 14, 17, 28, 35, 38, + 44, 55, 69, 78, 77, 66, 55, 54, 60, 58, 41, 24, 17, 19, 23, 20, + 7, -4, -4, 0, 2, 1, 0, -2, -4, -10, -17, -28, -42, -55, -59, -56, + -61, -72, -74, -63, -47, -32, -14, 5, 13, 7, -4, -12, -19, -28, -38, -46, + -51, -50, -46, -47, -51, -52, -43, -30, -20, -13, -5, 0, 4, 4, 2, -13, + -40, -55, -47, -25, -12, -8, -3, 3, 5, 4, 2, 3, 7, 18, 32, 41, + 36, 25, 18, 21, 25, 21, 5, -9, -3, 19, 41, 45, 34, 24, 23, 27, + 30, 33, 38, 47, 62, 78, 82, 72, 61, 61, 67, 66, 54, 37, 24, 23, + 28, 25, 15, 5, 0, 0, 0, 1, 2, 2, -1, -4, -5, -15, -34, -47, + -49, -49, -58, -69, -73, -70, -63, -51, -30, -8, 5, 7, 3, -4, -11, -20, + -29, -41, -49, -50, -46, -49, -54, -56, -50, -42, -33, -22, -13, -10, -6, 5, + 12, -1, -30, -50, -50, -38, -27, -18, -10, -3, 1, 2, 2, -2, -4, 6, + 24, 36, 36, 27, 19, 22, 30, 28, 10, -8, -10, 9, 30, 39, 35, 30, + 26, 26, 28, 29, 29, 35, 53, 73, 80, 74, 65, 63, 69, 72, 64, 47, + 33, 28, 29, 28, 21, 12, 6, 2, -2, 1, 4, 1, -2, 2, 6, -4, + -23, -35, -38, -42, -51, -60, -66, -70, -71, -63, -45, -23, -5, 4, 6, 3, + -2, -7, -18, -32, -42, -43, -43, -47, -52, -54, -53, -51, -42, -27, -20, -21, + -14, 4, 17, 10, -13, -35, -45, -44, -37, -26, -17, -11, -3, 3, 3, -3, + -9, -4, 13, 31, 35, 27, 19, 23, 34, 36, 19, -3, -10, 2, 19, 31, + 35, 33, 29, 30, 32, 28, 22, 26, 43, 63, 76, 75, 67, 65, 71, 75, + 70, 57, 43, 36, 34, 30, 26, 21, 14, 5, 1, 4, 3, -2, -2, 6, + 11, 3, -11, -22, -29, -36, -43, -50, -57, -67, -74, -72, -60, -40, -19, -5, + 2, 4, 6, 3, -8, -23, -32, -35, -40, -45, -47, -51, -57, -58, -47, -33, + -30, -32, -24, -5, 13, 14, 1, -18, -36, -45, -42, -35, -27, -20, -11, 0, + 3, -3, -12, -12, 1, 21, 31, 25, 16, 20, 34, 40, 26, 5, -7, -6, + 7, 21, 27, 26, 27, 31, 33, 27, 17, 15, 28, 50, 65, 68, 64, 62, + 68, 74, 72, 61, 51, 44, 35, 29, 28, 25, 15, 7, 5, 5, -1, -8, + -5, 3, 8, 4, -4, -12, -22, -32, -38, -42, -50, -61, -72, -77, -73, -57, + -36, -20, -11, -2, 7, 8, -3, -14, -22, -30, -38, -41, -42, -49, -60, -62, + -52, -41, -40, -41, -34, -18, 0, 11, 10, -3, -23, -38, -42, -40, -36, -31, + -20, -6, 2, -1, -13, -19, -9, 12, 25, 20, 12, 17, 30, 39, 34, 17, + -2, -8, 1, 13, 19, 21, 23, 31, 37, 32, 18, 10, 18, 36, 55, 62, + 60, 60, 67, 73, 72, 68, 61, 51, 41, 35, 34, 28, 18, 12, 11, 8, + -2, -9, -7, 0, 4, 5, 3, -3, -14, -24, -31, -36, -41, -50, -64, -77, + -80, -68, -51, -37, -26, -11, 3, 6, 2, -3, -13, -24, -32, -33, -34, -46, + -60, -62, -54, -47, -46, -47, -43, -31, -13, 4, 12, 6, -9, -23, -34, -39, + -40, -38, -29, -14, 0, 2, -11, -22, -15, 4, 17, 16, 11, 13, 25, 39, + 41, 28, 9, -3, 0, 9, 15, 15, 19, 30, 40, 39, 26, 12, 11, 28, + 45, 54, 56, 60, 66, 70, 73, 74, 69, 58, 49, 45, 42, 32, 22, 18, + 19, 14, 3, -6, -7, -4, 0, 5, 6, 3, -5, -14, -24, -30, -32, -38, + -53, -71, -78, -72, -63, -54, -39, -22, -8, 1, 6, 6, -4, -18, -25, -23, + -25, -39, -54, -58, -54, -49, -49, -50, -49, -42, -26, -7, 7, 9, 2, -9, + -20, -30, -38, -43, -39, -22, -2, 3, -9, -20, -16, -2, 11, 14, 10, 10, + 20, 36, 46, 40, 22, 8, 6, 11, 13, 12, 15, 26, 41, 46, 36, 20, + 14, 24, 38, 47, 54, 60, 64, 69, 76, 81, 76, 66, 60, 58, 53, 40, + 30, 27, 27, 22, 12, 3, -3, -4, -1, 4, 8, 8, 5, -4, -15, -21, + -21, -25, -41, -58, -69, -71, -70, -64, -51, -35, -23, -9, 5, 10, 1, -13, + -17, -15, -19, -32, -46, -54, -54, -51, -50, -52, -55, -53, -40, -22, -6, 3, + 4, -2, -10, -19, -32, -47, -49, -32, -11, -3, -10, -20, -20, -10, 2, 7, + 5, 2, 10, 28, 42, 41, 29, 16, 10, 11, 11, 7, 6, 17, 35, 45, + 39, 26, 18, 19, 26, 37, 47, 53, 56, 61, 73, 81, 76, 68, 65, 65, + 59, 46, 36, 31, 28, 25, 19, 9, -1, -6, -4, -1, 2, 8, 9, 0, + -10, -15, -14, -18, -32, -46, -57, -68, -74, -71, -61, -51, -41, -23, -2, 8, + 2, -8, -11, -10, -13, -23, -37, -48, -53, -51, -49, -53, -59, -60, -53, -37, + -19, -7, -3, -2, -1, -6, -22, -43, -52, -42, -21, -9, -12, -20, -23, -16, + -4, 3, -1, -6, 0, 18, 34, 40, 33, 22, 16, 16, 13, 5, 0, 9, + 27, 39, 40, 32, 24, 18, 19, 29, 40, 44, 46, 55, 69, 77, 75, 71, + 70, 70, 65, 55, 45, 37, 32, 30, 26, 17, 7, 0, -5, -6, -1, 8, + 11, 4, -5, -7, -7, -13, -21, -30, -44, -59, -69, -69, -65, -63, -56, -36, + -13, 1, 1, -4, -6, -5, -6, -12, -25, -40, -47, -47, -46, -50, -56, -62, + -61, -48, -30, -18, -12, -6, 4, 6, -7, -32, -49, -46, -30, -16, -12, -19, + -25, -20, -7, 0, -3, -9, -7, 8, 26, 36, 34, 27, 24, 24, 19, 7, + -2, 4, 18, 31, 38, 38, 30, 20, 18, 26, 34, 35, 38, 48, 62, 71, + 73, 72, 73, 72, 70, 64, 53, 43, 38, 35, 30, 23, 16, 7, -4, -10, + -4, 6, 8, 3, -1, -2, -4, -9, -12, -19, -33, -51, -61, -65, -69, -73, + -70, -52, -30, -13, -6, -5, -7, -5, -2, -5, -17, -31, -41, -45, -44, -45, + -53, -64, -67, -58, -43, -31, -26, -17, -1, 10, 3, -19, -41, -48, -39, -23, + -16, -21, -27, -24, -12, -3, -5, -13, -15, -3, 16, 28, 29, 26, 28, 31, + 24, 10, 0, 0, 8, 20, 33, 38, 32, 22, 19, 24, 28, 28, 30, 40, + 52, 61, 68, 71, 72, 73, 73, 69, 59, 51, 45, 39, 32, 28, 26, 15, + 0, -9, -5, 2, 4, 2, 1, -1, -4, -6, -5, -10, -24, -41, -50, -56, + -66, -76, -77, -66, -47, -27, -15, -11, -10, -5, 0, -1, -8, -20, -33, -40, + -40, -40, -48, -62, -70, -64, -51, -43, -39, -29, -11, 7, 10, -5, -28, -43, + -41, -28, -20, -22, -29, -28, -17, -6, -5, -14, -20, -12, 6, 19, 22, 23, + 30, 35, 31, 20, 8, 0, 1, 13, 29, 37, 33, 26, 25, 27, 27, 25, + 26, 33, 43, 54, 63, 67, 70, 74, 76, 72, 66, 61, 54, 44, 37, 36, + 34, 24, 8, -3, -4, -2, 0, 2, 3, -1, -5, -3, 2, -2, -16, -29, + -36, -44, -57, -70, -79, -76, -60, -41, -27, -19, -14, -8, -1, 3, 0, -10, + -24, -33, -33, -32, -40, -55, -65, -63, -56, -51, -48, -40, -23, -1, 12, 7, + -13, -32, -37, -29, -21, -21, -28, -29, -19, -6, -2, -12, -20, -14, 0, 11, + 16, 22, 30, 37, 38, 33, 21, 7, 0, 9, 26, 36, 35, 32, 32, 32, + 31, 28, 27, 30, 38, 50, 58, 63, 70, 78, 79, 76, 74, 72, 64, 53, + 46, 45, 44, 34, 20, 9, 3, -1, 1, 7, 7, 0, -4, 2, 8, 5, + -5, -15, -23, -30, -41, -58, -73, -77, -68, -53, -38, -28, -21, -14, -5, 4, + 7, -1, -15, -25, -25, -24, -32, -48, -59, -61, -59, -57, -57, -54, -39, -16, + 4, 8, -5, -24, -33, -30, -24, -24, -32, -35, -26, -11, -6, -14, -20, -19, + -10, -2, 5, 13, 21, 29, 37, 40, 30, 11, 0, 4, 17, 27, 30, 31, + 31, 32, 32, 29, 23, 23, 31, 40, 45, 52, 63, 72, 74, 73, 75, 75, + 67, 56, 51, 50, 46, 38, 29, 18, 6, -3, -1, 5, 3, -4, -7, -2, + 4, 5, -2, -11, -17, -21, -30, -47, -66, -78, -77, -66, -53, -42, -34, -27, + -16, -3, 6, 1, -12, -21, -21, -21, -28, -42, -54, -60, -60, -61, -65, -67, + -57, -35, -11, 1, -3, -18, -30, -30, -25, -27, -36, -41, -32, -19, -13, -17, + -22, -22, -19, -14, -6, 2, 7, 17, 31, 41, 34, 17, 3, 1, 8, 17, + 23, 25, 26, 30, 32, 28, 22, 21, 25, 30, 34, 42, 54, 63, 66, 70, + 77, 77, 69, 61, 57, 55, 49, 44, 39, 28, 11, 2, 2, 5, 3, -3, + -8, -4, 3, 6, 2, -4, -9, -11, -16, -31, -52, -68, -75, -71, -61, -50, + -43, -38, -26, -8, 5, 4, -6, -13, -14, -13, -19, -31, -44, -51, -52, -55, + -64, -71, -67, -49, -24, -4, -1, -12, -22, -21, -18, -22, -33, -39, -33, -22, + -16, -16, -17, -19, -20, -16, -9, -4, -2, 5, 18, 31, 37, 32, 21, 11, + 9, 12, 17, 20, 24, 28, 32, 31, 28, 26, 26, 26, 28, 34, 43, 51, + 57, 65, 74, 77, 75, 72, 68, 63, 59, 56, 53, 44, 31, 19, 12, 11, + 8, 3, -2, -3, 0, 4, 5, 2, 0, -1, -3, -11, -25, -42, -58, -66, + -65, -59, -54, -51, -42, -27, -11, -2, -3, -6, -7, -7, -9, -16, -27, -36, + -40, -44, -52, -63, -70, -66, -49, -28, -15, -13, -16, -16, -13, -16, -24, -31, + -33, -29, -24, -19, -17, -19, -20, -18, -14, -13, -12, -6, 7, 22, 33, 35, + 28, 18, 12, 12, 14, 17, 21, 27, 31, 31, 30, 30, 28, 25, 25, 30, + 36, 42, 49, 58, 67, 74, 76, 75, 71, 66, 62, 60, 59, 53, 41, 29, + 19, 14, 11, 7, 1, -3, -2, 1, 3, 3, 1, 0, 0, -3, -11, -26, + -44, -59, -65, -63, -60, -57, -52, -41, -25, -11, -4, -4, -6, -6, -6, -9, + -17, -27, -35, -39, -44, -53, -65, -71, -65, -47, -28, -16, -15, -16, -15, -14, + -17, -25, -32, -33, -29, -24, -19, -17, -19, -20, -18, -14, -13, -12, -6, -2, + 1, 6, 5, 21, 46, 42, 15, 0, 5, 34, 48, 29, -4, -31, -33, -17, + 26, 49, 32, 0, -21, -15, 14, 24, 24, 16, 0, 3, 11, 11, 11, 5, + 9, 9, 8, 11, 30, 27, 22, 7, -3, -3, 10, 2, -2, -4, -13, -4, + -4, -2, -2, -3, -7, -6, -14, -15, -14, -14, -13, -3, -14, -16, -18, -13, + -15, -16, -22, -20, -14, -3, -6, -4, -14, -11, -6, -10, -15, -15, -16, -9, + -10, -19, -3, -5, -17, -15, -18, -16, -14, -14, -12, -15, -7, -22, -19, -17, + -20, -11, -17, -14, -11, -8, -10, -13, -12, -11, -6, -6, -9, 1, 1, -3, + 0, 6, -2, -9, 7, -8, 8, 4, 3, 1, -6, -2, -2, 2, -5, -7, + -4, -7, -8, -9, -6, -6, 0, -8, -12, -12, -13, -8, -4, -7, -3, -11, + -6, -15, -7, -9, -9, -3, -10, -8, -9, -15, -10, -2, 2, -7, -16, -17, + -15, -13, -9, -6, -5, -7, -9, -15, -17, -12, -19, -12, -8, -8, -4, -6, + -3, 0, -4, -11, -13, -7, -6, -2, 4, 4, 8, 10, 4, 3, 3, 4, + 7, 12, 11, 14, 15, 20, 20, 18, 16, 17, 15, 14, 15, 22, 23, 28, + 34, 29, 28, 17, 22, 24, 23, 25, 28, 28, 30, 24, 19, 16, 13, 18, + 20, 15, 8, 2, 3, 0, 2, 0, -3, -2, -9, -20, -23, -25, -24, -23, + -27, -33, -38, -39, -44, -36, -42, -44, -48, -53, -54, -56, -52, -50, -40, -35, + -44, -43, -44, -39, -28, -24, -23, -22, -15, -9, 2, 11, 19, 28, 31, 31, + 32, 35, 43, 61, 70, 78, 81, 73, 78, 78, 78, 85, 82, 85, 88, 87, + 84, 83, 83, 79, 74, 62, 49, 45, 42, 43, 44, 38, 30, 18, 6, -5, + -15, -17, -15, -22, -28, -38, -46, -48, -50, -58, -59, -72, -80, -83, -89, -88, + -89, -87, -81, -84, -93, -105, -110, -109, -110, -102, -96, -82, -65, -62, -60, -60, + -60, -51, -43, -37, -28, -16, 1, 15, 28, 35, 41, 46, 53, 56, 60, 66, + 77, 91, 101, 102, 101, 99, 104, 103, 97, 91, 86, 90, 91, 86, 85, 79, + 75, 71, 59, 48, 39, 35, 33, 32, 28, 22, 15, 13, 7, 3, -7, -15, + -16, -18, -19, -23, -28, -29, -33, -37, -47, -52, -56, -63, -61, -70, -67, -70, + -72, -72, -80, -93, -91, -99, -103, -96, -108, -105, -109, -112, -94, -81, -73, -67, + -71, -77, -69, -63, -57, -38, -27, -15, 0, 4, 6, 19, 26, 41, 53, 49, + 56, 58, 69, 84, 91, 95, 101, 103, 98, 93, 85, 87, 102, 102, 103, 95, + 81, 78, 78, 71, 66, 60, 51, 50, 44, 39, 34, 34, 32, 27, 15, 0, + -6, -8, -3, -3, -11, -10, -18, -21, -26, -35, -39, -38, -44, -48, -53, -63, + -61, -61, -71, -63, -86, -89, -86, -107, -99, -109, -108, -109, -108, -121, -128, -105, + -102, -83, -67, -88, -82, -76, -78, -62, -47, -41, -19, -6, 1, 7, 13, 33, + 44, 64, 61, 59, 68, 73, 93, 98, 107, 114, 109, 123, 107, 100, 105, 100, + 111, 117, 100, 93, 92, 86, 85, 80, 70, 59, 58, 47, 38, 41, 33, 40, + 38, 25, 16, 1, -2, -3, -3, -4, -10, -16, -12, -21, -28, -28, -36, -38, + -39, -52, -61, -61, -67, -63, -65, -76, -77, -86, -95, -95, -107, -109, -112, -112, + -121, -121, -122, -105, -79, -80, -71, -80, -84, -73, -70, -56, -43, -28, -10, 6, + 11, 17, 31, 43, 63, 69, 69, 65, 77, 88, 101, 113, 112, 127, 122, 122, + 115, 104, 112, 116, 122, 117, 106, 99, 97, 96, 94, 86, 75, 70, 61, 53, + 44, 41, 46, 47, 45, 28, 19, 9, 5, 9, 1, -8, -14, -20, -24, -26, + -28, -29, -36, -39, -42, -45, -41, -42, -45, -46, -49, -47, -50, -55, -53, -61, + -63, -67, -83, -78, -89, -91, -88, -100, -93, -108, -110, -110, -115, -90, -100, -91, + -80, -91, -73, -62, -60, -41, -33, -36, -25, -16, -9, 8, 18, 35, 40, 57, + 61, 66, 95, 94, 106, 114, 105, 117, 111, 117, 118, 115, 120, 111, 109, 111, + 104, 102, 106, 93, 88, 76, 66, 63, 52, 53, 31, 27, 25, 5, 12, 1, + -5, 0, -15, -17, -23, -27, -27, -31, -31, -37, -44, -41, -43, -43, -35, -45, + -43, -41, -50, -49, -51, -57, -58, -62, -72, -76, -79, -81, -82, -86, -92, -94, + -100, -109, -110, -102, -99, -96, -83, -96, -83, -67, -73, -45, -41, -42, -27, -27, + -19, -5, 7, 14, 30, 44, 46, 57, 75, 84, 98, 108, 102, 112, 114, 110, + 120, 115, 116, 117, 108, 112, 107, 104, 108, 99, 96, 90, 73, 69, 66, 57, + 48, 36, 26, 18, 13, 6, -3, 3, -8, -14, -15, -26, -25, -26, -33, -33, + -40, -45, -45, -45, -42, -43, -44, -45, -48, -46, -55, -57, -58, -62, -67, -73, + -78, -80, -81, -82, -89, -93, -99, -106, -108, -115, -100, -95, -103, -77, -91, -85, + -59, -63, -48, -32, -36, -33, -18, -14, -6, 11, 21, 27, 47, 55, 56, 81, + 92, 96, 114, 106, 111, 116, 110, 121, 113, 115, 115, 105, 111, 106, 101, 103, + 100, 92, 84, 74, 66, 60, 58, 43, 29, 29, 13, 9, 10, -6, -2, -6, + -16, -18, -22, -27, -30, -30, -35, -44, -43, -46, -46, -42, -44, -48, -45, -46, + -50, -54, -51, -61, -63, -61, -85, -76, -80, -94, -75, -98, -97, -93, -111, -103, + -106, -97, -97, -90, -79, -93, -73, -64, -67, -39, -38, -41, -20, -20, -12, 11, + 10, 30, 40, 48, 62, 62, 85, 91, 99, 111, 101, 112, 111, 113, 120, 112, + 119, 111, 108, 114, 101, 102, 104, 89, 91, 79, 63, 67, 56, 52, 41, 29, + 26, 12, 14, 3, -5, 1, -14, -15, -19, -27, -24, -30, -31, -34, -43, -43, + -45, -48, -40, -48, -48, -45, -51, -49, -53, -56, -57, -63, -69, -76, -86, -80, + -86, -90, -87, -98, -101, -101, -108, -103, -88, -96, -88, -77, -89, -70, -60, -56, + -39, -34, -30, -26, -11, -4, 6, 26, 27, 42, 54, 57, 72, 86, 95, 105, + 107, 108, 112, 109, 116, 118, 112, 117, 108, 109, 107, 104, 103, 99, 97, 83, + 77, 71, 57, 60, 49, 35, 30, 21, 11, 11, 4, -2, -3, -13, -17, -22, + -24, -28, -29, -29, -39, -39, -44, -44, -41, -45, -44, -50, -49, -49, -56, -50, + -60, -62, -55, -82, -70, -82, -90, -80, -95, -95, -100, -105, -112, -112, -93, -102, + -91, -81, -91, -77, -60, -65, -45, -33, -40, -25, -21, -14, 5, 10, 30, 35, + 49, 61, 61, 87, 94, 102, 109, 109, 112, 112, 116, 117, 116, 118, 116, 106, + 113, 108, 101, 110, 96, 91, 84, 69, 66, 58, 54, 38, 29, 26, 12, 11, + 6, -2, -2, -8, -16, -20, -23, -27, -28, -33, -34, -44, -43, -43, -47, -39, + -44, -47, -43, -47, -49, -50, -52, -57, -58, -68, -75, -76, -83, -86, -86, -91, + -97, -98, -103, -109, -102, -91, -99, -84, -81, -93, -65, -66, -60, -37, -42, -33, + -25, -18, -9, 6, 16, 28, 41, 49, 57, 68, 84, 93, 102, 106, 106, 110, + 107, 116, 114, 111, 119, 106, 111, 108, 101, 104, 99, 94, 85, 76, 68, 61, + 56, 49, 34, 28, 21, 10, 10, 2, -3, -3, -13, -15, -24, -26, -28, -34, + -31, -42, -45, -43, -48, -44, -43, -47, -47, -47, -48, -51, -57, -57, -63, -70, + -72, -80, -86, -81, -92, -88, -96, -103, -100, -113, -110, -96, -101, -96, -79, -91, + -82, -59, -68, -47, -34, -39, -29, -18, -13, -5, 18, 22, 32, 54, 52, 64, + 83, 90, 100, 108, 109, 110, 113, 113, 116, 113, 117, 113, 106, 111, 103, 100, + 101, 98, 86, 82, 73, 59, 61, 53, 36, 34, 24, 12, 10, 5, -5, -3, + -8, -17, -18, -24, -27, -29, -30, -35, -40, -41, -45, -43, -43, -42, -45, -46, + -44, -50, -49, -55, -58, -55, -71, -70, -79, -87, -77, -92, -88, -95, -104, -100, + -115, -107, -91, -105, -85, -83, -97, -67, -68, -65, -37, -43, -33, -29, -21, -9, + 0, 18, 23, 35, 55, 48, 69, 87, 86, 108, 107, 103, 117, 106, 117, 118, + 113, 122, 109, 111, 111, 102, 110, 101, 98, 92, 77, 73, 62, 59, 54, 34, + 34, 21, 11, 15, 2, 2, 2, -14, -12, -23, -26, -26, -33, -30, -40, -44, + -42, -49, -41, -41, -44, -43, -46, -49, -51, -59, -54, -63, -67, -64, -84, -79, + -76, -91, -82, -87, -100, -100, -101, -118, -101, -89, -107, -81, -82, -93, -65, -57, + -57, -36, -26, -39, -17, -9, -13, 14, 21, 26, 45, 53, 54, 76, 88, 95, + 111, 106, 111, 114, 109, 120, 115, 115, 116, 110, 105, 109, 104, 98, 105, 94, + 83, 81, 68, 60, 62, 49, 32, 33, 18, 9, 12, 0, -3, -3, -13, -18, + -20, -24, -27, -26, -31, -37, -40, -42, -42, -43, -42, -44, -48, -48, -47, -51, + -54, -52, -56, -64, -68, -75, -84, -79, -89, -91, -93, -104, -105, -110, -114, -97, + -97, -96, -78, -89, -81, -58, -66, -47, -34, -40, -31, -23, -14, -6, 14, 22, + 31, 54, 55, 63, 87, 91, 103, 113, 105, 111, 113, 109, 119, 112, 117, 114, + 106, 113, 106, 105, 105, 99, 93, 81, 74, 61, 58, 55, 36, 30, 25, 10, + 11, 6, -5, 1, -8, -16, -19, -25, -27, -32, -32, -37, -44, -41, -47, -43, + -39, -43, -44, -45, -46, -46, -56, -53, -55, -72, -64, -74, -91, -72, -88, -97, + -80, -100, -105, -100, -111, -111, -88, -100, -99, -74, -97, -79, -54, -68, -43, -32, + -41, -26, -10, -16, 6, 22, 19, 41, 51, 49, 69, 86, 88, 103, 107, 100, + 119, 110, 111, 125, 110, 115, 115, 104, 108, 106, 99, 98, 98, 82, 76, 71, + 60, 60, 52, 34, 30, 25, 9, 11, 3, -6, 0, -15, -18, -21, -27, -27, + -30, -31, -38, -39, -43, -43, -39, -43, -44, -46, -47, -47, -54, -53, -59, -58, + -65, -71, -75, -81, -75, -90, -83, -90, -100, -95, -111, -109, -101, -97, -100, -84, + -86, -89, -62, -64, -50, -34, -37, -30, -21, -11, -8, 10, 19, 26, 47, 49, + 59, 76, 89, 99, 107, 109, 110, 115, 113, 119, 115, 114, 115, 106, 111, 103, + 103, 101, 98, 94, 81, 78, 65, 63, 59, 43, 34, 25, 17, 10, 7, -4, + -3, -6, -14, -16, -23, -24, -28, -29, -33, -41, -41, -46, -43, -40, -44, -44, + -46, -46, -47, -50, -54, -56, -58, -69, -70, -76, -83, -75, -87, -87, -91, -100, + -100, -109, -108, -97, -98, -93, -83, -88, -76, -61, -59, -43, -36, -33, -28, -18, + -11, -4, 14, 21, 31, 52, 51, 63, 84, 90, 101, 111, 104, 113, 113, 111, + 118, 112, 114, 109, 108, 109, 102, 106, 101, 98, 94, 79, 74, 66, 58, 55, + 39, 29, 24, 13, 11, 5, -4, 0, -10, -15, -17, -24, -25, -28, -29, -34, + -41, -41, -47, -42, -44, -46, -45, -50, -45, -50, -55, -48, -60, -60, -65, -76, + -77, -83, -84, -91, -92, -94, -106, -103, -109, -106, -89, -101, -82, -81, -88, -63, + -66, -54, -36, -40, -31, -25, -16, -7, 6, 17, 30, 41, 55, 56, 73, 89, + 92, 109, 104, 106, 114, 104, 117, 113, 110, 116, 105, 108, 106, 100, 102, 98, + 94, 85, 74, 67, 59, 55, 48, 31, 28, 19, 10, 12, 0, 2, -2, -11, + -11, -21, -21, -26, -30, -30, -40, -43, -43, -44, -40, -39, -41, -43, -42, -46, + -52, -52, -58, -63, -65, -75, -79, -83, -80, -89, -85, -88, -101, -94, -104, -114, + -93, -97, -104, -78, -92, -89, -60, -68, -48, -36, -36, -26, -21, -8, -5, 12, + 23, 26, 47, 50, 54, 77, 85, 96, 109, 102, 114, 112, 109, 125, 112, 114, + 118, 102, 110, 103, 99, 101, 96, 92, 79, 76, 66, 59, 61, 43, 32, 31, + 14, 10, 9, -5, -2, -9, -17, -18, -28, -25, -31, -31, -31, -42, -38, -43, + -41, -39, -43, -44, -47, -45, -48, -51, -53, -54, -61, -64, -67, -77, -76, -82, + -81, -89, -93, -97, -106, -108, -105, -96, -99, -88, -82, -92, -67, -64, -60, -38, + -38, -36, -24, -20, -16, 4, 11, 21, 36, 46, 53, 66, 85, 88, 103, 108, + 102, 115, 107, 112, 115, 109, 114, 104, 106, 106, 99, 102, 101, 92, 89, 81, + 67, 66, 58, 47, 39, 28, 21, 11, 12, 2, -2, 2, -12, -12, -17, -25, + -24, -29, -30, -36, -39, -41, -41, -41, -39, -41, -44, -44, -47, -51, -52, -54, + -59, -63, -65, -75, -79, -75, -90, -81, -89, -99, -92, -109, -109, -105, -99, -97, + -92, -80, -90, -71, -58, -60, -37, -32, -37, -19, -15, -14, 9, 14, 23, 42, + 46, 56, 67, 83, 96, 100, 111, 106, 111, 114, 111, 117, 111, 112, 109, 103, + 107, 100, 99, 103, 92, 88, 82, 65, 66, 59, 48, 39, 27, 22, 12, 9, + 5, -5, 0, -12, -16, -17, -26, -25, -26, -31, -34, -40, -41, -41, -41, -40, + -42, -47, -43, -46, -46, -52, -50, -52, -61, -59, -74, -75, -77, -83, -84, -91, + -92, -105, -100, -106, -109, -81, -103, -86, -73, -96, -64, -62, -59, -38, -39, -36, + -28, -15, -11, 3, 18, 25, 37, 53, 53, 67, 89, 85, 106, 103, 98, 115, + 99, 114, 115, 103, 116, 103, 104, 109, 98, 101, 98, 91, 84, 75, 67, 60, + 55, 50, 31, 28, 20, 7, 15, 0, -3, 2, -15, -12, -19, -25, -24, -32, + -32, -38, -44, -44, -45, -42, -41, -44, -43, -46, -44, -44, -58, -48, -63, -67, + -63, -87, -75, -83, -90, -81, -94, -95, -95, -107, -109, -99, -95, -99, -85, -85, + -90, -68, -62, -60, -36, -34, -39, -15, -13, -9, 14, 15, 29, 42, 50, 55, + 68, 87, 91, 101, 107, 106, 110, 113, 114, 115, 114, 112, 108, 105, 106, 98, + 98, 100, 88, 84, 75, 63, 63, 57, 46, 34, 28, 18, 10, 8, 0, -5, + -5, -15, -19, -20, -26, -26, -26, -31, -36, -40, -42, -43, -42, -39, -44, -44, + -42, -44, -47, -51, -52, -54, -65, -63, -76, -81, -68, -93, -84, -85, -104, -92, + -105, -109, -95, -95, -96, -84, -82, -84, -64, -64, -52, -39, -37, -33, -23, -11, + -9, 10, 20, 25, 49, 46, 60, 76, 82, 98, 101, 104, 110, 108, 108, 116, + 111, 111, 113, 104, 108, 106, 101, 98, 99, 92, 80, 79, 63, 61, 59, 41, + 35, 27, 18, 13, 9, 2, 0, -5, -12, -15, -20, -22, -26, -27, -30, -38, + -39, -42, -40, -39, -40, -40, -45, -43, -47, -49, -54, -53, -57, -70, -59, -80, + -77, -72, -93, -75, -91, -99, -93, -105, -108, -97, -92, -99, -80, -84, -84, -61, + -59, -49, -35, -28, -34, -14, -9, -10, 19, 17, 27, 47, 47, 61, 72, 87, + 95, 105, 104, 110, 111, 109, 117, 109, 111, 109, 103, 103, 102, 97, 95, 100, + 85, 81, 77, 61, 64, 55, 42, 34, 26, 17, 10, 9, -3, -2, -5, -13, + -15, -20, -23, -27, -27, -32, -37, -38, -41, -40, -41, -39, -43, -43, -40, -48, + -47, -49, -55, -61, -59, -70, -80, -69, -87, -83, -79, -97, -89, -98, -101, -107, + -96, -93, -101, -77, -90, -84, -62, -63, -49, -36, -34, -30, -15, -12, -2, 11, + 20, 32, 39, 53, 56, 71, 87, 89, 103, 101, 109, 109, 109, 118, 106, 114, + 111, 101, 107, 102, 93, 99, 94, 84, 85, 71, 65, 62, 54, 45, 32, 30, + 16, 12, 8, -5, -2, -9, -14, -16, -24, -22, -27, -29, -31, -38, -41, -38, + -44, -42, -41, -47, -45, -44, -48, -50, -50, -52, -62, -57, -69, -79, -69, -83, + -88, -78, -99, -97, -92, -109, -106, -91, -100, -93, -76, -91, -80, -60, -66, -48, + -37, -38, -32, -18, -15, -4, 11, 14, 31, 42, 48, 60, 69, 85, 94, 96, + 102, 107, 103, 109, 115, 104, 112, 109, 100, 106, 103, 95, 97, 96, 84, 82, + 73, 60, 62, 54, 41, 33, 27, 17, 14, 7, 0, 0, -8, -11, -16, -23, + -23, -29, -29, -32, -39, -40, -40, -40, -41, -40, -46, -48, -45, -50, -51, -54, + -56, -64, -63, -71, -78, -73, -84, -82, -87, -95, -93, -102, -102, -108, -95, -96, + -95, -76, -90, -77, -57, -61, -42, -33, -35, -26, -13, -14, 3, 15, 17, 36, + 45, 54, 60, 80, 89, 96, 108, 101, 111, 110, 109, 118, 107, 110, 109, 102, + 103, 103, 95, 97, 96, 83, 82, 70, 60, 61, 51, 38, 28, 23, 11, 8, + 4, -7, -3, -10, -16, -17, -22, -25, -27, -29, -35, -38, -43, -42, -41, -40, + -39, -43, -42, -44, -45, -46, -53, -51, -55, -68, -65, -75, -79, -77, -88, -83, + -94, -93, -101, -105, -96, -96, -92, -85, -85, -83, -71, -64, -57, -41, -41, -31, + -27, -17, -7, 2, 18, 23, 38, 48, 51, 68, 78, 91, 98, 102, 106, 108, + 110, 112, 115, 110, 115, 107, 107, 108, 99, 102, 97, 94, 87, 76, 70, 63, + 60, 49, 39, 30, 22, 16, 8, 4, 0, -4, -10, -14, -20, -24, -25, -31, + -30, -37, -41, -40, -41, -38, -39, -40, -42, -41, -43, -48, -44, -55, -58, -57, + -71, -71, -73, -78, -79, -80, -88, -89, -95, -99, -103, -101, -88, -98, -85, -79, + -90, -62, -60, -54, -35, -35, -27, -21, -9, -3, 7, 22, 26, 38, 52, 54, + 67, 87, 89, 101, 105, 103, 114, 107, 117, 112, 107, 116, 100, 105, 103, 94, + 98, 93, 87, 80, 73, 65, 59, 56, 45, 31, 28, 19, 6, 10, -3, -5, + -4, -17, -16, -22, -24, -25, -30, -28, -39, -37, -40, -44, -40, -44, -46, -46, + -47, -51, -50, -55, -55, -60, -67, -65, -81, -75, -78, -93, -78, -97, -101, -94, + -113, -104, -92, -96, -91, -79, -86, -79, -58, -58, -49, -34, -34, -33, -14, -12, + -5, 20, 19, 34, 49, 49, 66, 76, 91, 98, 98, 105, 104, 107, 111, 110, + 109, 108, 108, 103, 101, 102, 97, 95, 96, 80, 75, 71, 56, 58, 49, 33, + 28, 20, 13, 7, 4, -4, -7, -9, -18, -22, -22, -28, -30, -30, -38, -41, + -41, -43, -40, -41, -40, -44, -43, -45, -48, -49, -55, -55, -59, -67, -66, -82, + -70, -81, -86, -78, -101, -92, -98, -111, -98, -95, -95, -89, -76, -91, -70, -56, + -61, -38, -34, -33, -25, -12, -10, 1, 21, 15, 39, 47, 48, 68, 75, 90, + 97, 101, 103, 106, 106, 110, 111, 104, 111, 101, 99, 103, 96, 94, 95, 92, + 75, 79, 64, 55, 64, 43, 36, 30, 17, 13, 9, 3, -4, -3, -12, -16, + -18, -23, -25, -26, -29, -35, -38, -42, -40, -39, -41, -38, -48, -42, -45, -50, + -49, -52, -57, -63, -57, -78, -76, -67, -94, -75, -88, -100, -92, -103, -106, -97, + -88, -96, -81, -77, -85, -60, -55, -51, -35, -30, -33, -19, -9, -10, 17, 16, + 30, 46, 48, 64, 72, 86, 96, 101, 104, 105, 111, 104, 116, 109, 107, 110, + 104, 101, 104, 100, 93, 100, 86, 77, 78, 59, 60, 54, 40, 32, 23, 18, + 9, 9, 0, -5, -6, -14, -17, -20, -23, -25, -26, -31, -35, -39, -40, -36, + -40, -37, -40, -45, -42, -45, -48, -51, -50, -57, -64, -62, -76, -78, -71, -90, + -84, -88, -101, -97, -105, -108, -94, -97, -92, -81, -87, -76, -63, -58, -42, -36, + -33, -27, -15, -10, -2, 18, 19, 34, 49, 47, 66, 78, 86, 102, 104, 104, + 111, 109, 112, 115, 112, 110, 108, 106, 101, 102, 98, 96, 97, 86, 79, 72, + 62, 61, 51, 39, 32, 20, 15, 10, 2, 1, -4, -9, -13, -18, -22, -24, + -25, -29, -33, -37, -41, -39, -37, -39, -39, -43, -46, -46, -49, -49, -56, -54, + -57, -68, -66, -73, -77, -79, -83, -90, -96, -95, -107, -110, -98, -97, -98, -76, + -87, -83, -56, -68, -49, -34, -43, -28, -26, -18, -8, 3, 14, 22, 39, 47, + 54, 70, 83, 90, 101, 100, 104, 107, 102, 113, 103, 106, 109, 95, 106, 99, + 95, 101, 92, 93, 83, 74, 66, 60, 56, 44, 33, 26, 17, 12, 8, 1, + 2, -4, -11, -10, -21, -19, -25, -29, -28, -39, -38, -41, -41, -37, -40, -42, + -43, -42, -45, -47, -48, -56, -52, -59, -69, -67, -78, -78, -79, -88, -86, -95, + -100, -99, -112, -95, -92, -101, -77, -86, -86, -62, -65, -51, -39, -35, -31, -26, + -8, -11, 7, 26, 21, 45, 53, 50, 76, 86, 90, 105, 102, 105, 109, 108, + 115, 107, 112, 110, 100, 108, 100, 96, 100, 93, 89, 79, 72, 64, 58, 56, + 42, 31, 28, 14, 10, 9, -5, -2, -6, -14, -15, -22, -22, -27, -28, -31, + -41, -37, -41, -42, -37, -41, -45, -43, -45, -47, -48, -49, -58, -53, -64, -71, + -68, -82, -75, -83, -91, -87, -103, -97, -104, -111, -90, -98, -95, -77, -91, -76, + -61, -63, -43, -41, -35, -29, -23, -7, -7, 13, 22, 24, 50, 50, 59, 82, + 82, 99, 102, 100, 110, 105, 111, 113, 104, 114, 103, 104, 107, 96, 102, 97, + 92, 90, 77, 73, 64, 58, 53, 38, 31, 23, 13, 12, 3, 0, -2, -11, + -10, -17, -21, -20, -29, -27, -33, -40, -38, -44, -39, -39, -43, -41, -42, -42, + -46, -42, -53, -53, -52, -71, -67, -73, -83, -80, -81, -89, -93, -91, -100, -106, + -97, -96, -93, -88, -81, -85, -79, -59, -58, -48, -30, -36, -28, -11, -9, -2, + 21, 22, 32, 50, 52, 58, 79, 89, 90, 104, 104, 100, 113, 111, 109, 114, + 109, 107, 103, 104, 99, 94, 97, 91, 78, 79, 65, 58, 61, 47, 37, 30, + 23, 14, 10, 7, -7, -4, -8, -21, -17, -23, -30, -26, -30, -36, -37, -39, + -38, -38, -36, -38, -45, -41, -45, -49, -51, -56, -57, -63, -64, -69, -78, -70, + -80, -84, -84, -91, -100, -98, -106, -108, -90, -103, -90, -80, -93, -65, -64, -52, + -38, -37, -27, -26, -12, -6, 3, 18, 22, 36, 48, 54, 69, 84, 89, 105, + 103, 106, 117, 105, 117, 113, 106, 113, 101, 105, 101, 99, 98, 93, 94, 83, + 75, 70, 60, 55, 49, 33, 27, 19, 10, 8, -2, -2, -7, -13, -12, -22, + -20, -23, -28, -28, -35, -39, -40, -41, -40, -42, -40, -43, -42, -42, -44, -46, + -49, -52, -59, -60, -70, -74, -71, -84, -82, -88, -96, -98, -100, -105, -102, -88, + -95, -83, -79, -87, -62, -62, -52, -40, -39, -31, -27, -14, -10, 7, 17, 25, + 42, 49, 59, 72, 85, 92, 103, 103, 102, 111, 104, 113, 110, 104, 112, 102, + 107, 103, 101, 99, 97, 92, 81, 76, 64, 61, 54, 42, 33, 24, 17, 11, + 8, -2, -2, -5, -13, -12, -22, -23, -26, -31, -32, -38, -40, -43, -39, -40, + -41, -40, -44, -41, -44, -47, -51, -49, -62, -55, -68, -78, -68, -89, -79, -81, + -96, -85, -101, -100, -103, -98, -91, -97, -79, -83, -87, -61, -64, -55, -31, -41, + -29, -15, -19, 3, 9, 18, 33, 36, 56, 54, 71, 87, 87, 103, 103, 103, + 110, 107, 113, 112, 108, 111, 101, 104, 103, 92, 101, 92, 84, 84, 66, 65, + 59, 51, 45, 31, 27, 16, 10, 6, -3, -3, -9, -15, -16, -22, -24, -25, + -30, -28, -36, -40, -36, -42, -38, -41, -45, -44, -47, -47, -49, -51, -52, -54, + -62, -68, -73, -78, -81, -84, -83, -97, -94, -101, -113, -100, -99, -96, -87, -83, + -85, -75, -60, -60, -43, -36, -38, -27, -20, -15, 0, 14, 19, 33, 47, 49, + 67, 78, 90, 100, 103, 105, 107, 108, 110, 112, 109, 109, 107, 102, 105, 100, + 99, 98, 95, 84, 80, 69, 59, 60, 48, 36, 31, 18, 14, 9, 3, -2, + -5, -10, -15, -19, -24, -25, -28, -31, -34, -39, -41, -40, -38, -40, -38, -43, + -43, -42, -48, -47, -53, -54, -58, -67, -63, -79, -73, -78, -90, -80, -98, -97, + -101, -109, -105, -93, -98, -90, -76, -93, -66, -60, -59, -33, -42, -32, -26, -18, + -9, 0, 17, 21, 38, 48, 53, 69, 82, 93, 101, 107, 102, 112, 108, 111, + 115, 105, 112, 103, 105, 104, 96, 103, 95, 95, 85, 76, 68, 63, 59, 47, + 38, 26, 19, 13, 7, 1, -3, -4, -14, -12, -19, -23, -21, -29, -29, -35, + -40, -41, -42, -39, -43, -42, -46, -43, -47, -45, -48, -54, -47, -66, -61, -68, + -85, -66, -90, -84, -84, -103, -91, -106, -105, -96, -90, -92, -81, -79, -86, -59, + -59, -53, -34, -36, -33, -19, -10, -10, 17, 20, 26, 52, 48, 60, 75, 85, + 95, 102, 104, 102, 111, 107, 113, 110, 109, 111, 103, 107, 102, 97, 96, 95, + 85, 77, 73, 56, 60, 52, 37, 33, 22, 16, 11, 7, -3, -4, -6, -16, + -14, -21, -24, -24, -28, -32, -37, -38, -42, -36, -37, -39, -39, -43, -40, -42, + -48, -50, -50, -64, -57, -70, -84, -63, -90, -81, -77, -101, -85, -99, -105, -102, + -100, -92, -99, -79, -89, -86, -58, -65, -49, -29, -41, -26, -11, -19, 6, 12, + 14, 39, 37, 52, 60, 68, 90, 90, 104, 102, 106, 111, 108, 118, 109, 109, + 111, 98, 106, 101, 90, 101, 90, 82, 86, 63, 65, 63, 48, 47, 29, 25, + 16, 10, 6, -6, -3, -13, -18, -16, -26, -25, -25, -32, -30, -39, -43, -37, + -43, -39, -39, -48, -44, -46, -53, -50, -56, -59, -59, -67, -72, -77, -76, -84, + -83, -84, -100, -95, -103, -115, -98, -93, -103, -82, -82, -91, -60, -62, -54, -34, + -35, -31, -23, -13, -11, 7, 19, 21, 43, 48, 55, 73, 85, 94, 104, 102, + 109, 110, 105, 118, 107, 109, 113, 98, 106, 103, 96, 99, 98, 90, 82, 79, + 62, 62, 58, 41, 34, 26, 14, 10, 8, -3, -2, -5, -14, -13, -20, -20, + -24, -26, -28, -38, -39, -42, -42, -41, -41, -42, -48, -41, -43, -50, -41, -49, + -59, -50, -68, -74, -67, -82, -80, -89, -87, -101, -101, -93, -121, -85, -90, -105, + -65, -93, -82, -55, -69, -49, -38, -46, -32, -27, -19, -5, 3, 19, 26, 41, + 53, 52, 81, 81, 95, 104, 90, 113, 101, 105, 118, 99, 113, 109, 100, 109, + 104, 98, 104, 96, 89, 83, 71, 66, 57, 56, 38, 28, 29, 8, 17, 6, + -2, 3, -24, -13, -79, -103, -120, -116, -104, -87, -76, -63, 63, 82, 97, 108, + 119, 99, 70, 69, 80, 91, 92, 98, 115, 124, 127, 113, 82, 42, 4, -44, + -70, -82, -100, -87, -62, -58, -71, -65, -79, -60, -102, -113, -62, -44, -31, -31, + -22, -18, -3, 4, 11, 20, 28, 11, 15, 18, 27, 18, 7, 13, 26, 11, + -19, -69, -108, -84, -51, -21, -3, -6, -18, -17, -31, -33, -18, 2, 4, 26, + 47, 48, 77, 117, 127, 127, 127, 121, 110, 86, 72, 62, 46, 11, 17, -2, + -7, -13, -44, -60, -61, -61, -63, -72, -79, -99, -116, -127, -128, -128, -124, -81, + -51, -4, 5, -6, 7, 8, 9, 31, 31, 16, 34, 28, 34, 34, 46, 78, + 84, 93, 69, 47, 40, 64, 44, 27, 22, 0, -29, -8, 15, -6, -36, -66, + -68, -42, 0, 6, 1, 13, 24, 41, 64, 58, 50, 40, 4, 0, 3, -24, + -3, 21, 28, 26, 9, -30, -42, -61, -85, -92, -91, -96, -87, -74, -31, -20, + -38, -14, -44, -17, 18, -25, -9, 7, 1, 11, -2, -19, 12, 47, 76, 72, + 58, 68, 69, 82, 86, 76, 58, 9, -23, -12, -7, -22, -2, 0, -9, -2, + -15, -10, -3, -22, -17, -38, -44, -33, -24, -27, -16, 0, -15, 20, 19, 18, + 1, 10, 41, -1, -25, -25, -11, 30, 37, 9, 45, 37, -30, -30, 21, 5, + -26, -43, -56, -42, -48, -48, -29, -62, -76, -42, -23, -12, -14, 8, 45, 36, + 40, 25, 14, 11, 40, 46, 55, 65, 30, 17, 30, 36, 33, 18, 13, 16, + 15, 46, 37, 2, -1, -26, -36, -19, -21, -36, -62, -51, -48, -20, -2, 3, + -12, -12, -10, -35, -37, -49, -22, 14, 61, 40, 60, 75, 33, 41, 48, 38, + 29, -32, -45, -56, -64, -61, -30, -20, 30, 10, -46, -37, -35, -30, -24, -12, + -23, -34, -29, -22, -20, -14, 4, 44, 77, 49, 10, 8, 24, 20, 28, 31, + 27, 40, 35, 69, 39, 54, 38, 26, 22, 43, 36, 7, 14, 2, -25, -50, + -51, -56, -42, -55, -46, -36, -44, -36, -35, 1, 23, 11, -3, -34, -66, -33, + -12, -31, -27, -13, -1, 21, 31, 23, 0, -11, -3, -2, 9, 27, 5, -8, + -2, -17, -13, 10, 9, 3, 35, 32, 43, 24, 15, 2, -15, -9, -5, 2, + 5, 27, 25, 42, 76, 61, 17, 25, 14, -5, -17, -24, -6, 11, 23, 7, + -8, 5, -11, -23, -27, -48, -30, -12, -26, -36, -37, -39, -46, -61, -55, -23, + -20, -22, -14, -10, -16, -16, -22, -11, -3, -14, -34, -16, 9, 28, 25, 50, + 63, 52, 56, 46, 50, 54, 56, 45, 54, 29, 20, 21, 0, 0, 6, 16, + 28, 14, -1, -9, -10, -4, -9, -13, -7, -21, -27, -29, -40, -41, -35, -42, + -64, -11, 9, 2, -12, -24, -37, -40, -34, -29, -34, -12, -26, -20, -6, -4, + 5, 5, 27, 1, -17, 2, 21, 12, 8, 9, 15, 23, 24, 1, 5, 22, + 25, 28, 57, 55, 41, 33, 36, 27, 5, 1, 15, 34, 23, 4, 20, 18, + -1, -21, -22, -15, -17, -8, -6, -6, -12, -15, -26, 1, 29, -8, -40, -52, + -55, -19, -21, -36, -48, -56, -29, -15, -29, -39, -46, -35, -14, -11, -16, 1, + 27, 22, -10, -14, -7, -12, -12, 23, 55, 48, 65, 42, 20, 46, 45, 49, + 42, 38, 34, 25, 33, 21, 10, 38, 40, 26, 22, 37, 33, 12, 4, 7, + -14, -49, -41, -36, -53, -40, -35, -44, -31, -22, -19, -50, -78, -80, -78, -48, + -31, -18, -27, -28, -7, -17, -11, 5, 32, 39, 19, 14, 22, 34, 37, 23, + 20, 40, 40, 27, 14, 11, 7, 29, 34, 19, 32, 7, -15, -12, -24, -12, + 8, 6, 21, 34, 29, -6, -22, -15, 1, -1, 24, 27, 20, 36, 42, 45, + 27, -14, -50, -34, -14, -26, -25, -10, 10, -4, -28, -30, -34, -69, -91, -85, + -74, -51, -38, -24, -19, -9, -7, -30, -35, -30, -36, -12, 25, 32, 44, 50, + 45, 51, 68, 94, 90, 74, 60, 52, 64, 48, 30, 11, 11, 11, 2, 14, + 24, 16, 13, -7, -17, -9, -12, -20, -32, -45, -54, -58, -35, -23, -46, -51, + -33, -28, -29, -24, -36, -30, -24, -22, -20, -13, -9, -14, -7, 10, 26, 22, + 9, 9, 10, -2, -9, -15, -11, -1, 19, 27, 33, 28, 5, 3, 5, 6, + 10, 14, 24, 32, 36, 40, 41, 37, 19, 11, 3, -7, -10, -7, 6, 27, + 38, 28, 23, 16, 18, 15, -7, -33, -20, -13, -24, -25, -19, -15, -26, -52, + -56, -48, -41, -36, -30, -32, -30, -15, -38, -49, -47, -32, -17, -17, -11, -3, + 3, 8, 24, 28, 16, 6, 1, 7, 28, 41, 42, 69, 87, 78, 73, 62, + 30, 14, 9, 7, 15, 32, 20, 10, -8, -20, 2, 9, -2, 5, 12, -4, + -12, -19, -32, -37, -29, -24, -28, -39, -43, -40, -44, -28, -25, -33, -39, -37, + -34, -29, -28, -25, -19, -1, -5, -22, -12, 2, 6, 38, 46, 25, 30, 41, + 47, 37, 21, 7, -7, -8, 11, 39, 48, 43, 35, 27, 25, 22, -1, -22, + -11, 13, -4, -13, -3, -8, -7, -11, -17, -5, 5, 9, 8, 15, 25, 16, + 22, 20, 5, -16, -27, -29, -30, -9, 9, 9, 3, -14, -50, -56, -56, -79, + -92, -80, -57, -24, 12, 10, 11, 4, -22, -21, -13, -2, 4, 10, 15, 8, + 35, 72, 53, 44, 25, 25, 48, 56, 69, 53, 50, 75, 85, 71, 33, 12, + -16, -32, -25, -14, -5, -16, -23, -19, -22, -39, -41, -47, -45, -33, -35, -39, + -38, -35, -34, -29, -28, -28, -23, -10, -7, -9, -11, -18, -5, 13, 1, -13, + -8, -5, 6, 27, 46, 43, 25, 8, 11, 16, 18, 23, 30, 12, 5, 10, + 7, 5, -6, -4, -5, 1, 10, 9, 15, 21, 17, 10, -8, -16, 10, 33, + 34, 23, 13, 17, 17, 9, 11, 7, -4, -8, -8, -22, -27, -26, -19, -7, + -18, -16, -16, -47, -62, -55, -36, -16, -25, -33, -30, -34, -42, -49, -41, -43, + -31, -20, -3, 28, 48, 66, 64, 36, 20, 26, 21, 22, 39, 51, 45, 39, + 40, 53, 56, 39, 24, 16, 12, 16, 24, 27, 16, 13, 7, -18, -33, -50, + -47, -33, -24, -20, -26, -32, -31, -46, -53, -58, -56, -29, -13, -11, -2, 8, + -11, -24, -11, -9, -6, -2, -6, 1, 4, 5, 11, 6, 7, 16, 30, 28, + 19, 15, 7, 4, 11, 27, 22, 6, 9, 11, 3, 4, 17, 27, 18, 11, + 12, 5, 2, -2, -6, -7, -2, 10, 12, 9, 1, -2, 3, 4, 11, 21, + 30, 28, 6, -9, -18, -22, -22, -38, -41, -27, -18, -18, -27, -27, -23, -32, + -35, -32, -34, -30, -25, -24, -18, -9, -5, 5, -5, -26, -19, -11, -4, 11, + 37, 48, 46, 50, 53, 50, 45, 45, 37, 18, 24, 44, 38, 43, 47, 29, + 15, 11, 10, 12, 4, -8, -6, -4, -17, -27, -28, -36, -34, -37, -53, -53, + -46, -38, -38, -37, -28, -24, -23, -37, -42, -30, 0, 20, 18, 12, 14, 9, + 2, 6, 15, 13, 10, 14, 12, 2, 12, 29, 21, 1, 7, 21, 19, 14, + 15, 15, 4, -1, 5, -1, -4, 0, -2, 3, 6, 6, 13, 21, 15, 7, + 3, 5, 2, -3, 3, 3, 5, 8, 10, 16, 14, -1, -7, 2, 11, 12, + -10, -35, -42, -26, -21, -37, -44, -44, -47, -42, -27, -27, -23, -15, -16, -20, + -21, -14, -12, -9, -7, -6, 0, 13, 30, 32, 37, 38, 31, 24, 25, 43, + 54, 49, 46, 44, 40, 41, 30, 9, -1, 6, 22, 31, 22, 9, 0, -14, + -23, -29, -29, -28, -35, -39, -39, -39, -33, -25, -30, -44, -49, -45, -45, -35, + -19, 2, 16, 16, 9, 0, 0, 6, 2, -1, 11, 27, 40, 32, 16, -2, + -2, 1, 3, 1, 7, 12, 6, 8, 11, 5, -1, -2, -1, 1, 8, 10, + 5, 4, 14, 17, 6, -1, 0, 4, 4, 17, 23, 19, 25, 20, 5, -8, + -9, -2, -1, -6, -3, 13, 16, 1, -13, -19, -21, -26, -34, -37, -23, -13, + -13, -24, -40, -42, -40, -39, -29, -22, -21, -18, -12, -2, 18, 24, 10, 0, + -6, -4, 15, 33, 34, 34, 44, 41, 31, 33, 44, 43, 31, 22, 20, 17, + 16, 23, 22, 19, 21, 10, -5, -6, -9, -8, -2, -5, -16, -28, -36, -47, + -53, -39, -23, -21, -24, -32, -43, -39, -34, -24, -18, -14, -11, -12, -6, 10, + 29, 41, 40, 27, 14, 10, 4, 1, 3, 2, 9, 19, 21, 9, -10, -16, + -10, 8, 18, 20, 13, -3, -8, -4, -1, 2, 5, 5, -1, 3, 9, 12, + 16, 16, 14, 9, 3, 5, 10, 4, -6, 1, 6, 5, 13, 20, 11, 1, + -7, -21, -30, -25, -12, -9, -13, -19, -24, -29, -34, -30, -32, -39, -33, -24, + -20, -22, -24, -13, 3, 6, 2, 1, 3, 5, 16, 30, 35, 35, 24, 16, + 15, 19, 31, 37, 33, 28, 29, 29, 30, 26, 20, 15, 13, 10, 10, 12, + 9, 7, -3, -21, -39, -44, -43, -42, -34, -26, -23, -18, -12, -18, -32, -36, + -31, -27, -20, -10, -7, -9, -11, -5, 2, 12, 19, 19, 25, 24, 11, 3, + 15, 29, 30, 20, 9, 1, -1, 1, 5, 2, -3, -2, 0, -6, -18, -27, + -20, -3, 8, 13, 15, 11, 7, 10, 18, 16, 10, 6, 3, -1, 1, 11, + 19, 19, 15, 14, 5, -2, -2, -7, -12, -15, -20, -16, -10, -5, 2, 1, + -13, -29, -33, -24, -10, -6, -13, -18, -23, -31, -32, -26, -22, -18, -13, -3, + 2, 3, 7, 8, 10, 19, 27, 32, 33, 33, 35, 38, 43, 41, 29, 9, + -4, -9, 2, 16, 17, 13, 15, 17, 13, 10, 5, -1, -8, -18, -29, -32, + -27, -21, -22, -30, -31, -31, -33, -31, -27, -18, -7, -6, -15, -16, -8, -1, + 4, 12, 18, 22, 20, 16, 11, 10, 14, 18, 16, 15, 14, 9, 6, 4, + 3, 3, 0, -5, -13, -18, -15, -13, -9, -7, -8, -5, -2, -5, -1, 5, + 8, 10, 11, 12, 17, 19, 16, 10, 4, 4, 8, 8, 8, 13, 14, 9, + 3, 0, -1, 0, 0, -7, -19, -24, -20, -15, -12, -15, -21, -23, -24, -26, + -28, -29, -28, -21, -10, -1, 5, 6, -3, -12, -14, -11, -1, 12, 16, 17, + 28, 36, 28, 20, 25, 27, 24, 25, 28, 21, 15, 11, 3, 4, 12, 11, + 0, -7, -5, -1, -1, -5, -8, -11, -17, -23, -22, -19, -21, -20, -20, -22, + -24, -22, -17, -20, -24, -20, -10, 2, 10, 13, 14, 14, 11, 8, 8, 12, + 17, 18, 20, 20, 14, 4, -1, -2, -1, 3, 11, 12, 6, 0, -9, -20, + -25, -18, -9, -8, -13, -18, -19, -14, -6, 0, 4, 11, 19, 22, 20, 19, + 15, 13, 14, 18, 17, 12, 7, 9, 14, 9, -1, -4, -1, -5, -10, -12, + -16, -23, -19, -7, -5, -10, -10, -11, -19, -27, -24, -14, -6, -3, -10, -21, + -24, -15, -6, 0, 9, 15, 12, 8, 6, 9, 9, 11, 20, 26, 31, 35, + 30, 21, 16, 16, 13, 6, 2, 4, 5, 3, -2, -10, -13, -11, -8, -9, + -13, -16, -18, -18, -19, -22, -18, -8, -3, -1, 0, -5, -11, -10, -9, -11, + -9, -2, 2, 4, 10, 15, 18, 19, 21, 21, 22, 22, 15, 4, -4, -8, + -7, -6, -10, -14, -18, -23, -20, -15, -8, -1, 0, -4, -7, -9, -9, -6, + -2, 2, 6, 7, 4, 1, 0, 7, 13, 11, 14, 22, 22, 15, 8, 2, + 4, 10, 16, 17, 13, 10, 9, 6, -3, -13, -23, -26, -21, -17, -14, -12, + -13, -16, -14, -9, -8, -8, -11, -18, -18, -12, -4, 0, 2, 6, 6, -1, + -6, 0, 8, 11, 13, 11, 6, 6, 9, 13, 16, 16, 15, 10, 7, 10, + 10, 4, 0, -2, -3, -1, 2, 2, -1, -5, -13, -21, -27, -30, -26, -16, + -4, 5, 8, 6, 2, -3, -5, -1, 4, 8, 9, 11, 11, 6, 0, 0, + 7, 12, 13, 11, 7, 1, -4, -3, 0, 5, 6, 5, -2, -10, -13, -13, + -10, -5, -4, -9, -18, -28, -31, -24, -14, -10, -4, 2, 5, 4, 2, 4, + 13, 20, 21, 19, 14, 11, 11, 12, 13, 14, 15, 17, 18, 18, 14, 5, + -3, -5, -8, -11, -11, -12, -15, -15, -13, -13, -15, -13, -12, -15, -16, -11, + -7, -6, -4, -1, 4, 6, -1, -10, -11, -7, -4, -1, 4, 9, 11, 12, + 9, 7, 8, 8, 7, 9, 13, 15, 12, 4, 1, 1, -2, -9, -10, -7, + -1, 3, 3, -1, -9, -12, -9, -5, 1, 3, -2, -10, -10, -7, -4, 2, + 8, 6, 4, 6, 5, -1, -1, 7, 17, 20, 17, 16, 19, 16, 7, -3, + -8, -9, -9, -11, -15, -24, -27, -20, -15, -12, -11, -7, -3, -4, -6, -7, + -6, -8, -14, -18, -18, -15, -10, -5, 3, 12, 18, 20, 17, 11, 10, 16, + 21, 22, 23, 23, 22, 17, 9, 0, -3, 2, 10, 15, 16, 11, 2, -9, + -19, -23, -22, -15, -10, -8, -11, -13, -15, -17, -19, -18, -15, -10, -3, 1, + -2, -6, -3, 0, -3, -3, 0, 6, 10, 9, 7, 4, -1, -4, 0, 10, + 17, 16, 11, 5, 0, -1, 2, 5, 1, -6, -10, -10, -8, -6, -4, -2, + -4, -7, -9, -9, -6, 2, 12, 17, 16, 11, 8, 7, 6, 5, 7, 9, + 12, 14, 14, 9, 3, -1, -3, -5, -4, 0, 4, -1, -10, -18, -24, -29, + -28, -20, -14, -13, -12, -8, -5, -5, -9, -13, -14, -11, -10, -9, -4, 1, + 3, 2, 3, 8, 16, 20, 18, 13, 10, 14, 24, 29, 29, 27, 23, 17, + 14, 16, 17, 15, 9, -1, -7, -10, -14, -18, -16, -11, -8, -7, -8, -12, + -18, -26, -29, -26, -19, -11, -5, -3, -3, -2, 0, 2, 0, -3, -3, -2, + -3, -4, -2, -1, 3, 7, 9, 8, 7, 3, 1, 4, 5, 2, 3, 5, + 5, 0, -7, -9, -6, -1, 5, 9, 8, 3, -2, -6, -5, 3, 9, 12, + 11, 8, 4, 3, 4, 6, 11, 13, 8, 1, 0, 4, 9, 13, 12, 5, + 2, 3, 3, 0, -6, -16, -26, -30, -28, -26, -22, -18, -17, -19, -22, -24, + -19, -12, -7, -2, 1, 0, -2, -4, -5, -2, 4, 10, 14, 15, 15, 16, + 16, 17, 19, 22, 26, 25, 19, 13, 10, 7, 9, 11, 10, 7, 4, 1, + -5, -8, -8, -4, 0, 1, -4, -11, -16, -17, -16, -14, -12, -10, -11, -14, + -15, -16, -13, -9, -3, 1, 2, 1, 0, 0, -3, -9, -13, -10, -8, -7, + -4, 0, 3, 6, 9, 9, 5, 3, 3, 5, 8, 12, 12, 6, -1, -2, + 2, 8, 8, 4, -2, -5, -1, 4, 10, 13, 14, 13, 13, 14, 14, 12, + 10, 8, 8, 8, 6, 6, 9, 6, -1, -9, -15, -19, -22, -24, -23, -25, + -25, -23, -20, -19, -19, -21, -20, -20, -21, -19, -11, -2, 2, 1, 0, 3, + 9, 13, 15, 16, 14, 10, 5, 3, 8, 14, 16, 18, 20, 22, 24, 21, + 15, 9, 6, 8, 14, 18, 15, 9, 4, 1, 0, -2, -4, -4, -3, -3, + -4, -7, -11, -13, -12, -11, -15, -19, -22, -25, -25, -21, -14, -11, -15, -19, + -18, -14, -7, -1, 4, 2, -3, -6, -4, 0, 5, 10, 16, 17, 12, 7, + 2, -1, -3, 0, 3, 6, 10, 14, 12, 6, 2, 5, 10, 15, 18, 18, + 16, 14, 11, 6, 4, 3, 1, 1, 2, 6, 9, 9, 3, -2, -3, -4, + -6, -8, -10, -15, -19, -20, -19, -18, -17, -15, -16, -17, -18, -20, -22, -21, + -16, -11, -4, 1, 0, -4, -4, -1, 1, 2, 4, 4, 3, 3, 4, 7, + 11, 16, 21, 20, 15, 11, 9, 12, 16, 21, 24, 23, 21, 17, 13, 11, + 9, 4, 0, 0, 1, 3, 4, 0, -4, -7, -7, -9, -13, -17, -20, -22, + -23, -21, -16, -12, -12, -15, -17, -17, -15, -12, -10, -10, -11, -12, -15, -15, + -10, -4, 0, -1, -1, 1, 4, 7, 13, 19, 22, 23, 21, 19, 18, 17, + 11, 5, 2, 5, 10, 13, 15, 15, 14, 13, 10, 5, 1, 0, 2, 5, + 8, 10, 9, 6, 4, 2, -1, -5, -7, -8, -7, -8, -11, -13, -14, -16, + -19, -21, -22, -22, -24, -23, -20, -17, -16, -16, -15, -16, -16, -15, -13, -11, + -9, -5, 0, 6, 12, 15, 18, 18, 17, 17, 19, 20, 19, 19, 20, 23, + 25, 25, 23, 20, 17, 13, 11, 9, 9, 8, 6, 3, 1, -2, -5, -5, + -2, -1, -3, -7, -6, -3, 0, -2, -9, -21, -29, -32, -32, -30, -27, -27, + -29, -30, -28, -24, -23, -21, -16, -7, 0, 1, 2, 2, 4, 7, 10, 14, + 16, 14, 12, 13, 15, 18, 20, 22, 23, 20, 15, 8, 3, 2, 7, 13, + 15, 13, 7, 2, 0, 0, -1, -2, -1, 1, 2, 1, 0, 2, 3, 4, + 4, 6, 7, 5, 0, -10, -21, -30, -36, -36, -33, -28, -23, -18, -15, -14, + -17, -19, -19, -17, -12, -5, -2, -2, -3, -1, 2, 6, 10, 12, 14, 13, + 12, 13, 18, 25, 29, 28, 24, 19, 14, 10, 6, 6, 9, 12, 13, 15, + 17, 18, 18, 14, 7, 0, -1, 1, 1, -2, -6, -8, -10, -11, -13, -17, + -19, -18, -17, -16, -14, -14, -15, -17, -19, -22, -26, -26, -24, -20, -17, -14, + -13, -12, -10, -7, -4, 1, 5, 7, 9, 10, 13, 15, 17, 18, 21, 24, + 22, 21, 19, 17, 15, 13, 14, 14, 16, 17, 18, 16, 12, 10, 8, 6, + 5, 3, 0, -3, -6, -7, -5, -4, -4, -5, -5, -4, -4, -4, -8, -13, + -19, -24, -27, -28, -27, -25, -25, -27, -27, -25, -19, -14, -8, -3, 1, 6, + 9, 8, 3, -3, -6, -4, -1, 4, 9, 14, 18, 20, 22, 22, 23, 23, + 22, 21, 20, 20, 21, 21, 19, 15, 9, 3, -2, -4, -3, 0, 2, 2, + 2, 3, 3, 1, -4, -10, -15, -19, -19, -16, -11, -7, -7, -9, -13, -17, + -23, -28, -30, -29, -24, -20, -18, -19, -20, -19, -18, -19, -18, -13, -5, 1, + 6, 9, 11, 13, 16, 21, 26, 29, 30, 29, 29, 28, 26, 23, 20, 20, + 21, 21, 20, 18, 15, 9, 2, -4, -6, -5, -3, -3, -4, -6, -7, -9, + -10, -10, -10, -10, -11, -13, -12, -11, -8, -6, -6, -10, -17, -26, -32, -35, + -35, -34, -32, -27, -19, -9, -3, -1, -2, -5, -7, -6, -1, 7, 14, 18, + 21, 23, 25, 26, 26, 23, 20, 20, 23, 24, 24, 21, 19, 14, 8, 2, + -1, 0, 1, 2, 3, 6, 8, 8, 5, 2, -2, -5, -5, -4, -1, 1, + 1, -1, -6, -9, -11, -13, -17, -20, -24, -26, -27, -26, -23, -21, -20, -23, + -26, -27, -26, -24, -20, -15, -9, -2, 4, 8, 10, 13, 16, 19, 21, 23, + 25, 28, 33, 36, 38, 38, 35, 32, 29, 24, 16, 11, 6, 2, -2, -6, + -6, -5, -4, -4, -7, -11, -14, -13, -10, -8, -8, -8, -9, -11, -12, -12, + -11, -11, -12, -14, -17, -19, -19, -18, -18, -20, -22, -23, -21, -18, -14, -11, + -8, -4, -1, 5, 11, 13, 11, 8, 6, 7, 9, 11, 13, 15, 19, 22, + 23, 25, 27, 27, 22, 17, 11, 6, 4, 5, 9, 13, 15, 15, 11, 6, + 0, -4, -7, -8, -6, -3, -2, -3, -6, -9, -13, -18, -22, -23, -20, -15, + -11, -10, -11, -14, -19, -24, -27, -28, -28, -27, -26, -23, -19, -15, -10, -6, + -1, 4, 8, 10, 11, 11, 13, 15, 17, 20, 23, 24, 24, 26, 28, 28, + 28, 27, 26, 24, 22, 20, 16, 13, 10, 8, 6, 3, -3, -9, -15, -17, + -16, -15, -13, -13, -14, -17, -19, -20, -20, -17, -14, -12, -13, -14, -13, -13, + -14, -15, -14, -13, -12, -12, -12, -10, -8, -7, -8, -9, -9, -7, -4, 0, + 3, 6, 8, 10, 12, 14, 18, 22, 25, 26, 27, 28, 28, 27, 24, 20, + 16, 13, 11, 9, 6, 3, 0, -3, -3, -2, 1, 3, 5, 3, 0, -4, + -8, -12, -17, -21, -22, -20, -17, -15, -14, -14, -13, -15, -19, -22, -21, -18, + -14, -13, -15, -16, -17, -17, -19, -19, -16, -11, -4, 1, 6, 10, 13, 17, + 20, 23, 24, 24, 24, 25, 28, 33, 37, 38, 35, 30, 24, 20, 16, 13, + 9, 2, -4, -8, -8, -8, -7, -7, -9, -12, -16, -18, -18, -16, -15, -16, + -16, -16, -13, -10, -10, -11, -13, -15, -15, -15, -15, -16, -17, -16, -14, -13, + -13, -13, -13, -12, -9, -5, -2, 1, 3, 6, 12, 18, 22, 22, 21, 18, + 16, 16, 19, 23, 29, 32, 30, 24, 18, 13, 9, 6, 3, 0, -2, -4, + -6, -8, -10, -11, -10, -6, -3, -2, -3, -5, -5, -6, -6, -7, -6, -5, + -4, -5, -8, -10, -11, -12, -14, -16, -18, -20, -21, -21, -22, -23, -24, -24, + -22, -18, -11, -4, 1, 4, 5, 6, 8, 11, 15, 20, 24, 26, 27, 28, + 31, 32, 31, 30, 28, 27, 24, 20, 17, 14, 12, 9, 3, -3, -9, -12, + -15, -16, -17, -15, -13, -10, -10, -11, -13, -14, -15, -17, -19, -21, -23, -24, + -22, -18, -13, -9, -8, -8, -8, -9, -9, -9, -7, -4, 0, 2, 3, 5, + 5, 3, 3, 4, 5, 6, 7, 10, 14, 17, 20, 20, 20, 21, 22, 20, + 18, 16, 15, 14, 12, 9, 7, 6, 4, 2, -2, -5, -7, -9, -9, -8, + -5, -2, 0, 0, -1, -3, -7, -12, -16, -16, -15, -13, -12, -13, -13, -12, + -11, -11, -12, -15, -19, -23, -24, -22, -19, -16, -13, -10, -5, -1, 3, 6, + 7, 8, 8, 10, 13, 17, 21, 25, 27, 28, 28, 26, 24, 24, 25, 27, + 28, 29, 28, 25, 19, 12, 4, -3, -10, -15, -19, -22, -24, -25, -26, -25, + -23, -21, -20, -18, -17, -16, -14, -12, -11, -12, -14, -14, -13, -13, -15, -16, + -16, -16, -15, -11, -4, 0, -2, 0, 0, 3, 14, 34, 24, -3, -14, -12, + 6, 6, -11, -23, -5, 15, 20, 15, -19, -12, 3, 19, 11, -5, 1, 4, + 7, -13, -3, 5, -13, 0, -2, 8, 0, -6, 16, 23, 13, 6, 2, 14, + 25, 2, 11, 3, -7, -8, -24, -6, -4, -18, 6, 30, 14, 9, 0, 0, + 13, -7, 0, -3, 9, 8, -6, -14, -15, -23, -19, -7, 0, -3, 1, -8, + -10, -10, -17, -12, -7, -10, 1, -12, -13, 0, -15, -20, -25, -16, -6, -7, + -6, -6, -2, -4, -13, -12, -6, -6, -5, 2, 8, -5, -13, -3, -4, -11, + -16, -3, 12, -2, -8, -4, -4, 4, -15, -17, -6, -2, 5, -4, 3, -2, + -10, -4, -5, -7, -8, 4, 17, 1, -3, -14, -4, -2, -7, -4, -6, 10, + 5, -6, -7, -8, 10, -5, -3, 3, -8, 11, 7, -5, -3, -13, -7, 0, + -6, 4, 0, -7, 12, -9, -17, -7, 5, 2, -3, -4, -7, 7, -2, -13, + -5, -2, 5, 4, 0, 7, -3, 4, 1, -2, -4, 6, 8, 8, 0, -2, + 2, 3, 2, 1, -2, 5, 12, 6, 3, 2, -3, 2, 3, 1, 8, 6, + 7, 2, -5, -3, 1, 5, 2, 0, -3, 2, 7, 2, 0, -9, 0, 5, + 1, 3, 1, 4, 6, -5, -3, -2, 2, 6, 4, 6, 1, 2, 4, 4, + -2, 2, 5, 5, 7, 7, 2, 6, 0, 3, 0, -3, 8, 4, 4, 9, + -3, 2, 1, 1, 2, 1, 5, 5, 4, 6, 1, -6, -2, 3, 5, 6, + 4, 3, 4, 1, 2, -4, 0, 6, 2, 2, 4, 3, 5, -3, -2, -5, + -3, 5, 2, 1, 3, 1, -2, -3, -4, -6, 3, 5, 1, -2, 1, 2, + -2, -2, -2, -3, 3, 5, 3, 4, 2, 2, 1, 0, 1, 4, 9, 9, + 5, 2, 1, 6, 4, 4, 5, 5, 7, 8, 4, 5, 1, 2, 3, 1, + 1, 4, 2, 3, 0, -4, -7, -5, 0, -3, -3, -3, -5, 0, -8, -7, + -8, -5, -3, -6, -3, -4, -5, 0, -7, -4, -5, -3, 1, 1, -2, 1, + -2, 2, 0, 0, -2, 3, 5, 4, 5, 4, 2, 4, 2, 4, 5, 6, + 5, 6, 4, 4, 4, 4, 3, 4, 2, 4, 4, 2, -2, -2, 0, -3, + -3, -3, -4, -2, -7, -6, -7, -9, -7, -10, -9, -10, -10, -8, -11, -9, + -9, -12, -10, -13, -12, -7, -8, -6, -6, -9, -6, -5, -3, 0, 0, 1, + 1, 4, 3, 4, 8, 6, 8, 7, 6, 10, 9, 12, 12, 11, 12, 8, + 13, 10, 11, 10, 8, 9, 8, 6, 9, 4, 5, 0, -3, -5, -5, -6, + -7, -9, -12, -15, -17, -21, -18, -22, -21, -23, -25, -24, -27, -27, -26, -30, + -27, -27, -28, -20, -22, -19, -14, -15, -12, -10, -10, -2, 3, 4, 12, 12, + 14, 20, 17, 25, 27, 29, 33, 35, 35, 40, 38, 41, 39, 36, 38, 36, + 36, 38, 31, 33, 25, 21, 14, 8, 1, 2, 0, -3, -5, -15, -23, -28, + -40, -39, -43, -46, -43, -52, -53, -59, -66, -62, -69, -63, -64, -64, -50, -56, + -44, -45, -43, -38, -36, -31, -20, -8, 4, 12, 19, 18, 28, 31, 40, 52, + 57, 68, 73, 73, 77, 73, 81, 79, 82, 82, 77, 82, 77, 75, 69, 59, + 53, 42, 33, 24, 22, 17, 11, 1, -17, -25, -36, -42, -46, -55, -60, -64, + -73, -77, -88, -90, -92, -97, -98, -100, -100, -92, -85, -79, -80, -76, -79, -69, + -56, -50, -32, -24, -15, 0, -2, 11, 15, 29, 45, 55, 67, 72, 82, 88, + 95, 101, 102, 109, 109, 112, 109, 110, 110, 106, 104, 91, 81, 77, 68, 66, + 54, 42, 32, 14, 6, -6, -12, -20, -29, -43, -55, -65, -76, -76, -85, -89, + -97, -105, -107, -114, -115, -117, -117, -113, -112, -104, -101, -91, -85, -84, -70, -72, + -55, -42, -34, -14, -8, 5, 16, 22, 35, 44, 57, 69, 78, 89, 94, 101, + 104, 109, 109, 119, 118, 117, 120, 110, 114, 114, 99, 102, 84, 74, 72, 57, + 52, 43, 32, 22, 10, -7, -20, -28, -34, -47, -54, -60, -67, -71, -80, -87, + -90, -105, -105, -110, -120, -115, -120, -123, -113, -111, -109, -97, -98, -92, -83, -82, + -76, -63, -61, -48, -39, -30, -16, -3, 10, 22, 32, 42, 49, 61, 67, 76, + 84, 91, 101, 105, 115, 116, 117, 125, 115, 119, 116, 106, 111, 102, 97, 92, + 84, 79, 70, 64, 50, 45, 31, 19, 14, -2, -9, -19, -30, -35, -47, -54, + -62, -67, -73, -82, -86, -96, -100, -105, -109, -116, -118, -120, -120, -117, -111, -110, + -97, -96, -90, -84, -78, -73, -64, -55, -50, -39, -25, -20, 1, 11, 19, 37, + 40, 51, 61, 68, 76, 85, 94, 97, 105, 114, 112, 120, 122, 119, 121, 117, + 110, 106, 105, 92, 90, 84, 69, 71, 57, 48, 45, 29, 22, 14, -2, -9, + -22, -31, -40, -47, -59, -62, -68, -76, -80, -87, -97, -96, -111, -111, -116, -124, + -119, -123, -120, -109, -109, -98, -95, -93, -84, -81, -75, -66, -55, -51, -37, -28, + -16, 1, 12, 23, 39, 40, 55, 59, 68, 77, 86, 94, 103, 104, 116, 117, + 118, 125, 122, 117, 120, 107, 108, 104, 95, 92, 85, 72, 70, 60, 48, 43, + 29, 18, 10, -7, -12, -22, -30, -38, -49, -58, -63, -72, -75, -84, -90, -93, + -100, -110, -103, -121, -115, -115, -124, -110, -112, -111, -92, -98, -86, -81, -77, -69, + -61, -53, -48, -34, -27, -13, 1, 9, 28, 37, 45, 58, 59, 76, 78, 85, + 97, 98, 109, 114, 111, 123, 120, 119, 121, 116, 111, 110, 101, 93, 92, 79, + 73, 68, 55, 52, 40, 30, 21, 10, 0, -13, -23, -29, -41, -47, -58, -64, + -69, -75, -84, -89, -93, -103, -105, -110, -120, -115, -117, -128, -105, -114, -109, -88, + -102, -86, -76, -84, -64, -63, -56, -43, -37, -25, -10, 4, 11, 31, 36, 46, + 56, 58, 74, 78, 84, 100, 95, 110, 114, 110, 124, 120, 116, 121, 110, 105, + 108, 97, 96, 91, 79, 75, 66, 57, 51, 38, 29, 17, 5, -3, -13, -20, + -28, -40, -46, -55, -66, -68, -76, -85, -88, -97, -102, -106, -110, -117, -115, -120, + -122, -108, -117, -103, -98, -96, -86, -79, -77, -66, -59, -54, -46, -33, -31, -10, + -2, 11, 27, 36, 47, 58, 62, 74, 78, 86, 94, 96, 106, 109, 115, 120, + 118, 121, 119, 112, 114, 104, 98, 94, 85, 77, 72, 63, 56, 49, 37, 31, + 20, 6, -2, -15, -24, -33, -44, -50, -58, -63, -68, -76, -82, -89, -95, -105, + -105, -116, -118, -117, -126, -114, -111, -118, -92, -105, -92, -83, -88, -72, -71, -65, + -51, -50, -31, -25, -9, 2, 16, 29, 35, 50, 53, 67, 73, 75, 92, 88, + 104, 112, 108, 122, 117, 119, 123, 114, 116, 110, 104, 98, 94, 86, 80, 75, + 63, 59, 47, 36, 29, 13, 9, -5, -16, -21, -36, -40, -50, -61, -61, -73, + -77, -85, -93, -95, -103, -108, -117, -120, -118, -125, -117, -108, -116, -96, -98, -97, + -83, -82, -78, -66, -61, -54, -43, -32, -25, -2, 3, 16, 33, 36, 52, 56, + 66, 75, 78, 94, 91, 103, 113, 108, 122, 119, 119, 121, 116, 112, 110, 106, + 93, 96, 83, 76, 74, 59, 58, 47, 34, 28, 14, 6, -6, -17, -27, -36, + -44, -54, -61, -63, -70, -76, -86, -90, -99, -102, -108, -117, -115, -121, -123, -111, + -120, -102, -100, -101, -84, -91, -76, -74, -70, -54, -56, -41, -30, -20, -3, 8, + 23, 31, 46, 47, 59, 70, 71, 83, 89, 90, 108, 108, 115, 120, 121, 122, + 118, 118, 109, 110, 102, 93, 93, 82, 78, 72, 62, 57, 45, 37, 22, 15, + 4, -10, -18, -30, -36, -42, -54, -57, -63, -68, -77, -86, -91, -102, -103, -108, + -117, -114, -119, -117, -115, -110, -106, -100, -91, -99, -79, -81, -77, -59, -61, -50, + -36, -33, -16, -4, 10, 16, 35, 39, 48, 62, 64, 76, 85, 89, 98, 105, + 110, 113, 120, 119, 118, 123, 112, 111, 110, 100, 98, 93, 82, 78, 70, 58, + 54, 45, 30, 24, 12, 0, -7, -20, -28, -36, -45, -55, -61, -66, -73, -79, + -88, -93, -103, -105, -112, -119, -115, -124, -123, -109, -119, -103, -98, -102, -92, -84, + -83, -75, -62, -59, -50, -34, -34, -12, 1, 7, 26, 33, 42, 50, 62, 67, + 76, 88, 90, 101, 110, 108, 118, 121, 119, 122, 121, 111, 113, 110, 98, 98, + 91, 80, 78, 66, 58, 53, 40, 29, 20, 8, -4, -11, -22, -33, -37, -49, + -57, -61, -68, -77, -81, -90, -96, -101, -110, -112, -116, -120, -116, -121, -119, -104, + -111, -96, -91, -96, -79, -79, -76, -59, -57, -46, -33, -25, -14, 5, 11, 26, + 39, 42, 55, 61, 70, 81, 86, 94, 101, 105, 114, 116, 120, 121, 119, 119, + 115, 111, 107, 102, 94, 90, 82, 73, 68, 59, 50, 41, 28, 20, 7, -4, + -12, -22, -30, -41, -48, -56, -62, -69, -75, -83, -90, -98, -100, -107, -111, -119, + -112, -124, -120, -107, -119, -101, -93, -104, -80, -85, -83, -61, -65, -55, -40, -38, + -25, -7, -3, 13, 29, 34, 45, 57, 59, 74, 79, 87, 98, 98, 108, 111, + 112, 122, 117, 119, 119, 111, 110, 107, 96, 96, 89, 76, 74, 63, 54, 51, + 35, 27, 19, 5, -3, -12, -25, -29, -43, -52, -58, -64, -71, -78, -82, -92, + -98, -101, -108, -110, -114, -120, -119, -118, -115, -110, -106, -95, -97, -82, -84, -76, + -62, -63, -51, -42, -39, -20, -12, 2, 15, 29, 36, 47, 58, 62, 74, 80, + 85, 95, 101, 106, 111, 116, 118, 117, 122, 113, 115, 111, 99, 103, 90, 85, + 80, 68, 63, 56, 46, 36, 28, 17, 5, -5, -19, -25, -35, -43, -52, -58, + -62, -72, -75, -83, -94, -94, -105, -105, -115, -115, -116, -122, -114, -112, -108, -98, + -99, -89, -86, -82, -72, -69, -58, -52, -44, -31, -21, -6, 4, 17, 28, 39, + 48, 53, 66, 72, 80, 88, 92, 104, 108, 113, 116, 119, 121, 116, 119, 112, + 108, 107, 94, 94, 85, 79, 72, 62, 57, 48, 37, 25, 17, 8, -8, -15, + -26, -35, -42, -55, -59, -65, -73, -75, -87, -89, -97, -104, -109, -116, -116, -121, + -120, -120, -109, -108, -103, -90, -97, -78, -78, -77, -60, -64, -50, -41, -34, -16, + -7, 9, 19, 33, 42, 52, 60, 65, 77, 79, 87, 96, 99, 109, 113, 118, + 124, 117, 121, 117, 109, 110, 99, 94, 93, 83, 77, 73, 63, 55, 50, 32, + 26, 18, 0, -6, -20, -29, -34, -49, -53, -57, -63, -71, -76, -83, -91, -97, + -108, -112, -114, -122, -115, -124, -112, -105, -112, -89, -99, -90, -78, -89, -72, -66, + -61, -49, -41, -28, -16, 2, 6, 25, 35, 36, 53, 54, 67, 77, 79, 93, + 97, 105, 112, 111, 122, 118, 119, 117, 112, 109, 108, 99, 95, 92, 82, 76, + 71, 59, 56, 43, 30, 24, 10, 0, -9, -18, -26, -36, -45, -55, -59, -68, + -75, -81, -88, -94, -99, -106, -109, -110, -119, -117, -119, -116, -111, -105, -101, -91, + -92, -83, -75, -75, -61, -52, -52, -35, -29, -18, 0, 9, 22, 36, 41, 51, + 64, 68, 78, 88, 90, 101, 103, 109, 113, 115, 121, 117, 118, 116, 109, 109, + 102, 94, 90, 80, 71, 67, 57, 47, 42, 30, 19, 14, -4, -9, -19, -31, + -36, -50, -55, -61, -68, -74, -79, -87, -93, -101, -107, -107, -115, -118, -118, -123, + -112, -110, -109, -92, -93, -94, -74, -83, -71, -57, -61, -45, -34, -31, -10, 0, + 12, 27, 37, 42, 55, 61, 70, 77, 87, 95, 96, 106, 112, 113, 123, 122, + 117, 122, 112, 109, 110, 96, 96, 92, 76, 74, 68, 55, 50, 40, 28, 20, + 7, -6, -10, -23, -31, -42, -51, -59, -65, -70, -76, -82, -88, -92, -104, -104, + -105, -122, -113, -122, -126, -106, -119, -103, -91, -99, -82, -80, -76, -66, -59, -54, + -46, -34, -30, -9, 1, 13, 33, 34, 51, 57, 63, 76, 77, 91, 95, 95, + 110, 108, 115, 122, 120, 120, 123, 112, 110, 110, 94, 95, 87, 70, 74, 62, + 55, 50, 39, 29, 20, 7, -5, -13, -26, -35, -44, -56, -61, -65, -69, -75, + -83, -86, -98, -104, -104, -121, -115, -119, -128, -110, -117, -116, -92, -100, -90, -78, + -83, -75, -63, -64, -55, -41, -39, -20, -7, 1, 21, 31, 40, 51, 55, 67, + 72, 77, 91, 93, 99, 110, 109, 118, 125, 118, 124, 119, 108, 114, 101, 93, + 96, 81, 75, 73, 59, 57, 48, 35, 27, 15, 1, -7, -20, -29, -37, -49, + -56, -61, -65, -69, -74, -83, -91, -98, -107, -113, -117, -120, -122, -118, -115, -111, + -103, -101, -92, -89, -85, -80, -77, -65, -61, -51, -41, -33, -16, -4, 8, 21, + 34, 40, 49, 57, 63, 73, 82, 89, 98, 104, 109, 117, 118, 123, 122, 119, + 116, 110, 108, 100, 97, 93, 83, 80, 70, 64, 55, 45, 34, 22, 12, -2, + -10, -20, -30, -35, -48, -55, -62, -67, -71, -78, -86, -91, -101, -104, -110, -117, + -117, -120, -123, -111, -111, -110, -90, -99, -90, -76, -85, -71, -58, -63, -45, -37, + -33, -14, 1, 4, 27, 34, 41, 53, 59, 66, 79, 84, 92, 100, 103, 110, + 115, 116, 123, 118, 118, 117, 107, 110, 101, 95, 93, 79, 76, 68, 57, 52, + 43, 30, 23, 11, -3, -8, -20, -30, -34, -48, -55, -60, -69, -74, -81, -89, + -92, -101, -105, -108, -114, -117, -118, -122, -112, -113, -108, -95, -101, -87, -82, -83, + -68, -60, -56, -45, -38, -28, -17, -2, 6, 23, 33, 40, 54, 60, 68, 80, + 85, 94, 96, 103, 109, 110, 119, 118, 118, 121, 113, 112, 110, 100, 98, 90, + 77, 73, 66, 55, 51, 41, 29, 25, 8, 1, -9, -23, -28, -42, -51, -59, + -64, -67, -75, -79, -86, -94, -98, -105, -111, -115, -117, -121, -123, -111, -120, -102, + -95, -100, -79, -84, -81, -61, -69, -55, -46, -42, -27, -14, -3, 11, 30, 35, + 49, 57, 60, 76, 76, 86, 95, 95, 109, 108, 116, 122, 121, 123, 120, 116, + 114, 106, 100, 94, 88, 78, 73, 65, 59, 52, 38, 33, 20, 10, -2, -15, + -22, -32, -42, -51, -58, -62, -67, -77, -80, -86, -94, -100, -106, -113, -115, -119, + -122, -118, -117, -107, -106, -98, -89, -89, -78, -76, -71, -57, -56, -46, -36, -25, + -12, 0, 16, 26, 39, 49, 54, 67, 72, 80, 88, 94, 101, 104, 115, 113, + 121, 125, 116, 123, 116, 110, 109, 98, 93, 88, 78, 69, 65, 56, 47, 42, + 27, 20, 8, -6, -15, -27, -33, -43, -53, -58, -64, -68, -74, -86, -87, -96, + -106, -103, -117, -116, -117, -123, -117, -106, -114, -97, -96, -96, -81, -81, -80, -62, + -64, -49, -45, -34, -19, -8, 4, 17, 28, 40, 47, 54, 66, 73, 79, 93, + 95, 102, 113, 110, 117, 123, 119, 121, 117, 113, 111, 106, 96, 95, 88, 78, + 72, 63, 55, 47, 35, 26, 14, 4, -9, -19, -24, -35, -43, -51, -61, -65, + -72, -79, -88, -88, -99, -107, -107, -120, -114, -120, -122, -113, -116, -102, -106, -95, + -89, -95, -72, -80, -70, -50, -58, -37, -30, -20, -5, 6, 18, 29, 44, 45, + 57, 72, 68, 89, 89, 97, 109, 104, 120, 113, 118, 124, 112, 120, 112, 107, + 106, 96, 91, 87, 78, 66, 65, 52, 40, 39, 17, 17, 4, -13, -13, -30, + -35, -44, -58, -59, -66, -72, -78, -85, -93, -97, -106, -114, -110, -120, -120, -118, + -120, -109, -110, -98, -100, -89, -81, -87, -68, -68, -59, -44, -46, -29, -18, -5, + 5, 22, 32, 39, 54, 56, 68, 79, 79, 94, 98, 102, 110, 112, 117, 119, + 124, 117, 116, 116, 104, 106, 97, 89, 86, 74, 67, 60, 53, 41, 34, 24, + 12, 4, -9, -19, -28, -38, -47, -58, -60, -68, -73, -77, -88, -93, -96, -111, + -109, -115, -124, -118, -122, -120, -107, -109, -102, -91, -95, -82, -78, -78, -60, -59, + -51, -36, -35, -14, -3, 6, 24, 34, 41, 56, 59, 67, 81, 82, 92, 103, + 102, 112, 119, 114, 123, 123, 116, 121, 112, 106, 107, 93, 91, 84, 74, 69, + 61, 52, 43, 32, 21, 13, -2, -10, -22, -31, -38, -51, -56, -59, -69, -71, + -76, -87, -90, -100, -107, -110, -119, -118, -120, -123, -108, -118, -101, -92, -102, -77, + -85, -83, -63, -71, -58, -45, -44, -27, -15, -2, 10, 30, 32, 46, 57, 56, + 74, 73, 84, 93, 95, 109, 108, 117, 117, 124, 119, 119, 119, 112, 109, 100, + 96, 90, 81, 75, 65, 59, 51, 41, 33, 22, 12, 0, -12, -23, -30, -40, + -51, -57, -64, -71, -73, -83, -84, -95, -102, -102, -116, -117, -118, -128, -116, -114, + -116, -102, -99, -95, -86, -80, -80, -71, -58, -61, -46, -38, -30, -10, -4, 12, + 26, 37, 47, 54, 67, 68, 79, 89, 86, 104, 104, 111, 118, 118, 123, 121, + 119, 116, 112, 109, 99, 96, 88, 80, 75, 66, 58, 49, 41, 29, 19, 10, + -5, -10, -25, -35, -39, -53, -58, -64, -69, -75, -81, -87, -100, -99, -112, -116, + -118, -126, -123, -115, -120, -111, -102, -100, -93, -86, -85, -76, -69, -64, -56, -47, + -38, -25, -10, 4, 16, 31, 40, 46, 61, 65, 70, 83, 86, 93, 103, 105, + 114, 125, 118, 124, 125, 112, 120, 111, 98, 103, 91, 86, 83, 71, 66, 61, + 49, 38, 32, 16, 7, -4, -17, -26, -36, -44, -54, -60, -59, -71, -75, -79, + -94, -95, -103, -117, -112, -120, -127, -120, -118, -117, -104, -102, -99, -88, -84, -86, + -73, -70, -64, -51, -47, -37, -17, -10, 7, 19, 32, 40, 52, 56, 67, 73, + 80, 87, 92, 103, 109, 110, 123, 119, 121, 126, 111, 113, 112, 98, 98, 91, + 80, 80, 71, 60, 61, 47, 36, 30, 13, 5, -5, -19, -27, -35, -43, -52, + -58, -62, -71, -76, -84, -96, -100, -105, -118, -115, -121, -123, -121, -114, -117, -110, + -98, -105, -91, -83, -90, -71, -68, -64, -48, -43, -33, -17, -5, 3, 23, 32, + 38, 54, 59, 66, 79, 82, 92, 100, 105, 108, 116, 119, 117, 126, 116, 115, + 118, 106, 105, 99, 91, 85, 78, 67, 60, 54, 41, 33, 24, 11, 0, 3, + 10, 14, -8, 46, 7, -20, -23, -28, 17, 9, 47, -7, -15, -35, -1, -26, + 44, 34, -31, 31, -47, -32, 30, -2, 32, 15, -15, -17, -39, 16, -2, 26, + 23, 3, -43, 11, -37, 14, 37, 7, 4, -21, -30, -9, 14, 18, 38, -13, + -16, -21, -24, 8, 38, 3, 16, -29, -11, -26, 20, 15, 24, -9, 0, -34, + -21, 32, -16, 41, -1, -20, -7, -7, -7, 27, 0, -2, -2, -11, -11, 19, + -16, 32, -19, -4, 11, -40, 49, -13, -12, 12, -32, 12, 17, 1, 23, -34, + -20, 14, -20, 33, 44, -51, 7, -21, -38, 46, 19, 37, -28, -29, -17, -40, + 63, 36, -33, 42, -45, -57, 16, 37, -3, 54, 0, -64, -25, -7, 15, 37, + 34, -2, -65, -12, -3, -7, 76, -2, -6, -28, -22, -30, 40, 11, 12, 21, + -43, -6, -1, -31, 73, -35, 33, -1, -67, 29, -24, 16, 42, 4, -26, 17, + -71, 32, 0, 0, 72, -56, 4, -2, -75, 76, -25, 39, 24, -42, -6, -20, + -31, 56, 1, 3, 49, -63, -12, -16, -10, 49, 12, 29, -32, -59, 35, -39, + 35, 45, -33, -21, 46, -68, 13, 16, 12, 0, 2, 32, -70, 12, 30, -62, + 64, 5, -31, 22, -30, 11, -30, 43, 2, -8, 16, -3, -60, 39, -11, -13, + 63, -32, 8, -6, -45, 39, -38, 30, 49, -89, 96, -84, 0, 43, -51, 52, + -4, -6, 7, -31, -10, 12, -22, 62, 8, -57, 65, -101, 1, 69, -46, 76, + -18, -34, -24, -33, 50, -6, 55, 16, -70, -19, 2, -33, 59, 61, -40, 7, + -44, -33, -7, 61, 31, -15, 5, -32, -70, 47, 34, 8, 22, -16, -44, -47, + 56, -6, 12, 56, -46, -32, -3, 7, -4, 42, 19, -41, -35, 41, -59, 43, + 45, -44, 9, -9, -7, -19, 36, 2, -50, 49, -6, -34, 33, -1, -38, 17, + 44, -33, 5, 28, -68, -13, 62, -25, 15, 45, -57, -32, 23, -14, 37, 11, + 29, -56, -48, 46, -55, 48, 94, -74, 22, -40, -59, 36, 9, 75, -19, -31, + 6, -104, 39, 80, -23, 59, -12, -104, 10, -12, 24, 59, 5, 9, -78, -12, + 24, -47, 116, -6, -51, 34, -71, -26, 55, 3, 11, 38, -31, -9, -45, 21, + -11, 4, 92, -79, 16, -16, -41, 29, 27, 19, -5, -19, -13, -35, 29, 22, + -7, 20, -35, 6, -21, 30, -2, 6, -8, -20, -12, 30, -13, 8, 23, -52, + 21, 8, -16, 40, -20, -7, -15, -38, 62, -33, 48, 5, -66, 28, -25, 15, + 39, 5, -46, 8, -46, 32, 12, 37, -9, -49, 43, -78, 43, 46, -43, 39, + -41, -36, 13, 19, 48, -21, 9, -37, -54, 45, 32, -14, 41, -32, -66, 42, + -8, 37, 12, -10, -12, -74, 71, -30, 16, 65, -64, -1, -13, -12, 17, 24, + 10, -16, -31, -1, -3, 1, 68, -47, -7, -8, -41, 74, -16, 32, -27, -42, + 22, -49, 80, -11, 0, 23, -84, 34, -24, 31, 48, -37, 23, -55, -25, 22, + 14, 22, 59, -78, -11, -1, -45, 90, -35, 32, 0, -75, 63, -65, 34, 52, + -71, 70, -56, -14, 30, -22, 10, 55, -74, 41, -19, -47, 88, -62, 50, -11, + -57, 44, -54, 59, 17, -23, 12, -40, -41, 60, 3, 15, 28, -71, -1, -17, + 11, 61, -28, 47, -59, -48, 35, -18, 51, 27, -20, -35, -36, 14, 6, 44, + 23, -30, -33, -17, -1, 14, 49, -2, -32, -12, -20, 5, 29, 34, -33, 9, + -34, -26, 36, -2, 40, -28, 5, -26, -39, 65, -27, 19, 31, -54, 0, -8, + 12, 2, 30, -5, -25, -22, 24, -29, 26, 52, -57, 7, 5, -56, 46, 1, + 8, 4, -5, 1, -51, 28, 14, -21, 48, -17, -46, 4, 11, -6, 35, 7, + -16, -31, -10, 25, -49, 95, -28, -29, 19, -46, -5, 32, 21, 8, -1, -24, + -36, -17, 59, -7, 33, 10, -76, -14, 19, -1, 56, 16, -23, -64, -8, 7, + 8, 85, 0, -57, -21, -35, -7, 72, 23, 28, -66, -16, -47, 2, 68, 24, + 5, 0, -69, -26, 22, -7, 72, 0, -12, -20, -51, 15, -11, 44, 44, -46, + 36, -59, -38, 32, 19, -3, 71, -45, -28, -29, -17, 36, 8, 79, -47, -53, + 18, -65, 38, 75, -24, 20, -36, -34, -26, 38, 39, -7, -3, 7, -85, 44, + 26, -17, 42, -20, -29, -26, 26, 18, -8, 36, -17, -73, 40, 4, -1, 52, + -16, -47, -15, 14, 4, 29, 30, -41, -44, 15, -2, 16, 60, -26, -54, 17, + -33, 22, 48, -5, -15, -20, -13, -15, 31, 37, -28, 6, -17, -22, -10, 64, + -43, 16, 22, -71, 41, 3, -1, 6, -12, 12, -38, 11, 38, -49, 37, 24, + -64, 27, 18, -73, 81, -33, 14, -3, -32, 43, -60, 53, 24, -76, 70, -29, + -33, 50, -18, -34, 48, -38, 37, -15, -5, 25, -80, 70, -4, -45, 89, -72, + -3, 13, -23, 28, 21, -9, -9, -25, -11, 24, -26, 62, -14, -49, 67, -97, + 57, 12, -23, 46, -46, 9, -20, -4, 25, -1, 5, 18, -31, -25, 38, -43, + 44, 17, -42, 37, -66, 37, -16, 26, 18, -16, -17, -4, -17, 7, 38, -11, + 4, -3, -51, 32, -17, 38, 18, -34, 23, -58, 4, 25, 0, 26, 3, -35, + -11, -10, 16, 24, 8, 4, -33, -30, 22, -2, 14, 52, -61, 10, -23, -4, + 20, 10, 32, -44, -2, 1, -36, 37, 32, -25, 2, 0, -40, 14, 24, -5, + 13, -28, 20, -51, 41, 15, -23, 25, -12, -41, 30, -2, -11, 40, -34, 14, + -24, 3, 22, -31, 44, -22, -31, 57, -55, 28, 0, -9, 1, 11, -10, 8, + -13, 3, -2, -23, 60, -49, 23, 10, -59, 36, -3, -3, 35, -23, 5, -42, + 15, 7, -2, 35, 0, -45, 8, -4, -27, 63, -4, -14, 9, -39, 1, 1, + 27, 19, -27, 24, -49, -6, 34, -5, 10, 19, -32, -20, 14, -12, 16, 26, + -9, -19, -9, -8, 8, 7, 40, -29, -14, -4, -25, 7, 56, -15, 6, -20, + -36, 3, 10, 33, 20, -23, -5, -42, -18, 54, -17, 63, -5, -59, 2, -44, + 12, 57, 17, 15, -33, -44, -16, -17, 65, 40, -9, 10, -72, -51, 39, 10, + 65, 19, -25, -47, -51, 17, 20, 53, 30, -35, -35, -34, -16, 36, 48, 12, + -3, -35, -42, -9, 28, 34, 12, 15, -42, -39, 7, 8, 24, 28, 1, -31, + -36, 9, -1, 28, 29, -14, -34, 14, -43, 23, 34, -7, 24, -44, 10, -28, + -5, 53, -29, 29, -7, -33, 2, -1, 5, 19, 10, -17, 2, -33, 14, 1, + 8, 32, -36, 17, -28, -18, 36, -22, 29, 2, -25, 5, -17, 13, 1, 16, + -1, -10, -12, 3, -9, 10, 19, -22, 16, -3, -20, 24, -22, 15, -3, -14, + 22, -30, 31, -14, -11, 12, -11, 8, 17, -9, -4, -13, -13, 7, 10, 19, + -6, -7, -2, -32, 24, 8, 0, 17, -20, -10, -15, 13, 10, 11, 4, -1, + -40, 19, -4, -6, 42, -31, -1, -5, -12, 19, 6, 7, -5, -26, 10, -12, + 15, 20, -8, -19, 12, -40, 31, 15, -3, 16, -23, -27, 7, -5, 31, 6, + 3, -6, -41, 14, -2, 7, 38, -10, -29, 11, -44, 17, 29, 6, 20, -26, + 1, -45, 9, 31, -18, 40, -1, -47, 8, -10, -4, 29, 33, -25, 1, -31, + -12, -9, 35, 30, -25, 31, -48, -28, 20, 17, 9, 30, -19, -39, -13, 6, + 8, 38, 15, -10, -42, 0, -24, 15, 49, -9, -12, 5, -44, -5, 42, 4, + 6, 8, -27, -29, 5, 24, -2, 10, 28, -56, 1, 23, -29, 29, 15, -19, + -11, 1, -4, -8, 24, 6, -15, 2, 7, -27, 12, 21, -40, 36, -15, -12, + 22, -16, 17, -17, 15, -6, -18, 23, -3, -26, 39, -27, -5, 26, -20, 8, + 5, -11, 7, -21, 19, -11, -8, 35, -25, 2, 18, -35, 9, 16, -21, 29, + -16, 1, -13, -13, 28, -18, 23, 13, -36, 6, -1, -23, 26, 12, -15, 17, + -20, -2, -7, 3, 22, -22, 27, -11, -34, 36, -30, 11, 17, 2, -12, 13, + -22, -11, 11, -5, 26, -17, 26, -25, -32, 44, -47, 39, 25, -31, 16, -35, + -1, -4, 26, 16, 3, -16, -10, -23, -8, 55, -27, 26, 0, -63, 41, -26, + 28, 22, -23, 14, -42, 5, 20, -13, 28, 3, -42, 20, -6, -17, 52, -32, + 6, -2, -37, 42, -27, 29, 15, -51, 40, -38, 2, 33, -19, 6, 11, -43, + 25, 0, -19, 57, -54, 31, -9, -43, 58, -52, 36, 11, -44, 50, -44, 8, + 23, -24, 12, 6, -34, 25, -9, -15, 50, -55, 35, -7, -25, 49, -48, 32, + -23, -18, 37, -30, 28, 8, -27, 7, -2, -19, 22, 10, -11, 10, -27, 4, + -16, 18, 29, -19, 20, -22, -36, 16, -2, 18, 14, 3, -24, -15, -5, 12, + 13, 20, 4, -40, 2, -23, 8, 29, 7, 9, -23, -10, -13, 5, 19, 9, + -3, -14, -7, -19, 21, 6, 5, 10, -20, 0, -14, 12, 0, 2, 5, -13, + 1, -3, 12, -12, 20, -13, -7, 6, -11, 5, 0, 5, -5, -4, 10, -10, + 2, 6, -5, -12, 18, -13, -9, 19, -17, 11, -1, 8, -5, -22, 26, -26, + 1, 29, -17, -7, 16, -22, -8, 23, -3, 4, -3, -2, -15, -20, 42, -21, + 4, 40, -55, 8, 8, -22, 21, 20, -17, 2, -14, -7, -2, 10, 31, -25, + 10, -3, -54, 40, 5, -12, 42, -17, -37, 13, -12, 7, 24, 10, -6, -36, + 12, -9, -25, 74, -24, -19, 38, -64, 5, 25, 0, 16, 1, -9, -25, -23, + 36, -8, 6, 50, -58, -12, 22, -53, 52, 18, -12, 16, -51, 15, -30, 25, + 46, -37, 31, -26, -49, 30, 9, -1, 42, -19, -28, -13, -5, 16, 4, 42, + -18, -40, 20, -30, 1, 49, -4, -15, 0, -21, -19, 21, 26, 0, -9, 9, + -43, -1, 26, -5, 21, -7, -6, -32, 9, 12, -3, 34, -17, -12, -17, -4, + 9, 7, 28, -19, -3, -13, -11, 7, 15, 15, -19, 15, -38, -5, 17, -1, + 29, -20, 15, -39, -11, 41, -33, 45, -8, -21, -11, -3, 7, 0, 28, -7, + -19, -8, 7, -20, 23, 24, -40, 24, -17, -16, 26, -9, 21, -27, 13, -11, + -22, 29, -7, 0, 22, -22, -16, 14, -12, 12, 11, -5, -6, -17, 14, -15, + 9, 30, -28, 5, 1, -26, 8, 18, -7, 1, 6, -12, -15, 9, 13, -13, + 13, 13, -42, 14, 3, -16, 20, 7, -3, -22, 25, -26, 4, 16, -7, 3, + -8, 17, -33, 14, 9, -21, 25, -3, -11, -1, 1, -13, 1, 23, -20, 26, + -18, 0, -18, 3, 24, -25, 36, -15, -29, 22, -22, 3, 24, -5, -1, 0, + -18, 2, -11, 20, 10, -17, 30, -37, -15, 29, -33, 39, 11, -23, 7, -34, + 8, 0, 11, 36, -27, -12, 9, -47, 29, 31, -29, 40, -37, -14, 3, -17, + 45, -11, 8, 12, -60, 20, -2, -2, 41, -12, -18, 3, -37, 27, 12, -4, + 37, -56, 17, -21, -5, 44, -20, 14, -2, -40, 20, 0, 3, 22, -13, -10, + -6, -16, 29, -12, 14, 15, -49, 24, -11, -7, 39, -18, 3, -20, -12, 19, + -10, 32, 2, -34, 10, -13, -13, 37, 1, -7, 3, -33, 4, 2, 18, 25, + -25, 8, -33, -13, 34, -7, 24, 4, -33, -10, -2, 2, 25, 12, -1, -25, + -12, 3, -18, 34, 12, -15, 4, -9, -25, 10, 17, -3, 9, 2, -13, -23, + 9, 8, -13, 37, -10, -15, 1, -13, -1, 0, 31, -15, 0, 5, -29, 6, + 5, 15, -9, 16, -9, -29, 15, -10, 3, 15, 9, -11, -12, 11, -29, 17, + 14, -7, 6, -6, -7, -24, 30, -11, 9, 18, -20, -8, -6, 6, -10, 22, + 10, -29, 14, -13, -8, 13, 17, -13, 2, 1, -24, 5, 5, 12, -10, 15, + -7, -28, 21, -2, -8, 22, -9, -14, -2, 6, -5, 5, 12, -7, -15, 14, + -4, -16, 27, -10, -14, 13, -5, -9, 10, 5, -8, -5, 16, -20, 2, 13, + -14, -3, 17, -18, 2, 10, -12, 9, -6, -2, -16, 13, 10, -15, 33, -24, + -17, 10, -4, 15, 1, 9, -23, -9, 6, -5, 5, 21, -10, -13, 11, -21, + -2, 19, -10, 23, -20, 10, -16, -21, 33, -17, 17, 18, -30, 1, -14, -1, + 20, -2, 18, -15, -24, 6, -5, 6, 36, -26, 6, -18, -23, 34, -12, 25, + 1, -30, -1, -11, 10, 22, -1, 4, -19, -28, 21, -11, 22, 25, -33, 4, + -21, -7, 22, 7, 19, -23, -13, -3, -13, 21, 17, -11, 7, -19, -12, 12, + -10, 30, -13, -5, 4, -30, 27, -9, 17, -3, -25, 13, -23, 13, 27, -15, + -5, 3, -35, 17, 19, -8, 29, -37, 1, -15, -10, 48, -20, 26, -7, -49, + 22, -23, 21, 33, -10, -8, -17, -34, 11, 19, 12, 40, -39, -14, -13, -36, + 64, -4, 20, 9, -55, 3, -24, 21, 31, 10, -1, -22, -30, -7, 12, 18, + 29, -10, -7, -28, -22, 22, 3, 26, 4, -13, -18, -16, 21, -9, 28, -1, + -21, 0, -12, 5, 6, 5, 10, -20, 1, 3, -20, 21, 7, -23, 24, -25, + -6, 21, -13, 25, -19, -8, 2, -14, 20, 13, -23, 25, -31, -7, 24, -16, + 20, 6, -25, 8, -24, 12, 15, -10, 24, -25, -2, 0, -12, 14, 10, -13, + 4, 1, -17, 9, 6, -9, 9, 0, -3, -8, 11, -10, -2, 7, -1, -6, + 6, 1, -12, 1, 18, -31, 23, -2, -21, 21, -6, -8, 15, -14, 4, -6, + -1, 17, -22, 20, -6, -35, 37, -17, -6, 47, -41, 6, -6, -16, 12, 16, + 6, 1, -36, 18, -26, 4, 59, -36, -1, 16, -64, 30, 14, 1, 16, -13, + 0, -35, 17, 13, -8, 12, 14, -45, 11, 12, -24, 27, 12, -27, 10, -6, + -9, 1, 14, -7, -6, 8, -4, -8, 8, 8, -24, 13, 7, -27, 28, -1, + -28, 27, -19, -2, 17, -5, 6, -10, -5, 4, -25, 32, 2, -22, 32, -28, + -20, 35, -20, 16, 7, -18, 1, -22, 20, 0, 2, 20, -15, -25, 24, -25, + 12, 25, -23, 10, -19, -5, 8, 2, 20, -6, -13, 0, -22, 12, 15, -3, + 13, -13, -25, 12, -6, 18, 13, -3, -14, -22, 3, -2, 14, 25, -10, -16, + -5, -13, 2, 22, 9, -2, -11, -12, -20, 15, 20, 1, 14, -19, -17, -9, + 1, 19, 5, 0, 4, -35, 17, -7, 5, 20, -16, 2, -8, -11, 11, -2, + 2, 7, -19, 15, -10, 2, 12, -14, -3, 2, -9, 17, -3, 2, -7, -16, + 10, 2, 9, 10, -14, -9, -6, -11, 21, 5, 4, 6, -24, -5, -4, 6, + 18, 0, 8, -21, -18, 8, -8, 21, 16, -11, -9, -12, -15, 15, 3, 27, + -9, -16, 5, -30, 13, 23, -11, 21, -19, -15, -3, -9, 30, -9, 14, -6, + -22, -5, 15, -11, 23, -1, -14, -4, -9, 8, 4, 1, 20, -34, 9, 1, + -17, 24, -6, 1, -9, 1, -4, 3, 6, 8, -16, 0, 2, -13, 11, 21, + -31, 24, -21, -4, 13, -2, 7, -9, -3, 0, -18, 29, -4, -9, 16, -19, + -13, 25, -5, -1, 15, -24, 4, -15, 22, 4, -11, 20, -21, -25, 39, -23, + 14, 14, -23, 1, -8, 3, 12, -9, 23, -19, -18, 24, -22, 5, 30, -32, + 11, 2, -21, 18, -6, 5, 1, -9, 13, -22, 4, 19, -28, 26, 3, -28, + 21, -4, -25, 32, -15, 5, 0, -2, -4, -9, 15, 0, -13, 21, -14, -20, + 31, -19, 2, 17, -14, -9, 12, -6, 4, -1, 4, -17, -1, 12, -2, 0, + 20, -31, -8, 12, -8, 17, 14, -13, -16, -9, -7, 20, 11, 18, -13, -28, + -3, -12, 13, 40, -12, 4, -20, -32, 8, 17, 14, 21, -10, -28, -18, -2, + 11, 22, 17, 0, -34, -6, -3, -17, 50, 1, -13, 4, -22, -21, 17, 16, + 4, 7, 0, -27, -11, 4, 10, 2, 24, -6, -28, 7, -12, -2, 33, -3, + -6, 2, -37, 3, 9, 7, 24, -4, -14, -6, -24, 25, -1, 11, 16, -36, + -9, 12, -25, 45, 5, -20, 11, -36, 11, 7, 0, 30, -32, -1, 7, -33, + 37, 0, -9, 15, -21, -10, 12, -15, 24, -8, 3, 4, -20, 7, 3, -15, + 28, -14, -7, 13, -23, 2, 11, 0, 4, 7, -9, -16, 1, 7, -7, 19, + -3, -12, -14, 15, -10, 7, 30, -26, -13, 15, -30, 15, 26, -12, -1, -8, + -9, -5, 13, 22, -12, -12, 7, -36, 17, 31, -24, 27, -21, -24, 15, -10, + 26, 4, -12, 4, -36, 13, 14, -5, 27, -14, -22, 7, -12, 6, 23, -13, + 7, -19, -2, 7, -8, 25, -5, -17, 18, -25, 3, 14, -8, 4, 0, -1, + -11, 4, 12, -18, 15, 2, -23, 12, -2, -7, 12, 1, -1, -15, 11, -3, + -17, 41, -24, -7, 13, -25, 3, 22, -9, 15, -12, -9, 0, -17, 32, -5, + -5, 19, -49, 19, 3, -11, 45, -30, 2, -4, -28, 29, 0, 7, 12, -34, + 6, -10, 1, 33, -9, -6, 4, -41, 25, 2, 4, 29, -40, 8, -17, -9, + 42, -16, 16, -10, -33, 11, -7, 22, 12, -6, -6, -25, -4, 18, -3, 25, + -4, -29, 5, -17, 8, 22, 1, 4, -22, 1, -13, 2, 31, -19, 9, 2, + -36, 17, 5, -7, 20, -11, -2, -13, 4, 9, -18, 24, -3, -30, 33, -19, + -11, 31, -21, 6, 0, -5, 3, -10, 17, -7, -19, 30, -24, 0, 26, -23, + 3, 7, -17, 9, -3, 9, -1, -17, 23, -25, -3, 34, -27, 10, 15, -34, + 9, 1, 1, 7, -1, 12, -31, 4, 16, -27, 32, 10, -33, 10, -1, -27, + 29, 9, -9, 0, -1, -16, -6, 24, 2, -17, 23, -20, -24, 33, -11, -2, + 17, -7, -21, 13, 1, -7, 10, 1, -12, -9, 13, -1, -5, 20, -16, -15, + 15, -8, 5, 13, -10, -7, -9, 5, 2, 10, 7, -7, -22, 12, -13, 6, + 26, -14, -6, 0, -17, 3, 16, 6, 0, -11, 3, -26, 13, 15, -6, 7, + 4, -29, 6, 7, -3, 13, 1, -11, -9, 2, -1, 3, 9, -3, -8, 1, + -4, 0, 5, 0, 0, -2, 0, -1, 0, 0, -2, 11, 23, 22, 24, 25, + 20, 21, 15, 40, -1, -24, -42, -5, -19, -11, -8, 4, -46, -31, -14, -33, + -40, -44, -48, -89, -63, -47, -33, -27, -10, -6, 22, 25, 26, 28, 37, 11, + 15, 51, 44, 54, 66, 66, 71, 111, 84, 70, 63, 47, 39, 22, 47, -28, + -79, -111, -90, -91, -112, -81, -87, -49, -46, -5, -24, 26, 24, 47, 29, 23, + 30, 30, 13, -1, 4, -14, 17, 35, 62, 31, 53, 59, 72, 64, 27, 26, + 9, 9, -61, -44, -88, -74, -81, -83, -124, -96, -37, -78, -48, -56, -68, -60, + 7, 44, 39, 54, 77, 102, 110, 108, 89, 101, 100, 105, 64, 22, -1, 44, + 40, -19, -29, -35, -16, -27, -40, -77, -82, -113, -104, -93, -57, -72, -56, -3, + 1, 7, -1, 49, 39, 30, 31, 23, 10, 31, 11, 7, -19, -2, -2, 28, + 62, 92, 75, 33, 34, -20, -47, -61, -85, -105, -93, -119, -112, -54, -70, -67, + -32, -1, 4, 4, 20, 29, 62, 70, 54, 62, 78, 115, 92, 85, 78, 52, + 21, 19, 27, 2, -8, 13, 0, 5, 3, 9, 18, 0, -59, -61, -45, -57, + -65, -76, -89, -102, -48, -24, 17, 6, 26, 33, 35, 26, 41, 63, 20, 12, + 29, 34, 8, 7, 31, 21, 31, 39, 33, -5, -8, -55, -57, -98, -94, -88, + -64, -82, -74, -39, -14, 3, 16, 22, 8, 2, 17, 5, 36, 76, 74, 71, + 57, 73, 62, 47, 30, 32, 19, 4, 7, -14, -18, -2, 17, -5, 13, 22, + 31, 10, 8, -13, -47, -80, -85, -86, -71, -73, -60, -35, -10, 9, 19, 49, + 53, 47, 60, 73, 43, 33, 20, 13, -1, -7, -7, 7, 9, -2, 5, -14, + -40, -69, -61, -66, -67, -84, -58, -58, -33, 2, -7, -5, 12, 32, 18, 25, + 19, 24, 65, 59, 62, 64, 63, 55, 60, 52, 31, 19, -12, -26, -4, -7, + -10, -3, 6, -22, -14, 12, 19, 4, -26, -38, -40, -56, -61, -66, -59, -65, + -51, -20, 29, 40, 51, 52, 62, 61, 53, 26, 20, 6, 8, 6, 9, -14, + -14, -15, -2, -11, -23, -36, -38, -60, -77, -69, -60, -51, -56, -44, -27, 10, + -2, 14, 10, 22, 16, 41, 60, 39, 35, 60, 62, 43, 45, 63, 52, 17, + 12, 15, -1, -2, 0, -38, -48, -32, -22, -7, 3, 13, 10, -2, -1, -8, + -12, -25, -48, -46, -52, -49, -36, -17, 9, 17, 26, 48, 57, 55, 69, 60, + 32, 6, 4, -6, -20, -24, -9, -21, -25, -14, -18, -38, -38, -32, -51, -52, + -60, -34, -6, -6, -16, -11, -2, -1, 17, 19, 3, 11, 25, 31, 41, 39, + 33, 33, 41, 34, 34, 23, 21, 15, 6, -13, -24, -28, -20, -8, -12, -19, + -12, -5, 9, 14, 2, -12, -25, -28, -21, -28, -23, -22, -18, -26, -5, 24, + 45, 46, 47, 39, 33, 36, 42, 29, 7, -5, -10, -21, -29, -39, -39, -31, + -24, -29, -39, -51, -43, -27, -22, -18, -25, -26, -20, 9, 19, 18, 4, -2, + 19, 30, 38, 25, 24, 28, 33, 41, 38, 34, 32, 38, 24, 8, 4, -8, + -11, -15, -25, -31, -25, -20, -22, -15, -11, -9, -12, -17, -20, -20, -15, -6, + -11, -8, 0, 11, 29, 19, 17, 17, 18, 28, 31, 25, 18, 23, 18, 10, + 1, -7, -18, -26, -24, -30, -41, -38, -44, -32, -31, -31, -35, -25, -12, -2, + -8, -11, -13, -13, -2, 8, 15, 19, 29, 35, 37, 39, 43, 42, 40, 35, + 27, 25, 18, 15, 9, 4, -4, -15, -28, -28, -26, -28, -18, -15, -25, -23, + -12, -11, -14, -10, -2, -4, -1, 8, 15, 19, 22, 25, 16, 16, 17, 5, + 7, 13, 18, 13, 9, 6, 6, 4, -4, -21, -31, -28, -37, -39, -34, -38, + -38, -32, -17, -6, -4, -14, -19, -9, 3, -2, 3, 4, 7, 8, 13, 23, + 35, 38, 43, 42, 31, 25, 23, 17, 8, 3, 4, -7, -7, -10, -13, -20, + -19, -28, -33, -30, -23, -18, -13, -17, -12, 3, 14, 23, 31, 27, 23, 21, + 22, 19, 12, 4, 2, 2, -2, 0, 4, 11, 11, 6, 4, -2, -5, -14, + -17, -30, -38, -44, -42, -28, -21, -23, -21, -15, -15, -4, 8, 11, 4, -7, + -15, -7, 5, 10, 21, 26, 28, 27, 34, 37, 36, 28, 19, 10, 11, 8, + -2, -18, -17, -19, -19, -22, -24, -21, -24, -18, -17, -13, -19, -13, -1, 12, + 19, 22, 21, 19, 19, 30, 34, 24, 13, 7, 2, 1, 1, 2, -1, -2, + -6, 0, 0, -2, -15, -21, -17, -21, -28, -32, -31, -31, -32, -27, -24, -17, + -4, 1, -3, -1, 1, 4, 7, 8, 15, 16, 15, 15, 20, 32, 36, 38, + 32, 19, 12, 3, 2, -2, -4, -11, -19, -17, -15, -11, -16, -20, -27, -30, + -28, -22, -13, -6, -2, 2, 12, 23, 29, 45, 44, 36, 32, 21, 16, 14, + 10, 1, -9, -8, -2, -1, -7, -13, -13, -12, -9, -11, -18, -24, -26, -28, + -30, -24, -21, -21, -21, -11, -11, -10, 0, -2, 0, 4, 12, 13, 14, 12, + 17, 22, 28, 30, 28, 20, 16, 13, 8, 2, -2, -6, -15, -14, -18, -15, + -15, -16, -18, -18, -16, -19, -18, -17, -10, 0, -1, 4, 13, 22, 37, 39, + 36, 27, 27, 32, 26, 15, 6, -1, -4, -5, -7, -11, -11, -9, -15, -15, + -14, -18, -21, -19, -17, -21, -19, -15, -15, -10, -15, -14, -12, -11, -6, -2, + 1, -2, 1, 5, 14, 22, 33, 35, 23, 18, 16, 13, 11, 6, 1, -9, + -18, -11, -6, -7, -8, -9, -11, -11, -12, -13, -17, -21, -24, -24, -15, -4, + 7, 12, 17, 25, 30, 28, 31, 32, 31, 27, 22, 15, 12, 3, -2, -8, + -6, -3, -9, -13, -22, -24, -20, -18, -22, -24, -18, -14, -13, -10, -11, -9, + -3, -2, -3, -5, -10, -10, -5, -1, 4, 11, 15, 19, 22, 27, 23, 20, + 16, 14, 5, -3, -11, -15, -16, -12, -12, -11, -5, 1, -3, -10, -13, -15, + -11, -10, -10, -11, -8, -3, 2, 7, 9, 15, 25, 30, 33, 31, 25, 21, + 20, 16, 13, 7, -2, -8, -5, -4, -11, -20, -21, -22, -21, -17, -20, -21, + -22, -19, -19, -11, -4, -2, -2, -2, 2, 5, 2, 0, 0, -3, 1, 8, + 16, 13, 14, 17, 15, 13, 8, 5, -1, -6, -10, -13, -14, -14, -13, -10, + -7, -8, -8, -6, -6, -3, -1, -1, -9, -12, -7, 3, 13, 17, 14, 13, + 17, 22, 23, 24, 18, 15, 18, 18, 18, 15, 8, 0, -5, -8, -11, -15, + -17, -21, -26, -26, -24, -26, -24, -13, -9, -6, -3, -2, 3, 4, 6, 7, + 5, 2, 4, 2, -2, -4, -3, 5, 13, 17, 10, 3, -1, -2, -4, -5, + -11, -14, -13, -11, -8, -8, -8, -6, -3, 0, -1, -5, -5, 0, 4, 3, + 1, 2, 0, 0, 6, 13, 20, 17, 17, 18, 21, 18, 14, 13, 11, 11, + 7, 9, 3, -5, -12, -14, -18, -21, -23, -26, -26, -13, -3, -6, -13, -14, + -5, 5, 8, 3, 0, 1, 3, 6, 4, -1, -1, 1, 3, 7, 5, 3, + 0, 1, -1, 3, 0, -3, -11, -11, -9, -10, -9, -8, -5, -7, -7, -10, + -9, -6, -1, 4, 6, 4, 2, 5, 10, 13, 9, 12, 13, 14, 15, 16, + 13, 12, 10, 13, 14, 13, 8, 2, -1, -4, -6, -9, -15, -20, -21, -19, + -14, -16, -22, -21, -13, -5, -3, -3, -1, 3, 5, 10, 9, 9, 6, 8, + 7, 7, 7, 3, -4, -6, -4, -1, -4, -8, -10, -11, -8, -4, -6, -10, + -7, -8, -11, -11, -8, -5, -4, 0, 3, 3, 8, 10, 10, 12, 12, 11, + 10, 13, 12, 10, 6, 8, 9, 9, 11, 13, 11, 9, 10, 7, 2, -3, + -8, -9, -14, -16, -16, -19, -18, -14, -13, -11, -11, -10, -5, -1, 3, 5, + 2, 2, 9, 14, 11, 9, 10, 7, 2, 0, 2, -2, -9, -13, -15, -18, + -17, -15, -13, -10, -5, -5, -7, -7, -4, -1, 0, -2, -4, -2, 1, 4, + 9, 10, 10, 11, 11, 13, 14, 10, 11, 9, 9, 4, 6, 5, 4, 5, + 7, 8, 10, 9, 4, -4, -8, -9, -10, -11, -12, -14, -15, -17, -15, -9, + -4, -1, -6, -5, 2, 8, 8, 6, 5, 3, 4, 5, 9, 10, 10, 5, + -1, -5, -10, -12, -14, -16, -18, -17, -11, -10, -11, -8, -5, -2, -2, 0, + 3, 4, 5, 3, 2, 3, 5, 9, 12, 12, 11, 10, 12, 14, 12, 8, + 5, 0, -1, 1, 3, 0, 1, 3, 5, 6, 5, 0, -5, -11, -10, -13, + -12, -13, -15, -14, -8, -4, -3, -3, -4, 0, 4, 5, 3, 6, 4, 4, + 7, 10, 9, 9, 8, 5, 5, 2, -4, -10, -15, -17, -20, -22, -22, -19, + -14, -11, -10, -8, -6, 0, 3, 5, 3, 4, 8, 11, 11, 12, 13, 12, + 12, 15, 15, 16, 16, 13, 11, 6, 3, -2, -5, -5, -3, -2, -1, 2, + 0, -3, -4, -5, -7, -10, -12, -11, -12, -11, -8, -4, -2, 0, 1, 2, + 2, 2, 4, 3, 3, 4, 5, 9, 10, 6, 2, 1, 2, 0, -3, -7, + -13, -18, -19, -18, -16, -18, -20, -19, -14, -8, -4, -1, 3, 3, 5, 7, + 9, 9, 10, 12, 13, 13, 13, 13, 16, 15, 13, 9, 6, 3, 2, 1, + 0, -3, -5, -6, -4, -2, -2, -4, -4, -5, -5, -3, -3, -4, -6, -6, + -7, -4, 0, 2, 3, 2, 2, 1, 2, 2, 1, 4, 5, 4, 1, 0, + 2, 2, 0, -2, -6, -8, -6, -7, -9, -11, -15, -18, -19, -18, -18, -17, + -13, -9, -2, 2, 3, 5, 10, 12, 13, 14, 14, 15, 17, 17, 16, 16, + 15, 13, 11, 7, 2, -6, -10, -8, -6, -8, -8, -7, -6, -6, -3, -4, + -6, -5, -3, -2, -2, 0, 1, 0, 2, 2, 3, 2, 3, 2, 3, 3, + 5, 2, 0, 4, 6, 5, -1, -4, -2, -1, -2, -6, -8, -9, -10, -12, + -10, -14, -17, -22, -22, -21, -19, -15, -8, -3, 1, 7, 12, 12, 15, 19, + 22, 21, 18, 16, 16, 16, 13, 12, 6, 3, 3, 2, -3, -6, -7, -12, + -12, -11, -8, -9, -8, -7, -3, 0, 0, 0, 0, -2, -2, 0, 1, 2, + 2, 4, 6, 6, 7, 5, 4, 3, 4, 5, 3, 0, -2, -2, -4, -6, + -10, -8, -8, -10, -11, -12, -12, -12, -13, -16, -16, -16, -14, -11, -8, -4, + -2, 1, 6, 12, 17, 19, 20, 20, 21, 21, 19, 13, 10, 9, 5, 0, + -3, -4, -4, -5, -6, -6, -4, -7, -10, -12, -12, -12, -10, -7, -4, -2, + 4, 6, 8, 7, 7, 7, 7, 8, 8, 7, 5, 6, 6, 4, 1, -1, + -1, 0, -3, -7, -10, -10, -8, -11, -14, -14, -12, -11, -9, -6, -8, -8, + -8, -11, -13, -12, -9, -8, -5, 0, 4, 8, 11, 14, 18, 18, 20, 23, + 23, 20, 14, 9, 4, 0, -3, -6, -8, -8, -8, -8, -9, -10, -11, -10, + -9, -8, -8, -7, -6, -3, 0, 3, 6, 12, 16, 16, 14, 10, 8, 9, + 7, 4, 1, 0, 0, -2, -1, 0, 0, -3, -7, -10, -13, -13, -12, -13, + -15, -14, -13, -9, -6, -5, -5, -7, -8, -9, -7, -6, -5, -7, -5, 1, + 8, 13, 17, 19, 20, 21, 22, 22, 18, 12, 9, 5, -1, -5, -9, -11, + -13, -12, -12, -11, -10, -8, -7, -7, -6, -7, -6, -3, 0, 1, 3, 7, + 10, 11, 12, 15, 15, 14, 9, 6, 3, 1, 0, -2, -2, -2, -3, -6, + -8, -10, -11, -13, -15, -15, -15, -13, -12, -12, -7, -5, -5, -5, -4, -3, + -3, -4, -4, -1, -1, 1, 4, 7, 10, 12, 14, 17, 20, 22, 19, 14, + 8, 5, 2, -2, -5, -10, -14, -13, -11, -10, -10, -10, -10, -8, -6, -3, + -3, -3, -1, -1, 2, 6, 10, 13, 14, 15, 15, 15, 13, 11, 8, 5, + 1, -1, -3, -3, -6, -10, -12, -12, -12, -12, -13, -15, -18, -19, -15, -11, + -6, -4, -3, -4, -4, -2, 1, 4, 2, -1, -2, 1, 4, 6, 8, 7, + 7, 11, 14, 15, 15, 15, 13, 10, 6, 1, -3, -6, -9, -13, -15, -15, + -13, -11, -9, -9, -9, -7, -3, 0, 2, 2, 4, 7, 11, 15, 16, 14, + 11, 12, 13, 15, 13, 9, 4, 1, -1, -4, -6, -8, -11, -15, -17, -17, + -17, -17, -15, -13, -13, -12, -10, -7, -6, -4, 1, 2, 2, 3, 4, 5, + 4, 4, 3, 5, 6, 6, 8, 7, 7, 9, 11, 10, 9, 8, 5, 2, + 0, -2, -6, -10, -13, -13, -14, -14, -13, -11, -9, -4, -1, -1, -1, 2, + 6, 8, 10, 11, 12, 14, 14, 14, 13, 11, 10, 7, 4, 2, 3, 1, + -3, -6, -10, -14, -17, -18, -18, -19, -19, -17, -15, -13, -9, -5, -1, 1, + 0, 1, 3, 5, 6, 6, 6, 7, 8, 9, 8, 4, 1, 0, 2, 4, + 5, 6, 5, 4, 4, 4, 3, 1, -3, -7, -9, -11, -12, -12, -12, -11, + -10, -7, -4, -2, 1, 4, 5, 8, 11, 13, 14, 14, 11, 11, 11, 10, + 10, 9, 6, 5, 3, 1, -2, -5, -10, -14, -16, -17, -18, -19, -20, -19, + -17, -14, -10, -5, -1, 1, 3, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 8, 7, 6, 4, 2, 0, -1, 0, 0, 1, 2, 1, 1, 2, 1, -2, + -5, -8, -9, -10, -11, -12, -12, -10, -7, -4, -1, 2, 8, 11, 13, 15, + 15, 13, 12, 11, 10, 9, 8, 6, 5, 4, 4, 3, 0, -3, -6, -10, + -14, -18, -21, -22, -21, -18, -16, -13, -10, -6, -3, 0, 3, 5, 5, 5, + 6, 7, 8, 8, 8, 7, 8, 7, 6, 5, 4, 1, 0, -2, -4, -4, + -5, -4, -4, -3, -2, -1, -2, -3, -4, -7, -8, -9, -9, -9, -8, -5, + -2, 2, 4, 8, 11, 14, 15, 15, 14, 12, 10, 7, 5, 4, 4, 2, + 1, 1, 2, -1, -3, -7, -10, -15, -18, -18, -18, -18, -17, -15, -11, -7, + -3, 1, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 10, 9, 6, 4, + 2, 0, -3, -4, -6, -7, -7, -6, -5, -3, -2, -2, -2, -2, -3, -4, + -5, -6, -6, -6, -6, -5, -4, -1, 4, 7, 9, 11, 12, 12, 11, 10, + 9, 8, 7, 5, 3, 3, 2, 1, 0, -1, -4, -7, -8, -10, -13, -14, + -15, -15, -15, -14, -11, -9, -6, -3, 0, 2, 4, 5, 6, 7, 8, 9, + 10, 10, 9, 8, 6, 5, 3, 1, -3, -6, -8, -8, -7, -7, -7, -6, + -4, -2, 0, -1, -2, -3, -3, -3, -3, -4, -3, -3, -1, 1, 3, 4, + 6, 7, 8, 9, 10, 10, 9, 7, 6, 6, 4, 3, 2, 1, -1, -2, + -4, -6, -9, -11, -12, -12, -12, -11, -11, -10, -9, -8, -7, -5, -4, -1, + 1, 3, 5, 7, 9, 10, 11, 10, 9, 8, 7, 6, 2, -1, -3, -4, + -6, -7, -7, -7, -7, -6, -5, -5, -4, -3, -3, -4, -4, -4, -3, -2, + 0, 0, 1, 1, 2, 4, 6, 6, 7, 7, 8, 7, 7, 7, 7, 7, + 6, 5, 2, 0, -2, -4, -5, -7, -8, -8, -8, -9, -10, -10, -9, -8, + -7, -7, -7, -5, -3, -2, 0, 1, 2, 4, 6, 9, 10, 11, 12, 10, + 8, 6, 3, 1, -2, -4, -6, -7, -7, -7, -7, -8, -7, -7, -6, -6, + -5, -4, -3, -3, -2, -1, 1, 2, 2, 3, 4, 5, 5, 5, 6, 6, + 6, 5, 5, 6, 6, 6, 4, 3, 2, 1, -1, -3, -4, -6, -8, -9, + -9, -8, -8, -6, -5, -5, -5, -6, -6, -6, -5, -4, -2, 0, 2, 4, + 6, 7, 8, 9, 9, 9, 9, 6, 4, 1, -1, -3, -5, -6, -7, -7, + -7, -6, -6, -6, -6, -6, -5, -4, -3, -3, -2, -1, 1, 3, 4, 5, + 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, + -1, -3, -4, -5, -6, -7, -7, -7, -7, -7, -6, -5, -4, -4, -3, -3, + -3, -3, -2, -1, 0, 1, 3, 5, 7, 8, 8, 8, 7, 6, 4, 2, + 0, -2, -3, -4, -5, -6, -7, -7, -7, -7, -6, -6, -5, -5, -5, -3, + -2, 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 5, 4, 3, 3, 3, + 3, 3, 3, 2, 1, 1, -1, -2, -3, -4, -5, -6, -6, -7, -6, -5, + -4, -3, -3, -3, -3, -3, -2, -1, -1, 0, 1, 1, 1, 2, 3, 5, + 6, 6, 6, 5, 4, 2, 1, 0, -2, -4, -5, -5, -6, -6, -6, -7, + -7, -7, -6, -5, -4, -3, -2, -1, 0, 2, 3, 3, 4, 4, 5, 5, + 5, 4, 4, 4, 4, 3, 3, 2, 1, 1, 0, 0, -1, -1, -2, -3, + -4, -5, -5, -5, -5, -5, -4, -4, -3, -3, -2, -1, -1, -1, -1, 0, + 0, 0, 1, 2, 3, 3, 4, 4, 4, 4, 4, 3, 1, 0, 0, -2, + -3, -4, -5, -5, -6, -6, -6, -5, -4, -4, -4, -3, -2, -2, -1, 0, + 2, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, + 0, -1, -1, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -2, -2, + -2, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 1, 1, 0, 0, -1, -1, -2, -3, -3, -3, -4, -4, -4, -4, -3, + -3, -2, -1, -1, -1, 0, 1, 1, 1, 2, 2, 2, 3, 3, 2, 2, + 1, 1, 1, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -5, -41, -25, -37, -9, 28, 14, 6, 1, + 19, 16, -83, -53, -35, -44, -29, 8, -23, -29, -6, -20, -22, -19, -40, -2, + 14, 34, 78, 59, 73, 93, 73, 83, 124, 94, 87, 61, 98, 80, 29, 27, + 6, 8, -9, -8, -26, -33, -35, -32, -25, -32, -28, -59, -46, -31, -19, -12, + -12, 14, 14, -41, -59, -46, -33, -32, -52, -31, -29, -49, -51, -53, -85, -53, + -60, -100, -85, -84, -66, -37, -26, -11, -8, 22, 41, 33, 39, 27, 29, 75, + 59, 45, 52, 69, 66, 73, 90, 91, 103, 81, 46, 16, -21, -32, -13, -34, + -22, -42, -51, -35, -53, -62, -45, -35, -34, -29, 25, 62, 61, 39, -8, -20, + -5, -7, 2, 28, 1, -24, 8, 29, 11, -9, -54, -34, -35, -57, -41, -63, + -50, -16, -18, 26, 23, -2, 38, 9, 17, 41, 39, 82, 64, 64, 103, 64, + 43, 43, 51, 26, -3, 30, 1, 9, 14, -26, 20, -27, -50, -39, -47, -31, + -23, -33, 25, 56, 51, 20, -19, -60, -41, -27, -10, 3, -36, -30, -22, -46, + -5, -12, -7, -4, -54, 3, -25, -10, -1, -42, -75, -27, -84, -60, -88, -107, + -73, -29, -67, -53, 9, -10, 17, -29, -33, 55, 12, 7, 121, 70, 42, 123, + 96, 127, 74, 28, 51, 21, 60, 23, -10, 25, 103, 113, 65, 45, 15, -1, + 10, 2, -26, 1, -16, 19, 27, -8, -8, -24, -20, -17, -35, -86, -87, -32, + -51, -26, -60, -60, -50, -15, -31, -30, -50, -55, -19, 22, 14, 30, 49, 42, + 15, -11, -57, -15, -29, -65, -37, -56, -29, 15, 70, 69, 36, 24, 19, 21, + 19, 4, 60, 55, 18, -17, 0, -2, -21, 51, 49, -6, 22, 14, -24, -63, + -5, 4, -53, -33, -1, -37, -34, 40, 30, 12, -6, -1, 12, 12, 23, 20, + 43, 34, 11, -26, -40, 25, 56, -1, -41, -50, -37, -10, 20, -58, -65, -43, + -26, 42, 57, 77, 57, 26, -4, -10, -57, -45, -23, -49, -1, -59, -41, -26, + -27, 24, 52, -3, -12, 19, -44, -31, 33, 11, -14, 43, 31, 7, 58, 84, + 45, 35, 18, -5, 6, -21, -6, -20, -7, 41, 53, 29, 25, 55, 68, 37, + -29, -17, -41, -67, -76, -90, -112, -104, -60, -21, 25, 16, -23, -9, 30, 47, + 17, 3, 19, 4, -2, 30, 24, 1, 26, 33, 34, 10, 14, 1, -5, 16, + -2, -60, -32, -51, -48, -38, -34, -42, -20, 16, 17, -16, -32, -6, 4, -39, + -18, 1, -20, -22, 55, 70, 34, 5, -1, 13, 2, 1, 28, 20, -31, -2, + 51, 26, 24, 19, 11, -1, 2, 30, 13, 2, 70, 36, 15, 24, 5, 9, + 14, 48, 43, 8, 2, -10, 18, 33, 22, -27, -19, -17, -22, 11, 19, -5, + 0, -55, -60, -49, -63, -72, -45, -80, -55, -18, -8, 32, 52, 22, 0, -40, + -42, -30, -68, -51, -9, -67, -52, -10, 7, 35, 12, 36, 64, 23, 13, 64, + 39, 32, 73, 3, 6, -10, -6, 16, 18, 53, 51, 21, -20, -15, 13, -3, + 2, -39, -30, -7, -3, 6, 10, -4, -25, -7, -10, -10, -18, -31, -23, -38, + -48, -3, -26, -43, -7, 11, 31, 62, 41, -7, -34, -42, -24, 17, 12, 44, + 25, 24, 18, 11, 32, 51, 46, 46, 51, 33, 24, 32, 30, 40, 8, -30, + -39, -30, -44, -19, -33, -55, -41, -36, -70, -67, -64, -34, -37, -46, 1, 19, + 27, 81, 23, 13, 10, -5, -18, -19, -51, -14, -48, -75, 11, 51, 43, 63, + 37, 20, 19, 4, -23, 27, 47, 71, 29, 16, 15, -17, -11, 32, 40, 22, + 6, 16, -7, 5, 34, 61, 12, -21, -24, -13, -38, -41, -36, -33, 2, 9, + -45, -54, -36, 12, -18, -41, -25, -18, 19, 31, -11, -16, -22, -62, -65, -68, + -42, -4, -48, -49, 4, 38, 65, 47, 12, -20, -20, -8, 3, 32, 69, 84, + 44, 28, 31, 18, 36, 57, 74, 35, 19, 6, 24, 29, 36, 35, 6, -13, + -25, -43, -45, -35, -33, -44, -23, -41, -57, -52, -41, -35, -21, -16, -22, -11, + 33, 42, 14, 19, 16, 0, -6, -34, -17, -37, -25, -7, 6, 48, 47, 3, + -14, -17, -19, -11, -9, -11, 42, 42, 16, 1, 6, 15, 51, 42, 33, 29, + 20, -5, -3, 4, 54, 42, 8, -30, -19, -15, -15, -20, -6, -7, -24, -32, + -24, -17, -1, -16, -18, -36, -55, -38, -2, 8, 16, 7, -21, -35, -56, -67, + -17, -58, -67, -36, 21, 67, 48, 15, 8, 13, -9, -8, -1, 21, 107, 56, + 40, 56, 32, 33, 71, 60, 36, 30, 3, 31, 15, 4, 21, 2, -2, -25, + -30, -26, -13, -9, -26, -20, -34, -34, -51, -28, 6, -9, -24, -49, -67, -54, + -54, -52, -41, -42, -58, -37, 16, 39, 31, 16, 19, 11, -4, -23, -5, 24, + 1, 10, 24, 26, 15, 34, 70, 77, 56, 33, 43, 28, 17, 25, 12, 2, + 0, -12, -15, -2, 10, -19, -28, -45, -41, -28, -17, -3, -2, -9, -3, -25, + -45, -14, 23, 10, -5, -19, -32, -22, -10, -1, -15, -16, -6, 13, 48, 70, + 55, 23, 23, 10, -8, -14, 6, 8, -12, -5, 13, 10, -14, 0, 33, 23, + 18, 43, 21, 26, 33, 13, -14, -7, -3, -31, -29, -5, -5, -25, -27, -35, + -56, -45, -21, -17, -40, -14, 2, -23, -38, -9, 8, -16, -16, -7, -13, -25, + -4, -12, -21, -14, 3, 13, 44, 65, 60, 40, 15, 5, -20, -22, -3, 3, + 20, 39, 39, 9, 6, 21, 48, 24, 25, 25, 11, 0, 4, -5, -31, -34, + -22, -45, -40, -24, -24, -41, -38, -47, -54, -45, -16, -22, -32, -7, 16, -1, + -11, 23, 31, -1, -10, -20, -19, -9, 15, -10, -28, -21, 4, 24, 45, 60, + 56, 46, 30, 26, 23, 36, 48, 33, 46, 40, 34, 19, 12, 23, 43, 37, + 41, 43, 22, 24, 11, -11, -2, -5, 8, -28, -33, -11, -5, -26, -30, -25, + -45, -21, -8, -26, -35, -37, -39, -54, -56, -20, -23, -42, -52, -49, -63, -47, + -31, -29, -16, -21, -7, 14, 26, 48, 32, 12, -10, -22, -24, -6, 0, 33, + 44, 31, 25, 15, 10, 34, 48, 38, 14, 9, 16, 12, -23, -15, -15, -8, + -9, -19, -22, -2, -8, -10, -32, -27, 4, 12, -5, 1, -1, 4, -5, -3, + -5, 10, 37, 18, -8, -19, -3, 0, -10, -5, -31, -32, -29, -2, 18, 32, + 33, 14, -12, -15, 6, 8, 36, 66, 48, 38, 37, 42, 29, 49, 50, 42, + 28, 25, 33, 15, 2, 4, 2, 4, 2, -11, -1, 6, 3, 9, -14, -12, + -5, -12, -33, -36, -29, -26, -38, -44, -42, -38, -38, -52, -67, -70, -50, -32, + -27, -29, -38, -26, -27, 1, 21, 23, 16, -17, -34, -26, -18, -20, 2, 11, + 13, 5, 10, 13, 12, 28, 33, 35, 14, 14, 14, -8, -24, -25, -8, -16, + -23, -14, 12, 8, 21, 25, 13, 25, 29, 25, 6, 3, 36, 26, 34, 11, + 30, 29, 34, 23, 0, 1, 7, 8, 1, -10, -9, -13, 5, 17, 30, 26, + 25, 3, -11, -4, -4, 9, 13, 17, 6, 4, 17, -1, -4, 9, 16, 22, + 3, -2, -4, -16, -28, -22, -13, -34, -37, -31, -9, -7, -12, -16, -26, -12, + -14, -11, -23, -16, -24, -33, -24, -30, -17, -28, -34, -44, -51, -34, -24, -22, + -25, -2, 14, 23, 38, 46, 43, 28, 10, -6, -11, 1, 0, 5, 18, 16, + -3, 12, 27, 23, 32, 48, 42, 34, 21, 21, 10, -3, -10, -10, -20, -38, + -34, -29, -22, -16, -15, -17, -9, 7, 6, 6, -6, 1, 7, 6, 3, 11, + 30, 30, 15, 11, 11, 10, 17, 22, 23, 24, 9, 15, 5, -2, 4, 3, + -17, -21, -4, -21, -6, 8, -9, -1, 0, 8, -7, -18, -16, -3, -14, -13, + -8, -17, -10, -8, -26, -37, -28, -17, -35, -17, -10, 1, -6, 1, 25, 32, + 26, 9, -18, -19, 1, -12, -20, 2, 12, 5, -4, 15, 14, 15, 15, 17, + 14, 2, 6, 3, -18, -21, -9, -1, -15, -11, -15, -22, -1, 3, -7, 0, + 14, 14, -4, -13, 4, 18, 12, 15, 19, 25, 28, 27, 12, 9, 9, -10, + -17, -4, -5, -4, -20, -19, 11, 20, 13, 0, -19, -8, 6, -9, 6, 26, + 18, 14, 17, 22, 24, 18, 21, 37, 20, 7, 11, -8, -11, -4, -3, -8, + -22, -16, -18, -15, -4, -9, -21, -10, 5, -8, -7, -17, -7, -9, -20, -28, + -35, -31, -23, -23, -29, -28, -28, -33, -28, -24, -6, 0, -4, 7, 29, 25, + 15, -6, -19, 1, -2, -22, 4, 10, 1, 9, 10, 13, 4, 6, 21, 15, + 5, 21, 11, -18, -21, -15, -3, -4, -15, -15, -19, 4, 19, 11, 2, 17, + 16, 2, 14, 14, 17, 20, 22, 20, 10, 16, 27, 12, 8, 11, 5, -9, + -10, -6, -1, -7, -12, -3, 3, 8, 9, -5, -3, 6, -5, -6, 23, 14, + 11, 12, 21, 21, 4, 18, 30, 7, 12, 25, 3, -11, -16, -15, -10, -13, + -8, -6, -21, 2, -2, -25, -18, -8, -22, -22, -17, -12, -7, -12, -15, -20, + -41, -28, -24, -23, -12, -12, -15, -10, -7, 2, 1, 6, 18, 29, 23, 21, + 20, 9, -3, -9, -9, -10, -15, -8, -11, -2, 6, 14, 7, 7, 11, 9, + 14, 2, 3, 7, 6, 6, -21, -20, -10, -12, -15, -16, -18, -14, -11, -14, + 0, 0, -5, 3, 14, 12, 9, 0, -11, 5, 5, 12, 11, -1, 5, 3, + 1, 4, -1, -1, 13, 16, 8, 14, 9, -2, -7, -11, -17, -12, -5, -9, + -10, -13, -4, 1, 0, 4, 5, 0, 2, 3, 5, 14, 18, 9, -3, 2, + 15, 14, 6, 2, 1, -1, -5, -6, 0, 0, 0, 7, 20, 22, 23, 13, + 13, 17, 20, 35, 25, 20, 20, 14, 17, 16, 3, 7, 18, 15, 13, 17, + 6, -5, -6, -13, -23, -19, -19, -22, -22, -24, -17, -18, -22, -27, -31, -30, + -29, -30, -33, -36, -34, -37, -47, -38, -24, -28, -27, -31, -30, -28, -26, -20, + -14, -14, -9, 4, 17, 21, 15, 12, 25, 29, 33, 33, 30, 30, 31, 19, + 20, 14, 4, 10, 17, 18, 21, 28, 19, 20, 20, 5, -2, -3, -7, -10, + -2, 1, 4, 6, 4, 5, 3, 2, -1, -4, -7, -10, -3, -6, -16, -5, + -1, -8, -7, -6, -9, -10, -11, -7, -6, -10, -11, 2, 11, 7, 1, 6, + 12, 16, 18, 15, 11, 14, 16, 9, 11, 6, 5, 13, 14, 13, 11, 0, + -11, -4, -4, -8, -7, -5, -6, -3, -1, 2, -1, -6, -7, -9, -9, -9, + -15, -11, -14, -17, -16, -18, -17, -12, -7, -8, -7, -6, -2, -3, -12, -15, + -15, -18, -13, -19, -23, -24, -21, -21, -13, -12, -7, -3, -7, -6, -4, 2, + 1, 1, 3, 9, 23, 28, 23, 17, 24, 27, 22, 19, 16, 19, 10, 9, + 10, 10, 19, 8, 11, 16, 15, 11, 13, 14, 7, 5, -3, -7, -12, -15, + -16, -17, -10, -5, 4, -2, -2, -9, -13, -9, -8, -10, -10, -12, -5, 3, + 7, 3, 9, 3, 4, -1, -2, 2, -4, -9, -4, 0, 4, 4, -6, -3, + 12, 10, 15, 12, 7, 7, 1, -1, 8, 11, 9, 9, 13, 17, 17, 9, + 11, 4, 0, -3, -6, -8, -9, -10, -17, -20, -24, -17, -19, -22, -20, -21, + -15, -16, -19, -23, -21, -28, -26, -15, -14, -4, -1, -6, -3, -1, 4, 9, + 2, 4, 7, 7, 11, 15, 6, 17, 24, 16, 15, 9, 6, 6, 3, 1, + 3, 2, -2, 6, 6, 6, 3, -6, -3, -8, -7, -10, -13, -17, -18, -16, + -19, -13, -9, -3, 4, 10, 7, 7, 12, 11, 13, 10, 6, 1, 2, 4, + 4, 10, 10, 7, 4, 1, 4, -5, -12, -3, 1, 10, 7, 6, 4, 19, + 22, 20, 23, 16, 15, 19, 17, 14, 9, 7, 4, 4, 2, 5, 3, 0, + 0, -7, -7, -8, -7, -14, -15, -18, -25, -21, -21, -16, -13, -14, -17, -18, + -23, -21, -23, -29, -32, -33, -30, -23, -13, -11, -10, -8, -7, -2, 1, -3, + -1, 5, 13, 17, 13, 11, 13, 16, 14, 10, 11, 8, 16, 13, 4, 0, + 7, 13, 14, 15, 15, 17, 17, 9, 8, 9, 9, 2, 5, 11, 14, 7, + 4, 11, 10, 5, 7, 2, -1, -4, -9, -16, -15, -12, -9, -15, -23, -21, + -22, -22, -20, -22, -22, -21, -22, -22, -13, -6, 4, 2, -2, 2, 7, 6, + 10, 8, 9, 12, 21, 16, 11, 7, 11, 13, 11, 10, 11, 13, 9, 6, + 6, 5, 4, -5, 1, 4, 5, -1, -2, 6, 3, 3, -3, -10, -14, -14, + -14, -16, -8, -6, -1, -6, -7, -5, -7, -6, -9, -8, -8, -4, -5, -8, + -6, 3, 12, 4, -2, 3, 1, 1, -1, -4, -4, 5, 6, 1, -4, -3, + 5, 9, 8, 18, 20, 22, 15, 11, 11, 15, 12, 9, 11, 11, 11, 5, + 10, 12, 5, 3, -2, -4, -9, -9, -16, -17, -14, -12, -14, -20, -15, -16, + -17, -17, -19, -20, -19, -15, -17, -15, -13, -2, -3, -13, -8, 0, 4, 7, + 6, 4, 11, 13, 14, 11, 5, 6, 3, -1, -2, 2, 3, -1, -2, -6, + -4, -1, -3, 0, 3, 1, -2, -5, -5, -3, -6, -9, -7, -15, -13, -10, + -8, -4, 1, 9, 7, 2, 8, 8, 9, 12, 14, 7, 12, 12, 12, 8, + 14, 19, 11, 7, 10, 13, 10, 2, -2, -6, -1, 2, 6, 3, 1, 4, + 2, 2, 5, 8, 8, 7, 7, 2, 0, -3, -6, -3, -1, -6, -12, -9, + -6, -7, -9, -10, -14, -16, -12, -12, -11, -13, -16, -16, -20, -18, -14, -10, + -8, -9, -13, -9, -8, -9, -7, -9, -8, -3, -4, -3, -6, 0, 2, 3, + -3, 2, 5, 1, 6, 5, 5, 10, 11, 17, 15, 20, 25, 20, 15, 17, + 13, 12, 11, 7, 4, -1, -2, 6, 7, 7, 9, 10, 7, 9, 7, 5, + 5, 1, -6, -2, -5, -6, -3, -3, -1, -3, -5, -3, -6, -8, -7, -8, + -11, -12, -16, -19, -19, -14, -14, -17, -17, -11, -12, -15, -6, -8, -12, -12, + -9, -7, -6, 2, 9, 6, 8, 11, 13, 15, 14, 11, 7, 3, 3, 4, + 7, 9, 10, 6, 6, 5, 7, 11, 11, 4, 1, 1, -3, -5, -1, -1, + -1, -5, -2, -1, -1, 1, 1, -3, -7, -7, -9, -12, -11, -3, -3, -7, + -6, -6, -5, -5, 0, -3, -4, -2, 2, -1, 0, 6, 7, 7, 4, 3, + 5, -1, 0, -1, -7, -9, -8, -11, -5, 0, -1, 0, 2, 2, 5, 10, + 10, 7, 7, 7, 8, 8, 9, 11, 9, 8, 9, 6, 4, 2, 0, -3, + -5, -8, -8, -12, -8, -1, -4, -4, -5, -7, -9, -6, -5, -6, -8, -6, + -3, -7, 0, 5, 6, 3, 1, 6, 6, 4, 3, 1, -2, -4, -6, -4, + 3, 7, 3, 0, -1, -3, -2, -1, -2, -5, -8, -9, -7, -9, -8, -6, + -9, -7, -9, -7, -6, -7, -6, -7, -7, -7, -7, -8, -2, 1, 2, 4, + 3, 5, 6, 10, 11, 9, 10, 12, 9, 9, 11, 9, 10, 8, 7, 7, + 6, 7, 5, 4, 5, 4, -1, -4, -3, -5, -1, -2, -4, -4, -4, -4, + -2, -2, -3, -4, -2, -1, 0, 1, 8, 8, 4, 4, 4, 2, -2, -3, + -5, -6, -9, -10, -8, -5, 2, 1, -2, -2, -2, -2, -2, -5, -5, -7, + -7, -3, -4, -6, -4, -3, -5, -7, -5, -4, -7, -9, -6, -6, -9, -7, + -6, -2, 3, 3, 4, 5, 3, 4, 5, 2, 0, 2, 3, 2, 5, 7, + 10, 9, 7, 7, 6, 4, 1, -2, -5, -6, -10, -10, -8, 2, 8, 7, + 6, 7, 5, 5, 7, 6, 3, 4, 3, 4, 1, 3, 2, 4, 2, 1, + 1, -1, -3, -3, -4, -6, -9, -9, -9, -7, -6, -5, -5, -4, -5, -2, + -1, -2, -3, -1, -1, -3, -2, 2, 2, 3, 4, 4, 2, 0, -1, -3, + -4, -4, -5, -7, -2, 2, 2, -1, -3, -1, -4, -3, -2, -4, -4, -2, + -1, -2, -4, -2, -2, -1, -2, -2, -2, -3, -2, 0, 2, 0, -2, -2, + 0, 2, 3, 5, 4, 4, 4, 6, 3, 1, 0, 0, 0, 0, 5, 5, + 4, 6, 4, 2, 0, -2, -3, -6, -9, -8, -10, -10, -2, 3, 4, 4, + 4, 5, 4, 4, 5, 4, 4, 4, 4, 2, 3, 2, 2, 2, 1, 1, + 0, -2, -3, -3, -4, -6, -8, -7, -4, -6, -3, -3, -3, -2, 1, 0, + -1, -2, -2, -1, -1, 0, 1, 0, 0, 1, 0, 0, 0, -1, -2, -3, + -3, -4, -5, -4, -3, -3, -3, -3, -3, -3, -2, -1, 0, -1, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 2, 3, + 3, 2, 2, 0, -1, -1, -2, -3, -3, -4, -5, -4, 0, 3, 3, 3, + 3, 2, 3, 4, 6, 4, 4, 3, 2, 1, 2, 1, 0, 0, -1, -2, + -3, -3, -2, -2, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, + -2, -3, -2, -3, -2, -2, 0, 0, 0, 0, 0, -1, -1, -2, -2, -3, + -2, -4, -4, -3, 0, -1, 0, 0, 0, 0, 0, 1, 2, 1, 1, 1, + 0, 0, 0, -1, 0, -1, -1, -1, -1, -1, 0, 0, -1, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, + 0, 0, -1, -1, -2, -2, -2, -2, -2, -3, -3, -1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, -8, -33, -24, -25, -25, -26, -27, + -32, -28, -36, -31, -36, -22, -34, 11, -74, -14, 94, 41, 28, 33, 30, 40, + 34, 23, 41, 40, 60, 56, 59, 60, 44, 39, 54, 45, 52, 17, 44, 62, + 34, 33, 19, 18, 43, 35, 22, 36, -15, -10, 32, -7, -12, -6, -8, -50, + -47, -44, -4, -25, -48, -76, -58, -75, -96, -85, -118, -114, -63, -106, -103, -83, + -110, -99, -84, -76, -58, -63, -61, -51, -53, -36, -32, -41, -27, -11, 11, 8, + 27, 19, 30, 35, 28, 57, 53, 38, 71, 51, 68, 110, 78, 89, 109, 97, + 82, 94, 115, 114, 79, 70, 79, 94, 85, 76, 84, 95, 83, 82, 55, 54, + 54, 41, 41, 27, 20, 6, -11, -21, -16, -14, -33, -33, -52, -54, -59, -62, + -71, -79, -88, -88, -78, -78, -72, -71, -94, -99, -93, -90, -78, -87, -105, -103, + -79, -62, -71, -78, -63, -61, -66, -49, -23, -10, -11, -24, -20, -4, -22, 9, + 8, 27, 43, 34, 38, 51, 83, 65, 58, 74, 75, 70, 73, 71, 65, 100, + 89, 94, 65, 84, 49, 49, 61, 54, 43, 51, 58, 53, 35, 40, 36, 38, + 34, 23, 14, -12, -10, -1, -1, -11, -12, -19, -33, -66, -52, -42, -37, -55, + -42, -28, -32, -29, -35, -41, -28, -25, -46, -85, -64, -62, -55, -49, -68, -55, + -53, -52, -47, -43, -26, -32, -41, -34, -35, -40, -26, -8, -1, -6, -11, 5, + -2, 8, 3, 8, 6, 4, 20, 29, 43, 24, 33, 20, 30, 24, 39, 38, + 40, 29, 37, 36, 39, 61, 58, 41, 51, 59, 51, 55, 58, 48, 32, 45, + 40, 27, 30, 41, 44, 26, 19, 23, -3, 7, 0, -3, 2, 3, -6, -5, + -14, -6, -10, -27, -45, -47, -41, -38, -50, -51, -46, -43, -45, -65, -65, -80, + -95, -82, -74, -66, -69, -67, -33, -31, -53, -48, -51, -43, -18, -24, -24, -33, + -26, -10, 0, -17, -6, 17, 31, 2, 23, 45, 46, 12, 75, 38, 63, 69, + 31, 38, 80, 57, 48, 59, 81, 74, 32, 52, 72, 24, 60, 44, 55, 40, + 28, 48, 33, 24, 10, -2, 21, 34, 13, 18, 7, -1, -12, -20, -18, -30, + -9, -7, -30, -27, -26, -38, -20, -54, -55, -64, -53, -36, -62, -37, -71, -47, + -42, -71, -45, -55, -50, -54, -56, -36, -37, -54, -36, -12, -38, -33, -26, -7, + -22, -44, -10, 2, 3, 15, 8, 18, 6, 12, 8, 15, 28, 22, 50, 35, + 55, 42, 36, 49, 52, 64, 48, 60, 49, 60, 62, 40, 47, 68, 52, 59, + 61, 44, 53, 44, 35, 31, 31, 47, 22, 6, 4, -7, 5, -4, -21, -13, + -9, -10, -27, -46, -32, -44, -46, -62, -44, -51, -67, -53, -59, -63, -74, -67, + -61, -61, -65, -47, -58, -57, -45, -41, -46, -41, -38, -22, -25, -34, -16, -10, + -18, 0, 1, -6, 5, 17, 15, 10, 23, 38, 28, 28, 54, 40, 19, 55, + 55, 41, 46, 53, 40, 49, 51, 52, 41, 56, 39, 53, 38, 33, 35, 18, + 15, 38, 30, 23, 27, 13, 11, 7, 16, -1, 0, 0, 13, -6, -10, -15, + -10, -10, -24, -20, -16, -38, -36, -21, -40, -32, -42, -38, -52, -53, -41, -48, + -58, -50, -47, -37, -41, -45, -29, -41, -6, -48, -24, -25, -15, -9, -10, -10, + -10, -1, -17, 4, 3, 10, -4, 9, 15, 25, 24, 19, 23, 34, 28, 33, + 37, 38, 26, 36, 47, 35, 46, 45, 28, 35, 32, 32, 24, 21, 26, 23, + 19, 37, 20, 9, 29, -2, 26, 24, 8, 4, 14, 21, 11, -9, -8, 4, + -9, -31, -11, -15, -21, -24, -29, -22, -33, -26, -29, -48, -32, -44, -28, -22, + -35, -30, -38, -31, -46, -44, -36, -27, -23, -29, -24, -11, -20, -28, -13, -34, + -19, -1, 7, -3, -1, 6, -3, 5, 4, 8, 17, 26, 19, 33, 27, 16, + 35, 14, 36, 39, 22, 32, 31, 19, 32, 23, 29, 21, 30, 29, 23, 31, + 13, 24, 17, 11, 26, 18, 12, 5, 23, 16, 9, 15, -10, 3, 18, -15, + -4, -4, 6, -14, -15, -5, -34, -11, -20, -18, -8, -17, -29, -30, -29, -19, + -34, -35, -20, -36, -20, -16, -21, -38, -16, -30, -24, -25, -19, -18, -15, -7, + -5, -5, -10, -23, -3, -14, 0, -1, -12, -9, 7, 7, 2, 12, 5, 7, + 19, 10, 21, 21, 27, 30, 22, 18, 34, 22, 11, 26, 24, 20, 21, 25, + 29, 22, 27, 27, 20, 10, 20, 16, 22, 15, 16, 16, 5, 19, 10, 3, + 22, -5, -5, -7, -16, -4, -11, -22, -7, -16, -11, -23, -16, -30, -24, -28, + -20, -29, -24, -32, -22, -22, -30, -17, -23, -28, -22, -20, -21, -21, -17, -30, + -15, -14, -20, -9, 3, 6, 5, -20, 10, 13, -2, 11, 8, -1, 7, 16, + 5, 22, 23, 13, 22, 13, 22, 25, 15, 16, 11, 15, 13, 7, 12, 19, + 18, 20, 12, 23, 11, 6, 10, 1, 11, 19, 5, 20, 0, 11, 11, 1, + 14, 15, -3, -1, -7, 6, -6, -9, -9, 4, -3, -10, -20, -14, -9, -14, + -7, -10, -5, -4, -29, -14, -12, -26, -21, -27, -18, -10, -19, -27, -18, -8, + -25, -8, -13, -15, -14, -15, 5, -13, -7, -11, -4, -12, 0, 15, 5, 4, + 1, 11, 6, 4, 3, 6, 21, 19, 8, 15, 13, 6, 14, 16, 18, 17, + 20, 15, 11, 15, 24, 13, 11, 19, 7, 17, 14, 6, 17, 7, 7, 6, + 6, 5, 11, 0, 6, 0, -6, 5, 1, -11, -6, -1, -8, -9, -15, -7, + -4, -16, -17, -13, -13, -17, -14, -12, -12, -28, -13, -19, -25, -31, -24, -17, + -17, -16, -7, -15, -12, -8, -15, -8, -16, -10, -4, -1, -2, 3, 5, 2, + -2, 5, 3, 6, 10, 8, 11, 14, 14, 13, 15, 22, 16, 14, 18, 13, + 17, 19, 16, 10, 17, 8, 17, 14, 3, 14, 7, 10, 10, 7, 6, 6, + -1, 6, 1, 0, 12, -6, 6, 12, -4, -5, -4, -2, -2, -1, -2, -8, + -11, -9, -11, -11, -18, -6, -5, -16, -9, -14, -10, -13, -10, -11, -15, -14, + -14, -12, -17, -17, -17, -7, -11, -14, -15, -12, -6, -15, -5, -13, -9, 0, + 12, -2, -2, 6, 2, -7, 4, 10, 2, 9, 8, 7, 4, 5, 11, 15, + 11, 10, 18, 9, 13, 13, 13, 21, 11, 18, 19, 13, 14, 16, 6, 8, + 1, 19, 11, 10, 11, 1, 3, -1, -1, 5, -11, 5, -1, -5, -3, -13, + -10, -6, -7, -5, -15, -10, -11, -18, -8, -16, -20, -18, -9, -12, -17, -21, + -21, -13, -21, -8, -10, -10, -5, -16, -7, 2, -6, -6, -9, -7, -2, -9, + -5, 6, -7, 1, 3, -1, 2, 1, 2, 9, 8, 5, 15, 12, 1, 11, + 9, 8, 10, 15, 14, 5, 13, 17, 14, 15, 10, 7, 16, 5, 5, 5, + 8, 9, 10, 10, 7, 0, 4, 6, 9, -10, -4, 5, 2, -1, 0, -3, + -4, -5, -10, -5, -8, -9, -10, -3, -13, -6, -9, -20, -15, -11, -18, -14, + -10, -12, -20, -14, -14, -7, -12, -21, -14, -9, -8, -11, -5, -2, -7, -4, + 4, -2, -3, -1, 0, -1, 8, 6, 9, 7, 10, 6, 3, 4, 7, 10, + 11, 6, 9, 17, 11, 9, 7, -2, 16, 13, 12, 18, 5, 16, 9, 4, + 9, 6, 8, 9, 4, 4, 3, -2, -3, 2, -6, -3, 1, -7, -6, -3, + -6, -14, -8, -9, -4, -13, -9, -8, -16, -10, -12, -13, -11, -7, -8, -12, + -9, -8, -7, -11, -4, -8, -7, -8, -3, -13, -10, -3, 6, -5, -5, 0, + -5, -3, 6, -2, -2, 4, -2, 6, 2, -2, 5, 5, -2, 5, 15, 13, + 4, 6, 6, 14, 9, 4, 8, 7, 3, 11, 12, 2, 10, 7, 10, 8, + 4, 6, 2, 0, 3, 2, 4, 2, -6, -2, 2, -4, 3, -5, -6, -5, + -5, -5, -4, -8, -7, -4, -4, -7, -8, -7, -13, -10, -10, -11, -9, -8, + -8, -7, -11, -7, -3, -9, -6, -7, -3, -4, -5, 3, -3, -1, -2, -4, + 1, 4, 0, 3, 0, 5, 2, 0, 5, 4, 1, 3, 1, 0, 1, 7, + 3, 0, 4, 3, 6, 5, 0, 9, 5, 7, 6, 3, 6, 2, 3, 5, + -4, 9, 0, 4, 10, 0, 5, 1, -2, 4, -3, -3, -2, 0, 2, -7, + 3, -10, -1, -6, -9, -2, -4, -10, -3, -7, -6, -4, -10, -6, -6, -11, + -6, 0, -6, -8, -4, -1, -9, -10, 0, -6, -7, -2, -7, 1, -5, -5, + -1, 1, -6, 2, 0, -3, -1, 7, -4, 0, 7, 0, 8, 2, 3, 4, + 4, 2, 5, -1, 6, 7, 5, 6, 4, 2, 4, 6, 8, 6, 3, 1, + 8, 9, 2, -1, 4, 3, 4, 3, -3, 7, 4, 3, -2, 2, -4, -6, + -2, -5, -2, -3, 0, -5, -6, -13, -5, -6, -11, -9, -10, -5, -4, -9, + -9, -7, -7, -8, -8, -6, -5, -7, -5, -1, -3, -4, -2, -2, 2, -3, + 1, 2, -3, 1, 2, 1, 0, 1, 5, 0, 2, 5, 2, 0, 4, 1, + 7, 3, 2, 6, 0, 5, 7, 5, 5, 1, 3, 3, 5, 10, 3, 4, + 8, 2, 7, 3, -2, 3, 0, -1, -1, 1, 0, 1, -3, -2, -5, -4, + -3, -1, -7, -8, -4, -4, -10, -2, -8, -8, -8, -8, -9, -6, -8, -9, + -4, -2, -7, -5, -2, -7, -6, -9, -2, 0, -4, 4, -6, -3, -4, -1, + 2, 1, 2, 9, 0, 3, 0, 6, 4, 0, 5, 6, 2, 7, 7, 5, + 7, 6, 8, 6, 6, 5, 5, 1, 6, 5, -1, 3, 4, -1, 4, 1, + 4, 3, -5, 0, 4, 1, 4, -2, -3, -4, 0, -4, -8, -2, -5, -4, + -8, -6, -5, -3, -3, -7, -9, -6, -10, -10, -6, -6, -5, -4, -7, -6, + -4, -10, -3, -10, 0, -2, -2, -6, -1, 3, -3, -3, 1, 2, 1, 4, + 3, 4, 3, 4, 1, 2, 6, 5, 5, 5, 7, 9, 1, 5, 4, 4, + 7, 2, 9, 2, 4, 8, 2, 5, 6, 3, -2, -2, -1, -2, -1, 1, + -2, -4, 1, -6, -2, -5, -3, -5, -5, -6, -4, -3, -4, -10, -4, -3, + -8, -4, 0, -3, -5, -6, -6, -3, -1, -7, -3, 1, -1, -4, -2, 1, + -2, 0, -1, -2, 0, 0, 5, -2, 0, 3, 3, 1, 5, 2, 4, 1, + 4, 1, 2, 3, 3, 3, 4, 3, 3, 5, 1, 4, 2, 3, 1, 2, + 0, 2, 1, -2, -2, -1, 0, -2, -1, -1, -3, -5, -2, 0, -5, -1, + 0, -5, -2, -2, -2, -3, -3, -1, -4, -1, -2, -4, -2, -1, -2, -1, + 0, -3, -1, -1, 0, 1, -1, -1, 3, -4, -2, -2, 4, -2, -1, -1, + -1, 0, 0, -1, -1, -1, -1, 2, 0, -1, 2, -1, 0, -1, 2, 0, + 3, 5, -2, 1, 2, 0, 5, 0, -3, 4, -3, 1, 2, 0, 4, -1, + -2, 1, 0, 0, 0, -1, 1, -2, 0, 1, 1, 0, -5, 1, -2, -1, + 0, -2, -3, -1, -3, 0, -2, -3, -4, 1, -2, -3, -2, -2, -1, -1, + -2, -1, -4, -5, 2, -4, 0, 1, -1, 2, -2, -1, 0, 0, 1, -3, + 3, 2, 0, -2, 2, 1, 2, -2, 5, 3, -2, -2, -1, 1, 0, 0, + 1, 3, 2, 0, 0, -1, -2, 1, 1, 2, 1, 1, -1, 0, -1, -1, + -1, -3, 1, 1, 2, -2, -1, 0, 0, -2, 0, -1, -1, 2, -2, 1, + -1, 0, 0, -1, -1, -2, 0, -1, 1, -1, -1, 2, -2, 0, -1, -1, + 2, -1, 0, -3, -1, 0, 0, 0, -3, -3, -2, 0, 0, -1, -1, 0, + -4, 2, 0, -2, 0, 1, -3, -1, 2, 1, 0, -1, 0, 0, -1, 0, + 2, -1, -1, 0, 0, -2, 1, 1, 0, 1, 0, 2, -3, -2, 2, -1, + -1, 2, -2, 1, 1, 0, 0, 1, 1, 0, -4, 3, -1, 2, 0, 2, + -1, -2, 0, 1, 1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, + -1, 1, 0, -5, 0, -1, -1, -1, 1, -1, 1, -1, 1, 0, -2, 0, + -2, 1, -1, 1, 0, -1, -2, 0, -1, 0, 0, 2, 0, 0, 0, 1, + 0, 0, 2, 0, -1, 0, 0, 0, 2, -1, 1, 1, -1, -1, 0, 0, + 1, 1, 0, 0, 0, 0, -1, 0, 0, -2, 0, 0, -1, 1, -2, -1, + -1, -1, -2, -1, -2, 1, -1, 0, -2, -2, 1, -2, -1, 1, 0, 1, + 1, -1, -1, 0, -1, 0, 0, 0, -2, 0, -1, 0, 0, -1, -2, -2, + -2, 1, -1, 0, 0, -1, 1, 1, -2, -1, -2, -1, 1, -1, -1, -2, + -2, 0, 0, 1, -1, -1, -1, -1, -2, 2, 0, 0, 1, 1, 1, -2, + 0, -1, 0, -1, -1, 2, 0, -1, -1, -1, 1, -1, 2, 0, -1, 1, + 1, 0, 1, 0, -1, -1, -1, -1, -3, 0, 0, -1, 1, 0, 0, -2, + -2, -2, 0, -1, 0, 0, -1, 0, -1, -2, -1, -2, 0, -2, 0, 0, + -1, -2, 1, -2, 0, -1, -2, 2, 0, -1, 2, -1, 1, -1, 0, 0, + -1, 0, 0, 0, -1, 0, 1, 0, 0, 1, 0, -1, -1, 0, -2, -1, + 0, 0, 1, 0, 0, 0, 0, -1, -1, 1, -1, -2, -1, 0, 0, -2, + 0, -1, 0, 0, 0, 1, 0, 0, -1, 1, 0, -1, 0, 1, -1, 0, + -1, -2, 0, -1, 0, -1, -1, -1, 0, -1, 0, 0, 0, -1, -1, 0, + -2, 0, 0, 0, -2, -2, 0, -2, -1, -1, -1, -2, 0, -1, -1, -1, + 0, 0, -1, -1, 0, 1, -1, -1, 0, -1, 0, 0, 1, 1, 0, 0, + -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, 0, 0, -1, 0, + 0, -1, -1, 0, -1, -1, 0, -1, 0, -1, -1, 0, -2, -1, 0, -1, + -1, -1, -1, 0, -1, 0, 0, 0, 0, -1, 1, 0, 0, 0, -1, -1, + 0, -1, -1, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, -1, + 0, -2, 0, -1, -1, -1, 0, -1, -1, 0, -1, 0, 0, 0, -2, -1, + 0, -1, -1, 0, 1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, 0, + 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, + -1, 0, 0, -1, -1, -1, 0, 0, -1, -1, 0, -1, 0, 0, 0, -1, + 0, -1, -1, 0, -2, -1, -1, -1, 0, -1, 0, -1, -1, 0, 0, -1, + 0, -1, 0, -1, -1, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, + 0, -1, -1, 0, 0, 0, -1, 0, -1, 0, 1, -1, 0, 0, 0, 0, + 0, -1, 0, 0, 0, -1, 0, 0, -1, -1, 0, 0, 0, -1, 0, 1, + -1, -1, -1, 0, 0, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, + 0, -1, -1, 0, -1, -1, 0, -1, 0, -1, -1, -1, -1, 0, -1, -1, + -1, -1, -1, -1, -1, 0, -1, 0, -1, 0, 0, -1, -1, 0, -1, 0, + -1, 0, 0, -1, 0, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, -1, + -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, + 0, -1, 0, -1, 0, 0, 0, -1, -1, 0, 0, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 0, 0, -1, -1, -1, 0, 0, 0, -1, 0, -1, -1, + 0, -1, 0, 0, -1, -1, -1, -1, -1, 0, 0, -1, 0, 0, -1, 0, + 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, + -1, 0, 0, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, -1, -1, + 0, -1, -1, 0, -1, -1, 0, 0, -1, -1, -1, -1, 0, -1, -1, 0, + 0, -1, 0, 0, 0, -1, -1, 0, -1, -1, -1, 0, 0, -1, -1, -1, + -1, -1, 0, -1, 0, 0, -1, -1, 0, 0, -1, 0, 0, -1, -1, -1, + 0, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, 0, -1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + 0, 0, 0, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 0, -4, 11, 6, 16, 10, -16, -48, + -44, 2, 67, 42, -17, -51, 15, 71, 12, -22, -14, -44, -35, 11, 17, -18, + 2, -15, 19, 12, -1, -44, -15, 50, 45, -25, -61, 17, 10, -10, 31, 18, + -72, -27, 57, 26, -13, -17, -2, 6, -1, -23, -54, 17, 39, 8, 30, 28, + -6, -71, -5, 33, 27, -5, 17, 10, -23, -6, 12, -26, -6, -7, -9, -14, + 11, 37, 41, 8, -33, -14, 8, -31, -38, 13, 9, 15, 35, 33, 11, 17, + -41, -48, -33, 29, 25, 16, -9, -9, -17, -19, -29, 43, 64, -2, -55, -42, + -1, -21, -4, 29, 34, -25, -67, -29, 1, 51, 49, 25, -6, -15, -48, -76, + -3, 60, 78, 33, 19, 13, -38, -35, -35, -2, 62, 19, -4, -12, -4, -4, + -32, -30, 8, 68, -43, -66, -28, 55, 51, 20, -28, -29, -19, 20, -2, 8, + 21, -15, -43, 24, 22, -7, -2, 35, 15, -2, -24, -12, 3, 31, 13, -15, + -20, -17, -17, 26, -26, 24, -3, 7, 21, 26, -3, -17, -26, -50, -26, 33, + 58, 49, -22, -67, -17, 24, 7, -57, 5, 42, -11, -3, 32, -3, 7, 13, + -11, -9, 27, 17, 1, -5, -9, -18, -19, -3, -23, -5, 7, -8, 9, 13, + 12, -5, 7, -37, 22, 26, 21, 24, -20, -35, 23, 24, -35, -15, 46, -38, + -48, -14, -4, 0, -22, 3, 43, 38, -1, -14, -8, -5, -14, 1, 21, 23, + 29, -19, -47, -42, -49, -10, 66, 77, 48, -29, -32, 1, -11, 8, 17, -17, + 3, 43, 33, -22, -19, -41, 29, 22, -42, 9, 63, 28, -23, -59, -65, 7, + 53, -22, -10, -27, -30, 36, 48, -4, -6, -22, -16, 10, 14, -7, 22, 50, + -4, -25, -41, -55, -62, 23, 68, -16, -31, 49, 57, 21, -38, 14, 12, -43, + -49, -16, 28, 7, -12, -50, -17, 49, 65, 18, 1, -8, 28, 2, -27, -13, + 12, -11, -52, 4, 31, -32, -39, 15, 8, -19, 6, 25, -1, -23, 13, 34, + 59, 36, -16, -5, -7, -28, -30, 1, -14, -42, 10, 43, 26, -25, -37, -61, + 1, 63, 62, 1, -36, -24, 38, -7, -26, 27, 10, 4, 2, -19, -22, -27, + -24, 0, 33, -8, -57, -12, 62, 77, 51, -10, -42, -27, -28, -31, -3, 5, + 21, 10, 15, -27, -18, -18, -10, 3, 17, 19, 18, -16, -20, 25, -3, -19, + -5, 32, 17, -3, -32, -8, 2, -11, -24, -17, -11, 3, 42, 15, -12, -2, + 26, 9, -4, -30, -3, 16, 7, 13, 34, 40, 114, 11, -104, -71, 7, -14, + -34, -26, 35, 45, 47, 7, -7, -16, 11, -6, -29, -32, 1, 24, 32, 10, + 29, -10, -74, -80, -20, 18, 9, 18, 61, 38, -27, -44, 13, 16, -26, 20, + 69, 14, -14, -46, -7, -6, -35, 0, 9, 5, 58, 71, -36, -78, -15, 43, + 34, -61, -101, -27, 45, 26, -10, 23, 69, 69, 5, -72, -62, 19, 16, -37, + -60, 37, 60, 10, -49, -10, -2, -1, 43, 44, 10, -50, -5, 19, 8, -43, + -58, -17, 32, 28, 4, -1, -18, -10, 13, 8, 1, 1, 22, -3, -4, 9, + -8, -9, 17, 3, -15, -8, 14, 11, -14, -11, -5, 13, -24, -34, -1, -16, + -4, 32, 35, -32, 9, 22, 12, -27, -16, 14, 15, 0, -2, -12, -31, -24, + 14, 48, 10, -14, -7, -22, 4, -8, -14, 19, 21, -21, -25, -12, 19, 24, + 19, 27, -3, -15, -16, 10, 21, -14, 3, 8, 3, -11, -33, -16, 7, 5, + -8, 2, -3, 12, 5, -34, -19, -6, 26, 19, 0, -4, -12, 5, 12, 20, + 16, 19, 18, -13, -42, -26, -1, 0, -18, -16, 10, 27, 23, -5, -7, 9, + -8, 7, 22, 10, -28, -51, -26, 13, 44, 17, 16, 25, 14, -32, -45, -36, + -40, -3, 22, 41, 34, -12, -35, -31, 18, 3, 31, 28, 4, -21, 2, -14, + -24, -23, 19, -6, -7, -10, -1, -13, -13, 21, 52, 28, 7, 1, -25, -36, + 2, 34, 10, -37, -31, -13, 19, 11, -4, -20, 15, -5, -18, 40, -13, 15, + -36, 14, 18, 17, -21, 6, -39, 21, 7, -26, 8, -33, 24, 30, 32, -11, + -26, -47, -39, 62, 10, 11, 5, -17, -21, 10, 0, 18, 15, -22, 7, 13, + 14, -8, -9, 30, 33, -34, -41, -32, 37, 24, -19, -15, 1, 2, 10, 10, + -27, -46, -14, -9, 9, 47, 1, -22, -18, 5, 37, 29, -3, -19, -19, -18, + 8, 17, 1, -11, -6, -20, 27, 37, -2, -28, -34, -3, 22, 54, 34, -31, + -43, -28, -30, -33, 26, 49, 45, 43, -15, -58, -13, -2, -27, -7, 41, 11, + 19, -50, -74, -28, 31, 75, 39, -45, -7, 99, 44, -83, -47, 45, -1, -30, + 23, 29, -55, -30, 31, 28, -19, 2, -44, -46, -49, 30, 22, 58, 31, -50, + -20, 9, -38, -53, 49, 37, -9, 13, -25, -18, 18, -27, -7, 17, 3, 24, + 57, 26, -51, -52, -54, -43, 53, 85, 31, -36, -44, 7, 13, 19, -23, -33, + 36, 47, -38, -11, 37, -19, -6, 18, 17, 2, 31, 54, -29, -72, -80, -1, + 27, 52, 10, -29, -40, -48, -72, 24, 108, 66, -44, -76, -32, -24, 21, 69, + 54, 24, -2, -8, -28, -44, -50, 34, 95, 45, -40, -72, -32, 6, 28, -1, + 18, -7, 27, 1, -14, 21, -8, -51, -62, -24, 64, 56, 12, 19, -36, -22, + 10, 20, -10, -1, -5, -51, 36, 72, -42, -51, 70, 45, -48, -27, 54, 19, + -46, 8, 0, -46, 10, 37, 35, -21, -32, -22, -44, -82, -33, 59, 105, 48, + -32, -36, -31, 18, 60, -12, -49, 10, 89, 28, 12, 8, -45, -21, -6, -16, + -32, -17, -18, 3, 29, -3, 0, -20, -51, -31, 24, 52, 1, -17, -20, 1, + 35, 15, 5, 35, 27, 18, -19, 8, -71, -74, -8, 88, 57, -45, -37, 17, + 51, -1, -13, -4, 3, -13, -24, -7, 30, -7, -25, -1, 16, -8, -43, -70, + 11, 85, 77, 12, -62, -57, 35, 53, -33, -96, 8, 82, 21, -38, 25, 39, + -1, -27, -14, 18, -16, -45, -24, 42, 7, -9, 22, 32, -39, -5, -8, -49, + -17, 60, 88, 21, -93, -20, 82, 31, -26, -63, -17, 52, -28, -25, 13, -2, + -32, -46, 55, 56, -37, 6, -57, -33, 65, 63, 5, -25, -31, 69, 86, -32, + -34, -56, -23, -47, 14, 44, -23, 19, 6, 60, -27, -69, -37, 20, -14, -5, + 50, 44, 15, 13, -23, -60, -46, 23, 40, -5, -25, 6, 46, -4, -10, -27, + -12, 28, 45, 10, -13, -33, -19, -39, 42, 32, -23, -25, 24, -17, 13, 25, + 13, -32, 13, 48, 4, -93, -5, 40, -7, 37, -39, -37, 41, 1, -13, -33, + 43, -53, 106, 8, -57, -93, 55, 40, 56, -24, -4, -19, 7, -23, -65, -18, + 34, -30, 7, 66, 92, 3, -43, -37, -23, 12, -7, -17, 14, -15, -9, -18, + 18, 51, -1, -57, -17, 23, 19, 15, -40, -1, 0, -8, 39, -13, -43, 72, + 57, -1, -54, -17, 32, -19, 11, 0, 36, 25, -23, -86, 21, -3, 14, -17, + 76, 37, 23, 2, -23, -54, -42, -80, 61, 60, 63, -12, -57, -44, 15, 35, + 26, 11, -44, -22, 8, 33, -24, -17, 21, 38, -25, -39, 16, 43, -36, -28, + 54, 10, -52, -18, -34, -14, 76, 60, 24, -32, -19, 16, -13, -68, -5, 30, + -13, -23, -14, 61, 24, 35, 39, 4, -50, -58, -39, 0, 43, 43, 21, 24, + -20, -46, -36, 38, 8, -67, -8, 61, 38, 10, -12, 5, -4, -16, -47, -5, + -18, -20, 37, 41, 24, 4, 7, -19, 11, -52, 0, 17, 20, -30, -33, -16, + 60, 34, -15, -46, -77, 14, 29, 26, 21, 25, 8, 7, 36, 23, -39, -16, + 21, 11, -23, 11, -4, -6, -35, 13, -8, -49, -17, 44, 19, -25, -17, 9, + -5, -5, -1, -31, 11, 15, 17, -8, -31, -51, 12, 54, 85, 32, 4, -58, + -35, -31, 0, 10, 21, -20, -20, -29, 15, 26, -7, 8, 4, 0, 30, 2, + -26, 2, 19, 15, -18, -13, -20, -19, 47, 33, -6, -51, -30, -12, 12, 30, + 34, 31, 4, -45, -81, -7, -22, 1, 73, 98, 24, -67, -13, 19, -32, -86, + 6, 94, 4, -47, 21, -11, -50, 22, -3, -2, 50, 20, -37, -59, 35, 28, + -16, -36, -30, -11, 4, 69, 98, -65, -84, 73, 27, -90, -17, 84, 10, -51, + -14, 40, -24, -11, 16, -34, -26, 38, -43, -34, 58, 85, -33, -51, 17, 7, + 4, 52, 25, -35, 0, 44, -21, -47, 40, 44, -69, -65, 37, 35, -21, 4, + 32, -60, -75, 21, 64, 60, -6, -11, 6, 2, -41, -34, 19, 31, 9, 7, + -1, 11, 6, -11, -26, -23, 16, 35, -39, -68, 6, 56, -3, -42, 29, 28, + 3, 28, 14, -37, -16, 11, -8, -18, 15, -1, -8, 43, -20, -67, -12, 34, + 7, -12, -9, 5, -4, 7, -12, 27, -3, -68, 26, 96, 30, -33, -28, -25, + 19, 27, -33, -48, -3, 37, -1, -35, -11, 5, 42, 36, 6, -48, -38, 26, + 54, -23, -41, 52, 44, -32, -22, 28, -23, -32, 12, 41, -16, -6, -6, -17, + -18, -14, -12, -5, 18, 52, 45, -10, -16, 29, 11, -36, -26, 7, 36, 12, + -57, -48, 48, 70, 16, 21, -13, -46, -33, -62, -63, -21, 94, 94, 20, -110, + -47, 41, 67, -16, -57, -40, 85, 71, 7, -39, 15, -29, -50, -41, 18, -40, + -42, 38, 69, 21, -8, -58, -19, 23, 24, -20, -10, 11, 41, 7, -6, -30, + -23, 2, 16, 57, 38, -11, -50, 36, -16, -51, -51, 81, 24, -68, -84, 39, + 112, 62, -79, -104, 24, 102, 15, -38, 20, 22, -49, -91, 15, 51, 30, -1, + -15, -30, -12, 17, 42, -17, -48, 0, 49, 35, 2, -19, -16, -30, 9, 17, + -12, -4, -15, 5, 34, -1, -56, -64, 7, 48, 54, -16, -51, 20, 62, -17, + -27, -9, -10, -29, -1, 35, 44, -20, -23, -2, -12, -4, 31, 24, -24, -14, + 2, -28, -27, 49, 61, -54, -61, 6, 23, -20, 2, 41, 26, 2, 15, -5, + 6, -16, -36, -16, 2, -54, -53, -18, 62, 64, 10, -3, 91, 39, -54, -103, + -5, 16, -31, -28, 75, 105, -32, -114, -52, 68, 32, -52, -19, 25, 54, 61, + 14, -40, 12, 1, -56, -31, 74, 40, -73, -66, 0, 49, 36, 24, -20, 0, + 13, -40, -99, -11, 55, 31, -33, 39, 24, 3, -18, 7, 10, 4, -29, 17, + 19, 27, -30, -41, 9, 33, -24, -25, 30, 28, -34, -57, 8, -7, -46, 5, + 48, -22, -6, 57, 58, -31, -72, -2, 72, 44, -53, -42, 41, 1, -54, 30, + 54, -6, -79, -14, 33, -6, -22, 14, 10, -5, -8, 13, 23, 21, -47, -74, + 22, 24, -10, -7, 39, 2, 12, -7, -2, 4, 33, -20, -33, 18, 22, -88, + -71, 26, 81, 14, -37, 3, -24, 6, -8, 11, 40, 18, -7, -17, 20, -8, + -15, -41, -11, 27, 52, -27, -46, 33, 21, 46, -30, -13, 26, -91, -106, -47, + 54, 109, 67, -87, -90, 38, 92, 31, -10, -69, -73, -27, -6, 24, -6, 20, + 30, 45, 33, -13, -25, 10, 57, -16, -32, 0, -14, -55, -20, 4, 7, -4, + 3, 18, -11, 34, 11, -45, -45, -125, -38, -2, 19, 72, 82, 99, 98, 35, + -51, -81, -53, 3, -39, 23, -4, -58, -63, -24, 40, 84, 48, -7, -18, -2, + -8, -20, -10, 3, 21, 17, -39, -66, -20, -2, 37, 30, 39, 34, -5, -41, + -26, 33, 40, 18, -2, 11, 13, -20, -60, -21, 33, -25, -35, 30, 65, 22, + 13, -15, 2, 16, 11, -68, -18, 74, 10, -74, -34, -39, -17, 8, 59, 39, + -22, -38, -8, 9, 30, 23, 11, -3, -12, 10, -1, 59, 9, -28, -72, -27, + 32, 68, -11, -3, 27, 4, -33, -39, 7, -1, -5, -7, 26, -14, -26, -40, + -12, 5, 5, 1, -12, 64, 63, -41, -56, 10, 26, 40, -26, -44, -42, 25, + -6, 3, -1, 10, 9, -1, 9, 1, -28, 10, 24, 26, -33, -36, 46, 20, + -43, -52, -35, 22, 53, 30, -6, 18, -16, -49, -36, 45, 10, 21, 7, 9, + -33, -50, 21, 73, 33, -42, -46, 42, -12, -18, 5, -50, -25, 68, 55, -31, + -79, -7, 77, 25, -6, 29, 78, 24, -87, -41, -30, -41, -23, 75, 35, -32, + -65, -7, -13, 3, 41, 34, -24, -33, 25, 14, -52, -28, 19, 76, 45, -45, + -47, -5, 24, 9, -14, -41, -5, 49, 22, 10, -31, -35, -1, -6, 3, 10, + -1, -12, -20, -51, 9, 79, 53, -36, -38, -13, -14, -15, 50, 50, -36, -33, + 0, 5, 22, 23, 24, -51, -81, -27, 56, 42, -10, -16, 0, 0, -5, 16, + 12, -19, 11, 10, -15, -1, -32, -17, 1, 11, 62, -16, -21, 9, 21, -29, + -50, 16, 82, 17, -35, -4, 11, 3, 8, 8, -9, -13, 10, -39, -63, -19, + 54, 58, -16, -25, 18, 38, -8, -50, -54, -17, 18, 47, 17, -33, -45, 0, + 52, 57, -5, -34, -17, 32, 10, -28, -10, -21, -3, -9, -20, 20, 47, 22, + 5, -4, -15, -37, -22, -28, 9, 37, -18, -13, 3, 15, -33, -47, 20, 73, + 0, -36, 33, 60, -11, -77, -13, 42, 13, -20, 9, 47, 22, -27, 29, 6, + -71, -78, -20, 21, 4, 27, 23, 19, 31, 45, -29, -54, -10, 37, -78, -46, + -14, 67, 108, 57, 12, -62, -108, -15, 116, 56, -58, -110, -33, 33, 30, -39, + -26, 11, 29, 22, 8, 52, 76, 31, 0, -31, -50, -10, 59, 54, -13, -84, + -65, -60, 0, 35, 105, 61, -30, -117, -62, 35, 88, 57, 48, -38, -85, 41, + 12, -21, -6, 7, 15, 73, -30, -72, -37, 25, 0, -5, 65, 76, -90, -78, + 24, 47, 2, -14, 40, 83, 0, -32, -46, -62, -26, 50, 37, -4, -44, -40, + 55, 31, -38, -13, -17, -30, -4, 7, 68, 39, 1, -23, -38, -30, 6, -35, + 14, 52, -9, -62, -47, 45, 44, 11, -17, -9, 6, 16, 34, -3, -32, -21, + -33, -3, 21, 26, -39, 11, 65, 33, 19, -1, -49, -85, -97, 66, 58, -93, + -15, 15, 5, 81, 76, 29, -2, -52, -51, -30, 65, 38, -45, -14, 1, 28, + 22, 43, 19, -59, -109, -29, 29, -14, -22, -41, 0, 54, 76, 16, 8, 23, + 15, -47, -39, -8, 5, 36, -6, -3, -4, 13, 13, 21, -47, -53, -6, -9, + -27, -44, 8, 86, 64, 12, -5, -32, -10, -20, -27, -23, 8, 30, 1, 16, + 42, -35, -8, 4, -39, -11, -62, -29, 108, 87, -20, -104, -18, -55, 8, 47, + -16, 29, 38, 4, -44, -39, -20, 38, -13, 23, 82, 30, -67, -93, 26, 79, + 20, -79, -74, -23, 33, 59, 80, 39, -42, -100, 0, 19, 38, 9, -55, 9, + -15, 22, 68, -17, -55, -23, 1, 87, 19, -56, -60, 32, 37, 38, -67, -33, + -1, 31, 24, 15, -30, -5, -36, -29, -27, 8, 27, -9, 12, 29, 38, 33, + 0, -39, -18, 6, 19, 18, 8, 1, -33, 9, -1, 2, -29, -66, 0, 41, + 6, -50, -13, 9, 73, -28, -47, -21, 30, 68, 31, 32, 29, -46, -14, 13, + -44, -75, -3, 62, 55, 9, -49, -1, 54, 19, -6, 7, 16, 38, 13, -26, + -55, -76, -23, 16, 21, -33, -22, 16, 61, 25, -14, -35, 12, 23, -7, -17, + -32, -10, -16, -1, 7, 18, -1, 19, -2, -1, 21, -14, 1, -44, -44, -23, + -29, -1, 28, -28, 47, 64, 12, -4, -15, -37, -7, 24, 50, 6, -15, -26, + -5, 20, 12, -25, -21, -2, -18, -23, 9, 16, 24, 36, -30, -35, -12, 32, + 19, -13, 19, -6, 2, -2, -22, -11, 14, 50, 10, -21, -55, -14, 23, 6, + 6, -6, -26, -25, -8, 25, 14, 24, 14, -13, 18, 11, 23, -34, -49, -45, + 6, 39, 37, 3, 0, -29, 8, 26, -6, -7, -21, 2, -11, 6, 16, -1, + -17, 6, 32, -4, -54, -9, 22, -14, 6, 27, -1, -2, 34, 33, 8, 1, + -8, -14, -32, 23, -22, -23, -29, -12, 5, 25, 22, -4, 14, 5, 24, -39, + -29, 17, -21, -80, -60, -9, 78, 99, 81, -41, -53, 22, 11, -69, -22, -2, + 70, 80, 18, -56, -54, -79, -27, 56, 46, 28, -1, 12, -37, -76, 23, 64, + -4, -5, 4, 0, -2, -5, 10, -4, -9, 5, 3, 3, -2, 6, -2, -1, + 0, 2, 0, 1, -2, 2, -3, -2, 0, 1, -1, 0, 0, -1, -1, -1, + 0, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, -5, -6, -5, -5, + -3, 0, -1, -3, -1, 7, 16, 20, 8, -8, -24, -35, -39, -36, -35, -42, + -47, -35, -14, 0, 8, 17, 28, 45, 60, 65, 64, 66, 67, 60, 50, 39, + 26, 14, 5, -14, -40, -54, -56, -56, -55, -47, -36, -20, 1, 13, 15, 16, + 12, 2, -10, -20, -33, -43, -42, -38, -43, -40, -28, -17, -7, 6, 21, 34, + 48, 60, 63, 64, 66, 61, 54, 51, 41, 23, 10, 1, -18, -37, -46, -54, + -63, -60, -46, -30, -13, 5, 15, 16, 17, 11, -2, -11, -21, -34, -44, -45, + -43, -42, -33, -21, -17, -10, 5, 23, 39, 54, 62, 61, 62, 63, 59, 53, + 47, 38, 23, 10, -5, -23, -36, -42, -51, -61, -61, -48, -26, -2, 14, 16, + 13, 13, 9, -1, -14, -27, -36, -42, -44, -48, -44, -31, -17, -10, -8, 1, + 21, 47, 65, 67, 58, 54, 58, 61, 54, 41, 31, 23, 11, -9, -30, -41, + -44, -45, -54, -61, -52, -21, 11, 25, 19, 8, 4, 7, 2, -15, -33, -39, + -39, -44, -51, -48, -34, -12, -2, -4, -2, 19, 54, 74, 72, 58, 47, 51, + 59, 54, 40, 26, 20, 7, -16, -37, -46, -44, -42, -51, -58, -47, -15, 19, + 31, 25, 9, -1, -1, -4, -15, -30, -37, -41, -51, -55, -48, -28, -11, -4, + -2, 6, 28, 58, 73, 74, 63, 50, 45, 46, 49, 42, 31, 19, -6, -30, + -43, -44, -42, -51, -54, -49, -33, -3, 18, 30, 31, 17, 2, -13, -15, -15, + -25, -31, -45, -62, -60, -45, -24, -16, -10, 6, 20, 40, 58, 68, 74, 69, + 55, 41, 37, 44, 43, 34, 15, -17, -41, -48, -46, -51, -59, -51, -34, -16, + 3, 17, 29, 33, 23, 2, -15, -18, -18, -22, -31, -50, -64, -61, -42, -30, + -24, -8, 13, 35, 50, 57, 65, 70, 70, 58, 42, 40, 41, 40, 32, 6, + -23, -45, -53, -55, -64, -60, -45, -24, -1, 10, 19, 27, 28, 23, 4, -9, + -17, -22, -23, -36, -53, -61, -60, -47, -36, -22, -3, 19, 44, 56, 60, 65, + 65, 65, 60, 52, 45, 39, 37, 23, -2, -26, -49, -63, -66, -63, -55, -42, + -16, 3, 14, 25, 25, 22, 19, 11, -2, -17, -20, -29, -44, -50, -58, -64, + -53, -32, -13, 0, 25, 45, 53, 65, 68, 61, 60, 63, 60, 47, 42, 33, + 7, -10, -26, -56, -73, -68, -57, -53, -37, -12, -1, 14, 32, 26, 16, 17, + 16, 1, -12, -19, -38, -52, -47, -55, -65, -50, -23, -9, 4, 27, 40, 48, + 68, 72, 59, 58, 67, 64, 52, 42, 21, -5, -16, -31, -60, -73, -62, -54, + -49, -34, -17, -4, 17, 32, 24, 13, 18, 20, 6, -11, -29, -46, -48, -46, + -54, -59, -41, -17, -5, 6, 20, 35, 54, 71, 68, 55, 60, 74, 71, 53, + 27, 5, -6, -16, -35, -62, -70, -57, -49, -45, -40, -25, 4, 25, 29, 15, + 7, 23, 27, 10, -20, -46, -47, -41, -39, -47, -55, -34, -11, -1, 4, 11, + 38, 67, 72, 62, 48, 61, 83, 76, 49, 9, -9, -7, -15, -31, -59, -70, + -55, -48, -46, -43, -21, 16, 29, 22, 6, 1, 25, 32, 10, -28, -57, -47, + -34, -30, -38, -49, -33, -12, -4, 3, 17, 50, 72, 68, 55, 44, 61, 86, + 77, 41, -2, -16, -10, -13, -28, -56, -69, -58, -52, -47, -35, -7, 22, 25, + 13, -4, -2, 25, 33, 7, -35, -58, -46, -29, -22, -32, -44, -34, -16, -5, + 8, 30, 59, 72, 65, 46, 39, 62, 87, 76, 33, -8, -20, -13, -10, -28, + -57, -70, -62, -51, -42, -24, 3, 23, 23, 4, -15, -4, 25, 34, 3, -38, + -55, -45, -23, -17, -32, -43, -34, -15, -1, 14, 41, 64, 73, 59, 35, 35, + 64, 89, 73, 26, -11, -23, -14, -11, -33, -60, -69, -59, -48, -39, -14, 11, + 25, 17, -11, -24, -3, 30, 35, -3, -40, -54, -41, -18, -19, -36, -41, -28, + -10, 0, 21, 51, 70, 71, 47, 24, 36, 72, 93, 65, 17, -14, -22, -13, + -17, -43, -62, -63, -52, -48, -36, -5, 19, 26, 5, -26, -27, 5, 40, 31, + -12, -42, -50, -34, -20, -28, -37, -33, -17, -8, -1, 29, 61, 75, 64, 31, + 19, 44, 85, 93, 51, 9, -15, -18, -16, -30, -50, -57, -52, -48, -52, -32, + 3, 25, 20, -10, -34, -21, 19, 42, 20, -17, -40, -43, -35, -30, -32, -32, + -21, -12, -12, 3, 37, 67, 72, 50, 25, 24, 57, 92, 81, 42, 6, -12, + -18, -25, -39, -53, -52, -44, -49, -51, -28, 6, 25, 13, -17, -32, -11, 29, + 39, 8, -24, -38, -37, -33, -36, -39, -30, -10, -3, -9, 3, 38, 68, 71, + 46, 23, 32, 68, 92, 71, 31, 5, -7, -16, -31, -50, -55, -45, -37, -49, + -53, -27, 8, 23, 8, -20, -24, 3, 34, 28, -6, -28, -32, -30, -35, -46, + -43, -23, 0, 0, -10, 5, 41, 67, 65, 42, 30, 47, 77, 83, 52, 23, + 10, 2, -16, -43, -60, -55, -38, -36, -53, -53, -25, 8, 19, 3, -14, -8, + 17, 29, 9, -17, -24, -22, -26, -43, -53, -42, -14, 4, -3, -9, 10, 44, + 63, 58, 43, 43, 63, 77, 64, 38, 24, 20, 7, -23, -52, -62, -49, -38, + -45, -57, -49, -19, 6, 11, 2, -1, 12, 22, 13, -7, -18, -15, -17, -32, + -50, -52, -32, -11, -4, -8, -3, 21, 44, 55, 53, 52, 63, 70, 64, 49, + 35, 34, 24, 0, -29, -53, -54, -50, -51, -56, -57, -37, -17, -2, 7, 9, + 20, 21, 12, 1, -13, -11, -13, -24, -36, -49, -40, -30, -22, -12, -9, 10, + 25, 38, 51, 57, 70, 71, 62, 57, 44, 42, 34, 15, -4, -30, -42, -53, + -65, -61, -61, -49, -35, -22, -2, 10, 25, 27, 15, 11, -1, -8, -14, -22, + -27, -37, -37, -37, -40, -26, -14, -2, 10, 24, 42, 54, 68, 73, 65, 65, + 60, 49, 36, 27, 15, -7, -25, -43, -63, -69, -65, -61, -54, -36, -13, 3, + 18, 26, 23, 20, 16, 1, -16, -21, -20, -31, -37, -38, -40, -38, -25, -15, + -7, 11, 34, 48, 56, 66, 71, 72, 73, 61, 43, 34, 29, 11, -14, -31, + -46, -63, -69, -72, -69, -53, -28, -7, 3, 16, 27, 30, 28, 15, -3, -14, + -19, -25, -39, -42, -37, -38, -35, -30, -19, -2, 18, 39, 47, 56, 69, 75, + 78, 71, 60, 49, 35, 22, -1, -20, -32, -50, -65, -76, -75, -63, -49, -27, + -9, 6, 22, 28, 31, 27, 16, 6, -13, -26, -36, -43, -41, -42, -42, -36, + -27, -10, 2, 18, 38, 52, 64, 70, 73, 79, 76, 70, 50, 27, 11, -5, + -21, -41, -62, -69, -72, -68, -61, -50, -26, -4, 13, 21, 23, 32, 35, 27, + 6, -21, -33, -37, -42, -48, -53, -45, -31, -19, -8, 3, 23, 45, 59, 65, + 65, 73, 88, 88, 69, 40, 19, 10, -6, -30, -54, -69, -69, -68, -67, -59, + -43, -18, 2, 10, 15, 22, 39, 46, 27, -3, -28, -34, -37, -48, -56, -60, + -48, -29, -16, -1, 14, 35, 52, 58, 60, 64, 80, 96, 88, 64, 34, 16, + 6, -11, -36, -62, -77, -75, -68, -58, -47, -33, -14, -1, 7, 15, 28, 43, + 44, 24, -6, -30, -38, -40, -49, -63, -68, -56, -30, -5, 15, 27, 40, 51, + 59, 63, 72, 84, 91, 83, 60, 32, 12, 1, -14, -45, -73, -84, -78, -62, + -46, -36, -28, -17, 0, 11, 20, 31, 38, 35, 20, -6, -28, -40, -46, -58, + -72, -71, -52, -26, 4, 26, 37, 45, 54, 64, 69, 74, 81, 80, 73, 59, + 35, 13, -5, -28, -54, -75, -79, -74, -63, -43, -30, -21, -11, 0, 14, 23, + 29, 33, 23, 14, -2, -25, -41, -58, -69, -71, -64, -43, -24, 3, 33, 47, + 56, 60, 64, 73, 74, 75, 73, 62, 56, 38, 13, -12, -42, -57, -69, -77, + -71, -63, -44, -25, -15, -3, 2, 13, 26, 23, 24, 19, 8, -2, -24, -44, + -64, -74, -64, -60, -45, -16, 9, 34, 53, 63, 68, 66, 75, 73, 63, 66, + 62, 49, 34, 11, -17, -43, -54, -66, -82, -72, -52, -43, -28, -10, 0, 4, + 18, 27, 16, 13, 20, 8, -11, -26, -47, -66, -63, -59, -63, -47, -7, 20, + 34, 56, 69, 65, 73, 81, 67, 54, 61, 63, 44, 25, 6, -23, -37, -44, + -69, -85, -69, -48, -39, -26, -7, -4, 5, 27, 25, 9, 10, 15, 5, -17, + -34, -52, -62, -54, -54, -60, -40, -5, 21, 41, 59, 67, 66, 78, 81, 64, + 53, 58, 56, 39, 18, -3, -24, -34, -45, -64, -76, -67, -51, -37, -21, -8, + -3, 11, 22, 20, 11, 9, 11, -4, -23, -38, -56, -57, -53, -50, -42, -31, + -5, 21, 41, 63, 67, 72, 77, 69, 67, 58, 56, 49, 28, 16, -8, -28, + -35, -50, -53, -62, -65, -53, -44, -20, -2, 2, 14, 10, 14, 17, 7, 5, + -13, -27, -37, -60, -58, -55, -42, -22, -18, -2, 13, 36, 69, 73, 76, 71, + 62, 70, 60, 53, 42, 23, 16, -13, -35, -45, -51, -40, -46, -58, -60, -52, + -17, 4, 8, 11, 5, 14, 15, 4, -4, -20, -23, -37, -62, -67, -59, -27, + -2, -3, -3, 3, 36, 70, 77, 75, 66, 67, 70, 57, 46, 32, 29, 19, + -17, -49, -62, -46, -25, -33, -54, -68, -51, -15, 4, 8, 6, 11, 18, 8, + -7, -19, -16, -12, -35, -68, -83, -56, -9, 13, 7, -7, 4, 40, 66, 73, + 69, 73, 80, 69, 46, 27, 31, 42, 24, -23, -68, -69, -36, -14, -25, -57, + -66, -43, -16, -3, -2, 11, 28, 23, -2, -31, -29, -4, -1, -34, -83, -89, + -45, 3, 22, 6, -3, 16, 41, 56, 55, 68, 93, 93, 65, 23, 12, 38, + 53, 27, -38, -80, -64, -29, -12, -31, -54, -49, -34, -22, -24, -11, 28, 47, + 25, -24, -51, -27, 5, 5, -43, -90, -79, -34, 6, 11, 4, 17, 31, 39, + 34, 38, 79, 114, 105, 50, 3, 12, 44, 56, 16, -49, -72, -54, -28, -29, + -44, -37, -27, -28, -41, -45, -5, 46, 61, 17, -44, -53, -20, 7, -6, -53, + -78, -62, -27, -7, -6, 14, 41, 45, 26, 11, 38, 93, 127, 101, 34, 1, + 20, 48, 42, -1, -41, -53, -45, -40, -51, -44, -18, -9, -34, -61, -47, 7, + 57, 58, 2, -46, -43, -14, -5, -27, -52, -58, -46, -31, -26, -12, 28, 59, + 45, 10, 6, 50, 104, 124, 87, 30, 11, 30, 40, 19, -9, -26, -35, -44, + -58, -62, -38, -4, -6, -46, -67, -37, 21, 56, 43, -4, -37, -30, -15, -25, + -40, -44, -38, -38, -43, -38, -9, 40, 64, 37, 5, 14, 65, 106, 107, 75, + 36, 26, 34, 24, 4, -8, -10, -24, -53, -70, -64, -30, 0, -16, -53, -61, + -22, 28, 43, 29, -2, -21, -20, -26, -39, -43, -34, -26, -43, -54, -40, 0, + 46, 56, 30, 12, 30, 75, 97, 90, 69, 47, 38, 29, 13, 2, 0, -1, + -27, -61, -71, -55, -25, -14, -32, -50, -41, -6, 22, 25, 17, 4, -8, -19, + -31, -38, -35, -28, -35, -53, -54, -29, 7, 31, 32, 23, 28, 51, 72, 78, + 72, 65, 55, 42, 30, 19, 15, 11, -8, -36, -58, -58, -42, -35, -35, -43, + -40, -18, 0, 12, 14, 11, 9, -4, -15, -25, -31, -28, -36, -49, -53, -45, + -18, 1, 12, 19, 23, 43, 58, 64, 68, 64, 64, 57, 46, 40, 28, 22, + 9, -17, -35, -48, -47, -44, -47, -45, -44, -31, -12, -2, 7, 10, 9, 7, + -2, -8, -19, -28, -32, -44, -51, -48, -37, -21, -9, 5, 16, 26, 43, 55, + 60, 64, 63, 61, 58, 55, 48, 34, 21, 6, -13, -27, -39, -49, -53, -50, + -46, -41, -32, -16, -3, 5, 11, 9, 6, 5, -4, -17, -32, -40, -42, -44, + -42, -40, -32, -12, 5, 17, 24, 35, 50, 58, 64, 64, 60, 65, 61, 50, + 34, 18, 10, -2, -18, -38, -58, -56, -49, -45, -41, -38, -22, -4, 8, 14, + 8, 11, 10, -5, -20, -38, -41, -36, -37, -40, -48, -37, -12, 4, 14, 19, + 27, 46, 59, 66, 63, 62, 70, 64, 50, 34, 22, 17, 8, -11, -38, -59, + -57, -50, -49, -47, -43, -28, -6, 10, 16, 10, 14, 8, 1, -5, -5, -4, + -5, 5, 2, 2, 1, -1, 0, 1, 0, 2, 0, 0, -2, -1, -1, 2, + 1, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + -1, 0, 1, 0, 0, 0, 1, 0, 1, 0, -3, -10, -11, -8, -13, -25, + -21, -10, 0, 2, 18, 41, 44, 42, 66, 62, 28, 10, 17, 17, -16, -10, + 25, 28, 29, 34, 47, 34, -7, 7, 25, -12, -43, -44, -40, -61, -85, -78, + -55, -42, -33, -10, 17, 31, 43, 59, 51, 25, 25, 40, 27, -1, 2, 25, + 30, 15, 12, 27, 26, 13, 16, 9, -24, -43, -37, -49, -83, -92, -62, -40, + -42, -36, 1, 33, 34, 45, 61, 46, 27, 32, 33, 10, -6, 15, 38, 26, + 4, 15, 35, 19, 7, 17, 3, -26, -41, -50, -67, -91, -82, -48, -40, -46, + -24, 18, 33, 32, 54, 62, 46, 30, 22, 20, 7, 4, 28, 33, 15, 10, + 22, 25, 9, 13, 18, -2, -29, -54, -65, -74, -86, -68, -49, -46, -32, -8, + 17, 29, 45, 65, 60, 43, 23, 13, 17, 12, 18, 28, 22, 19, 16, 13, + 14, 16, 24, 13, -13, -40, -66, -72, -75, -74, -64, -55, -36, -20, -9, 15, + 43, 63, 65, 51, 37, 17, 9, 19, 23, 21, 19, 24, 21, 3, 4, 24, + 31, 18, -2, -20, -49, -77, -74, -65, -71, -69, -47, -27, -27, -10, 38, 66, + 59, 52, 51, 34, 4, 11, 36, 26, 12, 22, 26, 2, -11, 25, 45, 18, + 0, -1, -23, -72, -83, -55, -65, -83, -61, -34, -37, -36, 23, 71, 55, 43, + 60, 55, 11, 1, 40, 37, 8, 16, 31, 6, -22, 14, 55, 27, -3, 8, + 2, -52, -83, -57, -56, -89, -79, -43, -43, -55, -4, 66, 61, 35, 56, 68, + 31, 4, 32, 46, 13, 7, 31, 16, -24, -4, 50, 42, 2, 7, 16, -25, + -67, -60, -54, -86, -95, -55, -44, -63, -32, 40, 62, 40, 47, 67, 48, 22, + 32, 42, 18, 4, 25, 25, -15, -16, 29, 44, 21, 11, 15, -5, -39, -49, + -59, -85, -96, -72, -52, -62, -50, 7, 45, 49, 50, 56, 56, 43, 42, 39, + 19, 9, 16, 21, 1, -16, 9, 32, 31, 24, 14, 5, -14, -34, -52, -81, + -94, -85, -71, -62, -55, -21, 21, 41, 53, 55, 55, 57, 51, 44, 26, 13, + 15, 11, 3, -3, 0, 19, 27, 29, 26, 11, 0, -16, -41, -70, -90, -88, + -85, -80, -57, -34, -3, 26, 42, 57, 57, 60, 64, 50, 33, 20, 17, 9, + -6, -1, 6, 10, 23, 26, 28, 22, 10, 1, -27, -60, -78, -87, -90, -94, + -74, -42, -20, 10, 34, 44, 57, 65, 71, 58, 35, 30, 23, 8, -5, -7, + 4, 7, 19, 33, 23, 19, 24, 17, -13, -53, -65, -75, -96, -98, -83, -61, + -40, -7, 32, 38, 38, 66, 83, 65, 36, 36, 37, 8, -7, 1, 0, -5, + 11, 39, 34, 10, 21, 36, 4, -45, -59, -59, -89, -106, -84, -67, -62, -32, + 21, 41, 30, 47, 85, 80, 41, 34, 45, 20, -8, 0, 9, -7, -6, 31, + 45, 21, 12, 32, 25, -27, -55, -52, -76, -104, -95, -70, -64, -57, -7, 33, + 34, 38, 67, 84, 57, 35, 46, 29, -1, -4, 7, 7, -8, 12, 41, 31, + 21, 24, 25, -5, -43, -45, -65, -98, -98, -82, -62, -58, -35, 13, 27, 38, + 59, 70, 67, 45, 49, 39, 2, -3, 2, 9, 9, 6, 30, 30, 24, 31, + 20, 3, -26, -37, -48, -91, -100, -88, -75, -53, -41, -9, 12, 23, 55, 65, + 61, 54, 51, 51, 14, -6, 1, 1, 15, 18, 26, 29, 16, 30, 28, 4, + -14, -29, -36, -71, -100, -93, -87, -64, -38, -16, 2, 6, 33, 61, 59, 56, + 54, 55, 32, 1, -3, -4, 5, 25, 36, 36, 17, 14, 25, 14, -4, -19, + -30, -53, -84, -94, -95, -82, -49, -16, 4, 2, 10, 37, 56, 61, 58, 54, + 42, 19, 3, -9, -8, 14, 41, 53, 32, 10, 7, 10, 10, -7, -25, -43, + -65, -81, -97, -99, -72, -29, 9, 11, 3, 10, 33, 61, 65, 55, 46, 30, + 19, 0, -17, -5, 29, 62, 57, 24, -1, -6, 10, 8, -16, -35, -54, -64, + -80, -105, -99, -57, -2, 26, 13, -2, 6, 42, 67, 60, 49, 36, 31, 22, + -10, -24, 1, 49, 77, 53, 9, -14, -4, 10, -4, -26, -47, -56, -58, -89, + -115, -93, -34, 23, 33, 6, -6, 16, 50, 62, 53, 39, 34, 40, 16, -24, + -26, 15, 71, 82, 38, -5, -13, -1, 3, -13, -39, -53, -48, -61, -103, -119, + -80, -6, 42, 27, -1, 2, 26, 51, 56, 43, 33, 43, 42, 4, -34, -23, + 37, 87, 70, 20, -6, -10, -3, -5, -27, -49, -48, -44, -72, -115, -118, -56, + 22, 43, 17, 3, 12, 33, 51, 45, 34, 38, 51, 38, -11, -42, -9, 59, + 86, 53, 13, -5, -5, -3, -19, -42, -50, -43, -45, -85, -127, -105, -28, 34, + 37, 15, 8, 23, 41, 42, 34, 33, 45, 55, 26, -27, -38, 12, 69, 77, + 40, 9, 1, 0, -13, -33, -48, -49, -39, -55, -102, -124, -83, -8, 37, 31, + 14, 19, 35, 39, 34, 30, 35, 51, 50, 9, -31, -25, 27, 72, 65, 30, + 12, 9, -2, -23, -42, -52, -46, -43, -71, -109, -112, -63, 7, 36, 25, 20, + 33, 42, 35, 29, 29, 40, 52, 35, -2, -28, -12, 40, 69, 51, 26, 18, + 13, -8, -33, -48, -50, -46, -57, -84, -107, -98, -43, 14, 29, 24, 30, 44, + 43, 30, 26, 34, 44, 40, 19, -8, -20, 4, 46, 59, 42, 29, 25, 10, + -18, -40, -46, -47, -57, -73, -91, -100, -78, -30, 13, 25, 30, 44, 48, 39, + 29, 31, 41, 35, 23, 9, -9, -5, 16, 43, 52, 40, 37, 25, 0, -23, + -41, -43, -54, -74, -82, -93, -86, -60, -26, 12, 26, 41, 53, 44, 40, 33, + 36, 38, 19, 12, 2, -3, 9, 18, 40, 48, 42, 41, 16, -6, -23, -41, + -45, -68, -84, -86, -90, -71, -52, -22, 15, 32, 52, 54, 45, 45, 36, 36, + 25, 6, 6, 0, 5, 15, 21, 41, 46, 46, 37, 10, -7, -24, -42, -57, + -81, -88, -88, -83, -62, -43, -14, 16, 41, 59, 55, 48, 48, 40, 27, 10, + 2, 2, 0, 8, 22, 30, 36, 45, 50, 32, 5, -9, -23, -48, -75, -86, + -86, -88, -81, -54, -26, -11, 16, 52, 65, 55, 50, 53, 39, 9, -2, 4, + 2, -4, 11, 36, 34, 27, 47, 51, 26, 0, -9, -23, -63, -91, -85, -81, + -89, -79, -38, -13, -11, 23, 62, 67, 55, 52, 56, 29, -8, -7, 7, 0, + -5, 19, 44, 30, 28, 49, 46, 21, -2, -10, -32, -79, -96, -83, -81, -87, + -67, -27, -11, 0, 36, 65, 67, 58, 54, 48, 14, -15, -7, 3, 1, 6, + 26, 35, 30, 38, 46, 37, 18, -2, -18, -48, -85, -96, -89, -81, -70, -52, + -30, -8, 20, 48, 63, 66, 59, 50, 33, 6, -14, -15, -2, 13, 20, 21, + 25, 36, 45, 42, 31, 12, -10, -31, -56, -84, -103, -96, -70, -50, -43, -31, + 0, 35, 58, 68, 65, 51, 37, 26, 8, -19, -25, 2, 27, 27, 17, 20, + 36, 45, 45, 29, 0, -27, -41, -55, -87, -111, -93, -57, -37, -33, -23, 5, + 41, 70, 77, 59, 36, 26, 24, 4, -24, -22, 7, 31, 33, 19, 14, 29, + 49, 50, 22, -16, -39, -48, -63, -92, -104, -86, -51, -25, -19, -16, 10, 53, + 82, 74, 47, 26, 19, 16, -1, -18, -16, 7, 35, 37, 18, 10, 31, 55, + 41, 4, -25, -45, -57, -73, -90, -95, -82, -42, -9, -8, -11, 20, 71, 84, + 57, 39, 27, 13, 2, -6, -9, -12, 8, 45, 41, 8, 5, 42, 56, 20, + -10, -24, -50, -73, -83, -83, -87, -76, -25, 10, -5, -9, 39, 84, 71, 44, + 38, 26, 2, -9, -2, -4, -11, 17, 52, 36, 0, 11, 50, 43, 3, -19, + -31, -57, -84, -84, -77, -82, -59, -9, 14, 1, 7, 55, 81, 61, 38, 29, + 20, -2, -10, -1, -4, 0, 26, 42, 30, 8, 20, 41, 28, -4, -31, -46, + -64, -84, -82, -79, -66, -37, -7, 15, 18, 30, 58, 68, 57, 33, 17, 9, + 0, -3, -7, 0, 15, 23, 31, 29, 23, 24, 22, 14, -12, -43, -63, -72, + -73, -83, -75, -47, -26, -2, 20, 37, 48, 50, 57, 52, 30, 6, -1, 11, + 0, -9, 7, 16, 24, 28, 32, 33, 15, 7, 2, -21, -55, -79, -66, -67, + -81, -63, -38, -12, 9, 29, 53, 48, 42, 51, 47, 22, -6, 5, 18, -4, + -7, 6, 22, 28, 26, 39, 28, 2, -2, -8, -35, -73, -76, -56, -67, -77, + -55, -20, 4, 16, 40, 54, 42, 41, 51, 37, 7, 0, 17, 13, -12, -9, + 20, 31, 25, 29, 33, 15, -5, -8, -22, -57, -74, -62, -57, -74, -71, -33, + 0, 11, 26, 44, 45, 41, 47, 45, 22, 3, 12, 19, 0, -15, 4, 30, + 32, 27, 26, 17, 3, -4, -14, -44, -69, -66, -56, -63, -74, -52, -11, 12, + 21, 29, 35, 41, 49, 51, 31, 9, 11, 19, 11, -8, -7, 20, 36, 34, + 22, 10, 6, 5, -4, -33, -64, -66, -58, -58, -67, -63, -29, 4, 20, 21, + 21, 35, 52, 57, 39, 12, 10, 18, 16, 3, -7, 8, 31, 39, 25, 5, + 3, 10, 5, -22, -58, -67, -58, -56, -60, -64, -45, -11, 15, 19, 12, 24, + 50, 62, 46, 17, 9, 18, 20, 12, 0, 2, 21, 37, 31, 7, 0, 11, + 14, -12, -51, -66, -58, -53, -54, -59, -54, -29, 3, 16, 9, 17, 44, 62, + 51, 22, 8, 17, 24, 21, 9, 1, 11, 30, 31, 14, 3, 11, 16, -4, + -43, -65, -58, -49, -50, -53, -55, -43, -16, 5, 10, 16, 38, 59, 54, 26, + 7, 18, 29, 24, 18, 8, 5, 16, 27, 23, 11, 14, 18, -1, -36, -63, + -56, -43, -48, -47, -49, -52, -36, -12, 8, 17, 35, 55, 50, 28, 9, 17, + 33, 25, 24, 20, 5, 4, 15, 27, 23, 20, 22, 0, -32, -58, -55, -40, + -47, -44, -39, -52, -54, -34, -2, 19, 35, 53, 46, 27, 12, 18, 34, 26, + 26, 33, 13, -6, 0, 22, 34, 32, 28, 3, -31, -53, -51, -39, -47, -45, + -30, -45, -66, -56, -19, 15, 38, 52, 43, 22, 13, 22, 35, 26, 26, 41, + 25, -7, -13, 10, 35, 46, 39, 10, -29, -50, -46, -37, -47, -46, -27, -35, + -65, -72, -42, 2, 38, 55, 43, 19, 11, 24, 36, 27, 26, 43, 37, 2, + -19, -6, 25, 53, 56, 20, -24, -46, -43, -36, -46, -48, -29, -28, -56, -77, + -64, -22, 31, 61, 45, 16, 10, 23, 35, 30, 26, 41, 42, 16, -14, -21, + 7, 51, 70, 36, -15, -38, -40, -35, -42, -49, -35, -29, -44, -71, -81, -49, + 14, 60, 50, 18, 10, 21, 34, 34, 26, 37, 43, 30, 0, -27, -13, 37, + 74, 54, 2, -29, -35, -32, -37, -49, -42, -32, -36, -57, -85, -73, -12, 46, + 57, 27, 9, 17, 32, 38, 28, 30, 41, 39, 18, -20, -27, 15, 62, 68, + 26, -17, -30, -28, -29, -45, -51, -40, -34, -45, -77, -86, -42, 18, 54, 43, + 14, 12, 29, 42, 34, 25, 33, 41, 30, -2, -24, -5, 36, 65, 50, 3, + -24, -24, -19, -33, -54, -52, -42, -45, -61, -75, -58, -15, 32, 48, 25, 10, + 24, 45, 45, 27, 26, 32, 28, 13, -4, -6, 14, 44, 55, 24, -11, -18, + -12, -20, -46, -57, -53, -54, -57, -63, -57, -33, 4, 35, 32, 16, 22, 40, + 49, 36, 26, 28, 23, 17, 8, 1, 10, 27, 43, 33, 5, -6, -8, -14, + -33, -53, -57, -61, -62, -61, -59, -38, -10, 15, 26, 20, 26, 40, 44, 41, + 30, 27, 25, 18, 12, 3, 9, 26, 33, 28, 13, 5, 5, -8, -25, -45, + -57, -60, -64, -66, -65, -49, -17, 6, 13, 16, 26, 43, 47, 39, 32, 27, + 27, 25, 13, 3, 6, 22, 35, 26, 13, 10, 12, 5, -17, -40, -54, -58, + -58, -68, -74, -61, -31, -1, 9, 10, 23, 40, 50, 45, 31, 24, 27, 31, + 20, 3, 2, 17, 32, 31, 16, 12, 15, 12, -4, -31, -51, -55, -54, -62, + -76, -73, -47, -17, 2, 8, 19, 37, 51, 50, 34, 24, 26, 31, 25, 9, + 4, 13, 26, 34, 25, 9, 13, 20, -2, -33, -44, -43, -58, -78, -77, -59, + -44, -33, -10, 17, 6, 12, -9, 32, 13, 4, -4, 6, -9, 27, 8, 2, + -1, -3, -2, 3, -4, -3, 2, 0, -2, 1, -2, 1, -4, 2, 1, 0, + -2, -1, -3, 2, 0, -1, -2, -2, -2, -1, -2, -2, -1, -2, -2, -2, + -2, -1, -2, -1, 0, -1, -2, -2, -2, -1, 0, -2, -2, -2, -2, -1, + -1, -2, -1, -2, -2, -2, -3, -1, -1, 0, 0, -1, -3, -2, 1, 3, + 0, 0, -2, -8, -21, -17, -2, 12, 20, 19, 6, -13, -28, -73, -67, -64, + -58, -39, -11, 19, 38, 60, 96, 80, 38, 12, 6, -20, -65, -83, -65, -61, + -56, -17, 22, 35, 49, 74, 94, 55, 16, 20, -5, -52, -89, -81, -53, -65, + -36, 21, 37, 48, 51, 85, 82, 25, 23, 9, -36, -80, -105, -58, -57, -54, + 7, 36, 54, 44, 58, 97, 48, 26, 16, -21, -61, -115, -83, -45, -57, -12, + 23, 57, 54, 36, 86, 77, 37, 21, -16, -40, -103, -110, -54, -46, -24, 6, + 43, 68, 36, 62, 86, 60, 30, -12, -34, -80, -119, -76, -44, -24, -5, 24, + 64, 51, 50, 76, 72, 48, 0, -34, -68, -106, -94, -56, -26, -7, 11, 45, + 59, 58, 66, 71, 60, 23, -27, -68, -93, -93, -72, -37, -8, 10, 25, 50, + 70, 68, 62, 62, 45, -10, -70, -88, -83, -79, -57, -15, 15, 13, 31, 73, + 80, 59, 53, 61, 15, -67, -89, -73, -75, -75, -33, 21, 11, 10, 66, 92, + 65, 42, 63, 42, -56, -92, -66, -66, -84, -57, 16, 19, -5, 50, 98, 76, + 39, 56, 60, -35, -95, -64, -53, -84, -79, 0, 28, -8, 29, 96, 89, 42, + 46, 69, -10, -90, -69, -41, -74, -95, -25, 28, -1, 13, 81, 101, 53, 37, + 69, 11, -77, -75, -38, -53, -103, -55, 22, 8, 6, 61, 104, 75, 29, 59, + 31, -61, -76, -43, -36, -91, -88, 6, 17, 1, 46, 96, 94, 34, 40, 48, + -40, -80, -47, -27, -69, -107, -27, 26, 4, 29, 87, 105, 51, 24, 46, -10, + -76, -58, -21, -49, -107, -62, 17, 16, 17, 70, 110, 67, 22, 38, 10, -60, + -71, -24, -28, -97, -85, -6, 25, 18, 50, 106, 84, 28, 31, 16, -38, -71, + -38, -17, -78, -94, -30, 15, 30, 41, 86, 92, 44, 31, 15, -25, -54, -53, + -26, -57, -88, -51, -2, 33, 45, 68, 88, 59, 35, 17, -15, -42, -55, -41, + -48, -73, -60, -19, 24, 50, 61, 74, 67, 46, 21, -8, -32, -48, -54, -53, + -57, -57, -34, 9, 50, 63, 59, 65, 58, 29, -1, -24, -38, -62, -67, -48, + -47, -40, -8, 43, 68, 48, 58, 66, 38, 6, -19, -26, -62, -85, -45, -35, + -39, -21, 28, 72, 41, 47, 74, 45, 15, -14, -17, -53, -102, -50, -24, -36, + -26, 10, 69, 42, 32, 81, 52, 21, -4, -15, -39, -109, -64, -12, -35, -26, + -1, 54, 47, 21, 79, 65, 20, 7, -12, -33, -100, -82, -8, -27, -32, -2, + 36, 47, 21, 66, 77, 25, 12, -2, -36, -88, -87, -18, -16, -36, -8, 27, + 36, 30, 56, 77, 39, 12, 6, -33, -84, -79, -30, -11, -29, -20, 19, 27, + 31, 58, 66, 50, 21, 5, -25, -81, -75, -32, -17, -17, -27, 2, 24, 28, + 61, 61, 48, 35, 4, -22, -71, -77, -31, -19, -12, -23, -18, 16, 29, 59, + 65, 45, 41, 10, -23, -59, -76, -37, -14, -11, -18, -29, -2, 29, 57, 68, + 51, 37, 16, -21, -55, -67, -44, -12, -5, -21, -29, -19, 19, 59, 68, 61, + 36, 14, -12, -55, -61, -44, -16, 3, -21, -29, -25, 0, 55, 72, 69, 43, + 8, -6, -49, -63, -39, -18, 5, -15, -31, -26, -18, 39, 78, 75, 53, 8, + -8, -40, -67, -37, -15, 2, -8, -30, -26, -29, 16, 79, 84, 59, 14, -11, + -33, -66, -42, -9, -2, -6, -23, -26, -33, -7, 66, 94, 67, 22, -9, -32, + -62, -48, -8, 0, -9, -16, -20, -35, -24, 46, 96, 78, 31, -2, -29, -59, + -51, -13, 1, -10, -13, -9, -31, -35, 23, 86, 88, 42, 5, -22, -57, -53, + -18, -3, -10, -13, 0, -19, -44, 2, 69, 90, 57, 12, -13, -50, -57, -21, + -9, -13, -13, 1, -3, -41, -17, 51, 82, 69, 23, -9, -37, -57, -25, -12, + -22, -15, 0, 10, -25, -32, 32, 69, 71, 37, -4, -25, -48, -30, -12, -32, + -23, -3, 14, -2, -33, 11, 56, 63, 49, 3, -18, -32, -31, -13, -37, -38, + -9, 11, 17, -16, -6, 41, 53, 51, 11, -17, -15, -23, -14, -35, -54, -22, + 4, 26, 10, -10, 26, 43, 46, 19, -19, -6, -5, -10, -30, -65, -42, -9, + 24, 35, 3, 12, 32, 37, 24, -20, -8, 14, 2, -23, -68, -62, -26, 10, + 50, 28, 11, 22, 27, 24, -19, -19, 24, 21, -8, -63, -78, -45, -11, 47, + 53, 23, 21, 19, 22, -17, -34, 21, 40, 15, -48, -89, -65, -34, 30, 68, + 44, 27, 16, 16, -11, -47, 3, 49, 39, -22, -89, -82, -55, 3, 68, 61, + 44, 21, 11, -6, -53, -21, 45, 56, 11, -74, -96, -72, -26, 52, 73, 60, + 39, 10, -3, -48, -44, 27, 61, 42, -43, -101, -88, -52, 27, 73, 70, 59, + 21, -1, -40, -60, 2, 52, 60, -4, -90, -100, -74, -2, 62, 72, 76, 42, + 5, -30, -66, -22, 34, 63, 33, -62, -104, -92, -31, 44, 68, 84, 66, 21, + -21, -64, -41, 13, 54, 55, -26, -94, -104, -57, 20, 56, 82, 84, 43, -6, + -57, -54, -10, 36, 60, 7, -70, -107, -78, -6, 40, 73, 92, 66, 12, -45, + -57, -27, 16, 52, 29, -41, -96, -90, -32, 20, 60, 91, 83, 34, -27, -52, + -37, -3, 34, 36, -15, -77, -91, -52, -1, 43, 83, 93, 53, -5, -42, -40, + -17, 14, 32, 1, -54, -81, -65, -21, 23, 71, 96, 67, 16, -25, -37, -24, + -5, 21, 6, -36, -64, -69, -37, 3, 54, 93, 73, 35, -6, -28, -25, -19, + 8, 4, -27, -46, -65, -46, -14, 34, 86, 73, 49, 15, -17, -19, -28, -4, + -3, -28, -32, -56, -48, -24, 15, 74, 67, 55, 36, -2, -10, -28, -14, -9, + -36, -25, -42, -50, -29, 1, 60, 59, 50, 55, 16, -3, -22, -20, -14, -46, + -29, -28, -48, -33, -5, 47, 50, 40, 64, 40, 4, -14, -17, -19, -53, -40, + -18, -40, -41, -6, 39, 39, 28, 61, 62, 17, -10, -7, -21, -59, -53, -20, + -28, -47, -11, 38, 29, 15, 52, 77, 36, -6, 1, -12, -63, -66, -25, -20, + -46, -19, 37, 28, 0, 38, 83, 54, 5, 5, -2, -57, -81, -34, -15, -44, + -22, 29, 31, -4, 16, 85, 68, 17, 15, 1, -44, -87, -54, -8, -42, -27, + 25, 24, 2, 0, 69, 88, 24, 25, 11, -42, -76, -75, -14, -25, -40, 23, + 18, -3, 3, 42, 96, 45, 22, 29, -39, -70, -75, -40, -8, -39, 7, 24, + -17, 8, 33, 79, 76, 22, 35, -21, -75, -64, -60, -15, -17, -14, 21, -21, + -4, 40, 59, 88, 45, 24, -3, -71, -61, -59, -38, 1, -14, 0, -17, -18, + 41, 54, 82, 74, 22, -3, -53, -61, -53, -54, -2, 3, -19, -25, -22, 30, + 57, 73, 92, 38, -15, -40, -51, -50, -58, -17, 17, -23, -44, -22, 19, 55, + 72, 97, 60, -22, -40, -35, -45, -55, -32, 14, -17, -60, -26, 11, 46, 75, + 97, 78, -17, -46, -23, -38, -45, -37, -1, -14, -66, -31, 3, 34, 80, 98, + 85, -4, -47, -19, -33, -33, -30, -20, -25, -63, -34, -4, 18, 79, 104, 84, + 9, -38, -18, -29, -27, -14, -30, -46, -63, -32, -5, 3, 68, 111, 84, 18, + -23, -12, -25, -28, -2, -25, -67, -75, -29, 1, -6, 46, 112, 91, 22, -11, + 0, -18, -33, -1, -9, -76, -96, -34, 9, -8, 22, 101, 102, 27, -2, 14, + -7, -36, -9, 4, -68, -114, -48, 13, -3, 5, 80, 109, 40, 4, 26, 6, + -33, -18, 6, -52, -120, -67, 7, 4, -1, 55, 103, 58, 14, 31, 17, -21, + -24, -4, -39, -110, -84, -10, 6, 2, 34, 87, 71, 29, 36, 25, -7, -23, + -16, -33, -96, -90, -29, -1, 6, 22, 68, 75, 45, 45, 31, 4, -15, -24, + -37, -84, -87, -43, -15, 3, 18, 53, 68, 57, 58, 38, 11, -7, -22, -45, + -81, -79, -48, -29, -10, 17, 45, 57, 61, 71, 50, 17, 0, -15, -49, -85, + -74, -45, -40, -25, 10, 42, 49, 55, 82, 65, 22, 7, -9, -43, -89, -80, + -34, -47, -40, -1, 35, 52, 43, 85, 84, 25, 17, -4, -38, -85, -92, -28, + -44, -55, -9, 21, 53, 42, 75, 100, 35, 22, 6, -38, -74, -99, -38, -34, + -65, -18, 12, 42, 51, 63, 102, 52, 25, 21, -36, -70, -90, -56, -30, -64, + -30, 7, 27, 55, 63, 90, 69, 33, 26, -26, -69, -79, -66, -43, -54, -37, + -1, 17, 49, 69, 79, 72, 50, 30, -15, -61, -75, -68, -58, -52, -33, -12, + 9, 42, 69, 78, 64, 60, 42, -9, -49, -71, -69, -68, -61, -25, -17, -1, + 38, 64, 77, 59, 62, 58, -3, -37, -62, -72, -72, -73, -24, -12, -11, 35, + 55, 73, 59, 58, 69, 8, -29, -48, -75, -76, -82, -31, -4, -14, 28, 49, + 63, 61, 54, 73, 22, -21, -36, -71, -82, -88, -42, 0, -9, 21, 43, 53, + 57, 56, 73, 33, -12, -25, -62, -89, -95, -49, -2, -2, 18, 37, 43, 49, + 60, 75, 38, -2, -16, -49, -89, -105, -54, -7, 1, 19, 31, 37, 38, 59, + 81, 39, 4, -7, -35, -83, -115, -62, -10, 0, 20, 27, 32, 30, 53, 87, + 43, 4, 0, -24, -70, -118, -75, -12, -2, 19, 24, 27, 27, 45, 89, 52, + 4, 1, -14, -55, -113, -87, -18, -3, 13, 20, 24, 28, 41, 85, 60, 7, + -3, -9, -40, -100, -91, -28, -4, 7, 10, 21, 30, 43, 82, 62, 13, -8, + -11, -26, -85, -87, -36, -10, 2, -4, 14, 35, 47, 81, 62, 18, -9, -21, + -20, -65, -78, -38, -19, -4, -16, 0, 39, 54, 85, 65, 20, -7, -31, -24, + -47, -62, -33, -26, -15, -25, -19, 35, 63, 90, 73, 22, -3, -39, -39, -35, + -43, -20, -26, -30, -34, -36, 24, 71, 94, 85, 29, -3, -40, -58, -34, -24, + -4, -16, -46, -47, -47, 6, 73, 100, 97, 42, -4, -39, -73, -45, -8, 12, + 0, -51, -64, -56, -13, 66, 104, 106, 64, 2, -40, -82, -63, -3, 27, 18, + -43, -82, -68, -28, 51, 104, 112, 86, 19, -42, -86, -81, -10, 40, 34, -26, + -90, -86, -41, 31, 98, 116, 104, 46, -38, -92, -95, -25, 46, 48, -6, -84, + -105, -55, 13, 84, 117, 114, 76, -20, -95, -105, -45, 41, 54, 8, -65, -112, + -70, -1, 65, 109, 115, 100, 14, -85, -106, -62, 21, 50, 13, -44, -104, -84, + -14, 45, 98, 112, 111, 53, -62, -105, -75, -3, 44, 12, -31, -85, -93, -27, + 27, 82, 110, 110, 81, -27, -95, -81, -27, 31, 11, -31, -66, -90, -39, 12, + 61, 106, 107, 94, 12, -73, -79, -48, 11, 13, -32, -57, -78, -46, -1, 38, + 97, 109, 96, 43, -41, -69, -62, -13, 13, -30, -58, -68, -46, -11, 17, 81, + 112, 97, 59, -7, -51, -67, -37, 6, -23, -62, -67, -42, -14, 2, 60, 110, + 99, 65, 20, -24, -63, -56, -7, -15, -63, -75, -40, -12, -8, 39, 102, 103, + 67, 35, 6, -48, -68, -25, -11, -56, -85, -46, -7, -10, 22, 86, 107, 72, + 41, 29, -25, -70, -42, -14, -42, -91, -62, -5, -6, 9, 67, 105, 84, 40, + 40, 3, -64, -56, -23, -30, -83, -85, -12, 3, 1, 50, 97, 96, 44, 36, + 28, -45, -69, -33, -22, -67, -101, -34, 13, 2, 31, 88, 104, 56, 28, 37, + -16, -71, -51, -18, -49, -103, -62, 9, 14, 18, 70, 109, 68, 26, 36, 6, + -58, -68, -23, -28, -97, -84, -7, 23, 19, 50, 106, 84, 28, 31, -21, -26, + -18, -30, -24, -77, -76, -48, -46, 31, 0, -1, 0, 0, 2, 0, 1, -2, + 1, 0, -6, -7, -5, -3, 0, -3, -4, -2, 2, 0, -8, -11, -14, -10, + -8, -4, 6, 13, 14, 9, 2, -6, -10, -9, -6, 9, 17, 15, 8, 0, + 1, -4, -12, -19, -14, -8, -4, 3, 6, -2, -4, -6, -7, -10, -8, -12, + -11, 3, 23, 27, 11, 4, -3, -5, 0, -9, -3, 6, 11, 19, 4, -8, + -17, -20, -21, -3, 5, 8, 2, 3, 5, 2, -3, -3, -12, 4, 1, 3, + -7, 0, 5, 6, 0, -7, -8, -5, -7, -5, -3, 4, 9, 5, -5, -5, + -5, -17, -7, 3, 17, 15, 7, -2, -5, -3, 3, -8, -5, -3, 3, 8, + 12, 5, -10, -27, -20, 1, 5, -4, -9, -17, 4, 10, 9, -2, -12, -16, + -12, -2, 8, 16, 13, 11, 16, 19, 10, -2, -16, -21, -11, 14, 15, 21, + 11, 6, -10, -8, -11, -24, -35, -31, -13, 9, 24, 17, -2, -11, -20, -11, + -19, -7, 3, 8, 22, 21, 21, 2, -7, -10, 12, 24, 18, -3, -19, -6, + 0, -5, -18, -17, 6, 12, 7, -16, -20, -22, -27, -19, -14, 12, 14, 3, + 0, 2, 8, -3, -5, -3, 21, 29, 17, 6, -8, 3, 3, 10, 10, 3, + 12, 4, -9, -18, -20, -20, -9, 6, 3, -9, -7, -14, -9, -8, -9, -23, + -19, 7, 17, 20, 9, 8, 5, 9, 18, 9, 8, -10, -10, -4, 9, 25, + -6, -19, -19, -5, -4, -7, -7, -17, -15, -7, -4, 0, 2, -2, -17, -4, + 14, 23, 15, 2, -7, -5, 9, 11, 1, 0, -3, 0, 0, 15, 14, -4, + -15, -20, -26, -22, -13, 0, 6, 12, 5, -10, 2, 8, -2, -18, -8, 6, + 20, 28, 23, 0, -16, -7, 9, 7, 10, -12, -21, -19, 7, 12, 4, -17, + -28, -24, -3, 14, 4, -19, -18, -9, 11, 22, 16, -13, -23, -15, 18, 32, + 32, 17, -4, 1, 14, 11, 1, -20, -19, -3, 9, 13, -4, -13, -16, -18, + -23, -12, -17, -16, -20, -15, -14, -4, 8, 12, 0, 8, 5, 12, 17, 26, + 25, 14, 10, 11, 11, 18, 15, 4, -9, -13, -8, -9, -14, -20, -28, -32, + -12, -9, -16, -17, -24, -18, -12, 5, 10, 4, 6, 8, 18, 35, 31, 17, + 1, 12, 21, 33, 18, 6, -10, -11, -4, -9, -13, -19, -24, -24, -24, -18, + -20, -18, -20, -13, -15, -10, -9, -5, 8, 10, 13, 23, 26, 29, 14, 13, + 13, 13, 16, 25, 19, 17, 4, -15, -18, -15, -14, -17, -34, -23, -16, -12, + -16, -26, -33, -23, -15, -4, 4, 10, 16, 19, 22, 29, 28, 7, 1, 2, + 18, 26, 30, 21, 9, 3, -4, -10, -16, -29, -31, -27, -4, -9, -11, -28, + -23, -17, -15, -13, -11, 4, 11, 9, 13, 16, 25, 18, 8, 10, 18, 17, + 8, 18, 17, 11, -5, -19, -17, -12, -19, -38, -27, -8, 0, -3, -14, -19, + -20, -14, -10, -13, -3, 6, 12, 26, 38, 34, 14, 2, -2, 11, 19, 14, + 8, 5, 16, 9, -7, -19, -24, -29, -36, -26, -13, -12, -22, -28, -20, 5, + -3, -10, -19, 7, 20, 18, 17, 24, 25, 14, 18, 19, 29, 21, 11, 10, + 9, 13, -13, -29, -27, -20, -24, -30, -22, -12, -7, -15, -22, -21, -13, -14, + -20, -8, 12, 26, 25, 21, 33, 27, 25, 16, 13, 16, 16, -2, 2, 11, + 9, -2, -17, -18, -16, -25, -25, -26, -27, -30, -35, -30, -12, -6, -6, -6, + -5, 19, 19, 11, 15, 17, 24, 23, 34, 28, 23, 13, 2, 9, 18, 16, + -14, -18, -12, -7, -9, -31, -37, -33, -24, -14, -24, -20, -16, -21, -15, -7, + 5, 9, 15, 20, 28, 38, 29, 21, 15, 22, 17, 4, 12, 6, 12, -4, + -9, -15, -16, -19, -40, -38, -34, -23, -18, -17, -8, -10, -3, -7, 1, 3, + 4, 11, 13, 36, 41, 36, 24, 9, 17, 20, 21, 14, -5, -9, -11, -8, + -19, -14, -24, -30, -23, -18, -25, -30, -24, -17, -20, -9, -3, 6, 8, 22, + 23, 20, 27, 18, 10, 10, 14, 18, 14, 23, 17, 6, 5, -4, -8, -26, + -19, -24, -25, -24, -21, -27, -28, -15, -19, -16, -9, 0, 7, 9, 17, 14, + 15, 24, 30, 29, 29, 32, 16, 10, 8, 0, -3, -10, -7, -17, -22, -25, + -30, -36, -32, -25, -26, -22, -12, -16, -11, -3, 5, 7, 13, 21, 21, 26, + 32, 28, 26, 28, 31, 17, 15, 15, 5, -4, -14, -18, -28, -25, -24, -28, + -32, -33, -32, -29, -18, -17, -20, -10, -4, 6, 6, 18, 22, 22, 37, 38, + 31, 27, 26, 23, 22, 23, 12, 4, -5, -2, -11, -19, -25, -35, -35, -36, + -36, -43, -32, -24, -20, -12, -7, -3, -7, 3, 13, 23, 29, 35, 37, 35, + 42, 33, 26, 22, 17, 12, 6, 4, -9, -23, -28, -34, -34, -33, -31, -40, + -36, -27, -25, -22, -30, -20, -11, 2, 12, 22, 22, 26, 28, 35, 47, 44, + 27, 29, 29, 29, 19, 2, 1, -9, -15, -21, -34, -35, -34, -40, -44, -42, + -34, -31, -26, -21, -9, -12, -3, 10, 17, 29, 26, 27, 34, 48, 50, 34, + 33, 25, 21, 16, 8, 3, -8, -11, -25, -30, -37, -37, -42, -51, -34, -28, + -21, -26, -25, -19, -13, 4, 9, 17, 29, 41, 33, 33, 44, 45, 32, 31, + 28, 22, 16, 5, -10, -13, -16, -23, -38, -39, -39, -45, -54, -40, -32, -24, + -22, -17, -14, 0, 6, 9, 18, 41, 43, 34, 32, 40, 40, 31, 30, 27, + 22, 19, 14, -2, -16, -21, -34, -48, -45, -41, -41, -41, -45, -38, -25, -21, + -17, -20, -7, 11, 17, 19, 36, 40, 42, 44, 47, 46, 39, 33, 26, 15, + 11, 8, -5, -19, -24, -29, -40, -44, -48, -44, -37, -37, -43, -43, -26, -19, + -14, -2, 13, 23, 31, 36, 36, 43, 41, 47, 46, 44, 40, 24, 15, 14, + 3, -12, -21, -23, -30, -36, -47, -51, -50, -47, -44, -46, -31, -19, -16, -11, + 2, 16, 20, 25, 29, 40, 53, 51, 49, 45, 41, 35, 25, 18, 7, 5, + -12, -18, -23, -34, -39, -56, -58, -54, -49, -50, -45, -35, -26, -12, -5, 6, + 17, 29, 41, 42, 47, 50, 46, 49, 50, 50, 39, 30, 16, 2, -8, -15, + -21, -30, -41, -49, -50, -46, -57, -63, -57, -41, -29, -24, -12, -3, 5, 12, + 22, 33, 41, 50, 51, 53, 57, 55, 46, 36, 29, 16, 2, -4, -11, -21, + -33, -40, -49, -47, -53, -60, -58, -51, -42, -34, -23, -13, -2, 5, 17, 27, + 39, 49, 48, 51, 56, 54, 58, 44, 37, 28, 18, 4, -3, -15, -29, -39, + -49, -49, -51, -62, -65, -64, -47, -42, -36, -26, -14, -5, 10, 24, 32, 45, + 50, 49, 62, 65, 63, 47, 42, 41, 36, 23, 7, -7, -22, -31, -41, -53, + -58, -62, -59, -62, -56, -54, -50, -44, -32, -16, 0, 11, 25, 35, 50, 54, + 55, 56, 66, 65, 62, 54, 45, 36, 23, 14, -4, -22, -44, -55, -52, -62, + -61, -66, -70, -68, -60, -54, -45, -29, -15, 4, 21, 34, 36, 44, 54, 62, + 70, 73, 68, 67, 59, 50, 37, 21, -5, -12, -25, -39, -48, -53, -63, -76, + -73, -71, -71, -67, -57, -45, -29, -12, 2, 13, 30, 42, 51, 61, 76, 71, + 63, 66, 71, 60, 50, 40, 23, -2, -9, -20, -41, -54, -59, -72, -79, -71, + -64, -73, -68, -60, -51, -36, -13, 2, 13, 27, 47, 54, 71, 78, 71, 60, + 72, 74, 65, 54, 39, 28, 7, -6, -23, -50, -59, -64, -69, -75, -70, -78, + -74, -73, -64, -52, -37, -13, 6, 18, 40, 51, 58, 64, 78, 79, 75, 68, + 64, 68, 57, 45, 21, 4, -16, -34, -50, -65, -75, -83, -80, -71, -69, -68, + -73, -63, -57, -36, -16, 6, 26, 45, 60, 70, 71, 79, 79, 81, 78, 80, + 64, 55, 36, 16, -4, -23, -38, -54, -63, -69, -81, -85, -87, -76, -72, -66, + -61, -52, -30, -12, 12, 24, 44, 55, 69, 78, 85, 84, 74, 70, 71, 71, + 62, 41, 17, -11, -25, -42, -55, -66, -75, -87, -87, -81, -74, -76, -76, -63, + -48, -32, -13, 7, 30, 51, 64, 76, 80, 82, 83, 81, 80, 82, 70, 61, + 42, 19, 0, -28, -49, -61, -72, -78, -87, -90, -89, -88, -87, -82, -69, -54, + -33, -13, 15, 36, 58, 68, 79, 90, 96, 90, 84, 86, 89, 79, 62, 38, + 22, -3, -29, -55, -69, -81, -89, -94, -94, -94, -94, -89, -74, -62, -52, -35, + -18, 14, 39, 54, 65, 76, 87, 98, 95, 94, 90, 82, 75, 69, 47, 26, + -6, -33, -57, -72, -82, -88, -97, -90, -91, -88, -83, -80, -75, -59, -33, -9, + 20, 42, 58, 68, 82, 90, 94, 93, 94, 88, 85, 77, 65, 43, 16, -10, + -37, -60, -71, -84, -89, -95, -97, -102, -95, -84, -80, -72, -57, -26, -4, 19, + 42, 62, 80, 89, 94, 97, 100, 99, 90, 83, 71, 65, 39, 14, -9, -43, + -65, -83, -90, -95, -98, -96, -100, -96, -88, -76, -66, -51, -24, -12, 21, 45, + 70, 85, 93, 95, 97, 101, 105, 92, 84, 69, 58, 35, 16, -14, -44, -68, + -86, -88, -96, -101, -101, -102, -97, -90, -74, -69, -50, -19, 9, 35, 56, 76, + 84, 92, 98, 96, 99, 97, 93, 84, 77, 59, 24, 2, -30, -52, -76, -87, + -93, -98, -100, -102, -100, -96, -89, -81, -73, -46, -18, 12, 36, 62, 82, 88, + 96, 104, 107, 105, 102, 92, 84, 77, 53, 26, -6, -35, -57, -75, -81, -92, + -103, -114, -111, -108, -98, -88, -83, -67, -35, -7, 20, 39, 60, 70, 89, 106, + 116, 107, 103, 99, 86, 90, 82, 53, 18, -13, -31, -52, -73, -92, -102, -106, + -104, -97, -106, -99, -101, -92, -72, -42, -5, 16, 38, 66, 86, 101, 99, 101, + 95, 112, 107, 99, 95, 81, 53, 16, -3, -29, -60, -81, -102, -98, -102, -102, + -112, -114, -101, -104, -88, -69, -34, -8, 14, 41, 67, 92, 94, 99, 103, 104, + 115, 109, 103, 90, 78, 52, 22, 0, -39, -65, -92, -95, -91, -103, -104, -118, + -110, -102, -93, -84, -71, -36, -15, 19, 52, 81, 94, 89, 98, 103, 115, 117, + 102, 92, 83, 80, 49, 23, -11, -43, -67, -90, -93, -102, -105, -110, -118, -104, + -100, -89, -83, -64, -36, -7, 28, 50, 74, 88, 95, 104, 103, 115, 107, 106, + 97, 87, 74, 50, 20, -17, -47, -75, -89, -93, -101, -102, -115, -117, -106, -97, + -88, -90, -73, -38, 2, 36, 60, 75, 84, 96, 104, 115, 115, 102, 98, 96, + 96, 84, 52, 10, -12, -32, -53, -71, -87, -101, -109, -112, -109, -106, -105, -102, + -92, -74, -48, -19, 7, 33, 56, 76, 91, 101, 108, 111, 111, 108, 103, 96, + 85, 63, 33, 1, -27, -51, -73, -90, -102, -109, -112, -110, -107, -103, -100, -93, + -76, -50, -19, 10, 36, 58, 76, 91, 101, 108, 111, 111, 108, 103, 96, 85, + 63, 33, 1, -27, -51, -73, -90, -102, -109, -112, -110, -107, -103, -100, -93, -76, + -50, -19, 10, 36, 58, 76, -1, -2, -15, 21, -17, 23, -30, 1, 34, -34, + 6, 5, -15, 19, 1, -25, 6, 20, -2, -28, 15, 10, -15, 0, -7, 10, + 7, -5, -9, -6, 19, -3, -21, 3, 20, -4, -20, 1, 16, -3, -8, -2, + 5, 1, -8, -6, 3, 9, 2, -13, -4, 15, -7, -9, 0, 3, 6, -7, + -7, 5, 8, -8, -4, 0, 1, 1, -6, -4, 7, 2, -2, -7, 0, 4, + -3, -4, 0, 2, 0, -2, -4, 1, 4, -2, -4, -3, 1, 3, -5, -4, + 4, 3, -6, -5, 4, -1, -2, -3, 0, 3, -3, -1, -4, 3, 3, -5, + -3, 1, 1, -2, -3, 1, 2, -2, -4, 0, 0, 0, -1, -3, 1, 1, + -3, -2, 1, 0, -2, -2, 0, 0, -2, -1, 0, -1, 1, -2, -2, 1, + 0, -2, 0, -1, 0, -1, -1, -1, 0, 0, -1, -3, 1, 1, -2, -2, + 0, 1, -1, -2, -1, 0, 0, 0, -2, -1, 1, 0, -3, 0, 2, -1, + -2, 0, 0, 0, -2, 0, -1, 0, -1, -1, 1, 0, -1, 0, -1, 1, + 0, -13, 5, 7, -11, 24, -50, 41, 4, -29, 14, -11, 8, 11, -15, -12, + 15, 18, -21, -14, 22, -2, -11, -3, -3, 18, -3, -5, -14, 9, 22, -24, + -16, 23, 12, -23, -8, 9, 10, -4, -8, -3, 11, -4, -14, 0, 8, 8, + -5, -14, 8, 10, -12, -4, -2, 10, 0, -11, -3, 11, 0, -7, -2, -1, + 7, -6, -8, 3, 6, 0, -3, -8, 7, 2, -7, -2, 2, 1, -2, -4, + -1, 3, 3, -4, -5, 1, 3, -3, -6, 2, 5, -1, -7, -1, 3, -1, + -4, -3, 5, 0, -3, -2, -1, 4, -1, -5, -1, 3, -1, -4, -1, 3, + 1, -4, -2, 1, 0, -2, -3, 0, 2, -1, -4, 1, 1, -1, -2, -2, + 1, -1, -3, 0, 0, 0, -1, -2, 0, 0, -2, -1, 0, -1, 0, -2, + -1, 0, -1, 0, -1, -2, 2, -1, -2, -1, 0, 1, -2, 0, -1, -1, + 0, -1, -2, 0, 1, -1, -3, 0, 1, -1, -3, 0, 1, -2, -1, 0, + 0, -1, -1, 0, -1, -1, -1, -1, 0, 0, -1, -1, 0, 0, -2, 0, + 0, 0, 0, -2, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, + -1, 0, 0, -1, 0, -1, 1, 0, 0, 0, 1, -1, -1, 0, 0, 0, + 1, -2, 4, -3, 3, -40, 71, -73, 67, -27, -68, 127, -80, 3, 5, 1, + 17, -14, 1, -30, 53, -3, -42, 15, 19, -9, -17, -1, 13, 16, -17, 4, + -32, 43, 15, -68, 18, 54, -38, -7, -1, 11, 7, -3, -18, 5, 25, -27, + -9, 9, 19, -6, -12, -8, 20, -1, -15, -1, 1, 17, -10, -16, 12, 12, + -13, 0, -6, 10, 2, -16, -1, 14, -4, 4, -11, -2, 12, -6, -8, 4, + 4, -2, -4, 1, -2, 4, 3, -7, -5, 8, 0, -10, 1, 4, 2, -4, + -6, 4, 1, -1, -7, 1, 8, -9, 2, -5, 3, 3, -4, -3, 0, 3, + -3, -5, 4, 3, -3, -4, 0, 2, 0, -3, -4, 5, 0, -5, -1, 2, + 0, -3, 0, -1, 2, -2, -4, 3, 0, -1, -2, -1, 2, -2, -2, 1, + -1, 0, -1, -3, 1, 1, -2, 1, -3, 1, 1, -3, -1, 1, 0, -1, + -2, 1, -1, -1, 1, -2, 1, -1, -1, -1, -1, 0, 1, -3, 0, 0, + 1, -4, 0, 1, -2, 0, -2, 0, 0, 0, -2, 1, -1, 0, -2, 0, + 2, -2, -1, 0, -1, 2, -2, -1, 1, -2, 0, -1, 1, -1, -1, -1, + 1, -2, 1, -1, -1, 2, -3, 0, 0, -1, 1, -1, 0, 1, 0, -2, + 0, -1, 1, -2, 0, 0, -1, 1, 0, -2, 0, 1, -2, 1, 0, 0, + -1, 0, 1, -1, -1, -1, 1, 1, -1, 0, 0, 0, -1, 1, 0, -1, + 1, 0, 0, 1, 0, -1, 1, 0, 3, -40, 58, -39, 12, 42, -117, 108, + 1, -66, 22, 17, 0, -9, 10, -39, 42, 4, -23, -12, 28, 3, -34, 9, + 17, 3, -9, 10, -29, 13, 53, -79, 3, 64, -26, -24, 16, -9, 14, 2, + -8, -15, 31, -9, -30, 11, 29, -15, -7, 0, 3, 6, -4, -9, -6, 22, + 1, -24, 9, 11, -8, 0, -2, 2, 8, -12, -6, 10, 2, 2, -9, -4, + 11, -2, -10, 3, 2, 3, -5, -1, 1, -1, 6, -4, -8, 9, 2, -8, + -3, 6, 3, -4, -3, -1, 6, -2, -8, 0, 9, -4, -3, -2, 2, 4, + -4, -1, -1, 4, -2, -6, 4, 2, -1, -4, 0, 1, 2, -3, -5, 3, + 3, -3, -4, 3, 0, -1, 0, -2, 2, 0, -3, 0, 3, 0, -3, -1, + 2, 0, -3, 1, 0, -1, 2, -2, -2, 2, -1, 0, -1, -1, 1, -1, + -2, 0, 0, 1, -3, 1, 0, -1, 1, -2, -1, 2, -2, -1, 0, -1, + 2, -3, -1, 1, 1, -2, -2, 2, 1, -2, -1, 0, 0, 1, -3, 1, + 0, 0, 0, -2, 3, 0, -2, 0, 0, 1, 0, -1, 1, -2, 0, 0, + 0, -1, 1, 0, 0, 0, -1, 1, -1, 1, 0, -1, 1, -2, 0, 1, + 1, 0, 1, -2, 1, 0, 1, 0, 0, 3, -1, 0, 1, 0, 0, 3, + -29, 35, -12, -16, 56, -88, 39, 62, -79, 5, 29, 1, -13, 12, -29, 26, + 17, -28, -3, 12, 5, -11, -19, 28, 1, -5, 9, -21, -7, 60, -56, -20, + 57, -10, -27, 21, -21, 16, 12, -12, -21, 24, 6, -29, 4, 19, 2, -7, + -5, -3, 7, 6, -11, -9, 11, 13, -18, -4, 13, 1, -3, -6, -1, 10, + -8, -6, 5, 3, 5, -3, -11, 4, 9, -11, 0, 4, 3, -4, -1, 0, + 0, 7, 0, -14, 7, 5, -7, -4, 4, 5, -1, -4, -4, 4, 1, -4, + -4, 7, -1, -1, -3, 0, 5, -1, -4, -1, 2, 0, -3, 1, 1, 2, + -2, -4, 1, 2, 0, -5, 2, 3, -2, -2, 1, 1, -2, 2, -3, 0, + 0, -1, -1, 0, 1, 0, -3, 0, 0, -1, 1, -1, -2, 1, -1, 0, + -2, 2, 1, -2, -1, 1, 0, -1, -1, 0, 1, -1, 0, -2, 1, 1, + -1, 0, -1, -1, 0, 0, -1, -1, 0, -1, -1, 2, -2, -1, 1, 0, + 0, -1, -1, 1, 0, -1, 1, -1, 0, 1, -3, 1, 1, -1, -1, 0, + 1, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, 0, 2, -2, 0, 1, + 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, -1, -1, -7, -9, 35, -52, + 59, -33, -32, 64, -15, -41, 19, 22, -20, 9, -11, -3, 33, -27, 2, 7, + -9, 19, -37, 24, 7, -11, 11, -1, -30, 37, 8, -57, 36, 19, -33, 14, + 0, -17, 26, 1, -20, -5, 26, -18, -13, 14, 7, -6, 4, -9, -4, 11, + 3, -14, -7, 20, 0, -18, 10, 1, 4, -5, -7, 6, 0, -3, -2, -2, + 8, 5, -11, -6, 10, -1, -10, 6, -2, -1, 1, -3, 0, 3, 5, -9, + -5, 9, -3, -4, 1, 1, 3, -1, -4, -1, 2, -2, -5, 5, -3, 0, + 1, -5, 4, 2, -3, -3, 0, 0, -2, 1, 0, -2, 3, -2, -5, 2, + 2, -2, -4, 3, 0, -2, 1, -2, -2, 5, -2, -6, 1, 2, -1, -1, + 0, 1, -1, -2, -1, -1, 2, 0, -4, 0, 1, 0, -3, 0, 2, 0, + -3, 0, 0, 1, -1, -1, 1, 0, -1, -2, 1, 0, 0, -1, 0, -2, + 1, 0, -1, 1, -1, 0, -2, 1, 1, -2, -1, 2, -2, 1, -3, 1, + 1, -1, 0, 0, -1, 1, 0, -2, 2, -1, -1, 0, 0, 1, 0, 1, + 0, -2, 1, 0, 0, -1, 1, 0, 0, 0, 0, -3, -20, 45, -56, 40, + -5, -34, 27, 24, -42, -1, 29, -14, -4, 2, -7, 24, -20, -1, 18, -25, + 25, -29, 9, 21, -26, 14, 4, -20, 7, 27, -42, 5, 31, -24, -2, 19, + -30, 21, 8, -11, -17, 20, 1, -22, 11, 7, -7, 6, -5, -7, 3, 11, + -6, -18, 11, 16, -20, 1, 5, 2, -3, -3, 0, -3, 4, -1, -7, 2, + 10, -9, -8, 7, 2, -9, 5, -1, -5, 2, 1, -3, -2, 9, -5, -8, + 4, 1, -5, 0, 1, 2, -1, 0, -5, 4, -1, -5, 4, -3, 1, 1, + -5, 3, 0, 0, -3, 0, -1, -2, 1, 2, -5, 2, 1, -5, -2, 3, + -1, -5, 2, 1, -4, 2, -1, -4, 2, 3, -7, -1, 2, 0, -2, 1, + 0, -2, -1, 0, -3, 1, 2, -3, -2, 3, 0, -3, -1, 1, 0, -1, + -2, -1, 1, 0, 0, -1, 0, 0, -2, 0, 0, 1, -2, 2, -3, 1, + 0, 0, -2, 1, 0, -1, 0, 0, -1, -1, 2, -3, 0, 0, -1, 0, + 0, -1, 1, 0, -4, -13, 32, -41, 31, -10, -10, 4, 22, -25, -8, 21, + -3, -14, 5, 1, 12, -23, 8, 18, -31, 25, -26, 10, 17, -23, 8, 5, + -9, 0, 16, -25, 2, 23, -22, -2, 22, -30, 15, 7, -6, -13, 12, 1, + -17, 9, 5, -6, 4, -3, -7, 5, 7, -6, -13, 7, 10, -11, 0, 0, + 4, -3, -3, 2, -7, 4, 2, -5, 0, 6, -3, -8, 4, 2, -8, 7, + 0, -8, -1, 6, 0, -8, 6, 0, -5, 1, 0, -5, 3, 2, -3, -2, + 4, -5, -1, -1, -2, 3, -4, 1, -1, -3, 3, -1, -2, -2, 1, -2, + -2, 1, 1, -4, 1, 2, -5, -3, 5, -3, -4, 4, -1, -4, 2, -1, + -4, 3, 1, -5, -2, 2, 0, -2, 2, -1, -4, 3, -1, -3, 0, 1, + -2, -2, 1, -1, -1, -1, 0, 0, -1, -1, -1, 0, -1, 1, -1, -1, + 0, -2, 1, 0, -1, -1, 0, -1, -1, -1, 2, -2, -1, 1, -1, -2, + 1, -1, -1, 1, -2, 1, -7, -3, 15, -23, 20, -16, 9, -12, 16, -12, + -8, 11, 5, -18, 6, 8, 0, -18, 16, 4, -19, 16, -17, 10, 5, -8, + -2, 9, -5, -4, 10, -17, 5, 13, -18, 2, 12, -17, 10, 0, -2, -8, + 7, -4, -7, 6, 1, -3, 1, 3, -9, -2, 10, -7, -8, 4, 6, -6, + 1, 0, 0, -2, 1, -1, -8, 6, 1, -5, 2, 4, -2, -4, 1, 1, + -7, 5, -1, -4, -2, 4, 0, -4, 4, -3, -4, 1, 0, -3, 0, 2, + -1, -2, 2, -2, -1, -3, 0, 3, -4, 3, -3, 0, 2, 0, -3, -1, + 1, -3, -1, 2, 0, -1, 0, 0, -3, 0, 1, -4, -1, 2, 0, -2, + 0, 1, -3, 1, 1, -3, -2, 2, -1, -1, 2, -1, -2, 1, 0, -1, + -1, -1, -3, -8, -16, -20, -7, 14, 20, 19, 18, 16, 11, 3, -9, -21, + -36, -43, -39, -24, 6, 38, 57, 55, 26, 0, -7, -10, -13, -12, -11, -29, + -56, -59, -37, 0, 43, 74, 87, 75, 37, -2, -31, -51, -59, -45, -15, -16, + -34, -20, -10, -5, 29, 61, 72, 51, 18, -2, -21, -39, -35, -24, 1, 0, + -31, -29, -23, -44, -13, 48, 82, 79, 46, 16, -4, -44, -58, -26, 3, 6, + -38, -52, -24, -42, -35, 47, 95, 88, 55, 19, 12, -22, -72, -38, 4, 3, + -31, -67, -29, -24, -60, 23, 112, 111, 72, 22, 7, -20, -90, -73, -1, 19, + -4, -57, -36, 3, -54, -32, 98, 125, 71, 14, 14, 0, -82, -106, 0, 42, + 10, -48, -32, -2, -54, -63, 72, 125, 82, 24, 14, -8, -57, -104, -22, 52, + 34, -34, -46, -16, -35, -83, 32, 127, 99, 26, 19, 4, -55, -110, -48, 45, + 36, -12, -26, -22, -41, -64, -7, 107, 113, 56, 6, 4, -41, -92, -74, 35, + 57, 12, -41, -21, -39, -67, -40, 86, 114, 71, 10, 22, -31, -83, -83, 16, + 46, 34, -28, -18, -42, -58, -60, 55, 108, 97, 3, 21, -8, -77, -102, 10, + 45, 42, -26, -2, -27, -68, -73, 45, 83, 92, 29, 25, -8, -56, -104, -13, + 35, 52, -6, -7, -22, -46, -91, 10, 80, 95, 35, 26, 8, -38, -106, -34, + 34, 42, 5, 1, -23, -39, -73, -28, 61, 89, 60, 20, 2, -7, -73, -86, + 24, 52, 26, -12, -11, -19, -58, -86, 46, 91, 62, 17, 22, -15, -39, -106, + 8, 55, 45, -13, -6, -30, -21, -102, 4, 82, 87, 7, 28, -3, -9, -115, + -32, 50, 63, -23, 8, -19, -18, -94, -28, 61, 96, 14, 39, -4, 1, -85, + -60, 23, 79, -3, 2, -20, -10, -82, -65, 25, 108, 28, 31, 19, 9, -65, + -74, -5, 78, 16, -3, -9, -14, -65, -76, -3, 93, 60, 29, 22, 13, -43, + -90, -30, 61, 49, -9, -1, 4, -52, -98, -16, 68, 72, 21, 38, 15, -31, + -94, -34, 32, 67, 5, 9, 0, -28, -111, -33, 40, 85, 24, 37, 23, -6, + -104, -44, 13, 69, 9, 14, 8, -11, -110, -53, 20, 80, 32, 48, 30, 5, + -87, -66, -7, 63, 33, 12, 2, 5, -86, -94, -2, 79, 46, 26, 44, 22, + -59, -88, -19, 54, 48, 13, 14, 4, -51, -112, -37, 67, 71, 21, 38, 29, + -29, -104, -50, 44, 63, 11, 10, 14, -24, -103, -67, 49, 88, 20, 27, 43, + -10, -90, -79, 24, 69, 21, 7, 18, -8, -82, -103, 17, 94, 38, 10, 54, + 12, -70, -97, 1, 68, 37, -4, 27, -6, -56, -104, -21, 82, 67, -3, 46, + 23, -37, -108, -31, 57, 58, -13, 29, 11, -32, -106, -50, 53, 92, -6, 38, + 38, -15, -105, -54, 34, 79, -12, 20, 22, -11, -98, -70, 22, 99, 4, 16, + 48, 14, -99, -75, 15, 82, 2, 0, 44, 8, -93, -80, 0, 84, 29, -3, + 57, 32, -79, -94, 1, 66, 27, -19, 49, 29, -73, -109, -7, 54, 52, -17, + 62, 53, -46, -113, -4, 43, 51, -30, 46, 37, -42, -128, -23, 26, 69, -18, + 51, 59, -2, -122, -30, 24, 66, -27, 31, 51, 1, -128, -48, 13, 71, -11, + 33, 66, 22, -110, -57, 8, 68, -9, 12, 53, 28, -104, -87, -4, 67, 8, + 8, 72, 53, -80, -91, -4, 59, 10, -13, 63, 44, -81, -109, -19, 46, 33, + -6, 76, 57, -43, -104, -24, 36, 42, -26, 55, 51, -34, -126, -39, 19, 58, + -21, 68, 71, -8, -114, -32, 2, 62, -24, 52, 54, -4, -120, -53, -22, 71, + -8, 49, 62, 31, -102, -52, -25, 70, -5, 24, 55, 35, -109, -69, -40, 59, + 16, 25, 65, 55, -80, -70, -37, 47, 23, 7, 48, 51, -73, -97, -48, 30, + 46, 6, 57, 74, -37, -98, -34, 21, 48, -10, 44, 58, -34, -123, -46, -2, + 61, 2, 50, 69, 10, -110, -40, -5, 59, -9, 31, 53, 19, -126, -59, -20, + 62, 8, 32, 64, 49, -105, -59, -16, 58, 2, 17, 50, 45, -102, -83, -31, + 46, 24, 15, 53, 69, -65, -86, -24, 42, 25, -4, 45, 64, -58, -112, -37, + 30, 41, -6, 51, 75, -24, -105, -32, 26, 41, -19, 39, 62, -14, -117, -51, + 7, 54, -13, 35, 78, 19, -105, -47, 9, 58, -19, 21, 69, 18, -113, -66, + -10, 52, -10, 14, 75, 42, -83, -60, -5, 52, 0, -3, 69, 43, -83, -83, + -21, 35, 17, -13, 72, 57, -54, -82, -10, 29, 28, -29, 65, 52, -45, -98, + -21, 1, 40, -30, 64, 63, -7, -94, -9, 1, 51, -36, 51, 54, -8, -115, + -23, -22, 47, -30, 48, 65, 24, -90, -13, -15, 46, -26, 30, 55, 21, -100, + -37, -26, 31, -10, 24, 65, 41, -71, -35, -10, 25, -2, 4, 58, 32, -69, + -61, -16, 2, 8, 1, 67, 42, -33, -56, -1, -1, 20, -13, 59, 33, -28, + -82, -10, -20, 22, -15, 64, 40, -1, -70, 0, -17, 29, -22, 53, 33, 1, + -84, -15, -29, 22, -19, 53, 43, 22, -64, -7, -19, 25, -18, 37, 38, 16, + -73, -30, -33, 11, -14, 32, 50, 31, -45, -17, -15, 16, -4, 16, 43, 23, + -49, -43, -30, -2, -1, 8, 52, 36, -25, -32, -13, -1, 11, -1, 42, 30, + -25, -49, -25, -18, 10, -7, 44, 40, -2, -34, -11, -15, 21, -6, 29, 33, + -5, -54, -29, -30, 13, -6, 29, 46, 15, -32, -10, -18, 16, -1, 13, 36, + 9, -45, -30, -32, 0, 1, 12, 43, 28, -23, -16, -16, 6, 9, 2, 33, + 22, -33, -34, -27, -11, 2, 1, 35, 36, -14, -16, -11, -5, 8, 3, 24, + 32, -19, -30, -29, -17, -4, 1, 20, 43, -5, -14, -13, -4, 0, 7, 11, + 39, -9, -23, -28, -17, -16, 1, 9, 44, 3, -7, -15, -4, -4, 7, 5, + 38, 3, -20, -30, -19, -19, -8, 0, 40, 17, -6, -7, -3, -2, -1, 4, + 32, 16, -20, -21, -26, -17, -18, -3, 28, 32, -7, -1, -9, 4, -9, 3, + 22, 34, -19, -14, -27, -13, -27, -10, 16, 44, -8, 5, -6, 3, -12, 1, + 13, 40, -12, -11, -25, -17, -27, -15, 5, 45, 4, 2, 0, 0, -9, -5, + 6, 38, 2, -17, -14, -20, -24, -23, 0, 38, 19, -4, 11, -4, -7, -10, + 4, 27, 20, -20, -9, -23, -22, -30, -6, 26, 35, -8, 12, 2, -4, -15, + 2, 20, 32, -16, -7, -15, -22, -37, -14, 18, 39, -3, 5, 8, -5, -18, + -2, 18, 34, -4, -14, -4, -21, -35, -25, 15, 36, 8, -4, 21, -5, -17, + -14, 23, 26, 9, -22, 4, -25, -32, -40, 14, 27, 24, -12, 30, 1, -8, + -26, 24, 21, 19, -28, 9, -20, -28, -51, 7, 23, 30, -15, 27, 9, -7, + -32, 16, 25, 23, -21, 4, -8, -27, -50, -10, 25, 29, -9, 13, 24, -7, + -28, -3, 34, 20, -12, -9, 10, -31, -43, -29, 30, 23, 2, -3, 38, -9, + -19, -19, 39, 18, -1, -20, 25, -29, -36, -42, 26, 17, 12, -14, 43, -3, + -15, -29, 35, 19, 6, -28, 27, -18, -36, -48, 16, 17, 15, -15, 39, 12, + -13, -29, 24, 24, 9, -25, 19, -1, -39, -50, 1, 18, 11, -11, 25, 26, + -14, -26, 12, 32, 10, -17, 6, 17, -33, -48, -14, 20, 6, -7, 11, 36, + -9, -26, -1, 34, 11, -9, -4, 25, -25, -49, -26, 19, 4, -4, 5, 41, + 3, -21, -8, 31, 12, -7, -11, 23, -13, -47, -37, 13, 6, -3, 1, 40, + 14, -17, -14, 26, 16, -2, -12, 20, -3, -40, -44, 2, 6, -2, -4, 35, + 24, -9, -19, 19, 17, 2, -13, 16, 5, -29, -48, -7, 4, 3, -7, 28, + 28, 2, -21, 13, 14, 9, -14, 11, 9, -15, -49, -17, -3, 6, -11, 20, + 30, 14, -23, 7, 12, 14, -11, 6, 10, -4, -46, -24, -10, 6, -8, 11, + 29, 24, -15, 0, 11, 14, -4, -2, 11, 3, -37, -36, -13, -3, -2, 2, + 28, 27, -2, -10, 14, 9, 7, -8, 13, 3, -21, -42, -14, -14, 4, -6, + 24, 24, 13, -16, 12, 3, 14, -8, 12, 4, -7, -44, -18, -20, 5, -6, + 18, 22, 23, -13, 6, 2, 13, -4, 5, 5, 1, -36, -26, -20, -1, -1, + 10, 23, 25, -3, -4, 5, 9, 5, -2, 8, 1, -24, -36, -18, -10, 4, + 1, 24, 23, 11, -9, 8, 4, 12, -7, 9, 1, -12, -40, -19, -16, 4, + -4, 21, 21, 16, -9, 6, 2, 13, -4, 6, 6, -4, -33, -24, -18, -2, + -2, 10, 21, 18, 0, -3, 3, 8, 6, -1, 8, 0, -18, -31, -19, -10, + 1, 0, 19, 20, 13, -5, 4, 5, 12, -4, 5, 2, -7, -34, -24, -17, + 1, -4, 13, 20, 21, -3, 2, 5, 14, 0, 2, 4, 0, -26, -28, -20, + -6, -4, 4, 18, 23, 6, -3, 5, 9, 7, -1, 6, 3, -14, -33, -22, + -14, -1, -1, 16, 22, 17, -4, 4, 4, 10, -2, 4, 3, -4, -30, -25, + -19, -2, -2, 11, 20, 23, 0, 0, 2, 10, 3, 1, 4, 1, -23, -30, + -22, -8, -1, 4, 19, 23, 10, -3, 4, 6, 8, -2, 5, 2, -13, -33, + -23, -15, 0, -1, 16, 21, 16, -3, 3, 4, 11, 0, 5, 6, -3, -27, + -25, -19, -4, -2, 9, 19, 19, 2, -3, 2, 8, 6, -1, 8, 0, 0, + 2, 33, 42, 58, 71, 79, 85, 88, 91, 94, 79, 95, 82, 106, 86, 105, + 47, 16, -6, 13, 44, 31, -15, -38, -36, 20, 70, 41, 48, 58, 24, -57, + -127, -119, -102, -126, -128, -111, -78, -82, -88, -87, -60, -66, -98, -104, -99, -97, + -99, -104, -101, -88, -87, -91, -61, -27, -34, -54, -55, -45, -24, -10, -5, -4, + 5, 34, 63, 101, 94, 78, 52, 51, 52, 74, 81, 77, 59, 46, 17, 7, + 39, 53, 47, 42, 66, 83, 73, 52, 28, 22, 11, 8, 11, 0, -15, -23, + -15, -14, -6, 16, 46, 62, 71, 76, 90, 102, 103, 103, 101, 100, 90, 75, + 63, 67, 49, 37, 28, 12, 5, 6, 15, 15, 8, -7, -12, -4, -10, -28, + -24, -17, -25, -50, -64, -81, -103, -116, -116, -113, -95, -72, -54, -41, -47, -65, + -65, -50, -33, -24, -7, 11, 8, -4, -13, -28, -51, -75, -90, -91, -90, -90, + -87, -88, -83, -84, -82, -81, -81, -76, -65, -71, -85, -84, -79, -83, -81, -77, + -72, -70, -65, -66, -66, -65, -66, -68, -61, -56, -51, -36, -13, -3, -5, -8, + -12, -12, 3, 16, 21, 31, 50, 69, 77, 82, 90, 102, 110, 114, 116, 117, + 118, 119, 116, 112, 109, 105, 98, 99, 103, 102, 91, 73, 64, 63, 61, 57, + 51, 40, 24, 35, 57, 75, 84, 79, 65, 37, 4, -26, -45, -57, -54, -46, + -45, -54, -67, -67, -48, -16, 15, 35, 44, 45, 44, 45, 46, 38, 23, 2, + -15, -34, -52, -60, -70, -77, -80, -79, -74, -77, -84, -86, -80, -72, -68, -72, + -80, -87, -92, -96, -101, -104, -104, -101, -93, -90, -89, -86, -85, -84, -83, -82, + -81, -79, -77, -76, -73, -71, -66, -62, -55, -39, -31, -27, -25, -31, -37, -46, + -51, -53, -54, -48, -45, -38, -20, 3, 24, 35, 39, 32, 16, 5, 3, 0, + -6, -13, -13, -11, -2, 14, 28, 40, 50, 53, 50, 55, 64, 74, 90, 105, + 108, 112, 106, 104, 109, 112, 123, 127, 127, 127, 127, 127, 127, 118, 113, 107, + 110, 114, 111, 104, 101, 101, 102, 103, 99, 99, 89, 73, 53, 35, 20, 0, + -22, -43, -63, -77, -82, -76, -65, -48, -36, -29, -24, -25, -29, -37, -40, -49, + -59, -67, -73, -76, -78, -79, -75, -73, -74, -75, -68, -52, -44, -30, -19, -9, + -6, -9, -13, -24, -33, -35, -31, -30, -35, -40, -44, -45, -51, -53, -54, -50, + -50, -47, -42, -50, -55, -54, -56, -56, -54, -54, -49, -48, -41, -32, -28, -18, + -13, -5, 6, 18, 33, 49, 60, 71, 78, 88, 95, 97, 93, 88, 91, 93, + 97, 98, 97, 94, 91, 85, 81, 72, 70, 66, 61, 60, 64, 66, 74, 83, + 92, 102, 108, 109, 107, 102, 97, 95, 91, 87, 80, 74, 67, 62, 61, 58, + 61, 61, 57, 53, 43, 35, 27, 25, 24, 20, 20, 22, 27, 34, 36, 32, + 21, 8, -3, -10, -16, -18, -16, -16, -19, -15, -11, -11, -12, -20, -34, -45, + -59, -72, -80, -89, -94, -95, -102, -111, -114, -111, -111, -108, -106, -104, -101, -98, + -93, -90, -86, -86, -83, -82, -81, -79, -76, -73, -70, -72, -78, -81, -79, -79, + -72, -60, -43, -31, -25, -27, -34, -37, -40, -42, -41, -39, -36, -34, -25, -12, + -4, 5, 12, 16, 17, 15, 13, 6, -4, -7, -8, -6, -1, 4, 7, 9, + 12, 16, 19, 19, 22, 28, 29, 28, 29, 30, 34, 40, 49, 57, 71, 78, + 85, 92, 96, 95, 89, 85, 86, 93, 99, 104, 102, 100, 94, 85, 77, 73, + 69, 66, 63, 60, 60, 59, 57, 52, 47, 41, 31, 18, 6, -3, -7, -11, + -12, -14, -18, -22, -23, -22, -24, -30, -37, -41, -44, -50, -56, -64, -67, -65, + -62, -58, -58, -58, -59, -61, -62, -66, -72, -78, -79, -77, -73, -68, -64, -61, + -56, -53, -54, -52, -52, -57, -63, -69, -70, -68, -65, -62, -59, -57, -56, -58, + -60, -61, -63, -64, -62, -61, -60, -58, -54, -49, -45, -42, -39, -36, -32, -28, + -22, -13, -7, -3, 2, 13, 28, 41, 52, 64, 71, 73, 73, 70, 64, 61, + 60, 64, 66, 65, 66, 64, 61, 60, 62, 65, 64, 66, 67, 67, 68, 66, + 64, 66, 68, 73, 76, 74, 72, 66, 58, 52, 46, 42, 38, 38, 41, 47, + 52, 52, 48, 45, 42, 40, 38, 34, 29, 27, 26, 28, 29, 28, 29, 30, + 31, 28, 24, 21, 19, 17, 14, 10, 6, 3, -4, -9, -15, -19, -26, -33, + -40, -49, -55, -60, -65, -70, -73, -72, -72, -71, -70, -71, -75, -78, -81, -83, + -86, -86, -85, -84, -82, -80, -77, -72, -69, -66, -63, -61, -61, -61, -61, -61, + -60, -58, -53, -48, -42, -36, -30, -28, -30, -32, -33, -32, -31, -28, -22, -18, + -10, -5, 0, 3, 6, 11, 16, 19, 22, 24, 26, 27, 29, 34, 40, 46, + 48, 48, 48, 45, 40, 36, 33, 31, 33, 35, 40, 48, 55, 62, 68, 73, + 76, 78, 78, 77, 79, 82, 85, 87, 87, 87, 86, 86, 86, 83, 78, 71, + 63, 55, 48, 44, 39, 36, 36, 36, 35, 32, 28, 24, 18, 13, 9, 6, + 4, 1, -2, -5, -11, -17, -20, -21, -20, -21, -24, -28, -32, -34, -33, -33, + -35, -37, -40, -43, -47, -52, -58, -63, -69, -74, -77, -80, -81, -82, -81, -80, + -77, -74, -69, -62, -54, -48, -48, -51, -54, -57, -57, -57, -56, -55, -55, -56, + -57, -56, -55, -54, -54, -54, -54, -52, -49, -45, -41, -38, -34, -31, -29, -27, + -24, -20, -17, -11, -7, -3, 0, 5, 10, 16, 22, 27, 31, 34, 38, 42, + 44, 45, 48, 50, 52, 57, 61, 64, 64, 65, 65, 63, 60, 57, 55, 55, + 58, 61, 63, 65, 67, 69, 71, 74, 77, 79, 79, 77, 74, 71, 68, 66, + 63, 60, 57, 55, 51, 46, 40, 36, 30, 25, 20, 17, 16, 17, 16, 14, + 12, 10, 7, 3, -1, -5, -11, -15, -17, -18, -18, -19, -21, -25, -29, -32, + -33, -33, -36, -39, -43, -46, -50, -53, -56, -58, -59, -60, -61, -62, -63, -65, + -66, -67, -68, -70, -72, -72, -70, -67, -63, -61, -60, -60, -58, -56, -54, -53, + -52, -52, -52, -51, -50, -49, -47, -45, -43, -40, -37, -35, -34, -32, -29, -25, + -21, -18, -14, -9, -4, 0, 4, 7, 11, 15, 18, 21, 25, 28, 33, 37, + 41, 44, 46, 47, 47, 46, 46, 45, 43, 42, 42, 43, 46, 48, 49, 50, + 52, 55, 59, 62, 65, 66, 67, 68, 69, 69, 70, 72, 74, 74, 73, 72, + 71, 69, 65, 61, 57, 53, 50, 46, 43, 38, 35, 32, 28, 23, 19, 17, + 17, 15, 13, 11, 9, 5, 1, -3, -6, -9, -12, -14, -17, -19, -23, -27, + -31, -35, -38, -40, -43, -46, -48, -52, -55, -57, -61, -64, -66, -67, -68, -69, + -70, -70, -70, -69, -69, -70, -71, -70, -66, -62, -59, -55, -52, -50, -46, -43, + -41, -38, -36, -35, -35, -34, -33, -33, -33, -33, -31, -30, -28, -26, -25, -24, + -21, -20, -20, -19, -19, -18, -17, -16, -15, -13, -11, -8, -3, 2, 9, 15, + 21, 27, 33, 38, 41, 45, 48, 51, 53, 55, 56, 56, 56, 56, 56, 56, + 56, 55, 57, 58, 60, 61, 62, 62, 64, 66, 68, 69, 71, 72, 73, 74, + 72, 70, 67, 63, 60, 57, 54, 50, 46, 41, 36, 31, 27, 23, 19, 16, + 14, 12, 11, 9, 8, 5, 2, -1, -4, -8, -10, -15, -18, -19, -20, -22, + -22, -23, -23, -24, -26, -29, -31, -33, -35, -36, -37, -38, -41, -44, -46, -48, + -50, -52, -54, -56, -59, -61, -63, -63, -64, -65, -64, -63, -62, -61, -60, -59, + -58, -57, -58, -57, -57, -55, -53, -50, -49, -47, -46, -43, -40, -37, -33, -31, + -28, -26, -23, -20, -16, -14, -12, -9, -5, -2, 1, 5, 9, 13, 17, 21, + 24, 26, 29, 32, 35, 37, 37, 38, 39, 41, 43, 44, 45, 46, 48, 50, + 51, 53, 52, 52, 50, 48, 47, 46, 46, 46, 46, 47, 48, 49, 51, 54, + 56, 58, 60, 61, 62, 62, 62, 61, 59, 57, 55, 54, 53, 52, 51, 49, + 46, 41, 36, 31, 27, 22, 18, 14, 11, 9, 6, 3, 0, -2, -5, -8, + -11, -16, -20, -25, -28, -31, -34, -37, -39, -41, -41, -42, -42, -42, -43, -45, + -46, -47, -49, -50, -52, -54, -56, -57, -58, -60, -61, -63, -64, -64, -64, -63, + -63, -61, -59, -58, -57, -55, -54, -53, -52, -52, -51, -50, -49, -47, -46, -45, + -44, -42, -40, -38, -35, -32, -30, -28, -25, -22, -19, -17, -15, -12, -9, -5, + -1, 3, 7, 11, 15, 19, 23, 25, 27, 30, 34, 36, 37, 38, 39, 40, + 42, 44, 45, 46, 47, 49, 50, 52, 53, 52, 51, 49, 47, 47, 46, 46, + 46, 47, 47, 48, 50, 52, 55, 57, 59, 61, 62, 62, 62, 61, 60, 58, + 56, 54, 54, 53, 51, 50, 47, 44, 39, 34, 29, 25, 20, 16, 13, 10, + 7, 4, 2, -1, -3, -6, -9, -14, -18, -22, -26, -30, -33, -35, -38, -40, + -41, -41, -42, -42, -43, -44, -46, -47, -48, -49, -51, -53, -55, -56, -57, -59, + -60, -62, -63, -64, -64, -63, -63, -62, -60, -59, -57, -56, -55, -53, -52, -52, + -51, -51, -50, -48, -46, -45, -44, -43, -41, -39, -36, -34, -31, -29, -26, -24, + -21, -16, -1, -2, -1, -3, 1, -2, -2, -4, 2, 6, 2, -2, -2, 0, + 7, 8, 4, -2, -2, 6, 5, 6, 0, -2, 5, 12, 10, 0, -5, -3, + 5, 10, 9, -7, -8, -7, 5, 8, 3, -9, -13, -5, 3, 5, -5, -9, + -4, 0, 6, 0, -4, -11, -7, 3, 4, 0, -5, 0, -1, 5, 1, 4, + -6, -5, -3, 12, 9, -2, -10, 4, 11, 8, -4, -5, -9, -6, 1, 19, + 13, -2, -22, 4, 9, 6, -26, -4, 3, 12, -9, 0, 2, 0, -15, 4, + 8, -8, -20, 0, 15, 8, -13, -2, -4, -4, -2, 12, 3, -14, -18, 1, + 21, 13, -9, -25, -8, 17, 15, 5, -14, -17, 5, 19, 13, -15, -17, -3, + 10, 20, 10, -27, -19, 5, 11, 12, 3, -13, -17, -1, 6, -3, -2, 1, + -1, -11, -17, 7, 7, -7, -7, -13, 9, 0, -5, 9, -5, -9, 6, 5, + -2, -16, -5, 15, 17, -10, -20, 1, 11, 14, -1, 1, 10, -11, -8, -1, + 18, 13, -2, -12, 1, -16, -2, 34, 27, -28, -42, -3, 42, 26, -14, -39, + -19, 7, 26, 25, -16, -55, -26, 32, 57, 4, -69, -48, 6, 75, 29, -51, + -67, -32, 51, 56, 7, -57, -75, 14, 63, 43, -29, -82, -27, 31, 56, 28, + -43, -81, -31, 59, 85, 1, -100, -59, 8, 102, 41, -42, -92, -52, 72, 79, + 29, -103, -85, -1, 117, 49, -54, -113, 7, 24, 94, -28, -39, -84, 39, 28, + 61, -44, -28, -67, 61, 23, 35, -40, -23, -37, 6, 38, 69, -42, -61, -53, + 58, 86, 2, -93, -24, 19, 72, 17, -19, -87, 45, 10, 64, -13, -45, -57, + 38, 48, 36, -51, -35, -37, 46, 26, 37, -73, -28, -12, 44, 22, 27, -84, + -22, 6, 70, 17, -24, -82, -7, 26, 79, 9, -63, -78, 6, 90, 68, -55, + -118, -3, 92, 62, -10, -73, -50, 14, 110, 15, -5, -118, 5, 69, 53, 22, + -81, -45, 29, 47, 80, -69, -28, -52, 58, 66, -1, -25, -59, -22, 107, 2, + 43, -108, -13, 20, 59, 56, -58, -66, -7, 34, 114, -42, -63, -50, 42, 69, + 44, -63, -37, -50, 114, 27, 18, -49, -81, 20, 74, 51, -14, -102, -4, 40, + 70, 38, -64, -73, 11, 60, 76, -41, -30, -78, 42, 46, 68, -63, -48, -56, + 89, 43, 28, -100, -53, 41, 60, 11, -6, -76, -16, 44, 52, 9, -67, -48, + 10, 69, 30, -1, -84, -4, 36, 72, -23, -22, -27, -33, 55, 74, -11, -86, + -1, 27, 36, 31, -7, -101, 49, 5, 66, -7, -46, -39, 9, 64, 44, -63, + -33, -22, 55, 23, 43, -79, -24, 5, 29, 54, -14, -59, -53, 63, 32, 20, + -34, -32, -36, 93, -2, 20, -35, -38, 18, 51, 61, -94, 15, -14, 17, 69, + 5, -87, 16, 28, 34, 1, 34, -57, -53, 118, -22, 34, -10, -71, 23, 70, + 25, -29, -7, -19, -3, 117, -33, -12, -21, -19, 43, 84, -38, -57, 33, 0, + 32, 41, -7, -103, 85, 2, 2, 58, -14, -103, 103, 7, -17, 34, -32, -59, + 71, 51, -78, 76, -65, -30, 63, 48, -66, 9, -11, -28, 52, 50, -72, -37, + 73, -61, 75, 7, -51, -44, 73, -3, -11, 40, -78, 7, 63, -15, -16, 30, + -53, 12, 38, 12, -42, 39, -63, 47, 23, 0, -23, -11, 8, -25, 60, -37, + -15, -3, -9, 12, 27, -14, -40, 22, 12, 14, 15, -31, -14, 15, 23, -12, + 14, -31, 19, 13, 32, -39, 27, -51, 43, 8, 0, 5, -26, 16, 4, 19, + -24, 17, -18, 6, -2, 49, -67, 39, -1, -30, 46, -13, -16, -9, 21, -17, + 27, 2, -34, 19, -3, 24, 8, -38, 13, -10, 22, 15, -34, 2, 4, -10, + 18, 14, -15, -15, 26, -12, 28, -21, 0, -6, 0, 7, 0, -15, 6, -2, + -18, 9, 8, -18, -15, 59, -94, 81, -40, -24, 14, -18, 25, -15, 4, -21, + -9, 24, -20, 3, 3, -52, 56, -29, 4, 5, -51, 45, -50, 73, -75, 13, + 17, -48, 38, -10, -16, 5, 4, -22, 3, 17, -27, -23, 42, -30, -5, 41, + -53, 10, 23, -28, 1, 29, -47, 9, 13, -3, -18, 9, -13, -11, 18, 12, + -53, 28, 1, -41, 41, 7, -61, 32, 0, -34, 16, 9, -74, 45, -23, -33, + 22, 39, -104, 49, 23, -96, 83, 5, -46, 36, -4, -45, 54, -25, -26, 21, + 2, -39, 51, -25, -25, 43, -22, -25, 30, -2, -32, 39, 14, -69, 42, 22, + -78, 60, 23, -83, 33, 44, -74, 19, 69, -113, 43, 53, -88, 51, 17, -74, + 42, 1, -38, 4, 39, -67, 12, 35, -39, -23, 73, -82, -5, 67, -71, -5, + 42, -36, -48, 78, -64, -4, 40, -48, -7, 50, -80, 17, 31, -56, 9, 6, + -18, -36, 43, -37, -29, 47, -47, -18, 33, -29, -27, 40, -30, -37, 51, -46, + -25, 61, -66, 7, 28, -48, 30, -15, -8, -6, 17, -14, -9, 26, -23, 4, + 9, -15, 12, -9, 16, -22, 7, 22, -51, 59, -29, -23, 54, -49, 6, 20, + -19, -11, 17, -3, -30, 32, -27, -5, 16, -28, 4, 4, -27, 32, -46, 27, + -18, -8, 11, -25, 18, -6, -17, 10, 1, -18, 24, -33, 10, 8, -12, -10, + 21, -19, 0, 8, -18, 14, 11, -44, 39, -22, -4, -6, 11, -15, -13, 17, + -17, -6, 13, -22, -1, 7, -5, -8, 0, 4, -24, 29, -23, 0, 20, -25, + -8, 30, -34, 31, -29, 11, -9, 21, -15, -1, 10, -9, -11, 32, -23, -2, + -14, 27, -19, 10, -4, -23, 14, 13, -45, 48, -44, 11, -4, -7, -3, 4, + -2, -34, -8, 37, -41, 20, -24, -4, -10, 2, 4, 12, -28, -30, 9, 32, + -16, 6, -46, -23, 60, 0, -22, -3, -23, -15, 48, 12, -34, -17, -18, 10, + 46, -1, -56, -8, 12, 9, 18, 13, -72, -3, 26, 9, 28, -14, -89, 15, + 67, -18, 1, -19, -52, 45, 26, -8, -5, -25, -25, 36, 38, -13, -36, -18, + -6, 55, 23, -51, -14, 4, 6, 25, 24, -41, -44, 38, 19, 10, 10, -59, + -14, 42, 1, 6, -8, -43, -1, 43, 10, -30, -10, -36, 18, 35, -20, -14, + -11, -19, 9, 20, -5, -22, -9, -6, 13, 26, -30, -23, 4, 1, 20, 9, + -20, -22, 3, -1, 17, 28, -26, -25, 16, -2, -4, 12, -10, -16, 24, -2, + -18, 17, -27, -1, 36, -6, -7, -4, -26, 6, 29, -3, -17, -6, -4, 18, + 18, -26, -10, -4, 6, 30, -1, -6, -24, 0, 24, 12, 2, -16, -25, 13, + 32, -3, -4, -3, -24, 15, 16, -7, 8, -20, -13, 36, 9, -24, -11, -10, + 10, 20, -1, -13, -10, -9, 20, 17, -12, -9, -15, 9, 20, -11, -14, -6, + 5, 10, 6, 5, -7, -11, 7, 19, 1, 3, -11, -10, 24, 14, -16, 2, + -9, 11, 14, 7, -1, -11, -4, 15, 24, 3, -24, -4, 4, 15, 13, -3, + -15, 0, 15, 8, 2, 0, -19, 16, 12, -1, 7, -13, -2, 18, 3, -3, + 5, -9, -10, 12, 9, -2, 8, -9, 4, 9, 6, 1, -8, 10, 4, -2, + 11, -14, 3, 5, 1, 9, 4, -15, 0, 10, 1, 5, -4, -10, 3, 7, + -1, 8, -13, 1, 4, 10, 6, -9, -3, 1, 6, 14, -3, -4, 4, -10, + 10, 13, -1, -4, 5, -3, 10, 13, -13, 4, 7, 1, 8, -1, 1, 4, + 5, 4, 11, -5, -2, 1, 8, 6, 1, 3, -1, -5, 11, 3, -3, 4, + -5, -1, 17, -4, -2, 6, -10, 10, 10, -4, 2, 3, -10, 10, 5, -2, + -2, -1, 4, 3, -1, -2, -4, 1, 6, -4, 6, -4, -10, 8, 2, -4, + 6, -4, -4, 12, -2, 2, 6, -9, 3, 2, 0, 7, -5, -3, 3, 2, + 4, -4, -2, 7, 3, 5, 9, -3, 1, 12, -3, 7, 6, -9, 4, 9, + -4, 12, 1, -7, 9, 2, 1, 10, -3, 1, 0, 0, 8, 0, -1, 5, + -2, 8, 1, -3, 10, 2, 0, 11, -4, -1, 6, -3, 2, 3, -5, 4, + 0, -5, 5, -3, 1, 3, 0, 4, -3, -3, 4, -2, -2, 5, -2, -1, + 6, -5, 2, 3, -4, 4, -2, -3, 11, -8, 0, 5, -1, 1, 0, -3, + 4, 2, 2, 6, -2, 4, 5, -3, 4, 7, -4, 11, -1, 0, 3, 0, + 3, 7, -2, 5, 1, 0, 6, 3, 2, 4, -1, 2, 6, 0, 3, 5, + -4, 6, 0, 2, 7, -4, -1, 2, -2, 7, 1, -1, 1, -2, 2, 4, + -5, 0, 4, -1, 2, -1, -2, 1, -2, 3, 2, -3, 3, -1, -4, 5, + -2, -2, 3, 0, -1, 2, -5, 2, 1, -4, 0, 1, -3, 5, -2, 2, + 2, -3, 1, 3, -2, 3, 1, -2, 4, 1, 2, 5, -2, 3, 1, 2, + 5, 0, -1, 4, 0, 1, 4, 2, 4, 4, -2, 0, 2, 3, 5, 0, + 0, 0, 1, 5, -2, -3, 4, 0, 1, 2, -2, -4, -4, -5, -6, -7, + -8, -9, -10, -11, -12, -13, -13, -14, -16, -18, -21, -25, -29, -34, -36, -38, + -39, -40, -42, -44, -47, -50, -53, -56, -58, -59, -58, -55, -50, -44, -38, -31, + -24, -18, -13, -9, -6, -3, 0, 3, 6, 9, 13, 17, 21, 27, 33, 42, + 53, 63, 74, 83, 91, 98, 104, 108, 111, 113, 115, 118, 119, 121, 123, 125, + 126, 127, 127, 127, 127, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, + 126, 125, 123, 121, 118, 114, 111, 107, 104, 101, 100, 99, 98, 98, 98, 98, + 98, 99, 98, 98, 97, 95, 92, 88, 81, 73, 63, 54, 46, 39, 33, 29, + 27, 25, 24, 22, 20, 18, 14, 10, 5, 0, -5, -8, -8, -7, -3, 2, + 8, 14, 19, 23, 26, 28, 29, 30, 31, 32, 32, 31, 30, 28, 24, 20, + 14, 9, 4, -1, -4, -7, -9, -10, -12, -13, -15, -17, -19, -22, -24, -25, + -25, -23, -21, -19, -17, -15, -15, -14, -15, -15, -16, -17, -17, -17, -16, -16, + -16, -17, -19, -22, -25, -30, -35, -39, -44, -47, -50, -53, -56, -58, -61, -63, + -64, -65, -65, -63, -60, -55, -49, -43, -38, -34, -32, -31, -31, -32, -33, -35, + -36, -37, -37, -36, -35, -34, -34, -34, -36, -39, -43, -49, -55, -61, -67, -72, + -77, -81, -85, -88, -90, -92, -94, -94, -95, -94, -94, -94, -94, -95, -96, -98, + -100, -102, -104, -105, -107, -108, -108, -109, -110, -110, -110, -109, -109, -109, -108, -108, + -109, -109, -109, -109, -108, -108, -107, -106, -106, -105, -105, -105, -105, -105, -105, -104, + -103, -101, -98, -93, -88, -82, -76, -70, -64, -58, -52, -47, -42, -38, -34, -31, + -29, -27, -25, -22, -18, -13, -7, -1, 6, 13, 20, 26, 32, 37, 41, 45, + 48, 51, 55, 58, 63, 68, 73, 77, 82, 85, 89, 91, 94, 96, 97, 98, + 99, 99, 99, 100, 100, 100, 101, 101, 101, 101, 101, 101, 99, 97, 95, 93, + 90, 87, 84, 81, 77, 73, 67, 60, 51, 40, 29, 17, 6, -5, -14, -23, + -31, -38, -45, -52, -58, -65, -70, -75, -80, -84, -87, -90, -92, -94, -95, -96, + -97, -98, -100, -101, -102, -102, -103, -103, -104, -104, -103, -102, -100, -97, -93, -89, + -86, -82, -79, -77, -75, -72, -70, -67, -63, -59, -53, -47, -40, -33, -26, -20, + -14, -9, -6, -3, 0, 3, 6, 9, 13, 17, 21, 26, 31, 37, 44, 51, + 58, 64, 70, 75, 79, 83, 86, 88, 90, 92, 93, 95, 96, 97, 98, 100, + 100, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 102, 102, + 102, 101, 100, 98, 96, 94, 92, 90, 89, 88, 88, 87, 87, 87, 87, 87, + 86, 85, 84, 82, 79, 76, 72, 67, 61, 55, 49, 43, 39, 35, 32, 30, + 29, 27, 25, 24, 21, 18, 15, 12, 8, 5, 3, 3, 4, 6, 9, 12, + 15, 18, 21, 23, 25, 27, 28, 30, 31, 31, 31, 30, 28, 25, 22, 18, + 14, 10, 7, 5, 3, 1, 0, -2, -4, -6, -9, -11, -14, -16, -17, -17, + -16, -14, -12, -11, -9, -9, -9, -10, -11, -12, -13, -14, -15, -15, -16, -16, + -17, -19, -22, -26, -30, -34, -38, -42, -45, -48, -50, -52, -53, -54, -55, -56, + -56, -55, -53, -50, -46, -42, -38, -35, -32, -31, -30, -31, -31, -33, -34, -35, + -36, -36, -36, -35, -35, -35, -36, -38, -41, -45, -49, -54, -59, -64, -68, -73, + -76, -80, -83, -86, -88, -89, -90, -91, -91, -91, -92, -92, -93, -95, -96, -98, + -100, -101, -102, -103, -104, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -104, -104, -103, -102, -102, -101, -100, -100, -100, -99, -99, -99, -98, -96, + -94, -91, -86, -82, -76, -71, -65, -59, -53, -48, -42, -37, -32, -28, -25, -22, + -19, -16, -13, -8, -3, 3, 9, 16, 22, 28, 35, 40, 45, 49, 53, 56, + 60, 63, 67, 71, 76, 80, 85, 88, 92, 94, 97, 99, 100, 102, 103, 103, + 104, 104, 104, 104, 105, 105, 105, 105, 105, 104, 103, 101, 99, 97, 94, 91, + 87, 84, 80, 76, 71, 65, 57, 48, 39, 28, 18, 8, -2, -11, -19, -27, + -34, -41, -47, -54, -60, -65, -70, -75, -79, -82, -85, -87, -89, -91, -92, -94, + -95, -96, -97, -98, -99, -100, -100, -100, -100, -100, -98, -96, -94, -90, -87, -84, + -81, -78, -76, -73, -71, -68, -65, -61, -57, -52, -46, -40, -33, -27, -21, -15, + -11, -7, -4, 0, 3, 7, 11, 15, 20, 24, 29, 35, 41, 48, 54, 61, + 67, 72, 77, 81, 85, 88, 90, 92, 94, 95, 97, 98, 99, 101, 102, 103, + 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, + 104, 103, 101, 99, 98, 96, 95, 93, 93, 92, 92, 91, 91, 90, 90, 88, + 87, 86, 84, 81, 78, 74, 69, 64, 59, 54, 49, 45, 42, 39, 37, 35, + 33, 31, 29, 27, 24, 21, 18, 15, 13, 11, 11, 12, 13, 15, 17, 20, + 22, 24, 25, 27, 28, 29, 30, 31, 31, 31, 30, 28, 26, 23, 20, 17, + 14, 11, 9, 8, 6, 5, 3, 1, -1, -4, -6, -8, -10, -11, -11, -11, + -10, -9, -8, -8, -8, -9, -10, -11, -13, -14, -15, -16, -17, -17, -18, -20, + -22, -25, -28, -31, -35, -38, -41, -44, -46, -47, -49, -50, -51, -52, -52, -52, + -51, -49, -47, -44, -40, -38, -35, -33, -33, -32, -33, -33, -34, -35, -36, -37, + -38, -38, -38, -38, -39, -40, -42, -45, -49, -53, -57, -61, -65, -69, -73, -76, + -79, -82, -85, -87, -88, -89, -90, -91, -91, -92, -93, -94, -95, -97, -98, -99, + -100, -101, -102, -103, -103, -104, -104, -104, -104, -104, -104, -104, -104, -104, -103, -103, + -103, -102, -102, -101, -100, -99, -99, -98, -97, -97, -96, -96, -95, -94, -92, -89, + -86, -82, -77, -72, -67, -61, -56, -50, -45, -39, -34, -29, -25, -21, -18, -14, + -11, -5, 4, 8, 14, 19, 25, 31, 37, 42, 47, 52, 57, 61, 65, 69, + 72, 76, 79, 83, 86, 89, 92, 95, 97, 99, 101, 102, 104, 104, 105, 106, + 106, 106, 106, 106, 106, 105, 104, 104, 103, 101, 99, 97, 95, 92, 89, 85, + 81, 77, 73, 68, 62, 57, 50, 43, 35, 28, 19, 12, 4, -4, -11, -18, + -25, -32, -38, -44, -50, -55, -61, -65, -69, -73, -77, -80, -82, -85, -87, -89, + -91, -92, -93, -95, -95, -96, -97, -97, -97, -96, -96, -95, -93, -92, -90, -88, + -86, -84, -82, -79, -77, -74, -71, -68, -64, -60, -55, -51, -46, -41, -36, -31, + -26, -21, -16, -11, -7, -2, 3, 8, 14, 19, 25, 30, 36, 42, 47, 53, + 58, 63, 68, 72, 76, 79, 82, 85, 87, 89, 91, 93, 95, 96, 98, 99, + 101, 102, 103, 103, 104, 105, 105, 105, 106, 106, 106, 106, 106, 106, 106, 105, + 105, 105, 104, 103, 103, 102, 101, 100, 99, 99, 98, 97, 96, 95, 93, 92, + 91, 89, 87, 85, 82, 79, 76, 73, 70, 67, 63, 60, 58, 55, 53, 50, + 48, 46, 44, 41, 39, 37, 34, 32, 31, 29, 28, 28, 27, 28, 28, 28, + 28, 29, 29, 29, 29, 30, 30, 30, 29, 29, 28, 27, 26, 25, 23, 22, + 20, 19, 17, 16, 15, 13, 12, 10, 8, 6, 4, 2, 1, -1, -2, -4, + -5, -6, -7, -9, -10, -12, -13, -15, -17, -19, -21, -22, -24, -26, -27, -29, + -31, -32, -34, -36, -38, -40, -42, -43, -45, -46, -47, -47, -48, -48, -49, -49, + -48, -48, -47, -46, -45, -44, -44, -43, -43, -43, -44, -44, -45, -46, -47, -48, + -49, -50, -51, -52, -53, -55, -57, -59, -61, -64, -67, -70, -72, -75, -78, -80, + -82, -84, -86, -88, -90, -91, -92, -94, -95, -96, -97, -98, -98, -99, -100, -101, + -101, -101, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -101, -101, -100, -100, + -99, -98, -97, -96, -95, -94, -93, -92, -91, -89, -88, -87, -85, -83, -81, -78, + -75, -71, -67, -63, -58, -54, -49, -44, -39, -33, -28, -23, -18, -13, -8, -3, + 2, 7, 13, 18, 23, 29, 35, 40, 45, 51, 55, 60, 64, 68, 71, 75, + 78, 82, 85, 88, 91, 93, 96, 98, 100, 101, 103, 104, 105, 105, 106, 106, + 106, 106, 105, 105, 104, 104, 103, 101, 100, 98, 95, 93, 90, 86, 83, 79, + 75, 70, 65, 60, 54, 47, 40, 33, 25, 18, 10, 2, -5, -12, -19, -26, + -32, -38, -44, -50, -55, -60, -65, -69, -73, -76, -79, -82, -84, -87, -89, -90, + -92, -93, -94, -95, -96, -96, -96, -96, -96, -95, -94, -93, -91, -90, -88, -86, + -84, -81, -79, -76, -74, -70, -67, -63, -59, -54, -49, -44, -39, -34, -29, -24, + -19, -14, -10, -5, -2, -1, 3, -2, 1, -3, 4, -2, 0, 0, 8, 0, + 10, -9, -7, -128, -72, 13, -44, -13, -18, 4, -4, 12, 3, 31, 4, 66, + 74, 38, 38, 36, 30, 25, 22, 18, 13, 7, 5, 2, 1, -5, -7, -9, + -9, -11, -14, -12, -14, -12, -16, -13, -16, -13, -14, -16, -11, -14, -10, -13, + -11, -13, -8, -8, -6, -6, -5, 0, -6, -3, -3, 3, -4, 6, -13, 17, + -5, -5, 15, -1, -23, 6, 23, 28, 35, 13, 41, -3, 24, 25, -4, 6, + 30, 4, 18, 10, -32, -64, -120, -64, -91, -76, -33, -45, -58, 2, 1, -19, + -14, 18, 48, 50, 59, 51, 53, 47, 46, 41, 37, 35, 26, 28, 19, 21, + 10, 13, 9, 3, 5, -4, 2, -5, -3, -8, -5, -8, -8, -10, -9, -10, + -10, -12, -7, -17, -8, -11, -14, -5, -15, -5, -4, -10, -13, 11, -22, 3, + -3, -4, -5, -11, 13, 2, -16, -9, -5, -12, 27, 15, 17, 21, 20, 20, + 8, 14, 13, 0, 10, 35, 10, -1, -12, -52, -89, -78, -58, -85, -74, -51, + -25, -25, -28, -30, -14, 12, 29, 44, 44, 51, 46, 50, 49, 43, 38, 36, + 32, 29, 23, 19, 17, 14, 10, 6, 6, 2, 4, -8, 3, -7, -3, -6, + -7, -11, -4, -12, -7, -6, -20, 1, -15, -14, -8, -7, -10, -10, -10, 2, + -14, -12, 7, -10, -8, -5, -6, 1, 6, -2, -12, -19, -3, 3, 2, 19, + 19, 14, 19, 24, 13, 5, 12, 12, 13, 21, 29, 5, -18, -43, -48, -64, + -82, -82, -71, -44, -37, -37, -40, -33, -23, 5, 20, 33, 38, 45, 48, 51, + 46, 44, 41, 38, 36, 27, 26, 24, 19, 13, 16, 5, 11, 4, -1, 3, + -4, -3, 1, -9, -7, -2, -9, -6, -13, -4, -6, -17, -8, -6, -15, -10, + -5, -10, -8, -10, -5, -7, -5, -2, -14, -10, 3, 5, -4, -3, -10, -17, + -10, 3, 4, 5, 18, 18, 18, 16, 16, 10, 5, 11, 23, 26, 22, 7, + -9, -16, -37, -62, -80, -76, -65, -46, -43, -43, -51, -41, -24, -4, 11, 24, + 32, 41, 47, 43, 49, 45, 41, 40, 33, 31, 31, 20, 23, 18, 11, 16, + 9, 5, 3, 2, 5, -2, -7, 2, -4, -10, -3, -5, -8, -10, -7, -8, + -14, -10, -8, -11, -9, -6, -14, -10, -2, -3, -12, -10, -7, -9, 0, 6, + -1, -11, -12, -11, -10, -7, 4, 7, 12, 17, 20, 18, 13, 6, 8, 19, + 22, 24, 17, 14, 5, -8, -29, -54, -77, -71, -55, -50, -44, -54, -57, -39, + -32, -15, 3, 15, 31, 34, 39, 47, 45, 44, 44, 37, 37, 33, 28, 27, + 18, 20, 21, 10, 7, 10, 7, 1, 2, 2, 0, -5, 0, -2, -7, -3, + -5, -8, -8, -5, -13, -13, -5, -6, -14, -11, -8, -8, -5, -5, -9, -17, + -10, -2, 0, -2, -1, -9, -12, -14, -12, -6, -1, 3, 11, 19, 19, 14, + 7, 9, 13, 17, 23, 22, 19, 21, 12, 2, -21, -55, -65, -59, -52, -47, + -56, -56, -50, -53, -38, -22, -7, 10, 18, 29, 36, 40, 45, 43, 38, 41, + 40, 32, 27, 26, 26, 19, 17, 17, 12, 9, 9, 6, 2, 4, 4, -1, + -2, 2, -3, -3, 0, -2, -8, -9, -7, -7, -7, -6, -8, -12, -6, -4, + -7, -12, -13, -10, -5, -2, -2, -3, -8, -12, -15, -16, -14, -13, -7, 2, + 8, 11, 8, 4, 5, 8, 13, 20, 22, 23, 24, 23, 19, 6, -13, -23, + -29, -32, -37, -42, -46, -53, -57, -53, -49, -39, -25, -12, -1, 10, 21, 28, + 32, 35, 36, 34, 34, 32, 28, 25, 24, 21, 18, 19, 16, 10, 7, 8, + 9, 8, 6, 5, 2, 3, 6, 7, 5, 2, -2, -4, -3, -1, -3, -4, + -3, -1, -3, -8, -13, -14, -11, -4, -1, -2, -4, -6, -11, -16, -19, -21, + -21, -17, -9, -3, 0, 0, -3, -5, -2, 4, 11, 18, 23, 25, 26, 24, + 17, 10, 5, -1, -7, -12, -20, -29, -37, -44, -51, -55, -54, -47, -39, -28, + -16, -4, 9, 18, 23, 27, 31, 31, 30, 30, 28, 23, 20, 22, 23, 20, + 14, 10, 9, 9, 10, 9, 6, 4, 4, 6, 9, 10, 7, 2, 0, 1, + -1, -2, -2, -1, 1, 2, -2, -10, -14, -11, -8, -5, -2, -1, -3, -6, + -9, -14, -20, -23, -23, -18, -11, -5, -3, -4, -6, -8, -4, 2, 7, 14, + 21, 25, 25, 23, 19, 13, 8, 4, -1, -9, -15, -23, -31, -39, -48, -53, + -51, -48, -44, -34, -20, -8, 3, 12, 20, 24, 27, 30, 31, 29, 24, 22, + 22, 23, 22, 18, 13, 10, 10, 11, 11, 9, 5, 3, 5, 10, 11, 9, + 7, 5, 4, 2, 0, -3, -1, 3, 5, 2, -3, -8, -11, -10, -7, -5, + -3, -2, -2, -4, -7, -14, -20, -24, -24, -19, -12, -6, -6, -8, -8, -8, + -7, -2, 5, 12, 19, 23, 24, 22, 20, 16, 12, 7, 1, -5, -10, -17, + -27, -36, -42, -47, -52, -51, -45, -36, -26, -12, 0, 9, 15, 21, 27, 30, + 29, 26, 23, 22, 23, 23, 21, 17, 12, 9, 10, 12, 10, 6, 3, 4, + 7, 10, 11, 9, 8, 9, 7, 2, -1, 0, 2, 6, 6, 3, -2, -7, + -9, -8, -6, -4, -3, -1, -1, -2, -6, -13, -21, -26, -24, -18, -13, -10, + -9, -10, -11, -11, -10, -5, 3, 10, 17, 21, 22, 22, 21, 19, 14, 8, + 5, 1, -7, -14, -21, -29, -38, -45, -49, -50, -48, -40, -28, -16, -6, 3, + 11, 19, 26, 27, 26, 24, 22, 22, 24, 24, 20, 14, 11, 11, 12, 11, + 8, 4, 3, 6, 8, 9, 9, 10, 11, 10, 6, 2, 0, 2, 5, 8, + 7, 3, -2, -5, -6, -7, -6, -4, -3, -1, 1, 1, -5, -13, -21, -24, + -23, -18, -14, -12, -11, -12, -13, -14, -13, -8, 0, 8, 14, 17, 21, 22, + 21, 18, 15, 12, 8, 2, -3, -9, -16, -24, -32, -40, -47, -51, -49, -41, + -30, -21, -12, -1, 9, 17, 23, 25, 24, 21, 21, 24, 24, 22, 17, 12, + 11, 13, 12, 8, 4, 3, 4, 6, 7, 7, 9, 11, 12, 10, 6, 3, + 3, 6, 9, 10, 8, 5, 1, -2, -3, -3, -2, -1, 1, 3, 3, 1, + -5, -12, -18, -20, -20, -18, -16, -16, -16, -17, -19, -20, -17, -11, -5, 1, + 8, 13, 17, 18, 18, 17, 16, 14, 11, 7, 2, -3, -8, -14, -22, -34, + -43, -46, -42, -35, -28, -20, -11, -2, 7, 15, 19, 19, 19, 19, 20, 20, + 17, 14, 11, 10, 9, 7, 1, -4, -6, -4, 0, 2, 4, 6, 7, 8, + 9, 8, 7, 7, 10, 13, 15, 15, 13, 9, 6, 3, 2, 4, 7, 9, + 11, 11, 7, 1, -5, -10, -13, -14, -14, -14, -16, -19, -23, -26, -28, -27, + -23, -18, -13, -7, -1, 6, 11, 14, 15, 14, 14, 15, 15, 12, 7, 2, + -1, -4, -11, -22, -34, -41, -40, -34, -26, -19, -12, -4, 4, 10, 14, 17, + 17, 18, 19, 18, 15, 12, 10, 9, 8, 6, 0, -6, -11, -10, -6, -1, + 3, 5, 6, 6, 6, 7, 7, 8, 10, 13, 16, 18, 17, 13, 9, 5, + 3, 4, 7, 11, 13, 14, 11, 5, -2, -7, -11, -12, -12, -13, -14, -17, + -22, -26, -28, -29, -27, -22, -17, -11, -5, 1, 7, 12, 14, 14, 13, 14, + 15, 14, 11, 5, 0, -2, -6, -15, -27, -37, -42, -38, -31, -24, -17, -9, + -1, 6, 12, 15, 17, 18, 19, 19, 17, 13, 11, 9, 9, 8, 4, -2, + -8, -11, -9, -4, 1, 4, 5, 6, 6, 6, 7, 7, 9, 11, 14, 17, + 18, 16, 12, 8, 4, 3, 5, 9, 12, 14, 13, 9, 2, -4, -9, -12, + -13, -12, -13, -15, -19, -23, -27, -29, -28, -25, -20, -15, -9, -3, 3, 9, + 13, 15, 14, 13, 15, 15, 13, 9, 3, -1, -3, -9, -19, -31, -40, -41, + -36, -28, -21, -14, -6, 2, 9, 13, 16, 17, 18, 19, 18, 16, 12, 10, + 9, 9, 7, 2, -4, -10, -11, -8, -2, 2, 5, 5, 6, 6, 7, 7, + 8, 9, 12, 16, 18, 17, 14, 10, 6, 4, 4, 6, 10, 13, 14, 12, + 7, 0, -6, -10, -12, -13, -13, -14, -16, -21, -25, -28, -29, -28, -24, -18, + -13, -7, -1, 6, 11, 14, 15, 13, 14, 15, 15, 12, 7, 2, -1, -5, + -12, -23, -35, -41, -40, -34, -26, -19, -12, -3, 4, 10, 14, 17, 18, 18, + 19, 18, 14, 11, 9, 9, 8, 6, 0, -7, -11, -10, -6, 0, 2, -1, + -2, -9, -24, 4, -3, 3, -3, 10, 7, 4, 13, -4, 1, 3, 3, 0, + 2, 8, -9, -9, 2, 1, -1, 7, 17, 21, 37, 25, 13, 14, -2, 15, + 20, 5, 0, -3, -7, -27, -14, -18, -19, -29, -20, -4, -18, -32, -30, -30, + -29, -32, -22, -26, -19, -19, -1, -6, 4, 7, 5, 2, 0, -8, -16, -12, + -13, -17, -17, 19, 20, 24, 16, 8, -4, 8, 0, 13, 28, 33, 16, 11, + 5, -3, -1, 4, 12, 12, 40, 20, 11, 4, 5, 8, -1, 2, 5, 5, + 22, 13, 21, 8, 9, 18, 20, 13, 20, 26, 11, 24, 17, 10, 27, 30, + 22, 28, 30, 41, 47, 57, 36, 36, 20, -16, 4, 6, -19, -21, -41, -39, + -33, -38, -41, -46, -42, -36, -18, -37, -65, -75, -77, -78, -62, -63, -62, -68, + -63, -63, -44, -50, -30, -41, -43, -26, -34, -35, -36, -45, -49, -27, 1, -6, + -4, -7, -20, -16, -20, -21, -13, 2, -6, -1, -12, 0, -1, 15, 19, 20, + 26, 37, 40, 46, 37, 50, 35, 34, 41, 43, 51, 54, 55, 50, 56, 47, + 59, 51, 51, 75, 67, 66, 71, 59, 60, 72, 75, 72, 80, 79, 82, 98, + 99, 87, 93, 62, 49, 58, 41, 42, 28, 5, -6, -6, -18, -24, -23, -30, + -25, -20, -38, -60, -75, -77, -80, -75, -71, -75, -70, -73, -69, -76, -60, -66, + -71, -66, -57, -62, -61, -61, -87, -90, -69, -63, -46, -31, -35, -47, -42, -53, + -63, -53, -45, -33, -36, -39, -37, -43, -39, -34, -30, -19, -9, 2, -9, -1, + -3, 1, -3, 5, 7, 15, 24, 22, 23, 20, 32, 43, 33, 48, 63, 67, + 70, 68, 52, 59, 73, 73, 77, 85, 73, 81, 103, 98, 116, 115, 87, 80, + 76, 72, 69, 60, 37, 27, 29, 12, 19, 4, -12, 1, 3, -3, -31, -42, + -57, -67, -67, -61, -61, -61, -48, -58, -51, -41, -46, -48, -40, -35, -33, -26, + -36, -67, -68, -65, -59, -47, -28, -34, -37, -36, -52, -61, -61, -47, -34, -39, + -39, -42, -42, -48, -36, -38, -37, -20, -19, -16, -16, -18, -20, -22, -26, -22, + -16, -15, 1, -4, -6, 10, 12, 13, 22, 32, 41, 54, 52, 44, 54, 66, + 61, 78, 81, 71, 87, 89, 99, 119, 107, 91, 77, 76, 69, 76, 68, 47, + 49, 35, 33, 37, 22, 14, 24, 37, 26, 13, -10, -26, -41, -43, -34, -40, + -34, -33, -43, -39, -25, -27, -27, -18, -25, -15, -1, -10, -29, -42, -39, -39, + -19, -7, -10, -10, -11, -20, -35, -44, -33, -30, -28, -36, -34, -47, -41, -36, + -46, -42, -34, -27, -29, -25, -34, -30, -32, -40, -36, -36, -31, -16, -25, -25, + -15, -21, -14, -9, -11, 1, 17, 15, 9, 25, 20, 25, 46, 39, 46, 50, + 51, 68, 85, 87, 72, 65, 52, 50, 59, 44, 42, 29, 23, 22, 23, 11, + -5, 8, 14, 19, 8, -6, -23, -38, -43, -42, -48, -41, -34, -42, -38, -19, + -23, -16, -15, -19, -10, 8, 8, -9, -18, -27, -30, -10, -4, 7, 6, 15, + 8, -8, -17, -15, -8, -11, -3, -15, -17, -14, -16, -27, -30, -26, -22, -19, + -21, -22, -19, -30, -27, -26, -36, -22, -9, -13, -10, -10, -8, -9, -6, -12, + -1, 16, 6, 11, 16, 6, 19, 24, 27, 38, 38, 38, 48, 71, 72, 78, + 66, 51, 54, 52, 49, 42, 32, 21, 25, 26, 13, 1, -1, 10, 15, 8, + 1, -22, -38, -47, -56, -58, -46, -43, -46, -33, -25, -17, -11, -9, -19, -9, + 16, 18, 12, 1, -17, -18, -9, 3, 9, 17, 24, 26, 9, -4, -1, -6, + 2, 9, 0, -2, 2, -3, -13, -16, -15, -8, -8, -8, -1, -6, -17, -11, + -22, -24, -16, -12, -9, -9, -9, -9, -6, -8, -16, 2, 6, 2, 13, 9, + 7, 10, 17, 19, 30, 31, 22, 37, 49, 61, 70, 56, 43, 37, 36, 31, + 32, 15, 4, 11, 9, 4, -14, -16, -7, -5, -1, -8, -28, -46, -56, -75, + -74, -67, -70, -67, -62, -55, -47, -36, -32, -42, -28, -9, 1, 4, -4, -17, + -30, -18, -12, -2, 4, 15, 21, 7, 1, -7, -6, -1, 7, 0, 0, 3, + -3, -8, -15, -18, -6, -9, -6, 5, -2, -2, 0, -7, -12, -7, -3, 2, + 7, 3, 4, 14, 2, 1, 12, 11, 17, 20, 19, 16, 19, 20, 24, 39, + 36, 37, 42, 55, 71, 84, 76, 63, 56, 47, 49, 46, 29, 18, 14, 18, + 11, -5, -11, -8, -3, 4, 4, -16, -27, -44, -60, -64, -59, -62, -62, -55, + -55, -47, -28, -32, -35, -29, -15, -3, 4, 3, -15, -25, -24, -13, -11, -3, + 10, 14, 12, 4, -5, -9, -1, 2, -1, 1, 1, -1, -7, -17, -16, -12, + -17, -8, 0, -1, -1, -2, -8, -13, -9, -9, 0, 9, 1, 14, 16, 6, + 7, 10, 12, 18, 26, 20, 22, 22, 16, 25, 32, 36, 34, 36, 43, 60, + 75, 72, 67, 52, 44, 50, 45, 38, 17, 14, 17, 11, -2, -9, -14, -10, + 0, -4, -12, -24, -41, -59, -67, -63, -70, -69, -62, -70, -55, -40, -38, -42, + -38, -29, -16, -3, -3, -9, -29, -31, -25, -26, -20, -7, 0, 2, -1, -14, + -18, -14, -14, -12, -10, -10, -4, -13, -21, -19, -22, -24, -16, -10, -6, -2, + -2, -10, -12, -15, -17, -4, -4, -5, 7, 9, 3, 4, 7, 5, 18, 23, + 22, 28, 25, 22, 27, 34, 39, 43, 38, 41, 62, 71, 79, 78, 62, 55, + 55, 57, 49, 31, 23, 30, 21, 15, 7, -5, 1, 8, 9, 8, -3, -16, + -39, -46, -50, -60, -55, -58, -62, -53, -36, -33, -34, -34, -29, -18, -6, 5, + -2, -17, -23, -22, -24, -17, -8, 1, 9, 10, -4, -7, -8, -9, -6, -9, + -6, 0, -11, -14, -14, -21, -24, -21, -16, -10, 1, -3, -3, -5, -14, -11, + -7, -7, -5, 6, 9, 4, 8, 1, 3, 11, 16, 20, 26, 24, 20, 25, + 29, 36, 41, 32, 40, 51, 64, 77, 78, 67, 55, 54, 57, 53, 33, 27, + 25, 22, 20, 9, -3, -3, 3, 7, 6, 4, -16, -32, -42, -55, -60, -61, + -64, -70, -62, -49, -39, -41, -40, -37, -33, -18, -5, -8, -16, -24, -29, -31, + -28, -24, -15, -1, 1, -7, -11, -14, -13, -14, -18, -11, -8, -14, -16, -16, + -25, -31, -29, -31, -20, -12, -13, -6, -11, -19, -19, -14, -17, -12, -1, 2, + 6, 7, 2, 4, 8, 11, 18, 24, 21, 22, 19, 21, 33, 33, 32, 32, + 40, 55, 71, 76, 72, 58, 55, 62, 56, 42, 34, 28, 29, 26, 17, 4, + 2, 6, 4, 13, 12, -4, -18, -30, -45, -50, -51, -59, -63, -61, -47, -37, + -33, -32, -34, -32, -19, -4, -3, -5, -13, -21, -23, -22, -24, -13, 1, 5, + 5, -3, -6, -1, -7, -9, -2, 1, -2, -2, -4, -13, -16, -22, -22, -15, + -10, -4, 2, -1, -11, -8, -7, -12, -6, 1, 6, 12, 11, 8, 9, 9, + 9, 20, 23, 26, 25, 20, 24, 32, 34, 35, 33, 35, 49, 63, 74, 74, + 58, 55, 60, 54, 45, 33, 27, 25, 26, 19, 6, 4, 1, 1, 9, 12, + -1, -10, -26, -43, -50, -54, -61, -70, -69, -61, -50, -43, -40, -44, -44, -34, + -18, -12, -9, -15, -24, -25, -28, -31, -22, -12, -2, 1, -8, -8, -5, -12, + -14, -8, -8, -8, -5, -9, -11, -18, -27, -26, -22, -19, -12, -1, -4, -9, + -8, -11, -14, -12, -8, 0, 7, 5, 5, 6, 0, 3, 8, 13, 20, 18, + 13, 15, 22, 27, 29, 25, 26, 36, 51, 70, 71, 59, 56, 57, 55, 47, + 37, 25, 24, 27, 17, 9, 3, -2, -2, 8, 9, 6, -2, -16, -34, -44, + -47, -54, -63, -66, -63, -55, -44, -39, -42, -44, -35, -23, -11, -4, -10, -16, + -17, -23, -25, -22, -13, 1, 6, 1, 1, 4, -2, -4, 1, -1, 4, 3, + 2, 2, -3, -12, -15, -14, -15, -7, 3, 5, 3, 2, 1, -2, -4, -4, + 3, 9, 10, 13, 11, 9, 8, 9, 15, 22, 22, 20, 19, 21, 27, 30, + 28, 28, 28, 42, 61, 69, 65, 60, 60, 58, 55, 47, 35, 30, 30, 24, + 18, 10, 0, -1, 2, 6, 7, 3, -8, -24, -36, -43, -50, -59, -65, -66, + -62, -52, -43, -43, -44, -41, -35, -21, -12, -12, -13, -17, -23, -26, -30, -24, + -12, -4, -5, -3, -2, -5, -6, -6, -5, -3, -2, -1, 2, 2, -5, -3, + 2, 8, 17, 26, 32, 42, 50, 56, 68, 73, 64, 63, 65, 48, 56, 71, + 48, 49, 50, 26, 30, 30, 16, 25, 21, -2, 0, -13, -15, -2, -19, -17, + -16, -50, -49, -49, -81, -85, -88, -108, -112, -116, -127, -126, -113, -113, -106, -79, + -65, -48, -17, 5, 20, 41, 58, 63, 69, 59, 28, 17, 0, -32, -41, -52, + -69, -63, -61, -59, -41, -26, -19, 6, 28, 33, 52, 67, 70, 81, 87, 84, + 90, 93, 84, 72, 69, 60, 45, 56, 57, 40, 46, 39, 25, 29, 25, 16, + 21, 12, -1, -3, -11, -8, -5, -16, -12, -21, -41, -38, -48, -68, -70, -77, + -91, -93, -98, -106, -103, -93, -92, -82, -60, -47, -30, -4, 13, 27, 44, 56, + 60, 62, 47, 23, 13, -8, -32, -40, -54, -64, -59, -59, -53, -36, -26, -14, + 12, 27, 36, 56, 66, 72, 84, 86, 86, 93, 92, 82, 73, 70, 57, 49, + 59, 52, 43, 47, 37, 29, 30, 24, 18, 18, 7, -2, -6, -11, -7, -10, + -16, -14, -29, -42, -42, -57, -71, -73, -83, -93, -96, -102, -107, -101, -93, -90, + -75, -55, -41, -22, 3, 19, 33, 50, 59, 61, 60, 41, 21, 10, -14, -33, + -43, -57, -63, -60, -61, -51, -36, -27, -9, 15, 26, 40, 59, 66, 74, 85, + 85, 88, 94, 90, 80, 75, 69, 56, 54, 60, 50, 47, 46, 36, 31, 30, + 23, 19, 15, 4, -3, -7, -10, -9, -14, -17, -19, -35, -44, -47, -63, -73, + -77, -88, -96, -98, -104, -107, -99, -92, -86, -69, -50, -35, -14, 9, 24, 38, + 54, 60, 61, 56, 36, 19, 4, -20, -35, -46, -60, -62, -61, -60, -48, -35, + -25, -3, 17, 27, 45, 60, 66, 77, 85, 86, 91, 94, 88, 80, 75, 67, + 56, 58, 59, 50, 49, 45, 36, 33, 30, 23, 19, 13, 2, -5, -8, -10, + -11, -16, -18, -25, -40, -45, -53, -68, -76, -81, -91, -97, -100, -106, -106, -97, + -90, -81, -63, -44, -28, -6, 15, 28, 44, 57, 61, 61, 52, 31, 16, -1, + -24, -37, -50, -61, -62, -62, -59, -46, -35, -22, 1, 18, 30, 48, 61, 68, + 79, 85, 87, 92, 93, 86, 80, 75, 66, 58, 60, 58, 51, 50, 44, 37, + 33, 29, 23, 17, 10, 0, -6, -9, -10, -14, -18, -21, -31, -43, -48, -59, + -72, -78, -85, -94, -99, -102, -107, -104, -95, -88, -76, -56, -39, -22, 2, 20, + 33, 49, 59, 61, 60, 47, 27, 12, -7, -27, -40, -53, -62, -62, -63, -57, + -44, -34, -18, 5, 19, 33, 51, 61, 70, 81, 85, 88, 94, 92, 85, 80, + 74, 65, 60, 62, 57, 52, 50, 43, 37, 33, 28, 22, 15, 8, -2, -7, + -10, -12, -16, -20, -24, -36, -46, -52, -64, -75, -81, -89, -97, -100, -104, -107, + -102, -93, -85, -70, -50, -33, -14, 8, 25, 38, 53, 61, 61, 58, 42, 24, + 8, -12, -30, -43, -56, -62, -63, -63, -54, -43, -32, -13, 7, 20, 37, 53, + 62, 72, 82, 85, 89, 94, 90, 84, 80, 73, 64, 62, 62, 56, 53, 49, + 43, 37, 33, 27, 20, 14, 5, -3, -8, -11, -13, -18, -22, -28, -40, -49, + -57, -69, -78, -84, -92, -99, -102, -105, -106, -99, -90, -81, -64, -44, -27, -7, + 14, 29, 43, 56, 61, 61, 54, 37, 20, 4, -17, -33, -46, -58, -62, -64, + -62, -52, -42, -29, -9, 9, 23, 40, 55, 64, 74, 83, 86, 91, 93, 89, + 84, 80, 72, 65, 64, 62, 56, 53, 49, 42, 37, 33, 26, 19, 12, 3, + -5, -8, -12, -16, -20, -24, -33, -44, -52, -61, -73, -80, -87, -95, -100, -103, + -106, -104, -96, -88, -76, -57, -38, -21, 0, 20, 33, 47, 59, 62, 60, 51, + 33, 17, -1, -21, -36, -49, -59, -63, -64, -61, -51, -40, -25, -5, 11, 26, + 43, 56, 65, 76, 83, 87, 92, 93, 88, 84, 79, 71, 65, 65, 61, 56, + 53, 48, 42, 37, 32, 25, 17, 10, 1, -6, -10, -13, -18, -22, -27, -37, + -48, -55, -65, -76, -83, -90, -97, -101, -104, -106, -102, -94, -84, -71, -51, -33, + -15, 7, 24, 38, 51, 60, 62, 59, 46, 29, 13, -6, -25, -39, -52, -60, + -63, -64, -59, -49, -38, -21, -1, 14, 29, 46, 57, 67, 78, 84, 88, 92, + 92, 87, 83, 78, 70, 66, 65, 61, 57, 53, 48, 42, 37, 31, 23, 15, + 7, -1, -7, -11, -15, -20, -24, -31, -41, -51, -59, -69, -79, -85, -93, -99, + -102, -105, -106, -100, -91, -80, -65, -45, -27, -8, 13, 29, 42, 55, 61, 61, + 56, 42, 25, 8, -11, -28, -42, -54, -61, -64, -64, -57, -47, -35, -17, 1, + 16, 33, 48, 59, 69, 79, 84, 89, 93, 91, 87, 83, 77, 70, 67, 65, + 60, 57, 53, 47, 41, 36, 29, 21, 14, 5, -3, -8, -12, -17, -22, -27, + -35, -45, -54, -63, -73, -81, -88, -95, -100, -103, -105, -104, -97, -88, -76, -58, + -39, -21, -1, 18, 33, 46, 58, 62, 61, 53, 38, 21, 4, -15, -31, -45, + -56, -62, -65, -64, -56, -46, -32, -13, 4, 19, 36, 50, 61, 71, 80, 85, + 90, 92, 90, 86, 82, 76, 70, 68, 65, 60, 57, 52, 46, 41, 35, 27, + 19, 12, 3, -5, -9, -14, -19, -24, -29, -38, -48, -57, -66, -76, -84, -91, + -97, -101, -104, -105, -102, -94, -84, -71, -52, -33, -15, 5, 23, 37, 50, 60, + 62, 60, 50, 34, 17, -1, -19, -35, -48, -58, -63, -65, -62, -54, -43, -28, + -10, 7, 22, 39, 52, 62, 73, 81, 86, 91, 92, 89, 86, 82, 75, 70, + 68, 64, 60, 57, 52, 46, 40, 34, 26, 17, 9, 1, -6, -11, -15, -21, + -26, -32, -42, -52, -60, -70, -79, -86, -93, -99, -102, -104, -105, -100, -91, -80, + -65, -46, -27, -9, 11, 28, 42, 54, 61, 62, 58, 46, 30, 13, -6, -23, + -38, -51, -60, -64, -65, -61, -52, -41, -25, -6, 9, 26, 42, 54, 64, 75, + 82, 87, 91, 91, 89, 85, 81, 74, 71, 68, 64, 60, 56, 51, 45, 39, + 32, 24, 16, 7, -1, -7, -12, -17, -23, -28, -36, -45, -55, -64, -73, -82, + -88, -95, -100, -103, -105, -104, -97, -88, -76, -59, -40, -22, -2, 17, 32, 45, + 57, 62, 62, 56, 42, 26, 9, -10, -27, -41, -53, -61, -65, -65, -60, -50, + -38, -21, -3, 12, 29, 44, 55, 66, 76, 82, 88, 91, 91, 88, 85, 80, + 74, 71, 68, 63, 60, 56, 50, 44, 38, 30, 22, 14, 5, -3, -9, -14, + -19, -25, -31, -39, -49, -58, -67, -77, -84, -91, -97, -101, -103, -105, -102, -95, + -84, -71, -53, -34, -16, 4, 22, 37, 49, 59, 63, 61, 53, 38, 22, 4, + -14, -30, -44, -56, -62, -66, -65, -58, -48, -35, -17, -1, 15, 32, 46, 57, + 68, 77, 83, 88, 91, 90, 88, 84, 79, 74, 71, 67, 63, 60, 55, 49, + 43, 37, 28, 20, 12, 3, -5, -10, -15, -21, -27, -33, -43, -52, -61, -70, + -79, -86, -93, -98, -102, -104, -104, -100, -92, -81, -66, -47, -28, -10, 10, 27, + 40, 53, 61, 63, 59, 49, 34, 18, -1, -18, -34, -47, -58, -63, -66, -64, + -56, -46, -31, -14, 2, 18, 35, 48, 59, 70, 78, 84, 89, 91, 90, 87, + 83, 78, 74, 71, 67, 63, 59, 54, 49, 42, 35, 27, 18, 9, 1, -6, + -12, -17, -23, -29, -36, -46, -55, -64, -73, -82, -89, -95, -100, -102, -104, -103, + -97, -88, -76, -60, -41, -23, -4, 15, 31, 44, 55, 62, 62, 57, 46, 30, + 13, -5, -22, -37, -50, -59, -64, -66, -62, -55, -43, -28, -11, 5, 22, 37, + 50, 61, 71, 79, 85, 89, 91, 89, 87, 82, 77, 73, 70, 66, 63, 59, + 53, 47, 41, 33, 24, 16, 7, -1, -8, -14, -19, -25, -32, -40, -49, -58, + -67, -76, -84, -91, -96, -101, -103, -104, -102, -95, -85, -72, -55, -37, -18, 1, + 19, 34, 47, 57, 62, 62, 56, 43, 28, 10, -8, -25, -39, -52, -60, -65, + -66, -62, -53, -42, -25, -9, 8, 24, 39, 51, 62, 72, 80, 86, 90, 90, + 89, 86, 82, 77, 73, 70, 66, 62, 58, 53, 47, 40, 33, 24, 15, 6, + -2, -8, -14, -19, -25, -32, -40, -49, -58, -67, -72, -103, -18, -76, 0, 0, + 0, 0, 1, 2, 3, 5, 6, 0, -7, -8, -15, -9, 10, 8, 17, 33, + 14, 5, 38, 44, 31, 63, 70, 51, 73, 82, 68, 85, 100, 96, 97, 103, + 115, 114, 112, 127, 122, 110, 116, 113, 109, 120, 120, 118, 113, 91, 93, 109, + 97, 98, 115, 110, 109, 120, 112, 94, 75, 63, 69, 72, 64, 64, 59, 45, + 39, 36, 35, 42, 42, 24, 5, 2, 3, 4, 7, 9, 11, 14, 17, 19, + 14, -3, -20, -26, -30, -26, -24, -31, -32, -34, -40, -39, -33, -34, -45, -56, + -60, -66, -64, -55, -60, -62, -56, -59, -58, -50, -56, -70, -73, -76, -86, -77, + -70, -80, -76, -71, -77, -71, -66, -76, -85, -82, -90, -95, -80, -82, -92, -85, + -86, -94, -85, -79, -86, -92, -90, -94, -101, -92, -85, -90, -84, -77, -78, -74, + -73, -85, -86, -85, -95, -85, -77, -90, -88, -83, -94, -93, -83, -81, -81, -86, + -89, -89, -94, -88, -77, -77, -71, -59, -58, -59, -63, -72, -74, -77, -73, -61, + -67, -72, -67, -73, -80, -74, -68, -60, -56, -65, -70, -67, -72, -66, -52, -49, + -40, -27, -27, -32, -39, -47, -50, -42, -30, -31, -34, -32, -38, -46, -46, -43, + -35, -20, -16, -24, -30, -30, -31, -24, -13, -6, 4, 13, 11, 3, -5, -9, + -2, 12, 15, 15, 16, 9, 3, -2, -5, -1, 12, 24, 30, 29, 20, 17, + 22, 25, 30, 41, 47, 49, 46, 37, 32, 41, 52, 54, 60, 61, 52, 48, + 45, 36, 35, 43, 51, 60, 67, 69, 60, 57, 63, 63, 64, 73, 75, 72, + 69, 63, 67, 78, 78, 82, 89, 80, 73, 76, 67, 60, 64, 67, 73, 79, + 83, 88, 82, 75, 80, 81, 77, 83, 83, 76, 74, 77, 83, 85, 86, 94, + 89, 80, 82, 78, 69, 68, 68, 69, 78, 80, 81, 90, 83, 73, 79, 77, + 70, 73, 70, 62, 65, 73, 75, 76, 84, 82, 70, 71, 69, 59, 57, 54, + 48, 53, 63, 64, 68, 76, 66, 57, 58, 51, 42, 40, 33, 28, 37, 46, + 49, 55, 56, 42, 37, 37, 27, 22, 20, 10, 4, 8, 15, 24, 30, 31, + 24, 14, 8, -3, -14, -21, -26, -26, -15, -4, -1, -4, -13, -21, -26, -34, + -39, -42, -50, -57, -63, -66, -60, -47, -43, -48, -51, -57, -66, -75, -82, -88, + -91, -88, -78, -74, -81, -86, -85, -92, -101, -100, -102, -109, -109, -110, -112, -113, + -115, -109, -106, -113, -113, -107, -110, -110, -106, -108, -112, -109, -110, -114, -111, -98, + -95, -98, -93, -93, -98, -94, -89, -81, -69, -65, -71, -73, -73, -77, -73, -62, + -56, -48, -40, -41, -45, -47, -47, -37, -20, -11, -4, 5, 4, 3, 6, 9, + 16, 30, 39, 47, 51, 44, 40, 45, 47, 50, 59, 64, 66, 68, 65, 65, + 75, 80, 78, 87, 95, 91, 93, 98, 96, 98, 104, 100, 96, 99, 104, 101, + 100, 106, 107, 105, 108, 109, 109, 110, 111, 110, 101, 87, 82, 84, 81, 82, + 88, 89, 90, 91, 85, 71, 57, 49, 48, 51, 52, 55, 59, 58, 58, 60, + 61, 61, 57, 42, 24, 14, 7, 5, 9, 11, 15, 20, 21, 19, 11, -3, + -18, -27, -33, -31, -25, -24, -21, -16, -16, -14, -11, -17, -29, -40, -49, -59, + -61, -55, -54, -52, -45, -42, -41, -41, -48, -59, -65, -72, -81, -79, -72, -73, + -69, -62, -61, -59, -60, -69, -76, -79, -87, -92, -84, -81, -82, -76, -72, -71, + -67, -66, -72, -79, -81, -87, -94, -92, -87, -86, -82, -76, -75, -75, -78, -85, + -87, -91, -96, -91, -82, -83, -80, -74, -74, -71, -64, -64, -68, -73, -77, -81, + -87, -88, -82, -79, -76, -70, -69, -72, -76, -80, -84, -87, -82, -71, -67, -64, + -58, -57, -55, -49, -43, -39, -40, -47, -54, -58, -64, -66, -61, -58, -54, -49, + -50, -55, -59, -63, -65, -58, -45, -38, -32, -25, -24, -23, -18, -13, -5, 3, + 4, -2, -11, -17, -23, -26, -23, -20, -18, -15, -18, -24, -28, -28, -21, -7, + 3, 11, 18, 20, 19, 22, 24, 30, 40, 47, 51, 49, 40, 32, 28, 24, + 23, 25, 25, 23, 20, 15, 15, 23, 34, 43, 51, 59, 59, 58, 59, 58, + 60, 67, 73, 78, 84, 85, 78, 71, 68, 63, 60, 60, 57, 53, 50, 50, + 56, 65, 70, 76, 84, 84, 81, 81, 79, 76, 79, 84, 87, 91, 96, 98, + 94, 88, 85, 81, 76, 73, 70, 66, 66, 70, 76, 80, 84, 91, 92, 87, + 86, 83, 78, 76, 78, 81, 85, 88, 91, 96, 93, 86, 83, 78, 71, 68, + 64, 61, 64, 71, 74, 78, 84, 86, 80, 76, 72, 64, 59, 56, 55, 59, + 66, 69, 74, 79, 76, 69, 64, 57, 48, 43, 39, 39, 45, 52, 56, 62, + 63, 55, 47, 41, 31, 21, 15, 8, 5, 9, 16, 24, 31, 35, 33, 26, + 19, 10, 0, -6, -9, -7, -7, -13, -17, -22, -26, -31, -34, -37, -40, -42, + -44, -46, -48, -50, -51, -54, -56, -58, -61, -64, -67, -70, -74, -78, -82, -86, + -90, -93, -97, -99, -102, -104, -106, -108, -109, -110, -111, -112, -113, -113, -114, -114, + -115, -115, -115, -115, -115, -114, -113, -111, -109, -107, -104, -100, -97, -93, -90, -87, + -84, -82, -80, -78, -76, -74, -73, -71, -69, -67, -65, -61, -58, -53, -48, -42, + -35, -28, -21, -13, -6, 1, 8, 15, 21, 26, 31, 35, 38, 41, 44, 46, + 48, 50, 52, 55, 58, 61, 64, 68, 72, 76, 80, 83, 87, 90, 92, 94, + 96, 98, 99, 100, 101, 102, 102, 103, 103, 103, 103, 104, 103, 103, 103, 102, + 101, 99, 97, 94, 92, 88, 85, 81, 78, 74, 71, 67, 64, 61, 58, 55, + 53, 51, 49, 47, 46, 44, 42, 40, 37, 34, 30, 26, 22, 17, 12, 8, + 3, -1, -5, -9, -13, -16, -20, -23, -26, -29, -31, -33, -35, -37, -38, -40, + -42, -44, -46, -48, -51, -54, -56, -59, -61, -64, -65, -67, -69, -70, -72, -74, + -75, -77, -78, -80, -81, -82, -83, -84, -85, -86, -86, -87, -88, -89, -90, -90, + -91, -92, -92, -92, -92, -92, -92, -91, -91, -92, -92, -92, -93, -93, -94, -94, + -94, -95, -95, -95, -95, -95, -95, -95, -95, -95, -94, -93, -92, -91, -90, -89, + -87, -86, -85, -85, -85, -84, -84, -85, -85, -85, -85, -85, -85, -85, -85, -85, + -84, -83, -82, -81, -79, -77, -75, -73, -70, -68, -65, -63, -62, -60, -59, -59, + -59, -59, -59, -59, -59, -60, -59, -59, -59, -58, -57, -55, -53, -50, -47, -44, + -40, -36, -32, -29, -25, -22, -20, -18, -17, -16, -15, -15, -16, -16, -16, -16, + -16, -16, -15, -13, -11, -9, -6, -2, 2, 6, 10, 15, 19, 22, 26, 29, + 31, 33, 35, 36, 36, 36, 36, 35, 35, 35, 35, 35, 36, 38, 40, 42, + 45, 48, 52, 55, 58, 61, 64, 67, 70, 72, 73, 74, 75, 76, 76, 76, + 75, 75, 74, 74, 74, 74, 74, 75, 77, 78, 80, 82, 83, 85, 87, 89, + 90, 91, 92, 93, 94, 94, 94, 94, 94, 93, 93, 92, 91, 91, 90, 90, + 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, + 93, 93, 92, 92, 91, 90, 89, 88, 87, 87, 86, 86, 85, 85, 85, 84, + 84, 83, 83, 82, 81, 80, 79, 78, 77, 77, 76, 75, 74, 72, 71, 70, + 68, 67, 65, 64, 63, 61, 60, 58, 57, 55, 53, 50, 48, 45, 43, 40, + 38, 36, 34, 32, 30, 29, 27, 25, 23, 21, 19, 17, 14, 12, 9, 6, + 3, 0, -4, -8, -12, -17, -21, -25, -29, -33, -36, -39, -42, -45, -47, -49, + -51, -53, -55, -58, -60, -63, -65, -68, -71, -74, -77, -81, -84, -87, -91, -94, + -97, -99, -102, -104, -105, -107, -108, -109, -110, -111, -111, -112, -112, -113, -113, -113, + -113, -113, -113, -112, -111, -109, -107, -105, -102, -99, -96, -93, -90, -87, -84, -82, + -79, -77, -75, -73, -70, -69, -66, -64, -60, -58, -53, -49, -44, -39, -32, -27, + -19, -14, -8, -3, 3, 11, 22, 10, 8, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 5, 6, 6, 6, 6, + 6, 6, 7, 5, 7, 5, 6, 4, 6, 4, 4, 4, 4, 3, 3, 2, + 3, 1, 3, -2, 2, 0, 0, 0, 0, -2, -1, -2, -3, -3, 0, -5, + -1, -2, -2, -2, -1, 0, -3, -1, -1, 0, 1, -1, 0, -1, 0, 0, + 1, 0, 0, 1, -1, 1, -1, 1, -2, -1, -3, 0, -2, -1, -2, -2, + -2, -3, -2, -3, -4, -5, -6, -5, -9, -8, -9, -9, -9, -11, -10, -13, + -14, -14, -15, -16, -15, -17, -19, -19, -21, -18, -21, -20, -22, -20, -24, -21, + -22, -19, -20, -21, -17, -19, -16, -17, -15, -17, -13, -11, -10, -7, -5, -3, + 2, 6, 4, 8, 9, 18, 14, 31, 25, 24, 25, 24, 21, 13, 15, 15, + 11, 9, 1, 4, -20, -18, -38, -44, -57, -57, -55, -55, -52, -55, -46, -47, + -40, -32, -26, -19, -16, -2, 3, 13, 19, 28, 30, 37, 40, 44, 39, 38, + 35, 34, 37, 41, 48, 51, 53, 58, 61, 70, 74, 76, 76, 80, 81, 86, + 83, 83, 78, 78, 73, 69, 65, 55, 47, 40, 36, 29, 23, 16, 14, 8, + -2, -4, -11, -11, -19, -22, -26, -25, -34, -39, -40, -41, -45, -49, -51, -57, + -56, -58, -59, -66, -70, -70, -72, -65, -64, -59, -53, -49, -45, -34, -29, -21, + -15, -10, -6, -6, -3, -4, 2, 3, 3, 3, -1, -3, -11, -11, -13, -16, + -22, -24, -27, -32, -34, -37, -35, -31, -30, -26, -25, -22, -21, -15, -13, -15, + -10, -12, -12, -7, 2, 15, 22, 27, 24, 28, 22, 22, 21, 22, 17, 13, + 14, 9, 5, 2, -8, -12, -16, -14, -17, -17, -17, -17, -14, -8, -3, -3, + 0, 5, 3, 5, 6, 3, -2, -6, -9, -11, -13, -18, -19, -29, -42, -61, + -72, -79, -81, -83, -82, -79, -76, -65, -54, -42, -33, -24, -14, 0, 18, 33, + 48, 62, 75, 87, 93, 99, 100, 102, 102, 104, 102, 100, 100, 96, 93, 95, + 96, 105, 109, 112, 111, 110, 106, 106, 104, 102, 97, 93, 85, 80, 71, 60, + 48, 36, 26, 12, 0, -5, -13, -21, -28, -31, -36, -42, -49, -53, -56, -59, + -61, -63, -64, -64, -63, -67, -70, -77, -75, -77, -78, -79, -80, -81, -80, -75, + -69, -64, -57, -50, -43, -35, -26, -16, -6, 6, 13, 17, 22, 26, 25, 27, + 27, 26, 23, 19, 11, 5, -5, -12, -19, -24, -31, -37, -42, -45, -50, -49, + -48, -47, -43, -41, -38, -38, -37, -35, -35, -37, -42, -40, -33, -27, -20, -12, + -11, -13, -10, -9, -10, -10, -10, -13, -11, -9, -8, -11, -13, -16, -18, -17, + -15, -15, -14, -12, -8, -3, 3, 8, 16, 22, 25, 31, 34, 36, 36, 34, + 31, 25, 23, 24, 26, 23, 13, -1, -16, -29, -38, -45, -51, -56, -57, -54, + -48, -39, -34, -29, -20, -10, 0, 13, 27, 39, 54, 68, 79, 87, 92, 94, + 96, 94, 92, 89, 87, 82, 76, 72, 71, 74, 76, 81, 83, 83, 84, 84, + 85, 85, 82, 81, 82, 80, 75, 71, 66, 57, 46, 34, 24, 15, 5, -2, + -8, -13, -19, -26, -31, -37, -41, -44, -48, -53, -54, -53, -54, -54, -57, -61, + -64, -67, -70, -72, -75, -77, -79, -79, -76, -73, -70, -63, -58, -53, -47, -38, + -29, -21, -13, -6, 0, 4, 7, 7, 8, 8, 6, 5, -1, -8, -15, -22, + -30, -36, -41, -47, -51, -54, -56, -58, -59, -56, -50, -45, -42, -37, -31, -26, + -23, -23, -23, -24, -21, -14, -6, 2, 8, 12, 15, 18, 21, 20, 20, 20, + 20, 21, 23, 22, 18, 13, 10, 8, 6, 5, 4, 3, 2, 2, 4, 7, + 10, 13, 18, 22, 24, 26, 28, 27, 21, 14, 8, 5, 4, 2, -3, -12, + -24, -37, -50, -59, -67, -76, -80, -79, -75, -69, -61, -55, -47, -38, -27, -15, + -2, 11, 27, 43, 58, 71, 82, 90, 94, 96, 98, 98, 98, 95, 89, 84, + 81, 79, 81, 85, 88, 89, 91, 92, 92, 90, 89, 89, 88, 85, 82, 79, + 75, 67, 58, 48, 37, 25, 14, 4, -4, -10, -17, -24, -31, -37, -42, -47, + -51, -56, -59, -59, -59, -59, -61, -63, -65, -67, -70, -72, -74, -76, -78, -78, + -78, -75, -70, -66, -61, -56, -50, -41, -33, -23, -14, -6, 2, 10, 16, 19, + 21, 23, 24, 24, 22, 19, 13, 7, 0, -6, -14, -20, -25, -27, -32, -37, + -39, -39, -38, -36, -33, -30, -27, -22, -19, -19, -20, -23, -24, -22, -18, -13, + -8, -4, 0, 2, 5, 6, 5, 3, 2, 4, 6, 6, 5, 1, -2, -6, + -8, -9, -10, -11, -13, -12, -12, -11, -9, -4, 0, 4, 8, 13, 18, 20, + 19, 14, 10, 6, 4, 4, 4, 0, -8, -17, -28, -38, -49, -60, -68, -72, + -72, -70, -65, -59, -54, -46, -37, -27, -17, -5, 8, 22, 37, 51, 66, 77, + 84, 88, 91, 93, 94, 94, 91, 85, 79, 75, 74, 76, 77, 80, 83, 85, + 85, 85, 86, 86, 85, 85, 85, 83, 81, 77, 70, 64, 55, 44, 32, 22, + 13, 6, -1, -9, -16, -22, -27, -32, -38, -43, -46, -47, -47, -47, -48, -49, + -49, -50, -52, -54, -56, -59, -62, -64, -66, -65, -64, -61, -59, -56, -53, -48, + -41, -33, -25, -17, -10, -2, 4, 9, 13, 15, 16, 17, 17, 15, 11, 7, + 1, -7, -15, -22, -27, -33, -38, -43, -47, -49, -50, -50, -49, -46, -42, -37, + -31, -28, -28, -29, -30, -29, -26, -22, -17, -13, -8, -3, 2, 6, 7, 6, + 5, 6, 8, 10, 12, 11, 8, 5, 3, 1, -1, -2, -3, -4, -6, -7, + -6, -3, 0, 1, 5, 10, 16, 20, 21, 19, 15, 10, 8, 6, 6, 4, + 0, -5, -12, -22, -33, -45, -57, -65, -70, -72, -70, -68, -64, -58, -51, -44, + -36, -24, -13, -2, 11, 27, 43, 58, 70, 78, 83, 88, 92, 96, 97, 93, + 89, 85, 81, 80, 81, 83, 86, 88, 90, 91, 91, 91, 91, 91, 91, 91, + 89, 86, 83, 79, 72, 63, 52, 41, 30, 21, 13, 4, -5, -11, -17, -23, + -31, -38, -44, -47, -49, -50, -52, -54, -55, -57, -57, -58, -60, -63, -66, -69, + -72, -74, -73, -72, -70, -69, -67, -64, -59, -53, -45, -37, -30, -22, -14, -7, + -2, 3, 8, 10, 12, 12, 13, 12, 8, 3, -4, -10, -16, -21, -27, -33, + -37, -41, -44, -46, -48, -48, -45, -48, -43, -37, -33, -31, -32, -33, -32, -29, + -26, -22, -18, -12, -5, 1, 6, 9, 9, 9, 9, 11, 14, 16, 16, 14, + 12, 8, 5, 3, 2, 1, -1, -3, -4, -4, -2, -1, 2, 5, 11, 18, + 24, 27, 27, 24, 20, 17, 15, 13, 11, 9, 5, -1, -10, -22, -35, -49, + -61, -70, -75, -77, -76, -73, -69, -63, -56, -47, -36, -25, -13, 0, 16, 34, + 52, 67, 79, 88, 95, 101, 106, 109, 108, 105, 100, 95, 92, 90, 91, 93, + 96, 99, 100, 101, 101, 101, 101, 101, 101, 100, 97, 95, 91, 85, 78, 67, + 55, 43, 31, 21, 11, 1, -7, -14, -21, -29, -37, -45, -51, -54, -56, -58, + -60, -62, -64, -65, -66, -67, -69, -72, -76, -80, -82, -84, -83, -82, -80, -79, + -77, -73, -67, -60, -51, -42, -34, -25, -16, -8, -2, 4, 9, 12, 13, 14, + 14, 13, 9, 3, -5, -12, -18, -25, -31, -37, -42, -47, -50, -53, -54, -53, + -48, -41, -36, -32, -31, -31, -32, -31, -28, -25, -22, -17, -12, -5, 1, 1, + -2, -1, -9, -9, -6, 5, 6, -1, -10, 8, 24, 11, -2, -14, -9, -15, + -13, 5, 14, 12, -6, -1, -12, 1, -9, 12, 12, 10, 5, -19, -11, -13, + -2, 8, 5, 1, -2, -3, 9, -6, 6, 5, 6, -3, -17, -7, 3, 2, + -1, 0, 7, -7, 5, 4, 6, -18, -24, 6, 20, -1, -4, -1, 10, 3, + -10, 8, 7, -11, -17, -15, 5, 18, 4, 1, 8, -16, -4, 0, 11, 9, + -10, -15, 0, -22, -12, 19, 34, 16, -9, -16, -7, -12, -10, 13, 23, -1, + -10, -2, -3, -11, 13, 7, -6, -9, 3, 11, -10, -18, 12, 22, 7, -27, + -29, -4, 20, 20, 10, 8, -16, -26, -6, 22, 21, 7, 15, 8, -50, -50, + -7, 35, 22, -13, 32, 41, -33, -46, -10, 23, -7, -25, 23, 21, -38, -36, + 14, 44, 2, 2, 34, -14, -51, -29, 11, 19, 7, 22, 13, -23, -21, -8, + -9, 1, 14, 26, 26, -8, -34, -33, 4, 1, -6, -2, 16, -7, -23, 12, + 27, 5, 6, 6, 0, -8, 0, -1, -17, -13, -12, 3, 9, 4, 11, 23, + 36, 0, -43, -16, 4, -21, -26, 27, 16, -25, 3, 65, 4, -34, 24, -10, + -38, -14, 13, 4, -15, 36, 44, -42, -51, 20, -5, -6, 68, 20, -18, -39, + -11, 9, 17, 6, -33, -20, -13, 48, 30, 22, -4, -9, -53, -20, 32, 32, + -16, 17, -11, -36, -8, -5, 39, 28, 33, 21, -64, -48, 3, -22, 15, 62, + -26, 0, 3, 5, 73, -14, -48, -20, -59, 4, 70, 60, -7, -2, -88, -22, + -17, 39, 17, 33, -3, 15, 28, -47, -80, -37, 5, 7, 104, 16, -99, -92, + -36, 109, 78, 26, -15, -92, -21, 62, 48, -51, -81, -25, 55, 63, 35, 21, + -115, -54, 101, 73, -41, -110, -66, 50, 107, 45, -8, -109, -38, 12, 102, 3, + 17, -45, -2, -36, 39, 46, -12, -28, -27, -17, 17, -18, 82, -5, -3, -25, + -5, -14, 15, 9, -3, -17, -6, 2, 7, -36, -13, 6, 21, -23, -20, 16, + -18, 3, -2, 26, 0, 13, -23, -2, -19, -28, -18, 15, 12, 22, -4, 23, + -17, -22, -9, -18, -4, 11, 13, 0, 34, -16, -20, 26, 23, 15, -4, -25, + 7, 8, -9, 8, 44, 1, -40, 17, -32, 9, -30, -52, 52, 3, 2, -21, + 83, 58, -14, -46, -61, -12, -67, -20, 64, 72, 57, -10, 5, 1, -77, 31, + -47, -39, 12, 22, 57, 28, 0, 9, -76, 15, -74, 33, -12, 39, 114, -35, + -36, -38, -23, 27, -21, 14, 56, 47, 6, -72, -61, -4, 18, -4, 19, 13, + 45, 71, 48, -1, -125, -52, -56, -20, -18, -12, 51, 78, 68, -46, 32, -40, + -29, -28, -81, -25, 75, 42, 58, -38, 1, -29, -34, 31, -36, -14, 10, 64, + 37, 2, -31, -72, -17, -33, 30, -52, -54, 25, 43, 70, 81, -9, -73, 4, + -65, 15, -28, 25, 0, 28, 19, 51, -26, 6, 0, -37, -15, -22, -20, -16, + -5, 50, 56, 67, 25, 16, -35, -29, -14, -39, 19, -24, -52, -13, -32, -10, + 39, 33, 59, 6, 37, 55, 11, -9, -35, -15, -57, -56, -36, -34, 19, 19, + 6, 20, 17, -11, 5, 26, 19, 16, 7, -20, -26, -55, -62, -36, -18, 19, + 37, 47, 25, -6, -14, 1, -4, -13, 12, 23, 34, 38, 41, 33, 31, -10, + -56, -52, -49, -31, -40, -21, -12, 0, 5, 12, 22, 22, 21, 31, 12, 2, + -8, -4, -18, -7, 3, 1, -1, 11, 12, 18, 17, 9, -2, -12, -13, -11, + -1, 8, 3, 3, 2, 5, -5, -16, -15, -13, -8, -12, -9, -2, -1, 2, + 7, 10, 7, 11, 14, 7, -1, -4, 5, -3, -2, 0, -6, -10, -1, -5, + 3, 9, 0, -8, -9, -6, -6, 0, 6, 3, 6, 7, 10, 0, -8, -3, + -5, -1, -8, -7, -4, -3, -3, 0, -1, -6, 2, 7, 7, 5, 4, 10, + 5, 8, -1, -11, -15, -11, -15, -10, -1, -8, -12, -5, 1, 3, 6, 8, + 11, 18, 22, 26, 10, -10, -1, -15, -3, -21, -16, -14, -12, -7, -8, -18, + -20, -11, 9, 20, 27, 26, 11, 1, 21, 6, 3, -9, -15, -9, -20, 3, + 5, 21, 14, 6, 11, -21, -22, -6, -21, -23, -18, 11, 6, 5, 21, 9, + 23, 16, -3, -30, -7, -27, -4, 5, 18, 22, 16, 2, 7, -1, -2, -10, + -14, -10, -17, -10, -15, -16, 3, 12, 30, 18, -1, -6, -15, -3, 5, 11, + -18, -2, 8, 21, 11, -13, -4, -30, -7, 0, 12, 25, -3, 17, 14, -20, + -6, -27, -41, -11, -12, 23, -8, 13, 24, 18, 27, -11, -8, -12, -2, 17, + 23, 13, -20, -21, -2, -21, -34, -46, -23, 28, 48, 9, -10, 8, 29, 27, + 5, -29, -12, 13, -5, -2, -35, 1, 3, 24, 13, 17, -18, -30, -21, 14, + -1, 6, -8, 48, 45, -7, -34, -49, -32, -6, -26, 20, 29, 76, 30, -21, + -66, -36, -15, 40, -5, 29, 3, 10, -39, -25, -2, 24, 19, 19, -4, -8, + 3, -22, -23, -18, 13, 17, -3, -25, 23, 66, 26, -18, -27, -34, -30, -30, + 36, 25, 28, -22, -17, -7, -22, 21, 18, 42, 8, -25, -28, -31, -10, 15, + 18, 0, -1, -5, 16, -12, 13, 13, 12, -8, -37, -9, 13, -5, 8, -3, + 13, -8, 4, 24, -16, -43, -18, 26, 26, -11, -9, 19, 9, -15, 9, 15, + -12, -31, -27, 8, 29, 5, 7, 17, -33, -14, 14, 23, -1, -18, -18, -4, + -35, -17, 47, 71, -16, -20, -11, -16, -25, 6, 37, 14, -18, 1, -8, -14, + 10, 14, 2, -20, 0, 20, -10, -25, 14, 32, 7, -39, -38, -3, 34, 25, + 13, 3, -24, -34, 5, 38, 18, 7, 29, -30, -74, -41, 36, 40, -12, 26, + 55, -17, -59, -26, 28, -2, -31, 24, 25, -44, -39, 21, 44, -1, 10, 33, + -34, -50, -12, 18, 13, 20, 17, -6, -31, -10, -6, -1, 7, 12, 14, 6, + -16, -24, 6, 9, -16, -16, 6, 2, -10, 13, 12, -10, 0, 11, 11, 10, + -3, -22, -22, -12, -7, 19, 17, -2, -12, 6, 16, 7, -11, -1, -20, -22, + -8, 26, 16, -3, 12, 1, -33, 2, 30, -23, -5, 28, -17, -19, 21, 9, + -28, -14, 25, -1, 4, 24, 0, -26, -9, 7, 2, -2, 20, -10, -11, 5, + -3, -4, 8, -9, 14, 18, 25, -22, -15, -22, -3, -12, 27, 30, 15, -11, + -26, -4, 15, -7, -14, 23, -23, -4, 34, -2, -38, 14, -11, -24, 16, 34, + 11, -13, 3, -3, -19, -34, 0, -3, 24, 43, 1, -12, -38, -25, -11, 23, + 35, 12, -28, -25, -16, 7, 22, 1, -10, 8, 8, -3, 6, -24, -20, -13, + 9, 31, 12, -16, 7, -29, 5, 8, -28, 3, 4, 12, 26, -9, -15, -5, + -20, 9, 21, 0, 1, -9, 0, 8, -3, -7, -9, -3, 22, 8, 3, -11, + -9, -11, 3, 15, 9, -10, 1, -3, -3, -2, -5, 9, 0, 12, 7, -15, + -7, 0, -8, 5, 9, -5, 7, -7, 10, 4, -11, -2, -8, -4, 9, 9, + 0, -2, -11, -3, -4, 3, 4, 3, -2, 3, 3, -8, -9, -2, 0, 3, + 5, -1, -10, -7, 2, 8, 3, 0, -5, -5, 2, 4, -2, -5, -3, 2, + 3, 0, 2, -5, -3, 3, 2, -2, -4, -2, 1, 2, 1, 0, 0, 0, + 0, -1, -7, -9, -5, 0, 2, 2, 5, 6, 0, -11, -13, -5, 3, 1, + 0, 0, 1, -3, -9, -6, -1, 5, 3, -3, -5, -3, -1, -4, -3, -1, + 2, -2, -9, -7, -2, -5, -18, -31, -36, -36, -41, -38, -29, -21, -27, -31, + -26, -4, 37, 65, 67, 44, 22, 10, 2, -4, 8, 32, 44, 38, 24, 17, + 9, 4, 3, 12, 26, 32, 32, 23, 16, 7, 1, -7, -13, -8, 1, -5, + -39, -72, -79, -64, -49, -40, -24, -1, 12, 0, -25, -44, -43, -30, -14, 1, + 13, 13, 4, 4, 16, 34, 46, 55, 65, 73, 67, 53, 54, 58, 62, 60, + 51, 38, 33, 20, -7, -27, -40, -46, -55, -58, -41, -9, 7, 8, 2, -26, + -49, -71, -92, -101, -93, -80, -70, -71, -73, -65, -67, -69, -61, -42, -15, 15, + 18, -5, -33, -54, -54, -40, -18, 2, 21, 21, 3, -28, -52, -33, 9, 35, + 33, 30, 34, 45, 46, 43, 54, 63, 65, 61, 56, 43, 45, 59, 77, 96, + 104, 112, 115, 100, 78, 53, 22, -3, -6, 5, 24, 37, 38, 35, 25, 3, + -19, -38, -51, -46, -33, -34, -42, -47, -48, -38, -27, -30, -40, -48, -45, -30, + -24, -38, -44, -43, -47, -34, -13, 7, 27, 30, 9, -18, -38, -22, 19, 47, + 70, 83, 68, 28, -13, -41, -41, -19, -1, 10, 8, 4, 4, -7, -12, 6, + 32, 42, 31, 0, -39, -71, -99, -115, -111, -85, -56, -46, -61, -74, -66, -45, + -22, 4, 21, 27, 25, 1, -30, -51, -37, 4, 37, 40, 26, 17, 12, 12, + 5, 1, 2, 12, 29, 43, 44, 45, 54, 45, 28, 10, 13, 26, 32, 43, + 59, 67, 62, 60, 66, 72, 61, 34, 11, 0, 1, -6, -18, -12, 19, 47, + 51, 32, 9, -8, -22, -26, -27, -30, -29, -12, 7, 18, 13, -1, -11, -11, + 5, 16, 14, 11, 5, -19, -47, -54, -29, 13, 37, 42, 33, 9, -17, -31, + -21, 14, 61, 81, 68, 39, 4, -26, -46, -38, -17, -1, 1, -4, -14, -25, + -23, -4, 24, 43, 49, 37, 4, -48, -97, -123, -116, -89, -66, -65, -73, -67, + -64, -66, -69, -46, 3, 36, 27, -3, -25, -39, -38, -39, -36, -24, -9, 5, + 13, 13, 4, -1, -13, -15, 0, 22, 47, 65, 76, 67, 35, 3, -4, 6, + 27, 47, 58, 68, 72, 73, 72, 66, 59, 62, 61, 49, 28, -5, -30, -27, + 9, 40, 51, 46, 40, 28, 1, -30, -56, -57, -41, -13, 5, 12, 7, -11, + -38, -54, -40, -16, 12, 23, 13, -16, -49, -62, -55, -29, 4, 38, 45, 28, + -5, -36, -36, -5, 39, 68, 77, 73, 55, 8, -35, -46, -29, -15, -15, -16, + -12, -9, -23, -30, -18, 16, 48, 51, 24, -18, -45, -72, -96, -111, -101, -80, + -67, -71, -79, -77, -70, -46, -22, -7, -4, -5, -4, -2, -15, -37, -43, -42, + -27, -5, 9, 27, 38, 27, 4, -14, -15, 6, 30, 61, 93, 90, 52, 16, + 2, 1, 5, 11, 34, 64, 79, 71, 48, 35, 43, 61, 59, 46, 27, 1, + -22, -33, -25, -9, 15, 37, 56, 54, 28, -10, -44, -58, -49, -27, -8, 20, + 29, 0, -42, -66, -60, -34, -7, 16, 30, 15, -20, -50, -64, -49, -11, 21, + 34, 34, 17, -7, -31, -29, 3, 43, 69, 78, 73, 45, 10, -20, -32, -33, + -26, -12, -6, -18, -41, -44, -27, -6, 10, 17, 19, 18, -4, -49, -87, -108, + -100, -84, -87, -93, -83, -67, -54, -45, -45, -35, -23, -13, 6, 17, 14, 1, + -22, -40, -35, -18, 2, 28, 57, 63, 33, -7, -21, -4, 23, 57, 89, 102, + 94, 68, 37, 8, -4, 4, 37, 71, 88, 79, 54, 46, 55, 62, 55, 53, + 54, 46, 20, -14, -40, -41, -16, 15, 44, 60, 59, 30, -21, -61, -70, -54, + -26, 10, 29, 19, -16, -49, -63, -58, -33, 4, 29, 26, -1, -33, -49, -50, + -34, -9, 16, 34, 34, 9, -20, -25, -9, 13, 29, 54, 87, 91, 56, 11, + -12, -11, -12, -20, -22, -17, -11, -12, -22, -25, -15, 3, 19, 19, 9, -11, + -38, -62, -76, -92, -107, -109, -95, -68, -53, -49, -49, -58, -63, -48, -25, -5, + 12, 12, -7, -36, -56, -56, -32, 8, 50, 64, 36, 6, -10, -15, -11, 9, + 47, 94, 118, 100, 58, 14, -3, 3, 19, 44, 72, 83, 78, 75, 66, 53, + 45, 52, 66, 70, 52, 22, -8, -36, -36, -14, 21, 63, 84, 63, 14, -29, + -55, -54, -42, -12, 28, 40, 14, -24, -52, -58, -42, -22, 6, 19, 16, -5, + -34, -49, -43, -24, -12, 2, 14, 22, 10, -10, -20, -16, 3, 28, 60, 72, + 61, 42, 25, 1, -26, -44, -46, -31, -25, -26, -32, -30, -24, -12, -12, -15, + 0, 6, -3, -23, -47, -79, -112, -128, -115, -84, -61, -45, -42, -51, -64, -68, + -61, -33, 9, 29, 12, -28, -54, -64, -56, -30, 9, 36, 41, 34, 10, -18, + -38, -29, 13, 70, 105, 106, 79, 48, 31, 12, -1, 12, 51, 78, 89, 87, + 75, 66, 49, 44, 56, 73, 79, 66, 23, -23, -42, -39, -9, 31, 65, 75, + 52, 7, -32, -54, -57, -30, 3, 24, 19, 2, -18, -39, -50, -39, -10, 8, + 10, -2, -12, -18, -21, -29, -33, -16, 11, 28, 17, 1, -4, 3, -3, -6, + 13, 42, 64, 67, 56, 29, 2, -21, -36, -42, -40, -25, -15, -10, -7, -10, + -27, -38, -24, 2, 19, 14, -6, -44, -86, -115, -121, -109, -81, -45, -27, -36, + -58, -76, -81, -53, -13, 11, 8, -11, -24, -40, -58, -62, -30, 11, 42, 44, + 17, -15, -36, -38, -22, 15, 53, 84, 88, 73, 52, 19, -6, -9, 13, 44, + 71, 88, 93, 79, 54, 42, 46, 67, 82, 79, 54, 20, -10, -28, -27, 0, + 46, 70, 61, 29, 2, -18, -38, -45, -23, 7, 16, 10, -8, -22, -26, -30, + -32, -23, -13, -2, 6, -6, -15, -16, -18, -20, -9, 0, 2, 11, 19, 17, + -2, -21, -12, 14, 33, 50, 65, 61, 43, 19, -17, -44, -50, -42, -21, 1, + 11, 1, -31, -56, -45, -22, -1, 17, 18, -4, -44, -95, -126, -123, -95, -56, + -36, -41, -51, -59, -68, -60, -38, -15, 5, 14, 7, -17, -47, -61, -37, 1, + 27, 33, 24, 7, -13, -30, -43, -26, 13, 47, 70, 74, 68, 48, 12, -19, + -14, 14, 46, 74, 81, 75, 64, 52, 48, 56, 67, 82, 78, 44, 9, -12, + -20, -8, 18, 41, 57, 46, 23, 0, -23, -33, -21, -10, -10, -2, 3, 5, + -2, -19, -33, -32, -24, -16, -11, -14, -6, 7, -2, -20, -25, -16, -6, 6, + 17, 27, 22, 2, -10, -11, 0, 24, 51, 68, 79, 65, 25, -19, -49, -48, + -30, -9, 8, 10, -12, -40, -57, -57, -34, -1, 25, 24, -7, -56, -95, -111, + -102, -84, -69, -57, -44, -42, -59, -74, -71, -47, -17, 0, 3, -6, -21, -37, + -38, -27, -6, 15, 23, 22, 12, -4, -23, -32, -26, 1, 36, 63, 82, 78, + 46, 12, -1, 2, 20, 41, 64, 81, 79, 66, 59, 61, 67, 75, 76, 66, + 49, 27, 5, -7, 2, 24, 41, 44, 38, 28, 13, -5, -19, -21, -17, -11, + -2, 4, 4, -2, -14, -28, -32, -27, -21, -16, -13, -1, 6, -4, -21, -25, + -17, -7, 6, 0, 0, -4, -4, -5, -8, -4, 3, 8, 6, 1, 1, 2, + 3, 3, -2, -7, -11, -10, -5, -2, 4, 6, 0, -2, -5, -4, -4, -9, + -9, -7, -11, -11, -10, -7, 4, 0, -4, -4, -1, 4, 0, -4, -3, -5, + -6, -5, -4, 4, -1, 2, 11, 5, -13, -20, -30, -49, -50, -34, -22, -33, + -27, -20, -17, 0, 34, 70, 73, 42, 3, -26, -37, -25, -1, 25, 48, 71, + 75, 44, 22, 45, 69, 57, 44, 52, 58, 24, -23, -41, -50, -58, -67, -82, + -66, -29, -29, -41, -34, -19, -4, -4, -1, 20, 50, 56, 35, 12, 4, -8, + -15, 4, 28, 44, 46, 34, 17, 2, 0, 11, 28, 42, 22, -28, -51, -45, + -34, -39, -37, -19, -17, -30, -32, -18, -4, 9, 19, 38, 35, 3, -24, -35, + -40, -23, -11, -25, -47, -52, -51, -58, -61, -52, -47, -37, -17, -5, -5, -16, + -31, -24, -11, -1, -3, -23, -40, -48, -40, -12, 15, 25, 17, -5, -2, 14, + 21, 15, -12, -26, -18, -2, 28, 48, 55, 52, 42, 35, 35, 42, 38, 36, + 40, 53, 55, 52, 44, 36, 49, 57, 56, 57, 55, 50, 39, 27, 31, 30, + 15, 11, 12, 6, 4, 14, 28, 23, 1, -6, -17, -35, -44, -41, -33, -22, + -9, -6, -12, -15, -13, -27, -29, -7, 14, -5, -55, -71, -49, -33, -37, -46, + -33, -18, -43, -89, -96, -65, -23, 2, 8, 20, 24, -11, -50, -51, -12, 15, + 4, 1, 20, 47, 53, 43, 52, 77, 98, 114, 110, 100, 88, 53, 10, -29, + -55, -71, -83, -77, -58, -55, -57, -52, -48, -47, -46, -12, 34, 59, 52, 25, + -10, -33, -21, 18, 49, 54, 46, 18, 13, 30, 41, 48, 54, 53, 44, 24, + 1, -13, -25, -43, -38, -28, -35, -55, -71, -64, -40, -13, 10, 24, 38, 41, + 21, -1, -11, 1, 15, 7, -6, -13, -39, -57, -64, -51, -20, -12, -24, -37, + -30, -4, 17, 21, 12, -7, -16, -15, -7, 6, 1, -20, -34, -30, -1, 32, + 44, 36, 22, 25, 21, 6, 1, -2, -13, -5, 19, 28, 24, 12, 11, 16, + 19, 38, 54, 49, 38, 28, 28, 39, 52, 49, 32, 25, 33, 45, 49, 39, + 40, 46, 20, -9, -6, 6, 1, -22, -29, 10, 48, 33, -17, -51, -55, -44, + -49, -50, -36, -33, -57, -84, -71, -21, 11, 13, 4, -1, -8, -32, -45, -32, + -10, 2, -13, -37, -39, -42, -57, -65, -63, -36, -11, 10, 33, 22, -12, -34, + -28, -12, 2, 8, 6, -2, -4, 0, 10, 22, 36, 57, 82, 104, 122, 127, + 109, 70, 17, -28, -45, -36, -20, -33, -68, -102, -114, -103, -76, -45, -20, -7, + -11, -10, -2, 6, 0, -14, -5, 30, 48, 29, 3, -8, 10, 39, 67, 86, + 83, 59, 32, 17, 32, 46, 40, 11, -29, -48, -57, -68, -69, -57, -43, -26, + -13, -2, 1, 1, 3, 4, 8, 21, 20, 11, 3, -2, -6, -26, -39, -33, + -34, -36, -28, -23, -27, -28, -17, -1, 0, -6, -10, -9, -7, -12, -26, -44, + -54, -38, -16, 0, 18, 27, 17, -3, -18, -3, 19, 11, -9, -7, 10, 14, + 5, 5, 18, 29, 29, 12, 16, 38, 43, 14, 2, 24, 55, 59, 33, 17, + 24, 44, 65, 75, 77, 55, 15, -16, -20, 6, 31, 27, 17, 18, 19, 17, + 7, 0, -5, -20, -22, -25, -49, -69, -73, -58, -45, -29, -4, 9, -1, -23, + -51, -52, -24, -2, 11, 12, -16, -51, -75, -77, -67, -59, -59, -54, -35, -15, + -9, -9, -9, -7, -8, -12, -1, 15, 22, 10, -14, -34, -28, -14, 11, 64, + 113, 127, 117, 97, 87, 84, 68, 50, 37, 36, 24, -15, -58, -78, -84, -71, + -40, -14, -12, -34, -48, -41, -14, 20, 37, 35, 16, -6, 1, 14, 15, 20, + 23, 24, 38, 58, 69, 57, 40, 54, 73, 75, 65, 40, -3, -49, -68, -56, + -42, -42, -53, -59, -44, -23, -9, -3, -11, -18, -13, -11, -5, 3, 13, 4, + -25, -39, -22, -14, -16, -27, -38, -37, -42, -55, -51, -21, 8, 10, -8, -12, + -4, -10, -39, -55, -38, -13, -4, -11, -15, -3, 15, 12, 2, 11, 28, 34, + 15, -5, 3, 11, 6, 12, 25, 25, 13, 10, 15, 27, 48, 55, 38, 23, + 17, 23, 32, 23, 32, 57, 75, 75, 52, 22, 10, 5, 12, 28, 33, 23, + 2, -14, -4, 19, 30, 25, 15, 1, -27, -64, -78, -67, -49, -45, -48, -42, + -31, -25, -40, -50, -39, -18, -4, 13, 19, 12, -10, -43, -59, -53, -47, -54, + -61, -51, -20, -2, -12, -23, -25, -18, 5, 33, 51, 45, 16, -16, -46, -53, + -38, -6, 33, 57, 74, 81, 75, 77, 89, 105, 114, 110, 83, 39, -6, -25, + -28, -39, -48, -52, -55, -59, -67, -67, -57, -42, -23, -3, 10, 3, -19, -33, + -30, -8, 20, 23, 2, -18, -17, 12, 40, 58, 65, 65, 66, 71, 64, 54, + 38, 1, -41, -62, -47, -26, -31, -49, -55, -42, -21, -17, -19, -10, -2, -3, + -10, -13, 2, 13, -10, -38, -27, 3, 8, -18, -46, -61, -65, -53, -36, -18, + -5, -6, -14, -22, -18, -12, -19, -29, -28, -21, -10, -15, -24, -18, -4, 16, + 23, 17, 14, 10, 9, 13, 15, 28, 35, 19, 4, 2, -2, 9, 34, 62, + 66, 43, 13, -2, 15, 42, 50, 48, 51, 56, 56, 45, 44, 45, 48, 40, + 33, 31, 27, 10, -10, -4, 16, 41, 52, 48, 31, -1, -36, -56, -50, -27, + -14, -25, -43, -60, -67, -47, -31, -38, -47, -40, -17, 13, 32, 28, -10, -50, + -68, -62, -40, -21, -20, -33, -58, -72, -63, -45, -28, -11, 18, 48, 42, 15, + -14, -43, -54, -40, -15, 4, 2, -5, 0, 20, 55, 91, 113, 120, 109, 89, + 77, 63, 43, 26, 20, 12, -13, -47, -69, -68, -53, -49, -49, -36, -28, -27, + -27, -28, -12, 5, 1, -9, -2, 14, 10, -25, -39, -6, 21, 35, 41, 53, + 73, 82, 74, 64, 54, 39, 9, -23, -37, -30, -22, -30, -52, -62, -54, -32, + -9, 2, 5, -3, -17, -25, -17, -1, 13, 8, -7, -12, -7, -7, -21, -40, + -51, -51, -38, -21, -16, -22, -29, -33, -23, -10, -2, -9, -24, -33, -33, -29, + -21, -8, 3, 2, -10, -18, -11, 8, 26, 32, 27, 21, 14, 7, 1, 3, + 12, 22, 35, 45, 43, 29, 13, 10, 20, 37, 54, 59, 45, 28, 28, 37, + 48, 55, 60, 60, 43, 17, 0, -3, 9, 24, 31, 31, 28, 28, 26, 14, + -5, -22, -31, -30, -21, -7, -8, -34, -63, -82, -80, -63, -45, -28, -14, -5, + 3, 2, -11, -27, -39, -33, -11, 2, -8, -39, -73, -95, -91, -54, -8, 19, + 16, 4, 5, 14, 14, 2, -8, -14, -19, -33, -45, -38, -19, 2, 21, 54, + 93, 106, 90, 74, 80, 97, 98, 76, 52, 34, 10, -18, -37, -36, -27, -35, + -52, -62, -56, -44, -39, -37, -29, -17, -8, -2, 3, 4, -4, -16, -27, -32, + -19, 1, 19, 41, 60, 70, 71, 67, 64, 61, 53, 38, 14, -8, -21, -29, + -34, -38, -39, -29, -15, 0, 5, -5, -19, -25, -16, 5, 19, 17, 6, -3, + -7, 0, -1, 1, -2, -5, 0, 0, 2, 0, -3, -2, 0, 1, 0, -2, + -2, -2, 0, 3, 3, -2, -5, -1, -1, -1, -4, 3, 9, 1, -1, -2, + -11, -7, 1, 9, 11, 8, -4, -11, -12, -9, -4, 18, 15, 14, 1, -22, + -29, -14, 3, 30, 29, 14, -2, -35, -43, -11, 13, 36, 42, 15, -16, -49, + -44, -10, 28, 47, 38, 11, -25, -66, -39, 4, 36, 58, 33, -3, -44, -65, + -29, 19, 52, 54, 23, -13, -59, -65, -15, 32, 69, 49, 8, -30, -74, -51, + 3, 43, 71, 40, -5, -48, -77, -31, 16, 57, 67, 24, -15, -67, -72, -12, + 36, 66, 59, 5, -31, -80, -51, 3, 49, 75, 37, -2, -59, -81, -28, 20, + 67, 66, 22, -23, -76, -65, -10, 41, 78, 48, 4, -36, -85, -47, 6, 59, + 80, 31, -8, -69, -82, -22, 29, 73, 63, 17, -31, -81, -63, -1, 47, 79, + 47, 3, -56, -90, -40, 19, 75, 73, 28, -25, -86, -74, -10, 48, 85, 56, + 6, -51, -93, -48, 11, 67, 86, 33, -11, -78, -87, -29, 36, 89, 66, 13, + -38, -91, -60, 2, 50, 83, 48, 0, -56, -90, -41, 16, 71, 78, 30, -17, + -80, -75, -20, 31, 82, 62, 15, -32, -85, -66, -7, 48, 84, 50, 4, -53, + -87, -44, 8, 62, 78, 35, -8, -65, -83, -30, 23, 70, 71, 24, -20, -76, + -75, -12, 32, 73, 62, 15, -30, -85, -62, -2, 41, 76, 51, 9, -39, -86, + -52, 1, 45, 79, 46, 8, -49, -89, -46, 3, 54, 80, 43, 7, -55, -83, + -50, 0, 53, 76, 54, 11, -52, -83, -55, 0, 40, 67, 58, 22, -32, -79, + -67, -11, 28, 63, 52, 37, -9, -70, -63, -28, 10, 42, 49, 53, 8, -46, + -64, -41, 1, 22, 38, 51, 39, -16, -63, -46, -23, 5, 33, 38, 48, 14, + -42, -57, -29, -5, 22, 37, 40, 28, -23, -53, -39, -10, 14, 30, 40, 31, + -1, -48, -40, -18, 11, 19, 31, 26, 14, -20, -50, -25, -5, 11, 31, 30, + 14, 0, -35, -39, -4, -1, 19, 27, 17, 9, -10, -39, -21, -8, 9, 24, + 26, 13, -5, -19, -30, -12, -1, 17, 25, 16, 3, -19, -26, -13, -6, 17, + 22, 20, 5, -16, -32, -19, -1, 23, 27, 23, 4, -30, -33, -23, -1, 35, + 35, 24, -2, -41, -45, -21, 9, 45, 41, 22, -12, -50, -46, -18, 28, 55, + 45, 10, -27, -78, -42, 0, 53, 66, 32, -1, -61, -74, -28, 27, 64, 64, + 24, -28, -80, -66, -15, 53, 84, 48, 5, -59, -94, -41, 17, 75, 80, 26, + -21, -91, -79, -12, 48, 87, 55, 10, -58, -96, -46, 9, 80, 81, 30, -23, + -84, -80, -15, 49, 90, 49, 9, -57, -95, -45, 17, 76, 79, 26, -20, -91, + -75, -18, 52, 90, 52, 6, -59, -92, -41, 15, 68, 80, 31, -21, -87, -76, + -13, 45, 87, 49, 11, -60, -94, -35, 14, 80, 68, 22, -23, -89, -66, -7, + 47, 93, 44, -8, -61, -95, -31, 24, 86, 75, 10, -35, -96, -66, -1, 61, + 100, 44, -12, -77, -105, -33, 32, 97, 92, 16, -44, -111, -90, -5, 65, 121, + 65, -3, -80, -123, -59, 17, 98, 111, 46, -25, -112, -109, -33, 42, 112, 90, + 30, -55, -115, -84, -17, 66, 105, 71, 13, -73, -113, -61, 0, 77, 96, 56, + 4, -80, -108, -50, 8, 78, 93, 47, 3, -88, -98, -40, 7, 65, 76, 53, + 18, -71, -90, -44, 0, 39, 57, 43, 34, -19, -69, -54, -19, 18, 32, 31, + 34, 7, -40, -36, -21, -1, 12, 12, 25, 27, -9, -32, -14, -14, 2, 0, + 1, 20, 19, -2, -13, -11, -18, -12, -2, 18, 24, 12, -2, -14, -19, -19, + -12, 18, 24, 22, -2, -15, -32, -20, 3, 22, 26, 17, -13, -31, -27, -13, + 17, 33, 32, 5, -29, -47, -29, 2, 33, 42, 32, -6, -53, -52, -24, 22, + 51, 41, 27, -32, -74, -45, 0, 45, 59, 33, -1, -62, -66, -31, 26, 73, + 49, 17, -42, -80, -42, -8, 63, 72, 28, -10, -75, -72, -23, 32, 88, 47, + 13, -56, -93, -38, 10, 76, 69, 26, -20, -96, -66, -10, 48, 90, 47, 0, + -69, -103, -29, 25, 87, 73, 18, -35, -104, -68, -2, 61, 93, 47, -5, -83, + -98, -31, 30, 92, 68, 17, -39, -97, -63, -5, 64, 88, 35, -9, -74, -86, + -22, 31, 85, 54, 13, -44, -93, -46, 9, 65, 75, 23, -17, -75, -78, -15, + 39, 84, 54, 3, -52, -96, -46, 12, 71, 90, 29, -18, -89, -87, -26, 36, + 86, 72, 26, -37, -106, -77, -12, 45, 99, 68, 22, -46, -108, -73, -10, 43, + 87, 69, 19, -27, -92, -79, -12, 27, 63, 57, 26, 4, -53, -75, -35, 12, + 33, 37, 31, 26, -9, -53, -39, -16, 6, 20, 23, 22, 13, -8, -22, -23, + -18, -3, 9, 25, 19, 4, -8, -20, -17, -10, 6, 16, 17, 13, -8, -34, + -21, -6, 17, 33, 23, 6, -32, -51, -23, 11, 36, 46, 31, -11, -46, -65, + -31, 15, 59, 55, 28, -20, -73, -64, -26, 42, 78, 51, 14, -53, -85, -48, + -4, 70, 80, 38, -16, -80, -76, -32, 39, 90, 58, 19, -59, -99, -50, 14, + 71, 75, 36, -21, -94, -70, -23, 51, 88, 53, 9, -68, -97, -40, 16, 83, + 73, 29, -33, -100, -61, -13, 58, 87, 41, 0, -74, -81, -35, 24, 87, 55, + 20, -41, -88, -58, 0, 69, 73, 34, -5, -86, -75, -20, 38, 79, 49, 13, + -48, -90, -39, 2, 71, 68, 31, -16, -84, -67, -15, 38, 79, 42, 12, -50, + -85, -37, 2, 62, 71, 34, -5, -83, -75, -24, 27, 82, 51, 27, -30, -88, + -54, -15, 44, 73, 50, 16, -49, -81, -47, -6, 38, 58, 50, 27, -31, -69, + -52, -13, 15, 36, 45, 33, -5, -41, -44, -23, 2, 14, 27, 33, 10, -25, + -20, -18, -6, 1, -1, 17, 22, 3, -13, -10, -17, -13, -6, 13, 24, 15, + 1, -11, -19, -19, -16, 12, 24, 24, 3, -12, -29, -26, -1, 18, 27, 19, + -4, -31, -28, -19, 11, 30, 35, 12, -21, -46, -35, -6, 28, 42, 36, 5, + -46, -57, -31, 10, 50, 43, 33, -16, -71, -55, -9, 35, 62, 38, 10, -51, + -71, -40, 11, 69, 58, 24, -26, -81, -50, -18, 48, 79, 37, 1, -62, -81, + -32, 16, 84, 59, 20, -37, -96, -50, -2, 63, 78, 33, -4, -85, -80, -20, + 33, 88, 59, 10, -50, -107, -47, 14, 75, 85, 27, -19, -95, -83, -15, 47, + 94, 60, 8, -66, -105, -46, 15, 83, 81, 26, -23, -91, -76, -18, 48, 92, + 47, 1, -59, -94, -36, 18, 78, 66, 19, -27, -91, -60, -3, 53, 80, 35, + -8, -62, -86, -28, 27, 79, 66, 13, -38, -94, -62, 1, 56, 95, 42, -6, + -75, -96, -39, 22, 80, 80, 36, -20, -97, -92, -24, 30, 93, 79, 32, -27, + -102, -87, -22, 31, 81, 79, 29, -14, -81, -91, -25, 19, 56, 63, 31, 11, + -39, -77, -47, 3, 31, 37, 33, 27, 3, -48, -46, -20, 0, 18, 22, 23, + 16, -3, -20, -19, -15, -4, 2, 8, 5, 0, 0, 0, 0, 2, 2, 5, + 9, 12, 14, 12, 7, 6, 4, 0, -1, -1, 1, -2, -2, -11, -17, -32, + -41, -49, -55, -58, -61, -61, -65, -61, -57, -47, -37, -27, -22, -15, -5, 6, + 12, 16, 21, 27, 28, 32, 33, 35, 41, 44, 45, 47, 50, 54, 57, 56, + 53, 53, 54, 50, 50, 52, 54, 56, 52, 53, 54, 50, 49, 46, 43, 38, + 33, 27, 19, 8, 2, -11, -20, -27, -29, -30, -32, -35, -42, -52, -57, -57, + -59, -48, -40, -27, -13, 4, 13, 20, 18, 14, 11, 7, 3, -1, -3, -10, + -11, -20, -28, -46, -60, -72, -82, -92, -97, -97, -97, -94, -90, -81, -71, -61, + -55, -55, -53, -47, -38, -29, -23, -11, -6, -3, 1, 2, 5, 6, 3, 3, + 5, 15, 24, 28, 30, 30, 35, 37, 36, 39, 39, 44, 47, 48, 56, 62, + 73, 84, 91, 96, 95, 91, 85, 76, 72, 63, 55, 47, 44, 43, 41, 38, + 31, 19, 7, 0, -9, -7, -4, 8, 22, 40, 54, 67, 71, 70, 64, 56, + 45, 32, 24, 15, 12, 3, -3, -21, -42, -66, -84, -102, -117, -124, -128, -127, + -124, -118, -107, -96, -86, -86, -88, -86, -80, -70, -63, -50, -40, -33, -25, -23, + -20, -18, -18, -21, -25, -22, -14, -8, -3, -3, -1, 1, 0, 1, -3, -1, + 2, 4, 13, 24, 35, 49, 59, 67, 70, 69, 68, 59, 54, 46, 40, 31, + 29, 27, 25, 23, 20, 12, -1, -9, -19, -22, -21, -11, 3, 23, 41, 60, + 71, 76, 73, 71, 65, 56, 50, 44, 42, 35, 33, 24, 9, -13, -31, -48, + -65, -76, -83, -83, -82, -77, -69, -59, -46, -40, -40, -41, -38, -30, -24, -13, + -2, 8, 17, 22, 24, 25, 23, 20, 13, 9, 11, 15, 19, 16, 12, 9, + 4, 1, -6, -10, -11, -14, -12, -5, 3, 15, 26, 35, 40, 41, 41, 35, + 28, 19, 12, 3, -2, -6, -7, -10, -13, -19, -31, -39, -50, -56, -58, -52, + -41, -22, -3, 18, 34, 46, 48, 47, 45, 38, 32, 26, 24, 20, 19, 15, + 5, -14, -32, -49, -65, -79, -88, -91, -91, -88, -82, -75, -63, -52, -47, -46, + -46, -38, -31, -21, -8, 4, 17, 26, 31, 36, 39, 42, 40, 35, 36, 39, + 47, 48, 45, 43, 38, 36, 30, 24, 22, 19, 18, 23, 29, 40, 50, 61, + 68, 72, 74, 71, 66, 57, 50, 40, 32, 24, 21, 16, 12, 7, -3, -14, + -26, -38, -45, -46, -43, -31, -16, 3, 18, 33, 39, 39, 36, 31, 22, 13, + 8, 3, -1, -4, -9, -24, -42, -60, -77, -94, -107, -115, -119, -120, -116, -112, + -103, -91, -81, -78, -80, -75, -69, -61, -51, -39, -25, -13, -5, 2, 8, 14, + 17, 16, 15, 16, 24, 31, 32, 32, 29, 29, 27, 22, 21, 20, 19, 22, + 26, 35, 46, 59, 70, 77, 83, 85, 84, 79, 74, 66, 59, 50, 46, 41, + 38, 35, 29, 21, 11, 0, -9, -14, -16, -11, 0, 16, 30, 48, 58, 62, + 61, 58, 51, 40, 31, 25, 19, 15, 13, 4, -11, -28, -44, -61, -76, -87, + -95, -100, -100, -99, -95, -86, -75, -68, -69, -68, -67, -62, -56, -49, -38, -27, + -19, -13, -9, -3, 2, 1, -1, -3, 0, 7, 10, 10, 6, 5, 4, 0, + -4, -5, -7, -7, -7, -2, 5, 16, 27, 36, 44, 49, 52, 50, 46, 40, + 35, 26, 22, 18, 15, 15, 13, 9, 4, -5, -14, -19, -23, -21, -14, 0, + 15, 33, 49, 60, 63, 63, 61, 53, 44, 38, 32, 27, 27, 23, 14, 0, + -14, -29, -44, -58, -67, -74, -76, -76, -73, -67, -55, -45, -41, -41, -41, -39, + -35, -30, -23, -12, -3, 4, 9, 14, 20, 21, 20, 17, 15, 19, 24, 26, + 24, 21, 20, 18, 12, 9, 6, 3, 0, 1, 4, 11, 21, 30, 38, 43, + 47, 48, 45, 38, 32, 23, 15, 9, 5, 3, 1, -2, -5, -13, -22, -30, + -37, -41, -40, -30, -18, -3, 15, 30, 38, 41, 41, 37, 27, 19, 12, 6, + 3, 2, -2, -13, -25, -39, -53, -67, -78, -88, -92, -92, -91, -86, -77, -63, + -54, -50, -48, -47, -43, -38, -32, -23, -11, -1, 6, 11, 19, 25, 27, 26, + 24, 26, 31, 36, 38, 36, 37, 37, 34, 32, 29, 27, 24, 22, 23, 27, + 35, 45, 53, 61, 67, 70, 71, 66, 60, 51, 42, 34, 28, 24, 21, 18, + 16, 11, 2, -8, -16, -24, -28, -25, -17, -5, 10, 26, 39, 45, 47, 45, + 37, 27, 18, 9, 3, 0, -2, -10, -22, -36, -51, -67, -81, -93, -102, -107, + -108, -107, -102, -90, -78, -71, -67, -66, -63, -59, -56, -49, -39, -28, -19, -13, + -6, 1, 7, 8, 6, 5, 8, 14, 19, 19, 19, 20, 20, 19, 16, 15, + 13, 12, 11, 13, 20, 30, 39, 49, 57, 63, 68, 68, 65, 58, 51, 43, + 37, 32, 29, 27, 26, 24, 19, 11, 2, -5, -12, -14, -9, 0, 13, 30, + 46, 56, 62, 65, 61, 53, 44, 35, 26, 22, 20, 15, 6, -6, -20, -36, + -51, -66, -78, -87, -91, -92, -92, -85, -74, -65, -58, -56, -55, -52, -50, -46, + -40, -30, -20, -14, -8, -2, 5, 7, 6, 3, 2, 5, 10, 11, 10, 9, + 9, 8, 5, 2, 0, -2, -5, -5, -3, 5, 14, 23, 32, 39, 46, 50, + 49, 45, 38, 31, 24, 17, 14, 11, 10, 9, 7, 2, -5, -12, -20, -25, + -25, -19, -8, 7, 24, 40, 50, 58, 60, 56, 49, 41, 31, 24, 22, 20, + 15, 6, -5, -19, -34, -48, -61, -72, -79, -83, -85, -81, -72, -62, -52, -47, + -44, -41, -39, -35, -31, -24, -13, -5, 1, 7, 14, 20, 22, 21, 19, 18, + 22, 25, 25, 24, 23, 23, 20, 17, 15, 12, 10, 7, 5, 9, 16, 24, + 33, 40, 47, 53, 56, 54, 48, 41, 33, 25, 20, 15, 11, 9, 8, 5, + -2, -10, -19, -27, -32, -31, -25, -15, 0, 17, 30, 40, 46, 46, 42, 35, + 25, 15, 10, 9, 5, -2, -11, -23, -37, -52, -65, -79, -89, -95, -99, -100, + -95, -85, -74, -65, -60, -55, -52, -48, -44, -40, -29, -18, -10, -4, 4, 12, + 18, 20, 19, 17, 20, 24, 27, 27, 26, 26, 25, 23, 21, 19, 17, 15, + 12, 13, 17, 25, 34, 41, 49, 57, 62, 65, 63, 57, 51, 42, 35, 30, + 25, 22, 21, 19, 15, 8, 0, -9, -17, -21, -20, -14, -3, 13, 26, 38, + 48, 53, 52, 47, 39, 28, 19, 15, 13, 8, 0, -10, -22, -37, -51, -65, + -79, -88, -95, -100, -99, -94, -84, -74, -67, -61, -58, -55, -51, -49, -43, -33, + -23, -17, -10, -2, 6, 10, 11, 9, 9, 12, 15, 17, 16, 16, 16, 14, + 12, 11, 9, 8, 5, 3, 4, 10, 18, 26, 34, 42, 50, 57, 59, 57, + 52, 45, 38, 32, 27, 23, 21, 20, 19, 14, 8, 1, -9, 2, 5, 7, + 8, -1, 6, 15, 1, 20, 28, 1, 37, 41, 31, 29, 27, 61, 40, -12, + 38, 52, -16, -20, -1, -23, -48, -56, -63, -61, -77, -100, -88, -76, -103, -113, + -98, -103, -118, -120, -108, -107, -104, -110, -118, -104, -109, -128, -107, -83, -106, -86, + -94, -100, -77, -113, -88, -43, -77, -46, -44, -69, -34, -54, -39, 4, -30, 11, + 18, -25, 20, 16, 10, 52, 35, 52, 74, 33, 55, 74, 59, 70, 81, 85, + 91, 81, 72, 89, 94, 82, 80, 99, 100, 85, 86, 91, 100, 91, 81, 91, + 102, 83, 74, 92, 95, 63, 62, 75, 71, 63, 39, 54, 74, 15, 1, 31, + 6, -5, -13, -20, -8, -44, -59, -38, -69, -73, -67, -86, -90, -68, -73, -77, + -49, -82, -70, -43, -76, -27, 0, -29, 22, 25, -5, 44, 45, 29, 66, 71, + 49, 84, 92, 73, 92, 74, 72, 91, 37, 48, 99, 47, 31, 44, 36, 33, + -5, -11, 26, 6, -33, -22, -6, -32, -55, -44, -45, -52, -63, -73, -55, -51, + -77, -79, -61, -73, -91, -83, -70, -77, -74, -82, -85, -68, -88, -98, -57, -67, + -77, -58, -75, -66, -64, -78, -33, -37, -50, -19, -47, -38, -23, -41, 3, 6, + -7, 30, 0, -4, 24, 15, 31, 45, 44, 66, 44, 34, 58, 54, 59, 67, + 71, 87, 78, 60, 73, 84, 78, 76, 86, 95, 89, 76, 85, 94, 89, 73, + 82, 99, 85, 66, 75, 93, 75, 50, 56, 69, 59, 31, 31, 61, 29, -15, + 15, 5, -15, -14, -36, -25, -29, -69, -55, -53, -82, -78, -76, -95, -88, -69, + -80, -65, -63, -86, -58, -67, -59, -12, -28, -9, 29, -8, 13, 44, 22, 44, + 68, 53, 62, 91, 74, 81, 89, 64, 84, 78, 35, 78, 86, 44, 43, 47, + 45, 22, -5, 17, 21, -16, -24, -14, -14, -34, -50, -40, -36, -63, -71, -58, + -60, -69, -78, -78, -67, -81, -98, -78, -71, -89, -85, -84, -86, -82, -99, -82, + -60, -76, -75, -74, -76, -71, -86, -68, -37, -51, -34, -41, -57, -37, -51, -31, + -7, -17, -3, 1, 7, 22, 31, 46, 57, 41, 43, 56, 63, 62, 68, 85, + 86, 80, 84, 92, 96, 93, 93, 104, 105, 96, 99, 108, 106, 102, 98, 102, + 111, 99, 87, 106, 110, 85, 80, 88, 89, 79, 68, 70, 81, 48, 25, 39, + 32, 18, 9, 12, 0, -29, -31, -38, -60, -52, -63, -79, -71, -66, -62, -59, + -62, -74, -72, -73, -81, -43, -21, -28, 8, 10, -10, 16, 28, 27, 42, 50, + 47, 66, 76, 68, 81, 73, 67, 72, 39, 40, 67, 41, 23, 25, 22, 12, + -16, -22, -5, -27, -51, -44, -45, -57, -68, -73, -71, -74, -91, -89, -84, -90, + -97, -98, -98, -102, -105, -108, -103, -97, -105, -109, -101, -107, -113, -106, -92, -87, + -90, -92, -92, -92, -100, -92, -57, -56, -54, -40, -59, -58, -54, -61, -23, -9, + -12, 16, 0, -14, 4, 5, 17, 32, 41, 57, 55, 43, 54, 66, 67, 68, + 84, 89, 87, 87, 91, 98, 100, 96, 104, 109, 105, 103, 108, 111, 109, 105, + 105, 113, 111, 99, 102, 115, 104, 88, 90, 97, 93, 80, 75, 86, 75, 37, + 40, 43, 33, 20, 20, -14, -26, -36, -53, -52, -65, -75, -75, -69, -69, -69, + -74, -77, -76, -74, -59, -34, -26, -9, 9, 5, 13, 32, 39, 42, 53, 58, + 61, 73, 77, 77, 73, 61, 57, 46, 29, 37, 37, 17, 6, 2, -10, -27, + -38, -41, -46, -58, -68, -69, -75, -85, -89, -92, -97, -101, -103, -106, -107, -108, + -112, -111, -112, -115, -115, -115, -113, -111, -116, -115, -112, -116, -117, -110, -101, -98, + -101, -101, -98, -101, -101, -86, -69, -65, -59, -57, -62, -58, -54, -39, -19, -12, + 1, 7, -1, 5, 16, 24, 36, 46, 58, 64, 61, 64, 74, 79, 81, 90, + 96, 97, 100, 100, 104, 108, 107, 111, 114, 113, 115, 115, 115, 118, 117, 116, + 118, 119, 116, 115, 116, 117, 111, 104, 105, 107, 99, 93, 95, 91, 71, 57, + 53, 47, 38, 29, 23, 14, -11, -28, -38, -49, -58, -67, -73, -80, -84, -84, + -83, -82, -80, -78, -74, -67, -56, -42, -29, -16, -4, 7, 18, 29, 40, 49, + 57, 64, 70, 74, 78, 79, 77, 72, 67, 60, 53, 48, 42, 33, 23, 14, + 4, -6, -16, -24, -32, -40, -48, -55, -61, -68, -74, -78, -83, -87, -91, -94, + -96, -99, -101, -103, -104, -106, -107, -107, -107, -107, -107, -108, -107, -107, -107, -105, + -101, -98, -96, -94, -93, -91, -87, -82, -74, -67, -62, -57, -54, -49, -43, -35, + -25, -16, -7, -1, 4, 10, 17, 25, 33, 41, 49, 55, 59, 63, 69, 74, + 78, 83, 88, 91, 93, 96, 98, 100, 102, 104, 106, 107, 107, 108, 108, 109, + 109, 108, 108, 108, 107, 105, 104, 102, 99, 94, 91, 87, 83, 78, 73, 66, + 56, 46, 37, 28, 19, 9, 0, -11, -23, -35, -45, -55, -64, -71, -78, -83, + -85, -84, -83, -81, -79, -75, -70, -61, -49, -36, -23, -10, 2, 12, 24, 35, + 45, 53, 61, 67, 72, 76, 79, 78, 75, 70, 65, 58, 52, 46, 39, 29, + 20, 11, 1, -9, -18, -26, -34, -42, -50, -56, -63, -69, -74, -79, -83, -88, + -91, -94, -96, -98, -101, -102, -104, -105, -106, -106, -106, -106, -106, -106, -106, -106, + -105, -102, -98, -96, -94, -92, -90, -88, -84, -77, -70, -64, -59, -55, -51, -45, + -38, -29, -20, -11, -4, 2, 7, 13, 21, 29, 37, 44, 51, 56, 60, 65, + 70, 75, 80, 84, 88, 91, 93, 96, 98, 100, 102, 104, 105, 106, 107, 107, + 108, 108, 107, 107, 107, 106, 104, 103, 101, 99, 95, 91, 87, 83, 78, 73, + 67, 59, 49, 39, 30, 21, 12, 3, -8, -19, -31, -41, -51, -60, -68, -75, + -81, -84, -85, -84, -82, -80, -77, -73, -65, -55, -42, -29, -16, -4, 7, 18, + 29, 40, 49, 57, 64, 70, 74, 78, 79, 77, 73, 68, 62, 56, 50, 44, + 36, 26, 17, 7, -3, -12, -20, -28, -36, -44, -51, -58, -64, -70, -75, -79, + -84, -88, -91, -93, -96, -98, -100, -102, -103, -105, -105, -105, -105, -105, -105, -105, + -105, -104, -102, -99, -96, -94, -92, -90, -88, -85, -79, -72, -66, -61, -56, -52, + -47, -41, -33, -24, -15, -8, -1, 4, 10, 17, 24, 32, 40, 47, 53, 57, + 62, 67, 72, 77, 81, 85, 89, 91, 94, 96, 98, 100, 102, 104, 105, 105, + 106, 106, 107, 106, 106, 106, 105, 104, 102, 101, 99, 95, 91, 87, 83, 79, + 74, 68, 61, 52, 42, 33, 24, 15, 5, -5, -15, -27, -38, -48, -57, -66, + -72, -79, -83, -85, -85, -83, -81, -79, -75, -69, -60, -48, -35, -23, -10, 2, + 13, 24, 35, 45, 54, 61, 67, 72, 77, 78, 79, 76, 72, 66, 60, 54, + 49, 41, 32, 23, 12, 3, -4, -17, -15, 1, -1, 0, 0, 1, 3, 5, + 9, 13, 18, 24, 32, 38, 32, 18, -9, -48, -73, -41, 2, -3, -24, -34, + -44, -72, -111, -124, -62, 40, 40, -51, -35, 45, 46, -22, -79, 35, 78, -47, + -98, -88, -69, -57, -44, -31, -17, -9, -3, 6, 41, 85, 43, -91, -128, -65, + -25, -21, -19, -12, 2, 16, 29, 39, 49, 48, 10, -69, -47, 50, 8, -52, + -44, 5, 21, -40, -42, 33, 79, 66, 38, 24, 25, 26, 18, 21, 70, 117, + 98, 28, -1, 20, 22, 0, 1, 9, -10, -49, -33, 39, 68, 39, -5, -17, + -58, -76, 78, 104, 17, 6, -23, -43, -13, 58, 85, 43, 21, 35, 46, 31, + 22, 35, 14, -48, -74, -38, 6, 10, -8, -17, -24, -37, -60, -69, -41, 15, + 27, -21, -26, 18, 28, -1, -41, 5, 51, -9, -51, -48, -38, -31, -24, -16, + -8, -2, 1, 6, 23, 52, 41, -39, -83, -50, -19, -13, -12, -8, 1, 10, + 20, 27, 34, 35, 15, -40, -46, 27, 16, -35, -38, -6, 19, -18, -35, 17, + 61, 55, 33, 21, 22, 25, 21, 18, 52, 98, 92, 31, -5, 9, 17, -1, + -2, 7, -7, -47, -43, 24, 62, 39, -3, -20, -48, -88, 46, 113, 25, 4, + -20, -45, -25, 42, 82, 47, 19, 28, 42, 32, 18, 30, 19, -39, -77, -51, + -4, 10, -6, -18, -25, -37, -57, -70, -50, 4, 26, -15, -33, 9, 27, 6, + -38, -12, 50, 6, -47, -50, -40, -32, -25, -17, -10, -3, 0, 4, 17, 45, + 47, -23, -82, -60, -24, -14, -13, -10, -2, 7, 16, 24, 30, 33, 18, -32, + -56, 13, 23, -31, -41, -15, 19, -6, -35, 4, 52, 55, 35, 21, 22, 25, + 22, 15, 41, 89, 94, 38, -5, 4, 16, 2, -2, 7, -4, -41, -48, 12, + 58, 43, 2, -20, -38, -89, 14, 118, 38, 3, -15, -43, -32, 28, 78, 53, + 19, 24, 40, 34, 18, 26, 23, -28, -75, -61, -14, 10, -2, -16, -24, -34, + -53, -68, -55, -7, 25, -8, -36, 1, 27, 12, -31, -26, 45, 22, -39, -50, + -41, -32, -25, -17, -10, -4, 0, 3, 13, 38, 51, -5, -77, -69, -31, -15, + -14, -11, -4, 5, 13, 21, 27, 31, 20, -24, -61, -3, 28, -23, -43, -23, + 15, 5, -32, -6, 43, 53, 36, 22, 21, 26, 24, 14, 32, 79, 95, 46, + -3, 0, 15, 5, -1, 7, -1, -36, -52, 2, 53, 46, 7, -18, -30, -84, + -15, 114, 55, 4, -10, -40, -37, 15, 72, 59, 22, 20, 36, 36, 19, 23, + 26, -18, -70, -68, -25, 7, 2, -13, -22, -32, -49, -65, -59, -16, 22, -1, + -36, -8, 25, 17, -22, -35, 34, 36, -29, -48, -42, -32, -25, -18, -10, -4, + 0, 3, 10, 32, 52, 11, -67, -76, -38, -16, -13, -11, -6, 3, 11, 19, + 25, 30, 22, -15, -62, -19, 30, -14, -43, -30, 9, 13, -25, -15, 33, 51, + 37, 23, 21, 26, 26, 15, 24, 68, 94, 54, 0, -3, 13, 8, 1, 8, + 2, -30, -53, -8, 47, 49, 13, -16, -25, -75, -41, 102, 73, 6, -5, -36, + -40, 2, 65, 64, 25, 18, 33, 37, 21, 21, 27, -8, -63, -73, -36, 2, + 5, -10, -21, -30, -45, -62, -61, -25, 17, 5, -35, -17, 21, 21, -13, -39, + 20, 46, -16, -46, -42, -32, -25, -17, -10, -4, 0, 3, 8, 27, 50, 25, + -54, -81, -46, -19, -13, -12, -7, 1, 9, 17, 23, 28, 23, -8, -59, -35, + 27, -5, -42, -35, 2, 20, -16, -20, 24, 47, 38, 24, 21, 27, 28, 17, + 18, 58, 91, 62, 5, -6, 10, 10, 3, 9, 5, -24, -52, -17, 40, 50, + 18, -13, -22, -64, -60, 83, 90, 12, -3, -31, -41, -8, 55, 67, 30, 17, + 30, 37, 24, 19, 27, 1, -54, -75, -46, -4, 7, -7, -18, -28, -41, -58, + -61, -32, 11, 10, -31, -24, 17, 23, -4, -39, 5, 52, -2, -42, -42, -32, + -25, -17, -10, -4, 0, 3, 6, 22, 47, 35, -38, -82, -55, -23, -13, -12, + -8, -1, 7, 15, 21, 26, 23, -1, -53, -48, 20, 5, -39, -39, -6, 22, + -5, -22, 14, 43, 38, 25, 21, 27, 29, 19, 15, 47, 86, 68, 12, -7, + 7, 11, 4, 10, 7, -18, -50, -25, 33, 51, 24, -10, -20, -52, -72, 58, + 103, 21, -1, -26, -41, -17, 44, 67, 35, 16, 27, 36, 26, 18, 25, 8, + -45, -76, -55, -13, 7, -3, -16, -26, -38, -55, -61, -38, 4, 13, -26, -30, + 11, 25, 4, -36, -10, 51, 14, -37, -42, -33, -24, -17, -10, -4, 1, 3, + 6, 18, 42, 42, -22, -80, -63, -28, -14, -12, -9, -3, 5, 12, 19, 24, + 23, 3, -46, -58, 9, 14, -34, -41, -14, 21, 6, -21, 4, 36, 38, 26, + 21, 26, 30, 22, 13, 37, 78, 73, 20, -7, 4, 11, 6, 10, 10, -11, + -45, -33, 22, 49, 29, -4, -18, -40, -75, 23, 108, 40, 1, -18, -39, -26, + 28, 65, 42, 17, 22, 34, 29, 18, 23, 15, -30, -71, -65, -27, 3, 2, + -11, -22, -34, -49, -58, -45, -7, 13, -16, -35, -1, 24, 13, -23, -26, 37, + 36, -20, -39, -34, -24, -17, -10, -4, 1, 3, 5, 12, 33, 46, 6, -64, + -75, -40, -17, -12, -10, -5, 2, 9, 15, 20, 22, 10, -30, -65, -18, 20, + -19, -42, -27, 11, 21, -8, -8, 22, 34, 27, 22, 26, 31, 27, 14, 22, + 60, 75, 34, -4, -2, 8, 8, 11, 14, -2, -36, -42, 6, 44, 36, 4, + -15, -26, -66, -24, 95, 71, 8, -10, -33, -32, 7, 56, 51, 21, 17, 29, + 32, 20, 19, 20, -12, -59, -72, -45, -8, 5, -5, -17, -28, -42, -54, -50, + -21, 9, -5, -36, -16, 19, 21, -7, -34, 12, 51, 4, -33, -34, -25, -17, + -10, -4, 1, 4, 5, 9, 23, 44, 29, -39, -79, -55, -24, -13, -10, -7, + -1, 6, 12, 16, 20, 14, -15, -62, -46, 16, -2, -39, -36, -2, 29, 9, + -12, 8, 28, 27, 23, 25, 31, 31, 17, 13, 43, 72, 46, 2, -5, 5, + 8, 11, 16, 5, -26, -44, -8, 36, 40, 12, -12, -19, -52, -53, 67, 94, + 20, -5, -27, -35, -7, 45, 55, 27, 15, 25, 32, 23, 17, 21, 0, -47, + -73, -57, -19, 4, 0, -13, -24, -37, -50, -51, -29, 3, 1, -32, -26, 12, + 23, 3, -32, -6, 52, 22, -26, -34, -25, -17, -10, -4, 1, 5, 6, 8, + 18, 39, 38, -21, -76, -64, -30, -14, -10, -8, -2, 4, 10, 15, 18, 14, + -9, -56, -57, 7, 7, -35, -39, -10, 27, 18, -10, 2, 23, 26, 23, 24, + 31, 32, 20, 11, 35, 67, 51, 7, -6, 3, 8, 11, 17, 8, -20, -44, + -15, 31, 41, 16, -9, -17, -43, -61, 44, 102, 31, -2, -23, -35, -15, 36, + 56, 32, 0, -27, 1, -1, -1, 3, -4, -2, 1, -1, -2, 2, 3, -6, + 1, 2, -6, 2, 2, -4, -1, 2, -5, 1, 4, -4, 0, -1, 0, -1, + -2, 2, 2, -6, 0, 4, -3, -3, 4, -2, -3, -2, 0, 1, 1, -2, + -2, 3, -8, 27, -42, 11, 21, -35, 34, -25, 12, 9, -24, 14, 13, -38, + 53, -42, -3, 46, -73, 55, -16, -9, 28, -49, 38, -12, -21, 49, -51, 20, + 32, -73, 64, -28, -7, 32, -50, 42, -11, -30, 49, -21, -31, 46, -25, -7, + 20, -22, 18, -16, -10, 21, -23, 5, 28, -35, 8, 0, 8, -26, 19, 6, + -11, -20, 64, -46, -18, 51, -73, 119, -117, 46, 36, -80, 67, -46, 22, 0, + -24, 56, -59, 14, 26, -40, 24, -9, 20, -20, -15, 43, -26, -11, 9, 14, + -3, -31, 6, 54, -62, 3, 67, -78, 20, 21, -25, 31, -41, 18, 27, -53, + 32, 15, -48, 37, -11, 4, -12, -3, 31, -24, -21, 42, -10, -45, 55, -32, + 34, -43, -14, 86, -78, 8, 39, -35, -2, 13, 2, 5, -11, -4, 7, 5, + -31, 37, -4, -28, 28, -9, -11, 10, -1, 4, -18, 17, -9, -13, 24, -18, + 20, -18, -30, 59, -25, -29, 48, -15, -29, 23, 4, -3, -18, 14, 6, -8, + -19, 19, 8, -13, 0, 13, -18, 4, 1, 0, 0, 10, -14, -12, 39, -46, + 23, 9, -22, 23, -20, -22, 63, -42, -28, 77, -66, 12, 38, -56, 31, 27, + -77, 66, -11, -39, 59, -33, -41, 92, -54, -50, 96, -36, -46, 46, -17, 31, + -43, -28, 98, -57, -50, 84, -22, -44, 39, -8, 17, -28, -13, 63, -67, 16, + 10, 3, -15, -4, 36, -34, -1, 26, -27, -2, 13, 7, -22, 0, 27, -11, + -19, 6, 26, -42, 14, 18, -7, -14, -10, 37, -14, -24, 25, -4, -5, -10, + 3, 35, -39, -7, 31, -8, -23, 15, 4, -1, -25, 28, 7, -35, 34, -16, + -1, 9, -35, 45, -22, -17, 48, -52, 24, 22, -65, 48, 7, -45, 47, -19, + -33, 71, -70, 46, -7, -52, 68, -25, -35, 48, -13, -17, 14, 2, -12, 8, + -10, 1, 22, -32, 4, 34, -26, -18, 29, -7, -19, 15, -7, 15, -8, -29, + 50, -22, -35, 53, -19, -37, 47, -9, -40, 41, 1, -27, 7, 3, 0, 0, + -7, 13, -7, -21, 26, 14, -44, 11, 40, -51, 10, 26, -28, 16, -13, -3, + 31, -42, 11, 34, -52, 11, 34, -43, 10, 29, -19, -21, 27, -10, -5, 10, + -14, 11, 3, -35, 43, 3, -52, 37, 22, -66, 49, -12, -19, 50, -58, 16, + 42, -70, 50, -2, -42, 60, -69, 43, 11, -57, 54, -8, -31, 23, -8, -7, + 24, -32, 11, 21, -51, 60, -44, -6, 68, -87, 33, 45, -79, 50, -7, -13, + 21, -40, 31, 12, -41, 18, 24, -39, 15, 7, -17, 25, -20, -12, 43, -47, + 17, 6, -16, 10, 4, -11, -1, 14, -10, -7, 6, 9, -23, 9, 3, 13, + -30, 16, 16, -33, 17, 4, -17, 23, -29, 3, 54, -86, 50, 11, -41, 30, + -23, 15, 18, -60, 56, 7, -65, 49, -4, -12, 1, -6, 19, -4, -33, 35, + -10, -12, 13, -2, -2, -2, 2, -10, 16, -8, -11, 19, -6, -19, 24, -14, + 9, 3, -24, 24, -6, -13, 19, -11, -6, 6, -9, 16, -8, -10, 14, -10, + -1, -5, 16, -8, -25, 37, -11, -27, 37, -14, -13, 19, -17, 14, -5, -15, + 26, -27, 10, 11, -23, 22, -5, -19, 25, -7, -28, 44, -35, 0, 25, -31, + 31, -10, -26, 46, -41, 2, 33, -40, 24, 8, -43, 44, -12, -25, 37, -25, + -6, 29, -27, 5, 24, -40, 24, -1, -25, 23, -1, -6, -2, -1, 14, -24, + 8, 13, -11, 0, -13, 16, 15, -56, 43, 12, -35, 14, -9, 18, -10, -19, + 28, -3, -27, 23, -2, -14, 27, -35, 10, 35, -68, 44, 7, -43, 46, -21, + -25, 56, -35, -21, 51, -33, -8, 28, -27, 19, -2, -26, 36, -26, 3, 13, + -12, 6, -10, 8, -14, 15, -12, 0, 13, -9, -16, 32, -27, 3, 23, -49, + 49, -17, -31, 63, -64, 25, 36, -76, 61, -11, -47, 75, -54, -9, 69, -81, + 32, 29, -63, 46, -7, -26, 39, -31, 6, 18, -26, 13, -5, 5, -5, -2, + 5, -12, 17, -17, -2, 22, -25, 1, 20, -19, 3, 6, -6, 3, -9, 10, + -6, -3, 7, -7, -3, 12, -5, -5, -11, 24, -7, -23, 24, 0, -14, 0, + 12, -10, -2, 5, 0, 1, -10, 10, -2, -17, 26, -11, -16, 28, -22, 6, + 4, -17, 30, -27, -7, 46, -54, 15, 29, -42, 25, -4, -15, 26, -29, 11, + 15, -28, 19, -7, 1, 8, -20, 14, 1, -15, 11, -2, -2, 0, -10, 15, + -5, -12, 15, -1, -15, 12, 4, -15, 9, -1, -9, 9, -5, -6, 13, -12, + 1, 6, -6, -3, 6, -4, 0, -6, 11, -9, -2, 13, -12, -2, -1, 8, + -11, 4, 2, -6, 4, -4, 4, 0, -13, 15, 0, -21, 23, -5, -15, 15, + -2, -9, 6, -2, -4, 2, 3, -1, -7, 7, -2, -9, 6, 2, -9, 4, + 5, -12, 10, -9, 4, 5, -16, 12, -2, -13, 20, -13, -4, 17, -23, 14, + 2, -20, 22, -13, -3, 15, -22, 12, 4, -18, 17, -7, -7, 13, -14, 6, + 4, -10, 9, -5, -6, 7, 0, -7, 8, -4, -1, 0, -6, 4, 7, -14, + 2, 13, -16, 3, 10, -15, 7, -1, -10, 14, -10, -2, 11, -9, -4, 7, + -6, 3, -3, -5, 9, -6, -3, 5, 1, -7, 3, -2, 0, -2, 0, 4, + -3, -2, 4, -6, 4, -2, -2, 0, 1, 0, -7, 7, -2, -7, 9, -7, + -4, 11, -15, 11, -2, -9, 9, -4, -3, 2, 3, -7, 5, 0, -5, 6, + -7, 1, 7, -10, -2, 13, -9, -4, 8, -4, -2, -1, 1, 1, -7, 4, + 5, -8, 0, 6, -6, 0, 3, -4, 0, 1, -2, 2, -4, -4, 8, -7, + -1, 6, -9, 8, -3, -6, 12, -12, 1, 10, -11, 1, 5, -6, 3, -2, + -3, 7, -10, 2, 7, -12, 5, 2, -5, 3, -5, 0, 6, -10, 3, 4, + -8, 2, 2, -3, 3, -8, 8, 2, -14, 10, 3, -12, 8, 2, -11, 8, + -2, -6, 9, -7, -4, 10, -9, -1, 7, -7, 1, 3, -8, 8, -2, -8, + 10, -3, -5, 5, -6, 3, 1, -8, 10, -5, -5, 7, -4, -2, 2, -3, + 1, -1, -3, 4, -3, 0, 0, 0, 0, -4, 3, -2, -3, 3, -5, 3, + 0, -7, 5, 1, -8, 5, 1, -6, 6, -5, 0, 3, -7, 3, 2, -6, + 3, 2, -6, 3, 1, -3, -2, 5, -4, -1, 3, -4, 0, 0, -3, 5, + -5, -3, 7, -5, -3, 6, -4, 0, -1, -3, 3, -2, -1, 2, -1, -2, + 1, -2, 1, -1, -7, 8, -1, 5, -7, 13, -22, 8, -7, 8, -110, -28, + 24, 54, 36, 2, 60, -45, 57, 42, -43, 20, 41, -66, 24, -11, 18, -18, + -38, -63, -36, 30, -11, 33, 25, 30, 18, 11, -18, -5, 5, -46, 40, 1, + -13, -18, -20, -31, 20, 10, 29, -7, -18, 40, -29, -17, 42, -19, 6, -4, + 6, -8, 10, -26, -5, 3, 1, -17, 6, 0, 19, -1, 8, 0, -6, -10, + -1, -12, -1, 1, -3, 8, -7, 4, 11, 4, 14, -13, 16, -19, -4, -13, + -13, -14, 6, 4, -1, 4, 11, -1, 11, -1, 1, -4, -1, -15, 6, -9, + 1, -1, 0, 3, 1, -8, 3, -1, -1, 2, -2, 2, -2, 1, -5, -7, + 3, -3, 6, -3, 4, -1, 0, -4, 2, -7, 3, -6, -1, -1, 4, 0, + 3, -2, 2, -5, 5, -8, -3, -3, 2, -5, 7, -1, 4, -2, 4, -10, + 6, -6, -1, -4, 5, -13, 7, -6, 5, -8, 17, -20, 14, -6, 9, -40, + 71, -127, 9, -73, 127, 76, -28, 74, -32, 8, -62, -49, -38, 40, -68, 22, + -12, 68, 10, 39, -10, 0, 35, -23, 0, -59, -15, -7, -3, -23, 1, -20, + 37, 27, 2, 30, -2, 17, 2, -5, -7, -27, -29, 16, -3, -11, 1, -16, + -5, -8, -10, 7, 32, 9, 5, -4, 16, 5, -8, -17, -16, 5, -13, 8, + 11, 15, -10, -9, 0, -1, 2, 7, -3, -23, 9, 2, 3, 1, -13, -1, + -6, 11, -6, 8, 1, 12, -12, 9, -14, 8, -1, 0, -3, -13, 4, -7, + -4, 8, 5, -5, -7, 4, -2, -3, 2, 3, -6, 8, -3, 1, -3, -2, + 2, -6, 2, -4, -3, -4, 3, 1, 0, 0, 1, -1, -1, 2, -2, 0, + -4, -2, 1, 2, 0, -3, 1, -3, 0, -1, -3, -6, 2, -2, 3, -4, + 10, -8, 9, -5, 12, -19, 46, 37, -128, 60, -90, 102, -65, 40, -57, 39, + -6, 23, -8, 19, 24, 15, -17, -47, -27, -36, -16, 21, 3, 23, 14, 50, + -8, 19, 25, 7, -9, -28, -63, -37, 0, -42, 54, -17, 68, -3, 30, -12, + -4, 11, -15, 9, -25, -15, -2, -27, -25, 38, -8, -13, 33, 24, 12, -38, + 39, -12, -3, -17, -44, 38, 2, 27, 3, -5, -4, -13, -30, -56, -4, 11, + 1, 9, 17, 46, 25, -14, 6, -3, -7, -21, 2, 16, -5, -22, 2, -2, + 6, -12, -25, -15, 10, 9, 8, 11, 43, 8, -5, -22, -16, 14, -31, 16, + 7, -7, -26, -20, -2, 9, 11, 26, 7, 6, -20, -13, 0, 4, 17, -17, + -18, 10, 2, -10, 27, -8, 24, -23, -14, 1, 0, 13, -19, 14, 10, -16, + 16, -4, -20, 20, -33, 2, 2, 24, 21, -3, -26, -24, -18, -18, 10, 10, + 24, 18, 2, 9, -24, 16, -14, -8, 9, -5, -14, 8, -5, 30, -11, 11, + -13, -15, -12, 7, 4, -13, -13, 13, -13, 12, 23, 9, 0, 14, -10, -9, + -35, -2, -21, 12, -1, 17, 19, 11, -4, 0, -18, -24, 11, -10, 1, 11, + 12, -13, -16, 10, -23, 21, 9, -9, 3, 12, -6, 3, -5, 12, 0, -2, + 0, -19, -9, 5, -11, -7, 10, 1, -3, 9, 18, -6, 0, -1, 1, -13, + 2, 1, -3, -8, 17, -4, -9, 18, -15, 8, -1, -11, -5, -14, 11, -5, + -7, 12, 16, -7, 7, -3, -11, -5, -6, 1, 4, -3, -3, 15, 5, 0, + 3, 6, -16, 4, -14, -6, -9, -4, 2, 11, 11, 7, -2, 4, -12, -7, + -14, -6, -7, 9, 4, 7, -2, 6, 5, 6, -4, -3, -4, 7, -7, -11, + -9, 0, -3, 7, -2, -2, 3, 13, -4, -6, -15, 9, -7, -1, 4, 6, + 5, 8, -6, -8, 0, -11, -4, 6, -8, 4, 3, 5, 13, -4, -9, -3, + 4, -3, -3, 4, -1, -12, 6, -14, 2, 3, 15, 2, 6, -7, -8, 3, + 1, -2, 3, -3, -12, -6, -14, 7, -2, 13, 6, 10, 6, 0, -2, -10, + -12, -8, -6, -7, -6, 6, 4, -2, 5, 2, 0, -1, 3, -11, 4, 0, + 20, -8, -2, 0, -1, -3, 7, -3, -4, -2, -6, -10, -10, -8, 1, 2, + 5, 8, 2, 5, 8, 3, 4, 3, -2, -15, 0, -1, -7, -2, -5, -10, + 10, -1, 5, 3, 5, -1, -2, -8, -5, -9, 1, -8, 6, 5, 4, 1, + 1, 2, 3, -2, 4, -7, 1, -7, -9, -2, 0, 2, 3, 6, -8, 8, + 3, 0, -2, -9, -3, -2, 0, 3, -1, -2, -3, 7, -3, 10, -8, 1, + -12, 3, -7, 2, -3, 7, 4, 4, 0, 0, -6, -1, -5, -3, -4, -7, + 0, 5, 7, 0, 2, -3, 10, -1, 3, -7, -5, -4, -9, -3, -7, 5, + -4, 9, 2, 1, 4, 5, 0, -5, 1, -8, 4, -9, 5, -5, 0, 3, + -2, -1, 1, 1, -7, 7, 0, 3, -5, 0, -3, -1, -1, -5, -1, 1, + -1, 1, -1, 0, 2, 0, 2, -7, -7, 4, -1, 0, 3, 4, -1, -3, + -4, -6, 3, -2, 4, -1, 5, -2, -1, -5, -2, -4, 1, 3, 2, 2, + 0, -3, 1, 1, -3, -3, -1, 1, -3, -2, -1, -2, -3, -1, 0, 4, + 3, 5, 2, 1, -4, -9, -3, -7, 1, -2, 7, -2, 3, 3, 3, 1, + 0, -1, -6, -7, -6, -4, -1, 1, 0, 5, 2, -2, 2, -3, -1, 3, + -1, 1, -4, -4, -5, 0, -7, 2, -4, 3, 4, 1, 2, -1, -1, -2, + -2, 0, -1, 1, -1, -1, -3, 1, 1, 3, -3, -1, 1, 1, -2, -3, + -8, -5, 0, -1, 5, 2, 3, 1, -2, -1, -1, -3, 1, 1, -2, -3, + -3, -1, 0, -1, 1, 2, 2, 5, 0, -1, -2, -1, -2, 0, -4, 0, + -5, -1, -1, 0, 1, 5, 4, -2, -1, -2, 0, -6, -1, 0, 1, -1, + -2, 1, 0, 0, 3, 1, -2, 1, -2, -4, -1, 0, -1, -1, -4, -2, + -4, 2, -1, 1, 0, 3, 2, 0, 4, -1, 4, -6, 2, -4, -3, -5, + -4, -3, 0, 2, 0, 1, 4, 2, 2, -2, -2, -5, -6, -5, -3, -2, + 1, -1, 0, 0, 2, 2, 2, 0, 4, -2, 3, 2, -1, -2, -3, -3, + -3, -5, -5, -5, -1, -1, 0, 2, 2, 4, 1, 2, 1, 2, -1, -1, + -3, -4, -5, -3, -2, -2, -1, 1, 4, 2, 2, 2, 1, -1, -2, -6, + -2, -3, 2, -1, 1, -2, 0, 2, 1, 2, -2, 1, 0, -2, -2, -3, + 0, -2, -1, -1, 0, -2, -2, 1, 0, 2, -1, 1, -1, 0, -1, -1, + 0, -1, 0, -2, 2, 0, 2, 2, 5, 3, 6, 8, 12, 13, -6, -110, + -7, 51, -99, -128, 10, -28, -39, 25, -33, -27, 41, 34, -5, 17, 23, 25, + 24, 23, 20, 24, 25, 24, 21, 20, 23, 23, 16, 20, 9, 20, 18, 10, + 14, 5, 14, 11, 7, 5, 3, 10, 2, 7, -4, 0, 3, 0, -3, -5, + -6, -1, -12, -4, -17, -10, 9, -42, -40, 65, 40, -58, 29, 72, 39, 50, + 31, -1, 30, 25, -7, -4, -33, -47, -29, -49, -74, -69, -71, -79, -61, -51, + -57, -53, -34, -20, -22, -16, -10, -6, -2, 1, 3, 4, 8, 8, 12, 10, + 9, 14, 13, 12, 12, 13, 12, 12, 14, 12, 12, 12, 12, 13, 12, 9, + 11, 11, 11, 7, 8, 7, 8, 9, 2, 5, 8, -6, 2, 17, -17, -20, + 18, 5, -15, 15, 27, 21, 37, 44, 41, 46, 38, 26, 32, 26, -4, -15, + -6, -20, -44, -50, -54, -60, -59, -58, -58, -54, -46, -38, -32, -26, -19, -14, + -9, -5, -1, 2, 5, 7, 8, 10, 11, 12, 13, 13, 14, 14, 14, 13, + 13, 14, 15, 14, 11, 13, 14, 13, 12, 10, 12, 12, 10, 10, 8, 6, + 11, 9, -1, 5, 11, -1, -6, 1, -1, -4, 0, -1, 0, 14, 25, 24, + 28, 37, 38, 38, 38, 31, 22, 14, 4, -5, -15, -26, -38, -47, -52, -54, + -56, -57, -55, -51, -45, -39, -34, -28, -22, -17, -13, -8, -3, -1, 2, 5, + 7, 8, 10, 11, 12, 13, 13, 13, 13, 14, 14, 13, 13, 14, 13, 12, + 13, 13, 12, 11, 12, 11, 9, 11, 9, 6, 7, 8, 5, 3, 2, 0, + 0, 0, -2, -3, 0, 3, 6, 11, 18, 23, 27, 31, 34, 35, 32, 27, + 21, 14, 5, -5, -15, -26, -35, -43, -48, -52, -53, -53, -52, -49, -44, -40, + -35, -29, -24, -19, -14, -10, -6, -3, 1, 3, 5, 7, 9, 10, 11, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 12, 11, 13, 11, 10, + 10, 9, 9, 8, 7, 7, 5, 4, 3, 2, 0, -1, -1, 0, 2, 4, + 8, 12, 17, 22, 25, 28, 30, 30, 28, 24, 19, 12, 3, -5, -14, -23, + -31, -37, -43, -46, -46, -48, -47, -43, -41, -38, -33, -29, -25, -21, -16, -12, + -8, -5, -2, 0, 3, 5, 7, 9, 10, 11, 12, 12, 13, 14, 13, 13, + 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, 7, 7, 6, + 5, 4, 4, 3, 3, 3, 3, 5, 6, 8, 10, 12, 14, 17, 18, 19, + 20, 19, 17, 14, 10, 5, 0, -6, -11, -17, -22, -26, -29, -32, -34, -34, + -35, -34, -32, -31, -28, -26, -23, -20, -17, -14, -11, -8, -5, -3, 0, 2, + 4, 6, 7, 8, 9, 10, 11, 11, 12, 12, 12, 12, 11, 11, 11, 10, + 10, 9, 9, 8, 8, 7, 7, 6, 5, 5, 5, 4, 4, 5, 5, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 12, 10, 8, 5, 2, + -2, -6, -10, -14, -18, -21, -24, -26, -28, -29, -29, -30, -29, -28, -27, -25, + -23, -20, -18, -15, -12, -10, -7, -4, -2, 0, 2, 4, 6, 7, 9, 10, + 10, 11, 11, 12, 12, 12, 12, 11, 11, 11, 10, 10, 9, 9, 8, 8, + 7, 7, 6, 6, 5, 5, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, + 12, 13, 13, 13, 12, 11, 10, 8, 5, 2, -1, -5, -9, -13, -16, -19, + -22, -24, -26, -27, -28, -28, -28, -27, -26, -24, -22, -20, -18, -15, -13, -10, + -7, -5, -2, 0, 2, 4, 5, 7, 8, 9, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, + 5, 5, 6, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 12, 11, 10, + 9, 7, 5, 2, -1, -5, -8, -12, -15, -18, -21, -23, -25, -26, -27, -27, + -27, -26, -25, -24, -22, -20, -18, -16, -13, -11, -8, -6, -3, -1, 1, 3, + 4, 6, 7, 8, 9, 10, 10, 10, 11, 11, 11, 10, 10, 10, 10, 9, + 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, 5, 5, 6, 6, 6, 7, + 8, 9, 9, 10, 11, 11, 11, 11, 11, 10, 9, 7, 4, 2, -1, -4, + -7, -11, -14, -17, -19, -21, -23, -24, -25, -26, -26, -25, -24, -23, -22, -20, + -18, -16, -13, -11, -9, -6, -4, -2, 0, 2, 4, 5, 7, 8, 9, 9, + 10, 10, 11, 11, 11, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 7, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, + 11, 11, 10, 10, 8, 7, 5, 2, -1, -3, -7, -10, -13, -15, -18, -20, + -22, -23, -24, -25, -25, -24, -24, -23, -21, -20, -18, -16, -14, -11, -9, -7, + -5, -2, 0, 1, 3, 5, 6, 7, 8, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 9, 9, 8, 8, 8, 7, 7, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 9, 9, 8, 7, 6, 4, + 2, 0, -2, -5, -7, -10, -12, -15, -17, -18, -20, -21, -21, -22, -22, -21, + -21, -20, -18, -17, -15, -13, -12, -10, -8, -6, -4, -2, 0, 1, 3, 4, + 5, 6, 7, 8, 8, 8, 9, 9, 9, 9, 9, 8, 8, 8, 8, 7, + 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 7, 6, 5, 4, 3, 1, -1, -3, -5, -7, -9, -10, + -12, -14, -15, -16, -17, -18, -18, -18, -18, -17, -17, -16, -15, -13, -12, -11, + -9, -7, -6, -4, -3, -1, 0, 1, 3, 4, 5, 5, 6, 7, 7, 7, + 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, + 4, 3, 2, 0, -1, -3, -5, -7, -9, -10, -12, -13, -15, -16, -17, -17, + -18, -18, -18, -17, -17, -16, -15, -14, -12, -11, -9, -8, -6, -5, -3, -2, + -1, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 6, 6, 5, 4, 3, 2, 0, -1, -3, + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, + 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 10, + 11, 12, 12, 13, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 26, + 27, 29, 29, 29, 28, 28, 28, 29, 30, 31, 31, 31, 31, 28, 19, -8, + -41, -53, -57, -59, -60, -62, -62, -63, -64, -65, -65, -66, -67, -69, -69, -69, + -72, -74, -73, -74, -76, -78, -79, -81, -82, -82, -83, -81, -83, -85, -81, -81, + -88, -90, -80, -64, -47, -32, -23, -18, -15, -13, -12, -12, -12, -13, -13, -13, + -13, -13, -12, -12, -11, -9, -7, -6, -4, -2, -1, 0, 1, 2, 4, 5, + 7, 10, 12, 14, 16, 18, 19, 18, 19, 21, 19, 20, 22, 22, 22, 25, + 27, 28, 29, 29, 29, 29, 29, 30, 31, 31, 31, 33, 34, 34, 35, 34, + 33, 31, 30, 29, 26, 25, 26, 25, 22, 22, 21, 20, 20, 19, 19, 19, + 18, 18, 18, 17, 17, 17, 17, 16, 16, 16, 15, 13, 13, 14, 14, 15, + 13, 12, 13, 13, 11, 12, 14, 14, 16, 17, 15, 16, 19, 19, 19, 19, + 21, 19, 17, 18, 19, 18, 15, 15, 17, 18, 18, 13, 11, 14, 15, 14, + 11, 6, 5, 10, 13, 17, 18, 11, 2, -2, -2, -3, 2, 14, 24, 30, + 37, 47, 52, 52, 56, 63, 65, 65, 63, 65, 72, 75, 73, 71, 73, 77, + 82, 82, 77, 77, 82, 90, 99, 104, 99, 89, 84, 86, 94, 106, 119, 127, + 126, 117, 104, 87, 64, 42, 24, 10, -2, -15, -22, -25, -27, -30, -35, -37, + -36, -34, -33, -36, -40, -42, -44, -43, -44, -48, -53, -57, -59, -57, -53, -52, + -53, -57, -62, -68, -73, -75, -75, -71, -63, -56, -48, -40, -34, -29, -26, -23, + -22, -21, -19, -19, -20, -21, -22, -22, -22, -22, -22, -21, -21, -21, -20, -19, + -19, -18, -18, -17, -17, -16, -14, -14, -13, -11, -9, -9, -9, -9, -9, -8, + -8, -8, -8, -8, -7, -6, -7, -6, -4, -3, -2, -2, -3, -4, -3, -3, + -2, -1, 0, 0, -1, -1, 0, -1, -1, -1, -3, -5, -5, -8, -10, -10, + -9, -9, -10, -11, -11, -11, -11, -11, -10, -9, -10, -10, -10, -11, -12, -12, + -13, -12, -11, -12, -14, -14, -11, -10, -12, -11, -11, -12, -12, -11, -11, -13, + -12, -9, -6, -6, -7, -7, -6, -5, -4, -4, -5, -8, -12, -11, -8, -4, + -3, -5, -6, -7, -9, -12, -13, -8, -3, -2, -4, -8, -11, -14, -15, -17, + -19, -19, -15, -8, -1, 2, 4, 8, 12, 17, 23, 26, 25, 24, 25, 30, + 36, 40, 39, 36, 33, 32, 33, 37, 43, 49, 53, 53, 49, 45, 43, 43, + 46, 52, 60, 67, 76, 82, 82, 78, 69, 58, 47, 37, 26, 14, 2, -9, + -16, -21, -24, -28, -32, -35, -37, -38, -37, -36, -36, -36, -39, -43, -46, -49, + -51, -49, -47, -46, -45, -45, -48, -52, -58, -62, -65, -66, -65, -62, -58, -54, + -50, -45, -39, -34, -30, -28, -25, -23, -21, -20, -20, -20, -20, -19, -18, -19, + -20, -18, -17, -18, -17, -17, -18, -17, -16, -15, -15, -13, -12, -10, -10, -10, + -9, -8, -7, -6, -4, -4, -5, -6, -5, -4, -4, -3, -2, -2, -1, -1, + -1, 0, 2, 3, 2, 2, 3, 2, 1, 2, 4, 5, 5, 4, 4, 4, + 3, 2, 2, 1, 0, 0, -1, -4, -5, -4, -2, -2, -3, -3, -3, -2, + -1, -2, -3, -2, -3, -4, -4, -3, -4, -6, -7, -4, 0, 0, -2, -4, + -4, -3, -2, -2, -3, -4, -4, -3, -2, -1, 3, 6, 8, 6, 3, 0, + 0, 2, 4, 5, 4, 3, 2, 2, 2, 1, 0, -1, 2, 7, 11, 9, + 6, 2, -1, -3, -3, -5, -7, -8, -6, -3, 2, 8, 13, 17, 18, 18, + 19, 23, 28, 34, 40, 42, 42, 40, 39, 39, 40, 42, 46, 50, 55, 59, + 59, 55, 51, 48, 48, 51, 57, 63, 70, 76, 82, 86, 88, 89, 86, 80, + 71, 61, 51, 43, 34, 25, 18, 10, 2, -5, -9, -12, -13, -12, -12, -13, + -14, -17, -22, -26, -29, -28, -27, -25, -24, -24, -25, -27, -31, -35, -40, -43, + -46, -47, -49, -49, -46, -43, -40, -36, -32, -28, -24, -21, -18, -16, -14, -13, + -13, -12, -11, -11, -12, -11, -10, -9, -11, -11, -11, -12, -12, -12, -10, -10, + -10, -10, -9, -8, -7, -6, -5, -4, -4, -4, -4, -4, -3, -2, -2, -1, + -2, -3, -2, -1, 0, 0, 1, 2, 3, 2, 1, 1, 2, 3, 3, 4, + 5, 4, 4, 5, 6, 7, 6, 4, 3, 3, 3, 2, -1, -3, -3, -1, + -1, -2, -3, -3, -2, -1, 1, 0, -1, -1, -2, -5, -6, -5, -4, -4, + -4, -4, -6, -6, -4, -1, 0, -2, -6, -9, -10, -8, -5, -4, -3, -3, + -1, 1, 1, -1, -3, -4, -2, 0, 2, 2, 0, -3, -6, -7, -6, -4, + -3, -2, -1, -1, -1, 0, 1, 0, -3, -9, -14, -18, -18, -15, -12, -9, + -8, -7, -5, -3, -2, 0, 5, 11, 17, 22, 25, 24, 23, 21, 20, 22, + 27, 32, 37, 40, 41, 40, 39, 37, 35, 34, 34, 35, 39, 45, 52, 59, + 66, 71, 73, 75, 74, 71, 65, 60, 55, 48, 39, 28, 17, 7, -1, -7, + -11, -13, -13, -14, -17, -21, -24, -28, -31, -32, -32, -32, -32, -31, -29, -29, + -30, -33, -36, -40, -44, -47, -50, -52, -54, -55, -54, -52, -49, -47, -43, -39, + -35, -31, -28, -26, -24, -22, -21, -19, -18, -17, -17, -16, -15, -16, -18, -17, + -16, -16, -17, -18, -18, -17, -16, -16, -14, -13, -13, -12, -12, -12, -11, -10, + -10, -9, -7, -8, -9, -10, -10, -8, -6, -5, -6, -6, -5, -3, -3, -4, + -4, -4, -3, -2, -2, -1, -1, -1, 0, 2, 3, 3, 3, 2, 1, 0, + -1, -1, -1, -2, -3, -5, -5, -4, -2, -3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 3, 2, 0, + -1, 1, 2, 1, -1, -1, 2, 2, 0, 1, 2, 2, -1, -4, -10, -21, + -30, -36, -41, -44, -40, -30, -18, -10, -8, -11, -13, -8, 3, 18, 32, 41, + 44, 45, 48, 49, 43, 32, 23, 14, 7, 8, 16, 27, 35, 37, 30, 18, + 9, 5, 3, 2, 1, 1, -1, -6, -11, -12, -6, -2, -5, -11, -18, -28, + -39, -47, -55, -69, -86, -99, -102, -92, -70, -46, -28, -15, -3, 7, 17, 26, + 28, 24, 23, 30, 42, 53, 57, 50, 36, 21, 5, -5, -4, 6, 20, 31, + 35, 34, 29, 26, 27, 37, 56, 76, 85, 80, 71, 63, 55, 47, 34, 13, + -13, -32, -39, -40, -46, -65, -93, -117, -128, -128, -126, -120, -110, -96, -78, -58, + -36, -14, 3, 10, 20, 41, 60, 68, 63, 54, 45, 39, 36, 32, 28, 29, + 35, 41, 47, 46, 41, 39, 43, 53, 68, 80, 78, 64, 46, 28, 13, 3, + -9, -35, -64, -80, -82, -74, -66, -71, -91, -111, -121, -118, -105, -86, -68, -57, + -49, -37, -22, -7, 5, 14, 26, 42, 55, 56, 46, 35, 25, 14, 6, 2, + 1, 3, 11, 22, 32, 40, 43, 42, 46, 60, 77, 88, 90, 78, 54, 30, + 14, 2, -15, -37, -62, -82, -90, -89, -86, -90, -99, -107, -109, -101, -81, -54, + -29, -14, -5, 7, 24, 40, 49, 56, 68, 83, 92, 92, 87, 74, 54, 32, + 12, -5, -19, -25, -24, -18, -7, 1, -1, -6, -4, 13, 41, 69, 84, 80, + 63, 44, 32, 29, 25, 11, -10, -25, -31, -35, -40, -48, -65, -87, -104, -109, + -102, -87, -69, -58, -54, -42, -21, 0, 13, 29, 51, 71, 84, 89, 86, 75, + 54, 33, 14, -3, -19, -29, -27, -22, -18, -11, -8, -16, -26, -19, 2, 24, + 40, 48, 42, 27, 21, 29, 34, 24, 7, -5, -14, -23, -28, -32, -45, -67, + -82, -85, -78, -63, -46, -34, -29, -24, -13, 0, 12, 25, 44, 65, 79, 85, + 86, 78, 60, 41, 27, 12, -5, -15, -15, -14, -13, -8, -7, -17, -27, -23, + -3, 23, 44, 51, 43, 25, 12, 11, 14, 8, -3, -10, -15, -22, -28, -30, + -36, -55, -73, -78, -74, -71, -63, -51, -43, -39, -34, -25, -18, -9, 8, 28, + 46, 56, 61, 62, 58, 47, 36, 28, 20, 12, 11, 16, 19, 20, 21, 15, + 0, -6, 10, 37, 57, 63, 55, 36, 15, 2, -3, -9, -19, -27, -34, -43, + -49, -49, -52, -66, -82, -86, -81, -77, -71, -61, -51, -47, -43, -35, -22, -12, + 2, 24, 47, 58, 63, 67, 66, 58, 51, 45, 34, 18, 9, 7, 7, 7, + 8, 1, -14, -24, -12, 18, 47, 64, 68, 63, 53, 42, 37, 38, 36, 29, + 21, 16, 11, 5, -2, -17, -36, -49, -52, -56, -62, -63, -61, -61, -63, -60, + -56, -49, -37, -19, 2, 17, 25, 30, 34, 37, 37, 37, 34, 25, 15, 11, + 13, 14, 14, 8, -7, -21, -16, 9, 37, 53, 60, 61, 53, 40, 33, 34, + 32, 22, 14, 12, 10, 6, -2, -15, -32, -48, -57, -60, -63, -67, -66, -63, + -63, -65, -64, -58, -49, -34, -13, 6, 16, 21, 28, 34, 38, 41, 43, 36, + 25, 19, 21, 26, 27, 20, 4, -11, -11, 7, 31, 53, 66, 70, 66, 57, + 49, 47, 44, 33, 21, 17, 16, 10, 1, -9, -26, -46, -60, -67, -76, -84, + -84, -80, -78, -79, -78, -73, -65, -52, -32, -11, 4, 10, 17, 25, 32, 36, + 40, 37, 24, 13, 15, 23, 23, 11, -5, -19, -25, -16, 9, 38, 59, 70, + 72, 67, 63, 63, 60, 50, 39, 32, 28, 22, 14, 3, -14, -34, -53, -65, + -76, -87, -94, -93, -91, -94, -96, -93, -86, -76, -56, -30, -9, 4, 16, 29, + 40, 51, 63, 65, 52, 39, 39, 45, 42, 29, 11, -7, -22, -24, -8, 19, + 42, 54, 60, 63, 61, 58, 57, 53, 43, 36, 36, 34, 28, 21, 11, -5, + -24, -39, -52, -65, -75, -77, -75, -75, -78, -80, -78, -73, -61, -43, -23, -9, + 1, 10, 23, 39, 52, 56, 47, 36, 35, 41, 42, 33, 17, -2, -24, -35, + -26, -3, 18, 32, 42, 50, 52, 53, 52, 47, 38, 31, 30, 31, 29, 26, + 22, 14, -1, -18, -33, -46, -58, -65, -65, -65, -71, -79, -81, -79, -75, -62, + -42, -27, -21, -14, 1, 19, 34, 40, 36, 29, 27, 31, 38, 39, 29, 9, + -12, -27, -28, -14, 8, 25, 37, 50, 62, 67, 66, 62, 53, 42, 36, 37, + 36, 32, 30, 25, 12, -7, -24, -39, -54, -65, -67, -67, -72, -78, -81, -82, + -81, -70, -51, -35, -29, -23, -7, 15, 30, 37, 40, 35, 25, 25, 36, 41, + 33, 15, -6, -26, -36, -27, -9, 7, 20, 35, 50, 58, 59, 58, 52, 43, + 37, 37, 37, 36, 34, 31, 24, 8, -11, -29, -44, -57, -67, -70, -73, -79, + -86, -92, -93, -87, -72, -59, -53, -46, -29, -9, 7, 20, 28, 26, 19, 17, + 27, 38, 38, 26, 7, -12, -25, -26, -15, 1, 14, 28, 47, 61, 67, 68, + 68, 63, 54, 51, 53, 51, 49, 49, 47, 34, 14, -5, -22, -39, -56, -65, + -67, -73, -86, -96, -97, -92, -86, -77, -69, -61, -49, -28, -6, 10, 22, 27, + 25, 24, 33, 49, 56, 48, 32, 13, -5, -15, -12, -2, 7, 18, 35, 50, + 59, 63, 65, 61, 53, 48, 46, 44, 43, 46, 49, 43, 27, 10, -6, -25, + -45, -53, -53, -60, -75, -87, -90, -90, -88, -81, -75, -72, -65, -48, -25, -6, + 5, 10, 13, 18, 31, 49, 60, 58, 44, 28, 12, -1, -7, -7, -1, 8, + 23, 41, 54, 61, 65, 66, 63, 56, 48, 43, 41, 42, 44, 43, 37, 25, + 8, -12, -32, -44, -49, -53, -64, -80, -91, -95, -93, -89, -85, -82, -78, -68, + -50, -27, -6, 0, -1, 0, 0, 0, 1, 2, 3, 6, 9, 13, 17, 19, + 13, -4, -15, -10, 4, 19, 26, 15, -9, -16, 6, -2, -18, 38, 64, 21, + -48, 30, 82, -23, -63, -50, -26, -7, 12, 26, 47, 83, 100, 3, -108, -87, + -30, -6, 5, 18, 33, 46, 47, 21, -52, -46, 48, 3, -54, -32, 22, 25, + -7, 12, 9, -18, -33, -24, 2, 44, 88, 92, 10, -28, -1, 1, 20, 42, + 1, -17, 53, 72, 12, -16, -74, -31, 127, 52, 1, -35, -46, 13, 39, -13, + -13, 13, 12, 11, 8, -57, -80, -44, -5, 14, 18, 6, -13, -26, -11, -8, + -24, 3, 30, 14, -28, -12, 41, -2, -37, -35, -23, -12, -1, 6, 17, 34, + 53, 19, -55, -67, -32, -13, -5, 2, 12, 19, 24, 14, -24, -47, 12, 11, + -36, -35, -1, 18, -3, 0, 5, -13, -25, -22, -5, 19, 53, 69, 21, -28, + -10, -5, 6, 28, 8, -25, 23, 57, 17, -17, -49, -63, 84, 70, 3, -23, + -50, -6, 36, -2, -20, 8, 14, 9, 13, -37, -82, -58, -19, 8, 17, 10, + -9, -26, -19, -7, -24, -9, 25, 22, -17, -28, 33, 16, -32, -37, -27, -15, + -4, 4, 13, 27, 48, 35, -35, -72, -43, -17, -7, -1, 9, 16, 23, 17, + -12, -51, -7, 21, -27, -40, -12, 19, 6, -3, 5, -9, -22, -23, -8, 11, + 42, 68, 38, -23, -16, -6, 3, 25, 19, -24, 8, 54, 31, -13, -33, -76, + 46, 95, 13, -13, -48, -20, 32, 13, -22, 2, 15, 10, 15, -17, -77, -67, + -31, 3, 17, 15, -3, -21, -23, -7, -20, -18, 18, 27, -4, -34, 17, 33, + -21, -36, -29, -16, -6, 4, 11, 23, 42, 47, -12, -69, -54, -22, -8, -2, + 7, 15, 22, 20, -2, -46, -27, 23, -13, -41, -22, 15, 16, -2, 4, -5, + -18, -21, -10, 5, 32, 64, 53, -12, -21, -6, 0, 21, 27, -16, -6, 48, + 42, -6, -22, -71, 2, 106, 31, -6, -41, -32, 22, 25, -18, -4, 15, 12, + 14, -1, -64, -74, -42, -5, 16, 19, 4, -16, -25, -10, -14, -23, 9, 29, + 9, -31, -2, 42, -5, -33, -30, -18, -8, 3, 9, 19, 36, 51, 10, -58, + -63, -29, -11, -2, 4, 13, 20, 21, 6, -35, -44, 16, 1, -38, -30, 7, + 23, 3, 2, -2, -16, -20, -12, 2, 23, 56, 62, 3, -24, -7, -2, 17, + 30, -5, -17, 37, 49, 4, -17, -57, -37, 99, 55, 0, -31, -41, 9, 33, + -10, -11, 13, 14, 12, 9, -47, -78, -53, -15, 12, 20, 9, -10, -24, -14, + -11, -25, -2, 27, 18, -21, -20, 39, 13, -29, -31, -20, -9, 1, 8, 17, + 30, 49, 29, -41, -70, -39, -15, -4, 2, 11, 17, 21, 11, -22, -52, 0, + 14, -31, -36, -4, 25, 11, 1, -1, -13, -19, -13, 0, 15, 45, 65, 20, + -24, -10, -4, 12, 30, 8, -22, 24, 52, 17, -14, -39, -61, 71, 81, 8, + -21, -44, -5, 34, 2, -16, 9, 16, 11, 14, -29, -76, -62, -27, 6, 20, + 15, -4, -21, -19, -9, -23, -12, 22, 25, -8, -30, 26, 30, -20, -31, -23, + -11, -1, 8, 14, 25, 44, 42, -19, -69, -50, -20, -6, 1, 9, 15, 20, + 15, -11, -51, -19, 20, -20, -39, -15, 23, 20, 2, 0, -11, -17, -14, -2, + 9, 35, 63, 37, -19, -14, -5, 8, 28, 18, -22, 9, 50, 28, -11, -26, + -68, 32, 100, 22, -13, -43, -18, 30, 15, -17, 4, 16, 12, 15, -12, -69, + -69, -39, -2, 18, 19, 2, -17, -22, -10, -19, -20, 15, 27, 4, -31, 7, + 41, -7, -30, -25, -13, -3, 6, 12, 22, 38, 48, 3, -61, -60, -27, -9, + 0, 7, 13, 19, 17, -2, -44, -37, 18, -7, -39, -24, 15, 28, 7, 0, + -9, -16, -14, -3, 6, 25, 57, 49, -9, -18, -7, 3, 25, 26, -15, -4, + 45, 38, -5, -18, -61, -8, 103, 42, -6, -37, -30, 21, 25, -13, -3, 16, + 13, 14, 2, -56, -73, -49, -12, 15, 21, 8, -11, -23, -13, -15, -24, 4, + 28, 14, -25, -12, 42, 9, -26, -26, -15, -5, 5, 11, 19, 32, 48, 22, + -46, -67, -36, -12, -2, 4, 12, 17, 18, 4, -33, -50, 6, 6, -35, -31, + 4, 31, 14, 0, -8, -15, -14, -4, 4, 17, 48, 57, 4, -21, -8, -1, + 21, 30, -5, -15, 36, 44, 5, -14, -46, -40, 88, 67, 2, -29, -37, 9, + 31, -6, -9, 14, 15, 13, 11, -40, -74, -58, -24, 9, 22, 13, -6, -21, + -17, -13, -25, -6, 25, 21, -13, -25, 33, 26, -19, -27, -18, -6, 3, 10, + 16, 27, 45, 36, -26, -69, -46, -17, -4, 2, 10, 15, 18, 9, -22, -55, + -11, 15, -26, -36, -8, 30, 23, 2, -6, -14, -14, -6, 4, 11, 37, 59, + 19, -20, -10, -4, 16, 31, 7, -20, 23, 47, 15, -13, -32, -58, 58, 88, + 13, -21, -40, -5, 32, 4, -13, 10, 17, 12, 14, -23, -70, -65, -35, 1, + 20, 17, 0, -18, -20, -12, -23, -16, 19, 25, -1, -30, 16, 39, -8, -26, + -20, -8, 1, 9, 14, 23, 39, 44, -5, -63, -57, -24, -7, 1, 8, 13, + 17, 12, -12, -52, -30, 17, -15, -38, -18, 23, 32, 7, -6, -13, -14, -7, + 3, 8, 27, 55, 33, -16, -13, -6, 10, 30, 17, -20, 10, 46, 25, -9, + -21, -60, 19, 100, 31, -13, -39, -17, 27, 15, -13, 4, 17, 13, 15, -8, + -61, -69, -46, -10, 17, 21, 6, -13, -22, -13, -20, -22, 10, 27, 9, -27, + -4, 44, 6, -24, -22, -11, -1, 8, 13, 20, 33, 46, 14, -50, -65, -33, + -11, 0, 5, 12, 15, 14, -4, -43, -46, 10, -2, -36, -27, 13, 36, 15, + -4, -13, -14, -8, 3, 7, 18, 49, 43, -7, -16, -7, 5, 27, 24, -14, + -3, 42, 33, -3, -16, -51, -17, 97, 51, -3, -38, -5, -13, 1, -7, 5, + -22, -32, -35, -32, -43, -35, -55, -42, -66, -48, -80, -57, -17, -128, -59, -76, + 0, -26, 1, -33, 21, 3, 16, 15, 26, 43, 28, 66, 6, 97, 40, 103, + 67, 101, 102, 98, 94, 21, 98, 90, 57, 78, 89, 81, 61, -6, 54, 4, + 62, 19, 27, 34, 12, 16, 14, -17, 19, -5, -2, -13, -38, -24, -3, -33, + -14, -11, -16, 0, -13, 7, -26, -13, -16, 6, -57, -23, -28, -13, -9, -34, + -32, -20, -87, -62, -28, -38, -75, -37, -27, -41, -71, -48, -30, -44, -83, -67, + -52, -48, -45, -46, -45, -63, -47, -40, -32, -45, -24, -32, -43, -21, -17, 0, + 21, 26, 43, 51, 62, 47, 41, 55, 57, 68, 34, 53, 63, 62, 71, 60, + 61, 56, 53, 56, 54, 38, 50, 58, 50, 40, 28, 54, 39, 41, 38, 22, + 32, 20, -3, 19, -1, -7, -6, -16, -16, -14, -27, -29, -46, -66, -61, -51, + -54, -61, -41, -50, -47, -52, -55, -45, -44, -28, -58, -56, -31, -37, -36, -32, + -18, -16, -34, -29, -9, -21, -20, -30, -22, -17, -19, -8, -12, -14, -6, -14, + -6, -11, -2, 4, -6, 9, 8, 17, 23, 13, 31, 13, 24, 30, 28, 29, + 30, 43, 34, 37, 52, 42, 44, 50, 67, 59, 49, 54, 48, 43, 51, 45, + 42, 62, 47, 39, 37, 36, 24, 28, 13, 3, 9, -11, -3, -9, -14, -18, + -34, -27, -29, -39, -42, -38, -46, -37, -46, -43, -41, -35, -38, -31, -38, -34, + -39, -39, -34, -48, -44, -47, -49, -54, -52, -44, -53, -37, -47, -38, -31, -38, + -27, -19, -19, -15, -16, 0, 0, 2, 7, 13, 29, 22, 32, 32, 39, 47, + 41, 40, 55, 48, 41, 44, 57, 43, 36, 47, 43, 42, 37, 32, 32, 27, + 33, 36, 30, 23, 25, 25, 22, 18, 22, 20, 16, 8, 6, 12, 7, 0, + 1, 3, -5, -14, -9, -7, -8, -19, -15, -16, -23, -21, -21, -32, -31, -29, + -26, -27, -29, -33, -26, -29, -30, -39, -28, -41, -43, -35, -34, -32, -29, -28, + -28, -25, -27, -24, -27, -27, -27, -22, -23, -17, -9, -10, -14, -10, -8, -4, + -2, -1, -3, 5, 4, 10, 11, 7, 13, 11, 14, 27, 22, 22, 22, 27, + 36, 34, 36, 37, 45, 44, 47, 48, 51, 49, 52, 51, 52, 48, 50, 47, + 48, 42, 40, 29, 33, 24, 22, 12, 5, 0, -3, -5, -9, -21, -21, -25, + -19, -28, -28, -30, -33, -39, -42, -42, -46, -46, -45, -42, -43, -47, -47, -36, + -32, -30, -34, -31, -22, -29, -29, -30, -26, -28, -30, -21, -26, -27, -21, -19, + -16, -11, -12, -8, -2, 1, -4, 1, 0, 1, 9, 8, 7, 12, 10, 13, + 20, 17, 18, 21, 26, 29, 30, 30, 29, 34, 33, 34, 33, 30, 32, 33, + 28, 33, 29, 35, 32, 31, 30, 31, 30, 25, 27, 24, 21, 21, 20, 16, + 17, 12, 6, 4, -3, 1, -6, -7, -11, -13, -11, -10, -8, -13, -12, -9, + -17, -14, -19, -24, -22, -24, -30, -32, -30, -33, -37, -39, -40, -42, -39, -41, + -39, -40, -41, -35, -35, -35, -37, -36, -33, -30, -25, -25, -19, -16, -16, -10, + -6, -7, -4, -2, 1, 3, 6, 10, 9, 15, 17, 18, 17, 13, 19, 18, + 17, 19, 20, 24, 24, 27, 27, 29, 30, 26, 28, 28, 27, 28, 26, 25, + 24, 25, 20, 19, 17, 18, 15, 12, 13, 10, 6, 8, 6, 3, 4, 3, + 0, -3, 0, -1, -2, -5, -4, -5, -4, -5, -6, -8, -9, -9, -12, -11, + -16, -16, -15, -15, -13, -17, -16, -17, -17, -21, -20, -25, -24, -24, -24, -26, + -30, -30, -27, -30, -26, -26, -27, -27, -25, -24, -19, -20, -17, -13, -12, -8, + -8, -8, -6, -5, -2, -1, 0, 3, 8, 10, 12, 16, 18, 24, 25, 25, + 28, 30, 28, 32, 33, 31, 32, 31, 35, 33, 31, 31, 27, 28, 26, 23, + 23, 20, 22, 18, 16, 13, 11, 9, 5, 4, -2, -2, -3, -8, -9, -11, + -12, -13, -15, -15, -15, -15, -15, -14, -12, -12, -13, -13, -8, -11, -10, -12, + -10, -12, -12, -8, -8, -9, -9, -9, -8, -9, -10, -11, -11, -10, -13, -14, + -13, -16, -16, -17, -17, -18, -19, -18, -17, -16, -16, -15, -15, -13, -12, -10, + -12, -10, -9, -8, -6, -6, -3, 0, 0, 1, 2, 2, 3, 4, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 12, 13, 14, 14, 15, 15, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 14, 13, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -1, -2, -3, -4, -5, + -5, -6, -7, -7, -8, -9, -9, -10, -11, -11, -12, -12, -13, -13, -13, -13, + -14, -14, -14, -15, -15, -15, -15, -15, -15, -16, -16, -16, -15, -15, -15, -14, + -13, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -2, -1, 0, 1, 2, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 16, 16, 15, 15, + 14, 14, 13, 12, 11, 10, 9, 7, 6, 5, 3, 1, 0, -2, -4, -5, + -7, -9, -10, -11, -13, -14, -15, -15, -16, -17, -17, -18, -18, -18, -18, -18, + -18, -18, -18, -18, -18, -18, -18, -17, -17, -16, -16, -15, -14, -14, -13, -12, + -11, -10, -9, -8, -7, -6, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 9, 10, 11, 11, 12, 13, 13, 13, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 12, 12, + 11, 10, 9, 8, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, 0, + 0, -1, 2, 1, 0, 1, 4, 2, 2, 2, 5, 2, 5, 5, 8, 4, + 13, 15, 19, -62, -65, 56, -18, -128, -39, 15, -57, -10, 19, -22, -11, 36, + 30, 5, 19, 25, 17, 21, 21, 16, 21, 18, 17, 17, 15, 14, 13, 12, + 10, 6, 8, 6, 6, -1, 1, -4, 7, -10, -36, 35, 64, -25, -18, 83, + 50, 22, 39, 21, 19, -4, -20, 28, 0, -88, -55, -5, -55, -83, -64, -58, + -77, -61, -22, -39, -57, -15, 2, -14, -9, -1, 1, 1, 2, 9, 5, 6, + 11, 9, 9, 10, 11, 12, 12, 10, 9, 9, 13, 7, 3, 14, 4, -3, + 2, 2, 17, 40, 12, 14, 55, 58, 44, 39, 38, 37, 6, 4, 31, -6, + -50, -25, -15, -49, -52, -41, -60, -68, -32, -25, -47, -36, -9, -5, -7, -3, + 3, 4, 6, 8, 11, 9, 10, 14, 14, 11, 13, 15, 14, 13, 14, 12, + 11, 12, 12, 8, 8, 3, 4, 5, -1, 8, 32, 21, 14, 43, 50, 39, + 47, 39, 20, 23, 16, 5, -9, -23, -26, -34, -48, -37, -48, -71, -56, -34, + -43, -49, -36, -20, -14, -13, -9, -4, -1, 1, 3, 6, 6, 6, 9, 10, + 8, 10, 11, 11, 11, 11, 10, 10, 10, 10, 6, 6, 4, 3, 6, -3, + 2, 25, 23, 16, 34, 38, 43, 51, 31, 19, 38, 22, -10, -7, 0, -25, + -45, -34, -32, -54, -62, -47, -39, -45, -47, -36, -24, -19, -16, -11, -6, -3, + 0, 2, 4, 6, 7, 8, 10, 11, 9, 11, 12, 11, 11, 12, 11, 10, + 10, 8, 7, 6, 3, 5, 4, 0, 13, 28, 23, 19, 36, 50, 42, 30, + 31, 39, 24, -6, -2, 7, -21, -40, -27, -34, -51, -51, -44, -42, -45, -45, + -37, -27, -22, -18, -13, -9, -6, -2, 1, 2, 5, 7, 7, 9, 11, 10, + 10, 12, 12, 11, 12, 11, 10, 10, 9, 7, 7, 4, 5, 7, 1, 7, + 27, 24, 15, 34, 47, 37, 32, 36, 36, 26, 4, -1, 4, -13, -30, -27, + -34, -47, -46, -42, -43, -45, -44, -38, -31, -25, -21, -17, -12, -8, -5, -1, + 1, 3, 5, 6, 8, 9, 10, 10, 10, 11, 11, 11, 11, 11, 10, 9, + 7, 7, 6, 3, 6, 5, 6, 17, 23, 19, 29, 40, 35, 33, 36, 34, + 26, 14, 3, 0, -6, -18, -26, -32, -39, -40, -38, -39, -41, -40, -36, -31, + -27, -23, -19, -15, -12, -8, -4, -2, 0, 3, 4, 5, 7, 8, 9, 9, + 9, 10, 10, 10, 10, 10, 9, 8, 8, 8, 7, 8, 10, 11, 14, 19, + 22, 25, 28, 29, 29, 29, 27, 21, 14, 7, -1, -5, -11, -19, -26, -29, + -31, -32, -33, -34, -33, -32, -29, -26, -24, -21, -18, -15, -12, -9, -6, -4, + -2, 0, 2, 3, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, + 10, 10, 11, 12, 14, 16, 18, 20, 22, 23, 24, 24, 23, 20, 17, 12, + 7, 2, -3, -8, -13, -17, -21, -23, -25, -26, -27, -27, -27, -26, -25, -23, + -21, -19, -17, -14, -12, -9, -7, -5, -3, -1, 1, 2, 4, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, 15, 16, 18, 19, 21, + 22, 22, 22, 21, 19, 17, 13, 9, 4, 0, -5, -10, -14, -18, -21, -23, + -25, -26, -26, -26, -26, -25, -23, -22, -20, -18, -15, -13, -11, -9, -6, -4, + -2, 0, 1, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 11, + 12, 13, 14, 15, 17, 18, 20, 21, 21, 21, 21, 19, 17, 14, 11, 7, + 2, -3, -7, -11, -15, -19, -21, -23, -25, -25, -26, -25, -25, -24, -22, -21, + -19, -17, -15, -12, -10, -8, -6, -4, -2, 0, 1, 3, 4, 5, 6, 6, + 7, 8, 8, 9, 9, 10, 11, 11, 12, 13, 15, 16, 17, 19, 20, 20, + 21, 20, 19, 18, 15, 12, 8, 4, 0, -4, -9, -13, -16, -19, -21, -23, + -24, -25, -25, -25, -24, -23, -21, -20, -18, -16, -14, -12, -9, -7, -5, -3, + -2, 0, 1, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 12, + 13, 14, 15, 17, 18, 19, 20, 20, 20, 19, 18, 16, 13, 10, 6, 2, + -2, -6, -10, -13, -16, -19, -21, -23, -24, -24, -24, -24, -23, -22, -20, -19, + -17, -15, -13, -11, -8, -6, -5, -3, -1, 0, 2, 3, 4, 5, 6, 7, + 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, + 19, 18, 16, 14, 11, 8, 4, 0, -3, -7, -11, -14, -17, -19, -21, -22, + -23, -23, -23, -23, -22, -21, -19, -18, -16, -14, -12, -10, -8, -6, -4, -2, + -1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 12, 13, + 14, 15, 16, 17, 18, 19, 19, 19, 18, 17, 15, 12, 9, 6, 3, -1, + -5, -9, -12, -15, -17, -19, -21, -22, -23, -23, -23, -22, -21, -20, -18, -17, + -15, -13, -11, -9, -7, -6, -4, -2, -1, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 18, 18, 18, 17, + 16, 14, 12, 10, 7, 4, 0, -3, -6, -9, -12, -15, -17, -18, -20, -20, + -21, -21, -21, -20, -19, -18, -17, -15, -14, -12, -10, -9, -7, -5, -4, -2, + -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, + 15, 15, 16, 16, 16, 16, 16, 15, 14, 12, 11, 8, 6, 3, 0, -3, + -6, -9, -12, 1, -1, 2, -1, 4, 2, 8, 5, 10, -5, 0, 5, 17, + -11, 0, 19, -17, 26, 65, 15, 29, 3, 35, 67, 50, 88, 59, 117, 28, + -6, -16, 29, 63, 62, -40, 59, 22, -95, -49, -55, 19, 36, -15, 26, -117, + 60, 8, -101, -115, 23, 60, -32, -106, -84, -88, -127, -99, -117, -110, -56, -42, + -53, -79, -44, 43, 10, -11, 72, 22, 61, 10, -92, -106, -111, -35, -68, -128, + -67, -36, -118, -97, -96, -4, 75, 70, 113, 36, 73, 115, 37, 6, 79, 97, + 89, -8, -38, -8, -72, -8, -29, -35, 73, 98, 66, 12, 40, 113, 106, 87, + 126, 112, 127, 87, -3, -21, -23, 40, 14, -68, -20, 21, -57, -67, -67, -4, + 69, 53, 90, 17, 36, 78, -7, -54, -2, 32, 21, -71, -109, -89, -124, -103, + -114, -113, -37, -4, -30, -88, -83, 15, 13, -35, 42, 28, 33, 14, -90, -92, + -104, -37, -34, -115, -73, -9, -75, -89, -85, -29, 67, 51, 97, 55, 47, 115, + 46, -9, 42, 90, 96, 26, -36, 11, -43, -25, -6, -37, 59, 104, 88, 31, + 22, 96, 116, 69, 110, 119, 119, 109, 11, -15, -26, 18, 37, -45, -32, 34, + -13, -62, -62, -30, 61, 47, 75, 46, 14, 72, 14, -58, -35, 16, 30, -38, + -109, -78, -109, -116, -102, -123, -57, -2, -11, -58, -95, -18, 22, -41, -3, 36, + 20, 31, -69, -94, -100, -72, -21, -91, -92, -9, -33, -82, -81, -57, 48, 52, + 70, 81, 35, 97, 69, -10, 8, 66, 94, 55, -27, 4, -5, -40, -1, -33, + 30, 102, 101, 61, 19, 70, 121, 72, 77, 123, 112, 121, 36, -13, -21, -10, + 38, -18, -43, 27, 25, -40, -59, -45, 40, 54, 52, 68, 15, 56, 35, -48, + -58, -12, 25, -10, -98, -84, -83, -122, -101, -123, -81, -8, -3, -28, -85, -47, + 20, -28, -39, 23, 18, 31, -38, -99, -92, -97, -35, -66, -102, -26, -3, -60, + -77, -69, 18, 59, 47, 87, 46, 73, 86, 3, -13, 34, 80, 70, -8, -12, + 19, -32, -12, -21, 3, 91, 105, 87, 34, 51, 114, 89, 53, 106, 115, 119, + 65, -10, -13, -25, 20, 4, -45, 9, 44, -8, -49, -51, 14, 61, 39, 68, + 34, 39, 51, -30, -67, -41, 7, 5, -76, -96, -65, -111, -110, -115, -103, -20, + -1, -9, -58, -65, 8, -9, -55, -6, 17, 24, -11, -94, -89, -102, -64, -50, + -101, -51, 6, -30, -66, -71, -12, 59, 40, 72, 67, 58, 91, 24, -21, 6, + 56, 74, 14, -22, 23, -8, -24, -14, -13, 71, 106, 101, 62, 42, 101, 105, + 49, 76, 114, 114, 87, 3, -12, -23, -6, 13, -37, -11, 45, 24, -29, -49, + -8, 57, 40, 53, 54, 32, 56, -6, -65, -61, -21, 6, -52, -101, -65, -85, + -115, -109, -116, -42, 0, -1, -27, -65, -12, 7, -51, -37, 7, 17, 6, -76, + -95, -94, -91, -52, -90, -76, -2, -4, -46, -66, -35, 46, 46, 49, 78, 57, + 85, 50, -17, -13, 26, 64, 34, -22, 9, 18, -22, -14, -18, 42, 103, 105, + 88, 50, 83, 114, 63, 49, 96, 110, 99, 26, -14, -15, -23, 6, -24, -29, + 33, 45, 0, -38, -23, 44, 50, 37, 60, 38, 52, 21, -54, -70, -48, -7, + -31, -95, -78, -63, -104, -108, -117, -69, -4, -1, -5, -47, -30, 13, -33, -58, + -14, 8, 11, -50, -99, -87, -101, -70, -77, -92, -22, 10, -22, -52, -46, 23, + 55, 36, 70, 66, 74, 69, -2, -23, 1, 43, 43, -11, -8, 29, -4, -17, + -16, 18, 91, 105, 102, 71, 72, 112, 83, 40, 70, 101, 102, 50, -10, -10, + -24, -10, -13, -36, 14, 52, 27, -18, -28, 26, 58, 33, 51, 49, 46, 40, + -34, -70, -66, -31, -22, -81, -92, -56, -83, -105, -112, -91, -17, 0, 2, -22, + -37, 7, -12, -61, -39, -5, 7, -27, -93, -90, -96, -90, -72, -95, -48, 9, + -1, -33, -46, 0, 55, 37, 50, 72, 68, 77, 20, -25, -15, 17, 40, 3, + -20, 22, 19, -12, -14, 2, 70, 105, 106, 92, 72, 104, 100, 48, 46, 83, + 98, 70, 3, -12, -16, -23, -11, -34, -8, 46, 47, 11, -21, 8, 57, 41, + 36, 53, 45, 48, -6, -64, -72, -57, -28, -61, -98, -65, -60, -94, -105, -103, + -41, 1, 0, -1, -29, -6, 5, -48, -60, -26, -3, -12, -74, -97, -86, -100, + -80, -89, -74, -6, 13, -10, -35, -18, 41, 48, 33, 64, 68, 75, 46, -15, + -25, -7, 24, 16, -20, 4, 33, 5, -11, -5, 43, 98, 105, 105, 85, 93, + 110, 67, 35, 59, 87, 81, 25, -13, -9, -23, -18, -27, -25, 30, 55, 37, + -1, -3, 46, 53, 29, 44, 47, 48, 20, -48, -72, -72, -47, -48, -93, -82, + -51, -73, -96, -102, -66, -6, 0, 5, -10, -16, 10, -26, -66, -49, -20, -10, + -51, -98, -86, -93, -93, -85, -88, -32, 14, 8, -16, -23, 22, 54, 32, 45, + 67, 70, 61, 4, -27, -21, 2, 17, -13, -13, 29, 26, -1, -5, 23, 83, + 104, 106, 100, 90, 110, 87, 40, 38, 68, 80, 45, -6, -9, -14, -24, -23, + -32, 8, 52, 53, 25, 1, 31, 60, 35, 30, 45, 45, 36, -24, -68, -76, + -67, -49, -80, -94, -57, -54, -81, -95, -82, -23, 2, 1, 4, -12, 4, -5, + -57, -65, -40, -20, -36, -87, -94, -83, -97, -87, -90, -57, 2, 18, 2, -12, + 8, 10, -20, 30, 25, 21, 14, 4, 15, -48, -33, 11, -70, 54, -5, -21, + -8, -3, 73, -52, 65, -55, 80, -28, -67, -3, -13, 21, -49, -2, 11, 36, + 59, -60, 34, -28, 21, -25, -45, 54, 5, 0, -19, -12, 20, 54, -51, -23, + 22, 36, -59, -20, 8, 28, -9, -54, 127, -44, 69, -128, 5, 69, -8, -98, + 45, 69, 20, -97, 23, -7, 121, -81, -2, -21, 51, -67, -14, -24, 127, -60, + 45, -116, 127, -29, -93, -23, 107, -5, -21, -62, 37, 41, 29, -74, -63, 103, + 24, -59, -44, 62, 43, -28, -46, 7, 72, 19, -70, -47, 42, 53, -68, -13, + 37, 59, -38, -60, 39, 66, 27, -128, 36, 77, 15, -74, -15, 75, 38, -49, + -11, -39, 16, -8, -30, 35, 41, -1, -2, 17, -68, 99, -97, 60, -49, 32, + -44, -29, 82, -26, 39, -35, 10, 38, -20, -21, -92, 83, -24, 13, 31, -33, + 22, 45, -31, -24, 9, -24, -32, 42, -17, 34, 7, -27, 6, 61, -9, -34, + -5, -8, -17, -6, -34, 17, 43, -9, 35, -34, 16, 27, -24, -17, -17, 5, + -17, 42, -31, 22, 17, -26, -22, 32, 41, -27, -25, -10, -5, 16, -2, 13, + -1, 48, -33, -27, 6, 16, 13, -37, -11, 18, 25, -42, -11, 46, -7, -15, + 9, 15, 4, -3, -36, -24, 31, -8, 14, 12, 27, -19, -17, -14, -7, 42, + -5, -15, 5, 1, -15, 14, 43, -19, 1, -25, -35, 16, 16, 29, -12, 8, + -14, 1, 21, -8, -12, -22, -4, 24, 26, -16, -22, 37, 3, -41, 7, 4, + 3, 30, 4, -27, 11, -6, -26, 33, 23, -23, -14, -20, -7, -4, 36, 0, + 18, 10, -27, 1, 1, 16, -1, -4, -44, -5, 17, 9, 13, -4, -3, 31, + 24, -14, -26, 9, -27, -28, 19, 22, 32, -11, -15, 5, 15, -23, -21, 16, + 14, 18, -11, -26, 13, 10, -12, -12, 11, 14, -6, -13, -3, 6, -6, 3, + 12, 32, 14, -22, -45, -10, 37, 11, -50, -11, 50, 22, -13, -4, -4, 15, + -16, -33, 7, 34, -9, -14, -1, 21, 15, -14, -12, -6, 7, 8, 2, 0, + -5, 6, 15, 4, -9, 13, 3, -51, -18, 27, 10, 5, -11, 6, -1, 5, + 22, 2, -14, -39, -12, 19, 17, 4, 11, 5, -25, 2, 23, 8, 2, -3, + -39, -22, 4, 18, 6, 14, 25, 20, -17, -20, 17, 7, -43, -38, -18, 17, + 24, -6, 30, 44, 6, -36, -20, 7, 24, 1, -69, -25, 47, 15, -4, 35, + 19, -18, -22, -12, 20, 39, -36, -49, 9, 28, -16, 9, 34, 36, -22, -69, + -16, 39, 7, -28, -3, 33, -18, -7, 18, 53, 24, -37, -61, -10, 38, 2, + -24, -11, 12, 17, 0, 28, 50, -5, -59, -57, 22, 14, -15, -5, 22, 9, + -20, 19, 33, 31, -33, -62, -13, -2, 45, -9, -4, -3, 19, 8, -8, 40, + 8, -16, -44, -19, 16, 3, 23, -32, 22, 5, -9, 5, 26, 21, -27, -18, + -45, 3, 15, 0, 7, 7, 7, 13, 18, -10, 3, -5, -30, -30, -3, 9, + 31, 17, -10, 19, 28, -33, -20, 31, 14, -67, -27, 13, 20, 29, 1, -2, + 24, -3, -26, -12, 32, -7, -31, -17, 5, 22, 11, -6, 6, 7, 2, 7, + 5, -12, -22, -17, -24, 22, 47, 1, 2, 10, 5, -29, -5, 13, 1, -30, + -28, -5, 23, 25, 6, 5, 1, 7, 0, 5, 3, -33, -37, -6, 19, 20, + 26, -1, -15, 21, 9, -14, -13, 0, -11, -24, -9, 9, 23, 1, 1, 32, + 11, -25, -18, 5, -5, -6, -9, -10, 2, 18, 4, 12, 6, -2, -8, 2, + 2, -7, 2, -22, -5, 17, 25, 15, -5, -1, -24, -8, -10, -5, 12, 7, + -4, -10, 4, 8, 22, 11, -1, -12, -31, -17, 6, 12, 11, 5, -3, -1, + 22, 0, -4, 3, -18, -17, -3, 16, 9, 2, -5, 0, 4, -9, 18, 17, + -22, -19, -8, -6, 21, 11, -6, -16, 33, 13, -15, -3, -15, 1, -3, -10, + -7, 8, 17, -11, 9, 19, 0, 5, 0, -18, -13, 2, -20, 10, 29, -11, + -13, 5, 11, 16, 4, -25, -21, 13, -5, 1, 3, -1, 6, 13, -7, -1, + 17, -6, -6, -9, -6, -3, -1, 1, 18, 11, -22, 2, 18, -2, -15, 1, + 5, -12, -10, -7, 9, 26, 10, -11, 5, 0, -7, -3, -11, -9, -3, 2, + -10, 19, 28, -3, -3, -4, 9, -14, -5, -7, 8, -3, -27, 5, 37, 11, + -2, 3, -27, -15, 12, -2, 14, 2, -8, -16, 22, 11, -1, 10, -17, -8, + -5, -23, 2, 29, 8, -21, 8, 12, 6, 8, -17, 3, -2, -12, -27, 16, + 25, -5, -7, 2, 19, 1, -15, 7, 2, -5, -34, 2, 18, 17, -10, 2, + 18, -1, -12, -10, 5, 1, -16, -9, 12, 21, 4, -10, 2, 12, 1, -19, + -11, 20, 5, -14, -21, 5, 17, -5, 3, 17, 4, -25, -5, 5, 4, 0, + -5, 2, 2, -1, 1, 13, 0, -11, -8, 3, 2, -1, -3, -3, 11, 8, + -6, 2, 7, 4, -5, -23, -2, 14, -1, -15, -2, 15, 10, 1, -4, 16, + 1, -24, -12, 8, 8, -20, -2, 14, 13, 10, 2, 2, -9, -6, -9, -3, + 5, 7, -3, -9, 0, 2, 8, 3, -1, 2, -4, 0, -1, -1, -1, -2, + -8, -14, -19, -28, -51, -53, -49, -48, -49, -44, -37, -30, -23, -14, -8, -11, + -5, 3, 11, 2, 0, 8, 19, 10, 1, 6, 18, 15, 4, 4, 17, 19, + 13, 9, 20, 27, 26, 26, 33, 42, 45, 53, 59, 68, 69, 83, 89, 92, + 85, 88, 91, 80, 56, 37, 29, 9, -25, -54, -65, -74, -94, -113, -112, -103, + -101, -103, -93, -79, -66, -62, -50, -41, -33, -27, -17, -11, -12, -8, 0, 7, + -1, -2, 5, 15, 8, -1, 3, 15, 13, 2, 2, 12, 17, 12, 8, 15, + 23, 24, 25, 29, 38, 42, 50, 56, 65, 68, 78, 87, 91, 87, 87, 91, + 84, 64, 43, 33, 16, -14, -44, -60, -70, -87, -107, -111, -105, -101, -103, -96, + -84, -70, -64, -55, -45, -36, -30, -22, -14, -14, -11, -4, 4, 0, -3, 1, + 11, 8, -1, 0, 10, 12, 3, 0, 9, 15, 11, 7, 14, 22, 23, 24, + 28, 37, 42, 49, 55, 64, 67, 78, 87, 91, 88, 88, 93, 86, 67, 47, + 36, 20, -10, -40, -56, -67, -84, -104, -109, -105, -101, -103, -96, -85, -71, -65, + -56, -46, -38, -31, -23, -16, -15, -12, -6, 2, -1, -5, 0, 9, 6, -1, + -1, 8, 11, 3, 0, 8, 14, 11, 7, 13, 21, 23, 23, 27, 37, 41, + 48, 54, 63, 67, 77, 86, 91, 89, 89, 93, 87, 70, 51, 39, 23, -6, + -36, -53, -64, -81, -101, -107, -103, -100, -102, -96, -85, -72, -66, -57, -47, -39, + -32, -25, -17, -16, -13, -7, 0, -3, -5, -1, 7, 6, -2, -2, 7, 9, + 2, -1, 7, 13, 10, 7, 12, 20, 22, 23, 27, 36, 41, 48, 54, 63, + 68, 77, 87, 91, 91, 91, 95, 89, 73, 54, 43, 27, -1, -31, -49, -61, + -78, -98, -105, -102, -99, -101, -96, -85, -73, -66, -58, -48, -40, -33, -26, -19, + -17, -14, -9, -2, -4, -6, -3, 5, 4, -3, -3, 5, 8, 1, -1, 6, + 12, 10, 7, 11, 20, 22, 23, 27, 35, 41, 47, 54, 62, 68, 76, 86, + 91, 91, 92, 96, 91, 76, 58, 46, 30, 3, -27, -45, -57, -75, -94, -103, + -100, -98, -100, -96, -85, -74, -67, -59, -49, -41, -34, -28, -20, -19, -15, -10, + -3, -5, -7, -4, 3, 3, -4, -4, 4, 7, 1, -2, 5, 11, 9, 6, + 11, 19, 21, 22, 26, 35, 40, 46, 53, 61, 67, 76, 86, 91, 92, 93, + 97, 93, 78, 61, 49, 33, 7, -22, -41, -54, -72, -91, -100, -99, -97, -100, + -96, -86, -74, -67, -60, -51, -42, -35, -29, -22, -20, -17, -11, -5, -6, -8, + -5, 2, 1, -5, -5, 2, 5, 0, -3, 3, 10, 8, 5, 10, 18, 21, + 21, 25, 34, 39, 45, 52, 61, 67, 75, 85, 91, 92, 94, 97, 94, 81, + 64, 52, 37, 11, -18, -37, -51, -69, -88, -98, -98, -96, -99, -95, -86, -75, + -68, -61, -52, -44, -36, -30, -23, -21, -17, -13, -6, -7, -9, -6, 0, 0, + -5, -5, 1, 4, -1, -3, 2, 8, 8, 5, 10, 17, 20, 21, 25, 33, + 39, 45, 51, 60, 66, 75, 85, 91, 93, 94, 98, 95, 83, 67, 55, 40, + 15, -14, -33, -48, -66, -85, -96, -96, -95, -98, -95, -86, -75, -69, -62, -53, + -45, -38, -32, -25, -22, -19, -14, -8, -9, -10, -8, -2, -1, -6, -7, -1, + 2, -2, -4, 1, 7, 6, 5, 8, 16, 19, 20, 24, 32, 38, 44, 50, + 59, 66, 74, 84, 91, 93, 95, 99, 97, 85, 70, 58, 43, 18, -10, -30, + -45, -63, -82, -93, -95, -94, -97, -95, -87, -76, -70, -63, -54, -46, -39, -33, + -26, -23, -20, -16, -10, -10, -12, -9, -3, -3, -7, -8, -2, 1, -2, -5, + 0, 6, 6, 4, 8, 15, 18, 20, 23, 31, 37, 43, 50, 58, 65, 74, + 83, 91, 93, 96, 100, 98, 87, 72, 61, 46, 22, -6, -27, -42, -60, -79, + -91, -94, -93, -97, -95, -87, -77, -70, -64, -55, -47, -40, -34, -28, -25, -22, + -17, -12, -11, -13, -11, -5, -4, -8, -9, -3, 0, -4, -6, -1, 5, 5, + 3, 7, 14, 18, 19, 23, 30, 36, 42, 49, 57, 65, 73, 83, 90, 94, + 96, 100, 99, 89, 75, 63, 49, 25, -2, -23, -38, -56, -76, -88, -92, -92, + -95, -94, -87, -77, -71, -65, -57, -48, -41, -36, -29, -26, -23, -19, -13, -12, + -14, -12, -7, -6, -9, -10, -5, -1, -4, -7, -2, 2, 5, 4, 6, 12, + 18, 20, 24, 30, 38, 45, 52, 61, 70, 79, 89, 99, 106, 109, 113, 115, + 109, 96, 81, 66, 44, 16, -12, -32, -52, -74, -92, -101, -104, -107, -108, -103, + -94, -85, -78, -70, -60, -52, -45, -38, -33, -29, -25, -19, -16, -17, -16, -12, + -9, -10, -12, -9, -5, -5, -7, -5, 0, 3, 3, 5, 11, 17, 20, 23, + 29, 37, 44, 51, 59, 69, 78, 88, 98, 105, 110, 114, 116, 110, 98, 84, + 69, 48, 20, -7, -29, -49, -71, -89, -99, -102, -105, -107, -103, -94, -86, -79, + -71, -62, -54, -47, -40, -34, -30, -26, -21, -18, -18, -17, -14, -10, -12, -14, + -11, -5, -10, 43, -94, 44, -13, 27, -98, 1, 9, 77, 63, 4, 8, -128, + 63, -73, 78, -116, 127, -14, 111, -87, -67, -43, -45, 38, 53, 99, -37, 14, + -51, -58, -23, -32, 34, 27, 75, 9, 51, -104, -71, -33, 27, 67, 0, -1, + 25, 0, -35, 1, -70, 28, -4, 109, 3, 5, -42, -7, 42, -15, 37, -62, + 67, -14, 48, -85, -46, -94, 37, 35, 23, 15, -79, 35, -50, 91, -64, 40, + -69, 46, 20, 43, -21, -51, 8, -1, 95, -47, 69, -104, 98, -44, 74, -61, + -14, -19, 7, 52, -40, 8, -89, 58, -53, 106, -106, 42, -82, 61, -1, -8, + -10, -59, 53, -18, 85, -83, 63, -73, 89, -32, 50, -62, 10, 13, 20, 62, + -81, 41, -84, 88, -32, 41, -78, 27, -30, 51, -6, -42, 6, -49, 74, -41, + 41, -89, 27, -33, 57, 0, -16, -8, -4, 45, 8, 20, -63, 36, -29, 75, + -23, -17, -23, -14, 45, -7, 17, -56, 20, -12, 45, -16, -13, -31, 6, 31, + -7, 17, -81, 40, -35, 73, -34, 0, -31, 10, 35, -4, 19, -60, 44, -30, + 83, -66, 41, -87, 59, -6, 23, -4, -59, 34, -33, 77, -70, 49, -89, 88, + -45, 63, -62, 4, -20, 18, 46, -49, 45, -101, 91, -56, 78, -79, 35, -51, + 67, -12, -2, -14, -49, 66, -35, 72, -87, 51, -74, 83, -38, 29, -36, -10, + 23, 3, 30, -59, 27, -59, 91, -44, 41, -63, 12, 2, 23, 8, -36, 14, + -35, 66, -38, 32, -59, 25, -11, 40, -6, -25, -2, -24, 55, -25, 29, -58, + 30, -17, 41, -18, -17, -3, -13, 50, -25, 26, -63, 35, -23, 50, -22, -5, + -18, 0, 33, -19, 22, -67, 57, -39, 63, -45, 6, -27, 13, 23, -6, 15, + -55, 44, -42, 70, -59, 36, -60, 56, -13, 15, -9, -50, 49, -38, 72, -63, + 37, -65, 67, -48, 55, -51, 10, 2, -5, 45, -61, 46, -83, 91, -58, 72, + -69, 23, -27, 35, -8, -3, -2, -33, 66, -61, 79, -100, 67, -60, 66, -26, + 13, -21, -13, 23, -11, 29, -49, 40, -53, 80, -67, 52, -63, 28, 6, -1, + 23, -45, 25, -30, 42, -25, 22, -42, 33, -26, 39, -26, -9, 10, -28, 61, + -50, 33, -43, 18, 2, 6, 4, -18, 4, -8, 24, -21, 22, -49, 50, -40, + 52, -35, -10, 17, -34, 64, -53, 38, -47, 37, -28, 40, -47, 33, -32, 28, + 3, -20, 30, -69, 79, -75, 88, -72, 39, -34, 22, -7, 9, -18, 1, 19, + -27, 58, -89, 81, -90, 89, -58, 42, -27, -5, 16, -21, 29, -34, 28, -37, + 59, -65, 72, -90, 69, -45, 31, 6, -36, 40, -53, 56, -47, 39, -42, 40, + -38, 50, -52, 34, -31, 7, 32, -47, 62, -79, 66, -51, 41, -27, 12, -10, + 12, -5, 3, -5, -18, 33, -44, 70, -75, 60, -52, 27, 4, -19, 22, -29, + 27, -15, 18, -31, 26, -36, 50, -41, 35, -31, 3, 19, -37, 55, -62, 51, + -38, 25, -11, 1, -13, 12, -7, 13, 4, -33, 38, -56, 72, -64, 52, -43, + 20, 6, -20, 25, -40, 34, -25, 38, -41, 43, -68, 68, -59, 53, -28, -7, + 27, -45, 63, -70, 56, -60, 59, -41, 48, -56, 39, -43, 35, -3, -19, 40, + -70, 85, -81, 76, -75, 48, -36, 41, -20, 12, -23, 0, 16, -23, 51, -76, + 78, -82, 80, -57, 29, -23, 3, 14, -2, 9, -29, 17, -31, 55, -51, 53, + -66, 49, -27, 17, 3, -35, 36, -33, 44, -27, 11, -30, 24, -18, 37, -29, + 4, -3, -15, 45, -47, 42, -57, 46, -19, 18, -11, -20, 10, -3, 24, -18, + 14, -46, 52, -50, 64, -57, 25, -14, 1, 33, -42, 30, -52, 50, -28, 47, + -54, 32, -49, 53, -25, 14, -4, -34, 57, -54, 69, -78, 46, -45, 52, -21, + 21, -37, 7, 1, 3, 29, -57, 56, -74, 90, -66, 47, -51, 16, 6, 10, + 10, -29, 9, -32, 58, -47, 59, -84, 65, -49, 52, -24, -18, 14, -30, 61, + -39, 31, -57, 39, -38, 67, -56, 37, -46, 26, 10, -15, 18, -49, 45, -27, + 42, -37, 11, -24, 30, -15, 21, -34, 15, -5, 11, 5, -24, 11, -16, 30, + -16, 6, -20, 7, 3, 11, -9, -5, -6, 4, 16, -15, 9, -29, 22, -6, + 14, -6, -16, 9, -12, 28, -22, 15, -27, 22, -11, 21, -23, 5, -10, 8, + 17, -22, 19, -42, 41, -31, 39, -37, 20, -20, 19, -3, -7, 2, -17, 27, + -20, 30, -43, 30, -34, 38, -24, 13, -13, -1, 16, -16, 19, -36, 28, -21, + 30, -22, 7, -17, 11, 2, 1, 1, -19, 22, -21, 32, -34, 18, -21, 17, + 6, -8, 5, -25, 21, -13, 24, -24, 12, -22, 24, -11, 10, -14, -7, 15, + -11, 28, -36, 21, -30, 30, -10, 10, -13, -5, 6, -2, 14, -22, 15, -25, + 33, -22, 23, -31, 11, -6, 8, 11, -21, 14, -28, 32, -23, 25, -31, 19, + -15, 19, -7, -7, 1, -13, 26, -19, 24, -37, 25, -24, 30, -18, 6, -9, + -2, 17, -16, 17, -34, 27, -19, 28, -21, 6, -15, 10, 4, 0, 2, -20, + 22, -19, -21, 0, -3, -3, 2, 1, -1, 2, -2, -1, 4, 3, -3, -15, + -21, -20, -23, -42, -45, -31, -27, -17, -8, 9, 29, 41, 44, 33, 20, 13, + 6, 12, 16, 25, 43, 44, 33, 33, 35, 15, -5, -3, 8, 16, 8, -10, + -6, 8, 4, -4, 1, -18, -38, -43, -51, -54, -55, -71, -85, -68, -58, -61, + -50, -33, -27, -15, -5, 22, 67, 100, 109, 114, 110, 91, 69, 50, 37, 35, + 46, 48, 37, 36, 14, -24, -38, -42, -38, -38, -59, -91, -86, -57, -44, -32, + -15, -26, -44, -30, -30, -30, -16, -31, -50, -34, -43, -59, -49, -44, -52, -62, + -69, -50, -4, 47, 83, 105, 120, 111, 88, 72, 55, 57, 76, 69, 59, 55, + 41, 10, -18, -32, -28, -19, -36, -68, -76, -72, -71, -46, -35, -47, -43, -43, + -61, -48, -28, -25, -22, -19, -23, -15, -7, 3, 4, -8, -28, -37, -5, 42, + 72, 107, 127, 122, 117, 90, 48, 37, 48, 51, 54, 56, 43, 24, -8, -37, + -33, -11, -28, -55, -61, -75, -75, -51, -58, -55, -33, -33, -41, -35, -30, -21, + -16, -17, -24, -26, -20, -18, -17, -12, -36, -72, -65, -45, -6, 53, 88, 106, + 119, 107, 71, 52, 50, 59, 75, 87, 85, 76, 43, -1, -7, 9, -1, -13, + -34, -69, -80, -74, -80, -73, -65, -67, -65, -56, -44, -33, -23, -18, -24, -25, + -16, -20, -9, -1, -21, -38, -55, -64, -40, 3, 39, 82, 113, 114, 95, 71, + 54, 56, 68, 76, 87, 94, 57, 10, -9, -17, -17, -15, -35, -60, -75, -89, + -92, -85, -76, -71, -74, -70, -53, -41, -20, -9, -9, 4, 4, 10, 33, 38, + 25, 15, -17, -43, -33, -15, 3, 40, 77, 94, 91, 69, 37, 31, 33, 37, + 68, 96, 82, 53, 25, 8, 22, 28, 9, -9, -27, -46, -56, -65, -62, -61, + -60, -51, -51, -39, -25, -23, -11, -3, -15, -10, 5, 12, 20, 18, -11, -41, + -52, -47, -34, -2, 33, 65, 82, 70, 51, 45, 28, 21, 49, 74, 86, 74, + 33, 5, 10, 14, 7, -10, -28, -45, -67, -68, -73, -76, -66, -66, -65, -46, + -39, -31, -9, -3, -6, 1, 8, 22, 41, 49, 33, 8, -16, -34, -30, -17, + 7, 49, 73, 64, 63, 50, 19, 5, 13, 32, 62, 65, 37, 8, -5, 4, + -1, -8, -15, -36, -50, -57, -71, -65, -53, -58, -49, -37, -40, -28, -10, -3, + 0, 2, -2, 5, 30, 41, 36, 22, -7, -33, -39, -46, -30, 15, 44, 56, + 72, 65, 44, 21, 2, 15, 42, 59, 49, 18, 2, -3, -4, 0, -10, -25, + -34, -52, -65, -59, -56, -50, -37, -33, -33, -25, -12, -2, 10, 12, 3, 6, + 27, 42, 52, 43, 16, -3, -24, -48, -41, -11, 16, 48, 67, 78, 75, 49, + 21, 13, 36, 64, 63, 47, 25, -1, -2, 2, -12, -18, -28, -53, -65, -71, + -76, -70, -55, -53, -49, -41, -35, -24, -1, 5, 1, 4, 8, 28, 51, 43, + 26, 18, -14, -42, -51, -49, -23, 5, 31, 55, 67, 58, 26, -2, 11, 35, + 49, 55, 35, 8, 3, -2, -5, -6, -13, -30, -38, -49, -61, -56, -45, -43, + -36, -31, -37, -25, -7, 1, 6, 1, -10, 11, 33, 29, 27, 17, -6, -34, + -58, -67, -57, -34, -4, 21, 50, 63, 37, 11, 8, 17, 45, 63, 55, 39, + 26, 12, 11, 10, -1, -11, -19, -35, -51, -52, -52, -45, -35, -36, -41, -31, + -24, -9, 9, -3, -12, 2, 19, 33, 40, 37, 25, -3, -30, -51, -59, -42, + -24, -3, 38, 58, 51, 32, 8, 2, 25, 45, 50, 49, 35, 18, 16, 19, + 10, 9, 4, -13, -27, -36, -45, -36, -24, -32, -29, -31, -33, -10, 6, 1, + -4, -6, 4, 19, 30, 37, 30, 12, -13, -48, -59, -57, -56, -35, 2, 31, + 48, 41, 12, -2, 7, 25, 41, 52, 44, 29, 25, 22, 18, 20, 15, 1, + -6, -26, -38, -28, -26, -21, -17, -31, -33, -19, -4, 0, -8, -16, -15, -11, + 9, 19, 22, 24, -2, -34, -49, -61, -70, -57, -32, 4, 38, 46, 26, 5, + -1, 7, 29, 45, 44, 38, 32, 23, 27, 30, 23, 24, 14, -8, -16, -24, + -24, -12, -10, -19, -27, -26, -9, -2, -4, -6, -16, -14, -2, 8, 23, 34, + 17, -6, -26, -47, -61, -62, -50, -18, 26, 50, 48, 31, 12, 6, 24, 40, + 44, 51, 40, 29, 34, 28, 27, 32, 20, 7, -5, -23, -26, -19, -9, -12, + -25, -25, -17, -8, 1, -4, -13, -12, -16, -9, 13, 26, 23, 8, -13, -37, + -55, -71, -78, -59, -18, 16, 35, 34, 8, -3, 4, 13, 31, 40, 34, 34, + 29, 23, 30, 31, 27, 21, 7, -6, -21, -21, -10, -10, -19, -24, -28, -17, + -6, -8, -9, -9, -19, -21, -5, 12, 23, 22, 5, -16, -34, -55, -80, -78, + -56, -22, 18, 33, 24, 14, 3, 7, 25, 31, 37, 41, 33, 29, 29, 32, + 33, 30, 24, 7, -16, -22, -18, -15, -14, -24, -31, -22, -13, -12, -8, -6, + -18, -27, -22, -6, -5, -1, -1, -1, 1, 2, 7, 13, 19, 10, -12, -31, + -13, 17, 29, -4, -29, 24, 53, 18, 92, 15, -15, 23, 13, -35, -52, 127, + 9, 3, -9, 31, -63, -64, -5, -50, 14, 33, -29, -42, 0, 43, 39, -15, + -59, -45, 3, 33, 12, -35, -10, 51, 18, 49, 55, -28, 16, 4, 3, -64, + 54, 53, -12, 0, 5, -4, -72, -7, -31, -14, 26, -2, -37, -14, 17, 35, + 4, -33, -45, -12, 15, 21, -16, -23, 22, 28, 12, 55, -7, -2, 7, 7, + -34, -10, 65, -4, 1, -5, 14, -46, -28, -9, -29, 13, 13, -23, -23, 4, + 27, 18, -17, -39, -25, 5, 20, 0, -26, 1, 34, 7, 41, 24, -20, 11, + 1, -6, -45, 53, 22, -6, -4, 9, -17, -52, -4, -30, -6, 20, -9, -29, + -8, 18, 27, -2, -33, -36, -6, 16, 13, -20, -16, 27, 19, 18, 49, -17, + 3, 2, 6, -42, 9, 55, -9, 1, -3, 9, -54, -19, -16, -24, 16, 7, + -27, -19, 8, 28, 12, -22, -40, -20, 8, 19, -7, -25, 9, 31, 7, 48, + 9, -14, 9, 2, -17, -35, 62, 9, -2, -6, 13, -30, -44, -4, -31, 2, + 18, -15, -27, -3, 22, 24, -8, -36, -32, -2, 17, 8, -23, -9, 31, 13, + 28, 40, -21, 8, 1, 3, -47, 29, 43, -9, 0, 1, 1, -57, -11, -22, + -17, 19, 2, -28, -14, 12, 29, 7, -27, -39, -14, 11, 17, -13, -22, 17, + 27, 10, 51, -4, -7, 7, 5, -27, -19, 64, -1, 1, -6, 14, -41, -34, + -8, -30, 8, 15, -20, -24, 2, 25, 20, -14, -38, -27, 2, 18, 2, -25, + -1, 33, 9, 37, 29, -21, 11, 0, -3, -46, 46, 29, -7, -2, 7, -9, + -54, -6, -27, -10, 20, -4, -28, -9, 16, 28, 1, -30, -37, -8, 14, 14, + -18, -17, 25, 22, 16, 50, -13, 1, 4, 5, -37, 0, 59, -7, 2, -4, + 12, -49, -24, -13, -26, 13, 11, -23, -19, 6, 27, 15, -19, -39, -21, 6, + 18, -4, -24, 7, 32, 8, 45, 15, -16, 10, 2, -12, -39, 58, 16, -3, + -5, 11, -22, -48, -4, -30, -2, 19, -10, -26, -4, 20, 25, -5, -34, -33, + -4, 16, 10, -21, -11, 30, 16, 25, 43, -19, 7, 1, 4, -44, 20, 49, + -8, 1, -1, 6, -54, -15, -19, -20, 17, 6, -26, -15, 10, 29, 9, -23, + -39, -16, 9, 17, -10, -22, 15, 29, 10, 50, 2, -10, 8, 3, -22, -26, + 63, 5, 0, -6, 14, -34, -39, -6, -30, 4, 17, -15, -24, 0, 24, 22, + -11, -36, -28, 1, 17, 5, -23, -3, 32, 12, 34, 33, -21, 10, 0, 0, + -46, 39, 36, -7, -1, 4, -3, -54, -9, -24, -14, 19, 0, -26, -10, 14, + 28, 4, -27, -37, -11, 12, 15, -15, -18, 22, 24, 14, 50, -9, -2, 5, + 5, -32, -8, 61, -3, 2, -5, 14, -44, -29, -10, -27, 10, 13, -20, -20, + 4, 26, 17, -16, -37, -23, 4, 18, -1, -23, 5, 32, 9, 42, 20, -18, + 11, 1, -7, -41, 53, 22, -4, -3, 9, -14, -50, -6, -27, -7, 19, -6, + -26, -5, 18, 26, -2, -31, -34, -6, 14, 11, -19, -12, 28, 19, 22, 45, + -17, 4, 2, 5, -40, 11, 54, -6, 2, -3, 10, -51, -20, -16, -23, 14, + 9, -23, -15, 8, 28, 12, -20, -38, -18, 7, 17, -7, -22, 13, 30, 10, + 47, 7, -12, 9, 2, -17, -31, 61, 10, 0, -5, 13, -26, -43, -6, -29, + 0, 18, -11, -23, -1, 22, 23, -8, -34, -30, -1, 15, 7, -22, -5, 31, + 14, 30, 37, -20, 9, 0, 2, -44, 30, 42, -7, 1, 2, 2, -53, -12, + -21, -17, 17, 4, -25, -11, 12, 28, 6, -25, -37, -13, 10, 15, -13, -18, + 20, 26, 13, 49, -5, -5, 6, 4, -27, -16, 62, 1, 2, -5, 14, -38, + -34, -9, -28, 6, 15, -16, -20, 3, 25, 19, -13, -36, -25, 2, 16, 1, + -23, 3, 32, 11, 38, 25, -19, 11, 0, -4, -43, 46, 29, -4, -2, 7, + -8, -51, -8, -25, -10, 18, -2, -25, -7, 16, 27, 0, -28, -35, -8, 12, + 12, -17, -13, 26, 21, 19, 46, -14, 2, 3, 4, -36, 2, 57, -4, 3, + -4, 12, -46, -25, -13, -25, 11, 12, -20, -16, 7, 27, 14, -18, -37, -20, + 5, 16, -5, -21, 10, 31, 10, 45, 12, -14, 10, 1, -12, -36, 57, 16, + -1, -4, 11, -20, -46, -6, -28, -4, 18, -8, -23, -3, 20, 24, -5, -32, + -31, -4, 13, 8, -20, -6, 29, 17, 27, 39, -19, 7, 0, 3, -42, 21, + 47, -6, 2, 0, 7, -51, -17, -18, -20, 15, 7, -23, -12, 10, 28, 8, + -22, -37, -15, 8, 15, -10, -19, 18, 27, 13, 47, 0, -8, 8, 3, -24, + -20, 52, -36, -2, 0, -2, 3, 5, -4, -28, 22, -43, 36, -13, -127, -43, + 2, -18, 126, 78, -127, -48, 68, -74, -67, 33, 62, 83, 42, -32, -46, -70, + -26, 115, 21, -66, 72, 52, -27, 44, 50, 50, 61, 28, -12, 3, -59, 49, + 3, -19, 39, 94, 16, 31, 6, 29, 3, -100, -1, -4, -60, 19, 7, -29, + -28, -38, -3, -47, -20, -21, -1, 5, -55, -12, -55, -39, 26, 47, -22, -9, + -41, -21, -19, -37, 0, 45, -56, 24, 75, -50, -9, 31, 28, 26, 13, -3, + -15, -27, 1, 1, -31, -10, 38, -1, 7, 43, 19, 21, 41, 33, 9, -17, + -3, -42, -76, -30, -8, -9, -1, 21, 22, 38, 32, 22, 0, -18, -32, -58, + -12, 5, -48, -13, 64, 29, -2, 2, 19, 43, 25, -19, -39, -69, -92, -15, + 23, 30, 30, 51, 37, 35, 37, 30, -27, -63, 5, -30, -56, -16, 26, 52, + 20, 14, 59, 27, -9, 22, -4, -20, -37, -17, -34, -34, -1, 35, 26, 31, + 5, -16, 4, 33, 22, 8, 5, -28, -41, -20, -10, -6, -2, -16, 12, 31, + -23, 7, -2, -39, -28, -13, 8, 5, 16, -4, -6, -18, -24, -27, -50, -6, + 5, 12, 0, -2, -14, -23, 5, -28, -10, 2, 28, 15, 2, 22, 27, 41, + 31, 2, 12, 31, 5, 12, -6, 15, 40, 34, 18, 26, 26, 12, 34, 23, + 34, 30, 22, 10, -26, -22, 1, 0, -1, 12, -4, -21, -5, -5, -20, -31, + -25, -24, -42, -44, -41, -41, -37, -29, -28, -29, -40, -17, -21, -38, -42, -38, + -40, -36, -13, -14, -8, -15, -7, -6, 5, 12, -1, -17, -1, 9, 2, 16, + 30, 27, 37, 36, 38, 36, 36, 19, 45, 45, 33, 26, 33, 28, 36, 31, + 17, 12, 22, 11, 11, 17, 5, -13, 6, 10, 2, -6, 2, 9, 15, -6, + -8, -23, -44, -3, -11, -35, -25, -35, -23, -21, 0, -11, -21, -17, 11, -6, + -11, -17, -33, -16, -16, -4, -7, -7, -9, -4, 1, 1, -3, 6, 7, 4, + -17, -11, -6, -4, 1, 3, 6, 4, 5, -4, 17, 7, 3, 9, -20, 0, + -7, -3, -5, 4, 9, 16, 2, 3, 8, 15, 15, 1, -3, 8, -1, 5, + 14, 7, 4, 8, -8, 2, -3, 5, 11, 5, 3, -4, 10, 17, 13, -11, + -5, 1, -3, 0, -6, -12, 2, -3, 13, -5, -25, -15, -7, 4, 1, -8, + -4, -12, -16, 3, 9, -6, 3, -21, -4, 4, -14, 1, -1, -2, 3, -8, + -5, 0, 7, -2, -3, -1, 3, -9, 5, -4, -17, -1, 9, 3, 7, 1, + -4, -3, 5, 2, -7, -9, 12, -6, -14, -16, 2, -1, 16, 2, 2, 7, + -6, -26, 3, -2, -4, -2, 10, 3, -7, 3, 8, 9, 5, 4, 1, -5, + -5, 11, 8, 7, 11, 12, -1, -5, -16, 13, 7, 2, 11, 4, -4, 9, + -8, -8, 14, 11, -8, 0, -1, -5, -2, -1, -10, -5, -9, -9, -16, -12, + -8, -16, 5, -10, -4, -11, -3, 1, 0, -3, -5, -13, -9, -2, -8, 5, + -9, -7, -2, 2, -11, -7, 13, 8, -3, 2, 7, -2, -1, 5, 0, 11, + 6, 13, 15, 1, -4, 9, 5, 3, 8, -3, -4, 16, 4, 11, 9, 0, + 8, 1, -6, -5, -18, 3, 7, -18, -4, 0, -3, -3, -6, -4, -5, -5, + -10, -2, -9, -5, -2, -4, -11, -2, 1, -5, -2, 11, -6, -9, 1, 4, + -6, -1, -5, 1, 2, 9, 5, 0, 4, 4, -2, 7, 0, -10, 5, 2, + -3, 0, -6, 7, -4, -3, 6, -1, -6, -1, -1, 2, -2, -6, -3, 0, + 8, -6, 4, -1, -5, -3, 3, 1, -5, -6, -2, -3, 5, 6, 0, 7, + -3, 3, -1, 0, -2, 9, 1, 1, -3, 4, 5, -5, 2, -2, 2, -11, + -2, -4, 11, 4, 5, 0, -5, -12, -6, -5, -5, 3, -2, -2, 2, 2, + 1, 0, -1, -8, -5, -5, -3, 2, -1, 3, -1, 3, 0, -1, 0, -1, + 1, 1, -4, -4, 2, -2, 1, -6, 1, 2, 4, 2, 2, -5, -1, 6, + -3, -1, -4, 11, 3, -9, -2, -6, -3, 2, 4, 2, 1, 2, 4, 3, + -6, -4, -3, -2, 0, 2, -2, 5, 2, -1, 3, -9, -3, -3, -4, -4, + -1, 0, -2, 7, 3, 1, 1, -2, -4, -2, -3, -2, -4, 2, 4, -1, + 2, 3, 0, 3, -1, 0, -2, -2, -3, 1, -1, -4, 5, -1, 5, 0, + -3, -2, -1, -4, 3, -1, -3, -2, -2, -1, 0, 0, 1, -1, 0, -2, + -2, 0, -3, -1, 0, 0, 1, 1, -2, -1, 1, -3, 1, 2, 0, -1, + 0, -1, 1, 5, -2, 1, -3, -3, -1, -3, 0, 1, 3, 2, -1, -1, + -2, -2, -1, 1, 0, -1, -2, -2, -2, -3, -3, -3, -2, -2, -2, -2, + -2, -2, -2, -1, 0, 1, 1, -2, -2, 0, 0, 2, -3, -16, -22, -20, + -28, -35, -31, -17, 19, 33, 36, 33, 34, 40, 36, 25, 18, 20, 18, 14, + 17, 12, 14, 10, -24, -36, -27, -38, -55, -69, -66, -47, -33, -13, 3, 5, + 10, 22, 25, 15, 28, 43, 41, 51, 56, 58, 58, 31, -18, -52, -64, -71, + -92, -105, -98, -77, -50, -17, 23, 59, 85, 99, 94, 76, 55, 14, -9, -5, + -7, -18, -17, -35, -53, -53, -33, -23, -33, -36, -15, 17, 32, 24, 12, 19, + 37, 54, 49, 38, 21, -14, -44, -30, -22, -15, 5, 8, -1, -26, -42, -46, + -49, -51, -37, -17, 1, -4, -19, -4, 45, 84, 91, 79, 57, 3, -30, -29, + -35, -25, -8, -6, -26, -61, -75, -73, -77, -72, -54, -19, 9, 6, -10, 3, + 47, 85, 92, 103, 92, 45, 21, 6, 4, 16, 27, 27, -1, -48, -69, -78, + -80, -84, -72, -33, -10, -24, -41, -20, 40, 82, 99, 123, 102, 69, 49, 30, + 27, 34, 42, 41, -2, -58, -96, -108, -103, -106, -83, -37, -10, -18, -38, -18, + 40, 65, 92, 110, 84, 44, 1, -26, -23, -7, 21, 32, 7, -39, -78, -84, + -79, -82, -61, -19, 5, -14, -52, -25, 25, 59, 102, 127, 116, 86, 40, 13, + 4, 9, 27, 29, 4, -47, -88, -94, -87, -83, -56, -18, 15, -13, -49, -30, + -2, 29, 69, 87, 80, 50, 9, -15, -27, -10, 18, 44, 36, -9, -45, -53, + -53, -46, -33, 6, 31, -8, -36, -28, -11, 21, 54, 76, 76, 44, 4, -33, + -53, -45, -18, 13, 10, -35, -62, -70, -61, -44, -19, 38, 63, 30, 9, 4, + 9, 35, 60, 81, 75, 51, 14, -25, -44, -37, -9, 29, 24, -11, -41, -59, + -51, -54, -33, 23, 35, 6, -13, -28, -18, 8, 43, 73, 76, 63, 33, -1, + -21, -22, 10, 43, 35, 5, -32, -47, -51, -68, -44, 6, 14, 0, -21, -34, + -25, 0, 37, 65, 73, 64, 35, 5, -22, -25, 11, 40, 39, 13, -20, -28, + -42, -64, -32, 6, 15, -1, -25, -39, -39, -16, 19, 44, 58, 53, 27, -2, + -39, -38, -2, 30, 40, 13, -16, -19, -45, -60, -29, 6, 17, 1, -21, -40, + -44, -24, 9, 38, 58, 51, 38, 8, -31, -29, 0, 34, 44, 9, -11, -23, + -58, -69, -42, -6, 9, 0, -16, -33, -36, -12, 19, 55, 72, 68, 58, 18, + -22, -25, -6, 29, 31, 2, -5, -23, -57, -69, -45, -8, 12, 10, 0, -22, + -24, -7, 20, 52, 61, 65, 59, 21, -15, -28, -11, 26, 20, 2, -2, -22, + -56, -71, -49, -14, 3, 8, -5, -26, -28, -19, 14, 42, 54, 71, 67, 38, + 8, -11, 16, 47, 37, 26, 18, -10, -51, -74, -59, -35, -19, -12, -24, -37, + -44, -34, 0, 24, 44, 67, 64, 43, 3, -18, 11, 35, 28, 22, 18, -4, + -47, -68, -55, -34, -11, -7, -15, -27, -43, -32, -1, 18, 42, 58, 60, 43, + -8, -29, -6, 11, 7, 4, 4, -17, -59, -75, -66, -41, -13, -3, 1, -11, + -29, -19, 1, 19, 42, 53, 64, 45, -8, -28, -9, 7, 4, 4, 9, -13, + -51, -71, -69, -43, -19, -7, 3, -11, -25, -17, -2, 23, 43, 60, 78, 55, + 1, -19, -5, 8, 3, 7, 13, -8, -41, -66, -67, -40, -19, 3, 16, 1, + -7, -5, 10, 34, 46, 67, 87, 62, 11, -13, -1, 8, 4, 15, 20, 1, + -33, -64, -65, -48, -30, -2, 6, -5, -14, -18, 1, 21, 32, 62, 86, 66, + 20, -3, 6, 7, 5, 16, 20, 7, -29, -62, -65, -59, -39, -13, -5, -8, + -22, -27, -6, 7, 17, 49, 74, 58, 14, -5, -2, -4, -3, 7, 14, 6, + -32, -59, -66, -63, -40, -16, -2, -2, -19, -20, -1, 6, 18, 49, 77, 62, + 21, 3, -1, -5, -2, 5, 18, 10, -26, -50, -65, -64, -43, -24, -5, -6, + -24, -23, -8, -2, 10, 45, 75, 60, 25, 6, -4, -4, -5, 3, 20, 8, + -20, -43, -60, -58, -45, -24, 1, -1, -15, -12, -1, 3, 16, 53, 83, 70, + 42, 19, 9, 7, 3, 16, 29, 17, -7, -35, -55, -56, -49, -24, 2, -1, + -11, -7, 3, 4, 16, 55, 83, 75, 50, 25, 15, 6, 0, 13, 21, 13, + -9, -40, -58, -66, -62, -35, -11, -11, -18, -13, -3, -7, 9, 49, 75, 74, + 51, 28, 19, 5, 1, 13, 20, 16, -3, -28, -48, -62, -61, -37, -16, -13, + -20, -15, -12, -19, -5, 21, 50, 61, 47, 28, 15, -1, -6, 0, 9, 14, + 1, -19, -37, -55, -56, -38, -16, -11, -13, -9, -9, -16, -8, 18, 48, 59, + 44, 28, 9, 15, -3, 2, -5, 3, 3, 4, 1, 7, -2, 7, -4, 2, + -124, -37, 33, -48, 7, -27, 8, -14, 77, 26, -9, 26, 7, 20, 10, 13, + 8, 9, 7, 4, 5, 2, 3, 2, 1, -1, 0, -3, -2, -5, 1, -10, + 11, 70, -6, 21, 5, 27, -2, 41, -15, -61, -66, -128, 0, -48, -21, -46, + -6, -55, 23, 53, -6, 11, 2, 14, 11, 10, 11, 8, 9, 9, 8, 5, + 8, 5, 6, 5, 6, 2, 7, -4, 6, 5, -23, 62, 29, 24, 8, 33, + 4, 32, 36, -30, -16, -124, -58, -39, -18, -51, -3, -43, -40, 53, 19, 12, + 4, 9, 12, 13, 10, 11, 9, 8, 11, 6, 5, 8, 6, 3, 9, 1, + 7, 2, -5, 22, -33, 20, 37, 35, 7, 29, 14, 8, 52, -5, 17, -64, + -84, -70, -15, -55, -23, -12, -72, 1, 28, 16, 8, 6, 7, 12, 10, 8, + 11, 6, 8, 10, 5, 4, 10, 1, 8, 4, 2, 10, -15, 26, -16, -9, + 14, 42, 17, 19, 29, -3, 42, 14, 28, -8, -45, -92, -37, -41, -54, 0, + -53, -48, 2, 18, 10, 8, 4, 8, 12, 8, 10, 10, 6, 9, 10, 2, + 10, 5, 3, 9, -2, 18, -16, 17, 3, -9, -12, 26, 28, 13, 35, 3, + 27, 19, 31, 17, 4, -60, -67, -33, -66, -22, -22, -58, -38, 2, 11, 9, + 7, 4, 9, 10, 8, 10, 9, 5, 12, 5, 5, 9, 2, 11, -5, 21, + -8, 4, 10, 5, -17, -1, 28, 11, 34, 13, 20, 17, 28, 24, 27, -6, + -61, -41, -57, -51, -17, -36, -56, -32, -1, 7, 8, 5, 6, 8, 10, 8, + 12, 6, 9, 9, 5, 9, 1, 15, -7, 15, 5, -2, 4, 14, -3, -18, + 15, 8, 28, 21, 20, 16, 23, 23, 29, 30, -20, -38, -45, -63, -38, -23, + -43, -53, -29, -5, 5, 5, 5, 5, 9, 7, 11, 8, 8, 10, 5, 12, + -2, 16, -1, 4, 11, 4, -3, 8, 15, -16, 0, 1, 16, 23, 23, 17, + 20, 21, 21, 39, 19, -14, -28, -52, -58, -33, -28, -47, -50, -30, -6, 2, + 5, 4, 6, 6, 9, 10, 7, 12, 3, 15, 0, 10, 8, 1, 6, 11, + 2, -4, 20, -1, -6, -5, 4, 15, 24, 20, 18, 23, 15, 30, 38, 13, + -6, -27, -56, -52, -30, -34, -48, -50, -28, -8, 2, 3, 5, 5, 6, 11, + 5, 13, 3, 12, 6, 5, 10, 5, 2, 7, 13, -8, 10, 11, 0, -6, + -4, 3, 17, 23, 16, 24, 18, 17, 36, 32, 13, -1, -30, -57, -45, -31, + -36, -51, -49, -28, -7, -1, 3, 6, 2, 11, 5, 12, 6, 9, 10, 5, + 8, 8, 5, -1, 16, 1, -1, 11, 9, -1, -5, -5, 4, 20, 17, 20, + 24, 14, 23, 37, 29, 16, 2, -33, -53, -42, -30, -39, -52, -49, -27, -9, + -3, 5, 0, 8, 5, 10, 8, 6, 10, 6, 7, 6, 11, -3, 8, 11, + 0, 2, 11, 8, -1, -5, -7, 9, 18, 16, 24, 20, 14, 27, 35, 27, + 21, 1, -33, -50, -38, -32, -42, -53, -48, -25, -14, -1, -2, 4, 3, 6, + 9, 5, 9, 7, 7, 4, 12, 4, 1, 10, 6, 2, 6, 10, 4, 0, + -6, -2, 11, 14, 18, 22, 17, 20, 32, 34, 28, 20, 0, -26, -36, -34, + -37, -45, -54, -44, -30, -13, -8, -3, 1, 2, 6, 4, 7, 8, 8, 2, + 8, 10, 1, 4, 6, 5, 5, 9, 6, 1, -3, -5, 3, 10, 14, 18, + 18, 17, 26, 35, 35, 29, 17, -1, -17, -24, -32, -41, -50, -51, -44, -28, + -18, -12, -5, -2, 2, 3, 3, 6, 9, 4, 3, 9, 6, 2, 2, 4, + 5, 9, 10, 4, -2, -5, -1, 5, 10, 14, 16, 15, 19, 30, 38, 37, + 29, 15, 1, -5, -14, -31, -43, -50, -52, -42, -29, -22, -16, -9, -3, 0, + 0, 2, 6, 6, 2, 4, 7, 6, 2, 1, 2, 6, 11, 10, 2, -5, + -4, 0, 5, 10, 14, 15, 14, 21, 32, 39, 38, 29, 14, 4, 0, -3, + -19, -32, -40, -43, -41, -36, -31, -25, -19, -12, -9, -8, -6, -1, 2, 2, + 0, -3, -4, -1, 3, 6, 6, 2, -3, -6, -2, 2, 2, 1, 2, 7, + 16, 25, 32, 35, 35, 36, 36, 33, 24, 11, -3, -18, -32, -40, -42, -40, + -36, -30, -25, -18, -12, -9, -8, -5, -1, 2, 2, 0, -3, -4, -1, 3, + 7, 6, 2, -4, -5, -2, 2, 2, 1, 2, 8, 17, 25, 32, 35, 36, + 36, 36, 32, 23, 10, -4, -20, -33, -41, -42, -40, -35, -30, -24, -18, -12, + -9, -8, -5, -1, 3, 2, -1, -4, -4, -1, 4, 7, 6, 1, -4, -5, + -2, -1, 3, 1, 3, 5, 3, -3, -1, -1, 1, -15, 1, 1, -5, -7, + 7, -2, -4, 3, -2, -5, -1, -3, -3, -1, 6, 3, 2, 3, -26, -117, + 35, -8, -19, 24, 58, -7, -6, 25, -9, 7, 4, 10, 2, 7, 6, 6, + 0, 6, -2, -1, -3, -3, 8, 71, 0, 17, 27, 20, -102, -115, 39, -32, + -18, -5, 58, -15, -12, 13, -10, -4, 1, 2, 1, 0, 6, 2, 1, 2, + 0, -4, 0, -5, 2, 67, 9, 14, 28, 29, -72, -126, 27, -25, -19, -14, + 58, -6, -11, 13, -5, -3, 3, 3, 4, 1, 8, 3, 3, 3, 3, -2, + 2, -3, -3, 62, 17, 14, 27, 35, -45, -128, 11, -19, -20, -22, 53, 1, + -12, 11, -3, -4, 2, 3, 4, 1, 7, 3, 3, 3, 3, -2, 2, -2, + -9, 57, 22, 14, 25, 37, -23, -125, -8, -15, -20, -30, 46, 9, -12, 10, + -2, -3, 0, 3, 3, 1, 6, 4, 2, 3, 2, -2, 1, 0, -16, 50, + 26, 13, 22, 37, -2, -117, -27, -13, -18, -36, 36, 16, -13, 9, -2, -2, + -2, 3, 2, 2, 4, 5, 1, 4, 2, -1, 0, 4, -20, 43, 29, 15, + 20, 36, 14, -102, -43, -15, -16, -40, 26, 22, -12, 8, -2, -2, -3, 3, + 1, 3, 2, 6, 1, 5, 1, 0, -1, 7, -23, 35, 31, 18, 18, 33, + 27, -83, -57, -20, -14, -42, 14, 26, -9, 7, -2, 0, -5, 3, 1, 4, + 1, 7, 0, 5, 1, 1, -2, 10, -24, 26, 31, 20, 17, 30, 36, -62, + -65, -27, -12, -43, 2, 28, -7, 6, -2, 0, -5, 3, 0, 4, 0, 7, + 0, 5, 1, 2, -4, 11, -23, 17, 32, 22, 16, 27, 42, -44, -67, -36, + -9, -42, -8, 28, -3, 5, -1, 1, -5, 2, 0, 4, 1, 7, 1, 5, + 1, 3, -5, 13, -22, 10, 31, 23, 17, 22, 45, -25, -66, -45, -8, -40, + -18, 27, 0, 5, -1, 1, -5, 1, 0, 4, 0, 6, 2, 4, 2, 3, + -6, 14, -19, 2, 29, 25, 19, 19, 47, -10, -60, -54, -10, -37, -27, 24, + 4, 4, 0, 1, -5, 0, 0, 3, 1, 5, 2, 4, 2, 4, -7, 15, + -16, -4, 27, 25, 21, 15, 48, 4, -51, -61, -12, -33, -34, 19, 7, 4, + 1, 0, -4, -1, 0, 3, 2, 5, 3, 3, 3, 5, -8, 15, -11, -10, + 24, 25, 23, 12, 45, 15, -39, -66, -18, -28, -40, 12, 10, 4, 2, 1, + -3, -2, 0, 2, 2, 4, 3, 3, 3, 5, -8, 13, -6, -14, 19, 25, + 25, 10, 43, 24, -25, -67, -25, -24, -45, 4, 11, 5, 3, 0, -2, -3, + -1, 1, 2, 3, 3, 3, 2, 6, -9, 11, -2, -17, 15, 24, 27, 9, + 39, 31, -13, -66, -33, -19, -48, -3, 11, 5, 3, 1, -2, -3, -1, 1, + 2, 4, 3, 3, 2, 8, -9, 9, 3, -18, 10, 22, 29, 9, 35, 35, + 0, -61, -41, -17, -49, -11, 10, 6, 3, 2, -2, -3, -2, 1, 1, 4, + 3, 5, 1, 9, -9, 7, 6, -18, 5, 20, 29, 10, 32, 38, 11, -47, + -45, -18, -47, -20, 5, 6, 4, 2, -1, -3, -2, 0, 1, 5, 1, 6, + 1, 7, -7, 6, 6, -16, 1, 16, 27, 11, 29, 40, 20, -30, -43, -23, + -46, -28, -2, 4, 4, 2, -1, -3, -2, -1, 0, 6, -1, 7, 2, 5, + -6, 5, 6, -15, -3, 13, 25, 12, 26, 41, 26, -14, -36, -26, -44, -35, + -11, 1, 4, 2, 0, -4, -3, -3, -1, 7, -2, 7, 4, 4, -6, 4, + 7, -13, -6, 10, 23, 12, 24, 42, 31, 0, -24, -28, -42, -40, -19, -4, + 4, 2, 1, -4, -3, -4, -3, 8, -3, 6, 6, 3, -6, 4, 7, -11, + -8, 7, 20, 12, 21, 41, 34, -2, -31, -34, -29, -21, -12, -3, -4, -10, + -7, -5, -6, -4, 5, 8, -3, -1, 7, -1, -11, -7, 0, 1, 6, 16, + 28, 33, 33, 30, 13, -1, -26, -35, -30, -24, -14, -5, -4, -11, -7, -5, + -6, -6, 3, 8, -2, -2, 7, 1, -11, -9, -1, 0, 4, 14, 26, 32, + 33, 32, 17, 3, -22, -34, -31, -25, -16, -6, -3, -10, -8, -5, -6, -7, + 2, 9, 0, -3, 6, 3, -9, -10, -2, 0, 3, 12, 24, 32, -1, 0, + -3, -1, -8, -5, -16, -5, -14, -4, -13, -5, -1, -7, 16, -17, 28, -16, + 47, 1, 70, 35, 97, 71, 98, 66, 32, -5, -71, -69, -122, -69, -105, -33, + -67, -6, -35, 2, -12, -2, 4, -12, 16, -19, 29, -16, 44, 2, 66, 37, + 92, 76, 95, 74, 33, 5, -69, -63, -122, -69, -106, -36, -66, -11, -33, -3, + -9, -7, 7, -16, 18, -22, 29, -17, 42, 3, 61, 40, 86, 81, 91, 82, + 34, 15, -67, -57, -122, -69, -105, -40, -64, -17, -29, -9, -6, -12, 10, -20, + 20, -23, 28, -17, 39, 4, 56, 42, 80, 85, 88, 89, 35, 24, -63, -53, + -119, -70, -104, -45, -62, -22, -26, -14, -2, -16, 12, -23, 20, -25, 27, -16, + 35, 7, 51, 45, 74, 89, 85, 96, 38, 32, -58, -49, -116, -72, -102, -50, + -60, -27, -24, -19, 0, -20, 14, -24, 20, -24, 24, -14, 31, 10, 45, 48, + 69, 92, 82, 102, 40, 39, -53, -45, -112, -74, -100, -55, -57, -33, -21, -24, + 3, -24, 15, -26, 19, -24, 22, -12, 27, 12, 40, 50, 63, 95, 80, 106, + 43, 45, -47, -42, -107, -76, -97, -60, -55, -38, -18, -28, 4, -26, 15, -27, + 18, -23, 19, -10, 23, 15, 35, 53, 59, 97, 78, 110, 47, 50, -39, -39, + -102, -79, -94, -65, -52, -43, -16, -32, 5, -28, 14, -27, 16, -21, 15, -7, + 18, 18, 30, 55, 54, 98, 76, 113, 51, 55, -32, -37, -96, -81, -91, -70, + -50, -48, -15, -35, 6, -30, 13, -26, 13, -19, 11, -5, 13, 20, 25, 56, + 50, 99, 75, 115, 56, 59, -24, -35, -90, -83, -88, -75, -48, -52, -14, -38, + 5, -30, 11, -25, 10, -17, 7, -2, 9, 22, 21, 57, 47, 99, 75, 116, + 61, 62, -15, -33, -82, -86, -84, -80, -47, -56, -14, -39, 4, -30, 9, -24, + 6, -15, 3, 1, 5, 24, 17, 57, 44, 98, 75, 116, 66, 65, -6, -31, + -75, -88, -81, -83, -46, -59, -14, -41, 3, -30, 6, -22, 3, -12, -1, 3, + 1, 26, 13, 57, 41, 96, 75, 115, 72, 68, 2, -29, -69, -89, -78, -87, + -45, -62, -15, -42, 0, -29, 3, -20, -1, -10, -5, 5, -2, 26, 11, 56, + 40, 94, 76, 114, 77, 69, 12, -28, -61, -91, -75, -89, -45, -64, -16, -42, + -2, -28, 0, -18, -5, -8, -9, 7, -6, 27, 8, 55, 38, 91, 77, 112, + 82, 71, 20, -25, -55, -91, -73, -91, -46, -65, -18, -42, -5, -26, -4, -15, + -10, -5, -13, 9, -9, 27, 7, 53, 37, 88, 78, 110, 87, 72, 29, -23, + -48, -90, -71, -93, -47, -66, -21, -41, -9, -24, -8, -13, -13, -3, -16, 9, + -11, 27, 5, 51, 37, 84, 79, 108, 93, 74, 37, -20, -42, -90, -70, -94, + -49, -66, -24, -40, -12, -23, -12, -12, -16, -2, -18, 10, -12, 25, 5, 48, + 37, 80, 81, 105, 98, 75, 45, -16, -36, -88, -68, -94, -51, -66, -28, -39, + -16, -21, -15, -10, -19, -1, -21, 10, -13, 24, 4, 45, 37, 76, 82, 102, + 102, 76, 52, -13, -30, -85, -67, -94, -54, -66, -31, -38, -20, -19, -19, -9, + -22, 0, -22, 9, -14, 22, 4, 41, 37, 71, 83, 99, 105, 77, 59, -8, + -25, -82, -67, -93, -56, -65, -35, -37, -23, -18, -22, -7, -25, 0, -24, 8, + -14, 20, 5, 37, 38, 67, 84, 96, 108, 79, 65, -3, -20, -79, -66, -92, + -59, -65, -39, -36, -27, -17, -25, -7, -27, -1, -24, 6, -14, 17, 6, 34, + 39, 63, 84, 93, 111, 80, 71, 1, -15, -75, -66, -90, -62, -64, -43, -35, + -31, -16, -28, -6, -28, -1, -25, 5, -14, 14, 6, 30, 39, 58, 85, 90, + 113, 82, 76, 7, -11, -70, -66, -88, -66, -62, -46, -34, -34, -15, -30, -7, + -30, -2, -25, 2, -13, 11, 7, 26, 40, 53, 84, 87, 115, 84, 81, 13, + -7, -65, -66, -85, -68, -61, -50, -33, -37, -15, -32, -7, -30, -4, -25, 0, + -12, 7, 9, 19, 37, 52, 80, 97, 118, 113, 98, 54, 7, -41, -72, -87, + -87, -75, -65, -47, -42, -29, -30, -22, -24, -19, -19, -14, -9, -2, 8, 17, + 36, 50, 77, 95, 117, 115, 101, 60, 13, -35, -69, -85, -88, -75, -66, -49, + -44, -31, -31, -23, -25, -20, -20, -15, -9, -2, -1, 0, 0, 0, 0, -1, + -1, -1, 3, 9, 14, 14, 10, -3, -17, -13, 1, 1, 23, 33, -14, -55, + -59, -80, -75, -35, -7, 51, 40, -29, -35, -53, -128, -31, 111, 72, 46, 55, + -19, -73, -23, 14, 64, 104, 87, 105, 68, -54, -76, -1, -18, 12, 92, 23, + -79, -93, -105, -119, -64, -20, 39, 70, 2, -45, -52, -107, -82, 73, 106, 56, + 53, 12, -57, -37, 14, 52, 105, 101, 94, 85, -5, -75, -25, -1, -8, 59, + 52, -45, -89, -94, -117, -90, -42, 1, 53, 29, -29, -45, -79, -104, 3, 99, + 78, 63, 42, -25, -49, -7, 30, 83, 112, 103, 99, 40, -54, -58, -11, -7, + 36, 68, -4, -80, -98, -114, -106, -57, -15, 33, 42, -10, -46, -66, -97, -45, + 68, 90, 67, 53, 4, -40, -20, 18, 60, 103, 107, 100, 69, -15, -62, -31, + -9, 15, 60, 31, -50, -90, -108, -115, -79, -33, 11, 42, 15, -33, -58, -87, + -75, 21, 87, 79, 63, 27, -26, -33, 1, 40, 88, 111, 105, 85, 20, -50, + -49, -17, 5, 46, 49, -17, -77, -102, -115, -95, -49, -7, 31, 28, -15, -50, + -76, -84, -21, 64, 84, 71, 45, -4, -32, -13, 22, 66, 103, 108, 95, 50, + -23, -56, -32, -5, 30, 55, 14, -53, -92, -111, -107, -68, -24, 16, 34, 4, + -37, -66, -85, -53, 32, 81, 77, 58, 17, -25, -24, 6, 46, 89, 108, 101, + 71, 6, -49, -45, -16, 15, 49, 36, -26, -77, -103, -110, -85, -41, 0, 30, + 20, -21, -55, -79, -72, -5, 65, 81, 67, 36, -10, -28, -8, 27, 71, 102, + 104, 85, 34, -31, -51, -29, 1, 37, 48, 2, -57, -93, -109, -97, -58, -16, + 20, 28, -4, -42, -70, -79, -36, 39, 78, 74, 51, 9, -24, -18, 11, 51, + 91, 105, 94, 57, -6, -48, -41, -12, 22, 48, 26, -33, -79, -103, -104, -74, + -32, 6, 28, 12, -27, -60, -78, -59, 8, 66, 78, 62, 27, -13, -24, -3, + 33, 74, 100, 99, 74, 20, -35, -48, -25, 8, 40, 40, -7, -61, -94, -106, + -88, -49, -9, 21, 21, -11, -47, -72, -71, -22, 45, 76, 71, 43, 2, -22, + -13, 16, 56, 91, 101, 85, 43, -15, -47, -36, -6, 28, 45, 16, -38, -80, + -102, -97, -65, -24, 11, 25, 4, -33, -63, -75, -46, 18, 66, 75, 56, 19, + -15, -20, 2, 38, 77, 98, 93, 62, 8, -38, -44, -20, 14, 41, 32, -15, + -64, -94, -101, -79, -40, -2, 22, 15, -17, -52, -72, -61, -9, 49, 74, 66, + 36, -2, -21, -9, 22, 61, 91, 96, 76, 31, -22, -45, -32, 0, 32, 40, + 7, -43, -82, -99, -89, -56, -17, 14, 21, -2, -38, -65, -69, -33, 26, 66, + 71, 50, 13, -16, -16, 7, 43, 79, 95, 85, 50, -2, -40, -40, -14, 20, + 40, 24, -22, -66, -93, -95, -70, -32, 3, 21, 9, -23, -55, -70, -51, 1, + 52, 71, 60, 28, -6, -19, -4, 27, 64, 90, 91, 66, 19, -27, -43, -26, + 6, 34, 35, -1, -48, -83, -96, -81, -47, -10, 16, 17, -9, -43, -66, -62, + -22, 33, 66, 67, 43, 7, -16, -13, 12, 48, 80, 91, 77, 39, -10, -40, + -36, -8, 24, 38, 17, -28, -69, -92, -89, -62, -25, 7, 19, 4, -29, -58, + -67, -42, 10, 55, 70, 55, 22, -9, -17, 0, 33, 68, 90, 86, 57, 10, + -31, -41, -21, 12, 36, 30, -8, -53, -85, -94, -75, -41, -5, 17, 13, -15, + -48, -67, -57, -13, 39, 68, 64, 37, 3, -16, -9, 18, 54, 84, 91, 72, + 30, -17, -41, -33, -2, 28, 37, 10, -35, -74, -94, -86, -56, -19, 10, 17, + -2, -36, -63, -66, -34, 19, 60, 70, 51, 17, -11, -15, 5, 39, 74, 92, + 83, 49, 1, -36, -40, -16, 18, 37, 24, -17, -61, -90, -93, -70, -34, 1, + 18, 8, -22, -55, -69, -50, -2, 47, 70, 61, 31, -3, -17, -5, 26, 62, + 88, 90, 65, 19, -25, -42, -27, 5, 33, 33, 1, -45, -81, -95, -81, -48, + -11, 14, 15, -10, -43, -66, -61, -22, 31, 65, 68, 43, 9, -14, -11, 12, + 49, 80, 92, 76, 38, -10, -39, -36, -8, 24, 38, 16, -27, -70, -92, -89, + -61, -25, 7, 17, 3, -31, -59, -68, -39, 8, 55, 55, 19, 0, -9, -10, + -14, -13, -21, -30, -32, -44, -49, -57, -65, -72, -83, -98, -104, -117, -123, -128, + -127, -128, -128, -128, -128, -127, -128, -120, -117, -109, -100, -90, -83, -72, -66, -55, + -50, -33, -42, -18, -29, -18, 15, -6, 11, 7, 19, 3, 38, 5, 48, 44, + 64, 57, 97, 82, 111, 104, 110, 107, 120, 116, 125, 126, 126, 126, 126, 127, + 117, 125, 123, 100, 127, 101, 124, 102, 121, 109, 126, 96, 125, 116, 127, 90, + 119, 87, 127, 90, 118, 95, 123, 93, 106, 90, 100, 104, 74, 84, 73, 97, + 72, 71, 57, 66, 80, 36, 59, 38, 55, 35, 57, -6, 64, 10, 25, 19, + 19, -22, 65, -26, 14, 2, -17, -12, 22, -40, -3, -31, -24, -38, -1, -56, + -6, -48, -36, -54, -19, -56, -33, -49, -69, -49, -52, -53, -60, -61, -84, -76, + -85, -96, -95, -95, -114, -93, -117, -104, -93, -101, -98, -100, -101, -96, -78, -95, + -71, -70, -72, -52, -63, -70, -43, -77, -41, -48, -65, -53, -53, -59, -42, -56, + -37, -64, -54, -52, -50, -54, -56, -54, -55, -62, -51, -47, -44, -67, -60, -63, + -56, -64, -53, -48, -61, -53, -58, -38, -48, -32, -38, -34, -28, -26, -23, -25, + -22, -6, -7, -12, -1, 5, 6, 6, -7, 22, -4, 27, 15, 18, 24, 37, + 30, 47, 24, 53, 29, 63, 29, 46, 46, 51, 52, 53, 36, 54, 65, 55, + 33, 64, 36, 69, 54, 26, 62, 66, 36, 68, 30, 47, 54, 58, 20, 55, + 31, 40, 50, 35, 19, 56, 33, 25, 46, 18, 22, 42, 21, 25, 32, 19, + 19, 26, 18, 23, 29, 24, 7, 27, 6, 33, 8, 17, -2, 14, 3, 23, + 14, 7, 5, -9, -13, -10, -23, -12, -16, -27, -8, -18, -15, -3, -18, -24, + -5, -23, -9, 0, -11, 4, -1, 4, 2, 5, -2, 3, -1, -7, 4, -11, + 1, -12, -4, -7, -10, -11, -11, -16, -23, -15, -20, -22, -23, -20, -30, -23, + -31, -25, -32, -35, -41, -34, -44, -39, -34, -49, -33, -30, -36, -29, -33, -14, + -24, -32, -18, -15, -7, -9, -11, 5, -14, 27, -11, 16, -10, 13, -9, 23, + -10, 19, 10, 18, 11, 29, 1, 47, 27, -4, 45, 3, 43, 40, 14, 13, + 57, 16, 34, 27, 22, 30, 32, 14, 24, 27, 20, 20, 17, 4, 20, 20, + 8, 8, 0, 10, -3, 17, -8, -1, -4, 1, 0, 6, -7, -3, -3, -13, + -5, -6, -18, -5, -28, -12, -13, -5, -11, -5, -28, -7, -15, -10, -6, -28, + -16, -12, -17, -8, -10, -19, -10, -24, -30, -32, -26, -31, -36, -32, -33, -27, + -25, -26, -26, -25, -25, -23, -16, -22, -10, -11, -7, -7, 4, -10, 10, -9, + 11, -8, 4, -6, 4, -8, 3, -4, 2, -3, -5, -3, -11, -8, -6, -12, + -11, -7, -24, -4, -17, -9, -18, -28, -16, -29, -23, -38, -24, -34, -22, -38, + -18, -27, -10, -22, -19, -21, -2, -23, 10, -19, 0, 4, 16, 7, 0, 3, + 17, 14, 26, 8, 25, 27, 30, 25, 38, 31, 49, 37, 42, 45, 48, 55, + 63, 46, 54, 54, 56, 59, 56, 47, 50, 53, 47, 50, 44, 42, 35, 40, + 31, 37, 35, 27, 20, 23, 19, 26, 24, 18, 11, 14, 18, 24, 18, 12, + 10, 3, 12, 2, 9, 4, 0, 0, 3, -4, 11, 1, 1, -1, -5, -7, + 1, -6, -1, 2, -4, 1, -1, -7, -9, -11, -21, -19, -20, -28, -27, -22, + -29, -24, -26, -32, -22, -25, -31, -24, -19, -22, -11, -19, -15, -4, -5, -4, + 0, -6, -6, 2, -9, -5, -5, -9, -10, -7, -18, -8, -14, -14, -19, -29, + -25, -16, -25, -30, -30, -30, -21, -29, -38, -37, -36, -41, -44, -53, -48, -43, + -44, -55, -46, -40, -33, -36, -40, -40, -28, -25, -24, -23, -17, -15, 1, -3, + -1, 5, 2, 9, 1, 4, 12, 13, 14, 15, 9, 21, 26, 32, 31, 28, + 28, 41, 38, 49, 45, 46, 53, 56, 57, 57, 57, 58, 55, 48, 56, 56, + 56, 45, 39, 41, 41, 44, 42, 25, 28, 27, 24, 28, 21, 14, 17, 8, + 15, 22, 13, 15, 16, 3, 11, 10, 4, 6, 4, -8, 0, -2, -2, -3, + -2, 1, 3, -3, -3, -6, -8, -5, 4, 3, 2, -4, -2, -1, 5, 3, + -2, -2, -2, 3, 7, -2, -26, -37, -34, -30, -13, -14, -21, -24, -27, -24, + -13, -7, -15, 6, 3, -30, -50, -48, -47, -41, -26, -8, 28, 43, 38, 57, + 63, 56, 75, 118, 127, 117, 99, 86, 85, 66, 46, 59, 80, 69, 43, 27, + -6, -47, -74, -80, -71, -57, -40, -44, -56, -78, -88, -78, -59, -52, -51, -56, + -57, -47, -36, -36, -39, -39, -32, -17, 6, 24, 33, 10, -14, -14, -2, -11, + -20, -15, -24, -28, -28, -25, -28, -54, -73, -65, -43, -18, 6, 27, 21, 23, + 17, 22, 18, 16, 31, 50, 45, 25, 22, 8, -20, -17, 8, 29, 10, -22, + -41, -45, -51, -53, -31, -18, -23, -7, 37, 54, 38, 36, 60, 100, 119, 120, + 122, 125, 110, 88, 94, 99, 90, 85, 82, 54, 26, -5, -49, -83, -85, -67, + -36, -14, -30, -55, -76, -86, -65, -41, -45, -60, -53, -43, -35, -34, -41, -43, + -45, -35, 10, 40, 32, 3, -3, -14, -30, -38, -33, -23, -29, -26, -18, -10, + -17, -37, -46, -58, -61, -45, -17, -4, -2, 19, 31, 27, 13, 22, 38, 49, + 59, 69, 60, 23, -13, -11, 13, 24, 19, 24, 8, -30, -58, -58, -66, -85, + -90, -61, -19, -1, -11, -5, 25, 42, 61, 92, 109, 106, 110, 104, 93, 93, + 89, 82, 86, 81, 71, 51, 13, -40, -74, -87, -73, -35, -24, -50, -71, -73, + -53, -50, -58, -68, -60, -61, -54, -30, -25, -40, -52, -25, 13, 32, 45, 49, + 44, 28, 22, 29, 32, 20, 3, 7, 6, 0, -1, -4, -30, -63, -69, -62, + -57, -49, -25, 2, 17, 24, 27, 30, 10, 4, 38, 77, 66, 32, 13, 7, + 0, 9, 31, 43, 23, -11, -25, -23, -46, -83, -87, -63, -42, -19, -6, -3, + 6, 27, 49, 81, 108, 121, 123, 124, 115, 110, 98, 80, 78, 77, 77, 69, + 54, 8, -56, -99, -92, -53, -46, -64, -75, -73, -70, -75, -62, -67, -86, -88, + -54, -28, -33, -46, -50, -40, -24, -3, 29, 51, 48, 34, 44, 44, 30, 18, + 13, -3, -15, -7, -1, -10, -36, -56, -65, -79, -100, -91, -64, -52, -40, -5, + 20, 9, -14, -9, 21, 49, 59, 58, 49, 25, -1, 11, 39, 39, 22, 19, + 20, 8, -19, -49, -72, -69, -58, -43, -27, -24, -13, -5, 12, 38, 74, 97, + 110, 124, 126, 126, 114, 105, 100, 87, 91, 108, 115, 73, 5, -41, -49, -49, + -53, -45, -49, -69, -77, -60, -51, -71, -94, -96, -68, -49, -46, -44, -45, -60, + -60, -27, 0, 11, 26, 37, 37, 37, 40, 42, 34, 8, -1, 14, 15, -5, + -12, -18, -44, -75, -85, -88, -98, -99, -76, -36, -12, -19, -24, -11, -9, 1, + 36, 71, 58, 29, 13, 17, 33, 33, 30, 35, 44, 44, 27, -3, -39, -51, + -61, -55, -41, -31, -25, -29, -21, -1, 23, 46, 76, 102, 109, 110, 116, 118, + 92, 61, 76, 112, 120, 93, 57, 14, -28, -54, -50, -46, -60, -83, -82, -64, + -62, -82, -89, -93, -101, -88, -59, -52, -64, -75, -76, -63, -50, -30, -1, 9, + 8, 11, 32, 44, 36, 29, 32, 27, 20, 22, 28, 24, 0, -21, -30, -45, + -78, -97, -83, -66, -50, -32, -17, -16, -23, -20, 4, 38, 51, 47, 37, 28, + 29, 27, 27, 31, 42, 54, 55, 43, 20, -5, -29, -40, -37, -30, -27, -23, + -15, -12, -11, 8, 43, 67, 78, 100, 122, 126, 107, 84, 81, 92, 106, 115, + 110, 79, 31, -3, -13, -26, -47, -56, -56, -58, -58, -56, -59, -72, -86, -84, + -66, -57, -56, -56, -60, -74, -74, -51, -32, -24, -14, 3, 14, 15, 19, 28, + 33, 19, 11, 22, 29, 18, 8, 9, 0, 0, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, + -1, -1, -1, -1, -1, -1, -1, 0, -1, -3, -2, -1, 0, 2, -4, -13, + -21, -23, -19, -8, 7, 17, 23, 26, 33, 38, 32, 17, -5, -17, -24, -20, + -6, -3, -16, -29, -26, -17, -5, -1, 2, 7, 11, 17, 15, 9, 9, 3, + 10, 15, 9, -14, -33, -27, -18, -6, -7, -10, -6, 0, 12, 15, 29, 38, + 36, 32, 11, 0, -30, -45, -50, -39, -23, -27, -24, -15, 6, 25, 37, 51, + 46, 40, 0, -19, -22, -34, -30, -40, -45, -51, -34, -1, 25, 48, 40, 43, + 51, 64, 58, 5, -22, -49, -63, -69, -68, -58, -54, -16, 13, 44, 66, 61, + 68, 72, 86, 47, -17, -56, -82, -88, -93, -72, -58, -40, 4, 45, 94, 98, + 84, 65, 68, 71, 15, -46, -88, -90, -88, -85, -62, -56, -34, -4, 41, 80, + 82, 74, 54, 70, 66, 25, -29, -70, -74, -90, -87, -79, -73, -46, -10, 54, + 90, 103, 88, 76, 90, 69, 25, -38, -76, -96, -119, -111, -103, -81, -57, -12, + 50, 90, 113, 98, 100, 112, 103, 60, -11, -54, -95, -121, -124, -119, -95, -71, + -10, 53, 103, 116, 93, 91, 89, 80, 31, -28, -67, -108, -122, -128, -110, -87, + -53, 8, 60, 107, 107, 89, 83, 83, 76, 27, -14, -52, -84, -99, -103, -82, + -72, -40, 4, 53, 92, 92, 88, 85, 97, 87, 42, 3, -45, -74, -106, -111, + -105, -101, -70, -30, 27, 65, 77, 83, 87, 106, 90, 58, 16, -30, -67, -101, + -100, -101, -93, -68, -27, 29, 60, 77, 79, 93, 111, 96, 71, 24, -21, -73, + -109, -118, -127, -118, -98, -50, 6, 43, 65, 70, 99, 115, 108, 82, 40, -1, + -53, -80, -94, -105, -101, -82, -31, 18, 56, 66, 72, 95, 103, 97, 64, 29, + -15, -63, -85, -102, -105, -104, -81, -35, 13, 53, 58, 69, 86, 97, 94, 67, + 39, -12, -54, -80, -97, -102, -103, -77, -38, 9, 40, 45, 60, 77, 95, 88, + 70, 41, -8, -46, -74, -87, -99, -100, -78, -42, 10, 37, 50, 66, 89, 110, + 103, 91, 57, 9, -33, -68, -86, -105, -105, -89, -51, -2, 23, 40, 53, 80, + 99, 98, 89, 53, 8, -37, -68, -90, -107, -106, -94, -51, -5, 25, 43, 58, + 86, 95, 98, 86, 52, 9, -36, -64, -92, -105, -108, -95, -53, -11, 22, 37, + 57, 81, 90, 96, 82, 52, 6, -34, -64, -92, -104, -113, -97, -59, -18, 15, + 31, 58, 79, 92, 98, 87, 57, 9, -29, -63, -87, -100, -109, -91, -58, -13, + 16, 36, 62, 78, 93, 96, 88, 56, 12, -25, -62, -83, -101, -106, -89, -57, + -15, 6, 30, 52, 71, 87, 94, 89, 55, 18, -21, -55, -76, -96, -100, -88, + -53, -16, 6, 31, 53, 76, 93, 105, 98, 64, 26, -18, -52, -78, -99, -105, + -95, -59, -26, 0, 24, 45, 66, 81, 97, 88, 62, 28, -12, -40, -67, -84, + -95, -83, -50, -21, 4, 24, 47, 64, 81, 96, 85, 63, 26, -11, -41, -69, + -88, -102, -91, -64, -36, -12, 10, 34, 51, 74, 87, 81, 62, 26, -7, -40, + -63, -83, -95, -83, -58, -31, -10, 14, 34, 51, 75, 85, 82, 61, 30, -3, + -34, -57, -81, -92, -83, -60, -36, -15, 11, 27, 47, 69, 80, 79, 59, 30, + -5, -33, -57, -82, -93, -84, -61, -38, -15, 10, 25, 48, 68, 80, 77, 58, + 29, -4, -30, -56, -80, -89, -78, -54, -34, -8, 10, 0, 0, 1, 0, -2, + -2, -5, -8, -3, 3, -4, -10, 2, 8, 3, 4, 5, -3, -9, 10, 26, + 26, 12, -4, -40, -64, -50, 1, 55, 69, 28, -23, -65, -83, -52, 13, 67, + 67, 39, 16, -15, -48, -38, 10, 53, 44, 5, -5, -14, -43, -35, 16, 54, + 37, -1, -26, -53, -82, -37, 35, 67, 44, 2, -10, -20, -39, -19, 27, 55, + 42, 3, -26, -67, -107, -62, 43, 110, 102, 43, -18, -63, -91, -35, 73, 120, + 77, -6, -72, -113, -109, -36, 53, 78, 50, 0, -46, -72, -71, -20, 67, 112, + 100, 44, -24, -88, -123, -84, 5, 71, 97, 66, 7, -53, -100, -80, -1, 83, + 127, 108, 38, -57, -121, -119, -57, 24, 84, 97, 62, -4, -77, -97, -46, 32, + 101, 108, 56, -20, -103, -119, -69, 18, 105, 126, 90, 6, -92, -126, -90, -3, + 85, 108, 75, 0, -86, -117, -85, -6, 76, 115, 101, 30, -68, -118, -105, -33, + 57, 105, 102, 41, -46, -104, -112, -59, 25, 95, 121, 81, -5, -88, -126, -94, + -12, 63, 101, 76, 7, -67, -107, -73, 11, 94, 127, 102, 21, -74, -124, -95, + -21, 57, 101, 82, 21, -48, -89, -59, 6, 67, 95, 60, -11, -82, -115, -81, + -13, 52, 84, 52, -9, -68, -96, -56, 9, 66, 93, 63, 10, -52, -86, -54, + 1, 60, 96, 70, 19, -44, -80, -51, 0, 55, 94, 69, 20, -42, -88, -76, + -40, 24, 79, 72, 34, -28, -75, -63, -23, 35, 71, 48, 4, -57, -95, -67, + -10, 62, 103, 75, 18, -61, -110, -86, -22, 61, 110, 90, 37, -45, -100, -87, + -39, 34, 81, 70, 33, -39, -88, -76, -24, 54, 94, 76, 32, -46, -100, -92, + -42, 35, 73, 62, 26, -46, -97, -93, -44, 36, 81, 75, 35, -38, -87, -81, + -26, 58, 99, 85, 37, -44, -101, -103, -46, 47, 98, 97, 56, -27, -90, -99, + -49, 37, 88, 95, 62, -12, -74, -93, -51, 27, 69, 71, 35, -30, -78, -87, + -38, 41, 84, 90, 57, -11, -71, -96, -56, 21, 69, 86, 60, -4, -67, -97, + -61, 12, 65, 88, 65, 3, -61, -94, -60, 14, 71, 96, 68, 3, -66, -104, + -70, 3, 59, 84, 59, -1, -67, -107, -76, -3, 59, 89, 64, 3, -67, -111, + -82, -9, 57, 92, 76, 26, -43, -93, -71, -9, 50, 80, 64, 16, -51, -100, + -79, -17, 49, 88, 77, 30, -41, -95, -79, -17, 49, 87, 77, 34, -36, -92, + -78, -19, 44, 82, 73, 33, -37, -95, -84, -23, 47, 89, 83, 43, -30, -92, + -83, -28, 39, 79, 74, 40, -28, -87, -82, -31, 34, 71, 67, 35, -31, -88, + -85, -36, 28, 68, 69, 44, -20, -79, -83, -43, 19, 59, 64, 41, -25, -89, + -100, -61, 9, 60, 76, 57, -10, -75, -90, -51, 22, 74, 88, 66, 1, -61, + -78, -42, 25, 71, 84, 63, -1, -67, -90, -59, 8, 59, 81, 68, 8, -56, + -85, -62, 1, 50, 74, 63, 7, -53, -84, -60, 5, 55, 80, 70, 17, -43, + -76, -55, 4, 49, 73, 65, 17, -41, -77, -62, -9, 38, 68, 64, 17, -43, + -84, -73, -22, 23, 56, 57, 18, -36, -77, -68, -23, 20, 51, 52, 16, -36, + -77, -70, -26, 18, 54, 59, 28, -22, -64, -59, -20, 21, 56, 63, 36, -12, + -55, -52, -16, 25, 58, 63, 35, -14, -59, -57, -22, 18, 51, 57, 31, -16, + -58, -58, -27, 10, 43, 51, 30, -16, -59, -60, -28, 12, 48, 57, 35, -13, + -59, -64, -35, 7, 47, 63, 47, 1, -46, -55, -32, 7, 47, 0, 0, -1, + -1, -4, 1, -1, -3, -13, -8, -14, -3, -2, -2, 1, 8, 5, 7, -21, + -13, -2, -6, -8, -22, -6, 5, 11, 34, 41, 33, 13, 28, 33, 48, 35, + 21, -3, -26, -18, -10, 3, 7, 22, 21, 63, 40, 41, 43, 4, -8, -43, + -63, -77, -77, -59, -18, 3, 2, -21, -46, -74, -90, -108, -101, -94, -89, -84, + -85, -77, -59, -50, -33, -7, 18, 37, 47, 64, 101, 127, 125, 127, 126, 126, + 126, 122, 100, 87, 62, 37, 28, 27, 25, 27, 34, 25, -4, -45, -85, -123, + -128, -126, -128, -127, -123, -92, -73, -55, -45, -37, -33, -32, -33, -43, -53, -55, + -43, -20, 3, 20, 34, 42, 49, 55, 63, 74, 84, 93, 101, 107, 112, 117, + 109, 92, 63, 33, 8, -13, -25, -29, -30, -27, -27, -32, -46, -63, -82, -98, + -109, -116, -121, -118, -104, -80, -49, -12, 21, 45, 58, 64, 66, 66, 61, 51, + 44, 37, 32, 32, 33, 33, 28, 23, 15, 8, 3, 2, 9, 16, 20, 24, + 23, 14, -1, -20, -37, -48, -53, -52, -47, -38, -26, -13, -5, -1, -4, -10, + -22, -34, -43, -48, -46, -34, -16, 5, 25, 45, 65, 78, 84, 83, 71, 55, + 39, 24, 9, -3, -12, -23, -34, -45, -57, -65, -71, -71, -63, -49, -34, -21, + -11, -2, 2, 8, 11, 12, 14, 14, 20, 28, 38, 50, 58, 63, 61, 56, + 46, 33, 17, -1, -19, -34, -45, -48, -44, -32, -19, -5, 5, 7, 4, -2, + -7, -11, -15, -18, -21, -23, -26, -28, -30, -31, -29, -26, -20, -12, -1, 11, + 21, 32, 42, 51, 55, 55, 52, 46, 41, 37, 32, 30, 28, 27, 24, 19, + 12, -1, -21, -45, -67, -89, -103, -107, -101, -90, -70, -51, -33, -18, -2, 11, + 23, 33, 39, 44, 49, 52, 57, 59, 59, 56, 52, 48, 41, 35, 28, 20, + 15, 11, 4, 0, -5, -11, -18, -25, -34, -42, -47, -48, -46, -40, -33, -27, + -24, -21, -24, -32, -42, -51, -56, -58, -56, -47, -35, -18, 2, 24, 48, 70, + 88, 99, 104, 102, 97, 89, 79, 69, 59, 49, 37, 27, 14, 0, -14, -29, + -44, -58, -71, -81, -87, -88, -88, -85, -81, -77, -72, -63, -51, -37, -21, -5, + 12, 29, 43, 53, 59, 61, 57, 48, 36, 24, 13, 8, 8, 15, 25, 38, + 48, 54, 54, 50, 43, 33, 22, 11, 3, -6, -15, -25, -35, -46, -54, -61, + -65, -68, -69, -69, -68, -64, -59, -52, -43, -32, -20, -7, 6, 19, 31, 42, + 51, 58, 62, 64, 62, 58, 52, 44, 35, 26, 17, 9, 1, -5, -10, -15, + -18, -19, -20, -19, -18, -16, -15, -14, -14, -15, -16, -17, -18, -19, -19, -19, + -19, -18, -16, -14, -11, -9, -6, -3, 0, 3, 6, 10, 14, 18, 22, 27, + 32, 35, 37, 37, 35, 30, 23, 14, 4, -6, -15, -24, -31, -36, -39, -40, + -39, -37, -32, -26, -19, -10, -1, 8, 17, 24, 29, 32, 33, 32, 29, 25, + 20, 15, 11, 7, 3, -1, -5, -9, -14, -19, -24, -28, -31, -32, -31, -27, + -23, -16, -10, -3, 2, 7, 10, 12, 13, 13, 13, 12, 10, 8, 7, 5, + 5, 5, 5, 6, 8, 10, 13, 17, 20, 23, 25, 26, 25, 21, 16, 9, + 1, -7, -16, -24, -31, -37, -42, -47, -49, -51, -52, -51, -48, -43, -37, -30, + -20, -7, 6, 19, -1, -4, -4, 0, -1, -4, -3, 4, 4, -2, -3, 2, + 1, -4, 0, 5, 0, -4, 2, -10, -26, -29, -34, -49, -61, -44, -21, -8, + -3, -3, 1, 20, 32, 38, 32, 12, -4, 1, 14, 28, 51, 68, 78, 80, + 72, 38, 1, -6, 16, 23, 2, -14, -15, -20, -33, -62, -65, -37, -18, -27, + -29, -26, -45, -38, 8, 52, 55, 31, 26, 16, 17, 45, 80, 87, 77, 62, + 54, 24, -23, -50, -43, -28, -47, -72, -86, -86, -87, -61, -35, -38, -57, -69, + -55, -27, 1, 4, 22, 45, 54, 31, 0, -7, -5, -3, 0, -9, -21, -20, + -15, -27, -31, -10, 5, 9, 3, -21, -67, -83, -46, -3, 8, 18, 22, 4, + -3, 5, 35, 52, 67, 72, 83, 89, 71, 37, 19, 25, 8, -11, -37, -58, + -80, -85, -68, -33, -24, -57, -60, -34, -16, -14, 17, 73, 96, 77, 48, 17, + -7, -9, 4, -1, -3, 6, 3, -12, -10, 19, 33, 33, 41, 35, -29, -70, + -64, -38, -18, 3, 17, -5, -26, -35, -5, 31, 63, 73, 86, 94, 80, 64, + 50, 46, 37, 28, -2, -32, -65, -91, -84, -63, -59, -82, -97, -80, -66, -65, + -43, 8, 49, 60, 61, 42, 27, 23, 23, 14, 15, 18, 10, -12, -17, -9, + -13, 8, 35, 42, 2, -41, -76, -87, -67, -46, -31, -32, -45, -72, -53, -5, + 32, 46, 72, 92, 96, 92, 77, 75, 73, 61, 44, 12, -32, -68, -72, -54, + -58, -75, -85, -67, -57, -61, -60, -46, -11, 24, 35, 22, 15, 6, -1, -13, + 8, 23, 8, -1, -1, -6, -8, 35, 71, 86, 79, 50, -11, -46, -38, -31, + -29, -21, -30, -64, -68, -43, -12, 10, 28, 62, 89, 88, 84, 85, 90, 89, + 95, 83, 28, -32, -53, -36, -44, -62, -64, -55, -59, -54, -52, -48, -23, 19, + 48, 37, 39, 42, 31, 12, 19, 20, 5, 4, 1, -23, -40, -14, 14, 42, + 68, 64, 14, -33, -53, -52, -32, -18, -24, -43, -67, -62, -36, -18, -1, 25, + 54, 57, 58, 56, 54, 50, 66, 80, 44, -21, -50, -40, -52, -69, -77, -60, + -56, -54, -53, -62, -49, -9, 28, 41, 58, 58, 47, 43, 49, 41, 34, 37, + 18, -19, -44, -47, -36, 1, 35, 38, 19, -20, -62, -71, -59, -36, -34, -47, + -63, -63, -50, -38, -17, 7, 37, 56, 74, 80, 73, 61, 87, 116, 99, 47, + -7, -26, -22, -20, -32, -57, -72, -76, -76, -71, -47, -9, 13, 24, 29, 29, + 25, 27, 52, 68, 62, 9, -38, -67, -66, -39, -11, -4, -24, -37, -47, -51, + -49, -44, -55, -39, -6, -17, -52, -54, -19, 1, 15, 24, 31, 41, 55, 71, + 79, 89, 111, 115, 88, 54, 22, -2, -8, -5, -7, -27, -49, -57, -69, -72, + -64, -30, -3, 17, 31, 37, 29, 14, 39, 67, 73, 47, 10, -40, -72, -58, + -23, -12, -19, -19, -39, -49, -42, -46, -62, -44, -8, -11, -36, -51, -39, -15, + 0, 13, 21, 25, 40, 55, 63, 73, 95, 115, 115, 85, 53, 20, 2, -1, + -2, -10, -32, -48, -64, -73, -77, -62, -33, -9, 16, 33, 31, 18, 17, 44, + 67, 70, 49, 6, -45, -69, -53, -24, -13, -19, -24, -40, -47, -45, -50, -62, + -43, -10, -13, -37, -51, -39, -15, 0, -3, -1, 1, -1, -6, -6, -4, -1, + -2, -6, -8, -7, -4, -5, -10, -14, -16, -16, -16, -17, -18, -18, -17, -15, + -15, -16, -15, -13, -10, -9, -9, -11, -13, -14, -11, -9, -8, -9, -7, -3, + -2, -5, -8, -6, 1, 5, 4, 1, 0, 1, 4, 4, 4, 5, 7, 9, + 9, 8, 8, 9, 10, 9, 5, 2, 3, 5, 7, 7, 9, 11, 11, 12, + 14, 14, 12, 8, 7, 8, 5, 1, 3, 8, 9, 9, 10, 14, 16, 15, + 14, 12, 11, 9, 7, 3, -2, -3, 3, 5, 0, -5, -1, -1, -6, -10, + -16, -23, -28, -29, -32, -39, -36, -23, -16, -19, -19, -10, -7, -12, -11, -5, + -6, -11, -13, -11, -9, -8, -2, 6, 8, 8, 9, 6, 2, 4, 8, 9, + 4, 4, 12, 18, 17, 14, 17, 20, 20, 16, 9, 7, 7, 5, 3, 4, + 1, -2, 0, 3, 2, -1, 1, 3, 3, 1, 2, 2, 0, 3, 6, 9, + 8, 0, -5, -3, 7, 12, 8, -2, -2, 9, 10, 2, -3, 2, 5, 1, + -3, -5, -6, -2, -3, -11, -20, -26, -28, -30, -32, -37, -43, -45, -43, -40, + -42, -41, -31, -22, -20, -18, -16, -16, -19, -15, -8, -3, -3, 3, 17, 26, + 22, 16, 18, 23, 27, 26, 23, 17, 15, 21, 25, 24, 25, 31, 36, 32, + 29, 23, 17, 15, 11, 5, 1, 4, 6, 8, 6, 7, 8, 10, 14, 18, + 22, 20, 17, 14, 15, 13, 10, 15, 15, 12, 9, 10, 15, 14, 9, 3, + 6, 10, 5, -3, -9, -16, -16, -10, -11, -20, -24, -18, -20, -32, -42, -48, + -55, -70, -84, -95, -100, -92, -75, -65, -68, -67, -56, -55, -51, -41, -33, -37, + -42, -38, -33, -31, -26, -6, 19, 30, 25, 25, 28, 30, 27, 19, 16, 18, + 31, 44, 46, 48, 56, 71, 77, 74, 66, 54, 47, 37, 19, 3, 2, 3, + 3, 4, 13, 20, 21, 25, 24, 25, 19, 18, 19, 19, 14, 6, 17, 14, + 1, 3, 12, 27, 29, 25, 13, 14, 24, 22, 6, -7, -7, 0, 11, 12, + 1, 0, 10, 8, -13, -32, -46, -52, -57, -70, -88, -106, -101, -81, -74, -82, + -75, -49, -37, -42, -44, -42, -46, -51, -47, -40, -32, -27, -6, 3, 16, 32, + 29, 25, 24, 30, 54, 69, 74, 78, 90, 108, 118, 124, 117, 107, 102, 93, + 76, 61, 50, 41, 35, 31, 26, 13, 4, 0, -1, 0, -6, -12, -10, -8, + -4, 0, -3, -20, -31, -27, -18, -16, -22, -29, -28, -9, 0, -3, -1, 2, + 11, 20, 24, 18, 22, 34, 32, 16, -1, -18, -34, -46, -55, -67, -91, -102, + -91, -72, -73, -81, -68, -55, -55, -65, -74, -79, -87, -87, -83, -81, -77, -60, + -25, 4, 4, -3, 0, 13, 29, 29, 24, 23, 29, 51, 67, 72, 77, 88, + 105, 114, 122, 116, 106, 100, 93, 77, 63, 51, 42, 36, 31, 27, 15, 5, + 0, -1, 0, -4, -10, -9, -7, -3, 2, -1, -16, -28, -26, -16, -13, -18, + -25, -25, -8, 2, 1, 2, 5, 13, 21, 26, 20, 23, 35, 35, 20, 3, + -14, -32, -45, -54, -67, -91, -102, -90, -72, -75, -82, -68, -56, -56, -66, -75, + -81, -88, -88, -83, -82, -77, -59, -22, 4, 1, -1, -2, -3, -3, -1, -1, + -6, -8, -9, -12, -5, 6, 15, 21, 22, 21, 9, -8, -16, -23, -32, -22, + 4, 27, 32, 17, -2, -21, -34, -37, -30, -24, -3, 24, 47, 58, 50, 23, + -12, -41, -52, -47, -33, -2, 28, 48, 45, 28, 0, -36, -58, -53, -34, -4, + 26, 52, 75, 73, 45, -5, -66, -101, -90, -61, -14, 23, 59, 87, 89, 63, + 10, -46, -79, -80, -55, -23, -3, 27, 58, 62, 41, -6, -66, -92, -77, -29, + 19, 41, 65, 74, 69, 42, -9, -73, -109, -107, -67, -17, 23, 70, 104, 111, + 83, 21, -56, -104, -109, -62, -21, 4, 34, 68, 89, 75, 19, -46, -89, -85, + -38, -1, 23, 45, 64, 74, 62, 8, -53, -98, -93, -47, -9, 16, 36, 62, + 86, 78, 13, -67, -121, -109, -56, -9, 25, 58, 89, 109, 81, 8, -70, -119, + -106, -56, -7, 32, 63, 90, 108, 74, -3, -89, -128, -118, -70, -22, 23, 62, + 101, 126, 98, 26, -64, -117, -110, -72, -32, 6, 44, 93, 124, 100, 28, -63, + -116, -110, -71, -26, 16, 54, 101, 121, 92, 13, -86, -128, -120, -79, -28, 15, + 60, 111, 127, 95, 11, -83, -127, -116, -80, -29, 15, 67, 117, 127, 100, 17, + -75, -118, -108, -75, -31, 7, 60, 109, 123, 87, 3, -83, -118, -106, -67, -23, + 13, 62, 106, 119, 85, 3, -77, -106, -95, -61, -27, 2, 52, 103, 124, 97, + 19, -61, -95, -92, -63, -34, -4, 45, 94, 116, 87, 8, -63, -91, -85, -58, + -36, -9, 36, 81, 104, 76, 2, -60, -87, -77, -52, -32, -2, 48, 97, 119, + 86, 7, -59, -90, -85, -65, -50, -22, 26, 78, 107, 79, 11, -49, -78, -73, + -58, -46, -18, 31, 85, 112, 75, 1, -59, -84, -73, -55, -40, -12, 30, 80, + 106, 74, 10, -46, -70, -62, -49, -39, -13, 31, 86, 110, 74, 8, -49, -70, + -59, -46, -33, -6, 38, 92, 111, 76, 13, -42, -62, -56, -51, -44, -23, 19, + 75, 97, 67, 8, -44, -63, -58, -56, -48, -26, 19, 75, 94, 64, 8, -40, + -55, -50, -49, -42, -25, 18, 69, 85, 57, 4, -41, -54, -51, -50, -45, -28, + 18, 71, 88, 60, 8, -35, -46, -47, -48, -46, -30, 16, 66, 84, 59, 9, + -30, -41, -43, -42, -40, -22, 25, 73, 88, 60, 8, -30, -42, -46, -45, -42, + -21, 28, 74, 83, 52, -1, -36, -46, -45, -40, -37, -17, 26, 66, 73, 41, + -10, -42, -54, -53, -48, -43, -19, 27, 68, 76, 44, -4, -34, -44, -41, -37, + -33, -10, 34, 71, 75, 40, -7, -36, -47, -43, -39, -35, -9, 35, 72, 75, + 39, -7, -38, -49, -45, -43, -38, -11, 33, 68, 70, 36, -4, -31, -39, -36, + -35, -31, -5, 36, 69, 69, 35, -4, -31, -38, -35, -37, -33, -8, 31, 64, + 63, 31, -7, -34, -42, -40, -43, -38, -12, 28, 61, 59, 27, -10, -34, -40, + -38, -41, -35, -9, 31, 63, 60, 29, -6, -31, -37, -38, -42, -35, -10, 29, + 60, 56, 27, -8, -30, -33, -34, -38, -32, -10, 28, 56, 51, 23, -9, -29, + -32, -34, -38, -33, -10, 29, 55, 50, 23, -9, -28, -30, -33, -37, -32, -8, + 32, 56, 52, 23, 23, 0, -2, 0, -2, -6, -6, -6, -5, -2, -1, 5, + 15, 20, 11, 12, 12, 6, 0, -8, -19, -12, -4, -19, -19, -4, 4, -7, + -3, 5, 8, 11, 14, 9, 9, 8, -4, -11, -6, -8, -16, -14, -7, -1, + -3, 1, 10, 13, 24, 28, 12, 10, 14, 11, -14, -29, -19, -12, -21, -25, + -16, 2, 0, -11, -7, 7, 10, 0, 0, 5, 11, 6, 10, 21, 13, 7, + 14, 4, -4, -9, -5, -11, -16, -7, -3, 3, 15, -2, 2, 17, 6, -19, + -16, 3, 3, -14, -10, 7, 7, 4, 8, 11, 4, -5, -12, -9, -6, -14, + -13, -17, -13, -8, 5, 9, 3, 10, 12, 24, 28, 26, 35, 20, -3, 24, + 23, -19, -31, -23, -23, -38, -34, -18, -10, -8, -6, -4, -1, 5, -4, -8, + 2, 15, 12, 26, 56, 37, 10, 25, 25, -4, -21, -24, -23, -26, -30, -27, + -8, 10, -5, 3, 30, 6, -26, -7, 13, -2, -19, -2, 11, 3, 14, 21, + 8, 12, 5, -19, -26, -12, 9, 1, -8, -8, 20, 27, 17, 16, 15, 0, + 23, 39, 11, -4, -13, -21, -21, -32, -36, -27, -20, -24, -10, -4, 5, 14, + 4, -11, -10, 7, -8, -7, 7, 7, 2, 15, 29, 55, 26, 4, 22, 37, + 32, 14, 10, 18, 7, -1, -28, -49, -24, -14, -41, -53, -37, -28, -27, -15, + 1, 2, 14, 14, 13, 3, 0, 1, 18, 9, 7, 11, 23, 23, 25, 16, + -7, 1, 13, 26, 26, 9, 13, 28, 28, 1, -29, -29, -26, -27, -43, -43, + -31, -12, -26, -15, 6, 16, 6, 22, 11, -4, 0, 3, 0, -4, -20, -9, + 15, 23, 19, 7, 25, 19, 42, 63, 40, 13, 22, 24, 1, -41, -60, -55, + -63, -69, -61, -31, -7, 10, 8, 0, 7, 4, 4, 20, 5, -4, 9, 27, + 31, 27, 23, 13, 19, 12, 2, 4, 15, 20, 35, 19, 16, 26, 3, -30, + -48, -31, -40, -60, -59, -47, -13, -3, 12, 22, 11, 7, 9, 8, 3, -10, + -34, -5, 6, 24, 38, 19, 13, 21, 40, 15, 2, 27, 26, 16, 44, 47, + -7, -43, -41, -29, -44, -80, -81, -58, -26, -17, 3, 16, 30, 19, 10, 25, + 16, 6, -12, -3, 13, 30, 38, 20, 17, 22, 25, 18, 13, 16, -3, 1, + 32, 44, -11, -48, -51, -34, -38, -49, -64, -70, -23, -10, -14, -1, 20, 18, + 20, 21, 11, 3, -8, -3, 13, 14, 22, 18, 32, 37, 30, 25, 16, 27, + 27, 18, 37, 52, 12, -26, -56, -57, -46, -71, -92, -86, -50, -21, -10, 8, + 15, 15, 18, 28, 17, 1, 1, 2, 13, 13, 23, 23, 21, 29, 31, 29, + 15, 20, 33, 32, 29, 46, 21, -31, -49, -53, -51, -66, -82, -76, -54, -32, + -10, 12, 19, 29, 18, 3, 0, 16, 20, 29, 31, 20, 25, 31, 43, 41, + 34, 44, 27, 29, 65, 54, -15, -70, -79, -63, -86, -114, -114, -79, -26, -2, + 6, 18, 19, 10, 19, 26, 15, 5, 0, 16, 23, 29, 30, 21, 25, 28, + 37, 37, 38, 44, 32, 29, 66, 65, -7, -67, -74, -59, -82, -114, -117, -85, + -31, -2, 11, 20, 18, 9, 20, 30, 15, 5, 0, 0, 1, 1, 2, 3, + 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 7, 7, 7, 7, 7, 6, + 4, 3, 2, 0, -1, -2, -3, -5, -6, -8, -9, -9, -11, -12, -14, -15, + -17, -17, -17, -18, -19, -19, -19, -18, -17, -16, -15, -13, -11, -8, -7, -6, + -5, -3, -1, 0, 0, 1, 3, 5, 8, 10, 12, 14, 17, 19, 21, 23, + 26, 27, 28, 28, 28, 26, 25, 24, 23, 23, 21, 19, 18, 16, 15, 14, + 13, 12, 11, 11, 11, 10, 8, 6, 5, 5, 4, 2, 0, -2, -4, -5, + -7, -10, -11, -12, -13, -14, -15, -15, -15, -15, -15, -16, -17, -18, -18, -19, + -21, -23, -25, -27, -28, -29, -29, -30, -30, -29, -27, -25, -23, -22, -20, -18, + -16, -14, -13, -12, -11, -11, -10, -9, -8, -6, -5, -4, -3, -1, 1, 3, + 4, 6, 7, 8, 8, 9, 10, 11, 12, 13, 13, 13, 13, 15, 18, 21, + 23, 24, 25, 25, 28, 31, 33, 34, 34, 32, 31, 31, 31, 30, 27, 22, + 16, 12, 10, 9, 7, 3, -5, -13, -19, -22, -22, -23, -25, -28, -31, -33, + -33, -32, -32, -31, -32, -33, -32, -29, -25, -21, -19, -19, -19, -19, -18, -15, + -9, -3, 2, 6, 9, 12, 16, 21, 27, 32, 37, 39, 40, 40, 39, 39, + 40, 41, 40, 38, 35, 34, 34, 33, 29, 22, 16, 11, 10, 11, 12, 12, + 10, 8, 7, 5, 3, 2, 0, -6, -12, -19, -23, -23, -22, -23, -26, -30, + -33, -33, -33, -34, -35, -37, -40, -45, -50, -53, -52, -48, -42, -37, -32, -27, + -22, -20, -18, -16, -16, -18, -21, -26, -30, -33, -34, -35, -36, -38, -40, -41, + -41, -38, -36, -36, -38, -41, -40, -38, -34, -30, -27, -25, -22, -20, -16, -15, + -16, -17, -18, -16, -13, -10, -7, -4, -2, 1, 6, 11, 16, 21, 24, 25, + 26, 24, 22, 19, 18, 19, 22, 24, 26, 30, 33, 38, 44, 50, 56, 61, + 63, 68, 72, 74, 73, 68, 64, 57, 50, 47, 46, 44, 37, 21, 3, -11, + -20, -23, -25, -30, -33, -36, -36, -34, -31, -27, -22, -21, -22, -21, -18, -21, + -24, -27, -31, -33, -32, -27, -21, -14, -13, -17, -17, -10, 0, 10, 15, 16, + 14, 8, 6, 10, 16, 25, 34, 39, 43, 47, 53, 62, 72, 82, 89, 92, + 90, 84, 79, 77, 77, 76, 67, 54, 42, 33, 26, 18, 5, -11, -27, -41, + -53, -65, -73, -77, -79, -81, -86, -93, -102, -110, -116, -118, -120, -124, -127, -128, + -128, -126, -122, -116, -107, -96, -85, -78, -72, -64, -54, -45, -39, -40, -46, -49, + -49, -47, -45, -44, -45, -45, -44, -42, -38, -33, -29, -26, -23, -20, -18, -14, + -11, -8, -5, -2, 2, 7, 11, 10, 8, 7, 9, 16, 22, 26, 28, 31, + 34, 39, 44, 49, 53, 57, 60, 62, 63, 63, 65, 66, 63, 57, 51, 46, + 46, 50, 53, 54, 55, 54, 55, 57, 63, 69, 73, 75, 73, 69, 66, 64, + 65, 63, 55, 43, 30, 18, 11, 3, -6, -15, -23, -29, -32, -32, -28, -22, + -16, -13, -16, -16, -11, -2, 9, 15, 1, 0, 0, 0, -1, 0, -3, 0, + -1, 0, -18, 21, -22, 23, -41, 20, 84, -39, 50, -61, 26, -126, -19, -37, + 15, 2, 70, -33, 127, -55, 117, -73, 15, -45, -50, 8, -11, 23, 33, 1, + 26, -67, 26, -25, 14, -45, 57, -124, 12, -4, -23, 107, -54, 127, -49, 43, + 27, -59, -30, 15, -128, 5, -128, 86, -39, 82, 12, 62, 9, 51, -59, 53, + -95, 67, -92, 68, -28, 94, 21, 47, -11, -1, -41, 0, -25, -9, 18, -68, + 15, -27, 49, -27, 103, -4, 3, -36, 58, -98, 56, -116, -31, -123, 25, -58, + 89, -21, 110, -25, 73, -28, 39, -21, 35, -40, 37, -20, 50, 55, 51, 6, + 1, -47, -11, -32, -23, 38, -67, 3, -54, 34, -55, 79, 1, 32, -61, 89, + -86, 53, -67, -10, -128, -6, -68, 51, -4, 82, 15, 83, -16, 63, -24, 55, + -29, 8, 0, 6, 11, 54, 14, 16, -39, -9, -12, -47, 37, -40, -22, -60, + 21, -76, 51, -17, 74, -63, 98, -36, 44, -33, 24, -113, -37, -89, 20, -30, + 67, 18, 87, 0, 67, -6, 38, 1, -2, -18, -5, -20, 32, 17, 21, -8, + -30, 15, -47, 11, -17, 11, -97, 43, -87, 27, -36, 91, -41, 66, 3, 44, + -28, 55, -74, -37, -92, -21, -37, 33, -1, 75, 22, 36, 14, 26, 8, 8, + -12, -7, -21, -1, 27, 11, 21, -30, 21, -37, -3, -13, 23, -27, -32, -10, + -23, -44, 56, -1, 43, -12, 76, -29, 48, -9, -25, -71, -70, -48, -20, 2, + 9, 56, 8, 56, -10, 52, -12, 31, -29, 27, -60, 62, -42, 83, -45, 30, + -24, 4, -26, 33, -23, 5, -18, -25, -53, -7, -6, -6, 19, 16, 31, 3, + 58, -14, 0, -64, -33, -58, -8, -43, 42, -18, 57, -9, 54, 1, 47, -3, + 36, -18, 3, 4, 6, 2, -17, 8, -14, -27, 35, 2, -3, 1, -8, -43, + -34, -1, -22, 12, 2, 37, -6, 53, 14, 16, -43, -22, -75, -2, -67, 23, + -24, 39, -3, 39, 6, 44, 9, 37, 5, 1, 3, 5, 12, -18, 0, 0, + -31, 5, 23, 1, -3, 10, -20, -48, -6, -30, 7, -18, 35, -4, 32, 21, + 39, -26, -1, -75, -9, -65, -3, -28, 20, -5, 32, 5, 36, 20, 30, 30, + 3, 10, -1, 16, -10, -7, -1, -17, -23, 18, 14, -3, 8, 9, -45, -14, + -35, -1, -27, 18, -2, 29, 1, 61, -14, 20, -56, -19, -51, -22, -38, 9, + -14, 22, 5, 24, 27, 23, 41, 13, 20, -7, 23, -2, -8, -2, -9, -26, + -6, 14, 11, -11, 37, -33, -12, -38, -6, -33, 7, -14, 30, -12, 55, 4, + 33, -32, -14, -45, -22, -43, -7, -15, 18, 18, 33, 17, 41, 22, 15, 14, + 8, -24, -16, -18, -16, -7, 6, 16, -2, 8, -14, -6, -23, 0, -22, 1, + -23, 21, 4, 24, -1, 9, -9, -11, -14, -13, -16, -14, -15, -12, -16, -5, + 8, 28, 25, 28, 34, 27, 15, 16, 2, -20, -22, -20, -15, -8, 10, 11, + 7, -3, -5, -16, -10, -13, -5, -16, -5, 4, 17, 13, 6, 1, -9, -1, + -2, -3, -4, -4, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -6, + -6, -6, -6, -6, -5, -3, -3, -5, -5, -5, -7, -8, -5, 4, 5, 13, + 12, -12, -5, 10, 5, 4, 0, 3, 26, 33, 10, -15, -69, -89, -25, 25, + 58, 70, 22, -41, -62, -31, 18, 17, -17, -12, -9, 20, 99, 96, 0, -88, + -123, -69, 61, 116, 54, -11, -45, -28, 40, 38, -42, -59, -53, -31, 63, 78, + -9, -65, -83, -59, 48, 110, 50, -11, -51, -54, 41, 96, 9, -87, -119, -77, + 42, 118, 67, -18, -57, -46, 24, 89, 81, 22, -43, -77, -65, -41, -23, -3, + 4, 8, -13, -54, -52, -21, 30, 89, 86, 8, -49, -76, -56, 30, 55, 52, + 47, -7, -45, -49, -48, -10, 68, 74, 43, 22, -27, -25, 12, 20, -5, -43, + -69, -46, 21, 53, 51, 38, -8, -32, 6, 20, -1, -19, -56, -67, -26, 27, + 76, 95, 23, -64, -60, -15, 33, 39, -8, -37, -24, -7, 7, 4, -25, -23, + -10, -14, -7, -5, -12, 2, 28, 31, 37, 21, -18, -16, -4, -22, -37, -46, + -56, -8, 58, 64, 53, 31, -9, -9, -2, -57, -85, -52, -13, 59, 92, 21, + -42, -47, -33, 27, 75, 27, -22, -38, -44, 18, 77, 32, -21, -46, -50, 34, + 89, 22, -37, -60, -56, 31, 95, 36, -27, -57, -82, -15, 53, 15, -13, -25, + -44, 14, 66, 14, -32, -53, -62, 25, 96, 50, 3, -32, -56, 25, 98, 51, + -9, -56, -78, 7, 92, 71, 28, -31, -92, -42, 28, 20, 24, 8, -34, 22, + 70, 18, -17, -53, -88, -20, 39, 7, -2, -8, -28, 35, 80, 19, -23, -55, + -93, -22, 63, 54, 47, 19, -52, -35, 2, -36, -32, -18, -49, -9, 41, 15, + 26, 34, -22, -6, 31, 1, 8, 9, -43, -15, 30, -3, -1, -7, -73, -48, + 6, -14, 5, 13, -47, -30, 12, -13, 6, 18, -37, -13, 39, 27, 45, 38, + -37, -32, 12, 3, 32, 46, -10, 6, 48, 16, 15, 15, -32, -2, 47, 24, + 26, 18, -51, -51, -15, -29, -1, 19, -28, -15, 21, 2, 18, 22, -34, -24, + 13, -3, 15, 14, -45, -34, 7, 10, 38, 31, -34, -30, 4, 5, 43, 61, + 13, 4, 6, -22, 4, 24, -13, -13, -10, -34, 0, 23, -16, -16, -13, -42, + -18, -4, -36, -17, 5, -10, 14, 22, -21, -22, -16, -37, -6, 20, -2, 17, + 36, 19, 43, 43, -9, -15, -12, -29, 6, 31, 6, 10, 7, -23, -2, 9, + -23, -15, -10, -26, 3, 20, -5, 1, 0, -22, 5, 22, -6, -8, -16, -37, + -5, 20, 2, 11, 6, -19, 11, 33, 12, 20, 16, -7, 20, 35, 11, 11, + -3, -28, 2, 19, -1, 3, -6, -29, -5, 2, -25, -17, -12, -16, 22, 34, + 3, -4, -21, -36, 4, 26, 8, -1, -30, -54, -23, -3, -11, 0, -12, -27, + 7, 24, 13, 19, -1, -21, 10, 27, 14, 17, 0, -14, 18, 33, 19, 14, + -17, -41, -10, 9, 2, 7, -14, -30, 4, 20, 9, 9, -15, -35, -3, 16, + 9, 0, -1, -2, -3, 4, 7, 4, -2, -3, 0, 3, -1, -1, 4, 5, + -2, -13, -9, 1, 4, 2, 1, 2, 2, -2, -8, -4, 0, 4, 4, -3, + -4, -3, 1, 2, -1, 3, 14, 1, -7, -12, -4, -2, 1, 1, 9, 5, + -6, -5, -2, -1, -1, 1, 14, 6, -6, -7, 3, 8, -2, -4, 13, 12, + -10, -17, -10, -5, -4, 2, 3, 7, -6, -6, -1, -1, -4, 1, 11, 6, + -6, -9, 10, 11, 3, 1, 14, 15, -12, -20, -12, -9, -15, -1, 7, 2, + -16, -7, 6, 0, -2, 10, 26, 17, -6, -11, 24, 21, 1, 0, 18, 15, + -17, -31, -28, -23, -14, 0, -4, 0, -16, -8, 8, -4, -3, 7, 15, 5, + -3, -3, 26, 25, 12, 8, 28, 17, -15, -28, -18, -17, -18, -7, -3, -7, + -20, 0, 7, 1, -9, 6, 9, -4, -9, 2, 15, 24, 34, 31, 10, -4, + -15, -29, -17, -21, -41, -40, -5, 19, -20, 3, 11, 33, 28, 21, 18, 15, + 16, 3, -1, 18, 17, 15, 1, -15, -10, -5, -14, -42, -48, -43, -26, 4, + -29, -14, -9, 32, 20, 12, 15, 21, 39, 24, 8, 26, 33, 6, -3, 0, + 1, -7, -16, -41, -44, -51, -34, -3, -6, -6, -19, 26, 10, 15, 35, 46, + 32, 20, 16, 23, 38, 15, -4, -10, 17, -6, -41, -48, -53, -70, -52, -9, + -9, -22, -15, 19, 24, 22, 30, 49, 34, 10, 1, 15, 33, 15, 1, 17, + 46, 12, -38, -59, -50, -57, -46, -13, -16, -30, -24, 26, 37, 33, 30, 45, + 40, 2, -11, 17, 41, 24, -4, 16, 48, 15, -38, -67, -64, -65, -46, -18, + -18, -35, -32, 35, 39, 37, 21, 45, 42, -2, -19, 14, 37, 22, 7, 24, + 40, 13, -42, -68, -63, -63, -38, -6, -12, -34, -25, 39, 43, 39, 17, 47, + 45, 3, -19, 21, 45, 25, 2, 21, 31, 0, -45, -71, -78, -83, -48, 2, + 7, -27, -32, 34, 45, 49, 23, 44, 36, 5, -5, 38, 60, 27, -13, 21, + 42, -13, -69, -81, -86, -79, -38, -9, -11, -41, -36, 38, 56, 45, 10, 43, + 43, 10, -6, 36, 57, 41, 10, 36, 46, -16, -67, -66, -71, -80, -44, -8, + -5, -29, -27, 30, 43, 46, 20, 52, 39, -9, -21, 40, 68, 42, -1, 20, + 32, -14, -70, -86, -94, -90, -45, -2, 0, -31, -17, 36, 47, 46, 18, 44, + 29, -2, -11, 46, 74, 51, 14, 36, 46, -15, -78, -87, -91, -89, -46, -12, + -11, -28, -5, 41, 46, 40, 17, 51, 33, -6, -13, 49, 75, 52, 15, 30, + 34, -21, -79, -88, -93, -88, -42, -9, -4, -25, -3, 36, 40, 34, 16, 44, + 23, -8, -10, 52, 83, 55, 17, 38, 31, -31, -82, -91, -93, -82, -39, -16, + -10, -25, 5, 33, 42, 32, 20, 54, 25, -9, -3, 59, 85, 63, 24, 37, + 24, -39, -86, -92, -97, -80, -34, -17, -15, -24, 10, 35, 45, 32, 16, 45, + 12, -23, -2, 62, 78, 53, 21, 37, 26, -39, -91, -95, -96, -77, -29, -16, + -16, -25, 10, -1, 0, 3, 21, -26, 18, -30, 32, -19, -15, -27, 2, 0, + 103, -84, -53, -52, 79, 51, 36, -69, -31, 48, 71, 33, -74, -64, 10, 51, + 49, -68, -91, -16, 30, 33, -31, -58, -42, 14, 24, -25, 23, -71, 79, -22, + 123, -74, 28, 28, 115, 99, -7, 9, -15, 72, 1, 16, -47, -5, -71, -18, + -75, -26, -71, -28, -56, -24, -57, -19, -33, -5, 7, -3, 14, -8, 82, 100, + 23, -32, -15, 80, 98, 68, -30, -21, 24, 71, 28, -41, -96, -22, 32, 37, + -57, -110, -67, 28, 35, -22, -112, -79, 13, 70, 27, -55, -63, 31, 95, 86, + -4, -40, 29, 110, 110, 28, -50, -12, 66, 80, 14, -87, -81, -7, 36, -5, + -95, -118, -42, 26, 8, -69, -121, -48, 37, 60, -6, -68, -29, 67, 104, 61, + -24, -17, 70, 123, 92, -5, -43, 23, 82, 67, -28, -96, -54, 18, 30, -39, + -115, -96, -7, 25, -13, -99, -101, -13, 52, 42, -35, -62, 9, 88, 93, 28, + -32, 15, 97, 118, 58, -29, -24, 51, 82, 39, -61, -88, -26, 28, 9, -70, + -117, -63, 7, 14, -46, -109, -71, 15, 55, 16, -51, -42, 43, 94, 75, 2, + -21, 48, 107, 101, 23, -36, 4, 65, 70, 1, -81, -69, -3, 26, -19, -94, + -106, -32, 14, -3, -74, -103, -37, 34, 46, -10, -56, -12, 66, 91, 49, -15, + 1, 74, 111, 76, -4, -28, 31, 72, 50, -33, -85, -43, 11, 15, -46, -106, + -80, -11, 13, -26, -92, -84, -8, 44, 29, -30, -48, 19, 80, 81, 26, -18, + 27, 91, 103, 49, -22, -10, 48, 68, 22, -60, -75, -22, 17, -5, -71, -105, + -54, 3, 3, -49, -98, -58, 14, 44, 11, -44, -27, 45, 85, 65, 5, -8, + 53, 100, 87, 21, -26, 11, 60, 56, -6, -74, -58, -4, 13, -25, -90, -91, + -29, 7, -12, -72, -90, -29, 32, 37, -10, -46, -2, 66, 83, 47, -8, 10, + 74, 101, 68, -3, -19, 31, 62, 38, -36, -77, -40, 6, 4, -49, -100, -72, + -12, 3, -31, -86, -73, -4, 37, 25, -28, -36, 25, 75, 74, 25, -9, 34, + 88, 94, 43, -16, -4, 47, 58, 15, -57, -69, -22, 6, -12, -73, -96, -50, + -4, -7, -53, -89, -49, 13, 36, 5, -37, -17, 47, 77, 59, 9, 2, 58, + 92, 79, 19, -17, 16, 54, 45, -13, -69, -52, -8, 3, -33, -85, -82, -29, + -2, -20, -68, -79, -23, 24, 29, -11, -34, 7, 61, 73, 41, 0, 22, 73, + 90, 58, 1, -9, 32, 52, 26, -36, -69, -35, -3, -7, -53, -90, -63, -16, + -7, -36, -78, -60, -4, 29, 16, -22, -23, 29, 68, 64, 26, 2, 42, 80, + 81, 38, -8, 5, 42, 44, 4, -53, -57, -21, -2, -22, -69, -83, -43, -10, + -15, -51, -77, -38, 11, 27, 3, -27, -5, 46, 68, 52, 13, 15, 58, 83, + 68, 19, -8, 21, 46, 32, -16, -60, -44, -12, -6, -36, -76, -74, -34, -10, + -20, -57, -73, -33, 12, 27, 3, -1, -6, -11, -3, 4, 0, -7, -8, 1, + 21, 14, 28, 33, 25, -1, 7, 4, -13, -21, -44, -29, -17, -31, -32, 2, + 0, -20, 4, 3, 4, 0, -2, -5, -4, -14, 3, 14, 9, 28, 34, 54, + 43, 54, 39, 19, 17, -1, 5, -23, -31, -25, -35, -46, -60, -29, -29, -13, + -37, -22, -16, -20, -27, -21, -6, -16, 8, -5, 15, 26, 69, 65, 74, 85, + 81, 76, 51, 22, -10, -10, -19, -3, -39, -73, -55, -36, -18, -45, -49, -45, + -52, -47, -74, -73, -56, -31, -15, -16, -5, 18, 65, 86, 108, 94, 97, 90, + 79, 54, 30, 19, 10, 25, -16, -34, -37, -9, -16, -35, -44, -60, -60, -50, + -62, -70, -66, -44, -34, -34, -29, -10, 23, 61, 85, 79, 75, 70, 61, 41, + 31, 7, 8, 3, -22, -42, -28, 0, -13, -29, -39, -52, -56, -55, -58, -60, + -57, -41, -35, -37, -19, 5, 35, 71, 87, 85, 97, 112, 97, 71, 56, 52, + 53, 43, 18, -7, -3, 10, 0, -17, -39, -55, -58, -64, -80, -106, -121, -112, + -110, -113, -105, -82, -51, -8, 16, 20, 45, 66, 66, 49, 46, 59, 75, 78, + 63, 62, 74, 80, 80, 69, 51, 27, 11, 0, -14, -40, -53, -48, -55, -68, + -71, -56, -34, -1, 14, 24, 49, 62, 59, 42, 34, 43, 47, 43, 26, 30, + 33, 38, 26, 4, -17, -41, -66, -81, -92, -112, -120, -115, -116, -128, -125, -103, + -71, -36, -11, 9, 33, 56, 59, 54, 61, 67, 77, 77, 77, 79, 74, 75, + 73, 55, 30, 10, -21, -38, -46, -61, -70, -67, -70, -81, -77, -64, -45, -23, + -4, 10, 30, 44, 44, 39, 42, 48, 51, 50, 51, 58, 58, 65, 65, 47, + 29, 12, -14, -31, -41, -53, -63, -60, -62, -64, -58, -44, -26, -11, 1, 10, + 20, 22, 17, 9, 5, 6, 6, 2, 4, 10, 10, 17, 19, 9, 7, -1, + -14, -18, -13, -14, -9, 1, 7, 12, 17, 23, 31, 35, 36, 35, 38, 31, + 21, 16, 3, 0, -8, -11, -11, -13, -19, -20, -23, -34, -39, -51, -69, -78, + -81, -83, -83, -78, -70, -60, -47, -34, -19, 2, 20, 39, 57, 60, 66, 67, + 63, 61, 53, 50, 51, 47, 37, 32, 23, 13, 6, -3, -17, -23, -28, -34, + -37, -35, -27, -15, -2, 4, 12, 23, 30, 44, 47, 43, 41, 35, 29, 22, + 15, 13, 14, 7, -1, -5, -11, -19, -20, -25, -37, -43, -41, -43, -47, -47, + -40, -29, -17, -7, 5, 13, 23, 38, 44, 37, 34, 31, 23, 17, 6, 1, + -2, -10, -20, -25, -35, -45, -50, -54, -64, -68, -65, -66, -65, -59, -47, -30, + -19, -7, 5, 14, 28, 48, 62, 66, 72, 75, 78, 76, 67, 60, 56, 46, + 32, 20, 9, -2, -10, -21, -35, -43, -44, -49, -56, -57, -51, -38, -25, -13, + -2, 9, 25, 42, 56, 59, 64, 65, 67, 65, 57, 52, 49, 41, 28, 18, + 8, -2, -10, 0, 8, 13, 21, 20, 20, 17, 10, 8, -2, -6, -17, -21, + -29, -23, -25, -14, -7, -2, 7, 10, 20, 21, 22, 23, 19, 14, 9, -2, + -6, -18, -20, -28, -25, -23, -18, -10, -3, 5, 9, 22, 17, 28, 22, 21, + 17, 11, 2, -8, -18, -23, -27, -26, -24, -19, -13, -6, 3, 9, 17, 20, + 28, 24, 25, 21, 13, 6, -5, -14, -21, -29, -29, -30, -23, -19, -7, -1, + 10, 18, 25, 29, 27, 28, 20, 17, 5, -7, -13, -26, -29, -30, -30, -27, + -20, -12, 0, 11, 19, 25, 27, 30, 26, 28, 19, 11, -2, -12, -24, -30, + -35, -34, -30, -24, -14, -2, 9, 18, 23, 28, 26, 33, 31, 29, 24, 12, + 5, -12, -23, -30, -37, -36, -36, -26, -19, -5, 5, 19, 22, 32, 32, 36, + 35, 26, 21, 3, -6, -22, -34, -41, -44, -38, -31, -18, -6, 6, 15, 23, + 32, 33, 39, 34, 31, 23, 10, -2, -21, -32, -44, -47, -45, -37, -23, -12, + 6, 13, 28, 30, 38, 40, 40, 38, 23, 17, -6, -15, -35, -42, -50, -49, + -41, -31, -14, 0, 14, 26, 35, 42, 45, 45, 40, 27, 18, -4, -14, -33, + -42, -54, -52, -47, -36, -21, -5, 13, 24, 39, 43, 52, 47, 42, 36, 20, + 7, -15, -32, -45, -55, -56, -54, -43, -27, -8, 12, 26, 38, 45, 50, 51, + 48, 40, 27, 9, -11, -30, -46, -58, -62, -58, -49, -31, -11, 9, 24, 41, + 45, 54, 53, 54, 45, 30, 14, -10, -27, -48, -58, -67, -64, -56, -35, -15, + 6, 24, 37, 45, 54, 56, 56, 49, 39, 18, 0, -26, -45, -60, -74, -70, + -63, -41, -23, 4, 21, 39, 48, 53, 61, 58, 59, 43, 29, 3, -20, -46, + -64, -77, -77, -69, -50, -27, 0, 20, 36, 49, 56, 64, 64, 63, 51, 34, + 6, -17, -46, -65, -79, -83, -76, -58, -33, -6, 17, 38, 49, 60, 67, 68, + 66, 53, 37, 13, -13, -38, -65, -79, -90, -82, -68, -41, -15, 14, 36, 52, + 63, 70, 73, 69, 62, 44, 19, -8, -38, -63, -83, -93, -90, -77, -49, -20, + 12, 34, 54, 65, 72, 75, 76, 65, 51, 26, -1, -33, -62, -86, -98, -96, + -86, -58, -29, 6, 32, 54, 66, 73, 79, 76, 73, 58, 36, 4, -27, -60, + -85, -101, -104, -92, -70, -36, -1, 31, 53, 70, 75, 81, 80, 78, 65, 41, + 15, -24, -56, -84, -105, -109, -101, -79, -46, -7, 25, 56, 65, 77, 82, 85, + 83, 69, 51, 19, -14, -50, -83, -103, -115, -107, -88, -55, -17, 21, 50, 67, + 81, 86, 89, 85, 79, 55, 28, -8, -46, -77, -103, -116, -117, -97, -67, -25, + 1, 39, 66, 81, 92, 96, 97, 90, 73, 45, 11, -27, -64, -97, -120, -128, + -117, -89, -49, -5, 35, 65, 81, 93, 98, 99, 91, 75, 46, 12, -27, 28, + -9, -42, -57, -50, -18, 33, 77, 77, 17, -64, -96, -55, 22, 73, 68, 17, + -43, -77, -67, -15, 59, 102, 79, 12, -48, -71, -57, -28, -3, 11, 10, -3, + -17, -4, 44, 88, 79, 10, -69, -103, -74, -6, 54, 75, 53, -4, -63, -80, + -38, 32, 73, 59, 7, -43, -67, -57, -18, 33, 71, 71, 24, -31, -47, -17, + 20, 23, -14, -58, -73, -47, 10, 73, 110, 93, 20, -62, -97, -68, -6, 43, + 54, 28, -13, -51, -65, -35, 26, 74, 69, 12, -50, -68, -37, 9, 37, 37, + 16, -12, -26, -7, 36, 65, 45, -19, -87, -112, -75, -7, 58, 97, 92, 41, + -30, -75, -62, -3, 49, 52, 7, -44, -63, -45, -6, 37, 60, 42, -5, -42, + -41, -3, 38, 41, 8, -33, -51, -38, 3, 54, 90, 79, 12, -76, -127, -106, + -29, 47, 78, 63, 23, -19, -36, -16, 24, 50, 35, -15, -59, -64, -27, 17, + 40, 35, 11, -20, -39, -26, 19, 63, 67, 14, -61, -97, -72, -5, 64, 101, + 87, 26, -49, -96, -86, -32, 24, 40, 17, -11, -17, -3, 24, 51, 55, 29, + -20, -66, -69, -23, 35, 55, 25, -26, -59, -55, -14, 44, 86, 80, 23, -56, + -105, -87, -19, 48, 79, 67, 27, -18, -46, -43, -14, 17, 16, -20, -54, -47, + 3, 59, 83, 66, 18, -35, -64, -54, -8, 44, 59, 18, -48, -87, -72, -16, + 49, 88, 84, 37, -31, -81, -79, -26, 33, 52, 29, -5, -19, -6, 20, 34, + 27, -5, -51, -84, -71, -9, 62, 95, 71, 12, -40, -58, -37, 8, 52, 63, + 22, -53, -103, -88, -23, 47, 80, 64, 24, -14, -33, -28, -3, 21, 18, -15, + -45, -39, 5, 57, 78, 54, -1, -60, -97, -89, -29, 50, 92, 67, 0, -53, + -57, -13, 38, 64, 52, 10, -44, -82, -76, -26, 28, 49, 32, 1, -14, -1, + 24, 40, 38, 9, -43, -87, -79, -13, 69, 110, 80, 4, -65, -90, -69, -21, + 32, 58, 39, -9, -48, -45, 0, 52, 69, 46, 5, -34, -57, -50, -14, 23, + 28, -8, -48, -48, 4, 71, 99, 69, 3, -63, -99, -88, -30, 46, 92, 78, + 16, -45, -66, -44, -6, 25, 34, 16, -24, -55, -43, 10, 67, 80, 37, -22, + -48, -29, 7, 30, 27, -5, -51, -84, -73, -11, 71, 116, 95, 27, -43, -84, + -84, -43, 18, 63, 60, 10, -44, -53, -9, 41, 49, 14, -31, -57, -50, -15, + 29, 61, 57, 14, -37, -51, -14, 38, 63, 47, -1, -61, -106, -105, -47, 44, + 115, 113, 42, -36, -64, -42, -2, 23, 20, -3, -28, -39, -21, 24, 64, 59, + 7, -48, -67, -47, -7, 36, 59, 47, 2, -55, -77, -31, 55, 111, 89, 7, + -75, -113, -96, -42, 21, 62, 64, 28, -13, -18, 17, 45, 28, -2, -7, -6, + -7, -7, -8, -8, -8, -8, -7, -6, -5, -4, -3, -3, -2, -2, -1, 0, + 1, 2, 4, 5, 6, 8, 9, 10, 11, 12, 13, 13, 14, 15, 16, 17, + 17, 17, 17, 17, 16, 16, 15, 15, 14, 14, 13, 12, 10, 10, 9, 8, + 7, 6, 5, 5, 4, 3, 2, 1, 0, -2, -3, -4, -5, -6, -7, -8, + -9, -10, -11, -12, -13, -13, -14, -14, -14, -14, -14, -15, -15, -15, -15, -16, + -16, -14, -14, -12, -10, -13, -10, -13, -7, -3, -5, -1, -1, -5, -5, 8, + 13, 10, 10, 15, 16, 17, 30, 34, 19, 17, 22, 29, 27, 22, 16, 1, + -3, 8, 18, 11, 6, 8, 8, 1, 6, 18, 5, -8, -4, 4, 5, 3, + 5, -3, -6, 12, 30, 23, 9, 5, 6, 9, 15, 27, 20, 2, 0, 10, + 17, 8, -1, -4, -8, -8, -3, -7, -19, -28, -24, -22, -31, -42, -47, -50, + -50, -42, -35, -35, -43, -41, -31, -27, -23, -17, -9, -7, 3, 26, 37, 38, + 37, 41, 39, 39, 49, 55, 50, 46, 53, 58, 51, 44, 36, 24, 9, 5, + 2, -12, -25, -28, -26, -33, -42, -44, -55, -66, -69, -62, -60, -65, -57, -42, + -33, -26, -15, -5, -6, 0, 15, 29, 34, 41, 55, 61, 62, 68, 71, 62, + 49, 49, 49, 39, 29, 24, 14, -2, -10, -16, -34, -56, -67, -70, -77, -83, + -85, -88, -93, -92, -79, -74, -78, -74, -61, -49, -41, -23, -9, -2, 11, 35, + 54, 56, 58, 64, 69, 73, 81, 91, 86, 77, 78, 77, 67, 50, 39, 24, + 6, -4, -10, -22, -41, -49, -52, -62, -73, -81, -87, -98, -97, -83, -74, -70, + -63, -46, -33, -23, -6, 9, 18, 26, 48, 69, 77, 85, 97, 106, 107, 111, + 114, 104, 89, 83, 84, 75, 60, 50, 34, 13, -5, -16, -34, -59, -74, -80, + -86, -95, -97, -96, -104, -104, -95, -86, -86, -82, -66, -49, -32, -11, 12, 26, + 36, 55, 73, 81, 84, 94, 104, 107, 114, 120, 116, 102, 92, 88, 73, 54, + 37, 21, 0, -16, -23, -37, -58, -76, -85, -94, -108, -114, -116, -120, -119, -106, + -89, -84, -78, -64, -49, -37, -21, 1, 13, 25, 46, 71, 88, 95, 105, 113, + 112, 113, 116, 112, 97, 91, 91, 83, 68, 51, 35, 11, -10, -23, -38, -60, + -80, -86, -93, -102, -107, -110, -116, -121, -114, -102, -98, -93, -77, -55, -38, -18, + 1, 13, 25, 46, 71, 88, 95, 105, 113, 112, 113, 116, 112, 97, 91, 91, + 83, 68, 51, 35, 11, -10, -23, -38, -60, -80, -86, -93, -102, -107, -110, -116, + -121, -114, -102, -98, -93, -77, -55, -38, -18, 1, -3, -7, -8, -3, 1, 0, + 3, -5, -9, -14, -15, -4, 0, 7, 12, 12, 11, 18, 16, 14, 14, 11, + 20, 14, 19, 7, 12, 8, 13, 8, 7, 9, 0, 9, -7, -4, -5, -8, + -7, -9, -7, -2, -7, -4, 1, 1, 0, -2, 3, 2, 1, 2, 1, -2, + -3, -7, -2, -2, -2, -5, -4, -4, -4, 3, 6, 8, 3, 0, -3, -2, + 3, 4, 3, 2, 2, -2, 1, 0, 2, 3, 9, 8, 2, -3, -4, -2, + 1, 4, 0, -2, 3, 1, 7, 1, -4, 0, 2, 3, 1, 1, 2, -5, + 3, -3, -4, -3, -8, 2, -7, 1, -3, -2, -5, -8, -7, -8, -7, -5, + -7, -4, -8, -10, -7, -8, -7, -5, 0, -2, 0, -2, -3, -3, -2, 0, + 1, 0, 1, 0, -3, -3, -5, -5, -9, -9, -13, -16, -21, -26, -25, -25, + -16, -16, -12, -13, -15, -9, 3, 25, 44, 66, 68, 66, 49, 17, 13, 18, + 41, 51, 40, 35, 25, 23, -2, -16, -28, -8, -4, -12, -18, -34, -29, -31, + -28, -18, -4, 2, 16, 13, 20, 9, 4, 2, -3, -4, -9, -9, -9, -8, + -9, -10, -13, -14, -15, -13, -4, 7, 13, 19, 18, 16, 9, 7, 4, 6, + 8, 7, 7, 3, -3, -15, -19, -24, -21, -16, -9, 0, 3, 7, 4, 4, + -3, -2, 6, 13, 20, 14, 16, 14, 11, 7, 0, -4, -3, -3, -7, -12, + -12, -9, -5, -5, -7, -9, -4, -2, -2, -2, -4, -9, -10, -13, -13, -14, + -15, -13, -9, -8, -9, -9, -7, -4, 2, 2, 6, 9, 8, 11, 9, 11, + 9, 8, 6, 0, -7, -13, -21, -29, -36, -45, -53, -63, -72, -73, -61, -41, + 0, 52, 98, 109, 81, 64, 54, 78, 77, 45, 39, 44, 25, 19, 6, -8, + 25, 30, 44, 62, 46, -20, -85, -89, -88, -47, -29, -30, 2, 11, 8, 12, + 24, 33, 29, 25, 22, 1, -15, -34, -37, -36, -41, -36, -28, -15, 2, 9, + 11, 14, 12, 8, 12, 17, 18, 19, 23, 20, 20, 20, 8, -5, -14, -15, + -15, -13, -13, -18, -19, -24, -29, -32, -31, -23, -12, -2, 12, 20, 23, 24, + 25, 20, 22, 18, 16, 14, 9, 7, 2, 1, -9, -10, -19, -15, -12, -13, + -8, -5, -4, -4, -7, -10, -12, -12, -16, -14, -8, -9, -13, -14, -18, -15, + -10, -5, -3, 3, 4, 6, 11, 13, 13, 16, 16, 16, 12, 6, -3, -10, + -16, -21, -28, -37, -48, -61, -77, -88, -87, -68, -34, 28, 92, 127, 99, 64, + 50, 72, 92, 55, 43, 51, 41, 32, 4, -8, -7, -17, -23, -31, -33, -35, + -32, -28, -23, -18, -12, -8, -4, -2, 0, 1, 2, 2, 3, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 4, 6, 7, 7, 7, 8, 9, 9, 8, + 8, 9, 11, 14, 18, 22, 27, 32, 33, 30, 21, 6, -12, -30, -45, -54, + -56, -51, -41, -29, -17, -9, -3, 0, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 3, 3, 3, 3, 3, 2, 3, 4, 5, 8, 9, 10, 9, 8, 7, + 7, 8, 10, 15, 20, 25, 30, 35, 39, 39, 32, 19, 0, -22, -42, -56, + -62, -61, -53, -40, -27, -15, -7, -3, -1, 0, 0, 0, 0, 2, 3, 4, + 5, 5, 5, 4, 2, 0, -1, 0, 2, 5, 8, 9, 10, 10, 9, 9, + 8, 9, 10, 14, 19, 24, 28, 32, 34, 38, 36, 29, 17, -5, -28, -49, + -61, -65, -61, -52, -39, -25, -14, -7, -3, -2, -1, -2, -1, 0, 2, 4, + 6, 7, 7, 5, 3, 0, -1, -1, 0, 3, 7, 11, 13, 14, 13, 12, + 10, 8, 8, 9, 12, 17, 22, 26, 29, 31, 33, 31, 26, 18, 3, -16, + -35, -50, -59, -61, -56, -46, -35, -23, -14, -6, -2, 0, 1, 2, 3, 4, + 4, 5, 5, 5, 4, 2, 1, -1, -1, 0, 2, 5, 9, 12, 13, 13, + 12, 11, 9, 7, 7, 8, 11, 15, 20, 24, 29, 33, 35, 34, 30, 21, + 4, -16, -37, -55, -66, -68, -63, -50, -35, -21, -9, -1, 4, 5, 5, 4, + 4, 3, 3, 3, 3, 2, 2, 1, 0, -1, -1, 1, 6, 10, 13, 15, + 15, 13, 11, 8, 5, 4, 4, 7, 11, 17, 22, 27, 32, 36, 39, 39, + 36, 24, 6, -20, -48, -70, -81, -79, -67, -48, -29, -12, -1, 5, 7, 7, + 4, 2, 1, 1, 2, 2, 3, 2, 2, -1, -2, -3, -3, -1, 3, 8, + 13, 16, 17, 16, 12, 8, 3, -1, -3, -2, 2, 11, 21, 29, 36, 38, + 39, 42, 48, 57, 52, 23, -27, -76, -107, -113, -98, -71, -42, -18, -1, 8, + 12, 13, 10, 7, 3, 1, 1, 2, 3, 2, 1, 0, -2, -3, -3, -1, + 2, 8, 13, 17, 18, 17, 12, 7, 1, -3, -4, -3, 20, 30, 38, 41, + 39, 38, 46, 65, 75, 45, -23, -89, -126, -127, -101, -64, -31, -7, 5, 11, + 13, 14, 13, 9, 4, 1, 0, 1, 2, 1, -1, -3, -4, -4, -2, 2, + 6, 10, 14, 18, 18, 15, 9, 1, -6, -10, -13, -10, -4, 7, 20, 0, + 14, 19, 23, 26, 28, 28, 26, 23, 18, 11, 3, -4, -10, -16, -21, -23, + -24, -22, -20, -16, -12, -8, -3, 3, 8, 13, 19, 23, 26, 27, 26, 23, + 17, 10, 4, -3, -9, -15, -20, -24, -25, -25, -22, -17, -11, -3, 3, 9, + 14, 18, 20, 22, 23, 23, 21, 17, 13, 6, 1, -6, -11, -15, -18, -20, + -19, -19, -17, -16, -13, -11, -8, -5, -1, 2, 5, 7, 9, 9, 8, 6, + 3, 0, -3, -7, -10, -14, -17, -19, -19, -18, -16, -12, -7, -2, 3, 8, + 13, 16, 18, 19, 17, 14, 8, -1, -11, -21, -31, -38, -41, -40, -34, -25, + -12, 2, 17, 32, 45, 56, 62, 65, 63, 58, 49, 38, 25, 10, -6, -18, + -28, -37, -44, -51, -59, -64, -64, -56, -40, -17, 7, 29, 46, 56, 58, 59, + 56, 51, 45, 33, 19, 4, -13, -26, -39, -49, -56, -59, -55, -46, -34, -19, + -4, 10, 21, 30, 40, 46, 51, 52, 49, 43, 31, 18, 5, -8, -16, -21, + -23, -26, -29, -35, -39, -42, -40, -34, -22, -11, 2, 11, 18, 21, 24, 23, + 22, 19, 14, 7, -3, -13, -21, -30, -39, -46, -50, -52, -49, -42, -31, -17, + -3, 12, 26, 39, 49, 57, 60, 58, 51, 39, 22, 1, -23, -47, -68, -82, + -89, -88, -77, -60, -37, -11, 16, 43, 65, 83, 94, 100, 101, 96, 87, 71, + 51, 29, 4, -18, -38, -58, -75, -91, -104, -109, -105, -87, -61, -27, 8, 39, + 67, 87, 97, 97, 88, 71, 54, 36, 16, -2, -23, -42, -57, -70, -75, -75, + -71, -60, -43, -23, -1, 18, 31, 47, 57, 66, 71, 68, 61, 49, 32, 17, + 1, -11, -22, -33, -41, -47, -54, -59, -63, -62, -57, -46, -30, -12, 1, 17, + 30, 41, 49, 50, 47, 40, 29, 17, 3, -14, -30, -46, -60, -70, -76, -77, + -73, -63, -48, -28, -4, 20, 44, 65, 81, 91, 93, 88, 77, 60, 37, 11, + -19, -49, -76, -97, -109, -110, -100, -81, -56, -25, 7, 38, 67, 91, 109, 121, + 127, 126, 116, 96, 68, 38, 8, -18, -43, -68, -90, -110, -124, -127, -116, -91, + -59, -22, 14, 47, 77, 98, 107, 105, 93, 74, 54, 33, 13, -6, -26, -45, + -60, -71, -78, -79, -74, -61, -42, -21, 1, 18, 33, 49, 60, 68, 73, 70, + 62, 48, 32, 15, 0, -13, -24, -34, -42, -48, -55, -61, -65, -65, -60, -48, + -32, -15, 2, 19, 32, 43, 50, 51, 47, 40, 28, 16, 1, -14, 2, -2, + 2, -5, -3, -1, 0, -4, -4, -6, -4, -6, -4, -4, -7, -6, -7, -6, + -1, 0, 3, 13, 14, 16, 12, 13, 2, 1, 0, -1, -1, -1, -2, -2, + -2, -3, -3, -4, -8, -4, -4, -5, -5, -5, -7, -9, -12, -8, -14, -11, + -14, -18, -8, 1, 31, 71, 68, 24, -5, -11, -7, -5, -5, -5, -3, -2, + -5, -5, -9, -8, -7, -7, -9, -12, -11, -17, -14, -16, -15, -20, -26, -30, + -27, -15, 16, 51, 87, 101, 70, 8, -18, -11, -14, -7, -7, -1, -2, -5, + -7, -12, -14, -10, -10, -13, -14, -13, -16, -16, -17, -18, -35, -31, -30, -34, + -9, 16, 56, 84, 89, 60, 30, 5, -7, -5, -8, -3, -4, -4, -6, -12, + -14, -13, -10, -12, -12, -9, -10, -8, -12, -13, -15, -19, -23, -26, -33, -29, + -28, -9, 12, 43, 71, 88, 72, 48, 29, -2, -16, -19, -12, -12, -12, -7, + -11, -10, -10, -10, -11, -13, -15, -18, -19, -17, -16, -15, -13, -12, -13, -9, + -13, -17, -21, -18, 2, 34, 59, 87, 92, 98, 38, -30, -24, -27, -18, -16, + -11, -11, -13, -15, -12, -14, -15, -18, -17, -20, -18, -15, -10, -7, -3, -1, + 2, -8, -11, -22, -22, -20, 7, 31, 61, 97, 106, 43, -23, -28, -25, -20, + -12, -7, -5, -7, -10, -13, -13, -13, -11, -14, -15, -15, -12, -8, -7, -4, + -2, -4, -10, -15, -19, -26, -10, 12, 42, 72, 101, 90, 20, -25, -27, -22, + -18, -10, -6, -9, -11, -16, -17, -16, -14, -10, -8, -9, -9, -9, -9, -9, + -8, -5, -3, -6, -10, -17, -24, -21, 4, 30, 61, 84, 96, 79, -16, -38, + -27, -26, -17, -12, -8, -12, -13, -14, -14, -11, -8, -4, -4, -7, -9, -8, + -10, -12, -8, -5, -4, -7, -10, -18, -24, -11, 14, 42, 70, 79, 93, 36, + -32, -26, -28, -19, -15, -9, -9, -13, -16, -14, -12, -8, -5, -3, -7, -9, + -9, -9, -11, -8, -5, -1, -6, -9, -15, -24, -23, 6, 28, 63, 86, 127, + 37, -45, -27, -28, -26, -19, -4, -5, -8, -11, -12, -14, -12, -8, -4, -8, + -8, -10, -8, -13, -8, -8, -3, -8, -8, -16, -23, -17, 7, 34, 69, 83, + 113, 37, -50, -28, -25, -22, -16, 0, -3, -8, -12, -12, -14, -14, -10, -5, + -7, -6, -9, -9, -13, -9, -10, -7, -9, -9, -15, -20, -14, 8, 33, 64, + 81, 90, 57, -29, -28, 0, -4, 10, 10, 11, -15, 4, -1, 3, -11, 11, + 2, -12, 3, 18, -10, -62, 89, -16, -95, 118, -128, 122, -128, 112, -100, 109, + -121, 120, -104, 58, 10, -88, 127, -102, 6, 98, -126, 35, 89, -111, -7, 112, + -53, -94, 92, 64, -106, -53, 109, 52, -100, -75, 86, 95, -45, -119, -12, 111, + 74, -58, -118, -27, 97, 100, -4, -107, -95, 17, 109, 92, -4, -99, -109, -26, + 78, 115, 66, -27, -104, -109, -41, 55, 112, 98, 32, -53, -109, -105, -44, 41, + 102, 109, 67, -4, -74, -112, -102, -47, 27, 88, 112, 93, 45, -19, -78, -110, + -105, -65, -4, 59, 101, 110, 87, 43, -13, -67, -103, -111, -89, -44, 13, 65, + 100, 109, 93, 59, 14, -36, -78, -104, -108, -90, -53, -6, 43, 83, 104, 106, + 88, 57, 17, -27, -66, -95, -108, -102, -80, -44, -2, 41, 77, 99, 106, 98, + 77, 46, 10, -29, -64, -91, -105, -105, -91, -64, -29, 10, 48, 78, 98, 105, + 100, 84, 59, 30, -3, -36, -65, -88, -101, -105, -99, -83, -60, -32, -1, 30, + 58, 80, 96, 103, 102, 94, 80, 62, 40, 16, -10, -35, -58, -78, -92, -101, + -104, -100, -91, -77, -58, -36, -13, 12, 36, 57, 75, 89, 98, 102, 102, 97, + 88, 76, 61, 44, 25, 5, -15, -35, -54, -70, -84, -94, -101, -104, -103, -98, + -89, -77, -63, -46, -27, -8, 12, 31, 49, 65, 79, 90, 97, 102, 104, 102, + 97, 90, 81, 70, 57, 42, 27, 10, -7, -24, -40, -56, -70, -81, -91, -99, + -103, -105, -105, -101, -95, -87, -76, -63, -49, -34, -18, -1, 16, 32, 48, 62, + 74, 85, 93, 100, 104, 105, 105, 102, 97, 90, 82, 72, 61, 48, 35, 21, + 6, -9, -24, -38, -52, -65, -76, -86, -94, -101, -105, -108, -108, -106, -102, -96, + -87, -78, -66, -54, -40, -26, -11, 4, 19, 34, 48, 61, 73, 83, 92, 99, + 104, 107, 108, 108, 105, 101, 96, 89, 80, 70, 60, 48, 36, 22, 9, -5, + -19, -33, -46, -58, -69, -80, -89, -96, -102, -107, -109, -110, -110, -107, -102, -97, + -89, -80, -70, -59, -47, -33, -20, -6, 7, 19, 30, 41, 50, 58, 65, 71, + 75, 78, 79, 80, 79, 77, 74, 70, 65, 60, 54, 48, 42, 36, 29, 22, + 16, 10, 4, -2, -7, -12, -16, -19, -22, -24, -26, -27, -27, -27, -26, -25, + -23, -22, -19, -17, -14, -12, -10, -1, -1, -4, -9, -9, -7, -6, -7, -3, + 4, 8, 10, 11, 13, 10, 4, -3, -10, -15, -13, -9, -10, -11, -5, 4, + 12, 14, 12, 13, 14, 9, 1, -8, -15, -21, -23, -22, -13, -3, 7, 17, + 24, 27, 19, 11, 16, 15, -5, -24, -29, -23, -27, -32, -21, 5, 18, 20, + 21, 24, 24, 15, 11, 8, -6, -30, -31, -19, -17, -24, -14, 2, 17, 15, + 12, 17, 16, 19, 8, -5, -2, -1, -17, -17, -3, 6, 5, -4, 0, 1, + -12, -9, 9, 11, -4, -14, -8, 9, -2, -21, -14, 4, 9, 9, 11, 18, + 21, 10, 8, 16, 10, 26, 35, 6, -14, -28, -25, -24, -55, -65, -33, -17, + 1, -6, -6, 8, 23, 33, 49, 37, 19, 16, 11, 24, 42, 17, -37, -36, + 3, 7, -23, -36, -9, 9, -12, -20, -8, -2, -4, -23, -17, -6, 0, 10, + 24, 24, 40, 46, 33, 39, 26, 5, 6, 9, -12, -26, -33, -42, -61, -52, + -43, -37, -21, -4, 7, 13, 28, 36, 31, 24, 1, -1, 20, 24, 23, 21, + 26, 27, 8, -32, -44, -3, 28, -1, -36, -30, -6, 13, -12, -34, -18, -6, + 9, 21, 25, 16, 10, 38, 62, 46, 17, -11, -7, 10, -8, -44, -53, -33, + -35, -38, -29, -27, -16, 0, 1, 9, 37, 50, 36, 2, -20, -12, 15, 21, + 24, 32, 29, 20, 23, 12, -8, -3, 4, -10, -5, 2, -19, -63, -70, -21, + 20, 41, 23, 33, 57, 61, 42, 21, 15, 10, -45, -82, -60, -29, -44, -77, + -50, -7, 4, -4, 10, 32, 56, 42, 1, -10, -18, 2, 22, 28, 33, 42, + 47, 43, 47, 11, -23, 0, 10, -40, -81, -70, -28, -29, -68, -29, 19, 6, + 7, 21, 40, 41, 32, 22, 28, 47, 69, 66, 35, 21, 15, -3, -20, -34, + -24, -6, -19, -59, -47, -42, -35, -28, 15, 45, 51, 66, 78, 83, 37, 1, + 13, 7, -51, -81, -92, -83, -87, -74, -58, -73, -51, 12, 35, 26, 35, 47, + 69, 70, 63, 65, 49, 47, 68, 73, 52, 33, 15, -12, -30, -50, -51, -46, + -45, -60, -50, -50, -50, -54, -24, 38, 78, 90, 106, 99, 40, -6, -11, -46, + -110, -127, -107, -76, -67, -53, -41, -41, -23, 14, 33, 27, 34, 49, 70, 71, + 66, 65, 51, 51, 69, 72, 52, 32, 10, -12, 0, -5, -2, -5, 2, -29, + 22, 0, -27, 67, -59, 45, -13, -37, 28, 65, -4, 6, 60, 5, 58, 44, + 60, 27, 43, 96, 71, 81, 48, 96, 70, 23, 90, 66, 80, 88, 40, 20, + 61, 64, 12, 36, 24, 4, 7, 5, -27, -38, -26, -33, -49, -50, -70, -69, + -93, -92, -94, -104, -104, -101, -110, -107, -111, -111, -126, -87, -119, -100, -94, -112, + -93, -93, -80, -81, -76, -58, -56, -70, -30, -21, -42, -13, -3, 2, 8, 20, + 28, 41, 45, 59, 62, 69, 84, 85, 90, 103, 109, 111, 118, 121, 121, 123, + 121, 122, 121, 122, 121, 122, 121, 121, 120, 121, 120, 121, 120, 121, 120, 120, + 119, 120, 119, 120, 118, 105, 106, 110, 83, 89, 92, 75, 67, 61, 57, 47, + 40, 33, 24, 17, 10, 3, -2, -10, -20, -31, -31, -37, -49, -50, -63, -66, + -69, -74, -79, -91, -89, -92, -95, -102, -106, -104, -107, -113, -113, -110, -113, -116, + -114, -115, -114, -115, -114, -113, -114, -113, -114, -113, -112, -113, -109, -105, -111, -106, + -107, -103, -100, -103, -99, -97, -98, -99, -92, -92, -93, -92, -92, -90, -88, -90, + -88, -86, -89, -85, -85, -87, -85, -85, -82, -83, -82, -80, -78, -79, -76, -74, + -73, -73, -69, -68, -66, -64, -65, -62, -58, -56, -56, -52, -50, -47, -43, -42, + -39, -35, -33, -31, -27, -23, -21, -16, -16, -8, -7, -3, 1, 0, 10, 15, + 15, 19, 26, 29, 30, 38, 41, 42, 47, 54, 54, 57, 63, 68, 69, 72, + 77, 78, 80, 85, 84, 86, 87, 86, 87, 86, 85, 86, 85, 84, 85, 84, + 83, 84, 83, 82, 82, 83, 82, 81, 82, 81, 80, 81, 80, 79, 80, 79, + 79, 78, 79, 78, 78, 77, 74, 70, 66, 64, 61, 55, 52, 49, 45, 40, + 35, 32, 29, 24, 19, 15, 12, 8, 4, 0, -4, -8, -11, -15, -17, -20, + -25, -26, -29, -32, -34, -37, -39, -41, -43, -45, -46, -48, -49, -50, -50, -52, + -52, -53, -52, -53, -54, -53, -53, -52, -52, -51, -50, -50, -49, -48, -48, -46, + -45, -44, -42, -41, -40, -39, -37, -35, -34, -32, -30, -28, -27, -24, -23, -22, + -20, -19, -17, -15, -14, -13, -12, -10, -9, -8, -8, -6, -6, -5, -4, -4, + -3, -3, -2, -2, -1, -2, -1, -2, -1, -1, 0, -1, -1, 1, 0, 0, + -3, -1, 1, -4, -4, -3, -2, -5, -3, 0, -1, -1, -3, -1, 0, 2, + 0, -2, -5, 5, 4, 1, 7, 2, 2, 1, 8, 1, 6, 2, -4, 2, + 1, -4, 6, -8, -3, -7, -2, -6, -1, -9, 1, -2, -4, 1, 2, 1, + -2, 8, 2, 0, 14, 9, 10, 5, 3, 5, 6, 4, 3, -8, -2, -4, + -10, -1, -5, -3, -4, -6, -13, -5, -4, -4, -3, 2, -13, -6, 3, 6, + 6, 7, 1, 1, 6, 6, 16, 13, 9, 10, 9, 2, 7, 10, 4, -4, + -3, -17, -7, -6, -6, -10, -17, -17, -10, -11, -9, -5, -6, -8, 2, 1, + 8, 19, 15, 18, 24, 19, 16, 17, 19, 11, 7, 1, -5, -8, -9, -15, + -8, -9, -14, -20, -19, -9, -18, -10, -13, -23, -13, -12, -7, 0, -1, 5, + 16, 12, 28, 30, 32, 34, 34, 19, 24, 23, 16, 11, 5, -7, -19, -17, + -16, -21, -26, -23, -32, -31, -30, -25, -26, -24, -19, -13, -9, -1, 0, 4, + 6, 13, 15, 19, 17, 13, 8, 8, 8, 7, 0, -4, -8, -10, -7, -5, + -6, -6, -9, -12, -8, -10, -9, -9, -11, -13, -12, -9, -4, -1, 4, 9, + 19, 27, 31, 26, 16, 14, 16, 16, 12, 1, -8, -14, -11, -9, -6, -11, + -11, -12, -14, -10, -11, -13, -15, -19, -23, -19, -14, -8, -5, -1, 8, 34, + 62, 59, 12, 14, 32, 22, 6, 20, 6, -9, -54, -16, -1, -19, 7, -15, + -13, -12, -14, -15, -14, -22, -24, -30, -30, -20, -12, -6, 3, 26, 66, 88, + 39, 0, 47, 36, -2, 26, -23, 21, 13, -6, -60, -42, 6, -22, 4, -18, + -16, -4, -16, -19, -24, -39, -31, -25, -32, -26, -11, 12, 55, 104, 75, 10, + 35, 62, 9, 26, -16, -8, 19, 3, -9, -61, -46, 2, -26, -7, -16, -10, + 2, -7, -22, -23, -38, -40, -37, -44, -33, -8, 37, 101, 124, 36, -5, 89, + 20, 38, 5, -26, 3, 1, 5, -28, -65, -21, 1, -22, -12, -26, 1, -7, + -10, -24, -26, -33, -37, -48, -50, -36, 5, 63, 122, 109, 7, 35, 84, 5, + 59, -36, -4, -11, -1, -5, -40, -55, -4, -15, -21, -16, -22, 5, -10, -17, + -20, -27, -23, -44, -54, -62, -23, 29, 114, 127, 51, 7, -2, -4, -2, 4, + 11, 14, 10, 2, -7, -9, -9, -15, -16, -7, 3, 2, -10, -21, -17, 6, + 10, -8, -28, -11, 45, 66, 64, 47, 36, 49, 49, 27, 9, -12, -18, -25, + -30, -11, 0, -5, 0, -1, -18, -36, -33, -18, -10, -13, -31, -26, -25, -17, + 4, 28, 70, 89, 48, 9, -32, -58, -56, -70, -57, -17, -38, -48, -35, -32, + -7, 35, 38, 53, 62, 44, 33, 27, -6, -35, -52, -65, -54, -40, -43, -30, + -25, 2, 63, 54, 34, 17, 34, 70, 60, 8, -15, -3, 0, 39, 55, 35, + 39, 60, 75, 36, 20, -7, -25, -66, -110, -89, -89, -71, -36, -12, 9, 31, + 41, 54, 46, 45, 59, 41, 22, 3, -69, -110, -126, -116, -64, -15, 9, 29, + 33, 30, 56, 42, 12, 23, 6, -27, -36, -21, -22, -32, -21, -30, -29, -5, + 9, 16, 22, -9, -12, 31, 24, -17, -41, -23, 32, 32, 26, 34, 64, 66, + 109, 104, 51, 5, 12, 16, -36, -58, -59, -66, -63, -82, -64, -23, -9, 11, + 16, 20, 19, 13, 12, 33, 37, 41, 46, 28, 7, -58, -93, -79, -64, -33, + -1, 22, -4, 2, 19, 4, -7, -3, -3, 5, 1, -10, -3, 12, -6, -38, + -29, -17, -5, 11, 2, -33, -20, 44, 42, 20, -30, -24, 9, 44, 38, 20, + 36, 71, 61, 86, 72, 25, -8, 10, 17, -35, -54, -63, -67, -70, -78, -58, + -16, -7, 19, 22, 20, 21, 29, 21, 16, 35, 36, 16, -8, -27, -61, -58, + -67, -43, 3, 35, 38, -2, -2, 10, -9, -29, -14, -5, -1, -5, 2, 12, + -6, -32, -23, -22, -16, -5, 3, -9, -29, 27, 56, 39, 11, -27, -28, 23, + 34, 28, 18, 20, 62, 82, 71, 74, 24, -4, 16, 18, -39, -54, -65, -61, + -52, -64, -49, -11, -4, 12, 17, 16, 25, 24, 6, 23, 36, 18, 18, -1, + -42, -50, -90, -43, 3, 35, 38, -2, -2, 10, -9, -29, -14, -5, -1, -5, + 2, 12, -6, -32, -23, -22, -16, -5, 3, -9, -29, 27, 56, 39, 11, -27, + -28, 23, 34, 28, 18, 20, 62, 82, 71, 74, 24, -4, 16, 18, -39, -54, + -65, -61, -52, -64, -49, -11, -4, 12, 17, 16, 25, 24, 6, 23, 36, 18, + 18, -1, -42, -50, -90, -43, 0, 1, 6, -11, 19, -25, 24, -15, 11, -6, + 1, 9, -6, -3, 11, -18, 28, -23, 8, 6, -2, -1, 0, -5, 18, -23, + 24, -28, 27, -12, -1, -2, 6, 4, -14, 19, -29, 42, -40, 22, -6, -3, + 14, -16, 4, 8, -9, 13, -22, 17, 5, -24, 37, -34, 20, -4, -11, 19, + -20, 21, -16, 1, 17, -17, 5, -9, 25, -31, 31, -40, 32, -11, -7, 4, + -4, 13, -23, 29, -40, 51, -49, 20, 3, -20, 38, -47, 34, -21, 14, -9, + 4, -13, 20, -29, 37, -57, 59, -48, 23, -5, -7, 5, -6, -5, 13, -17, + 9, -4, -12, 22, -19, -8, 10, -5, -7, 8, -18, 19, -13, 5, -12, 6, + -10, 18, -40, 66, -91, 82, -56, 17, 19, -51, 56, -45, 30, -19, 5, -6, + 7, -9, -4, -2, -5, 13, -19, 1, 20, -28, 13, -6, 0, -17, 33, -48, + 38, -16, -20, 53, -75, 75, -61, 30, -12, -9, 2, 5, -9, -7, 15, -17, + 9, 4, -46, 70, -85, 86, -67, 29, 18, -60, 76, -70, 29, -8, -1, 1, + 14, -58, 93, -118, 127, -125, 85, -36, -2, 17, -39, 46, -61, 70, -99, 122, + -120, 56, 15, -85, 116, -101, 30, 43, -108, 127, -122, 72, -38, -3, 20, -31, + 29, -37, 42, -50, 63, -72, 40, -7, -46, 66, -82, 53, -25, 1, 1, -1, + -3, 3, -24, 24, -34, 27, -24, 36, -49, 37, -38, 35, -42, 13, -4, -14, + 14, -29, 42, -58, 58, -60, 41, -39, 27, -35, 27, -32, 25, -37, 43, -50, + 32, -20, -4, 4, -14, 16, -43, 66, -93, 79, -58, 27, -11, -21, 34, -40, + 24, -7, -25, 31, -29, 19, -18, -2, 1, -6, 4, -31, 47, -63, 62, -64, + 32, 2, -29, 23, -21, 19, -41, 59, -76, 62, -52, 26, -11, -1, -10, 6, + -10, -7, 17, -42, 34, -12, -34, 73, -106, 92, -61, 26, -24, 8, -7, -2, + 3, -24, 31, -44, 27, -9, -22, 38, -43, 15, -4, -3, -2, -12, 5, 1, + -7, 7, -25, 17, -17, 4, -15, 27, -40, 34, -18, 6, -13, 12, -3, -9, + -6, 8, -18, 18, -36, 54, -55, 30, -25, 26, -41, 38, -49, 48, -38, 8, + 16, -40, 47, -52, 34, -12, -4, 2, -13, 0, 1, 6, -11, 19, -25, 24, + -15, 11, -6, 1, 9, -6, -3, 11, -18, 28, -23, 8, 6, -2, -1, 0, + -5, 18, -23, 24, -28, 27, -12, -1, -2, 6, 4, -14, 19, -29, 42, -40, + 22, -6, -3, 14, -16, 4, 8, -9, 13, -22, 17, 5, -24, 37, -34, 20, + -4, -11, 19, -20, 21, -16, 1, 17, -17, 5, -9, 25, -31, 31, -40, 32, + -11, -7, 4, -4, 13, -23, 29, -40, 51, -49, 20, 3, -20, 38, -47, 34, + -21, 14, -9, 4, -13, 20, -29, 37, -57, 59, -48, 23, -5, -7, 5, -6, + -5, 13, -17, 9, -4, -12, 22, -19, -8, 10, -5, -7, 8, -18, 19, -13, + 5, -12, 6, -10, 18, -40, 66, -91, 82, -56, 17, 19, -51, 56, -45, 30, + -19, 5, -6, 7, -9, -4, -2, -5, 13, -19, 1, 20, -28, 13, -6, 0, + -17, 33, -48, 38, -16, -20, 53, -75, 75, -61, 30, -12, -9, 2, 5, -9, + -7, 15, -17, 9, 4, -46, 70, -85, 86, -67, 29, 18, -60, 76, -70, 29, + -8, -1, 1, 14, -58, 93, -118, 127, -125, 85, -36, -2, 17, -39, 46, -61, + 70, -99, 122, -120, 56, 15, -85, 116, -101, 30, 43, -108, 127, -122, 72, -38, + -3, 20, -31, 29, -37, 42, -50, 63, -72, 40, -7, -46, 66, -82, 53, -25, + 1, 1, -1, -3, 3, -24, 24, -34, 27, -24, 36, -49, 37, -38, 35, -42, + 13, -4, -14, 14, -29, 42, -58, 58, -60, 41, -39, 27, -35, 27, -32, 25, + -37, 43, -50, 32, -20, -4, 4, -14, 16, -43, 66, -93, 79, -58, 27, -11, + -21, 34, -40, 24, -7, -25, 31, -29, 19, -18, -2, 1, -6, 4, -31, 47, + -63, 62, -64, 32, 2, -29, 23, -21, 19, -41, 59, -76, 62, -52, 26, -11, + -1, -10, 6, -10, -7, 17, -42, 34, -12, -34, 73, -106, 92, -61, 26, -24, + 8, -7, -2, 3, -24, 31, -44, 27, -9, -22, 38, -43, 15, -4, -3, -2, + -12, 5, 1, -7, 7, -25, 17, -17, 4, -15, 27, -40, 34, -18, 6, -13, + 12, -3, -9, -6, 8, -18, 18, -36, 54, -55, 30, -25, 26, -41, 38, -49, + 48, -38, 8, 16, -40, 47, -52, 34, -12, -4, 2, -13, -1, -2, -1, -4, + -3, -25, -41, 8, 16, 27, 2, 16, 1, 13, 21, -8, -6, -29, 17, 8, + 8, 20, -13, 5, 4, 25, 17, 30, 22, 14, 15, 19, 7, 51, -16, -15, + -32, -13, 12, -8, -17, -49, -27, -29, -29, -52, -66, -55, -32, -20, -41, -21, + -36, -11, -16, 22, 3, 19, 0, -6, -10, 0, -38, -17, -35, -19, -27, 0, + -35, -27, -9, -17, -14, -2, 20, 50, 63, 57, 49, 70, 70, 97, 81, 68, + 52, 78, 93, 98, 102, 56, 34, 20, 53, 60, 45, 24, -18, 21, -10, 0, + -38, -79, -38, -37, -13, -27, -41, -50, -51, 14, 10, 16, -21, -13, -22, -20, + -48, -53, -55, -66, -76, -65, -91, -105, -92, -87, -101, -79, -56, -34, -7, -4, + 7, 20, 15, 26, 29, 32, -8, 36, 47, 50, 66, 29, 18, -33, -11, -4, + -10, -24, -42, -31, -22, 2, -23, -75, -34, -36, 5, 1, 1, -17, -47, 20, + 43, 68, 28, 30, 9, 29, 7, -9, -5, -32, -46, -36, -15, -40, -35, -15, + -26, -21, 2, 21, 49, 62, 83, 87, 106, 77, 97, 94, 67, 60, 85, 79, + 110, 80, 61, 1, 8, 16, 50, 36, 2, -22, 4, -2, 21, -35, -33, -19, + 4, 24, 19, 10, -58, -23, 18, 45, 34, 8, -12, -6, -5, -48, -51, -75, + -72, -77, -37, -65, -80, -57, -66, -68, -38, -38, 2, 10, 38, 31, 58, 22, + 39, 37, 27, -9, 23, 9, 35, 18, 15, -31, -50, -44, -5, 6, -10, -63, + -41, -56, -15, -41, -71, -45, -37, 7, -6, 5, -56, -71, -6, 21, 41, 8, + -13, -14, -40, -30, -41, -40, -56, -31, -31, -9, -15, -5, 10, 42, 27, 73, + 82, 73, 73, 79, 70, 38, 28, 31, 23, 45, 42, 44, 30, -40, 8, 28, + 52, 30, -18, -29, -40, -14, -45, -50, -55, -68, -39, -6, -29, -45, -59, -32, + 4, 31, 23, 16, 20, 11, -1, 1, -28, -45, -53, -56, -67, -60, -55, -40, + -31, -25, -16, 11, 20, 36, 67, 70, 75, 77, 81, 65, 46, 38, 34, 39, + 51, 44, 57, 7, -4, 13, 37, 46, 19, -8, -29, -1, -9, -21, -32, -43, + -55, -58, -40, -8, 15, 29, 38, 44, 59, 63, 51, 20, -20, -47, -61, -58, + -48, -42, -43, -35, -15, 15, 41, 55, 61, 62, 70, 67, 45, 11, -31, -62, + -80, -78, -71, -62, -54, -39, -15, 18, 50, 68, 79, 83, 92, 88, 57, 16, + -31, -71, -94, -95, -90, -83, -71, -55, -28, 7, 49, 77, 93, 100, 109, 107, + 78, 36, -20, -71, -99, -104, -100, -92, -83, -69, -43, -5, 42, 79, 100, 108, + 114, 112, 90, 51, -9, -65, -100, -110, -105, -95, -87, -76, -52, -11, 35, 75, + 100, 107, 111, 106, 90, 52, -4, -60, -97, -109, -99, -87, -80, -65, -35, 5, + 43, 75, 91, 95, 93, 87, 71, 31, -19, -64, -93, -99, -88, -76, -66, -44, + -9, 28, 59, 79, 84, 80, 71, 59, 35, -5, -45, -76, -96, -95, -77, -59, + -39, -9, 28, 61, 86, 98, 93, 74, 52, 28, -6, -43, -72, -94, -108, -99, + -77, -52, -20, 19, 56, 84, 106, 115, 106, 79, 45, 3, -40, -74, -93, -108, + -112, -100, -79, -46, -1, 45, 78, 100, 113, 118, 108, 81, 39, -19, -67, -93, + -103, -108, -104, -94, -74, -32, 19, 61, 88, 102, 108, 109, 100, 73, 21, -44, + -87, -102, -104, -97, -90, -78, -49, 0, 46, 78, 90, 92, 89, 87, 77, 43, + -15, -72, -101, -104, -93, -79, -69, -47, -3, 47, 84, 96, 89, 74, 65, 58, + 37, -7, -61, -99, -110, -101, -82, -62, -38, 2, 49, 92, 112, 106, 82, 59, + 41, 18, -19, -61, -95, -111, -110, -98, -74, -39, 6, 54, 99, 122, 123, 104, + 79, 50, 12, -32, -72, -100, -111, -110, -106, -90, -54, -4, 49, 99, 123, 126, + 113, 95, 69, 24, -27, -72, -102, -114, -109, -104, -94, -64, -16, 36, 87, 116, + 121, 111, 97, 76, 36, -15, -61, -94, -110, -108, -98, -86, -60, -19, 29, 77, + 104, 109, 99, 86, 67, 35, -7, -47, -82, -98, -101, -92, -77, -48, -14, 25, + 67, 92, 95, 83, 66, 45, 18, -9, -37, -62, -77, -81, -78, -54, -16, 0, + 0, 0, 12, -10, 16, -14, -18, 17, -31, -2, 3, -19, -8, 17, 28, 37, + 31, -1, -25, -16, -47, -13, -43, -22, 6, 34, 41, 49, 41, 27, 6, -33, + -62, -54, -59, -32, -13, 29, 53, 73, 60, 54, 16, -19, -58, -77, -89, -42, + -46, 17, 55, 78, 86, 81, 33, -3, -35, -84, -110, -75, -70, 0, 39, 78, + 92, 105, 70, 13, -15, -82, -107, -103, -84, -41, 20, 81, 85, 127, 86, 39, + -4, -63, -103, -99, -107, -69, 2, 68, 82, 127, 84, 58, 28, -44, -88, -104, + -108, -83, -13, 29, 69, 116, 87, 77, 40, -16, -65, -89, -104, -89, -40, -1, + 47, 96, 90, 85, 52, 9, -38, -62, -96, -95, -62, -22, 21, 73, 78, 86, + 65, 35, -15, -41, -80, -92, -69, -48, 1, 43, 65, 80, 73, 49, 8, -23, + -59, -75, -74, -60, -22, 17, 49, 69, 65, 60, 25, -1, -36, -59, -70, -61, + -40, -9, 30, 52, 57, 63, 37, 17, -12, -41, -61, -57, -50, -30, 9, 30, + 49, 60, 47, 28, 6, -20, -49, -51, -53, -42, -11, 13, 34, 53, 50, 34, + 18, -3, -35, -39, -52, -49, -23, 0, 18, 41, 47, 36, 31, 10, -21, -28, + -43, -49, -31, -13, 2, 28, 39, 35, 38, 19, -7, -18, -33, -42, -36, -26, + -12, 19, 30, 34, 36, 22, 6, -5, -25, -38, -36, -29, -17, 8, 19, 26, + 35, 28, 12, 3, -17, -30, -29, -29, -22, -3, 9, 19, 33, 26, 14, 8, + -9, -18, -22, -28, -25, -9, 3, 15, 22, 20, 18, 12, 1, -11, -22, -24, + -21, -13, -3, 8, 11, 20, 21, 12, 5, -6, -19, -16, -17, -17, -7, 3, + 8, 20, 17, 7, 7, -2, -11, -13, -16, -17, -5, 2, 5, 12, 13, 8, + 6, 3, -9, -11, -9, -14, -5, 1, -3, 6, 11, 6, 7, 2, -6, -4, + -4, -10, -6, -3, -4, 5, 8, 2, 5, 4, -2, 0, -3, -9, -4, -3, + -3, 2, 3, 0, 6, 4, 0, -1, -2, -2, 0, 0, 0, 12, -10, 16, + -14, -18, 17, -31, -2, 3, -19, -8, 17, 28, 37, 31, -1, -25, -16, -47, + -13, -43, -22, 6, 34, 41, 49, 41, 27, 6, -33, -62, -54, -59, -32, -13, + 29, 53, 73, 60, 54, 16, -19, -58, -77, -89, -42, -46, 17, 55, 78, 86, + 81, 33, -3, -35, -84, -110, -75, -70, 0, 39, 78, 92, 105, 70, 13, -15, + -82, -107, -103, -84, -41, 20, 81, 85, 127, 86, 39, -4, -63, -103, -99, -107, + -69, 2, 68, 82, 127, 84, 58, 28, -44, -88, -104, -108, -83, -13, 29, 69, + 116, 87, 77, 40, -16, -65, -89, -104, -89, -40, -1, 47, 96, 90, 85, 52, + 9, -38, -62, -96, -95, -62, -22, 21, 73, 78, 86, 65, 35, -15, -41, -80, + -92, -69, -48, 1, 43, 65, 80, 73, 49, 8, -23, -59, -75, -74, -60, -22, + 17, 49, 69, 65, 60, 25, -1, -36, -59, -70, -61, -40, -9, 30, 52, 57, + 63, 37, 17, -12, -41, -61, -57, -50, -30, 9, 30, 49, 60, 47, 28, 6, + -20, -49, -51, -53, -42, -11, 13, 34, 53, 50, 34, 18, -3, -35, -39, -52, + -49, -23, 0, 18, 41, 47, 36, 31, 10, -21, -28, -43, -49, -31, -13, 2, + 28, 39, 35, 38, 19, -7, -18, -33, -42, -36, -26, -12, 19, 30, 34, 36, + 22, 6, -5, -25, -38, -36, -29, -17, 8, 19, 26, 35, 28, 12, 3, -17, + -30, -29, -29, -22, -3, 9, 19, 33, 26, 14, 8, -9, -18, -22, -28, -25, + -9, 3, 15, 22, 20, 18, 12, 1, -11, -22, -24, -21, -13, -3, 8, 11, + 20, 21, 12, 5, -6, -19, -16, -17, -17, -7, 3, 8, 20, 17, 7, 7, + -2, -11, -13, -16, -17, -5, 2, 5, 12, 13, 8, 6, 3, -9, -11, -9, + -14, -5, 1, -3, 6, 11, 6, 7, 2, -6, -4, -4, -10, -6, -3, -4, + 5, 8, 2, 5, 4, -2, 0, -3, -9, -4, -3, -3, 2, 3, 0, 6, + 4, 0, -1, -2, -2, 0, -1, -1, -3, -7, -14, -23, -32, -45, -55, -66, + -74, -83, -88, -80, -77, -71, -64, -54, -46, -37, -31, -25, -19, -12, -6, -1, + 4, 8, 12, 17, 21, 23, 25, 25, 27, 29, 32, 35, 36, 34, 32, 31, + 32, 35, 37, 37, 35, 31, 29, 29, 31, 33, 34, 32, 29, 26, 25, 27, + 30, 32, 31, 29, 27, 27, 29, 31, 34, 35, 35, 35, 36, 38, 41, 43, + 45, 47, 49, 52, 55, 57, 59, 61, 63, 66, 69, 70, 70, 68, 66, 63, + 61, 58, 54, 47, 36, 24, 11, 1, -9, -20, -33, -48, -64, -78, -89, -97, + -103, -110, -116, -123, -128, -128, -126, -121, -116, -112, -107, -102, -95, -88, -78, -69, + -61, -54, -47, -41, -34, -27, -21, -16, -12, -7, -2, 2, 5, 6, 8, 10, + 13, 16, 19, 19, 19, 17, 18, 19, 22, 24, 24, 22, 19, 18, 19, 21, + 23, 24, 22, 19, 17, 18, 20, 22, 24, 24, 22, 21, 22, 24, 27, 29, + 30, 30, 31, 32, 35, 37, 40, 42, 45, 47, 50, 53, 56, 58, 60, 62, + 66, 68, 70, 69, 68, 65, 63, 61, 59, 54, 46, 36, 24, 13, -1, -14, + -28, -43, -57, -68, -78, -86, -94, -102, -109, -114, -117, -117, -115, -112, -109, -106, + -101, -96, -89, -81, -73, -67, -59, -53, -46, -40, -34, -28, -23, -18, -13, -9, + -5, -2, 0, 2, 5, 7, 10, 12, 14, 15, 15, 15, 16, 18, 19, 20, + 20, 19, 18, 18, 19, 21, 22, 22, 21, 20, 19, 21, 23, 24, 25, 25, + 25, 25, 26, 29, 31, 33, 34, 35, 36, 38, 40, 43, 46, 48, 51, 53, + 56, 59, 62, 65, 68, 71, 74, 77, 78, 79, 78, 77, 76, 74, 71, 66, + 58, 49, 39, 28, 17, 6, -6, -20, -35, -50, -64, -75, -85, -94, -102, -110, + -117, -122, -124, -123, -121, -118, -114, -110, -106, -99, -92, -84, -76, -69, -61, -55, + -48, -41, -34, -29, -23, -18, -13, -9, -5, -2, 0, -1, -1, 0, 2, 0, + 3, 2, 2, 4, 5, 4, 4, 4, 4, 5, 3, 4, 3, 1, 2, 0, + 0, -1, -3, -4, -2, -3, -5, -3, -4, -5, -5, -4, -3, -3, -6, -5, + -4, -2, -5, -5, -2, -3, -3, -3, 1, 4, 4, 8, 8, 8, 13, 12, + 13, 14, 12, 9, 8, 6, 6, 3, -2, -2, -5, -5, -4, -5, -11, -16, + -12, -7, -3, -5, -10, -11, -6, -2, -2, -1, -4, -6, -6, -7, -8, -5, + -2, 2, 5, 6, 8, 8, 9, 13, 16, 16, 14, 11, 7, 5, 4, 2, + 0, -2, -3, -3, 0, -3, -13, -28, -11, 7, -1, -15, -1, -5, -18, -10, + 6, 11, -11, -1, -10, -14, -13, -13, -4, 4, 6, 14, 13, 10, 10, 15, + 17, 24, 24, 13, 12, 10, 1, 0, 2, -4, 0, -6, 2, 7, -22, -68, + 2, 35, -40, 14, -24, -3, -10, -9, -20, -3, 28, 2, -9, -12, -28, -19, + -4, -1, 15, 17, 17, 16, 12, 16, 22, 25, 28, 6, 17, 9, -1, -2, + -3, 2, 12, -6, 6, -5, -35, -89, 32, 28, -39, 20, -36, 9, -20, -9, + -34, 3, 34, 8, -16, -11, -37, -15, -3, 0, 26, 18, 13, 15, 13, 25, + 27, 29, 20, 3, 21, 2, -2, 0, -8, 11, 16, -1, 8, -21, -76, -81, + 87, -25, 4, -4, -23, 6, -26, -20, -35, 23, 28, 0, -18, -16, -43, 2, + -9, 17, 25, 15, 9, 18, 17, 37, 28, 35, 3, 14, 12, -5, -1, -1, + -5, 27, 0, 16, -11, -49, -128, 36, 40, -36, 35, -41, 21, -27, -14, -45, + 4, 24, 20, -23, -6, -41, -9, -1, 6, 23, 19, 5, 15, 14, 33, 35, + 40, 16, 5, 16, -3, -5, 4, -12, 24, 10, 18, 1, -38, -128, -21, 72, + -50, 42, -38, 19, -16, -16, -43, -10, 21, 24, -22, -11, -30, -15, 6, 4, + 22, 18, 6, 11, 13, 27, 39, 42, 22, 4, -3, -2, -2, -5, -3, -5, + -3, -2, -6, -5, -5, -6, -5, -3, -5, -3, -5, -4, -6, -3, -1, -2, + -1, 0, -2, 1, 2, 1, 4, 4, 5, 5, 5, 8, 10, 11, 9, 10, + 11, 8, 5, 10, 7, 5, 5, 0, -3, 1, 0, -5, -2, -8, -9, -7, + -7, -5, -9, -11, -9, -8, -8, -7, -9, -7, -6, -7, -5, -6, -5, -3, + -3, -3, -4, -4, -2, 0, 1, 2, 5, 9, 12, 16, 19, 22, 22, 24, + 22, 22, 19, 13, 11, 7, 7, 4, -2, -7, -9, -9, -8, -10, -14, -14, + -15, -15, -13, -14, -17, -18, -14, -12, -12, -8, -9, -7, -6, -6, -6, -8, + -9, -9, -11, -13, -11, -6, -1, 3, 9, 20, 27, 33, 37, 46, 46, 42, + 37, 28, 21, 14, 11, 10, 14, 20, -2, -40, -47, -22, -5, -4, -1, 4, + -15, -53, -56, -7, -33, -14, -2, -19, -7, -8, -15, -6, -9, -8, -3, -9, + -15, -18, -26, -19, -6, -5, -6, 0, 12, 22, 29, 30, 28, 32, 29, 21, + 15, 13, 5, 5, 3, 19, 30, 3, -68, -26, 2, -17, 17, -12, 15, -1, + -12, -48, -43, -19, -1, 3, 6, -8, -4, -10, -10, -4, 0, -6, -1, -7, + -9, -17, -12, -6, -9, -14, -5, 14, 33, 33, 41, 32, 41, 35, 20, 10, + 8, 4, 10, -2, 36, 40, 3, -110, -8, -7, -6, 16, -18, 27, -2, -4, + -56, -57, -33, 16, -2, 12, -11, -5, -17, -9, -5, 10, -6, 0, -12, -11, + -20, -10, -8, -12, -17, -3, 17, 38, 34, 45, 36, 51, 37, 18, 4, -3, + 3, 8, 8, 54, 48, -34, -128, 28, -33, 28, -13, 1, 21, 3, -20, -59, + -65, -10, 17, -1, 7, -17, -10, -19, -8, 5, 11, -4, -2, -16, -17, -20, + -9, -11, -18, -11, 3, 31, 36, 41, 41, 44, 53, 30, 10, 1, -13, 12, + -5, 42, 63, 43, -127, -55, 19, -27, 28, -1, 0, 3, 5, 8, 12, 14, + 15, 15, 14, 12, 8, 5, 1, -3, -9, -14, -17, -19, -18, -16, -12, -8, + -5, -4, -2, -1, -1, -2, -3, -4, -3, -2, -1, -1, 0, 0, 0, 2, + 8, 12, 16, 19, 23, 26, 34, 40, 39, 28, 11, -8, -26, -36, -40, -39, + -35, -27, -19, -10, -5, -6, -10, -12, -15, -14, -12, -9, -5, -3, -1, 1, + 6, 8, 7, 7, 7, 8, 13, 20, 28, 35, 43, 48, 55, 57, 51, 32, + 3, -29, -56, -68, -67, -60, -46, -31, -17, -7, -4, -7, -11, -15, -16, -15, + -10, -5, -1, 1, 3, 5, 7, 9, 11, 12, 12, 10, 13, 19, 26, 36, + 43, 51, 58, 65, 61, 40, 6, -30, -60, -75, -73, -64, -49, -32, -16, -5, + -1, -4, -11, -18, -23, -23, -19, -12, -5, 2, 8, 12, 13, 11, 9, 8, + 8, 10, 15, 21, 27, 32, 37, 42, 49, 55, 63, 55, 32, -3, -39, -66, + -79, -73, -56, -39, -24, -12, -7, -7, -12, -19, -24, -24, -21, -14, -6, 3, + 8, 11, 12, 11, 10, 10, 10, 11, 14, 17, 21, 27, 33, 41, 49, 56, + 63, 66, 49, 15, -27, -61, -82, -85, -73, -52, -33, -18, -9, -5, -7, -12, + -18, -21, -20, -15, -9, -1, 4, 8, 12, 15, 15, 14, 11, 8, 7, 10, + 15, 22, 32, 45, 59, 72, 86, 95, 75, 22, -40, -93, -119, -120, -97, -64, + -32, -9, 5, 9, 5, -3, -14, -21, -23, -20, -13, -5, 4, 12, 17, 18, + 15, 10, 7, 4, 3, 6, 9, 15, 21, 30, 40, 56, 77, 99, 99, 54, + -19, -86, -123, -127, -103, -66, -27, 1, 16, 18, 11, -1, -12, -21, -23, -21, + -16, -8, 1, 9, 16, 19, 16, 11, 8, 5, 5, 7, 9, 14, 19, 27, + 35, 49, 68, 90, 101, 73, 6, -66, -114, -128, -113, -78, -39, -6, 13, 19, + 11, -1, 0, 10, 30, 35, 40, 39, 37, 28, 18, 6, -9, -20, -30, -35, + -33, -30, -28, -23, -24, -23, -19, -20, -15, -11, -8, -3, 0, 1, 0, -2, + -4, -1, 0, 10, 15, 21, 27, 25, 25, 22, 13, 10, -5, -9, -15, -19, + -17, -17, -12, -7, 0, 4, 10, 8, 5, -5, -13, -23, -31, -30, -24, -13, + 11, 36, 62, 81, 83, 78, 54, 35, 19, -11, -29, -49, -57, -47, -35, -20, + -19, -26, -27, -33, -30, -26, -22, -11, -8, 3, 11, 6, 0, -16, -23, -23, + -11, 9, 23, 35, 45, 51, 46, 49, 26, 12, -13, -26, -37, -45, -31, -35, + -17, -4, 8, 23, 24, 23, 9, -10, -22, -37, -40, -38, -33, -12, 22, 67, + 100, 119, 111, 79, 50, 10, -12, -32, -52, -69, -62, -38, -14, -9, -21, -42, + -60, -50, -39, -19, -4, -1, 3, 15, 19, 2, -16, -43, -57, -48, -21, 19, + 38, 63, 66, 69, 74, 59, 39, 4, -33, -52, -67, -58, -39, -25, 2, 10, + 32, 35, 36, 18, -7, -25, -37, -31, -28, -23, -10, 11, 53, 101, 121, 123, + 92, 48, 11, -24, -42, -60, -66, -67, -48, -20, 2, -16, -41, -67, -87, -62, + -44, -10, 8, 19, 30, 34, 35, 4, -36, -66, -78, -75, -27, 22, 49, 83, + 91, 97, 90, 69, 39, -18, -61, -104, -98, -75, -32, 19, 47, 68, 70, 56, + 16, -33, -77, -89, -76, -47, 7, 35, 64, 100, 123, 125, 107, 60, 5, -39, + -76, -94, -101, -93, -69, -36, -3, 17, 10, -15, -56, -80, -86, -69, -40, -7, + 25, 49, 66, 72, 54, 19, -19, -55, -77, -67, -40, 4, 45, 76, 96, 100, + 92, 67, 32, -11, -56, -88, -91, -73, -33, 9, 41, 61, 65, 52, 17, -28, + -67, -80, -68, -36, 6, 47, 82, 114, 126, 114, 74, 18, -32, -73, -93, -101, + -93, -70, -36, -3, 17, 10, -15, 0, -1, -2, -2, 0, 2, 3, 6, 7, + 6, 6, 3, 2, -1, -4, -8, -12, -14, -13, -13, -11, -5, -1, 5, 10, + 14, 17, 19, 18, 15, 12, 7, 3, 1, -2, -4, -4, -7, -11, -13, -16, + -16, -12, -9, -6, -3, -1, -1, -1, -4, -8, -11, -15, -16, -15, -10, -2, + 7, 18, 25, 28, 28, 24, 16, 10, 4, -2, -5, -5, -4, -4, -1, 0, + 0, 1, 1, 0, -1, -3, -6, -11, -11, -14, -16, -17, -19, -19, -16, -10, + -2, 8, 19, 27, 33, 35, 32, 26, 21, 14, 7, 0, -6, -11, -18, -25, + -31, -32, -27, -19, -9, 1, 10, 15, 14, 10, 0, -13, -28, -38, -42, -40, + -26, -4, 17, 40, 58, 66, 62, 51, 35, 17, 3, -8, -16, -18, -18, -15, + -13, -15, -17, -17, -15, -13, -11, -12, -3, -2, 1, -3, -15, -28, -36, -42, + -40, -28, -11, 14, 45, 63, 70, 69, 56, 44, 36, 21, 3, -12, -18, -26, + -37, -47, -58, -55, -41, -20, 4, 22, 34, 43, 37, 22, -7, -43, -71, -88, + -86, -64, -31, 7, 56, 99, 115, 106, 85, 48, 17, 1, -14, -28, -33, -20, + -11, -12, -18, -37, -44, -41, -29, -23, -7, 15, 31, 40, 33, 8, -27, -56, + -73, -74, -63, -33, 4, 50, 93, 101, 91, 79, 56, 43, 24, 5, -17, -32, + -31, -43, -56, -63, -72, -57, -32, 3, 26, 46, 62, 63, 45, 9, -39, -85, + -112, -106, -84, -49, 6, 60, 104, 127, 115, 83, 46, 16, -1, -16, -21, -26, + -16, -2, -8, -25, -47, -67, -62, -49, -26, 2, 34, 60, 74, 65, 33, -21, + -71, -98, -92, -77, -36, 21, 69, 106, 112, 88, 58, 29, 9, -8, -18, -24, + -17, -4, -10, -26, -47, -67, -62, -49, -26, 2, 34, 60, 74, 65, 33, 17, + 16, -38, 9, 40, -58, 27, 43, -80, 52, -2, -54, 64, -27, -17, 32, 4, + -49, 53, -22, -47, 90, -73, 17, 42, -45, 8, 23, -41, -1, 58, -74, 40, + 25, -66, 56, -19, -45, 58, -9, -39, 45, 3, -48, 55, -41, -27, 78, -66, + 13, 40, -38, 0, 29, -51, 12, 57, -79, 38, 31, -64, 40, -4, -47, 63, + -16, -40, 55, -16, -32, 45, -31, -29, 76, -64, 0, 58, -49, 4, 31, -52, + 31, 5, -35, 45, -21, 4, -5, 3, -17, -7, 55, -72, 43, 35, -88, 80, + -57, 3, 45, -62, 53, -14, -2, -17, 46, -77, 42, 23, -61, 75, -54, 39, + -40, 31, -42, 25, 11, -48, 93, -97, 62, -27, -13, 7, 0, 30, -59, 82, + -74, 28, 10, -53, 65, -47, 46, -41, 40, -48, 7, 45, -95, 127, -99, 43, + -9, -25, 40, -58, 84, -84, 78, -66, 11, 50, -96, 111, -85, 51, -26, -14, + 36, -60, 91, -84, 58, -26, -22, 56, -87, 98, -71, 47, -25, -11, 44, -84, + 103, -92, 69, -32, -3, 25, -59, 87, -90, 70, -45, 17, 16, -57, 81, -73, + 50, -33, 14, 0, -35, 75, -84, 69, -42, 8, 11, -46, 74, -69, 57, -47, + 36, -26, -20, 69, -89, 83, -58, 37, -24, -7, 41, -58, 54, -53, 53, -42, + 14, 28, -54, 52, -55, 46, -41, 22, 30, -57, 58, -64, 56, -54, 26, 31, + -55, 63, -73, 66, -68, 49, -3, -38, 61, -71, 75, -87, 69, -15, -27, 37, + -55, 74, -84, 73, -34, -5, 26, -59, 74, -85, 84, -33, -12, 30, -57, 65, + -85, 86, -40, 9, 15, -50, 69, -94, 93, -53, 15, 11, -38, 58, -86, 96, + -64, 11, 21, -30, 17, -3, -3, 0, 0, -3, -4, -4, -3, -4, -4, -5, + -6, -6, -8, -5, -6, -3, 0, 2, 4, 7, 8, 12, 12, 14, 13, 13, + 12, 8, 7, 2, 2, -4, -6, -10, -11, -12, -12, -14, -10, -9, -3, -3, + 2, 3, 3, 2, 1, 1, -3, -3, -4, -3, -3, -3, -4, 0, -3, -3, + -3, 0, -3, 0, -3, 0, 1, 0, 0, 0, 0, 0, -3, 1, -3, 1, + -3, 2, 1, 0, 0, -3, -4, -5, -9, -10, -15, -16, -17, -17, -14, -10, + -3, 4, 9, 14, 19, 24, 25, 26, 28, 30, 34, 42, 31, 9, -31, -39, + -23, -15, -17, -23, -30, -23, -12, -10, 4, 9, 19, 13, 14, 6, 0, -9, + -11, -12, -9, -8, 0, 0, 2, 1, 1, -3, -3, -5, -3, -5, -3, -4, + 0, -3, -4, -4, -3, -5, -3, -5, -3, 0, 3, 2, 7, 7, 7, 3, + 0, -14, -17, -26, -26, -28, -21, -17, -11, -10, 2, 6, 19, 18, 32, 32, + 60, 69, 98, 60, 7, -58, -8, -8, -14, -39, -30, -14, -47, -21, -45, -3, + 7, 20, 14, 31, 12, 10, -15, -5, -23, -14, -15, -4, -8, 2, 1, 7, + -3, 2, -8, -4, -6, -6, -3, 0, -6, -6, -8, -10, -11, -12, -9, -9, + -4, -3, 0, 8, 10, 12, 15, 13, 4, -10, -15, -30, -32, -30, -23, -22, + -19, -14, -4, 3, 10, 14, 26, 40, 70, 102, 127, 62, -17, -39, 9, -25, + -9, -87, -12, -16, 0, -30, -27, -19, -9, 6, 18, 21, 19, 6, 0, -9, + -17, -14, -16, -8, -6, 0, 4, 4, -5, -4, -11, -3, -6, 2, 2, 0, + -6, 0, -2, -4, -8, -14, -21, -25, -28, -32, -36, -40, -44, -48, -51, -55, + -59, -63, -67, -71, -74, -78, -82, -86, -90, -94, -98, -101, -84, -60, -38, -15, + 8, 28, 27, 23, 19, 16, 11, 21, 46, 68, 93, 109, 106, 102, 98, 95, + 91, 87, 83, 79, 75, 71, 67, 64, 60, 56, 52, 49, 45, 41, 37, 33, + 30, 26, 22, 18, 15, 11, 7, 3, -1, -5, -9, -13, -17, -20, -24, -28, + -32, -35, -39, -43, -47, -51, -54, -58, -62, -66, -69, -73, -77, -81, -85, -89, + -93, -97, -100, -105, -95, -70, -48, -23, -7, -10, -14, -17, -22, -18, 4, 26, + 50, 72, 96, 107, 103, 100, 96, 92, 88, 84, 80, 76, 72, 68, 64, 61, + 57, 53, 49, 46, 42, 38, 34, 30, 26, 23, 19, 15, 11, 8, 4, 0, + -4, -8, -11, -15, -19, -23, -27, -30, -35, -38, -43, -46, -51, -54, -58, -61, + -66, -56, -31, -9, 16, 33, 30, 26, 22, 18, 15, 11, 7, 3, -1, -5, + -9, -13, -16, -20, -24, -28, -32, -36, -40, -43, -48, -51, -55, -59, -63, -50, + -26, -4, 20, 42, 64, 67, 62, 59, 55, 51, 47, 43, 39, 35, 31, 27, + 23, 20, 16, 12, 8, 4, 0, -4, -7, -11, -15, -19, -22, -27, -17, 8, + 30, 55, 72, 69, 65, 61, 57, 54, 50, 46, 42, 38, 34, 30, 26, 22, + 18, 15, 11, 7, 3, 0, -4, -8, -12, -15, -19, -23, -27, -31, -35, -38, + -42, -46, -50, -54, -57, -61, -65, -69, -73, -77, -81, -85, -89, -92, -96, -100, + -100, -79, -64, -47, -31, -15, 0, 0, -4, -3, -6, -8, 6, 10, -8, -13, + 22, 55, 15, -58, -102, -88, -25, 51, 77, 79, 82, 19, -45, -107, -128, -88, + 19, 81, 86, 71, 35, -16, -50, -73, -55, -27, -14, 7, 77, 89, 31, -22, + -27, -61, -86, -34, 40, 55, 67, 80, 57, -1, -48, -60, -41, -46, -31, 28, + 62, 47, 43, 33, -5, -34, -45, -52, -33, 26, 66, 70, 41, 17, -34, -79, + -93, -41, -6, 22, 53, 93, 62, 17, -20, -66, -118, -88, -4, 45, 60, 69, + 67, 2, -72, -109, -95, -78, -7, 67, 101, 78, 69, 19, -56, -110, -89, -64, + -19, 45, 100, 86, 36, -11, -65, -107, -108, -41, 24, 69, 93, 111, 56, -15, + -70, -81, -88, -38, 30, 88, 90, 83, 43, -24, -81, -82, -57, -24, 38, 100, + 115, 70, 26, -25, -75, -108, -66, -20, 29, 71, 105, 67, 7, -46, -67, -83, + -60, 0, 58, 82, 81, 57, -9, -72, -99, -78, -60, -8, 54, 95, 69, 44, + 0, -51, -92, -69, -26, 18, 53, 81, 63, 6, -44, -74, -88, -79, -19, 40, + 75, 75, 72, 18, -42, -80, -74, -69, -25, 32, 76, 66, 39, 5, -41, -82, + -76, -34, 3, 42, 79, 88, 38, -12, -49, -74, -92, -48, 8, 51, 70, 83, + 50, -7, -58, -68, -65, -43, 13, 70, 82, 62, 34, -17, -72, -94, -65, -28, + 17, 69, 101, 71, 25, -21, -60, -88, -66, -13, 37, 62, 82, 68, 11, -47, + -73, -79, -66, -15, 49, 82, 76, 57, 11, -51, -88, -78, -48, -9, 49, 0, + 0, 0, 0, 0, 0, -3, -5, -5, -7, -6, -2, 5, 16, 24, 21, 17, + 12, 3, -10, -31, -44, -47, -42, -28, -2, 26, 29, 36, 35, 1, -26, -39, + -52, -53, -38, -10, -32, -41, -7, 2, 22, 65, 89, 74, 15, -16, -24, 12, + 62, 39, 6, -12, -3, 47, 48, 21, 109, 127, 119, 53, -9, 19, 9, -50, + -55, -43, -71, -46, -5, -2, -20, -12, -9, 12, -27, -66, -50, -8, -19, -58, + -22, -8, -19, -34, -42, 10, 32, -4, 4, 46, 96, 34, -51, -10, -8, -93, + -70, -58, -46, -16, -32, -30, 6, 7, -41, -29, 3, 25, 73, 67, 45, 37, + 30, 83, 0, -31, -4, -50, -28, -41, -75, -110, -53, -13, -3, 22, 14, 14, + 13, 7, 9, 38, 47, 39, 17, -8, 90, 75, -5, -29, -46, -54, -102, -66, + -35, -27, -29, -21, 32, 5, 1, 1, -2, 16, 16, 19, 30, 50, 89, 41, + 6, 40, -10, -15, -41, -46, -43, -77, -100, -100, -48, -37, -26, -4, -9, 0, + 13, 36, 70, 75, 59, 34, 12, -13, -27, 37, 71, 48, 53, 37, 7, 8, + 34, 48, 40, 31, 25, 2, -20, -15, -5, 12, -11, -49, -20, 15, -13, -42, + -29, 16, -6, -58, -28, 17, 12, -20, -11, 16, -3, -37, -14, 3, -32, -10, + 40, 54, 53, 27, -3, -5, -34, -47, -49, -90, -68, -36, -32, -31, -16, 26, + 3, 0, -2, -2, 15, 16, 19, 30, 51, 88, 40, 6, 39, -10, 3, -2, + 11, -7, 23, 19, 74, 39, 32, -13, -21, -7, -39, -44, -128, -58, -21, 52, + -86, -74, -94, 75, 61, 72, -38, 13, 59, 116, 71, -9, -33, -12, 68, -2, + -35, -128, -42, -43, 39, -78, -57, -81, 56, 59, 63, -13, 7, 69, 98, 87, + -13, -9, -24, 70, -11, -23, -128, -42, -48, 28, -68, -61, -69, 34, 64, 46, + 8, -5, 79, 82, 100, -17, 5, -29, 69, -13, -21, -122, -49, -43, 11, -55, + -72, -54, 13, 73, 30, 23, -16, 87, 72, 107, -17, 10, -26, 64, -6, -26, + -109, -61, -31, -6, -40, -86, -41, -4, 80, 17, 31, -22, 88, 70, 106, -10, + 6, -16, 53, 7, -37, -93, -76, -17, -21, -28, -99, -33, -15, 83, 12, 31, + -21, 83, 76, 98, 2, -4, -1, 41, 24, -49, -77, -89, -6, -31, -20, -106, + -32, -19, 79, 14, 23, -15, 71, 87, 87, 17, -16, 13, 30, 39, -57, -67, + -97, -1, -34, -19, -106, -38, -16, 69, 23, 11, -5, 56, 100, 75, 32, -28, + 25, 22, 50, -59, -62, -98, -2, -30, -24, -100, -52, -9, 55, 36, -4, 5, + 41, 112, 67, 43, -34, 30, 21, 55, -53, -65, -93, -11, -18, -34, -88, -69, + 0, 41, 48, -17, 12, 29, 118, 65, 49, -34, 28, 27, 53, -42, -72, -83, + -23, -6, -44, -77, -85, 5, -69, 1, -12, -29, -28, -13, 1, 9, -4, -27, + -18, -5, 11, 65, 87, 54, 59, 66, 30, 12, 8, -6, -7, 4, -7, -39, + -59, -63, -48, -23, -13, -6, 22, 61, 68, 15, -59, -87, -41, 3, 5, -10, + -17, -17, -20, -23, -20, -28, -17, -3, -10, -29, 23, 11, 25, 52, 56, 62, + 80, 54, 22, -15, -31, -38, -5, 11, -9, -7, -36, -44, -6, 52, 127, 26, + -68, -125, -105, 22, 15, -27, -27, 13, 25, 69, 28, -42, -77, -57, -70, 15, + 44, 14, 26, 57, 69, 43, 33, 41, 33, 32, 25, -50, -98, -100, -38, 24, + 7, -35, -38, -2, 76, 64, 15, -79, -93, -50, -12, 27, 45, 32, -4, 23, + 6, -36, -47, -33, -52, -15, 37, 78, 49, 40, 17, 14, 14, 70, 81, 60, + -3, -4, -12, -42, -50, -28, -20, 5, 9, 27, 46, -13, -69, -99, -88, -47, + 5, -4, -10, 17, 39, -12, -8, -21, -16, 22, 9, -9, 1, 15, 15, 33, + 29, 17, 11, 38, 72, 29, -8, -36, -27, -42, 17, -40, 25, 25, 8, -3, + 14, 15, 2, 43, 33, -2, -19, -24, -8, 2, -69, -114, -94, -77, -87, 22, + 27, 19, 24, 57, 121, 94, 40, -27, -29, 4, 28, -12, 5, -21, -28, -18, + 0, -9, 1, 36, 22, 7, 6, 12, 7, 8, 55, 6, -2, -7, -13, -12, + -12, -8, -5, -5, -1, -4, -4, -3, -1, 5, 11, 15, 18, 16, 11, 5, + -5, -12, -16, -17, -14, -10, -7, -3, -2, -3, -3, -5, -3, 2, 9, 18, + 22, 23, 18, 11, -2, -14, -20, -22, -18, -12, -8, -5, -3, -5, -6, -6, + -5, 1, 11, 22, 30, 31, 24, 15, -1, -12, -20, -23, -19, -13, -8, -3, + -3, -2, -6, -8, -9, -5, 6, 21, 32, 35, 29, 19, 1, -15, -27, -29, + -25, -15, -9, -4, -1, -2, -7, -14, -15, -10, 4, 24, 42, 48, 43, 26, + 4, -20, -36, -38, -30, -17, -7, -3, 0, -1, -4, -16, -24, -19, -3, 26, + 49, 61, 60, 40, 9, -23, -45, -52, -39, -22, -5, -2, 1, 3, -2, -18, + -32, -30, -10, 22, 55, 77, 78, 52, 15, -22, -51, -66, -52, -29, -5, 0, + 2, 9, 6, -15, -37, -42, -22, 10, 55, 89, 99, 71, 22, -20, -58, -79, + -68, -35, -8, 6, 1, 12, 13, -9, -37, -50, -35, 0, 46, 93, 116, 90, + 33, -15, -60, -89, -84, -44, -9, 10, 3, 13, 19, -3, -35, -53, -43, -12, + 34, 91, 127, 109, 46, -9, -57, -95, -96, -57, -13, 11, 7, 10, 25, 2, + -2, -35, 0, 2, 7, 12, -7, -79, -68, 2, -6, -5, 19, 40, 33, 55, + 56, 17, 32, 32, 2, -20, 5, 51, 27, -21, -13, -11, -17, -20, -6, -63, + -125, -116, -86, -59, -34, 11, 23, 20, 39, 66, 50, 47, 54, 46, 11, -4, + 44, 67, 30, 11, 16, 6, -2, 7, -4, -77, -114, -107, -70, -50, -20, 29, + 26, 12, 48, 69, 44, 47, 49, 28, -8, 9, 53, 49, 15, 9, 8, -3, + -11, 7, -33, -107, -123, -101, -62, -49, -5, 25, 6, 13, 55, 49, 32, 40, + 39, 7, -17, 18, 49, 32, 7, 8, 1, -12, -3, 7, -62, -113, -109, -74, + -50, -31, 23, 32, 13, 40, 69, 48, 46, 54, 42, 2, 1, 42, 52, 25, + 10, 11, 0, -11, 10, -10, -90, -115, -101, -64, -52, -15, 29, 16, 10, 51, + 59, 41, 46, 49, 25, -9, 15, 48, 42, 15, 10, 7, -9, -7, 16, -43, + -107, -113, -89, -60, -47, 4, 27, 4, 19, 58, 47, 38, 46, 43, 6, -9, + 28, 47, 29, 10, 11, 2, -14, 5, 5, -73, -111, -106, -73, -56, -29, 24, + 22, 6, 40, 61, 43, 43, 52, 37, -3, 6, 41, 47, 23, 12, 11, 0, + -14, 1, 3, 5, 5, 6, 8, 6, 4, 0, -4, -5, -6, -9, -9, -11, + -11, -12, -13, -13, -13, -12, -11, -9, -5, -2, -1, 1, 4, 6, 9, 11, + 12, 12, 11, 8, 5, 2, -2, -2, -2, -2, 0, -1, -1, -2, -5, -5, + -5, -1, 4, 10, 17, 20, 22, 19, 15, 7, -1, -9, -15, -19, -21, -21, + -18, -16, -13, -11, -12, -15, -19, -23, -24, -20, -13, -3, 9, 20, 34, 44, + 50, 46, 35, 21, 7, -4, -14, -20, -19, -13, -8, 2, 0, -5, -15, -28, + -32, -29, -14, 0, 11, 27, 42, 58, 59, 45, 22, 4, -15, -26, -37, -43, + -42, -37, -17, 1, 18, 23, 8, -5, -29, -47, -47, -43, -25, -5, 20, 52, + 80, 92, 76, 43, 9, -20, -35, -38, -46, -41, -29, -12, 19, 35, 22, 4, + -34, -53, -58, -40, -26, -16, 14, 47, 88, 108, 90, 50, 16, -9, -36, -51, + -64, -64, -52, -33, -1, 32, 40, 24, 3, -29, -62, -58, -65, -52, -18, 23, + 68, 114, 127, 95, 41, 1, -36, -54, -56, -68, -55, -35, -17, 19, 42, 29, + 13, -16, -46, -60, -54, -56, -47, -11, 29, 72, 116, 127, 94, 41, -3, 0, + 16, 39, 54, 46, 18, 7, -15, -36, -9, -6, -16, -5, -15, -30, -23, -35, + -20, 22, 3, -19, -20, -13, -9, 19, 23, 10, 12, 35, 66, 54, 4, -43, + -58, -15, -10, 16, 55, 18, -39, -38, -30, 2, 9, 27, 51, -32, -60, -72, + -4, 32, 71, 19, -8, 56, -2, -42, 10, 21, -6, 31, -9, -70, 8, -6, + -19, -93, -20, -5, -31, 10, 5, 56, 24, -45, 11, 66, 48, 61, 89, 49, + -57, -6, -20, -69, -104, -83, -50, 32, 10, -16, -87, -78, 30, 127, 63, -17, + -91, -2, -12, 45, 83, 30, 56, 54, 42, 7, 79, -26, -52, -64, -97, 12, + -3, -107, -99, -39, 34, 86, 19, -25, 25, 90, -8, -38, 65, 36, 10, 30, + 36, 19, -6, 38, -47, -101, -52, -45, 30, -9, -106, 18, -10, -37, 16, 100, + -94, -111, -25, -35, -12, -8, -9, 51, 24, -5, -70, -52, -52, -19, -11, 48, + 93, 61, 17, 113, 125, 73, -16, -30, -57, -78, -116, -55, -38, -10, -5, -4, + 38, 31, -3, -46, -46, -50, -20, -10, 52, 84, 48, 14, 115, 119, 64, -16, + -1, 4, 0, -9, -11, -1, 6, 2, -2, 4, -6, -10, -2, 11, 14, 3, + -10, -15, -1, 17, 4, 6, 4, -12, -18, 6, 10, 4, 6, -8, -36, 2, + 3, 3, 5, 15, -20, -17, 9, 8, 11, 17, -8, -26, 18, 2, 5, 5, + 13, -24, -8, -2, 2, 5, 7, -21, -18, 13, 5, -5, 17, 7, -14, -13, + -12, 0, 14, 3, -12, -26, 13, 3, 10, 18, 12, -15, -14, -1, 3, 19, + 0, -10, -29, 11, 4, 17, 15, 12, -24, -20, 6, 9, 22, -3, -13, -15, + 9, 1, 7, 6, 18, -19, -26, -18, 2, 22, 0, -25, -20, 15, 8, -4, + 8, 31, -12, -20, -15, 9, 33, 9, -29, -2, 27, 7, -11, 8, 20, -20, + -41, -10, 15, 35, 15, -21, 11, 49, 6, -6, 4, 3, -48, -76, -35, 14, + 37, 22, -24, 29, 68, 20, 3, 7, -5, -68, -90, -59, 19, 36, 28, -13, + 59, 93, 30, 2, 18, -25, -88, -105, -81, 13, 26, 30, -4, 88, 109, 33, + 0, 22, -30, -88, -112, -76, 17, 31, 18, 5, 94, 114, 30, -4, 0, 4, + -30, -1, 0, -2, -2, -2, -1, 4, 11, 18, 30, 7, -64, -60, -30, -7, + 0, 2, 22, 67, 117, 23, -128, -74, -30, -5, -2, 1, 19, 62, 116, 38, + -123, -82, -31, -8, -1, -1, 16, 57, 114, 52, -117, -88, -33, -10, -2, -3, + 14, 52, 112, 64, -108, -96, -35, -13, -2, -4, 12, 49, 108, 77, -99, -102, + -37, -15, -2, -5, 10, 43, 104, 86, -87, -109, -40, -18, -2, -6, 8, 40, + 100, 95, -73, -115, -42, -21, -2, -8, 7, 35, 95, 102, -59, -120, -45, -24, + -2, -8, 5, 32, 90, 109, -44, -124, -49, -26, -3, -9, 3, 28, 85, 114, + -29, -126, -53, -28, -4, -9, 2, 25, 81, 116, -13, -127, -58, -29, -6, -9, + 0, 22, 75, 119, 3, -126, -63, -31, -7, -9, -2, 19, 70, 120, 18, -124, + -69, -32, -9, -9, -3, 16, 65, 119, 34, -63, -107, -58, -23, -11, -7, 7, + 46, 107, 89, -52, -109, -62, -25, -12, -8, 5, 42, 104, 97, -41, -87, -70, + -36, -18, -11, 0, 30, 85, 100, -2, -87, -5, 11, -23, -10, -3, -20, -3, + -17, -24, -33, -26, -1, -13, -12, -6, -9, 6, 25, 19, -7, -1, 22, -6, + -20, 13, 6, -12, 26, 48, 0, -7, 34, 23, 4, 32, 23, -41, -11, 49, + -3, -30, 35, 45, -14, -2, 62, 18, -44, -2, 26, -4, -28, -6, 16, 2, + -9, -9, 2, 18, 24, 9, -25, -57, -36, 30, 38, -21, -63, -37, 9, 37, + 40, 0, -56, -56, 3, 39, 20, -23, -52, -58, -46, 8, 67, 56, -18, -61, + -18, 36, 70, 95, 73, -35, -128, -127, -73, -17, 32, 48, 29, 28, 60, 106, + 113, 91, 36, -26, -67, -90, -91, -71, -44, -25, -13, 9, 36, 51, 69, 70, + 32, -40, -92, -99, -70, -25, 12, 29, 21, 3, -9, 10, 21, 12, -11, -22, + -27, -44, -23, 10, 30, 25, 24, 39, 18, 3, 8, 19, -1, -19, -8, 6, + 5, 13, 50, 43, 37, 36, 40, 37, 4, 12, -10, -33, -31, -25, -1, 1, + 7, 14, 10, -4, -11, -10, -6, -19, -42, -28, -54, -51, -18, -5, 3, 2, + -10, -10, 10, 28, 27, 16, 5, -5, -24, -26, -7, -14, -25, -16, 53, 33, + -49, -30, 53, 50, -24, -34, 40, 82, -118, -23, 120, -56, -70, -72, 106, -10, + -48, 3, 87, 28, -126, -16, 81, 4, -84, -51, 38, 62, -32, 36, 84, -12, + -41, 72, -42, -60, -64, 4, 77, -24, -79, -9, 122, 6, -94, 52, 43, 35, + 13, -62, -7, -89, 24, -30, 16, 29, 56, -59, 83, 42, 31, 36, -76, -2, + -128, -2, 45, 27, -104, -31, 66, 21, 19, 36, 121, 11, -76, -26, -93, 34, + 24, -34, -65, -53, 53, 17, 73, 46, 75, -9, -64, -21, -103, 41, 51, -41, + -83, -43, 108, 6, -11, 28, 127, 2, -84, -38, -72, 39, 17, -23, -15, -67, + 37, 6, 29, 64, 79, 17, -39, -39, -120, 55, 23, -17, -62, -51, 81, 23, + 20, 24, 99, -38, -99, 4, 17, -66, -41, -33, 63, 62, 16, 53, 91, 56, + -65, -36, -99, -38, 14, -47, -29, -38, 35, 83, 9, 48, 83, 62, -45, -31, + -103, -49, 14, 2, 6, -33, 33, -4, -1, 34, -93, 60, -49, 68, -21, 41, + -38, -38, 27, -87, 127, -34, 38, -3, -34, -2, -85, 79, -24, 4, 75, -23, + 11, -70, 1, -6, -6, 63, -48, 76, -71, 2, -7, -15, 46, -32, 48, -25, + -5, 10, -31, 18, -23, 5, 6, 17, 11, 3, 24, -46, -21, -1, -5, 31, + 1, 36, -23, -11, -4, -29, 14, -5, 29, 9, -2, -2, -20, -2, -15, 13, + 7, 4, 15, -11, 4, -13, -1, 1, -13, 15, -6, 9, 9, -2, -4, -11, + -2, -11, 7, 12, 9, 5, -6, -6, -16, -2, 3, 6, 13, 1, 7, -14, + -3, -11, -1, 8, 0, 18, -3, -3, -6, -13, 0, 4, 2, 9, 2, 2, + -6, -4, -1, -8, 2, 4, 2, 7, -4, 2, 1, -7, -3, -2, 0, 2, + 8, -2, 2, -1, -7, -3, -1, 3, 4, 3, 3, -3, -4, -4, 0, 2, + 1, 5, -1, -2, 1, -4, -1, 1, 0, 2, -5, -8, -3, -3, -9, -2, + -2, 5, 10, 16, 11, 5, -3, -5, -1, -4, -6, -7, -15, -18, -27, -31, + -21, -11, 22, 56, 90, 66, -17, -25, -25, 0, -12, -15, -25, -32, -39, -37, + -26, 6, 33, 65, 69, 44, -1, -13, -12, 1, 0, -9, -14, -22, -40, -44, + -42, -23, 8, 39, 60, 84, 57, -16, -25, -19, 2, -8, -11, -18, -32, -51, + -45, -32, -6, 28, 54, 85, 96, -5, -29, -23, -7, -10, -17, -16, -28, -53, + -44, -40, -7, 22, 52, 82, 112, 17, -37, -25, -20, -11, -18, -10, -23, -33, + -51, -40, -23, 10, 45, 65, 96, 64, -21, -35, -34, -19, -20, -13, -5, -14, + -35, -41, -39, -17, 9, 45, 58, 82, 98, -2, -57, -47, -23, -12, -11, -2, + -18, -28, -39, -36, -24, -1, 26, 57, 84, 121, 23, -65, -50, -40, -12, -11, + -4, -14, -20, -34, -32, -27, -5, 19, 56, 80, 127, 15, -66, -50, -2, -5, + -5, 2, 10, 8, -7, -16, -9, 6, 17, 8, -19, -20, 14, 38, 34, 20, + -5, 1, 50, 37, -50, -54, -66, -32, 32, -3, -13, -18, -17, 46, 89, -17, + -62, 45, 127, 57, -57, -67, -109, -11, 88, -31, -90, -88, -27, 63, 97, -27, + -105, -44, 65, 110, 60, -12, -30, -27, 17, 49, -2, -39, -6, 30, -16, -36, + -43, 32, 67, -54, -58, -38, -21, 47, 95, 76, -33, -78, -62, 10, 107, 24, + -106, -107, 12, 52, 27, 78, 8, -75, 25, 6, -26, 59, 32, -17, -7, -19, + 11, 32, -51, -52, 41, -9, -13, 94, 2, -65, 5, -46, -86, 34, 62, 85, + 29, -93, -89, -29, 44, 35, -31, -33, -19, 56, 127, 7, -9, -62, -52, 23, + 46, 44, -56, -16, -55, -46, 22, 83, -13, -42, -7, 13, 81, 49, 3, -9, + -30, -47, -30, 3, 23, 6, -7, -20, -44, 10, 96, -13, 0, 16, 31, 47, + 61, 75, 87, 98, 107, 115, 121, 125, 127, 127, 125, 121, 116, 108, 99, 88, + 75, 62, 47, 32, 16, 0, -16, -31, -47, -61, -75, -87, -98, -108, -116, -122, + -126, -128, -128, -126, -123, -117, -109, -100, -89, -77, -64, -49, -34, -18, -2, 14, + 29, 45, 59, 73, 86, 97, 106, 114, 121, 125, 127, 127, 126, 122, 116, 109, + 100, 89, 77, 63, 49, 34, 18, 2, -14, -30, -45, -60, -73, -86, -97, -107, + -115, -121, -126, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, -36, -20, + -4, 12, 28, 43, 58, 72, 84, 96, 106, 114, 120, 124, 127, 127, 126, 122, + 117, 109, 100, 90, 78, 64, 50, 35, 19, 3, -13, -29, -44, -59, -73, -85, + -97, -107, -115, -121, -125, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, + -36, -20, -4, 12, 2, 5, 5, 0, -16, -9, -2, -19, 4, 18, 6, 10, + -16, -21, 22, -2, 3, -7, 21, 43, -57, -37, 46, -39, -31, 78, 23, -23, + -10, -10, -7, -52, 44, 50, -44, 9, -9, -46, 47, 12, -75, 40, 45, 32, + -10, -25, -15, -45, 24, 44, -40, -10, 18, -48, -29, 63, 44, -30, -1, 83, + -45, -94, 96, 0, -103, 21, 29, -42, 21, 80, -25, -15, 26, 39, -79, -18, + 73, -111, -45, 61, 29, 55, -22, -77, 40, 9, -72, 78, 35, -1, -1, -69, + 12, -50, -42, 123, 45, -7, -39, -86, 3, 51, 30, 28, -4, -33, -41, -66, + 54, -8, -30, 127, -7, -30, -32, -39, 48, -65, 20, 121, -33, -14, -53, -32, + 46, -24, 36, 98, -49, -39, -61, 1, 49, -54, 65, 59, -83, -11, -49, 32, + 39, -72, 113, 59, -83, -11, -49, 32, 39, -72, 113, 59, -2, -4, -4, -7, + -8, -8, -7, -4, -3, -2, 1, 4, 6, 6, 6, 4, 2, 0, -2, -3, + -4, -7, -7, -5, -3, 0, 4, 9, 11, 11, 9, 7, 4, 1, -3, -7, + -9, -12, -13, -16, -19, -19, -13, -2, 9, 17, 19, 20, 18, 13, 8, 3, + 0, -2, -3, -8, -14, -21, -25, -21, -9, 4, 15, 23, 28, 25, 20, 9, + -7, -21, -14, 3, 3, -18, -38, -49, -32, -7, 8, 14, 26, 37, 42, 37, + 26, 7, -18, -27, -5, 8, -7, -24, -34, -40, -32, -19, 1, 17, 42, 56, + 58, 40, -19, -81, 1, 67, 0, -60, -49, -27, -24, 0, -18, -24, -8, 37, + 67, 70, 59, 34, -42, -81, 7, 51, -12, -54, -37, -14, -25, -14, -16, -24, + 4, 55, 75, 102, 52, -102, -104, 90, 30, -48, -76, 1, -14, 0, -2, -2, + -3, -5, -7, -8, -8, -7, -6, -4, -2, 0, 1, 3, 4, 6, 6, 6, + 6, 5, 4, 3, 1, 0, 0, -3, -4, -7, -10, -11, -11, -8, -6, 1, + 5, 6, 8, 11, 11, 8, 5, 5, 2, 1, 0, 0, -2, 1, -4, -16, + -36, -27, -5, 6, -3, -6, 0, -6, 2, 27, 24, 19, 16, 9, 3, 0, + -4, 2, 1, 9, 19, -14, -79, -32, 22, -4, -22, -14, 25, 8, -11, 13, + 28, 16, 19, 16, 1, -2, -4, -3, -6, 28, 38, -59, -111, 25, 16, -16, + -40, 16, 24, -20, 4, 24, 29, 17, 27, 13, 1, -10, -6, -10, -8, 43, + 61, -68, -128, 28, 12, -15, -39, 12, 21, -28, 12, 37, 25, 12, 27, 11, + 0, -16, -2, -12, -11, 52, 67, -68, 35, 54, 47, 4, -60, -92, -68, -27, + 0, -2, -18, -20, -6, 2, -8, -15, -11, -3, 3, -7, -11, -6, -2, 7, + 15, 18, 19, 22, 27, 40, 40, 29, 20, 24, 28, 34, 30, 25, 32, 20, + 14, 9, 16, 19, 17, 6, -1, 3, -6, -14, -23, -18, -7, 1, -18, -18, + -24, -25, -24, -35, -35, -35, -21, -12, -14, -21, -17, -29, -24, -31, -34, -9, + -11, -9, -3, -7, -7, 6, -17, -22, 7, 16, 14, -4, -11, 10, 33, 24, + 21, 27, 3, -19, -25, -18, 17, 50, 48, 49, 61, 31, -48, -103, -73, 9, + 56, 70, 82, 109, 127, 71, -46, -127, -96, -30, -4, 9, 47, 103, 117, 60, + -39, -110, -119, -94, -64, -40, -4, 35, -8, -14, -9, -5, -4, -3, 6, 18, + 19, 6, -14, -20, -12, -3, -3, -6, 2, 21, 28, 13, -16, -26, -14, -6, + -6, -7, 1, 27, 36, 18, -15, -27, -15, -3, -2, -10, -6, 25, 41, 22, + -17, -34, -18, -4, -3, -16, -12, 29, 56, 31, -24, -44, -20, -4, -1, -19, + -22, 31, 73, 47, -27, -62, -25, -2, 4, -21, -36, 26, 91, 61, -27, -79, + -33, 0, 10, -18, -49, 14, 106, 82, -24, -94, -40, 8, 14, -12, -59, 1, + 112, 105, -19, -106, -51, 12, 16, -4, -63, -13, 110, 127, -12, -114, -51, 0, + -1, -4, -8, -11, -8, -2, 0, 7, 14, 21, 46, 92, 120, 76, -36, -121, + -119, -73, -31, -7, 3, 2, -4, -6, 2, 22, 60, 106, 116, 43, -72, -128, + -105, -57, -21, -3, 3, -1, -6, -5, 7, 33, 76, 117, 102, 5, -100, -127, + -89, -43, -13, 0, 2, -3, -7, -2, 14, 46, 92, 122, 79, -34, -118, -118, + -72, -31, -8, 1, 0, -5, -7, 2, 23, 61, 107, 118, 46, -69, -126, -104, + -56, -21, -4, 1, 0, -4, -5, 0, 16, 48, 87, 103, 60, -25, -87, -94, + -58, -20, -4, -11, 12, 24, 31, -36, 29, -9, 2, -38, -5, -5, -10, -33, + -10, -24, -20, -39, -36, -18, -38, -58, -5, -22, -15, -15, 90, -42, -3, -8, + 25, 6, 28, 25, 17, 25, -16, 28, 80, 22, 12, -6, 35, 22, 8, -7, + 28, 29, -19, 7, 8, -1, -29, -23, 10, -23, -13, -26, -17, -20, -33, -41, + -19, -28, -64, -13, -21, -13, -29, 54, 25, -20, -36, 42, -4, 13, 52, -8, + 47, -14, 9, 42, 88, -12, 20, -5, 43, 22, -11, 127, 127, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, -128, -128, -128, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, -128, 1, 4, 7, 10, 12, 16, 19, 22, 25, 28, 31, 35, 38, 42, + 45, 49, 51, 56, 58, 63, 65, 70, 73, 78, 80, 85, 87, 93, 95, 100, + 102, 108, 109, 117, 114, 127, 85, -63, -60, -64, -60, -62, -59, -61, -59, -61, + -58, -60, -58, -59, -58, -58, -57, -57, -55, -55, -54, -54, -52, -51, -50, -49, + -47, -46, -44, -43, -41, -40, -37, -36, -34, -32, -30, -28, -25, -24, -21, -19, + -16, -14, -11, -9, -6, 1, 1, 4, 7, 10, 12, 16, 19, 22, 25, 28, + 31, 35, 38, 42, 45, 49, 51, 56, 58, 63, 65, 70, 73, 78, 80, 85, + 87, 93, 95, 100, 102, 108, 109, 117, 114, 127, 85, -63, -60, -64, -60, -62, + -59, -61, -59, -61, -58, -60, -58, -59, -58, -58, -57, -57, -55, -55, -54, -54, + -52, -51, -50, -49, -47, -46, -44, -43, -41, -40, -37, -36, -34, -32, -30, -28, + -25, -24, -21, -19, -16, -14, -11, -9, -6, 1, -3, -19, -24, -14, -8, -19, + -12, -10, -5, -12, -50, -19, 23, 35, 4, -20, -7, -26, 9, 40, 69, 16, + -88, -69, -38, -32, -27, 41, 65, 55, 18, -40, -38, -20, 66, 127, 121, 57, + -23, -55, -48, 13, 53, 31, -20, -38, -13, 10, 8, 0, 12, 17, 13, 2, + -1, -3, -3, 6, 13, 7, -17, -24, -12, 4, 3, -10, -20, -32, -22, -18, + -12, -3, 6, 16, 22, 29, 30, 27, 20, 11, 0, -7, -12, -11, -5, 0, + -3, -14, -20, -16, -9, -9, -17, -25, -29, -31, -33, -35, -33, -29, -25, -22, + -20, -17, -14, -13, -12, -11, -9, -10, -13, -15, -11, -5, 3, 9, 10, 9, + 9, 12, 18, 30, 50, 80, 119, 127, 102, 82, 77, 60, 37, 5, -34, -70, + -84, -83, -74, -60, -46, -29, -12, -2, 6, -23, 28, -20, 50, 50, -14, 14, + -28, -2, 28, 52, -25, -13, -52, 43, -41, -9, -26, 36, -25, -20, -17, 3, + -11, 38, 30, -61, 12, -6, 5, 45, 41, -4, 4, -20, -12, 45, 33, -11, + -29, -44, 27, -17, -36, -1, 17, -11, -31, -12, 4, -10, 37, 20, -39, -23, + 0, -104, -55, -11, 24, 33, 30, 7, -15, -31, -30, -25, -23, -20, -9, 10, + 31, 59, 91, 111, 115, 92, 51, 7, -33, -64, -81, -81, -71, -51, -22, 16, + 52, 74, 82, 81, 68, 38, 0, -40, -81, -112, -124, -102, -57, -11, 0, 7, + -23, -58, -85, -100, -104, -100, -92, -81, -69, -57, -45, -33, -22, -11, -1, 8, + 18, 27, 37, 49, 62, 79, 99, 118, 124, 111, 84, 53, 26, 5, -8, -14, + -15, -12, -6, 2, 12, 21, 28, 26, 9, -22, -58, -20, 7, 10, 21, -14, + 9, 22, 57, 62, 127, 56, 28, 26, -28, 10, -81, -31, -81, -35, -19, -55, + -27, -4, -4, 23, 49, 88, 85, 22, 1, 0, -3, 18, -22, -12, -39, -14, + -47, -67, -53, -53, -33, -20, 8, -22, 25, 30, 6, -19, -62, -19, 10, 83, + 57, -67, -88, -52, 63, 127, 42, -63, -121, -70, 82, 111, 46, -43, -114, -35, + 45, 73, 39, -19, -54, -41, 9, 49, 24, -16, -14, -9, -6, 10, 8, -22, + 25, 30, 6, -19, -62, -19, 10, 83, 57, -67, -88, -52, 63, 127, 42, -63, + -121, -70, 82, 111, 46, -43, -114, -35, 45, 73, 39, -19, -54, -41, 9, 49, + 24, -16, -14, -9, -6, 10, 8, -22, 25, 30, 6, -19, -62, -19, 10, 83, + 57, -67, -88, -52, 63, 127, 42, -63, -121, -70, 82, 111, 46, -43, -114, -35, + 45, 73, 39, -19, -54, -41, 9, 49, 24, -16, -14, -9, -6, 10, -18, -15, + 80, 127, 20, 18, 72, 60, -36, 22, 33, -73, -105, -27, 29, 25, 8, 43, + 23, -22, -35, -14, -8, -34, -25, -5, -18, -46, -13, -28, -3, -19, -10, -28, + -10, 17, -18, 96, 127, 123, 127, 126, 126, 95, 61, 22, -17, -56, -95, -118, + -123, -128, -128, -128, -128, -128, -128, -128, -128, -124, -93, -55, -17, 25, 62, 100, + 107, 119, 119, 127, 41, -4, -4, -10, -27, -62, -102, -128, -117, -85, -76, -49, + -25, -7, 15, 24, 14, 0, -9, -12, -3, 33, 81, 105, 111, 101, 80, 62, + 45, 30, 16, 8, 1, -4, 126, 86, -44, -68, -88, -63, 4, 84, 127, 14, + -29, -51, -127, -47, 58, 87, 82, 24, -17, -112, -113, 18, 46, 72, 102, 19, + -72, -118, -51, 9, 27, 126, 19, -53, -114, -108, 15, 122, 111, 21, -71, -70, + 5, 59, 83, 23, -72, -84, -49, 12, 37, 38, -28, -65, -26, 7, -2, 11, + 5, 23, 68, 19, 27, -54, 15, -24, -31, 46, 71, 81, -24, -33, -87, -41, + -71, -61, -70, -36, -44, -3, 12, -25, -20, 20, 68, 85, 127, 15, 50, -5, + 27, 51, 82, 106, 127, 118, 101, 92, 74, 52, 39, 37, 14, -41, -105, -108, + -94, -119, -124, -93, -57, -40, -37, -45, -51, -41, -5, 51, 127, 127, -128, -128, + -128, -128, -128, -128, -128, -128, -128, -128, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127 +}; + +const EAS_U32 eas_sampleLengths[] = +{ + 16820, 16708, 16592, 11754, 10954, 10295, 9922, 7489, + 5779, 5462, 4452, 3779, 3115, 3093, 3057, 3024, + 2818, 2776, 2171, 2168, 2052, 1902, 1835, 1614, + 1603, 1528, 1517, 1480, 1455, 1424, 1387, 1302, + 1262, 1254, 1230, 1227, 1185, 1181, 1178, 1168, + 1132, 1120, 1034, 1033, 1018, 994, 964, 926, + 907, 886, 881, 866, 830, 817, 816, 813, + 749, 748, 739, 720, 652, 610, 610, 583, + 564, 561, 556, 549, 542, 535, 530, 530, + 516, 508, 492, 478, 461, 448, 437, 431, + 423, 418, 403, 402, 400, 394, 387, 387, + 367, 357, 347, 347, 341, 336, 334, 329, + 325, 312, 294, 284, 277, 265, 255, 233, + 230, 213, 207, 205, 194, 193, 184, 181, + 181, 167, 164, 158, 152, 152, 145, 139, + 128, 103, 100, 88, 87, 84, 84, 72, + 71, 55, 46, 45, 43, 40, 40, 40, + 37, 35, 32, 32, 30, 29, 27, 23, + 22, 21, 21, 21, 21, 20 +}; + +const EAS_U32 eas_sampleOffsets[] = +{ + 0x00000000, 0x000041b4, 0x000082f8, 0x0000c3c8, 0x0000f1b2, 0x00011c7c, 0x000144b3, 0x00016b75, + 0x000188b6, 0x00019f49, 0x0001b49f, 0x0001c603, 0x0001d4c6, 0x0001e0f1, 0x0001ed06, 0x0001f8f7, + 0x000204c7, 0x00020fc9, 0x00021aa1, 0x0002231c, 0x00022b94, 0x00023398, 0x00023b06, 0x00024231, + 0x0002487f, 0x00024ec2, 0x000254ba, 0x00025aa7, 0x0002606f, 0x0002661e, 0x00026bae, 0x00027119, + 0x0002762f, 0x00027b1d, 0x00028003, 0x000284d1, 0x0002899c, 0x00028e3d, 0x000292da, 0x00029774, + 0x00029c04, 0x0002a070, 0x0002a4d0, 0x0002a8da, 0x0002ace3, 0x0002b0dd, 0x0002b4bf, 0x0002b883, + 0x0002bc21, 0x0002bfac, 0x0002c322, 0x0002c693, 0x0002c9f5, 0x0002cd33, 0x0002d064, 0x0002d394, + 0x0002d6c1, 0x0002d9ae, 0x0002dc9a, 0x0002df7d, 0x0002e24d, 0x0002e4d9, 0x0002e73b, 0x0002e99d, + 0x0002ebe4, 0x0002ee18, 0x0002f049, 0x0002f275, 0x0002f49a, 0x0002f6b8, 0x0002f8cf, 0x0002fae1, + 0x0002fcf3, 0x0002fef7, 0x000300f3, 0x000302df, 0x000304bd, 0x0003068a, 0x0003084a, 0x000309ff, + 0x00030bae, 0x00030d55, 0x00030ef7, 0x0003108a, 0x0003121c, 0x000313ac, 0x00031536, 0x000316b9, + 0x0003183c, 0x000319ab, 0x00031b10, 0x00031c6b, 0x00031dc6, 0x00031f1b, 0x0003206b, 0x000321b9, + 0x00032302, 0x00032447, 0x0003257f, 0x000326a5, 0x000327c1, 0x000328d6, 0x000329df, 0x00032ade, + 0x00032bc7, 0x00032cad, 0x00032d82, 0x00032e51, 0x00032f1e, 0x00032fe0, 0x000330a1, 0x00033159, + 0x0003320e, 0x000332c3, 0x0003336a, 0x0003340e, 0x000334ac, 0x00033544, 0x000335dc, 0x0003366d, + 0x000336f8, 0x00033778, 0x000337df, 0x00033843, 0x0003389b, 0x000338f2, 0x00033946, 0x0003399a, + 0x000339e2, 0x00033a29, 0x00033a60, 0x00033a8e, 0x00033abb, 0x00033ae6, 0x00033b0e, 0x00033b36, + 0x00033b5e, 0x00033b83, 0x00033ba6, 0x00033bc6, 0x00033be6, 0x00033c04, 0x00033c21, 0x00033c3c, + 0x00033c53, 0x00033c69, 0x00033c7e, 0x00033c93, 0x00033ca8, 0x00033cbd +}; + +/*---------------------------------------------------------------------------- + * S_EAS + *---------------------------------------------------------------------------- +*/ +const S_EAS easSoundLib = +{ + 0x01534145, + 0x00105622, + eas_banks, + eas_programs, + eas_regions, + eas_articulations, + eas_sampleLengths, + eas_sampleOffsets, + eas_samples, + 0, + 1, + 1, + 377, + 185, + 150, + 0 +}; /* end S_EAS */ + +/*---------------------------------------------------------------------------- + * Statistics + * + * Number of banks: 1 + * Number of programs: 1 + * Number of regions: 377 + * Number of articulations: 185 + * Number of samples: 150 + * Size of sample pool: 212050 + *---------------------------------------------------------------------------- +*/ +/* end wt_200k_G.c */ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/misc/eas_host.c b/code/embeddedaudiosynthesis/arm-wt-22k/misc/eas_host.c new file mode 100755 index 0000000..01e5ce3 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/misc/eas_host.c @@ -0,0 +1,787 @@ +/*---------------------------------------------------------------------------- + * + * File: + * eas_host.c + * + * Contents and purpose: + * This file contains the host wrapper functions for stdio, stdlib, etc. + * This is a sample version that wraps the standard library functions. + * Modify this file to suit the needs of your particular system. + * + * EAS_MAX_FILE_HANDLES sets the maximum number of MIDI streams within + * a MIDI type 1 file that can be played. To maintain efficiency, data + * is buffered locally when byte access is used (EAS_HWGetByte). The + * size of the buffer is set by EAS_FILE_BUFFER_SIZE. + * + * EAS_HW_FILE is a structure to support local file buffering. It + * comprises the OS File handle, some data related to the local file + * buffer, the position of the next byte of data to be read, the dup + * flag which when set, indicates that the handle has been duplicated, + * and the data buffer. Since the data buffer is only used for byte + * access, it does not need to be large. + * + * If the file system supports duplicate file handles and buffering, + * this entire subsystem can be replaced with direct calls to the + * native file I/O routines. + * + * If the system has enough memory to support reading the entire file + * into memory, it will be much more efficient to do so on the call to + * EAS_HWOpenFile and then close the file. Simply substitute a memory + * pointer for the FILE* pointer. Calls to EAS_HW_DupHandle will work + * as they do in this version. In the call to EAS_HWCloseFile, instead + * of calling fclose, free the memory containing the file data. + * + * Copyright 2005 Sonic Network Inc. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *---------------------------------------------------------------------------- + * Revision Control: + * $Revision: 853 $ + * $Date: 2007-09-05 09:54:17 -0700 (Wed, 05 Sep 2007) $ + *---------------------------------------------------------------------------- +*/ + +#ifdef _lint +#include "lint_stdlib.h" +#else +#include +#include +#include +#endif + +#include "eas_host.h" + +// #define DEBUG_FILE_IO + +/* Only for debugging LED, vibrate, and backlight functions */ +#include "eas_report.h" + +#ifndef EAS_MAX_FILE_HANDLES +#define EAS_MAX_FILE_HANDLES 32 +#endif + +#ifndef EAS_FILE_BUFFER_SIZE +#define EAS_FILE_BUFFER_SIZE 32 +#endif + +/* + * this structure and the related function are here + * to support the ability to create duplicate handles + * and buffering into a single file. If the OS supports + * duplicate file handles natively, this code can be + * stripped to eliminate double-buffering. + */ +typedef struct eas_hw_file_tag +{ + FILE *pFile; + EAS_I32 bytesInBuffer; + EAS_I32 readIndex; + EAS_I32 filePos; + EAS_BOOL dup; + EAS_U8 buffer[EAS_FILE_BUFFER_SIZE]; +} EAS_HW_FILE; + +typedef struct eas_hw_inst_data_tag +{ + EAS_HW_FILE files[EAS_MAX_FILE_HANDLES]; +} EAS_HW_INST_DATA; + +/* local memory for files and streams */ +#ifdef _STATIC_MEMORY +EAS_HW_INST_DATA fileData; +#endif + +/*---------------------------------------------------------------------------- + * EAS_HWInit + * + * Initialize host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData) +{ + + /* need to track file opens for duplicate handles */ +#ifndef _STATIC_MEMORY + *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA)); + if (!(*pHWInstData)) + return EAS_ERROR_MALLOC_FAILED; +#else + *pHWInstData = &fileData; +#endif + EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA)); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * EAS_HWShutdown + * + * Shut down host wrapper interface + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData) +{ + +#ifndef _STATIC_MEMORY + free(hwInstData); +#endif + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMalloc + * + * Allocates dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +#ifdef _STATIC_MEMORY +/*lint -esym(715, size) not used in static memory model */ +#endif +void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size) +{ +#ifdef _STATIC_MEMORY + return NULL; +#else + return malloc((EAS_U32)size); +#endif +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFree + * + * Frees dynamic memory + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +#ifdef _STATIC_MEMORY +/*lint -esym(715, p) not used in static memory model */ +#endif +void EAS_HWFree(EAS_HW_DATA_HANDLE hwInstData, void *p) +{ +#ifndef _STATIC_MEMORY + free(p); +#endif +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCpy + * + * Copy memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount) +{ + return memcpy(dest,src,(size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemSet + * + * Set memory wrapper + * + *---------------------------------------------------------------------------- +*/ +void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount) +{ + return memset(dest,val,(size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWMemCmp + * + * Compare memory wrapper + * + *---------------------------------------------------------------------------- +*/ +EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount) +{ + return (EAS_I32) memcmp(s1, s2, (size_t) amount); +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWOpenFile + * + * Open a file for read or write + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) +{ + EAS_HW_FILE *file; + int i; + + /* set return value to NULL */ + *pFile = NULL; + + /* only support read mode at this time */ + if (mode != EAS_FILE_READ) + return EAS_ERROR_INVALID_FILE_MODE; + + /* find an empty entry in the file table */ + file = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (file->pFile == NULL) + { + /* open the file */ + if (locator->path) + file->pFile = fopen((const char*) locator->path, "rb"); + if (file->pFile == NULL) + return EAS_ERROR_FILE_OPEN_FAILED; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWOpenFile: Open file %d\n", i); +#endif + + /* initialize some values */ + file->bytesInBuffer = 0; + file->readIndex = 0; + file->filePos = 0; + file->dup = EAS_FALSE; + + *pFile = file; + return EAS_SUCCESS; + } + file++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFillBuffer + * + * Fill buffer from file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFillBuffer (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file) +{ + /* reposition the file pointer */ + if (fseek(file->pFile, file->filePos, SEEK_SET) != 0) + return EAS_ERROR_FILE_SEEK; + + /* read some data from the file */ + file->bytesInBuffer = (EAS_I32) fread(file->buffer, 1, EAS_FILE_BUFFER_SIZE, file->pFile); + file->readIndex = 0; + if (file->bytesInBuffer == 0) + return EAS_EOF; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWReadFile + * + * Read data from a file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) +{ + EAS_RESULT result; + EAS_I32 temp; + EAS_U8 *p = pBuffer; + EAS_I32 bytesLeft = n; + + *pBytesRead = 0; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWReadFile: Reading %d bytes from position %d\n", n, file->filePos); +#endif + + /* try to fulfill request from buffer */ + for (;bytesLeft > 0;) + { + /* how many bytes can we get from buffer? */ + temp = file->bytesInBuffer - file->readIndex; + if (temp > bytesLeft) + temp = bytesLeft; + + /* copy data from buffer */ + EAS_HWMemCpy(p, &file->buffer[file->readIndex], temp); + *pBytesRead += temp; + file->readIndex += temp; + file->filePos += temp; + bytesLeft -= temp; + p += temp; + + /* don't refill buffer if request is bigger than buffer */ + if ((bytesLeft == 0) || (bytesLeft >= EAS_FILE_BUFFER_SIZE)) + break; + + /* refill buffer */ + if ((result = EAS_HWFillBuffer(hwInstData, file)) != EAS_SUCCESS) + return result; + } + + /* more to read? do unbuffered read directly to target memory */ + if (bytesLeft) + { + + /* position the file pointer */ + if (fseek(file->pFile, file->filePos, SEEK_SET) != 0) + return EAS_ERROR_FILE_SEEK; + + /* read data in the buffer */ + /*lint -e{826} lint doesn't like this with STATIC_MEMORY defined for some reason */ + temp = (EAS_I32) fread(p, 1, (size_t) bytesLeft, file->pFile); + *pBytesRead += temp; + file->filePos += temp; + + /* reset buffer info */ + file->bytesInBuffer = 0; + file->readIndex = 0; + } + +#ifdef DEBUG_FILE_IO + { +#define BYTES_PER_LINE 16 + char str[BYTES_PER_LINE * 3 + 1]; + EAS_INT i; + for (i = 0; i < (n > BYTES_PER_LINE ? BYTES_PER_LINE : n) ; i ++) + sprintf(&str[i*3], "%02x ", ((EAS_U8*)pBuffer)[i]); + if (i) + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "%s\n", str); + } +#endif + + /* were n bytes read? */ + if (*pBytesRead != n) + return EAS_EOF; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetByte + * + * Read a byte from a file + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) +{ + EAS_RESULT result; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* use local buffer - do we have any data? */ + if (file->readIndex >= file->bytesInBuffer) + { + if ((result = EAS_HWFillBuffer(hwInstData, file)) != EAS_SUCCESS) + return result; + + /* if nothing to read, return EOF */ + if (file->bytesInBuffer == 0) + return EAS_EOF; + } + + /* get a character from the buffer */ + *((EAS_U8*) p) = file->buffer[file->readIndex++]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetByte: Reading from position %d, byte = 0x%02x\n", file->filePos, *(EAS_U8*)p); +#endif + + file->filePos++; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetWord + * + * Read a 16-bit value from the file + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_I32 count; + EAS_U8 c[2]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetWord: Reading 2 bytes from position %d\n", file->filePos); +#endif + + /* read 2 bytes from the file */ + if ((result = EAS_HWReadFile(hwInstData, file, c, 2, &count)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U16*) p) = ((EAS_U16) c[0] << 8) | c[1]; + else + *((EAS_U16*) p) = ((EAS_U16) c[1] << 8) | c[0]; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWGetDWord + * + * Read a 16-bit value from the file + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) +{ + EAS_RESULT result; + EAS_I32 count; + EAS_U8 c[4]; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetDWord: Reading 4 bytes from position %d\n", file->filePos); +#endif + + /* read 4 bytes from the file */ + if ((result = EAS_HWReadFile(hwInstData, file, c, 4, &count)) != EAS_SUCCESS) + return result; + + /* order them as requested */ + if (msbFirst) + *((EAS_U32*) p) = ((EAS_U32) c[0] << 24) | ((EAS_U32) c[1] << 16) | ((EAS_U32) c[2] << 8) | c[3]; + else + *((EAS_U32*) p) = ((EAS_U32) c[3] << 24) | ((EAS_U32) c[2] << 16) | ((EAS_U32) c[1] << 8) | c[0]; + + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFilePos + * + * Returns the current location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) +{ + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + *pPosition = file->filePos; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeek + * + * Seek to a specific location in the file + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + EAS_I32 newIndex; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWFileSeek: Seeking to new position %d\n", file->filePos); +#endif + + /* is new position in current buffer? */ + newIndex = position - file->filePos + file->readIndex; + if ((newIndex >= 0) && (newIndex < file->bytesInBuffer)) + { + file->readIndex = newIndex; + file->filePos = position; + return EAS_SUCCESS; + } + + /* save new position and reset buffer info so EAS_HWGetByte doesn't fail */ + file->filePos = position; + file->bytesInBuffer = 0; + file->readIndex = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileSeekOfs + * + * Seek forward or back relative to the current position + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) +{ + EAS_I32 temp; + +#ifdef DEBUG_FILE_IO + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWFileSeekOfs: Seeking to new position %d\n", file->filePos + position); +#endif + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* is new position in current buffer? */ + temp = position + file->readIndex; + if ((temp >= 0) && (temp < file->bytesInBuffer)) + { + file->readIndex = temp; + file->filePos += position; + return EAS_SUCCESS; + } + + /* save new position and reset buffer info so EAS_HWGetByte doesn't fail */ + file->filePos += position; + file->bytesInBuffer = 0; + file->readIndex = 0; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWFileLength + * + * Return the file length + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) +{ + long pos; + + /* check handle integrity */ + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + if ((pos = ftell(file->pFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(file->pFile, 0L, SEEK_END) != 0) + return EAS_ERROR_FILE_LENGTH; + if ((*pLength = ftell(file->pFile)) == -1L) + return EAS_ERROR_FILE_LENGTH; + if (fseek(file->pFile, pos, SEEK_SET) != 0) + return EAS_ERROR_FILE_LENGTH; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWDupHandle + * + * Duplicate a file handle + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pDupFile) +{ + EAS_HW_FILE *dupfile; + int i; + + /* check handle integrity */ + *pDupFile = NULL; + if (file->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* find an empty entry in the file table */ + dupfile = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* is this slot being used? */ + if (dupfile->pFile == NULL) + { + + /* copy info from the handle to be duplicated */ + dupfile->filePos = file->filePos; + dupfile->pFile = file->pFile; + + /* set the duplicate handle flag */ + dupfile->dup = file->dup = EAS_TRUE; + + /* initialize some values */ + dupfile->bytesInBuffer = 0; + dupfile->readIndex = 0; + + *pDupFile = dupfile; + return EAS_SUCCESS; + } + dupfile++; + } + + /* too many open files */ + return EAS_ERROR_MAX_FILES_OPEN; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWClose + * + * Wrapper for fclose function + * + *---------------------------------------------------------------------------- +*/ +EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) +{ + EAS_HW_FILE *file2,*dupFile; + int i; + + /* check handle integrity */ + if (file1->pFile == NULL) + return EAS_ERROR_INVALID_HANDLE; + + /* check for duplicate handle */ + if (file1->dup) + { + dupFile = NULL; + file2 = hwInstData->files; + for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) + { + /* check for duplicate */ + if ((file1 != file2) && (file2->pFile == file1->pFile)) + { + /* is there more than one duplicate? */ + if (dupFile != NULL) + { + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; + } + + /* this is the first duplicate found */ + dupFile = file2; + } + file2++; + } + + /* there is only one duplicate, clear the dup flag */ + if (dupFile) + dupFile->dup = EAS_FALSE; + else + /* if we get here, there's a serious problem */ + return EAS_ERROR_HANDLE_INTEGRITY; + + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; + } + + /* no duplicates - close the file */ + if (fclose(file1->pFile) != 0) + return EAS_ERROR_CLOSE_FAILED; + + /* clear this entry and return */ + file1->pFile = NULL; + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWVibrate + * + * Turn on/off vibrate function + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "Vibrate state: %d\n", state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWLED + * + * Turn on/off LED + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "LED state: %d\n", state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWBackLight + * + * Turn on/off backlight + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) +{ + EAS_ReportX(_EAS_SEVERITY_NOFILTER, "Backlight state: %d\n", state); + return EAS_SUCCESS; +} + +/*---------------------------------------------------------------------------- + * + * EAS_HWYield + * + * This function is called periodically by the EAS library to give the + * host an opportunity to allow other tasks to run. There are two ways to + * use this call: + * + * If you have a multi-tasking OS, you can call the yield function in the + * OS to allow other tasks to run. In this case, return EAS_FALSE to tell + * the EAS library to continue processing when control returns from this + * function. + * + * If tasks run in a single thread by sequential function calls (sometimes + * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to + * return to the caller. Be sure to check the number of bytes rendered + * before passing the audio buffer to the codec - it may not be filled. + * The next call to EAS_Render will continue processing until the buffer + * has been filled. + * + *---------------------------------------------------------------------------- +*/ +/*lint -esym(715, hwInstData) hwInstData available for customer use */ +EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData) +{ + /* put your code here */ + return EAS_FALSE; +} diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/Leadsol.mxmf b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/Leadsol.mxmf new file mode 100755 index 0000000..239f500 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/Leadsol.mxmf differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/Leadsol_out.wav b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/Leadsol_out.wav new file mode 100755 index 0000000..43d326c Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/Leadsol_out.wav differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/WAVEtest.wav b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/WAVEtest.wav new file mode 100755 index 0000000..0d8178a Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/WAVEtest.wav differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/WAVEtest_out.wav b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/WAVEtest_out.wav new file mode 100755 index 0000000..1a66130 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/WAVEtest_out.wav differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/abba.imy b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/abba.imy new file mode 100755 index 0000000..9a056e6 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/abba.imy @@ -0,0 +1,10 @@ +BEGIN:IMELODY +VERSION:1.2 +FORMAT:CLASS1.0 +NAME:DanceQueen +COMPOSER: downloaded at www.ringtones.perbang.dk +BEAT:112 +STYLE:S1 +VOLUME:V10 +MELODY:*5#c1*4b2*5d1*5#c4*4b3*4a4*4b3.*5#c3*5#c2*5a4*5a3*5#g4*5#g3*5#f4*5#f1*5#c1*4b2*5d1*5#c4*4b3*4a4*4b3.*5#c3*5#c2*4b2*4a1.r2*5#c2*4b3*4b1r4r5*5#c2*4b3*4b2*5#c2*4a3.*4b3.*4#g3*4a3.*4b3.*4#g3*4a4*4#g4*4#f2.*5#c3*4b3.*4a3*4#g2*4a3*4a1r4*4#g2*4a3*4a2.*4b4*4a3*4#g4*4#g3.*4a3.*4a1 +END:IMELODY diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/abba_out.wav b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/abba_out.wav new file mode 100755 index 0000000..acf40d5 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/abba_out.wav differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/ants.mid b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/ants.mid new file mode 100755 index 0000000..d4ead53 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/ants.mid differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/ants_out.wav b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/ants_out.wav new file mode 100755 index 0000000..abb724d Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/ants_out.wav differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/greensleeves.rtttl b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/greensleeves.rtttl new file mode 100755 index 0000000..37865d1 --- /dev/null +++ b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/greensleeves.rtttl @@ -0,0 +1 @@ +Greensleaves:d=4, o=5, b=140:g, 2a#, c6, d.6, 8d#6, d6, 2c6, a, f., 8g, a, 2a#, g, g., 8f, g, 2a, f, 2d, g, 2a#, c6, d.6, 8e6, d6, 2c6, a, f., 8g, a, a#., 8a, g, f#., 8e, f#, 2g \ No newline at end of file diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/greensleeves_out.wav b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/greensleeves_out.wav new file mode 100755 index 0000000..5d61fb2 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/greensleeves_out.wav differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/test.ota b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/test.ota new file mode 100755 index 0000000..7aa5f99 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/test.ota differ diff --git a/code/embeddedaudiosynthesis/arm-wt-22k/vectors/test_out.wav b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/test_out.wav new file mode 100755 index 0000000..45ef142 Binary files /dev/null and b/code/embeddedaudiosynthesis/arm-wt-22k/vectors/test_out.wav differ diff --git a/code/embeddedaudiosynthesis/docs/EASLibrary3_5.odt b/code/embeddedaudiosynthesis/docs/EASLibrary3_5.odt new file mode 100755 index 0000000..5fd3f37 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/EASLibrary3_5.odt differ diff --git a/code/embeddedaudiosynthesis/docs/EASLibrary3_5.pdf b/code/embeddedaudiosynthesis/docs/EASLibrary3_5.pdf new file mode 100755 index 0000000..910ccc1 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/EASLibrary3_5.pdf differ diff --git a/code/embeddedaudiosynthesis/docs/EAS_API_Reference.odt b/code/embeddedaudiosynthesis/docs/EAS_API_Reference.odt new file mode 100755 index 0000000..bdfa441 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/EAS_API_Reference.odt differ diff --git a/code/embeddedaudiosynthesis/docs/EAS_API_Reference.pdf b/code/embeddedaudiosynthesis/docs/EAS_API_Reference.pdf new file mode 100755 index 0000000..71645cf Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/EAS_API_Reference.pdf differ diff --git a/code/embeddedaudiosynthesis/docs/EAS_Library_Integration_Guide.odt b/code/embeddedaudiosynthesis/docs/EAS_Library_Integration_Guide.odt new file mode 100755 index 0000000..b0bcb0d Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/EAS_Library_Integration_Guide.odt differ diff --git a/code/embeddedaudiosynthesis/docs/EAS_Library_Integration_Guide.pdf b/code/embeddedaudiosynthesis/docs/EAS_Library_Integration_Guide.pdf new file mode 100755 index 0000000..6cb4541 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/EAS_Library_Integration_Guide.pdf differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines.html b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines.html new file mode 100755 index 0000000..2ade2e3 --- /dev/null +++ b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines.html @@ -0,0 +1,2442 @@ + + + + + + + + +JET Authoring Guidelines + + + + + + + + +
+   Copyright (C) 2009 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ +
+ +

JET™ Content Authoring Guidelines

+ +

JET Interactive Music Engine

+ +

Vrs 1.0

+ +

Authored by SONiVOX

+ +

www.sonivoxrocks.com

+ +

Copyright 2009 Sonic Network, Inc.

+ +

 

+ +

 

+ +

1         +Introduction

+ +

1.1        +Overview

+ +

This document contains content creation +guidelines for composers and sound designers authoring music and sound effects +for the SONiVOX JET platform.  JET is an +interactive music player for small embedded devices, including the Google Android +platform. It allows applications to include interactive music soundtracks, in MIDI format, that respond in real-time to game play +events and user interaction.

+ +

 

+ +

JET works in conjunction with SONiVOX’s +Embedded Audio Synthesizer (EAS) which is the MIDI +playback device for Android.  Both the +JET and EAS engines are integrated into the Android embedded platform as well +as inherent in the JET Creator application. As such, the JET content author can +be sure that the playback will sound exactly the same in both the JET Creator +and the final Android application playing back on Android mobile devices.

+ +

 

+ +

The JET content author works in up to three +different applications to create JET content; a standard MIDI +sequencer (Logic, Cubase, etc.), optionally a DLS2 instrument editor (Awave), +and the JET Creator application to add and audition JET interactive elements.

+ +

 

+ +

The final result is a .jet file that the +content author gives to the application programmer for use in the game or +application.

+ +

 

+ +

 

+ +

1.2        +Abbreviations and Common Terms

+ +

It is important to use a common set of +terms to minimize confusion. Since JET uses MIDI +in a unique way, normal industry terms may not always suffice. Here is the +definition of terms as they are used in this document and in the JET Creator +application:

+ +

 

+ +

Channel: MIDI data associated with a specific MIDI +channel. Standard MIDI allows for 16 channels of MIDI +data each of which are typically associated with a specific instrument.

+ +

 

+ +

Controller: A MIDI event consisting of a +channel number, controller number, and a controller value. The MIDI spec associates many controller numbers with +specific functions, such as volume, expression, sustain pedal, etc. JET also +uses controller events as a means of embedding special control information in a +MIDI sequence to provide for audio +synchronization.

+ +

 

+ +

DAW: Digital Audio Workstation. A common term for MIDI +and audio sequencing applications such as Logic, SONAR, Cubase and others.

+ +

 

+ +

EAS: Embedded MIDI Synthesizer. The +name of the SONiVOX MIDI synthesizer engine.

+ +

 

+ +

JET: Jet Interactive Engine. The name of the SONiVOX JET interactive +music engine.

+ +

 

+ +

Segment: A musical section such as a chorus or verse that is a component of +the overall composition. In JET, a segment can be an entire MIDI file or a +derived from a portion of a MIDI file.

+ +

 

+ +

SMF-0: Standard MIDI File Type 0, a MIDI file that contains a single +track, but may be made up of multiple channels of MIDI +data.

+ +

 

+ +

SMF-1: Standard MIDI File Type 1, a MIDI file that contains a one more +tracks, and each track may in turn be made up of one or more channels of MIDI data. By convention, each channel is stored on a +separate track in an SMF-1 file. However, it is possible to have multiple MIDI +channels on a single track, or multiple tracks that contain data for the same MIDI channel.

+ +

 

+ +

Track: A single track in a DAW containing a timed sequence of MIDI events. Be careful not to confuse Tracks with +Channels. A MIDI file may contain many tracks with several tracks utilizing the +same MIDI channel.

+ +

 

+ +

 

+ +

1         +The JET Interactive Music Concept

+ +

Interactive music can be defined as music +that changes in real-time according to non-predictable events such as user +interaction or game play events. In this way, interactive music is much more +engaging as it has the ability to match the energy and mood of a game much +closer than a pre-composed composition that never changes. In some applications +and games, interactive music is central to the game play. Guitar Hero is one +such popular game. When the end user successfully ‘captures’ the musical notes +coming down the fret board, the music adapts itself and simultaneously keeps +score of successes and failures. JET allows for these types of music driven +games as well.

+ +

 

+ +

There are several methods for making and +controlling interactive music and JET is one such method. This section +describes the features of JET and how they might be used in a game or software +application. It also describes how JET can be used to save memory in small +footprint devices such as Android enabled mobile handsets.

+ +

1.1.1       Data Compression

+ +

JET supports a flexible music format that +can be used to create extended musical sequences with a minimal amount of data. +A musical composition is broken up into segments that can be sequenced to +create a longer piece. The sequencing can be fixed at the time the music file +is authored, or it can be created dynamically under program control.

+ +

1.1.2       Linear Music Example

+ +

+ +

Figure 1: Linear Music Piece

+ +

 

+ +

This diagram shows how musical segments are +stored. Each segment is authored as a separate MIDI +file. A post-processing tool combines the files into a single container file. +Each segment can contain alternate music tracks that can be muted or un-muted +to create additional interest. An example might be a brass accent in the chorus +that is played only the last time through. Also, segments can be transposed up +or down.

+ +

 

+ +

The bottom part of the diagram shows how +the musical segments can be recombined to create a linear music piece. In this +example, the bridge might end with a half-step key modulation and the remaining +segments could be transposed up a half-step to match.

+ +

1.1.3          +Non-linear Music Example

+ +

+ +

Figure 2: Non-linear music piece

+ +

 

+ +

In this diagram, we see a non-linear music +piece. The scenario is a first-person-shooter (FPS) and JET is providing the +background music. The intro plays as the level is loading and then transitions +under program control to the Searching segment. This segment is repeated +indefinitely, perhaps with small variations (using the mute/un-mute feature) +until activity in the game dictates a change.

+ +

 

+ +

As the player nears a monster lair, the +program starts a synchronized transition to the Danger segment, increasing the +tension level in the audio. As the player draws closer to the lair, additional +tracks are un-muted to increase the tension.

+ +

 

+ +

As the player enters into combat with the +monster, the program starts a synchronized transition to the Combat segment. +The segment repeats indefinitely as the combat continues. A Bonus Hit +temporarily un-mutes a decorative track that notifies the player of a +successful attack, and similarly, another track is temporarily un-muted to +signify when the player receives Special Damage.

+ +

 

+ +

At the end of combat, the music transitions +to a victory or defeat segment based on the outcome of battle.

+ +

1.1.4          +Mute/Un-mute Synchronization

+ +

JET can also synchronize the muting and +un-muting of tracks to events in the music. For example, in the FPS game, it +would probably be desirable to place the musical events relating to bonuses and +damage as close to the actual game event as possible. However, simply un-muting +a track at the moment the game event occurs might result in a music clip +starting in the middle. Alternatively, a clip could be started from the +beginning, but then it wouldn’t be synchronized with the other music tracks.

+ +

 

+ +

However, with the JET sync engine, a clip +can be started at the next opportune moment and maintain synchronization. This +can be accomplished by placing a number of short music clips on a decorative +track. A MIDI event in the stream signifies +the start of a clip and a second event signifies the end of a clip. When the +application calls the JET clip function, the next clip in the track is allowed +to play fully synchronized to the music. Optionally, the track can be +automatically muted by a second MIDI event.

+ +

 

+ +

+ +

Figure 3: Synchronized Mute/Unmute

+ +

1.2        +Audio Synchronization

+ +

JET provides an audio synchronization API +that allows game play to be synchronized to events in the audio. The mechanism +relies on data embedded in the MIDI file at +the time the content is authored. When the JET engine senses an event during +playback it generates a callback into the application program. The timing of +the callback can be adjusted to compensate for any latency in the audio +playback system so that audio and video can be synchronized. The diagram below +shows an example of a simple music game that involves pressing the left and +right arrows in time with the music.

+ +

 

+ +

 

+ +

+ +

Figure 4: Music Game with Synchronization

+ +

 

+ +

The arrows represent events in the music +sequence where game events need to be synchronized. In this case, the blue +arrow represents a time where the player is supposed to press the left button, +and the red arrow is for the right button. The yellow arrow tells the game +engine that the sequence is complete. The player is allowed a certain time +window before and after the event to press the appropriate key.

+ +

 

+ +

If an event is received and the player has +not pressed a button, a timer is set to half the length of the window. If the +player presses the button before the timer expires, the game registers a +success, and if not, the game registers a failure.

+ +

 

+ +

If the player presses the button before the +event is received, a timer is set to half the length of the window. If an event +is received before the timer expires, the game registers a success, and if not, +the game registers a failure. Game play might also include bonuses for getting +close to the timing of the actual event.

+ +

 

+ +

2         +JET Content Authoring Overview

+ +

To author JET files and hear them playback interactively, +the content author will work in two or three applications which are designed to +work together smoothly. The first is application is any off-the-shelf MIDI sequencing application or Digital Audio Workstation +that supports VST (for PC) or AU (for Mac) plugins. (Logic, SONAR, Cubase, etc) +Here the author will compose their MIDI music +files using the SONiVOX EAS Synth plugin as the playback synthesizer.

+ +

 

+ +

Once the composer has completed their MIDI file(s), they import them into the JET Creator application. +Here the author will setup and audition the conditions for interactive playback +within the JET enabled game.

+ +

 

+ +

Optionally, the author may elect to create +a custom DLS soundbank. This can be created in any off-the-shelf DLS authoring +application, such as Awave from MJSoft, and loaded into JET Creator along with +the MIDI files.

+ +

 

+ +

Below is an overview of this process. A +more detailed explanation of each step follows.

+ +

 

+ +
    +
  • Launch digital audio workstation (DAW)
  • +
      +
    • Assign the SONiVOX EAS Synth plugin as the playback + synthesizer
    • +
    • Optionally load a custom DLS2 soundset
    • +
    • Compose and save MIDI file(s)
    • +
    +
  • Launch the JET Creator application
  • +
      +
    • Create segments using the MIDI + and DLS2 source files
    • +
    • Add interactive elements
    • +
    • Audition interactive elements
    • +
    • Save and Export JET files for use in the Android application
    • +
    +
+ +

 

+ +

Launch DAW – Content authors will need to +use a third party MIDI authoring application to compose their MIDI +files. It is recommended they use a digital audio workstation (DAW) application +that supports VST or AU plugins as this will enable them to listen to the EAS +MIDI Synthesizer and DLS2 soundsets that will be utilized in the Android +application itself. Some examples of popular DAWs include SONAR (PC) and LOGIC +(MAC).

+ +

 

+ +

Assign SONiVOX EAS Synth plugin as the +playback synthesizer – The SONiVOX EAS Synth plugin is a VST and AU compatible +virtual instrument that plugs into VST or AU compatible DAWs. This software +plugin uses the same SONiVOX EAS MIDI synthesizer engine and default General +MIDI  wavetable soundset inherent in +Android. Using this plugin allows content authors to hear the exact audio +rendering of the instruments and MIDI file +that will be used in their Android applications.

+ +

 

+ +

Optionally Load DLS2 Soundset – The SONiVOX +EAS Synth plugin allows for the loading of any DLS2 compatible soundset for +playback. These could include a new GM wavetable set, or a small collection of +just a few custom instruments for a given application. Note, the DLS file does +not replace the internal GM wavetable used by the EAS engine. DLS soundsets +play in conjunction with the internal GM wavetable.

+ +

 

+ +

Compose MIDI File – Compose MIDI soundtracks for the Android application.

+ +

 

+ +

Launch JET Creator – Once all DLS2 and MIDI source files have been authored, the content author +should launch the JET Creator and begin creating JET Segments. The segments +will reference the MIDI files and any custom +DLS2 soundbanks.

+ +

 

+ +

Assign JET Segment Attributes – After +creating segments the content author interactive elements. Interactive elements +include mute and unmute settings of individual tracks in the MIDI file(s) as +well as MIDI controller numbers that serve as +“events” in the game. These attributes tell the JET engine how and when to play +the different musical segments according to the JET API commands in the Android +application. See below for more detail on this.

+ +

 

+ +

Audition Interactive Playback – After +assigning the segment attributes and creating the JET file, the content author +can audition all interactive playback elements in the JET Audition window.

+ +

 

+ +

Save .jtc File – After the author is +satisfied with the result, it is recommended they save the JET Creator .jtc +file which will save their settings, references to source files, etc.

+ +

 

+ +

Export Files – Exporting the JET Creator +file will bundle all source files and their attributes into a single .zip file. +The zip file will also contain a .jet file for use by the Android application.

+ +

 

+ +

 

+ +

3         +EAS Synth Virtual Instrument Plugin

+ +

Included in the JET Creator package is the +EAS software synthesizer in plug-in format. The EAS plugin synth allows the +composer to hear the instruments used in Android as they are composing their MIDI sequence. The EAS Synth plugin allows for the +loading of custom DLS2 sounds as well.

+ +

 

+ +

3.1        +Installing the EAS Synth Plugin

+ +

Follow the instructions for your individual +DAW to install and utilize the plugin. For Mac users this will typically +involve copying the “EAS Synth.componant” file into your plugins folder which +is usually located at /Library/Audio/Plug-ins/Components. PC users will want to +install the “EAS Synth.dll” into the plugin folder that their DAW requires.

+ +

 

+ +

3.2        +Requirements and Settings for +using the EAS Synth Plugin

+ +

The EAS Synth is an embedded synthesizer +for small mobile devices. This means it does not have the flexibility of high +end synthesizers typically utilized in a professional application such as +Logic, Digital Performer, etc. As such, only the following attributes are +supported.

+ +

 

+ +

Macintosh:

+ +

 

+ +

Mac OSX (Intel) Macs

+ +

ASIO Supported Soundcards

+ +

Sample Rate:    44100 hz

+ +

Buffer Size:       256 kbytes

+ +

 

+ +

PC:

+ +

 

+ +

Windows 2000 or Vista +operating systems

+ +

ASIO supported soundcards

+ +

Sample Rate:    44100 hz

+ +

Buffer Size:       256 kbytes

+ +

 

+ +

3.3        +Assigning MIDI +Tracks to use the EAS Synth

+ +

Each DAW has its own particular method of +assigning MIDI tracks to virtual instrument +plugins such as the SONiVOX EAS Synth. Please consult the user manual for your +DAW for detailed instructions. Below are some general guidelines for Logic +(Mac) and SONAR (PC).

+ +

3.3.1          +LOGIC 8

+ +

The SONiVOX EAS Synth virtual instrument is +a multi-timbral synthesizer. (i.e. it plays back multiple instruments on unique +MIDI channels in a single instance) In Logic +8, however, you’ll want to set up 16 Logic Instruments, +each with their own instance of the EAS Synth. Each Instrument should be assigned +its own MIDI channel. Use Channel 10 for +Drums. The reason for this is that MIDI controller messages, such as Volume +(CC7) and Pan (CC10) will not be channelized if the plugin is assigned to only +a single Instrument and all MIDI tracks are +set to playback on that Instrument. In order for each MIDI +channel to respond to its own controller messages, you must assign 16 different +EAS Synth instances to 16 unique Logic Instruments.

+ +

 

+ +

A Logic 8 template file has been included +in the Android Cupcake release to facilitate the above.

+ +

 

+ +

Playback in Logic 8 may require you to be +in record enable mode for each track you are auditioning. To record enable +multiple tracks hold down the Option key.

+ +

 

+ +

To write out a standard MIDI +(type 1) file from Logic, you need to use the File Export command. IMPORTANT: +Most edits in Logic are non-destructive edits meaning they are not modifying +the actual data but rather adding an overlay onto to the data. Quantize is one +such non-destructive edit. Therefore when you export a MIDI +file, you may not see your quanitization settings.

+ +

 

+ +

In addition, the mix parameters for volume, +pan and program changes may not appear in the event list and therefore may not +write out with the MIDI file. Before exporting +a MIDI file in Logic it is recommended you do +the following:

+ +

 

+ +

Select All and use the “Insert MIDI > +Insert MIDI Settings as Events” command.

+ +

 

+ +

Select All and use the “Apply Quantization +Settings Destructively” command.

+ +

 

+ +

3.3.2          +Cakewalk SONAR 7

+ +

Sonar 7 is a bit easier to set up, use and +save than Logic 8. Simply open or start a new MIDI +file. Go to the Insert menu and select Insert Soft Synth>SONiVOX>EAS +Synth. Then assign each MIDI track’s output to +the EAS Synth. There is no need to record enable a track to hear it play back. +When saving, be sure to select MIDI Type 1.

+ +

 

+ +

SONAR 8 works similarly to SONAR 7.

+ +

 

+ +

3.3.3          +Digital Performer

+ +

We’ve seen some instances when creating +content with Digital Performer where notes with a release velocity of non-0 +will generate an extra note-on event in the EAS synth. If you are hearing a +doubling, editing the release velocity events to zero should fix this problem.

+ +

 

+ +

3.4        +Using Custom DLS2 Soundsets

+ +

The SONiVOX EAS Synthesizer supports two +simultaneous soundsets or wavetables. One is the internal General MIDI wavetable +inherent to the SONiVOX EAS Synthesizer. The other is a Downloadable Sounds +Level 2 (DLS2) soundset. The internal wavetable is a GM Level 1 compliant +wavetable with 127 melodic instruments and 1 drumkit. It is in a proprietary +SONiVOX format. The DLS2 soundsets are an open format published by the MIDI +Manufactures Association.

+ +

 

+ +

In the Android Cupcake release, the +internal wavetable is only 200 kbytes, very small, in order to be compliant +with all Android devices which may not have a lot of memory. DLS2 soundsets can +be any size that a particular device supports. Upgraded (larger) internal +wavetables as well as custom DLS2 instruments can be licensed from SONiVOX.

+ +

3.4.1          +Loading a DLS2 Soundset

+ +

To load a custom soundset, click on the +Load DLS button in the EAS Synth plugin interface. Browse to the DLS2 file you +wish to load and say OK. Only DLS Level 2 formatted soundsets are +supported.

+ +

 

+ +

3.4.2          +Using a DLS2 Soundset

+ +

Since both the internal EAS GM wavetable +and a custom DLS2 soundset are used simultaneously, you must be sure you have +your MIDI Program Changes set correctly. DLS2 instruments must be assigned to a +Bank other than the default GM bank +used by the internal synthesizer.

+ +

 

+ +

The internal EAS synthesizer is assigned to +Banks 121 (melodic instruments) and 120 (drum instruments). This follows the +General MIDI Level 1 specification. Note: Most MIDI +sequencers require you to use Bank 0 to select the default wavetable. Custom +DLS2 soundsets, therefore, should utilize a different Bank. We recommend Bank +1.

+ +

 

+ +

The EAS synth supports MSB (Controller 0), +LSB (Controller 32) Bank change messages. There are two places you need to set +this Bank and Program Change number. The first is in your DLS2 soundset. Using +Bank 1, each Instrument would be assigned MSB 1, LSB 0, then the Instrument +Program Change number. The second place to use the Bank and Program Change +number is in your MIDI sequence.

+ +

 

+ +

In your MIDI +track, the MSB should be sent first followed by the LSB and then the Instrument +number. For example, if your DLS2 instrument is assigned MSB 1, LSB 0, +Program1, you would send CC0, 1 followed by CC32, 0 followed by Program Change +Message 1. This might look like the following in an event window:

+ +

 

+ +

 

+ +

+ +

 

+ +

 

+ +

 

+ +

4         +JET Creator Guidelines

+ +

JET Creator is the desktop application +where you’ll edit and audition the JET interactive music elements. For details +on the JET Creator application please see the “JET Creator User Manual”. Below +are some additional guidelines to help you out.

+ +

 

+ +

 

+ +

 

+ +

4.1        +Order of Tasks

+ +

As with all projects, its best to discuss and +design the interactive music scheme with the game designer and programmer +before beginning your composition. An outline and/or specification can go a +long way in saving you from having to redo things after the game is in place.

+ +

 

+ +

In general you’ll want to first write your +music in your DAW of choice the way you’re used to composing, then break up the +final MIDI file as needed for the application. +Next, move to JET Creator and create all of your music segments in the order +easiest to preview them when played in order. Finally, add the JET Events to +control the segments via the Android game and Audition them as needed in JET +Creator. Finally, save the project in JET Creator and hand off the .jet file to +the programmer to integrate it in the game. After previewing there will likely +be changes to the MIDI file(s) and JET Creator +attributes.

+ +

 

+ +

4.2        +Conserving Memory

+ +

If you’re trying to conserve memory, +compose as few MIDI files as possible, and create several segments from that MIDI file. For example a 12 bar MIDI +file with three sections of 4 bars, A, B, C, can create a much longer song. +Simply create multiple segments that reference the one MIDI +file, then order them however you like. For example, A, A, B, A, C, A, B, A, A +would create a 36 bar song. Use JET to add repeats, transpose segments, and +interactively mute and unmute tracks to keep it even more interesting.

+ +

 

+ +

4.3        +Replicate

+ +

To make adding segments or events faster, +use the Replicate command. Replicate can add multiple segments or events at one +time and uses an offset parameter and prefix naming convention to keep things +easy to read. The MOVE command is also useful for moving multiple events by a +set number of measures, beats or ticks.

+ +

 

+ +

4.4        +Interactive Options

+ +

There are several interactive audio +concepts possible in JET. Below are a few examples although we hope developers +will come up with others we haven’t thought of! These are:

+ +

4.4.1          +Multiple Segment Triggering

+ +

In this method the application is +triggering specific segments based on events in the game. For example a hallway +with lots of fighting might trigger segment 1 and a hallway with no fighting +might trigger segment 2. Using JET TriggerClips in conjunction with this method +creates even more diversity.

+ +

4.4.2          +Mute Arrays

+ +

In this method the application is +triggering mute and unmute events to specific tracks in a single MIDI sequence. For example a hallway with lots of +fighting might play MIDI tracks 1-16 and a +hallway with no fighting might play the same midi file but mute tracks 9-16. +Using JET TriggerClips in conjunction with this method creates even more +diversity.

+ +

4.4.3          +Music Driven Gameplay

+ +

Music driven gaming is similar to what +Guitar Hero and JETBOY have done in that the music content determines how +graphic events are displayed. The application then queries the user response to +the graphic events and interactively modifies the music in response. In this +method the game is utilizing JET Application Events, MIDI controllers that are +embedded in the MIDI file and read by the game +in real-time. Based on the user response, multiple segment triggering and/or +mute arrays can be set.

+ +

 

+ +

 

+ +
+ + + + diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/header.htm b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/header.htm new file mode 100755 index 0000000..4284a7a --- /dev/null +++ b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/header.htm @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + +
+ +

+ +


+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

+ +


+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

+ +


+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

+ +


+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

 

+ +

 

+ +
+ +
+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

SONiVOX JET Creator User Documentation    +Vrs.3   Page 1/13

+ +
+ + + + diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image001.jpg b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image001.jpg new file mode 100755 index 0000000..d244843 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image001.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image002.emz b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image002.emz new file mode 100755 index 0000000..f152c11 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image002.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image004.emz b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image004.emz new file mode 100755 index 0000000..010c4bd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image004.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image006.emz b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image006.emz new file mode 100755 index 0000000..a29ebfd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image006.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image008.gif b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image008.gif new file mode 100755 index 0000000..17919fd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image008.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image010.gif b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image010.gif new file mode 100755 index 0000000..54111a0 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image010.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image011.png b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image011.png new file mode 100755 index 0000000..1573b01 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image011.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image012.gif b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image012.gif new file mode 100755 index 0000000..4300d15 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image012.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image013.gif b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image013.gif new file mode 100755 index 0000000..eb1aa37 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image013.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image014.gif b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image014.gif new file mode 100755 index 0000000..4e99824 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image014.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image015.emz b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image015.emz new file mode 100755 index 0000000..31cba25 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Authoring_Guidelines_files/image015.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual.html b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual.html new file mode 100755 index 0000000..8582f5f --- /dev/null +++ b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual.html @@ -0,0 +1,3032 @@ + + + + + + + + + + + +SONiVOX JET Creator User Manual + + + + + + + + +
+   Copyright (C) 2009 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ +
+ +

JETCreator™ User Manual

+ +

Vrs 1.0

+ +

Content +Authoring Application for the

+ +

JET +Interactive Music Engine

+ +

Authored by SONiVOX

+ +

www.sonivoxrocks.com

+ +

Copyright 2009 Sonic Network, Inc.

+ + + +

 

+ +

 

+ +

1         +Introduction

+ +

1.1        +Overview

+ +

This document contains the user guidelines +for the SONiVOX JET Creator, an authoring application for creating and +auditioning JET files. JET is an interactive music player for small embedded +devices, including the Google Android platform. It allows applications to +include interactive music soundtracks, in MIDI +format, that respond in real-time to game play events and user interaction.

+ +

 

+ +

JET works in conjunction with SONiVOX’s +Embedded Audio Synthesizer (EAS) which is the MIDI +playback device for Android.  Both the +JET and EAS engines are integrated into the Android embedded platform as well +as inherent in the JET Creator application. As such, the JET content author can +be sure that the playback will sound exactly the same in both the JET Creator +and the final Android application playing back on Android mobile devices.

+ +

 

+ +

In addition to the graphical user +interface, there are two main functionalities taking place in JET Creator. The +first involves gathering all the source data (MIDI +files and DLS file), adding JET’s real-time attributes and building a JET +(.jet) file that the Android application will use. The second functionality +involves auditioning the interactive playback elements as they will take place +in the Android application.

+ +

 

+ +

The JET Creator application is written in +the Python programming language, therefore you need to have the current version +of Python and WXWidgets installed. There is both a Mac and Windows version.

+ +

 

+ +

 

+ +

1.2        +Abbreviations and Common Terms

+ +

 

+ +

It is important to use a common set of +terms to minimize confusion. Since JET uses MIDI +in a unique way, normal industry terms may not always suffice. Here is the +definition of terms as they are used in this document and in the JET Creator +application:

+ +

 

+ +

Channel: MIDI data associated with a specific MIDI +channel. Standard MIDI allows for 16 channels of MIDI +data each of which are typically associated with a specific instrument.

+ +

 

+ +

Controller: A MIDI event consisting of a +channel number, controller number, and a controller value. The MIDI spec associates many controller numbers with +specific functions, such as volume, expression, sustain pedal, etc. JET also +uses controller events as a means of embedding special control information in a +MIDI sequence to provide for audio synchronization.

+ +

 

+ +

DAW: Digital Audio Workstation. A common term for MIDI +and audio sequencing applications such as Logic, SONAR, Cubase and others.

+ +

 

+ +

EAS: Embedded MIDI Synthesizer. The +name of the SONiVOX MIDI synthesizer engine.

+ +

 

+ +

JET: Jet Interactive Engine. The name of the SONiVOX JET interactive +music engine.

+ +

 

+ +

M/B/T: Measures, Beats and Ticks

+ +

 

+ +

Segment: A musical section such as a chorus or verse that is a component of +the overall composition. In JET, a segment can be an entire MIDI file or a +derived from a portion of a MIDI file.

+ +

 

+ +

SMF-0: Standard MIDI File Type 0, a MIDI file that contains a single +track, but may be made up of multiple channels of MIDI +data.

+ +

 

+ +

SMF-1: Standard MIDI File Type 1, a MIDI file that contains a one more +tracks, and each track may in turn be made up of one or more channels of MIDI data. By convention, each channel is stored on a +separate track in an SMF-1 file. However, it is possible to have multiple MIDI +channels on a single track, or multiple tracks that contain data for the same MIDI channel.

+ +

 

+ +

Track: A single track in a DAW containing a timed sequence of MIDI events. Be careful not to confuse Tracks with +Channels. A MIDI file may contain many tracks with several tracks utilizing the +same MIDI channel.

+ +

 

+ +

 

+ +

1         +The JET Interactive Music Concept

+ +

Interactive music can be defined as music +that changes in real-time according to non-predictable events such as user +interaction or game play events. In this way, interactive music is much more +engaging as it has the ability to match the energy and mood of a game much +closer than a pre-composed composition that never changes. In some applications +and games, interactive music is central to the game play. Guitar Hero is one +such popular game. When the end user successfully ‘captures’ the musical notes +coming down the fret board, the music adapts itself and simultaneously keeps +score of successes and failures. JET allows for these types of music driven +games as well.

+ +

 

+ +

There are several methods for making and +controlling interactive music and JET is one such method. This section +describes the features of JET and how they might be used in a game or software +application. It also describes how JET can be used to save memory in small +footprint devices such as Android enabled mobile handsets.

+ +

1.1.1       Data Compression

+ +

JET supports a flexible music format that +can be used to create extended musical sequences with a minimal amount of data. +A musical composition is broken up into segments that can be sequenced to +create a longer piece. The sequencing can be fixed at the time the music file +is authored, or it can be created dynamically under program control.

+ +

1.1.2       Linear Music Example

+ +

+ +

Figure 1: Linear Music Piece

+ +

 

+ +

This diagram shows how musical segments are +stored. Each segment is authored as a separate MIDI +file. A post-processing tool combines the files into a single container file. +Each segment can contain alternate music tracks that can be muted or un-muted +to create additional interest. An example might be a brass accent in the chorus +that is played only the last time through. Also, segments can be transposed up +or down.

+ +

 

+ +

The bottom part of the diagram shows how +the musical segments can be recombined to create a linear music piece. In this +example, the bridge might end with a half-step key modulation and the remaining +segments could be transposed up a half-step to match.

+ +

1.1.3          +Non-linear Music Example

+ +

+ +

Figure 2: Non-linear music piece

+ +

 

+ +

In this diagram, we see a non-linear music +piece. The scenario is a first-person-shooter (FPS) and JET is providing the +background music. The intro plays as the level is loading and then transitions +under program control to the Searching segment. This segment is repeated indefinitely, +perhaps with small variations (using the mute/un-mute feature) until activity +in the game dictates a change.

+ +

 

+ +

As the player nears a monster lair, the +program starts a synchronized transition to the Danger segment, increasing the +tension level in the audio. As the player draws closer to the lair, additional +tracks are un-muted to increase the tension.

+ +

 

+ +

As the player enters into combat with the +monster, the program starts a synchronized transition to the Combat segment. +The segment repeats indefinitely as the combat continues. A Bonus Hit +temporarily un-mutes a decorative track that notifies the player of a +successful attack, and similarly, another track is temporarily un-muted to +signify when the player receives Special Damage.

+ +

 

+ +

At the end of combat, the music transitions +to a victory or defeat segment based on the outcome of battle.

+ +

1.1.4          +Mute/Un-mute Synchronization

+ +

JET can also synchronize the muting and +un-muting of tracks to events in the music. For example, in the FPS game, it would +probably be desirable to place the musical events relating to bonuses and +damage as close to the actual game event as possible. However, simply un-muting +a track at the moment the game event occurs might result in a music clip +starting in the middle. Alternatively, a clip could be started from the +beginning, but then it wouldn’t be synchronized with the other music tracks.

+ +

 

+ +

However, with the JET sync engine, a clip +can be started at the next opportune moment and maintain synchronization. This +can be accomplished by placing a number of short music clips on a decorative +track. A MIDI event in the stream signifies +the start of a clip and a second event signifies the end of a clip. When the +application calls the JET clip function, the next clip in the track is allowed +to play fully synchronized to the music. Optionally, the track can be +automatically muted by a second MIDI event.

+ +

 

+ +

+ +

Figure 3: Synchronized Mute/Unmute

+ +

1.2        +Audio Synchronization

+ +

JET provides an audio synchronization API +that allows game play to be synchronized to events in the audio. The mechanism +relies on data embedded in the MIDI file at +the time the content is authored. When the JET engine senses an event during +playback it generates a callback into the application program. The timing of +the callback can be adjusted to compensate for any latency in the audio +playback system so that audio and video can be synchronized. The diagram below +shows an example of a simple music game that involves pressing the left and +right arrows in time with the music.

+ +

 

+ +

 

+ +

+ +

Figure 4: Music Game with Synchronization

+ +

 

+ +

The arrows represent events in the music sequence +where game events need to be synchronized. In this case, the blue arrow +represents a time where the player is supposed to press the left button, and +the red arrow is for the right button. The yellow arrow tells the game engine +that the sequence is complete. The player is allowed a certain time window +before and after the event to press the appropriate key.

+ +

 

+ +

If an event is received and the player has +not pressed a button, a timer is set to half the length of the window. If the +player presses the button before the timer expires, the game registers a +success, and if not, the game registers a failure.

+ +

 

+ +

If the player presses the button before the +event is received, a timer is set to half the length of the window. If an event +is received before the timer expires, the game registers a success, and if not, +the game registers a failure. Game play might also include bonuses for getting +close to the timing of the actual event.

+ +

 

+ +

2         +JET Content Authoring Overview

+ +

To author JET files and hear them playback +interactively, the content author will work in two applications which are +designed to work together smoothly. The first is application is any +off-the-shelf MIDI sequencing application that +supports VST (for PC) or AU (for Mac) plugins. Here the author will compose +their MIDI music files using the plugin as the +synthesizer device. The second application is the JET Creator application. Here +the author will import their MIDI music files +(and optionally a DLS2 soundset) and setup the conditions for interactive +playback within the JET enabled game. Optionally the content author may create +a custom set of DLS instruments using an instrument editor that supports the +DLS Level 2 format. One such application is Awave from MJSoft.

+ +

 

+ +

Please see the JET Content Authoring Guidelines documentation for additional +details on content authoring.

+ +

 

+ +

3         +Installing and Launching JET +Creator

+ +

JET Creator is a python language +application, therefore, you must have Python and wxPython installed on your +machine.

+ +

 

+ +

JetCreator was created and tested with:

+ +

 

+ +

Python Version 2.5.4

+ +

wxPython Version 2.8.7.1

+ +

 

+ +

These can be downloaded here:

+ +

 

+ +

PC:

+ +

http://www.python.org/download/releases/2.5.4/

+ +

http://www.wxpython.org/download.php

+ +

 

+ +

MAC:

+ +

http://wiki.python.org/moin/MacPython/Leopard

+ +

http://www.wxpython.org/download.php

+ +

 

+ +

After installing Python and wxPython, +simply unzip or copy all the files in the JET Creator application directory to +a folder on your hard drive.

+ +

                                                    

+ +

To launch JET Creator go to a command +prompt and set the directory to where you’ve installed Python. Next run python +with the command:

+ +

 

+ +

python +jetcreator.py

+ +

 

+ +

 

+ +

4         +Using JET Creator

+ +

 

+ +

4.1        +File Types

+ +

There are a few different file types +associated with JET Creator.

+ +

 

+ +

.jtc        JET +Creator project file. This file contains all the information associated with a +JET Creator project. When you Save or Save-as out of JET Creator, this file +type is saved.

+ +

 

+ +

.jet        JET +File. This output file is automatically generated from JET Creator whenever you +save your JET Creator project. This is the file that bundles all JET assets +together into a single file that the Android application will use. Give this +file to the Android application developer.

+ +

 

+ +

.mid      MIDI File. This is the standard MIDI +type 1 file that JET Creator will use to make segments.

+ +

 

+ +

.seg      Segment +File. This is a JET Segment file. It has the same name as the MIDI +file which it references but contains additional Segment information.

+ +

 

+ +

.zip       Zip +Archive file. When you Export a JET Archive, a zip file is created that +contains all the assets (files) necessary for JET Creator. Use this to transfer +JET Creator projects to other people.

+ +

 

+ +

4.2        +Open Dialog

+ +

When +you first launch JET Creator you are presented with an open dialog like the +following.

+ +

 

+ +

+ +

 

+ +

 

+ +

Open will open an existing .jtc (JET Creator file) file. Use the browser +button to browse to the directory where you have saved your .jtc file.

+ +

 

+ +

New will create a new .jtc file.

+ +

 

+ +

Import will import a JET Archive (.zip) file.

+ +

 

+ +

Cancel will cancel the dialog and exit the application.

+ +

 

+ + + +

5         +Main Window

+ +

The main window of the JET Creator +application looks like the picture below. There are three main sections from +top to bottom: segment view, event view, and timeline.

+ +

 

+ +

The segment view section displays a list of +the current segments, which MIDI file and +(optionally) DLS2 file each segment is derived from. It also shows each +segments start and stop time and each segments quantize, transpose, repeat and +mute flag settings.

+ +

 

+ +

Just below the Segment view is the event +view. The event view section displays all events associated with a given +segment. Events only display when the segment they are assigned to is +highlighted. Each event displays its type, start and end points, track and midi +channel assignment, and its event ID.

+ +

 

+ +

Just below the Event view is the timeline +display. The timeline shows how many measures a given segment is as well as any +events associated with that segment. The timeline changes to display the +currently selected or playing segment. You can trigger an event in this window +while the segment is play by simply clicking on the event in the timeline +display.

+ +

 

+ +

 

+ +

+ +

 

+ +

JET +Creator Main Window

+ +

 

+ +

 

+ +

The buttons along the left side of main +window do the following:

+ +

 

+ +

Add:                    - +Displays the segment or event window for adding a new segment or event

+ +

Revise:                - +Displays the segment or event window for updating an existing segment or event

+ +

Delete:                 - +Deletes the selected segment or event (will ask for confirmation)

+ +

Move:                  - +Displays the move window which allows you to move selected segments or events +in time

+ +

Queue All:            - Queue’s +(selects) all segments for playback

+ +

Dequeue All:        - Dequeue’s +(deselects) all segments

+ +

Play:                    - +Starts playback of all queue’d segments. This button changes to Stop if any +segments are playing

+ +

Audition:              - +Displays the Audition window (see below)

+ +

 

+ +

5.1        +Segment Window

+ +

The segment window is where a given +segment’s attributes are assigned and auditioned, as shown in the picture +below. The left side of the window displays the segments attributes that are +stored in the JET file. The right side of the window allows the author to set +mute flags, repeat and transpose settings and audition the segment as it will +play in the JET game.

+ +

 

+ +

Note: the audition attributes (mute flags, repeat and transpose) are not stored in the JET content file +(.jet) but rather are defined by the game or application itself. In programming +language, these settings correspond directly with the API calls to the JET +engine. By including them here, the JET content author can simulate how the +segment will respond to the applications API commands during game play.

+ +

 

+ +

 

+ +

+ +

 

+ +

 

+ +

The segment parameters do the following:

+ +

 

+ +

Segment Name             - Sets +the name of the segment

+ +

MIDI File                       - +The name and location of the MIDI file from which +the segment is derived. The button to the immediate right will bring up a +browser for locating a midi file on the hard drive.

+ +

DLS File                       - +The name and location of the DLS2 file, if any, that the MIDI +file uses for that segment.

+ +

Starting M/B/T               - +Starting measure, beat and tick of the segment

+ +

Ending M/B/T                - +Ending measure, beat and tick of the segment

+ +

Quantize                       - +Quantize value for quantizing the current segment during playback

+ +

 

+ +

 

+ +

The audition fields are as follows:

+ +

 

+ +

Track Mutes                  - +Shows the MIDI tracks (not channels) +in the MIDI file. Clicking on a track’s +checkbox will mute that track.

+ +

Channel                        - +Displays the MIDI channel assigned to each +track

+ +

Name                            - +Displays the track name meta event (if present) for each track

+ +

Repeat                          - +Indicates the number of times a segment should repeat during playback

+ +

Transpose                     - +Indicates the transposition in semi-tones or half-steps a segment should +transpose during playback

+ +

 

+ +

To the right of the Audition window are a few additional buttons. +These do as follows:

+ +

 

+ +

OK                               - +Selecting OK confirms all segment settings and closes the segment window

+ +

Cancel                          - +Selecting Cancel cancels any changes and closes the segment window

+ +

Replicate                      - +Displays the Replicate Segment window for entering multiple segments at once. +See below.

+ +

Play/Stop Segment       - Starts +or Stops playback of the segment using the segment attributes assigned.

+ +

Play/Stop MIDI File       - +Starts or Stops playback of the MIDI file +which the segment is assigned to.

+ +

Pause/Resume              - +Pauses or Resumes playback.

+ +

 

+ +

 

+ +

5.2        +Event Window

+ +

The event window is where a given segment’s +event attributes are assigned and auditioned, as shown in the picture below. To +add an event to a segment, the author must first select the segment which will +contain the event, then select the Add button. This will bring up the Event +window.

+ +

 

+ +

+ +

 

+ +

 

+ +

There are two main sections to the event +window. The segment section on the left side of the event window is for display +only. It shows what the segment attributes are for the given segment. The Event +section, on the right side, is where events can be assigned. The following +parameters are available:

+ +

 

+ +

Event Name                    - +Assigns a name to an event

+ +

Event Type                     - +Selects which type of event to assign.

+ +

Starting M/B/T                - +Sets the starting measure, beat, and tick for the event

+ +

Ending M/B/T                 - +Sets the ending measure, beat, and tick for the event, if applicable

+ +

Track                              - +Sets which track in the given segment the event will apply to

+ +

Channel                          - +Sets which MIDI channel the event will apply +to. The MIDI channel should match the MIDI +channel of the track

+ +

Event ID                         - +Sets the event ID for the event. Multiple events can be assigned to the same +segment and therefore the Event ID is used to identify them

+ +

 

+ +

To the right of the Audition window are a few additional buttons. +These do as follows:

+ +

 

+ +

OK                               - +Selecting OK confirms all event settings and closes the event window

+ +

Cancel                          - +Selecting Cancel cancels any changes and closes the event window

+ +

Replicate                      - +Displays the Replicate Event window for entering multiple events at once. See +below.

+ +

Play/Stop                     - +Starts or Stops playback of the segment using the segment attributes assigned. +While the segment is playing, events can be triggered and auditioned.

+ +

Trigger                          - +Triggers the event assigned. This replicates the API command that the JET game +will use to trigger the event, therefore giving the content author a method for +auditioning the behaviour of the event.

+ +

Mute/UnMute                 - +Mute/UnMute will mute or unmute the track that the event is assigned to

+ +

Pause/Resume              - +Pauses or Resumes playback.

+ +

 

+ +

To audition the behaviour of an event, you +can select the Play button. This will initiate playback. The trigger button +will send the trigger event when pressed. This is equivalent to selecting the +green trigger event in the timeline.

+ +

 

+ +

Note: Trigger events are meant to unmute a +single track of a segment when triggered, then mute that track at the end of +the trigger segment. Therefore you should make sure the mute flag is set to +mute the track that a trigger event will be unmuting when receiving a trigger event. +

+ +

 

+ +

Please read Section 7 “Under The Hood” +below for details on how trigger events work and behave.

+ +

 

+ +

5.3        +Replicate Windows

+ +

Often in creating JET files, you’ll need to +create tens or even hundreds of events. You may also need to move events. The +Replicate and Move windows allow for this. There are two Replicate windows for +creating multiple segments or events. They look like the following:

+ +

 

+ +

+ +

 

+ +

Replicate Segment Window

+ +

 

+ +

 

+ +

 

+ +

+ +

 

+ +

Replicate Event Window

+ +

 

+ +

Both Replicate windows function the same. +After creating an initial segment or event, you can select the Replicate +button. The parameters are as follows:

+ +

 

+ +

Name Prefix                  - +Sets the prefix for the name of each segment or event created

+ +

Starting M/B/T               - +Sets the starting time for the first segment or event

+ +

Increment M/B/T            - +Sets the time between segments or events created.

+ +

Number                         - +Sets the number of segments or events you wish to create. If the number +overflows the length of the MIDI file (for +segments) or segment (for events), those objects will not be created.

+ +

Preview                         - +Preview allows you to examine the objects created before saying OK to insert +them.

+ +

 

+ +

 

+ +

5.4        +Move Windows

+ +

The Move function acts similarly to the +Replicate function in that it allows you to edit multiple segments or events at +one time, in this case move them in time. Like Replicate, there are two Move +windows, one for Segments and one for Events. The windows look like the +following:

+ +

 

+ +

+ +

 

+ +

Move Event Window

+ +

 

+ +

To use Move, first select the segments or +events you wish to move in time, then click the Move button. The parameters are +as follows:

+ +

 

+ +

Starting M/B/T               - +Sets the starting time for the first segment or event

+ +

Increment M/B/T            - +Sets the time in M/B/T you wish to move the objects by.

+ +

Preview                         - +Preview allows you to examine the objects created before saying OK to move +them.

+ +

 

+ +

 

+ +

5.5        +Audition Window

+ +

Clicking the Audition button in the main +window of the JET Creator application will open the Audition window. This is +where the content author or application programmer can simulate the interactive +playback as it may occur in the mobile application or game itself.

+ +

 

+ +

+ +

 

+ +

JET Audition Window

+ +

 

+ +

 

+ +

There are four main sections to the +audition window. The left most section displays the available segments and +their length in seconds. The middle section displays a running list of what +segments are queued for playback and what their playback status is. The far +right section displays the mute flags for the currently playing segment. The +timeline section at the bottom is the same as in the main window. It displays +the currently playing segment as well as a visual display of any event triggers +associated with that segment.

+ +

 

+ +

The Audition window allows you to queue up +any segment in any order for playback. To do this simply select the segment you +wish to cue and hit Queue. That segment will appear in the queue window and +start playing (if it is the first segment). Subsequently you can select any +other segment or segments and cue them up for playback. As the segments +complete playback, the next segment in the queue will begin playing. As is the +other windows of JET Creator, you can mute, unmute, trigger event clips, etc. +in realtime as each segment is playing back.

+ +

 

+ +

Specifically the buttons behave as follows:

+ +

 

+ +

Queue                           - +loads the selected segment into the queue and starts playback

+ +

Cancel and Queue         - +cancels the currently playing segment before queueing the selected segment for +playback

+ +

Cancel Current               - +cancels the currently playing segment in the queue and begins playback of the +next segment

+ +

Stop                             - +stops playback of all queued segments

+ +

Mute All                        - +mutes all tracks in the current segment

+ +

Mute None                    - +unmutes all tracks in the current segment

+ +

Original Mutes               - +sets the original mute flags for the current segment

+ +

 

+ +

The combination of these playback options +allows an author or application programmer to audition any behaviour an +interactive music application may encounter.

+ +

 

+ +

 

+ +

5.6        +JET Creator Menus

+ +

The JET Creator menus provide access to +many of the parameters in the main window plus a few additional parameters.

+ +

5.6.1          +File Menu

+ +

The File Menu contains the following +elements:

+ +

 

+ +

New                              - +Creates a new JET Creator file (.jtc)

+ +

Open                            - +Opens an existing JET Creator file

+ +

Save                             - +Saves the currently opened JET Creator file

+ +

Save As                        - +Saves the currently opened JET Creator file to a new file

+ +

Import Project               - Imports a JET Creator archive (.zip)

+ +

Export Project               - Exports a JET Creator archive (.zip)

+ +

Exit                              - +Exits the application

+ +

 

+ +

5.6.2          +Edit Menu

+ +

The Edit Menu contains the following +elements:

+ +

 

+ +

Undo                            - +Undo will undo the last edit made

+ +

Redo                            - +Redo will redo the last undo

+ +

Cut                               - +Copy selected parameter into clipboard and Delete selection

+ +

Copy                            - +Copy selected parameter into clipboard and keep selection

+ +

Paste                            - +Paste selected parameter

+ +

 

+ +

5.6.3          +JET

+ +

The Edit Menu contains the following +elements:

+ +

 

+ +

Properties                     - +Brings up the JET Creator priorities window. This window allows you to set the +following conditions for a given JET file:

+ +

Copyright Info               - Contains copyright info to be inserted into JET file

+ +

Chase Controllers          - Option to chase controllers (on/off). This should usually +be ON.

+ +

Delete Empty Tracks     - Deletes any empty MIDI tracks

+ +

 

+ +

5.6.4          +Segments

+ +

The Segments Menu contains the following +elements:

+ +

 

+ +

Add Segment                - +Brings up the Segment window

+ +

Update Segment           - Updates segment attributes

+ +

Delete Segment                        - Deletes the current segment from the +Segment List

+ +

 

+ +

5.6.5          +Help

+ +

The Help Menu will contain at least the +following elements:

+ +

 

+ +

JET Creator Help           - will launch PDF help document or go to on-line help

+ +

About                           - +JET Creator version number, SONiVOX info

+ +

 

+ +

 

+ +

6         +Trigger Events Explained

+ +

Breaking a MIDI +file into individual (non-linear) segments and queueing up those segments for +playback in a game based on events within the game is one way JET music files are +interactive. Trigger events are an additional method for interactive playback. +Both would be used together in an interactive game or application.

+ +

 

+ +

Trigger events allow for the following:

+ +

 

+ +
    +
  1. Tracks within a MIDI segment can be turned on or off based on game + events. For example the composer could author two drum tracks, one fast + and one slow. If the action in a game is fast, the fast drum track could + play. If the action in the game is slow, the slow drum track can play.
  2. +
  3. User actions can be compared to trigger events which are + pre-inserted into a music file at musically ‘correct’ places. Based on the + results, scoring or other game actions can take place.
  4. +
  5. Musical transitions between levels or action sequences can be + synchronized to be musically seemless.
  6. +
+ +

 

+ +

Under the hood, JET uses standard MIDI CC +events to accomplish these actions and to synchronize audio. The controllers +used by JET are among those not defined for specific use by the MIDI specification. The specific controller definitions +are as follows:

+ +

 

+ +

            Controllers +80-83           Reserved for use by +application

+ +

            Controller +102                JET event marker

+ +

            Controller +103                JET clip marker

+ +

            Controllers +104-119        Reserved for future use

+ +

 

+ +

6.1        +JET Clip Marker (CC103)

+ +

Controller 103 is reserved for marking +clips in a MIDI track that can be triggered by +the JET_TriggerClip API call. The clip ID is encoded in the low 6 bits of the +controller value. Bit 6 is set to one to indicate the start of a clip, and set +to zero to indicate the end of a clip.

+ +

 

+ +

For example, to identify a clip with a clip +ID of 1, the author inserts a MIDI controller +event with controller=103 and value=65 at the start of the clip and another +event with controller=103 and value=1 at the end of the clip. When the +JET_TriggerClip() function is called with a clip ID of 1, the track will be +un-muted when the controller value 65 is encountered and muted again when the +controller value 1 is encountered.

+ +

 

+ +

+ +

Figure 5: Synchronized Clip

+ +

 

+ +

In the figure above, if the +JET_TriggerClip() function is called prior to the first controller event, Track +3 will be un-muted when the first controller event occurs, the first clip will +play, and the track will be muted when the second controller event occurs. If +the JET_TriggerClip() function is called after the first controller event has +occurred, Track 3 will be un-muted when the third controller event occurs, the +second clip will play, and the track will be muted again when the fourth +controller event occurs.

+ +

 

+ +

Note: Normally, the track containing the clip is muted by the application +when the segment is initially queued by the call to JET_QueueSegment(). If it +is not muted, the clip will always play until Jet_TriggerClip() has been called +with the clip ID.

+ +

 

+ +

6.2        +JET Event Marker (CC102)

+ +

Controller 102 is reserved for marking +events in the MIDI streams that are specific +to JET functionality. Currently, the only defined value is 0, which marks the +end of a segment for timing purposes.

+ +

 

+ +

Normally, JET starts playback of the next +segment (or repeats the current segment) when the MIDI +end-of-track meta-event is encountered. Some MIDI +authoring tools make it difficult to place the end-of-track marker accurately, +resulting in synchronization problems when segments are joined together.

+ +

 

+ +

To avoid this problem, the author can place +a JET end-of-segment marker (controller=102, value=0) at the point where the +segment is to be looped. When the end-of-segment marker is encountered, the +next segment will be triggered, or if the current segment is looped, playback +will resume at the start of the segment.

+ +

 

+ +

The end-of-segment marker can also be used +to allow for completion of a musical figure beyond the end of measure that +marks the start of the next segment. For example, the content author might +create a 4-bar segment with a drum fill that ends on beat 1 of the 5th +bar – a bar beyond the natural end of the segment. By placing an end-of-segment +marker at the end of the 4th bar, the next segment will be +triggered, but the drum fill will continue in parallel with the next segment +providing musical continuity.

+ +

 

+ +

+ +

Figure 6: End-of-segment Marker

+ +

6.3        +Application Controllers +(CC80-83)

+ +

The application may use controllers in this +range for its own purposes. When a controller in this range is encountered, the +event is entered into an event queue that can be queried by the application. +Some possible uses include synchronizing video events with audio and marking a +point in a MIDI segment to queue up the next +segment. The range of controllers monitored by the application can be modified +by the application during initialization.

+ +

 

+ +
+ + + + diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/header.htm b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/header.htm new file mode 100755 index 0000000..e7a72f2 --- /dev/null +++ b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/header.htm @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + +
+ +

+ +


+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

+ +


+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

+ +


+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

+ +


+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

 

+ +

 

+ +

 

+ +

 

+ +

 

+ +
+ +
+ +

SONiVOX JET Creator User Documentation    +Vrs.3   Page 1/20

+ +

 

+ +
+ + + + diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image001.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image001.emz new file mode 100755 index 0000000..f152c11 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image001.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image002.gif b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image002.gif new file mode 100755 index 0000000..eb1aa37 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image002.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image003.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image003.emz new file mode 100755 index 0000000..010c4bd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image003.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image004.gif b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image004.gif new file mode 100755 index 0000000..4e99824 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image004.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image005.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image005.emz new file mode 100755 index 0000000..a29ebfd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image005.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image006.gif b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image006.gif new file mode 100755 index 0000000..17919fd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image006.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image007.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image007.emz new file mode 100755 index 0000000..31cba25 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image007.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image008.gif b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image008.gif new file mode 100755 index 0000000..54111a0 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image008.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image009.png b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image009.png new file mode 100755 index 0000000..0d5a14d Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image009.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image010.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image010.jpg new file mode 100755 index 0000000..d0dbb1d Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image010.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image011.png b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image011.png new file mode 100755 index 0000000..29c47ec Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image011.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image012.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image012.jpg new file mode 100755 index 0000000..ac54829 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image012.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image013.png b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image013.png new file mode 100755 index 0000000..b0434d7 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image013.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image014.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image014.jpg new file mode 100755 index 0000000..18212b3 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image014.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image015.png b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image015.png new file mode 100755 index 0000000..807797e Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image015.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image016.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image016.jpg new file mode 100755 index 0000000..fa7931d Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image016.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image017.png b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image017.png new file mode 100755 index 0000000..ca200d1 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image017.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image018.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image018.jpg new file mode 100755 index 0000000..64bb5c3 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image018.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image019.png b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image019.png new file mode 100755 index 0000000..7867902 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image019.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image020.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image020.jpg new file mode 100755 index 0000000..9943ae2 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image020.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image021.png b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image021.png new file mode 100755 index 0000000..690dcad Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image021.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image022.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image022.jpg new file mode 100755 index 0000000..7b517fa Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image022.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image023.png b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image023.png new file mode 100755 index 0000000..43f0fb1 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image023.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image024.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image024.jpg new file mode 100755 index 0000000..cea31c8 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image024.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image025.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image025.emz new file mode 100755 index 0000000..1668a8e Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image025.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image026.gif b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image026.gif new file mode 100755 index 0000000..f9a4a89 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image026.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image027.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image027.emz new file mode 100755 index 0000000..2b06699 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image027.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image028.gif b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image028.gif new file mode 100755 index 0000000..1d18152 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image028.gif differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image029.jpg b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image029.jpg new file mode 100755 index 0000000..d244843 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image029.jpg differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image030.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image030.emz new file mode 100755 index 0000000..f152c11 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image030.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image031.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image031.emz new file mode 100755 index 0000000..010c4bd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image031.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image032.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image032.emz new file mode 100755 index 0000000..a29ebfd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image032.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image033.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image033.emz new file mode 100755 index 0000000..31cba25 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image033.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image034.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image034.emz new file mode 100755 index 0000000..1668a8e Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image034.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image035.emz b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image035.emz new file mode 100755 index 0000000..2b06699 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Creator_User_Manual_files/image035.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.html b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.html new file mode 100755 index 0000000..198a9e6 --- /dev/null +++ b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.html @@ -0,0 +1,1333 @@ + + + + + + + + + + + +JET PROGRAMMING MANUAL + + + + + + + + +
+   Copyright (C) 2009 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ +
+ +

JET™ Programming Manual

+ +

JET +Interactive Music Engine

+ +

Vrs 2.0

+ +

Authored by SONiVOX

+ +

www.sonivoxrocks.com

+ +

Copyright 2009 Sonic Network, Inc.

+ + + +

 

+ +

 

+ +

 

+ +

Introduction

+ +

This document contains programmer guidelines for the SONiVOX +JET Interactive Music System. JET is an interactive music player for small +embedded devices, including the Google Android platform. It allows applications +to include interactive music soundtracks, in MIDI +format, that respond in real-time to game play events and user interaction.

+ +

 

+ +

JET works in conjunction with SONiVOX’s Embedded Audio +Synthesizer (EAS) which is the MIDI playback +device for Android.  Both the JET and EAS +engines are integrated into the Android embedded platform as well as inherent +in JET Creator, an application for +authoring JET content files. As such, the JET content author can be sure that +the playback will sound exactly the same in both JET Creator and the final Android application playing back on +Android mobile devices.

+ +

 

+ +

The programmer of a JET application will want to work +closely with the content author in designing how real-time application events +and music will interactively work together. Once decided, the content author +will create the content and ultimately save a .jet file for the programmer to +include in the application.

+ +

 

+ +

Please see “JET Creator User Documentation” for additional +information on authoring JET content.

+ +

 

+ +

Abbreviations and Common Terms

+ +

It is important to use a common set of terms to minimize confusion. +Since JET uses MIDI in a unique way, normal +industry terms may not always suffice. Here is the definition of terms as they +are used in this document and in the JET Creator application:

+ +

 

+ +

Channel: MIDI data +associated with a specific MIDI channel. +Standard MIDI allows for 16 channels of MIDI +data each of which are typically associated with a specific instrument.

+ +

 

+ +

Controller: A MIDI event consisting of a channel number, controller +number, and a controller value. The MIDI spec +associates many controller numbers with specific functions, such as volume, +expression, sustain pedal, etc. JET also uses controller events as a means of +embedding special control information in a MIDI +sequence to provide for audio synchronization.

+ +

 

+ +

DAW: Digital Audio +Workstation. A common term for MIDI and audio +sequencing applications such as Logic, SONAR, Cubase and others.

+ +

 

+ +

EAS: Embedded MIDI Synthesizer. The name of the SONiVOX MIDI +synthesizer engine.

+ +

 

+ +

JET: Jet +Interactive Engine. The name of the SONiVOX JET interactive music engine.

+ +

 

+ +

Segment: A musical +section such as a chorus or verse that is a component of the overall +composition. In JET, a segment can be an entire MIDI file or a derived from a +portion of a MIDI file.

+ +

 

+ +

SMF-0: Standard +MIDI File Type 0, a MIDI file that contains a single track, but may be made up +of multiple channels of MIDI data.

+ +

 

+ +

SMF-1: Standard +MIDI File Type 1, a MIDI file that contains a one more tracks, and each track +may in turn be made up of one or more channels of MIDI +data. By convention, each channel is stored on a separate track in an SMF-1 +file. However, it is possible to have multiple MIDI channels on a single track, +or multiple tracks that contain data for the same MIDI +channel.

+ +

 

+ +

Track: A single +track in a DAW containing a timed sequence of MIDI +events. Be careful not to confuse Tracks with Channels. A MIDI file may contain +many tracks with several tracks utilizing the same MIDI +channel.

+ +

 

+ +

 

+ +

The JET +Interactive Music Concept

+ +

Interactive music can be defined as music that changes in +real-time according to non-predictable events such as user interaction or game +play events. In this way, interactive music is much more engaging as it has the +ability to match the energy and mood of a game much closer than a pre-composed +composition that never changes. In some applications and games, interactive +music is central to the game play. Guitar Hero is one such popular game. When +the end user successfully ‘captures’ the musical notes coming down the fret +board, the music adapts itself and simultaneously keeps score of successes and +failures. JET allows for these types of music driven games as well.

+ +

 

+ +

There are several methods for making and controlling +interactive music and JET is one such method. This section describes the +features of JET and how they might be used in a game or software application. +It also describes how JET can be used to save memory in small footprint devices +such as Android enabled mobile handsets.

+ +

 

+ +

JET Operation

+ +

JET supports a flexible music format that can be used to +create extended musical sequences with a minimal amount of data. A musical +composition is broken up into segments that can be sequenced to create a longer +piece. The sequencing can be fixed at the time the music file is authored, or +it can be created dynamically under program control.

+ +

Linear Music +Example

+ +

+ +

Figure 1: Linear Music Piece

+ +

 

+ +

This diagram shows how musical segments are stored. Each +segment is authored as a separate MIDI file. A +post-processing tool combines the files into a single container file. Each +segment can contain alternate music tracks that can be muted or un-muted to +create additional interest. An example might be a brass accent in the chorus +that is played only the last time through. Also, segments can be transposed up +or down.

+ +

 

+ +

The bottom part of the diagram shows how the musical +segments can be recombined to create a linear music piece. In this example, the +bridge might end with a half-step key modulation and the remaining segments +could be transposed up a half-step to match.

+ +

Non-linear Music Example

+ +

+ +

Figure 2: Non-linear music piece

+ +

 

+ +

In this diagram, we see a non-linear music piece. The +scenario is a first-person-shooter (FPS) and JET is providing the background +music. The intro plays as the level is loading and then transitions under +program control to the Searching segment. This segment is repeated +indefinitely, perhaps with small variations (using the mute/un-mute feature) +until activity in the game dictates a change.

+ +

 

+ +

As the player nears a monster lair, the program starts a +synchronized transition to the Danger segment, increasing the tension level in +the audio. As the player draws closer to the lair, additional tracks are +un-muted to increase the tension.

+ +

 

+ +

As the player enters into combat with the monster, the +program starts a synchronized transition to the Combat segment. The segment +repeats indefinitely as the combat continues. A Bonus Hit temporarily un-mutes +a decorative track that notifies the player of a successful attack, and +similarly, another track is temporarily un-muted to signify when the player +receives Special Damage.

+ +

 

+ +

At the end of combat, the music transitions to a victory or +defeat segment based on the outcome of battle.

+ +

Mute/Un-mute Synchronization

+ +

JET can also synchronize the muting and un-muting of tracks +to events in the music. For example, in the FPS game, it would probably be +desirable to place the musical events relating to bonuses and damage as close +to the actual game event as possible. However, simply un-muting a track at the +moment the game event occurs might result in a music clip starting in the +middle. Alternatively, a clip could be started from the beginning, but then it +wouldn’t be synchronized with the other music tracks.

+ +

 

+ +

However, with the JET sync engine, a clip can be started at +the next opportune moment and maintain synchronization. This can be +accomplished by placing a number of short music clips on a decorative track. A MIDI event in the stream signifies the start of a clip +and a second event signifies the end of a clip. When the application calls the +JET clip function, the next clip in the track is allowed to play fully +synchronized to the music. Optionally, the track can be automatically muted by +a second MIDI event.

+ +

 

+ +

+ +

Figure 3: Synchronized Mute/Unmute

+ +

Audio Synchronization

+ +

JET provides an audio synchronization API that allows game +play to be synchronized to events in the audio. The mechanism relies on data +embedded in the MIDI file at the time the +content is authored. When the JET engine senses an event during playback it +generates a callback into the application program. The timing of the callback +can be adjusted to compensate for any latency in the audio playback system so +that audio and video can be synchronized. The diagram below shows an example of +a simple music game that involves pressing the left and right arrows in time +with the music.

+ +

 

+ +

 

+ +

+ +

Figure 4: Music Game with +Synchronization

+ +

 

+ +

The arrows represent events in the music sequence where game +events need to be synchronized. In this case, the blue arrow represents a time +where the player is supposed to press the left button, and the red arrow is for +the right button. The yellow arrow tells the game engine that the sequence is +complete. The player is allowed a certain time window before and after the +event to press the appropriate key.

+ +

 

+ +

If an event is received and the player has not pressed a +button, a timer is set to half the length of the window. If the player presses +the button before the timer expires, the game registers a success, and if not, +the game registers a failure.

+ +

 

+ +

If the player presses the button before the event is +received, a timer is set to half the length of the window. If an event is +received before the timer expires, the game registers a success, and if not, +the game registers a failure. Game play might also include bonuses for getting +close to the timing of the actual event.

+ +

 

+ +

Operational Details

+ +

JET uses the standard EAS library calls to manage multiple MIDI streams that are synchronized to sound like a +seamless audio track. JET requires the use of the dynamic memory model, i.e. +support for malloc() and free() memory allocation functions or their +equivalent. JET also requires the DLS parser and synthesizer module to support +custom instruments in JET content files.

+ +

 

+ +

JET uses standard MIDI +events for audio synchronization. This simplifies the authoring process by +allowing content authors to use their favorite tools for developing content. +After the content has been developed, a simple post-processing tool pulls the +content together into a JET compatible content file.

+ +

Synchronization Events

+ +

JET uses MIDI controller +events to synchronize audio. The controllers used by JET are among those not +defined for specific use by the MIDI +specification. The specific controller definitions are as follows:

+ +

 

+ +

            Controllers +80-83                 Reserved for use by +application

+ +

            Controller 102                       JET event marker

+ +

            Controller +103                       JET clip marker

+ +

            Controllers +104-119             Reserved for future +use

+ +

 

+ +

Controllers 80-83 – Application Controllers

+ +

The application may use controllers in this range for its +own purposes. When a controller in this range is encountered, the event is +entered into an event queue that can be queried by the application. Some +possible uses include synchronizing video events with audio and marking a point +in a MIDI segment to queue up the next +segment. The range of controllers monitored by the application can be modified +by the application during initialization.

+ +

Controller 102 – JET Event Marker

+ +

Controller 102 is reserved for marking events in the MIDI streams that are specific to JET functionality. +Currently, the only defined value is 0, which marks the end of a segment for +timing purposes.

+ +

 

+ +

Normally, JET starts playback of the next segment (or +repeats the current segment) when the MIDI +end-of-track meta-event is encountered. Some MIDI +authoring tools make it difficult to place the end-of-track marker accurately, +resulting in synchronization problems when segments are joined together.

+ +

 

+ +

To avoid this problem, the author can place a JET +end-of-segment marker (controller=102, value=0) at the point where the segment is +to be looped. When the end-of-segment marker is encountered, the next segment +will be triggered, or if the current segment is looped, playback will resume at +the start of the segment.

+ +

 

+ +

The end-of-segment marker can also be used to allow for +completion of a musical figure beyond the end of measure that marks the start +of the next segment. For example, the content author might create a 4-bar +segment with a drum fill that ends on beat 1 of the 5th bar – a bar +beyond the natural end of the segment. By placing an end-of-segment marker at +the end of the 4th bar, the next segment will be triggered, but the +drum fill will continue in parallel with the next segment providing musical +continuity.

+ +

 

+ +

+ +

Figure 5: End-of-segment Marker

+ +

Controller 103 – JET Clip Marker

+ +

Controller 103 is reserved for marking clips in a MIDI track that can be triggered by the JET_TriggerClip +API call. The clip ID is encoded in the low 6 bits of the controller value. Bit +6 is set to one to indicate the start of a clip, and set to zero to indicate +the end of a clip.

+ +

 

+ +

For example, to identify a clip with a clip ID of 1, the +author inserts a MIDI controller event with +controller=103 and value=65 at the start of the clip and another event with controller=103 +and value=1 at the end of the clip. When the JET_TriggerClip() function is +called with a clip ID of 1, the track will be un-muted when the controller +value 65 is encountered and muted again when the controller value 1 is +encountered.

+ +

 

+ +

+ +

Figure 6: Synchronized Clip

+ +

 

+ +

In the figure above, if the JET_TriggerClip() function is +called prior to the first controller event, Track 3 will be un-muted when the +first controller event occurs, the first clip will play, and the track will be +muted when the second controller event occurs. If the JET_TriggerClip() +function is called after the first controller event has occurred, Track 3 will +be un-muted when the third controller event occurs, the second clip will play, +and the track will be muted again when the fourth controller event occurs.

+ +

 

+ +

Note: Normally, +the track containing the clip is muted by the application when the segment is +initially queued by the call to JET_QueueSegment(). If it is not muted, the clip +will always play until Jet_TriggerClip() has been called with the clip ID.

+ +

JET Programming

+ +

The JET library builds on functionality in the EAS library. +It is assumed that the reader is familiar with EAS and has implemented basic +EAS audio functionality in the application. Specifically, the application must +first initialize EAS by calling EAS_Init() and must call EAS_Render() at +appropriate times to render audio and stream it to the audio hardware. JET also +requires the use of the dynamic memory model which uses malloc() and free() or +functional equivalents.

+ +

 

+ +

Most JET function calls return an EAS_RESULT type which +should be checked against the EAS_SUCCESS return code. Most failures are not +fatal, i.e. they will not put the library in a state where it must be +re-initialized. However, some failures such as memory allocation or file +open/read errors will likely result in the specific open content failing to +render.

+ +

JET Application Initialization

+ +

The JET library is initialized by the JET_Init() function. +The application must first call EAS_Init() and then pass the EAS data handle +returned by EAS_Init() to the JET_Init() function. Currently, only a single JET +application can be active at a time.

+ +

 

+ +

The JET_Init function takes 3 arguments: The first is the +EAS data handle. The second is a pointer to a configuration structure +S_JET_CONFIG and the third is the size of the configuration structure. For most +applications, it is sufficient to pass a NULL pointer and size 0 for the +configuration data.

+ +

 

+ +

However, if desired, the configuration can be modified to +allow the application to monitor MIDI events +outside the normal range of controllers allocated for JET application events. +In this case, a configuration structure should be allocated and the data fields +initialized with the appropriate values with the low and high controller +numbers to be monitored. The size field should be the sizeof() of the data +structure. This is to allow for future enhancement of the configuration data +while maintaining compatibility.

+ +

JET Application Termination

+ +

When the JET application terminates, it should call +JET_Shutdown() to release the resources allocated by the JET engine.  If the application has no other use for the +EAS library, it should also call EAS_Shutdown().

+ +

JET Audio Processing

+ +

To start the JET engine, the content must first be opened +with the JET_OpenFile() function. Just as with EAS_OpenFile(), the file locator +is an opaque value that is passed to the EAS_HWOpenFile() function. It can +either be a pointer to a filename, or a pointer to an in-memory object, +depending on the user implementation of file I/O in the eas_host.c or +eas_hostmm.c module. Only a single JET content file can be opened at a time.

+ +

 

+ +

Once the JET file is opened, the application can begin +queuing up segments for playback by calling the JET_QueueSegment() function. +Generally, it is advisable to keep a minimum of two segments queued at all +times:  the currently playing segment +plus an additional segment that is ready to start playing when the current +segment finishes. However, with proper programming, it is possible to queue up +segments using a “just-in-time” technique. This technique typically involves +careful placement of application controller events near the end of a segment so +that the application is informed when a segment is about to end.

+ +

 

+ +

After the segment(s) are queued up, playback can begin. By +default, the segments are initialized in a paused state. To start playback, +call the JET_Play() function. Playback can be paused again by calling the JET_Pause() +function. Once initiated, playback will continue as long as the application +continues to queue up new segments before all the segments in the queue are +exhausted.

+ +

 

+ +

The JET_Status() function can be used to monitor progress. +It returns the number of segments queued, repeat count, current segment ID, and +play status. By monitor the number of segments queued, the application can +determine when it needs to queue another segment and when playback has +completed.

+ +

 

+ +

When playback has completed and the application is finished +with the contents of the currently open file, the application should call +JET_CloseFile() to close the file and release any resources associated with the +file.

+ +

JET_Init

+ +

EAS_PUBLIC EAS_RESULT JET_Init +(EAS_DATA_HANDLE easHandle, S_JET_CONFIG *pConfig, EAS_INT configSize)

+ +

 

+ +

Initializes JET library for use by application. Most +application should simply pass a NULL for pConfig and 0 for configSize, which +means that only controller events in the application range (80-83) will end up +in the application event queue. If desired, the application can instantiate an +S_JET_CONFIG data structure and set the controller range to a different range. +In this case, the configSize parameter should be set to sizeof(S_JET_CONFIG).

+ +

JET_Shutdown

+ +

EAS_PUBLIC EAS_RESULT JET_Shutdown +(EAS_DATA_HANDLE easHandle)

+ +

 

+ +

Releases resources used by the JET library. The application +should call this function when it is no longer using the JET library.

+ +

JET_ OpenFile

+ +

EAS_PUBLIC EAS_RESULT JET_OpenFile +(EAS_DATA_HANDLE easHandle, EAS_FILE_LOCATOR locator)

+ +

 

+ +

Opens a JET content file for playback. Content must be +formatted for use by the JET library, which is typically accomplished with the +jetfile.py script (see “Creating JET Content”). Only a single JET content file +can be opened at a time. However, since JET can contain many MIDI +files and DLS libraries, this limitation is normally not an issue.

+ +

JET_ CloseFile

+ +

EAS_PUBLIC EAS_RESULT JET_CloseFile +(EAS_DATA_HANDLE easHandle)

+ +

 

+ +

Closes a JET file and release the resources associated with it.

+ +

JET_ Status

+ +

EAS_PUBLIC EAS_RESULT JET_Status +(EAS_DATA_HANDLE easHandle, S_JET_STATUS *pStatus)

+ +

 

+ +

Returns the current JET status. The elements of the status +data structure are as follows:

+ +

 

+ +

typedef struct s_jet_status_tag

+ +

{

+ +

     EAS_INT   currentUserID;

+ +

     EAS_INT   segmentRepeatCount;

+ +

     EAS_INT   numQueuedSegments;

+ +

     EAS_BOOL paused;

+ +

} S_JET_STATUS;

+ +

 

+ +

currentUserID: An +8-bit value assigned by the application.

+ +

 

+ +

segmentRepeatCount: +Number of times left to repeat. Zero indicates no repeats, a negative number +indicates an infinite number of repeats. Any positive value indicates that the +segment will play n+1 times.

+ +

 

+ +

numQueuedSegments: +Number of segments currently queued to play including the currently playing +segment. A value of zero indicates that nothing is playing. Normally, the +application will queue a new segment each time the value is 1 so that playback +is uninterrupted.

+ +

JET_ QueueSegment

+ +

EAS_PUBLIC EAS_RESULT JET_QueueSegment +(EAS_DATA_HANDLE easHandle, EAS_INT segmentNum, EAS_INT libNum, EAS_INT +repeatCount, EAS_INT transpose, EAS_U32 muteFlags, EAS_U8 userID)

+ +

 

+ +

Queues up a JET MIDI segment for playback. The parameters +are as follows:

+ +

 

+ +

segmentNum: +Segment number as identified in the JET content configuration file.

+ +

 

+ +

libNum: The library +number as specified in the JET content configuration file. Use -1 to select the +standard General MIDI library.

+ +

 

+ +

repeatCount: The +number of times this segment should repeat. Zero indicates no repeat, i.e. play +only once. Any positive number indicates to play n+1 times. Set to -1 to repeat +indefinitely.

+ +

 

+ +

transpose: The +amount of pitch transposition. Set to 0 for normal playback. Range is -12 to ++12.

+ +

 

+ +

muteFlags: +Specific which MIDI tracks (not MIDI channels) +should be muted during playback. These flags can be changed dynamically using +the mute functions. Bit 0 = track 0, bit 1 = track 1, etc.

+ +

 

+ +

userID: 8-bit +value specified by the application that uniquely identifies the segment. This +value is returned in the JET_Status() function as well as by the application +event when an event is detected in a segment. Normally, the application keeps +an 8-bit value that is incremented each time a new segment is queued up. This +can be used to look up any special characteristics of that track including +trigger clips and mute flags.

+ +

JET_ Play

+ +

EAS_PUBLIC EAS_RESULT JET_Play +(EAS_DATA_HANDLE easHandle)

+ +

 

+ +

Starts playback of the current segment. This function must +be called once after the initial segments are queued up to start playback. It +is also called after JET_Pause() to resume playback.

+ +

JET_ Pause

+ +

EAS_PUBLIC EAS_RESULT JET_Pause +(EAS_DATA_HANDLE easHandle)

+ +

 

+ +

Pauses playback of the current segment. Call JET_Pause() to +resume playback.

+ +

JET_ SetMuteFlags

+ +

EAS_PUBLIC EAS_RESULT JET_SetMuteFlags +(EAS_DATA_HANDLE easHandle, EAS_U32 muteFlags, EAS_BOOL sync)

+ +

 

+ +

Modifies the mute flags during playback. If the sync parameter is false, the mute flags +are updated at the beginning of the next render. This means that any new notes +or controller events will be processed during the next audio frame. If the sync parameter is true, the mute flags +will be updated at the start of the next segment. If the segment is repeated, +the flags will take effect the next time segment is repeated.

+ +

JET_ SetMuteFlag

+ +

EAS_PUBLIC EAS_RESULT JET_SetMuteFlag +(EAS_DATA_HANDLE easHandle, EAS_INT trackNum, EAS_BOOL muteFlag, EAS_BOOL sync)

+ +

Modifies a mute flag for a single track during playback. If +the sync parameter is false, the mute +flag is updated at the beginning of the next render. This means that any new +notes or controller events will be processed during the next audio frame. If +the sync parameter is true, the mute +flag will be updated at the start of the next segment. If the segment is +repeated, the flag will take effect the next time segment is repeated.

+ +

JET_ TriggerClip

+ +

EAS_PUBLIC EAS_RESULT JET_TriggerClip +(EAS_DATA_HANDLE easHandle, EAS_INT clipID)

+ +

 

+ +

Automatically updates mute flags in sync with the JET Clip +Marker (controller 103). The parameter clipID +must be in the range of 0-63. After the call to JET_TriggerClip, when JET next +encounters a controller event 103 with bits 0-5 of the value equal to clipID and bit 6 set to 1, it will automatically un-mute the track containing +the controller event. When JET encounters the complementary controller event +103 with bits 0-5 of the value equal to clipID +and bit 6 set to 0, it will mute +the track again.

+ +

JET_ GetEvent

+ +

EAS_BOOL JET_GetEvent (EAS_DATA_HANDLE +easHandle, EAS_U32 *pEventRaw, S_JET_EVENT *pEvent)

+ +

 

+ +

Attempts to read an event from the application event queue, +return EAS_TRUE if an event is found and EAS_FALSE if not. If the application +passes a valid pointer for pEventRaw, +a 32-bit compressed event code is returned. If the application passes a valid +pointer for pEvent, the event is +parsed into the S_JET_EVENT fields. The application can pass NULL for either +parameter and that variable will be ignored. Normally, the application will +call JET_GetEvent() repeatedly to retrieve events until it returns EAS_FALSE.

+ +

JET_ ParseEvent

+ +

EAS_PUBLIC void JET_ParseEvent (EAS_U32 +event, S_JET_EVENT *pEvent)

+ +

Parses a 32-bit compressed event code into a data structure. +The application passes the event code received from JET_GetEvent(). The parsed +event data is returned in the memory pointed to by pEvent.

+ +

JET_GetAppData

+ +

EAS_RESULT JET_GetAppData +(EAS_DATA_HANDLE easHandle, EAS_I32 *pAppDataOffset, EAS_I32 *pAppDataSize)

+ +

Returns the offset and size of the JAPP chunk in the JET +file. The application can use the file I/O functions in the eas_host module to +retrieve application specific data from the file.

+ +

 

+ +

 

+ +

Creating JET Content

+ +

JET uses standard MIDI files and DLS files that can be +created with commercially available content tools such as Logic, Cubase, +Digital Performer, or SONAR for MIDI files and +Awave for DLS2 files. These source files are then bundled into a .jet package +file suitable for use in a JET application.

+ +

 

+ +

To create JET file use the “JET Creator” desktop +application. The JET Creator application is written in Python and includes a +full graphical interface. It is available for MAC and PC platforms. See “JET +Creator User Manual” for more information.

+ +
+ + + + diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.odt b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.odt new file mode 100755 index 0000000..943b818 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.odt differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.pdf b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.pdf new file mode 100755 index 0000000..3e45005 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual.pdf differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/header.htm b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/header.htm new file mode 100755 index 0000000..8cc7121 --- /dev/null +++ b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/header.htm @@ -0,0 +1,73 @@ + + + + + + + + + + + + + +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

                                        JET +Programming Guide   vrs.2   Page 1/19

+ +
+ + + + diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image002.png b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image002.png new file mode 100755 index 0000000..931d4a4 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image002.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image004.png b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image004.png new file mode 100755 index 0000000..93086b5 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image004.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image006.png b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image006.png new file mode 100755 index 0000000..2916ddd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image006.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image008.png b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image008.png new file mode 100755 index 0000000..d80d93c Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image008.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image010.png b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image010.png new file mode 100755 index 0000000..542a7f7 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image010.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image012.png b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image012.png new file mode 100755 index 0000000..547759c Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image012.png differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image013.emz b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image013.emz new file mode 100755 index 0000000..f152c11 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image013.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image014.emz b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image014.emz new file mode 100755 index 0000000..010c4bd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image014.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image015.emz b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image015.emz new file mode 100755 index 0000000..a29ebfd Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image015.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image016.emz b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image016.emz new file mode 100755 index 0000000..31cba25 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image016.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image017.emz b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image017.emz new file mode 100755 index 0000000..2b06699 Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image017.emz differ diff --git a/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image018.emz b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image018.emz new file mode 100755 index 0000000..1668a8e Binary files /dev/null and b/code/embeddedaudiosynthesis/docs/JET_Programming_Manual_files/image018.emz differ diff --git a/code/ios/Carousel.h b/code/ios/Carousel.h new file mode 100755 index 0000000..a851c0a --- /dev/null +++ b/code/ios/Carousel.h @@ -0,0 +1,91 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + + +/* +============================================================================== + Carousel - + + This UI Object must be setup by Interface builder. + + items must be added by code. + +============================================================================== +*/ + +#import +#import +#import "Label.h" + +@interface idCarouselItem : NSObject +{ +@public + + UIImage * image; // Image Of the Item. + NSString * title; // Title of the Item. + int hash; // Optional Item Hash Value. +} + +@property (nonatomic, retain) NSString *title; +@property (nonatomic, retain) UIImage *image; +@property (nonatomic, assign) int hash; + +@end + + +@interface idCarousel : UIControl { +@public + + NSInteger currentItem; // The Current Carousel Item. + NSInteger prevItem; // The Prev Carousel Item. + NSInteger nextItem; // The Next Carousel Item. + +@private + IBOutlet UIImageView * mainSelection; // Renderable Main Selection + IBOutlet UIImageView * prevSelection; // Renderable Prev Selection + IBOutlet UIImageView * nextSelection; // Renderable Next Selection + IBOutlet idLabel * selectionLabel; // Title Label. + + CGRect mainRect; // Main Selection Layout Rect. + CGRect prevRect; // Prev Selection Layout Rect. + CGRect nextRect; // Next Selection Layout Rect. + + NSMutableArray * carouselItems; // All the Available Items to choose from. + + int hasDragged; // if the User has Dragged for a revolution. + CGPoint startDragPoint; // the starting point where the user has touched. +} + +- (void) Init; +- (void) AddCarouselItem:( NSString* )Image + :( NSString* )Title + :( int )ItemHash; + +- (NSInteger) GetSelectedItem_Index; +- (int) GetSelectedItem_Hash; + +- (IBAction) MoveForward; +- (IBAction) MoveBackward; + +- (void) RotateToOrigin; +- (void) RotateForward; +- (void) RotateBackward; + +@end diff --git a/code/ios/Carousel.mm b/code/ios/Carousel.mm new file mode 100755 index 0000000..e17eab0 --- /dev/null +++ b/code/ios/Carousel.mm @@ -0,0 +1,514 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ +#import +#import +#import "Carousel.h" +#include +@implementation idCarouselItem + +@synthesize image; +@synthesize title; +@synthesize hash; + +@end + +@implementation idCarousel + +// Move full turn at this percentage +const static float CAROUSEL_CHANGE_DRAG = 0.2f; +const static float CAROUSEL_BACKITEMS_ALPHA = 0.5f; +const static float CAROUSEL_FRONTITEM_ALPHA = 1.0f; + +enum idCarouselDrag_t { + CAROUSEL_DRAG_MOVE_NONE = 0, + CAROUSEL_DRAG_MOVE_FORWARD, + CAROUSEL_DRAG_MOVE_BACKWARD +}; + +/* + ======================== + Lerp + ======================== + */ +static CGFloat Lerp(CGFloat from, CGFloat to, CGFloat f ) +{ + return from + ( ( to - from ) * f ); +} + +/* + ======================== + LerpPoint + ======================== + */ +static CGPoint LerpPoint(CGPoint a, CGPoint b, CGFloat t) +{ + CGPoint p; + p.x = Lerp(a.x, b.x, t); + p.y = Lerp(a.y, b.y, t); + return p; +} + +/* + ======================== + LerpSize + ======================== + */ +static CGSize LerpSize(CGSize a, CGSize b, CGFloat t) +{ + CGSize s; + s.width = Lerp(a.width, b.width, t); + s.height = Lerp(a.height, b.height, t); + return s; +} + +/* + ======================== + LerpRect + ======================== + */ +static CGRect LerpRect( CGRect a, CGRect b, CGFloat t ) { + + CGRect r; + r.origin = LerpPoint( a.origin, b.origin, t ); + r.size = LerpSize( a.size, b.size, t ); + return r; + +} + +/* + ======================== + awakeFromNib + ======================== + */ +- (void) awakeFromNib { + + mainRect = mainSelection.frame; + prevRect = prevSelection.frame; + nextRect = nextSelection.frame; + + // Allocate our Items Array + carouselItems = [[ NSMutableArray alloc ] init ]; + + [super awakeFromNib]; +} + +/* + ======================== + touchesBegan + ======================== + */ +- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { + (void)(event); + hasDragged = 0; + startDragPoint = [[touches anyObject] locationInView:self]; +} + +/* + ======================== + touchesMoved + ======================== + */ +- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + (void)(event); + if( prevSelection == nil || nextSelection == nil ) { + // Nothing to transition to... dont swip transition + return; + } + + CGPoint movedPoint = [[touches anyObject] locationInView:self]; + CGFloat offsetX = movedPoint.x - startDragPoint.x; + + // Find out where im at relative to the side of the screen + CGFloat percentage = offsetX / self.frame.size.width; + percentage = (float)fmin( percentage, 1.0f ); + percentage = (float)fmax( percentage, -1.0f ); + + if( percentage > CAROUSEL_CHANGE_DRAG ) { + hasDragged = CAROUSEL_DRAG_MOVE_FORWARD; + } else if( percentage < -CAROUSEL_CHANGE_DRAG ) { + hasDragged = CAROUSEL_DRAG_MOVE_BACKWARD; + } + + if( percentage > 0 ) { // Going to the right of the screen.. + + CGRect newMainRect = LerpRect( mainRect, nextRect , percentage ); + CGRect newNextRect = LerpRect( nextRect, prevRect , percentage ); + CGRect newPrevRect = LerpRect( prevRect, mainRect , percentage ); + + mainSelection.frame = newMainRect; + prevSelection.frame = newPrevRect; + nextSelection.frame = newNextRect; + + mainSelection.alpha = Lerp( CAROUSEL_FRONTITEM_ALPHA, CAROUSEL_BACKITEMS_ALPHA, percentage ); + prevSelection.alpha = Lerp( CAROUSEL_BACKITEMS_ALPHA, CAROUSEL_FRONTITEM_ALPHA, percentage ); + + } else { // Going the left. + + percentage = CGFloat(fabs( percentage )); + + CGRect newMainRect = LerpRect( mainRect, prevRect , percentage ); + CGRect newNextRect = LerpRect( nextRect, mainRect , percentage ); + CGRect newPrevRect = LerpRect( prevRect, nextRect , percentage ); + + mainSelection.frame = newMainRect; + prevSelection.frame = newPrevRect; + nextSelection.frame = newNextRect; + + mainSelection.alpha = Lerp( CAROUSEL_FRONTITEM_ALPHA, CAROUSEL_BACKITEMS_ALPHA, percentage ); + nextSelection.alpha = Lerp( CAROUSEL_BACKITEMS_ALPHA, CAROUSEL_FRONTITEM_ALPHA, percentage ); + } +} + +/* + ======================== + touchesEnded + ======================== + */ +- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { + (void)(event); + (void)(touches); + + if( hasDragged == CAROUSEL_DRAG_MOVE_FORWARD ) { + [ self RotateForward ]; + } else if( hasDragged == CAROUSEL_DRAG_MOVE_BACKWARD ) { + [ self RotateBackward ]; + } else { + [ self RotateToOrigin ]; + } +} + +/* + ======================== + Init + ======================== + */ +- (void) Init { + + // Get the items At the new layout. + idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger)currentItem ]; + idCarouselItem * nItem = [ carouselItems objectAtIndex: (NSUInteger)nextItem ]; + idCarouselItem * pItem = [ carouselItems objectAtIndex: (NSUInteger)prevItem ]; + + // Set the Main Selection Text. + [ selectionLabel setText: cItem.title ]; + + // Set the prev selection UIImage + mainSelection.image = cItem.image; + prevSelection.image = nItem.image; + nextSelection.image = pItem.image; +} + +/* + ======================== + AddCarouselItem + ======================== + */ +- (void) AddCarouselItem:( NSString* )Image + :( NSString* )Title + :( int ) ItemHash { + + idCarouselItem * Item = [ idCarouselItem alloc ]; + + // Initialize the Item with the data passed in. + Item.image = [UIImage imageNamed: Image ]; + Item.title = Title; + Item.hash = ItemHash; + + // Add the Item to our object array. + [ carouselItems addObject: Item ]; + + // Set the Cur Item as the one just added. + currentItem = 0; + nextItem = 1; + prevItem = (NSInteger)[ carouselItems count ] - 1; + +} + +/* + ======================== + GetSelectedItem_Index + ======================== + */ +- (NSInteger) GetSelectedItem_Index { + return currentItem; +} + +/* + ======================== + GetSelectedItem_Hash + ======================== + */ +- (int) GetSelectedItem_Hash { + idCarouselItem * item = [ carouselItems objectAtIndex: (NSUInteger)currentItem ]; + + return item.hash; +} + +/* + ======================== + MoveForward + +Interface Builder Direct Access to moving the Carousel + ======================== + */ +- (IBAction) MoveForward { + [ self RotateForward ]; +} + +/* + ======================== + MoveBackward - + + Interface Builder Direct Access to moving the Carousel + ======================== + */ +- (IBAction) MoveBackward { + [ self RotateBackward ]; +} + +/* + ======================== + RotateToOrigin + ======================== + */ +- (void) RotateToOrigin { + + // Animate back to the correct position. + // Move the Current Selection to Next Selection + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; + [UIView setAnimationBeginsFromCurrentState:YES]; + + // Move them into Place. + mainSelection.frame = mainRect; + prevSelection.frame = prevRect; + nextSelection.frame = nextRect; + + mainSelection.alpha = 1.0f; + nextSelection.alpha = CAROUSEL_BACKITEMS_ALPHA; + prevSelection.alpha = CAROUSEL_BACKITEMS_ALPHA; + + [UIView commitAnimations]; +} + +/* + ======================== + RotateForward + ======================== + */ +- (void) RotateForward { + + if( prevSelection == nil || nextSelection == nil ) { + + // Flip book to the next selection. + // increment the item indicies. + currentItem++; + nextItem++; + prevItem++; + + // Check the Extents. + if( currentItem >= (NSInteger)[ carouselItems count ] ) { + currentItem = 0; + } + if( nextItem >= (NSInteger)[ carouselItems count ] ) { + nextItem = 0; + } + if( prevItem >= (NSInteger)[ carouselItems count ] ) { + prevItem = 0; + } + + idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger)currentItem ]; + + // Set the Main Selection Text. + [ selectionLabel setText: cItem.title ]; + + // Set the prev selection UIImage + mainSelection.image = cItem.image; + + [self sendActionsForControlEvents:UIControlEventValueChanged]; + + return; + } + + + UIImageView * tempMain = mainSelection; + UIImageView * tempPrev = prevSelection; + UIImageView * tempNext = nextSelection; + + // Move the Current Selection to Next Selection + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; + [UIView setAnimationBeginsFromCurrentState:YES]; + + // Move them into Place. + mainSelection.frame = nextRect; + prevSelection.frame = mainRect; + nextSelection.frame = prevRect; + + // Darken the prev/next + mainSelection.alpha = CAROUSEL_BACKITEMS_ALPHA; + prevSelection.alpha = CAROUSEL_FRONTITEM_ALPHA; + nextSelection.alpha = CAROUSEL_BACKITEMS_ALPHA; + + [UIView commitAnimations]; + + + // Swap out the ImageViews so that they are in the correct order. + nextSelection = tempMain; + mainSelection = tempPrev; + prevSelection = tempNext; + + // Make sure they are in back of the main selection. + [ self sendSubviewToBack: nextSelection ]; + [ self sendSubviewToBack: prevSelection ]; + + // increment the item indicies. + currentItem++; + nextItem++; + prevItem++; + + // Check the Extents. + if( currentItem >= (NSInteger)[ carouselItems count ] ) { + currentItem = 0; + } + if( nextItem >= (NSInteger)[ carouselItems count ] ) { + nextItem = 0; + } + if( prevItem >= (NSInteger)[ carouselItems count ] ) { + prevItem = 0; + } + + // Get the items At the new layout. + idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger)currentItem ]; + idCarouselItem * nItem = [ carouselItems objectAtIndex: (NSUInteger)nextItem ]; + idCarouselItem * pItem = [ carouselItems objectAtIndex: (NSUInteger)prevItem ]; + + // Set the Main Selection Text. + [ selectionLabel setText: cItem.title ]; + + // Set the prev selection UIImage + mainSelection.image = cItem.image; + prevSelection.image = nItem.image; + nextSelection.image = pItem.image; + + [self sendActionsForControlEvents:UIControlEventValueChanged]; +} + +/* + ======================== + RotateBackward + ======================== + */ +- (void) RotateBackward { + + if( nextSelection == nil || prevSelection == nil ) { + + // increment the item indicies. + currentItem--; + nextItem--; + prevItem--; + + // Check the Extents. + if( currentItem < 0 ) { + currentItem = (NSInteger)[ carouselItems count ] - 1; + } + if( nextItem < 0 ) { + nextItem = (NSInteger)[ carouselItems count ] - 1;; + } + if( prevItem < 0 ) { + prevItem = (NSInteger)[ carouselItems count ] - 1;; + } + + idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger)currentItem ]; + + // Set the Main Selection Text. + [ selectionLabel setText: cItem.title ]; + + // Set the prev selection UIImage + mainSelection.image = cItem.image; + + [self sendActionsForControlEvents:UIControlEventValueChanged]; + + return; + } + + UIImageView * tempMain = mainSelection; + UIImageView * tempPrev = prevSelection; + UIImageView * tempNext = nextSelection; + + // Move the Current Selection to Next Selection + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; + [UIView setAnimationBeginsFromCurrentState:YES]; + + // Move them into Place. + mainSelection.frame = prevRect; + prevSelection.frame = nextRect; + nextSelection.frame = mainRect; + + // Darken the prev/next + mainSelection.alpha = CAROUSEL_BACKITEMS_ALPHA; + prevSelection.alpha = CAROUSEL_BACKITEMS_ALPHA; + nextSelection.alpha = CAROUSEL_FRONTITEM_ALPHA; + + [UIView commitAnimations]; + + // Swap out the ImageViews so that they are in the correct order. + nextSelection = tempPrev; + mainSelection = tempNext; + prevSelection = tempMain; + + // Make sure they are in back of the main selection. + [ self sendSubviewToBack: nextSelection ]; + [ self sendSubviewToBack: prevSelection ]; + + // increment the item indicies. + currentItem--; + nextItem--; + prevItem--; + + // Check the Extents. + if( currentItem < 0 ) { + currentItem = (NSInteger)[ carouselItems count ] - 1; + } + if( nextItem < 0 ) { + nextItem = (NSInteger)[ carouselItems count ] - 1;; + } + if( prevItem < 0 ) { + prevItem = (NSInteger)[ carouselItems count ] - 1;; + } + + // Get the items At the new layout. + idCarouselItem * cItem = [ carouselItems objectAtIndex: (NSUInteger) currentItem ]; + idCarouselItem * nItem = [ carouselItems objectAtIndex: (NSUInteger)nextItem ]; + idCarouselItem * pItem = [ carouselItems objectAtIndex: (NSUInteger)prevItem ]; + + // Set the Main Selection Text. + [ selectionLabel setText: cItem.title ]; + + // Set the prev selection UIImage + mainSelection.image = cItem.image; + prevSelection.image = nItem.image; + nextSelection.image = pItem.image; + + [self sendActionsForControlEvents:UIControlEventValueChanged]; +} + +@end diff --git a/code/ios/Label.h b/code/ios/Label.h new file mode 100755 index 0000000..8081abd --- /dev/null +++ b/code/ios/Label.h @@ -0,0 +1,30 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import + + +@interface idLabel : UILabel { + +} + +- (void) SetupLabel: ( NSString * )fontName ; + +@end diff --git a/code/ios/Label.mm b/code/ios/Label.mm new file mode 100755 index 0000000..39eb8c2 --- /dev/null +++ b/code/ios/Label.mm @@ -0,0 +1,56 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ +#import +#import +#import "Label.h" +#include "Localization.h" +#include "iphone_delegate.h" + +@implementation idLabel + +/* + ======================== + awakeFromNib + ======================== + */ +- (void)awakeFromNib { + [ super awakeFromNib ]; + [ self SetupLabel:[gAppDelegate GetFontName]]; +} + + +/* + ======================== + SetupLabel + ======================== + */ +- (void) SetupLabel: ( NSString * )fontName { + + // Set the Font + CGFloat points = self.font.pointSize; + self.font = [UIFont fontWithName:fontName size:points]; + + // Localize the text. + NSString * unLocText = self.text; + const char * utf8string = idLocalization_GetString( [unLocText UTF8String ] ); + self.text = [ NSString stringWithCString: utf8string encoding:NSUTF8StringEncoding ]; +} + +@end diff --git a/code/ios/LabelButton.h b/code/ios/LabelButton.h new file mode 100755 index 0000000..d4e226f --- /dev/null +++ b/code/ios/LabelButton.h @@ -0,0 +1,40 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import +#import +#import "Label.h" + +@interface idLabelButton : UIButton { + + UIColor * labelColor; + UIColor * label2Color; +} + + +@property (nonatomic, retain) IBOutlet idLabel *label; +@property (nonatomic, retain) IBOutlet idLabel *label2; + +- (void) Hide; +- (void) Show; +- (void) Enable; +- (void) Disable; + +@end diff --git a/code/ios/LabelButton.mm b/code/ios/LabelButton.mm new file mode 100755 index 0000000..a21d0ab --- /dev/null +++ b/code/ios/LabelButton.mm @@ -0,0 +1,215 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ +#import "LabelButton.h" +#import "Label.h" +#include "iphone_delegate.h" +#if !TARGET_OS_TV +#import "Slider.h" +#endif +#import "Switch.h" +#import "Carousel.h" +#import "Localization.h" +@implementation idLabelButton + +@synthesize label; +@synthesize label2; + +#if TARGET_OS_TV +- (BOOL)canBecomeFocused { + return YES; +} +#endif + +/* + ======================== + idLabelButton::awakeFromNib + ======================== + */ +- (void)awakeFromNib { + + // Do not optimize my class out + [idLabel class ]; +#if !TARGET_OS_TV + [idSlider class]; +#endif + [idSwitch class]; + [idCarousel class]; + + CGFloat points = self.titleLabel.font.pointSize; + + self.titleLabel.font = [UIFont fontWithName:[gAppDelegate GetFontName] size:points]; + + // Localize the text. + NSString * unLocText = self.titleLabel.text; + if( unLocText ) { + const char * utf8string = idLocalization_GetString( [unLocText UTF8String ] ); + + NSString * localizedString = [ NSString stringWithCString: utf8string encoding:NSUTF8StringEncoding ]; + [self setTitle: localizedString forState:UIControlStateNormal]; + [self setTitle: localizedString forState:UIControlStateHighlighted]; + } + + if( self.label2 ) + label2Color = self.label2.textColor; + if( self.label ) { + labelColor = self.label.textColor; + } + + [super awakeFromNib]; +} + +/* + ======================== + idLabelButton::setHighlighted + ======================== + */ +- (void)setHighlighted:(BOOL)highlight { + if( highlight ) { + if( self.label ) + self.label.textColor = self.label.highlightedTextColor; + if( self.label2 ) + self.label2.textColor = self.label2.highlightedTextColor; + } else if( self.enabled ) { + if( self.label ) + // don't know what this does, but it's crashing things, so I'm disabling for now -tkidd +// self.label.textColor = labelColor; + if( self.label2 ) + self.label2.textColor = label2Color; + } + + [super setHighlighted:highlight]; + + // Localize the text. + NSString * unLocText = self.titleLabel.text; + if( unLocText ) { + const char * utf8string = idLocalization_GetString( [unLocText UTF8String ] ); + self.titleLabel.text = [ NSString stringWithCString: utf8string encoding:NSUTF8StringEncoding ]; + } +} + +/* + ======================== + idLabelButton::setEnabled + ======================== + */ +- (void)setEnabled:(BOOL)enabled { + if( !enabled ) { + if( self.label ) + self.label.textColor = self.label.highlightedTextColor; + if( self.label2 ) + self.label2.textColor = self.label2.highlightedTextColor; + } else { + if( self.label ) + self.label.textColor = labelColor; + if( self.label2 ) + self.label2.textColor = label2Color; + } + + [super setEnabled:enabled]; + + // Localize the text. + NSString * unLocText = self.titleLabel.text; + if( unLocText ) { + const char * utf8string = idLocalization_GetString( [unLocText UTF8String ] ); + self.titleLabel.text = [ NSString stringWithCString: utf8string encoding:NSUTF8StringEncoding ]; + } +} + +/* + ======================== + idLabelButton::Enable + ======================== + */ +- (void) Enable { + + self.enabled = YES; + if( self.label ) + label.enabled = YES; + if( self.label2 ) + label2.enabled = YES; +} + +/* + ======================== + idLabelButton::Disable + ======================== + */ +- (void) Disable { + self.enabled = NO; + if( self.label ) + label.enabled = NO; + if( self.label2 ) + label2.enabled = NO; +} + +/* + ======================== + idLabelButton::Hide + ======================== + */ +- (void) Hide { + + [UIView beginAnimations:@"Hide" context:nil]; + [UIView setAnimationDuration:1.0f]; + [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(Disable)]; + + self.alpha = 0.0f; + if( self.label ) + label.alpha = 0.0f; + if( self.label2 ) + label2.alpha = 0.0f; + + [UIView commitAnimations]; +} + +/* + ======================== + idLabelButton::Show + ======================== + */ +- (void) Show { + + [UIView beginAnimations:@"Show" context:nil]; + [UIView setAnimationDuration:1.0f]; + [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; + [UIView setAnimationBeginsFromCurrentState:YES]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(Enable)]; + + self.alpha = 1.0f; + if( self.label ) + label.alpha = 1.0f; + if( self.label2 ) + label2.alpha = 1.0f; + + [UIView commitAnimations]; +} + +- (void) dealloc { + label = nil; + label2 = nil; + + [super dealloc]; +} + +@end diff --git a/code/ios/Localization.h b/code/ios/Localization.h new file mode 100755 index 0000000..7faf09f --- /dev/null +++ b/code/ios/Localization.h @@ -0,0 +1,83 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +/* + ================================================================================================ + + A game-generic C++ wrapper around the iOS Localizable Strings functionality. + + Basics of Localaization on Apple platforms: + + Each Localization language has a bundle associated with it ( *.lproj ). + We gather the bundle for the current ( or needed ) language. + [[NSBundle mainBundle ] pathForResource:@"en" ofType:@"lproj" ]; + + You MUST add a Localizable.strings file ( named exactly that ) to the project. + + Apple provides a system for getting strings from the localizable.strings file. + NSString* nsString = [ bundle localizedStringForKey:key value:nil table:nil ]; + + The Localizable.strings file must be formatted like: + "KEY" = "VALUE"; + and end with a semi-coln. + + Apple Developer Reference: + http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html + + We wrapper this up into 4 easy functions. + "Localization_Initialize" Must be called to create/set the current language bundle for the system. + "Localization_SetLanguage" Can be called at dynamically to set the language. + "Localization_GetString" Gets a string value from a key'd pair + + SUPPORTED LANGUAGES: + ENGLISH, + FRENCH, + ITALIAN, + GERMAN, + SPANISH + + ================================================================================================ + */ + +#ifndef IDMOBILELIB_LOCALIZATION_H +#define IDMOBILELIB_LOCALIZATION_H + +#ifdef __cplusplus + extern "C" { +#endif + + enum ID_LANGUAGE { + LANGUAGE_ENGLISH = 0, + LANGUAGE_FRENCH, + LANGUAGE_ITALIAN, + LANGUAGE_GERMAN, + LANGUAGE_SPANISH + }; + + void idLocalization_Initialize(); + void idLocalization_SetLanguage( enum ID_LANGUAGE language ); + enum ID_LANGUAGE idLocalization_GetLanguage(); + const char * idLocalization_GetString( const char * key ); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/code/ios/Localization.mm b/code/ios/Localization.mm new file mode 100755 index 0000000..e7632c9 --- /dev/null +++ b/code/ios/Localization.mm @@ -0,0 +1,134 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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 "Localization.h" +#include "LocalizationObjectiveC.h" + +#import + +static NSBundle* mCurrentBundle = NULL; +static ID_LANGUAGE mCurrentLanguage; +static const char* mCurrentLanguageStr; + +/* + ======================== + idLocalization::SetLanguage + Sets the language of the system with an enumeration passed in. + ======================== + */ +void idLocalization_SetLanguage( ID_LANGUAGE language ) { + + NSString* langPath = nil; + + switch( language ) { + case LANGUAGE_ENGLISH: + langPath = [[NSBundle mainBundle ] pathForResource:@"en" ofType:@"lproj" ]; + break; + case LANGUAGE_FRENCH: + langPath = [[NSBundle mainBundle ] pathForResource:@"fr" ofType:@"lproj" ]; + break; + case LANGUAGE_ITALIAN: + langPath = [[NSBundle mainBundle ] pathForResource:@"it" ofType:@"lproj" ]; + break; + case LANGUAGE_GERMAN: + langPath = [[NSBundle mainBundle ] pathForResource:@"de" ofType:@"lproj" ]; + break; + case LANGUAGE_SPANISH: + langPath = [[NSBundle mainBundle ] pathForResource:@"es" ofType:@"lproj" ]; + break; + default: + langPath = [[NSBundle mainBundle ] pathForResource:@"en" ofType:@"lproj" ]; + break; + } + + mCurrentBundle = [[NSBundle bundleWithPath:langPath] retain ]; +} + + +/* + ======================== + idLocalization::GetLanguage + Gets the current system's language + ======================== + */ +ID_LANGUAGE idLocalization_GetLanguage() { + return mCurrentLanguage; +} + +/* + ======================== + idLocalization::Initialize + Gathers the local device's language, and sets that as the systems language. + ======================== + */ +void idLocalization_Initialize() { + + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + NSArray* languages = [defaults objectForKey:@"AppleLanguages"]; + NSString* current = [[languages objectAtIndex:0] retain ]; + mCurrentLanguageStr = [current UTF8String]; + + if([current isEqualToString:@"en"]){ + mCurrentLanguage = LANGUAGE_ENGLISH; + } else if([current isEqualToString:@"fr"]){ + mCurrentLanguage = LANGUAGE_FRENCH; + } else if([current isEqualToString:@"it"]){ + mCurrentLanguage = LANGUAGE_ENGLISH; + } else if([current isEqualToString:@"sp"] || [current isEqualToString:@"es"]){ + mCurrentLanguage = LANGUAGE_SPANISH; + } else if([current isEqualToString:@"ge"] || [current isEqualToString:@"de"]){ + mCurrentLanguage = LANGUAGE_GERMAN; + } else { + mCurrentLanguage = LANGUAGE_ENGLISH; + } + + idLocalization_SetLanguage( mCurrentLanguage ); +} + +/* + ======================== + idLocalization::GetString + Gets a String value from the pair key passed in from Localizable.strings file. + ======================== + */ +const char * idLocalization_GetString( const char * key ) { + + NSString* nsKey = [NSString stringWithUTF8String:key]; + NSString* nsString = [mCurrentBundle localizedStringForKey:nsKey value:nil table:nil]; + const char* cString = nil; + + if( nsString != nil ) { + cString = [nsString cStringUsingEncoding:NSWindowsCP1252StringEncoding]; + } else { + cString = key; + } + + return cString; +} + +/* + ======================== + idLocalization::GetString + Gets a String value from the pair key passed in from Localizable.strings file. + ======================== + */ +NSString * idLocalization_GetNSString( NSString * key ) { + return [mCurrentBundle localizedStringForKey:key value:nil table:nil]; +} diff --git a/code/ios/LocalizationObjectiveC.h b/code/ios/LocalizationObjectiveC.h new file mode 100755 index 0000000..d401f98 --- /dev/null +++ b/code/ios/LocalizationObjectiveC.h @@ -0,0 +1,39 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#ifndef idmobilelib_LocalizationObjectiveC_h +#define idmobilelib_LocalizationObjectiveC_h + +@class NSString; + +#ifdef __cplusplus +extern "C" { +#endif + +// If we already have an NSString localization key, we can use this function and avoid the +// overhead of the const char * <-> NSString * conversions. +NSString * idLocalization_GetNSString( NSString * key ); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/ios/RenderContext.h b/code/ios/RenderContext.h new file mode 100755 index 0000000..81070f8 --- /dev/null +++ b/code/ios/RenderContext.h @@ -0,0 +1,70 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#ifndef IDMOBILELIB_RENDER_CONTEXT_H +#define IDMOBILELIB_RENDER_CONTEXT_H + +#if defined(__OBJC__) && defined(__cplusplus) + +#import +#include +#include +#import +#import + + +class idRenderContext { +public: + + idRenderContext(); + virtual ~idRenderContext(); + + void Initialize( EAGLRenderingAPI apiVersion, EAGLSharegroup * sharegroup ); + void InitFrameBuffer( CAEAGLLayer * layer ); + + void Begin(); + void End(); + + void SetActiveContext(); + void SwapBuffers(); + + void SetContextWidth( int width ); + void SetContextHeight( int height ); + + int GetContextWidth() const { return mWidth; } + int GetContextHeight() const { return mHeight; } + EAGLSharegroup * GetShareGroup() { return [mEAGLContext sharegroup]; } + +protected: + + GLuint mViewRenderbuffer; + GLuint mViewFramebuffer; + GLuint mDepthRenderbuffer; + + EAGLContext *mEAGLContext; + + int mWidth; + int mHeight; + +}; + +#endif + +#endif // _RENDER_CONTEXT_H diff --git a/code/ios/RenderContext.mm b/code/ios/RenderContext.mm new file mode 100755 index 0000000..d10daaf --- /dev/null +++ b/code/ios/RenderContext.mm @@ -0,0 +1,174 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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 "RenderContext.h" + +/* + ========================================= + idRenderContext::idRenderContext + ========================================= + */ +idRenderContext::idRenderContext() : +mViewRenderbuffer( 0 ), +mViewFramebuffer( 0 ), +mDepthRenderbuffer( 0 ), +mEAGLContext( NULL ) { + + mWidth = 0; + mHeight = 0; +} + +/* + ========================================= + idRenderContext::Initialize + ========================================= + */ +void idRenderContext::Initialize( EAGLRenderingAPI apiVersion, EAGLSharegroup * sharegroup ) { + + // Allocate and initialize the Rendering context for this view. + if( sharegroup == NULL ) { + mEAGLContext = [[EAGLContext alloc] initWithAPI:apiVersion]; + } else { + + mEAGLContext = [[EAGLContext alloc] initWithAPI:apiVersion sharegroup: sharegroup]; + } + + assert( mEAGLContext ); + assert( [mEAGLContext API] == apiVersion ); + + SetActiveContext(); +} + +/* + ========================================= + idRenderContext::~idRenderContext + ========================================= + */ +idRenderContext::~idRenderContext() { + + glDeleteFramebuffersOES( 1, &mViewFramebuffer ); + mViewFramebuffer = 0; + glDeleteRenderbuffersOES( 1, &mViewRenderbuffer ); + mViewRenderbuffer = 0; + glDeleteRenderbuffersOES( 1, &mDepthRenderbuffer ); + mDepthRenderbuffer = 0; + + [ mEAGLContext release ]; +} + +/* + ========================================= + idRenderContext::SetActiveContext + ========================================= + */ +void idRenderContext::SetActiveContext() { + + if ( ![EAGLContext setCurrentContext:mEAGLContext]) { + assert( 0 ); + return; + } + +} + +/* + ========================================= + idRenderContext::SwapBuffers + ========================================= + */ +void idRenderContext::SwapBuffers() { + + glBindRenderbufferOES(GL_RENDERBUFFER_OES, mViewRenderbuffer); + + // present the renderbuffer for display + [mEAGLContext presentRenderbuffer:GL_RENDERBUFFER_OES]; + +} + +/* + ========================================= + idRenderContext::RenderBufferStorage + ========================================= + */ +void idRenderContext::InitFrameBuffer( CAEAGLLayer * layer ) { + + + glDeleteFramebuffersOES( 1, &mViewFramebuffer ); + mViewFramebuffer = 0; + glDeleteRenderbuffersOES( 1, &mViewRenderbuffer ); + mViewRenderbuffer = 0; + glDeleteRenderbuffersOES( 1, &mDepthRenderbuffer ); + mDepthRenderbuffer = 0; + + glGenFramebuffersOES(1, &mViewFramebuffer); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, mViewFramebuffer); + + glGenRenderbuffersOES(1, &mViewRenderbuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, mViewRenderbuffer); + + [mEAGLContext renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer]; + + // the backing sizes should be the same as the screen + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &mWidth); + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &mHeight); + + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, mViewRenderbuffer); + + glGenRenderbuffersOES(1, &mDepthRenderbuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, mDepthRenderbuffer); + glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, mWidth, mHeight); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, mDepthRenderbuffer); + + // the framebuffer will stay constant + glBindRenderbufferOES(GL_RENDERBUFFER_OES, mViewRenderbuffer); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, mViewFramebuffer); + + + if ( glCheckFramebufferStatusOES( GL_FRAMEBUFFER_OES ) != GL_FRAMEBUFFER_COMPLETE_OES ) { + assert( 0 ); + } + +} + +/* + ========================================= + idRenderContext::Begin + ========================================= + */ +void idRenderContext::Begin() { + + SetActiveContext(); + + // Clear the Buffer to begin for a new Frame. + //GL_Clear( true, true, false ); + + // Set the Viewport for our Context. + // GL_Viewport( 0, 0, mWidth, mHeight ); + +} + +/* + ========================================= + idRenderContext::End + ========================================= + */ +void idRenderContext::End() { + + SwapBuffers(); +} diff --git a/code/ios/Slider.h b/code/ios/Slider.h new file mode 100755 index 0000000..e781d5c --- /dev/null +++ b/code/ios/Slider.h @@ -0,0 +1,35 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ +#if !TARGET_OS_TV +#import +#import + + +@interface idSlider : UISlider { + + +} + +- (void) CustomizeSlider:( UIImage* )minimumImage + :( UIImage* )maximumImage + :( UIImage* )thumbImage; + +@end +#endif diff --git a/code/ios/Slider.mm b/code/ios/Slider.mm new file mode 100755 index 0000000..526e88d --- /dev/null +++ b/code/ios/Slider.mm @@ -0,0 +1,54 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#if !TARGET_OS_TV +#import "Slider.h" + + +@implementation idSlider + + + + +/* + ======================== + CustomizeSlider + ======================== + */ +- (void) CustomizeSlider:( UIImage* )minimumImage + :( UIImage* )maximumImage + :( UIImage* )thumbImage { + + minimumImage = nil; + maximumImage = nil; + + //[ self setMinimumTrackImage:minimumImage forState:UIControlStateNormal ]; + //[ self setMaximumTrackImage:maximumImage forState:UIControlStateNormal ]; + + [ self setThumbImage:thumbImage forState:UIControlStateNormal ]; + [ self setThumbImage:thumbImage forState:UIControlStateHighlighted ]; + +} +#endif + + + + +@end diff --git a/code/ios/Switch.h b/code/ios/Switch.h new file mode 100755 index 0000000..44eb71a --- /dev/null +++ b/code/ios/Switch.h @@ -0,0 +1,31 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import +#import + + +@interface idSwitch : UIButton { + BOOL on; +} + +@property(nonatomic,getter=isOn) BOOL on; + +@end diff --git a/code/ios/Switch.mm b/code/ios/Switch.mm new file mode 100755 index 0000000..9d0236a --- /dev/null +++ b/code/ios/Switch.mm @@ -0,0 +1,114 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "Switch.h" + + +@implementation idSwitch + +@synthesize on; + +#if TARGET_OS_TV +- (BOOL)canBecomeFocused { + return YES; +} +#endif + + +/* + ======================== + setOn + ======================== + */ +- (void)setOn:(BOOL)turnOn +{ + on = turnOn; + + if (on) + { + [ self setHighlighted: YES ]; + } + else + { + [ self setHighlighted: NO ]; + } +} + +/* + ======================== + touchesBegan + ======================== + */ +- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event +{ + NSLog(@"DOOM: touchesEnded"); + [super touchesBegan:touches withEvent:event]; +#if !TARGET_OS_TV + [self setOn: !on ]; +#endif +} + + +/* + ======================== + touchesEnded + ======================== + */ +- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event +{ + NSLog(@"DOOM: touchesEnded"); + [super touchesEnded:touches withEvent:event]; +#if !TARGET_OS_TV + if (on) + { + [ self setHighlighted: YES ]; + } + else + { + [ self setHighlighted: NO ]; + } +#endif +} + +- (void)pressesBegan:(NSSet *)presses withEvent:(UIPressesEvent *)event { + NSLog(@"DOOM: pressesBegan"); + [super pressesBegan:presses withEvent:event]; +#if TARGET_OS_TV +// [self setOn: !on ]; +// if (on) +// { +// [ self setHighlighted: YES ]; +// } +// else +// { +// [ self setHighlighted: NO ]; +// } +#endif +} + +- (void)pressesEnded:(NSSet *)presses withEvent:(UIPressesEvent *)event { + NSLog(@"DOOM: pressesEnded"); +} + +//- (void)drawRect:(CGRect)rect { +// +//} + +@end diff --git a/code/ios/View.h b/code/ios/View.h new file mode 100755 index 0000000..d970965 --- /dev/null +++ b/code/ios/View.h @@ -0,0 +1,49 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#ifndef IDMOBILELIB_VIEW_H +#define IDMOBILELIB_VIEW_H + +#import +#import +#import +#import +#include "RenderContext.h" + +/* + ================================================ + idView + + Standard Objective C OpenGL UIView Class + ================================================ + */ +@interface idView : UIView { +@public + idRenderContext mRenderContext; + +} +extern idView * gMainView; + +- (void) Initialize; +- (void) EndFrame; + +@end + +#endif diff --git a/code/ios/View.mm b/code/ios/View.mm new file mode 100755 index 0000000..a775c10 --- /dev/null +++ b/code/ios/View.mm @@ -0,0 +1,167 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "View.h" + +/* + ================================================ + idView + + Standard Objective C UIView Class + ================================================ + */ + +idView * gMainView; // global openGL View. + +@implementation idView + +/* + ================================== + idView::layerClass + ================================== + */ ++ (Class) layerClass +{ + return [CAEAGLLayer class]; +} + +/* + ================================== + idView::initWithCoder + ================================== + */ +- (id) initWithCoder:(NSCoder *)aCoder{ + + if ( ( self = [super initWithCoder:aCoder] ) ) { + [self Initialize]; + } + + return self; +} + +/* + ================================== + idView::initWithFrame + ================================== + */ +- (id) initWithFrame:(CGRect)rect{ + if ( ( self = [super initWithFrame:rect] ) ) { + [self Initialize]; + } + return self; +} + +/* + ================================== + idView::handleTouches + ================================== + */ +- (void) handleTouches:(UIEvent*)event { + (void)event; +} + + +/* + ================================== + idView::touchesBegan + ================================== +*/ +- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { + (void)touches; + + [self handleTouches:event]; +} + +/* + ================================== + idView::touchesMoved + ================================== +*/ +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + (void)touches; + + [self handleTouches:event]; +} + +/* + ================================== + idView::touchesEnded + ================================== +*/ +- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { + + (void)touches; + + [self handleTouches:event]; +} + +/* + ================================== + idView::touchesCancelled + ================================== + */ +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + + (void)touches; + + [self handleTouches:event]; +} + +/* + ================================== + idView::Initialize + ================================== + */ +- (void) Initialize { + +#if !TARGET_OS_TV + self.multipleTouchEnabled = YES; +#endif + gMainView = self; + + // Double the resolution on iPhone 4. + [self setContentScaleFactor:[UIScreen mainScreen].scale]; + + // Get the layer for this view + CAEAGLLayer *glLayer = (CAEAGLLayer *)self.layer; + glLayer.opaque = TRUE; + glLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, + kEAGLColorFormatRGB565, + kEAGLDrawablePropertyColorFormat, nil]; + + // Create Our Render Context. + mRenderContext.Initialize( kEAGLRenderingAPIOpenGLES1, NULL ); + + // Create our Frame Buffers. + mRenderContext.InitFrameBuffer( glLayer ); +} + +/* + ================================== + idView::EndFrame + ================================== + */ +- (void) EndFrame { + + mRenderContext.SwapBuffers(); +} + +@end diff --git a/code/iphone/.DS_Store b/code/iphone/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/code/iphone/.DS_Store and /dev/null differ diff --git a/code/iphone/Archive.zip b/code/iphone/Archive.zip new file mode 100644 index 0000000..720a022 Binary files /dev/null and b/code/iphone/Archive.zip differ diff --git a/code/iphone/BackgroundMusic.cpp b/code/iphone/BackgroundMusic.cpp old mode 100644 new mode 100755 index 2bcfcf8..6d0fc1a --- a/code/iphone/BackgroundMusic.cpp +++ b/code/iphone/BackgroundMusic.cpp @@ -1,7 +1,12 @@ /* - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. - + * BackgroundMusic.cpp + * doom + * + * Created by John Carmack on 5/15/09. + * Copyright 2009 Id Software. All rights reserved. + * + */ +/* 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 @@ -18,6 +23,8 @@ */ +// TODO: Figure out why I had to add a "2" to the end of a bunch of stuff here + //================================================================================================== // Includes @@ -26,8 +33,6 @@ // System Includes #include #include -#include -#include #include #include #include @@ -65,7 +70,7 @@ static Float32 gMasterVolumeGain = 0.5f; // Helper functions //================================================================================================== -OSStatus LoadFileDataInfo(const char *inFilePath, AudioFileID &outAFID, AudioStreamBasicDescription &outFormat, UInt64 &outDataSize) +OSStatus LoadFileDataInfo2(const char *inFilePath, AudioFileID &outAFID, AudioStreamBasicDescription &outFormat, UInt64 &outDataSize) { UInt32 thePropSize; @@ -89,14 +94,14 @@ OSStatus LoadFileDataInfo(const char *inFilePath, AudioFileID &outAFID, AudioStr return result; } -void CalculateBytesForTime (AudioStreamBasicDescription & inDesc, UInt32 inMaxPacketSize, Float64 inSeconds, UInt32 *outBufferSize, UInt32 *outNumPackets) +void CalculateBytesForTime2 (AudioStreamBasicDescription & inDesc, UInt32 inMaxPacketSize, Float64 inSeconds, UInt32 *outBufferSize, UInt32 *outNumPackets) { static const UInt32 maxBufferSize = 0x10000; // limit size to 64K static const UInt32 minBufferSize = 0x4000; // limit size to 16K if (inDesc.mFramesPerPacket) { Float64 numPacketsForTime = inDesc.mSampleRate / inDesc.mFramesPerPacket * inSeconds; - *outBufferSize = (long unsigned int)numPacketsForTime * inMaxPacketSize; + *outBufferSize = (UInt32)(numPacketsForTime * inMaxPacketSize); } else { // if frames per packet is zero, then the codec has no predictable packet == time // so we can't tailor this (we don't know how many Packets represent a time period @@ -161,7 +166,7 @@ static Boolean MatchFormatFlags(const AudioStreamBasicDescription& x, const Audi return xFlags == yFlags; } -Boolean FormatIsEqual(AudioStreamBasicDescription x, AudioStreamBasicDescription y) +Boolean FormatIsEqual2(AudioStreamBasicDescription x, AudioStreamBasicDescription y) { // the semantics for equality are: // 1) Values must match exactly @@ -180,9 +185,9 @@ Boolean FormatIsEqual(AudioStreamBasicDescription x, AudioStreamBasicDescription && MATCH(mBitsPerChannel) ; } -#pragma mark ***** BackgroundTrackMgr ***** +#pragma mark ***** BackgroundTrackMgr2 ***** //================================================================================================== -// BackgroundTrackMgr class +// BackgroundTrackMgr2 class //================================================================================================== typedef struct BG_FileInfo { std::string mFilePath; @@ -194,11 +199,11 @@ typedef struct BG_FileInfo { Boolean mFileDataInQueue; } BackgroundMusicFileInfo; -class BackgroundTrackMgr +class BackgroundTrackMgr2 { public: - BackgroundTrackMgr(); - ~BackgroundTrackMgr(); + BackgroundTrackMgr2(); + ~BackgroundTrackMgr2(); void Teardown(); @@ -225,10 +230,10 @@ class BackgroundTrackMgr Boolean mStopAtEnd; }; -BG_FileInfo *BackgroundTrackMgr::CurFileInfo; +BG_FileInfo *BackgroundTrackMgr2::CurFileInfo; -BackgroundTrackMgr::BackgroundTrackMgr() +BackgroundTrackMgr2::BackgroundTrackMgr2() : mQueue(0), mBufferByteSize(0), mCurrentPacket(0), @@ -238,11 +243,11 @@ mPacketDescs(NULL), mStopAtEnd(false) { } -BackgroundTrackMgr::~BackgroundTrackMgr() { +BackgroundTrackMgr2::~BackgroundTrackMgr2() { Teardown(); } -void BackgroundTrackMgr::Teardown() { +void BackgroundTrackMgr2::Teardown() { if (mQueue) { AudioQueueDispose(mQueue, true); mQueue = NULL; @@ -259,10 +264,10 @@ void BackgroundTrackMgr::Teardown() { } -void BackgroundTrackMgr::QueueCallback( void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer ) { +void BackgroundTrackMgr2::QueueCallback( void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer ) { // dispose of the buffer if no longer in use OSStatus result = noErr; - BackgroundTrackMgr *THIS = (BackgroundTrackMgr*)inUserData; + BackgroundTrackMgr2 *THIS = (BackgroundTrackMgr2*)inUserData; UInt32 nPackets = 0; // loop the current buffer if the following: // 1. file was loaded into the buffer previously @@ -275,8 +280,7 @@ void BackgroundTrackMgr::QueueCallback( void * inUserData, AudioQueueRef inAQ, A while (nPackets == 0) { // if loadAtOnce, get all packets in the file, otherwise ~.5 seconds of data nPackets = THIS->mNumPacketsToRead; - result = AudioFileReadPackets(CurFileInfo->mAFID, false, &numBytes, THIS->mPacketDescs, THIS->mCurrentPacket, &nPackets, - inCompleteAQBuffer->mAudioData); + result = AudioFileReadPacketData(CurFileInfo->mAFID, false, &numBytes, THIS->mPacketDescs, THIS->mCurrentPacket, &nPackets, inCompleteAQBuffer->mAudioData); AssertNoError("Error reading file data", end); inCompleteAQBuffer->mAudioDataByteSize = numBytes; @@ -314,7 +318,7 @@ void BackgroundTrackMgr::QueueCallback( void * inUserData, AudioQueueRef inAQ, A return; } -OSStatus BackgroundTrackMgr::SetupQueue(BG_FileInfo *inFileInfo) { +OSStatus BackgroundTrackMgr2::SetupQueue(BG_FileInfo *inFileInfo) { UInt32 size = 0; OSStatus err; OSStatus result = AudioQueueNewOutput(&inFileInfo->mFileFormat, QueueCallback, this, @@ -352,7 +356,7 @@ OSStatus BackgroundTrackMgr::SetupQueue(BG_FileInfo *inFileInfo) { return result; } -OSStatus BackgroundTrackMgr::SetupBuffers(BG_FileInfo *inFileInfo) { +OSStatus BackgroundTrackMgr2::SetupBuffers(BG_FileInfo *inFileInfo) { int numBuffersToQueue = kNumberBuffers; UInt32 maxPacketSize; UInt32 size = sizeof(maxPacketSize); @@ -366,7 +370,7 @@ OSStatus BackgroundTrackMgr::SetupBuffers(BG_FileInfo *inFileInfo) { AssertNoError("Error getting packet upper bound size", end); isFormatVBR = (inFileInfo->mFileFormat.mBytesPerPacket == 0 || inFileInfo->mFileFormat.mFramesPerPacket == 0); - CalculateBytesForTime(inFileInfo->mFileFormat, maxPacketSize, 0.5/*seconds*/, &mBufferByteSize, &mNumPacketsToRead); + CalculateBytesForTime2(inFileInfo->mFileFormat, maxPacketSize, 0.5/*seconds*/, &mBufferByteSize, &mNumPacketsToRead); // if the file is smaller than the capacity of all the buffer queues, always load it at once if ((mBufferByteSize * numBuffersToQueue) > inFileInfo->mFileDataSize) { @@ -406,7 +410,7 @@ OSStatus BackgroundTrackMgr::SetupBuffers(BG_FileInfo *inFileInfo) { return result; } -OSStatus BackgroundTrackMgr::LoadTrack(const char* inFilePath, Boolean inAddToQueue, Boolean inLoadAtOnce) { +OSStatus BackgroundTrackMgr2::LoadTrack(const char* inFilePath, Boolean inAddToQueue, Boolean inLoadAtOnce) { // OSStatus result = LoadFileDataInfo(CurFileInfo->mFilePath.c_str(), CurFileInfo->mAFID, CurFileInfo->mFileFormat, CurFileInfo->mFileDataSize); // AssertNoError("Error getting file data info", fail); OSStatus result; @@ -453,25 +457,25 @@ OSStatus BackgroundTrackMgr::LoadTrack(const char* inFilePath, Boolean inAddToQu return result; } -OSStatus BackgroundTrackMgr::SetVolume(Float32 inVolume) { +OSStatus BackgroundTrackMgr2::SetVolume(Float32 inVolume) { mVolume = inVolume; return AudioQueueSetParameter(mQueue, kAudioQueueParam_Volume, mVolume * gMasterVolumeGain); } -Float32 BackgroundTrackMgr::GetVolume() const { +Float32 BackgroundTrackMgr2::GetVolume() const { return mVolume; } -OSStatus BackgroundTrackMgr::Start() { +OSStatus BackgroundTrackMgr2::Start() { OSStatus result = AudioQueuePrime(mQueue, 1, NULL); if (result) { - printf("BackgroundTrackMgr: Error priming queue: %d\n", (int)result); + printf("BackgroundTrackMgr2: Error priming queue: %d\n", (int)result); return result; } return AudioQueueStart(mQueue, NULL); } -OSStatus BackgroundTrackMgr::Stop(Boolean inStopAtEnd) { +OSStatus BackgroundTrackMgr2::Stop(Boolean inStopAtEnd) { if (inStopAtEnd) { mStopAtEnd = true; return noErr; @@ -481,7 +485,7 @@ OSStatus BackgroundTrackMgr::Stop(Boolean inStopAtEnd) { } -static BackgroundTrackMgr sBackgroundTrackMgr; +static BackgroundTrackMgr2 sBackgroundTrackMgr; static char currentMusicName[1024]; @@ -533,6 +537,30 @@ void iphonePlayMusic( const char *name ) { iphoneStartMusic(); } +boolean sigilShredsLoaded; // Buckethead! +void iphoneStartMP3(const char *filename) { + if ( music->value == 0 ) { + // music is disabled + return; + } + + // necessary? -tkidd + char fullName[1024]; + sprintf( fullName, "%s", filename ); + + printf( "Starting music '%s'\n", fullName ); + + iphoneStopMusic(); + sBackgroundTrackMgr.LoadTrack( fullName, false, true); + sBackgroundTrackMgr.Start(); + + if ( !strcmp( currentMusicName, "intro" ) ) { + // stop the intro music at end, don't loop + sBackgroundTrackMgr.mStopAtEnd = true; + } else { + sBackgroundTrackMgr.mStopAtEnd = false; + } +} diff --git a/code/iphone/ControlsMenuView-tvos.xib b/code/iphone/ControlsMenuView-tvos.xib new file mode 100755 index 0000000..9e2a85a --- /dev/null +++ b/code/iphone/ControlsMenuView-tvos.xib @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/ControlsMenuView.xib b/code/iphone/ControlsMenuView.xib new file mode 100755 index 0000000..7e12698 --- /dev/null +++ b/code/iphone/ControlsMenuView.xib @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/ControlsMenuView.h b/code/iphone/ControlsMenuViewController.h old mode 100644 new mode 100755 similarity index 51% rename from code/iphone/ControlsMenuView.h rename to code/iphone/ControlsMenuViewController.h index e2de228..8f91a7f --- a/code/iphone/ControlsMenuView.h +++ b/code/iphone/ControlsMenuViewController.h @@ -1,25 +1,38 @@ /* - ======================================================================================= - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. + 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. - ======================================================================================= */ - - - #import -#import - -@interface ControlsMenuView : UIView { +/* + ================================================================================================ + ControlsMenuViewController + + ================================================================================================ + */ +@interface Doom_ControlsMenuViewController : UIViewController { + +#if !TARGET_OS_TV IBOutlet UISlider * movestickSize; IBOutlet UISlider * turnstickSize; IBOutlet UISlider * tiltMoveSpeed; IBOutlet UISlider * tiltTurnSpeed; - +#endif IBOutlet UIButton * singleThumbButton; IBOutlet UIButton * dualThumbButton; @@ -27,12 +40,12 @@ } - +#if !TARGET_OS_TV - (void) SetupSlider:(UISlider*)slider minimumTrack:(UIImage*)minImage maximumTrack:(UIImage*)maxImage thumb:(UIImage*)thumbImage; +#endif -- (void) SetOptions; - (IBAction) BackToMain; - (IBAction) HudLayoutPressed; - (IBAction) SingleThumbpadPressed; diff --git a/code/iphone/ControlsMenuView.m b/code/iphone/ControlsMenuViewController.mm old mode 100644 new mode 100755 similarity index 53% rename from code/iphone/ControlsMenuView.m rename to code/iphone/ControlsMenuViewController.mm index 82c1b48..b0563e3 --- a/code/iphone/ControlsMenuView.m +++ b/code/iphone/ControlsMenuViewController.mm @@ -1,75 +1,71 @@ /* - ======================================================================================= - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. + 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. - ======================================================================================= */ - - -#import "ControlsMenuView.h" -#import "doomAppDelegate.h" +#import "ControlsMenuViewController.h" #include "doomiphone.h" +#include "iphone_delegate.h" -@implementation ControlsMenuView - -- (void) SetOptions { - - movestickSize.value = stickMove->value / 255; - turnstickSize.value = stickTurn->value / 255; - tiltMoveSpeed.value = tiltMove->value; - tiltTurnSpeed.value = tiltTurn->value; - - if( controlScheme->value == 0 ) { - singleThumbButton.enabled = NO; - dualThumbButton.enabled = YES; - dirWheelButton.enabled = YES; - } else if( controlScheme->value == 1 ) { - singleThumbButton.enabled = YES; - dualThumbButton.enabled = NO; - dirWheelButton.enabled = YES; - } else if( controlScheme->value == 2 ) { - singleThumbButton.enabled = YES; - dualThumbButton.enabled = YES; - dirWheelButton.enabled = NO; - } - -} +/* + ================================================================================================ + ControlsMenuViewController + + ================================================================================================ + */ +@implementation Doom_ControlsMenuViewController -- (void) SetupSlider:(UISlider*)slider minimumTrack:(UIImage*)minImage - maximumTrack:(UIImage*)maxImage - thumb:(UIImage*)thumbImage { - - [slider setMinimumTrackImage:minImage forState:UIControlStateNormal]; - [slider setMaximumTrackImage:maxImage forState:UIControlStateNormal]; +/* + ======================== + Doom_ControlsMenuViewController::Initialize + ======================== + */ +- (void) Initialize { - [slider setThumbImage:thumbImage forState:UIControlStateNormal]; - [slider setThumbImage:thumbImage forState:UIControlStateHighlighted]; -} - -- (void) initialize{ - // Minimum track image setup. UIImage* minimumTrackImage = [UIImage imageNamed:@"SliderBar.png"]; - CGFloat minimumTrackImageCap = minimumTrackImage.size.width * 0.5f; - - UIImage* minimumTrackImageCapped = [minimumTrackImage stretchableImageWithLeftCapWidth:minimumTrackImageCap topCapHeight: 0.0f]; + NSInteger minimumTrackImageCap = (NSInteger)(minimumTrackImage.size.width * 0.5f); +#if TARGET_OS_TV + UIImage* minimumTrackImageCapped = [minimumTrackImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, minimumTrackImageCap, 0, 0)]; + NSLog(@"%@", minimumTrackImageCapped); +#else + UIImage* minimumTrackImageCapped = [minimumTrackImage stretchableImageWithLeftCapWidth:minimumTrackImageCap topCapHeight: 0]; +#endif // Maximum track image setup. UIImage* maximumTrackImage = [UIImage imageNamed:@"SliderBackground.png"]; - CGFloat maximumTrackImageCap = maximumTrackImage.size.width * 0.5f; - - UIImage* maximumTrackImageCapped = [maximumTrackImage stretchableImageWithLeftCapWidth:maximumTrackImageCap topCapHeight: 0.0f]; + NSInteger maximumTrackImageCap = (NSInteger)(maximumTrackImage.size.width * 0.5f); + +#if TARGET_OS_TV + UIImage* maximumTrackImageCapped = [maximumTrackImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, maximumTrackImageCap, 0, 0)]; + NSLog(@"%@", maximumTrackImageCapped); +#else + UIImage* maximumTrackImageCapped = [maximumTrackImage stretchableImageWithLeftCapWidth:maximumTrackImageCap topCapHeight: 0]; +#endif - // Thumb image. - UIImage* thumbImage = [UIImage imageNamed:@"SliderSkull.png"]; +#if !TARGET_OS_TV - // Set up slider instances. + // Thumb image. + UIImage* thumbImage = [UIImage imageNamed:@"SliderSkull.png"]; + + // Set up slider instances. [self SetupSlider:movestickSize minimumTrack:minimumTrackImageCapped maximumTrack:maximumTrackImageCapped thumb:thumbImage]; @@ -92,42 +88,114 @@ - (void) initialize{ maximumTrack:maximumTrackImageCapped thumb:thumbImage]; - -} + movestickSize.value = stickMove->value / 255; + turnstickSize.value = stickTurn->value / 255; + tiltMoveSpeed.value = tiltMove->value; + tiltTurnSpeed.value = tiltTurn->value; +#endif -- (void)awakeFromNib { - - [self initialize]; + if( controlScheme->value == 0 ) { + singleThumbButton.enabled = NO; + dualThumbButton.enabled = YES; + dirWheelButton.enabled = YES; + } else if( controlScheme->value == 1 ) { + singleThumbButton.enabled = YES; + dualThumbButton.enabled = NO; + dirWheelButton.enabled = YES; + } else if( controlScheme->value == 2 ) { + singleThumbButton.enabled = YES; + dualThumbButton.enabled = YES; + dirWheelButton.enabled = NO; + } } -- (id) initWithCoder:(NSCoder *)aCoder{ - - if(self = [super initWithCoder:aCoder] ) { - [self initialize]; +/* + ======================== + Doom_ControlsMenuViewController::initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization } - return self; } -- (id) initWithFrame:(CGRect)rect{ - if(self = [super initWithFrame:rect] ) { - [self initialize]; - } - return self; +/* + ======================== + Doom_ControlsMenuViewController::didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. } +#pragma mark - View lifecycle +/* + ======================== + Doom_ControlsMenuViewController::viewDidLoad + ======================== + */ +- (void)viewDidLoad +{ + [super viewDidLoad]; + [ self Initialize ]; +} + +#if !TARGET_OS_TV +/* + ======================== + Doom_ControlsMenuViewController::SetupSlider + ======================== + */ +- (void) SetupSlider:(UISlider*)slider minimumTrack:(UIImage*)minImage + maximumTrack:(UIImage*)maxImage + thumb:(UIImage*)thumbImage { + + //[slider setMinimumTrackImage:minImage forState:UIControlStateNormal]; + //slider setMaximumTrackImage:maxImage forState:UIControlStateNormal]; + + [slider setThumbImage:thumbImage forState:UIControlStateNormal]; + [slider setThumbImage:thumbImage forState:UIControlStateHighlighted]; +} +#endif + +/* + ======================== + Doom_ControlsMenuViewController::BackToMain + ======================== + */ - (IBAction) BackToMain { - [gAppDelegate MainMenu]; + + [self.navigationController popViewControllerAnimated:NO]; Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); } +/* + ======================== + Doom_ControlsMenuViewController::HudLayoutPressed + ======================== + */ - (IBAction) HudLayoutPressed { - [ gAppDelegate HUDLayout ]; + menuState = IPM_HUDEDIT; + HudEditFrame(); + [gAppDelegate ShowGLView ]; } +/* + ======================== + Doom_ControlsMenuViewController::SingleThumbpadPressed + ======================== + */ - (IBAction) SingleThumbpadPressed { Cvar_SetValue( controlScheme->name, 0 ); @@ -149,6 +217,11 @@ - (IBAction) SingleThumbpadPressed { } +/* + ======================== + Doom_ControlsMenuViewController::DualThumbpadPressed + ======================== + */ - (IBAction) DualThumbpadPressed { Cvar_SetValue( controlScheme->name, 1 ); @@ -169,6 +242,11 @@ - (IBAction) DualThumbpadPressed { } } +/* + ======================== + Doom_ControlsMenuViewController::DirWheelPressed + ======================== + */ - (IBAction) DirWheelPressed { Cvar_SetValue( controlScheme->name, 2 ); @@ -189,18 +267,38 @@ - (IBAction) DirWheelPressed { } } +/* + ======================== + Doom_ControlsMenuViewController::MoveStickValChanged + ======================== + */ - (IBAction) MoveStickValChanged { +#if !TARGET_OS_TV Cvar_SetValue( stickMove->name, movestickSize.value * 256.0f ); - +#endif + } +/* + ======================== + Doom_ControlsMenuViewController::TurnStickValChanged + ======================== + */ - (IBAction) TurnStickValChanged { +#if !TARGET_OS_TV Cvar_SetValue( stickTurn->name, turnstickSize.value * 256.0f ); +#endif } +/* + ======================== + Doom_ControlsMenuViewController::TiltMoveValChanged + ======================== + */ - (IBAction) TiltMoveValChanged { +#if !TARGET_OS_TV Cvar_SetValue( tiltMove->name, tiltMoveSpeed.value ); if ( tiltMove->value == 100 ) { @@ -211,12 +309,19 @@ - (IBAction) TiltMoveValChanged { Cvar_SetValue( tiltTurn->name, 0 ); tiltTurnSpeed.value = tiltTurn->value; } - +#endif + } +/* + ======================== + Doom_ControlsMenuViewController::TiltTurnValChanged + ======================== + */ - (IBAction) TiltTurnValChanged { +#if !TARGET_OS_TV Cvar_SetValue( tiltTurn->name, tiltTurnSpeed.value ); if ( tiltTurn->value == 1500 ) { @@ -227,8 +332,10 @@ - (IBAction) TiltTurnValChanged { Cvar_SetValue( tiltMove->name, 0 ); tiltMoveSpeed.value = tiltMove->value; } - +#endif } + + @end diff --git a/code/iphone/ControlsMenuView~ipad.xib b/code/iphone/ControlsMenuView~ipad.xib new file mode 100755 index 0000000..78939ca --- /dev/null +++ b/code/iphone/ControlsMenuView~ipad.xib @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/CreditsMenuView-tvos.xib b/code/iphone/CreditsMenuView-tvos.xib new file mode 100755 index 0000000..d465669 --- /dev/null +++ b/code/iphone/CreditsMenuView-tvos.xib @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/CreditsMenuView.xib b/code/iphone/CreditsMenuView.xib new file mode 100755 index 0000000..0067980 --- /dev/null +++ b/code/iphone/CreditsMenuView.xib @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/CreditsMenuViewController.h b/code/iphone/CreditsMenuViewController.h new file mode 100755 index 0000000..b306415 --- /dev/null +++ b/code/iphone/CreditsMenuViewController.h @@ -0,0 +1,37 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import + +/* + ================================================================================================ + CreditsMenuViewController + + ================================================================================================ + */ +@interface Doom_CreditsMenuViewController : UIViewController { + + IBOutlet UITableView *creditsList; + +} + +- (IBAction) BackToMain; + +@end diff --git a/code/iphone/CreditsMenuViewController.mm b/code/iphone/CreditsMenuViewController.mm new file mode 100755 index 0000000..fdc4d3b --- /dev/null +++ b/code/iphone/CreditsMenuViewController.mm @@ -0,0 +1,281 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "CreditsMenuViewController.h" +#include "doomiphone.h" +#include "iphone_delegate.h" + +@interface Doom_CreditsMenuViewController () + +@property (nonatomic, retain) UITableView *creditsList; + +@end + +@implementation Doom_CreditsMenuViewController + + +@synthesize creditsList; + +#define CREDITS_LINES 43 + +// 1 - heading 1 +// 2 - heading 2 +// 3 - normal text +// 4 - tiny text + +static const char * const CreditText[CREDITS_LINES] = { + "DOOM Classic", + "", + "Programming", + "John Carmack", + "Jeff Farrand", + "Ryan Gerieve", + "", + "Art", + "John Burnett", + "Danny Keys", + "", + "Audio", + "Zack Quarles", + "", + "QA Testing", + "Sean Palomino", + "", + "Doom & Ultimate Doom originally created by", + "id Software", + "", + "Programming", + "John Carmack", + "John Romero", + "Dave Taylor", + "", + "Design", + "John Romero", + "Sandy Peterson", + "", + "Art", + "Adrian Carmack", + "Kevin Cloud", + "", + "Audio", + "Bobby Prince", + "", + "Ultimate Doom", + "additional Level Design", + "John Anderson", + "Shawn Green", + "American McGee", + "John Romero", + "Tim Willts" +}; + +static const int CreditSizes[CREDITS_LINES] = { + 1, + 4, + 2, + 3, + 3, + 3, + 4, + 2, + 3, + 3, + 4, + 2, + 3, + 4, + 2, + 3, + 4, + 4, + 4, + 4, + 2, + 3, + 3, + 3, + 4, + 2, + 3, + 3, + 4, + 2, + 3, + 3, + 4, + 2, + 3, + 4, + 2, + 2, + 3, + 3, + 3, + 3, + 3, +}; + +/* + ======================== + Doom_CreditsMenuViewController::initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + + } + return self; +} + +/* + ======================== + Doom_CreditsMenuViewController::didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +#pragma mark - View lifecycle + +/* + ======================== + Doom_CreditsMenuViewController::viewDidLoad + ======================== + */ +- (void)viewDidLoad +{ + [super viewDidLoad]; + creditsList.allowsSelection = NO; +} + +/* + ======================== + Doom_CreditsMenuViewController::BackToMain + ======================== + */ +- (IBAction) BackToMain { + + [self.navigationController popViewControllerAnimated:NO]; + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +} + +/* + ======================== + + UITableView interface + + ======================== + */ + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return CREDITS_LINES; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *MyIdentifier = @"CreditsIdentifier"; + + UITableViewCell *cell = (UITableViewCell*)[self.creditsList dequeueReusableCellWithIdentifier:MyIdentifier]; + + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease]; + } + + cell.selectionStyle = UITableViewCellSelectionStyleNone; + + cell.textLabel.text = [NSString stringWithCString:CreditText[indexPath.row] encoding:NSASCIIStringEncoding]; + + cell.backgroundColor = UIColor.clearColor; + + cell.textLabel.textColor = [UIColor colorWithRed:255.0f/255.0f green:204.0f/255.0f blue:0.0f/255.0f alpha:1]; + + CGFloat points = cell.textLabel.font.pointSize; + + switch (CreditSizes[indexPath.row]) { + case 1: + points = 24; + break; + case 2: + points = 20; + break; + case 3: + points = 16; + break; + case 4: + points = 12; + break; + + default: + break; + } + + if (IS_IPAD) { + cell.textLabel.font = [UIFont fontWithName:[gAppDelegate GetFontName] size:points * 2]; + } else { + cell.textLabel.font = [UIFont fontWithName:[gAppDelegate GetFontName] size:points]; + } + + cell.textLabel.textAlignment = NSTextAlignmentCenter; + + return cell; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + + CGFloat size = 40; + + switch (CreditSizes[indexPath.row]) { + case 1: + size = 40; + break; + case 2: + size = 30; + break; + case 3: + size = 20; + break; + case 4: + size = 10; + break; + + default: + break; + } + + if (IS_IPAD) { + return size * 2; + } else { + return size; + } +} + +#if TARGET_OS_TV +-(NSArray> *)preferredFocusEnvironments { + return @[creditsList]; +} +#endif + +@end diff --git a/code/iphone/CreditsMenuView~ipad.xib b/code/iphone/CreditsMenuView~ipad.xib new file mode 100755 index 0000000..dcd30d7 --- /dev/null +++ b/code/iphone/CreditsMenuView~ipad.xib @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/Info.plist b/code/iphone/DOOM-iOS-Info.plist old mode 100644 new mode 100755 similarity index 71% rename from code/iphone/Info.plist rename to code/iphone/DOOM-iOS-Info.plist index b7203d2..e01a175 --- a/code/iphone/Info.plist +++ b/code/iphone/DOOM-iOS-Info.plist @@ -10,38 +10,36 @@ ${EXECUTABLE_NAME} CFBundleIconFile DOOM_57.png - CFBundleIconFiles - - DOOM_57.png - DOOM_114.png - DOOM_72.png - CFBundleIdentifier - com.idsoftware.${PRODUCT_NAME:identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL + CFBundleShortVersionString + 2.7 CFBundleSignature ???? CFBundleVersion - 2.1 + 2.7 LSRequiresIPhoneOS - NSMainNibFile - MainWindow - NSMainNibFile~ipad - MainWindow-iPad UIAppFonts idGinzaNar-Md2.otf + UIFileSharingEnabled + UIInterfaceOrientation UIInterfaceOrientationLandscapeLeft + UILaunchStoryboardName + DOOMLaunchScreen UIPrerenderedIcon + UIRequiresFullScreen + UIRequiresPersistentWiFi UIStatusBarHidden @@ -50,15 +48,13 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationPortrait UISupportedInterfaceOrientations~ipad UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationPortrait + UIViewControllerBasedStatusBarAppearance + diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Contents.json b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..0cc2196 --- /dev/null +++ b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-40.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-60.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-58.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-87.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-80.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-120.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-121.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-180.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-41.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-59.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-42.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-81.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-152.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-167.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-1024.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-1024.png new file mode 100755 index 0000000..67390a6 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-1024.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-120.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-120.png new file mode 100755 index 0000000..670e4cb Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-120.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-121.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-121.png new file mode 100644 index 0000000..670e4cb Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-121.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-152.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-152.png new file mode 100755 index 0000000..3f84730 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-152.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-167.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-167.png new file mode 100755 index 0000000..20d8b0b Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-167.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-180.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-180.png new file mode 100755 index 0000000..ff0f911 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-180.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-20.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-20.png new file mode 100755 index 0000000..ed6fcc0 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-20.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-29.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-29.png new file mode 100755 index 0000000..717ef66 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-29.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-40.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-40.png new file mode 100755 index 0000000..cc076fe Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-40.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-41.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-41.png new file mode 100644 index 0000000..cc076fe Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-41.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-42.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-42.png new file mode 100644 index 0000000..cc076fe Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-42.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-58.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-58.png new file mode 100755 index 0000000..4fbefdd Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-58.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-59.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-59.png new file mode 100644 index 0000000..4fbefdd Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-59.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-60.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-60.png new file mode 100755 index 0000000..4a6e89e Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-60.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-76.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100755 index 0000000..8592757 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-80.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-80.png new file mode 100755 index 0000000..ed9d09a Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-80.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-81.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-81.png new file mode 100644 index 0000000..ed9d09a Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-81.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-87.png b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-87.png new file mode 100755 index 0000000..d3dfd78 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/AppIcon.appiconset/Icon-87.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/Contents.json b/code/iphone/DOOM-iOS.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM-iOS.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-iOS.xcassets/background.imageset/Contents.json b/code/iphone/DOOM-iOS.xcassets/background.imageset/Contents.json new file mode 100644 index 0000000..fab6da4 --- /dev/null +++ b/code/iphone/DOOM-iOS.xcassets/background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doom_background.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-iOS.xcassets/background.imageset/doom_background.png b/code/iphone/DOOM-iOS.xcassets/background.imageset/doom_background.png new file mode 100644 index 0000000..8330ef2 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/background.imageset/doom_background.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/logo.imageset/Contents.json b/code/iphone/DOOM-iOS.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..8db0446 --- /dev/null +++ b/code/iphone/DOOM-iOS.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doomlogo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-iOS.xcassets/logo.imageset/doomlogo.png b/code/iphone/DOOM-iOS.xcassets/logo.imageset/doomlogo.png new file mode 100644 index 0000000..455a4c1 Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/logo.imageset/doomlogo.png differ diff --git a/code/iphone/DOOM-iOS.xcassets/splash.imageset/Contents.json b/code/iphone/DOOM-iOS.xcassets/splash.imageset/Contents.json new file mode 100644 index 0000000..66c07f0 --- /dev/null +++ b/code/iphone/DOOM-iOS.xcassets/splash.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doomcover.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-iOS.xcassets/splash.imageset/doomcover.jpg b/code/iphone/DOOM-iOS.xcassets/splash.imageset/doomcover.jpg new file mode 100644 index 0000000..15ae9cb Binary files /dev/null and b/code/iphone/DOOM-iOS.xcassets/splash.imageset/doomcover.jpg differ diff --git a/code/iphone/DOOM-tvOS-Info.plist b/code/iphone/DOOM-tvOS-Info.plist new file mode 100644 index 0000000..cfd92bf --- /dev/null +++ b/code/iphone/DOOM-tvOS-Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIAppFonts + + idGinzaNar-Md2.otf + + UIRequiredDeviceCapabilities + + arm64 + + UIUserInterfaceStyle + Automatic + + diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..0f07bf4 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "doom_tvos_icon_back.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/doom_tvos_icon_back.png b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/doom_tvos_icon_back.png new file mode 100644 index 0000000..1d85319 Binary files /dev/null and b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/doom_tvos_icon_back.png differ diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..6766d81 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "doom_tvos_icon_middle.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/doom_tvos_icon_middle.png b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/doom_tvos_icon_middle.png new file mode 100644 index 0000000..fece3ba Binary files /dev/null and b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/doom_tvos_icon_middle.png differ diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Contents.json new file mode 100644 index 0000000..2cdcef1 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Contents.json @@ -0,0 +1,35 @@ +{ + "assets" : [ + { + "size" : "1280x768", + "idiom" : "tv", + "filename" : "App Icon - App Store.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "400x240", + "idiom" : "tv", + "filename" : "App Icon.imagestack", + "role" : "primary-app-icon" + }, + { + "filename" : "LaunchImage.launchimage" + }, + { + "size" : "2320x720", + "idiom" : "tv", + "filename" : "Top Shelf Image Wide.imageset", + "role" : "top-shelf-image-wide" + }, + { + "size" : "1920x720", + "idiom" : "tv", + "filename" : "Top Shelf Image.imageset", + "role" : "top-shelf-image" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..bc4dcc8 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "orientation" : "landscape", + "idiom" : "tv", + "extent" : "full-screen", + "minimum-system-version" : "11.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "tv", + "filename" : "doom_tvos_launch.jpg", + "extent" : "full-screen", + "minimum-system-version" : "9.0", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/doom_tvos_launch.jpg b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/doom_tvos_launch.jpg new file mode 100644 index 0000000..57d0212 Binary files /dev/null and b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/doom_tvos_launch.jpg differ diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..b553161 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "doom_banner_1.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/doom_banner_1.png b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/doom_banner_1.png new file mode 100644 index 0000000..6f38c92 Binary files /dev/null and b/code/iphone/DOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/doom_banner_1.png differ diff --git a/code/iphone/DOOM-tvOS.xcassets/Contents.json b/code/iphone/DOOM-tvOS.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/LaunchImage.launchimage/Contents.json b/code/iphone/DOOM-tvOS.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..95b5982 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,50 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default@2x.png", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "minimum-system-version" : "7.0", + "subtype" : "retina4", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/LaunchImage.launchimage/Default@2x.png b/code/iphone/DOOM-tvOS.xcassets/LaunchImage.launchimage/Default@2x.png new file mode 100644 index 0000000..879be24 Binary files /dev/null and b/code/iphone/DOOM-tvOS.xcassets/LaunchImage.launchimage/Default@2x.png differ diff --git a/code/iphone/DOOM-tvOS.xcassets/background.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/background.imageset/Contents.json new file mode 100644 index 0000000..fab6da4 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doom_background.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/background.imageset/doom_background.png b/code/iphone/DOOM-tvOS.xcassets/background.imageset/doom_background.png new file mode 100644 index 0000000..8330ef2 Binary files /dev/null and b/code/iphone/DOOM-tvOS.xcassets/background.imageset/doom_background.png differ diff --git a/code/iphone/DOOM-tvOS.xcassets/logo.imageset/Contents.json b/code/iphone/DOOM-tvOS.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..8db0446 --- /dev/null +++ b/code/iphone/DOOM-tvOS.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doomlogo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM-tvOS.xcassets/logo.imageset/doomlogo.png b/code/iphone/DOOM-tvOS.xcassets/logo.imageset/doomlogo.png new file mode 100644 index 0000000..455a4c1 Binary files /dev/null and b/code/iphone/DOOM-tvOS.xcassets/logo.imageset/doomlogo.png differ diff --git a/code/iphone/Doom.xcodeproj/.svn/dir-prop-base b/code/iphone/DOOM.xcodeproj/.svn/dir-prop-base similarity index 100% rename from code/iphone/Doom.xcodeproj/.svn/dir-prop-base rename to code/iphone/DOOM.xcodeproj/.svn/dir-prop-base diff --git a/code/iphone/Doom.xcodeproj/.svn/entries b/code/iphone/DOOM.xcodeproj/.svn/entries similarity index 100% rename from code/iphone/Doom.xcodeproj/.svn/entries rename to code/iphone/DOOM.xcodeproj/.svn/entries diff --git a/code/iphone/Doom.xcodeproj/.svn/format b/code/iphone/DOOM.xcodeproj/.svn/format similarity index 100% rename from code/iphone/Doom.xcodeproj/.svn/format rename to code/iphone/DOOM.xcodeproj/.svn/format diff --git a/code/iphone/Doom.xcodeproj/.svn/prop-base/project.pbxproj.svn-base b/code/iphone/DOOM.xcodeproj/.svn/prop-base/project.pbxproj.svn-base similarity index 100% rename from code/iphone/Doom.xcodeproj/.svn/prop-base/project.pbxproj.svn-base rename to code/iphone/DOOM.xcodeproj/.svn/prop-base/project.pbxproj.svn-base diff --git a/code/iphone/Doom.xcodeproj/.svn/text-base/project.pbxproj.svn-base b/code/iphone/DOOM.xcodeproj/.svn/text-base/project.pbxproj.svn-base similarity index 100% rename from code/iphone/Doom.xcodeproj/.svn/text-base/project.pbxproj.svn-base rename to code/iphone/DOOM.xcodeproj/.svn/text-base/project.pbxproj.svn-base diff --git a/code/iphone/Doom.xcodeproj/_backup_project.bak b/code/iphone/DOOM.xcodeproj/_backup_project.bak similarity index 100% rename from code/iphone/Doom.xcodeproj/_backup_project.bak rename to code/iphone/DOOM.xcodeproj/_backup_project.bak diff --git a/code/iphone/Doom.xcodeproj/greghodges.mode1v3 b/code/iphone/DOOM.xcodeproj/greghodges.mode1v3 similarity index 100% rename from code/iphone/Doom.xcodeproj/greghodges.mode1v3 rename to code/iphone/DOOM.xcodeproj/greghodges.mode1v3 diff --git a/code/iphone/Doom.xcodeproj/greghodges.pbxuser b/code/iphone/DOOM.xcodeproj/greghodges.pbxuser similarity index 100% rename from code/iphone/Doom.xcodeproj/greghodges.pbxuser rename to code/iphone/DOOM.xcodeproj/greghodges.pbxuser diff --git a/code/iphone/Doom.xcodeproj/jeff.farrand.mode1v3 b/code/iphone/DOOM.xcodeproj/jeff.farrand.mode1v3 similarity index 100% rename from code/iphone/Doom.xcodeproj/jeff.farrand.mode1v3 rename to code/iphone/DOOM.xcodeproj/jeff.farrand.mode1v3 diff --git a/code/iphone/Doom.xcodeproj/jeff.farrand.pbxuser b/code/iphone/DOOM.xcodeproj/jeff.farrand.pbxuser similarity index 100% rename from code/iphone/Doom.xcodeproj/jeff.farrand.pbxuser rename to code/iphone/DOOM.xcodeproj/jeff.farrand.pbxuser diff --git a/code/iphone/Doom.xcodeproj/johnc.pbxuser b/code/iphone/DOOM.xcodeproj/johnc.pbxuser similarity index 100% rename from code/iphone/Doom.xcodeproj/johnc.pbxuser rename to code/iphone/DOOM.xcodeproj/johnc.pbxuser diff --git a/code/iphone/Doom.xcodeproj/johnc.perspectivev3 b/code/iphone/DOOM.xcodeproj/johnc.perspectivev3 similarity index 100% rename from code/iphone/Doom.xcodeproj/johnc.perspectivev3 rename to code/iphone/DOOM.xcodeproj/johnc.perspectivev3 diff --git a/code/iphone/DOOM.xcodeproj/project.pbxproj b/code/iphone/DOOM.xcodeproj/project.pbxproj new file mode 100755 index 0000000..0b2149c --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/project.pbxproj @@ -0,0 +1,8283 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + 4333CCE80F5CC23E00AE2B6F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */; }; + 4364BF3F0F5CB25900F29317 /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; + 43CF02FF0F56974E00E4A23D /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; + 43CF030A0F56D5C200E4A23D /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; + 43E8D2E10F4FC61E003F09B2 /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; + 43E8D4E00F51B48B003F09B2 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */; }; + 720EBBAE0F82E0BB003F989A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */; }; + 7229CE4A0F6C89F8004123C5 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; + 7229CE550F6C8CDE004123C5 /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; + 7239452C0F9C0E7500EADD62 /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; + 72484E5E0FB0E99900124E1C /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; + 72A560E21004FAEE00F788A5 /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; + 72B5FF390F7E5C3D00C8A372 /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; + 72D50DBC0F8ED98000BB49E6 /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; + 72E847650F93C61900AB3C99 /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; + 72E847740F93FFDB00AB3C99 /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; + 72E847750F93FFDB00AB3C99 /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; + 72E847B20F9400D700AB3C99 /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; + 72E847B30F9400D700AB3C99 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; + 72E847B50F9400D700AB3C99 /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; + 72E847B60F9400D700AB3C99 /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; + 72E847B70F9400D700AB3C99 /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; + 72E847B80F9400D700AB3C99 /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; + 72E847B90F9400D700AB3C99 /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; + 72E847BA0F9400D700AB3C99 /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; + 72E847BB0F9400D700AB3C99 /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + 72E847BC0F9400D700AB3C99 /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; + 72E847BD0F9400D700AB3C99 /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; + 72E847BE0F9400D700AB3C99 /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; + 72E847BF0F9400D700AB3C99 /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; + 72E847C00F9400D700AB3C99 /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; + 72E847C10F9400D700AB3C99 /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; + 72E847C20F9400D700AB3C99 /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; + 72E847C30F9400D700AB3C99 /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; + 72E847C40F9400D700AB3C99 /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; + 72E847C50F9400D700AB3C99 /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; + 72E847C60F9400D700AB3C99 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; + 72E848050F941A5900AB3C99 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; + 72E848070F941A5900AB3C99 /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; + 72E848080F941A5900AB3C99 /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; + 72E848090F941A5900AB3C99 /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; + 72E8480A0F941A5900AB3C99 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + 72E8480B0F941A5900AB3C99 /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; + 72E8480C0F941A5900AB3C99 /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; + 72E8480D0F941A5900AB3C99 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; + 72E8480E0F941A5900AB3C99 /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; + 72E8480F0F941A5900AB3C99 /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; + 72E848100F941A5900AB3C99 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; + 72E848110F941A5900AB3C99 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; + 72E848120F941A5900AB3C99 /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; + 72E848130F941A5900AB3C99 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; + 72E848140F941A5900AB3C99 /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + 72E848150F941A5900AB3C99 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; + 72E848160F941A5900AB3C99 /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; + 72E848170F941A5900AB3C99 /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; + 72E848180F941A5900AB3C99 /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; + 72E848190F941A5900AB3C99 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; + 72E8481A0F941A5900AB3C99 /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; + 72E8481B0F941A5900AB3C99 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; + 72E848260F941A8300AB3C99 /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; + 72E848270F941A8300AB3C99 /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; + 72E848280F941A8300AB3C99 /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; + 72E848290F941A8300AB3C99 /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; + 72E8483D0F941AAC00AB3C99 /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; + 72E8483E0F941AAC00AB3C99 /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; + 72E8483F0F941AAC00AB3C99 /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; + 72E848400F941AAC00AB3C99 /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; + 72E848410F941AAC00AB3C99 /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; + 72E848420F941AAC00AB3C99 /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; + 72E848430F941AAC00AB3C99 /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; + 72E848440F941AAC00AB3C99 /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; + 72E848450F941AAC00AB3C99 /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; + 72E8485C0F941ADC00AB3C99 /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; + 72E8485D0F941ADC00AB3C99 /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; + 72E8485E0F941ADC00AB3C99 /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; + 72E8485F0F941ADC00AB3C99 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + 72E848600F941ADC00AB3C99 /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; + 72E848610F941ADC00AB3C99 /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; + 72E848630F941ADC00AB3C99 /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; + 72E848640F941ADC00AB3C99 /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; + 72E848650F941ADC00AB3C99 /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; + 72E848660F941ADC00AB3C99 /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; + 72E848670F941ADC00AB3C99 /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; + 72E849600F942B9300AB3C99 /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; + 72E849610F942B9300AB3C99 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; + 72E849F60F94ED1100AB3C99 /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; + 72E84A290F9503F100AB3C99 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; + 72F1F9B40F96C18800AD49AC /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; + 72F1F9B50F96C18800AD49AC /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; + 72F1F9B60F96C18800AD49AC /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; + 72F1F9B70F96C18800AD49AC /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; + 72F1F9B80F96C18800AD49AC /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; + 72F1F9BA0F96C18800AD49AC /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; + 72F1F9BB0F96C18800AD49AC /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; + 72F1F9BC0F96C18800AD49AC /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; + 72F1F9BD0F96C18800AD49AC /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; + 72F1F9BE0F96C18800AD49AC /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; + A10638C3216EBC5A00BDE196 /* doom2.wad in Resources */ = {isa = PBXBuildFile; fileRef = A10638C2216EBC5A00BDE196 /* doom2.wad */; }; + A10638C8216EF7C700BDE196 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; + A10638C9216EF7C700BDE196 /* r_drawflush.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3020563345000955AE /* r_drawflush.inl */; }; + A10638CA216EF7C700BDE196 /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; + A10638CB216EF7C700BDE196 /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; + A10638CC216EF7C700BDE196 /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; + A10638CD216EF7C700BDE196 /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; + A10638CE216EF7C700BDE196 /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; + A10638CF216EF7C700BDE196 /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; + A10638D0216EF7C700BDE196 /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; + A10638D1216EF7C700BDE196 /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; + A10638D2216EF7C700BDE196 /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; + A10638D3216EF7C700BDE196 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E0720562FAF000955AE /* Localizable.strings */; }; + A10638D4216EF7C700BDE196 /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; + A10638D5216EF7C700BDE196 /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; + A10638D6216EF7C700BDE196 /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; + A10638D7216EF7C700BDE196 /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; + A10638D8216EF7C700BDE196 /* r_drawspan.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3120563345000955AE /* r_drawspan.inl */; }; + A10638D9216EF7C700BDE196 /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; + A10638DA216EF7C700BDE196 /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; + A10638DB216EF7C700BDE196 /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; + A10638DC216EF7C700BDE196 /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; + A10638DD216EF7C700BDE196 /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; + A10638DE216EF7C700BDE196 /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; + A10638DF216EF7C700BDE196 /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; + A10638E0216EF7C700BDE196 /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; + A10638E1216EF7C700BDE196 /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; + A10638E2216EF7C700BDE196 /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; + A10638E3216EF7C700BDE196 /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; + A10638E4216EF7C700BDE196 /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; + A10638E5216EF7C700BDE196 /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; + A10638E6216EF7C700BDE196 /* r_drawcolpipeline.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */; }; + A10638E7216EF7C700BDE196 /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; + A10638E8216EF7C700BDE196 /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; + A10638E9216EF7C700BDE196 /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2E20563345000955AE /* Makefile.am */; }; + A10638EA216EF7C700BDE196 /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; + A10638EB216EF7C700BDE196 /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; + A10638EC216EF7C700BDE196 /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; + A10638ED216EF7C700BDE196 /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; + A10638EE216EF7C700BDE196 /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; + A10638EF216EF7C700BDE196 /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; + A10638F0216EF7C700BDE196 /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; + A10638F1216EF7C700BDE196 /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; + A10638F2216EF7C700BDE196 /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; + A10638F3216EF7C700BDE196 /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; + A10638F4216EF7C700BDE196 /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; + A10638F5216EF7C700BDE196 /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; + A10638F6216EF7C700BDE196 /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; + A10638F7216EF7C700BDE196 /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; + A10638F8216EF7C700BDE196 /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; + A10638F9216EF7C700BDE196 /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; + A10638FA216EF7C700BDE196 /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; + A10638FB216EF7C700BDE196 /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; + A10638FC216EF7C700BDE196 /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; + A10638FD216EF7C700BDE196 /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; + A10638FE216EF7C700BDE196 /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; + A10638FF216EF7C700BDE196 /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; + A1063900216EF7C700BDE196 /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; + A1063901216EF7C700BDE196 /* EpisodeCell-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1EA3B8F208020B60038650E /* EpisodeCell-tvos.xib */; }; + A1063902216EF7C700BDE196 /* base.iPack in Resources */ = {isa = PBXBuildFile; fileRef = A12302FA205783E70075CBAD /* base.iPack */; }; + A1063904216EF7C700BDE196 /* prboom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F8205783E70075CBAD /* prboom.wad */; }; + A1063905216EF7C700BDE196 /* DOOM_76.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1820562FC4000955AE /* DOOM_76.png */; }; + A1063906216EF7C700BDE196 /* r_drawcolumn.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2D20563344000955AE /* r_drawcolumn.inl */; }; + A1063907216EF7C700BDE196 /* DOOM_120.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1720562FC3000955AE /* DOOM_120.png */; }; + A1063908216EF7C700BDE196 /* DOOM_144.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1620562FC3000955AE /* DOOM_144.png */; }; + A1063909216EF7C700BDE196 /* DOOM_152.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1520562FC3000955AE /* DOOM_152.png */; }; + A106390A216EF7C700BDE196 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; + A106390B216EF7C700BDE196 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; + A106390C216EF7C700BDE196 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; + A106390D216EF7C700BDE196 /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; + A106390E216EF7C700BDE196 /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; + A106390F216EF7C700BDE196 /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; + A1063910216EF7C700BDE196 /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; + A1063911216EF7C700BDE196 /* MainMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E15207F016500827A46 /* MainMenuView-tvos.xib */; }; + A1063913216EF7C700BDE196 /* MissionMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1B207F016600827A46 /* MissionMenuView-tvos.xib */; }; + A1063914216EF7C700BDE196 /* OpenGLView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E18207F016500827A46 /* OpenGLView-tvos.xib */; }; + A1063915216EF7C700BDE196 /* EpisodeMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1A207F016600827A46 /* EpisodeMenuView-tvos.xib */; }; + A1063916216EF7C700BDE196 /* SettingsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E19207F016500827A46 /* SettingsMenuView-tvos.xib */; }; + A1063917216EF7C700BDE196 /* CreditsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1C207F016600827A46 /* CreditsMenuView-tvos.xib */; }; + A1063918216EF7C700BDE196 /* ControlsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E17207F016500827A46 /* ControlsMenuView-tvos.xib */; }; + A1063919216EF7C700BDE196 /* LegalMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E16207F016500827A46 /* LegalMenuView-tvos.xib */; }; + A106391B216EF7C700BDE196 /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1020563B5F000955AE /* eas_math.c */; }; + A106391C216EF7C700BDE196 /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED120563B54000955AE /* eas_rtttl.c */; }; + A106391D216EF7C700BDE196 /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; + A106391E216EF7C700BDE196 /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; + A106391F216EF7C700BDE196 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; + A1063920216EF7C700BDE196 /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECE20563B53000955AE /* eas_otadata.c */; }; + A1063921216EF7C700BDE196 /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; + A1063922216EF7C700BDE196 /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0F20563B5F000955AE /* eas_tcdata.c */; }; + A1063923216EF7C700BDE196 /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; + A1063924216EF7C700BDE196 /* iphone_sys.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0A20562FAF000955AE /* iphone_sys.mm */; }; + A1063925216EF7C700BDE196 /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; + A1063926216EF7C700BDE196 /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; + A1063927216EF7C700BDE196 /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; + A1063928216EF7C700BDE196 /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; + A1063929216EF7C700BDE196 /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; + A106392A216EF7C700BDE196 /* iphone_common.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0620562FAF000955AE /* iphone_common.mm */; }; + A106392B216EF7C700BDE196 /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; + A106392C216EF7C700BDE196 /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A106392D216EF7C700BDE196 /* MissionMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD020562B74000955AE /* MissionMenuViewController.mm */; }; + A106392E216EF7C700BDE196 /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4B205634E7000955AE /* eas_config.c */; }; + A106392F216EF7C700BDE196 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; + A1063930216EF7C700BDE196 /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; + A1063931216EF7C700BDE196 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + A1063932216EF7C700BDE196 /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; + A1063933216EF7C700BDE196 /* GameController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C9520689D9500760204 /* GameController.mm */; }; + A1063934216EF7C700BDE196 /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEC20563B59000955AE /* eas_mixbuf.c */; }; + A1063935216EF7C700BDE196 /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; + A1063936216EF7C700BDE196 /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; + A1063937216EF7C700BDE196 /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; + A1063938216EF7C700BDE196 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; + A1063939216EF7C700BDE196 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DA205737F40075CBAD /* RenderContext.mm */; }; + A106393A216EF7C700BDE196 /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; + A106393B216EF7C700BDE196 /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0220563B5C000955AE /* eas_flog.c */; }; + A106393C216EF7C700BDE196 /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; + A106393D216EF7C700BDE196 /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; + A106393E216EF7C700BDE196 /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECF20563B53000955AE /* eas_data.c */; }; + A106393F216EF7C700BDE196 /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFC20563B5C000955AE /* eas_imelodydata.c */; }; + A1063940216EF7C700BDE196 /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; + A1063941216EF7C700BDE196 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; + A1063942216EF7C700BDE196 /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; + A1063943216EF7C700BDE196 /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECA20563B53000955AE /* eas_xmfdata.c */; }; + A1063944216EF7C700BDE196 /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; + A1063945216EF7C700BDE196 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; + A1063946216EF7C700BDE196 /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; + A1063947216EF7C700BDE196 /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; + A1063948216EF7C700BDE196 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063949216EF7C700BDE196 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; + A106394A216EF7C700BDE196 /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECB20563B53000955AE /* eas_xmf.c */; }; + A106394B216EF7C700BDE196 /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; + A106394C216EF7C700BDE196 /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED620563B54000955AE /* eas_wavefile.c */; }; + A106394D216EF7C700BDE196 /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; + A106394E216EF7C700BDE196 /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE520563B56000955AE /* eas_smfdata.c */; }; + A106394F216EF7C700BDE196 /* SoundEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0820562FAF000955AE /* SoundEngine.cpp */; }; + A1063950216EF7C700BDE196 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063951216EF7C700BDE196 /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; + A1063952216EF7C700BDE196 /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DC205737F40075CBAD /* View.mm */; }; + A1063953216EF7C700BDE196 /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0B20563B5E000955AE /* eas_voicemgt.c */; }; + A1063954216EF7C700BDE196 /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; + A1063955216EF7C700BDE196 /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D6205737F40075CBAD /* Label.mm */; }; + A1063956216EF7C700BDE196 /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEF20563B59000955AE /* eas_dlssynth.c */; }; + A1063957216EF7C700BDE196 /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; + A1063958216EF7C700BDE196 /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; + A1063959216EF7C700BDE196 /* MainMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD820562B75000955AE /* MainMenuViewController.mm */; }; + A106395A216EF7C700BDE196 /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; + A106395B216EF7C700BDE196 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; + A106395C216EF7C700BDE196 /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; + A106395D216EF7C700BDE196 /* eas_hostmm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E42205634E7000955AE /* eas_hostmm.c */; }; + A106395E216EF7C700BDE196 /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; + A106395F216EF7C700BDE196 /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFD20563B5C000955AE /* eas_mididata.c */; }; + A1063960216EF7C700BDE196 /* Doom_App.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E1D20562FD1000955AE /* Doom_App.m */; }; + A1063961216EF7C700BDE196 /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDA20563B54000955AE /* eas_pcmdata.c */; }; + A1063962216EF7C700BDE196 /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; + A1063963216EF7C700BDE196 /* eas_chorusdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDC20563B55000955AE /* eas_chorusdata.c */; }; + A1063964216EF7C700BDE196 /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE120563B55000955AE /* eas_chorus.c */; }; + A1063965216EF7C700BDE196 /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; + A1063966216EF7C700BDE196 /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; + A1063967216EF7C700BDE196 /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D7205737F40075CBAD /* LabelButton.mm */; }; + A1063968216EF7C700BDE196 /* SDL_Mixer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E27205632E2000955AE /* SDL_Mixer.m */; }; + A1063969216EF7C700BDE196 /* EASGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E5120563A06000955AE /* EASGlue.c */; }; + A106396A216EF7C700BDE196 /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302E1205737F50075CBAD /* Switch.mm */; }; + A106396B216EF7C700BDE196 /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0620563B5D000955AE /* eas_ima_tables.c */; }; + A106396C216EF7C700BDE196 /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; + A106396D216EF7C700BDE196 /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED820563B54000955AE /* eas_ota.c */; }; + A106396E216EF7C700BDE196 /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; + A106396F216EF7C700BDE196 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; + A1063970216EF7C700BDE196 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; + A1063971216EF7C700BDE196 /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; + A1063972216EF7C700BDE196 /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EED20563B59000955AE /* eas_smf.c */; }; + A1063973216EF7C700BDE196 /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; + A1063974216EF7C700BDE196 /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; + A1063975216EF7C700BDE196 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; + A1063976216EF7C700BDE196 /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; + A1063977216EF7C700BDE196 /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; + A1063978216EF7C700BDE196 /* iphone_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0320562FAF000955AE /* iphone_delegate.mm */; }; + A1063979216EF7C700BDE196 /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0C20563B5F000955AE /* eas_imelody.c */; }; + A106397A216EF7C700BDE196 /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; + A106397B216EF7C700BDE196 /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF720563B5B000955AE /* eas_tonecontrol.c */; }; + A106397C216EF7C700BDE196 /* LegalMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DC720562B73000955AE /* LegalMenuViewController.mm */; }; + A106397D216EF7C700BDE196 /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; + A106397E216EF7C700BDE196 /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; + A106397F216EF7C700BDE196 /* iphone_async.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0020562FAE000955AE /* iphone_async.cpp */; }; + A1063980216EF7C700BDE196 /* eas_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4C205634E7000955AE /* eas_wave.c */; }; + A1063981216EF7C700BDE196 /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED020563B54000955AE /* eas_imaadpcm.c */; }; + A1063982216EF7C700BDE196 /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; + A1063983216EF7C700BDE196 /* MainNavController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDC20562B75000955AE /* MainNavController.m */; }; + A1063984216EF7C700BDE196 /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; + A1063985216EF7C700BDE196 /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; + A1063986216EF7C700BDE196 /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; + A1063987216EF7C700BDE196 /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; + A1063988216EF7C700BDE196 /* eas_reverbdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0420563B5D000955AE /* eas_reverbdata.c */; }; + A1063989216EF7C700BDE196 /* eas_report.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E40205634E7000955AE /* eas_report.c */; }; + A106398A216EF7C700BDE196 /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; + A106398B216EF7C700BDE196 /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFA20563B5B000955AE /* eas_wtengine.c */; }; + A106398C216EF7C700BDE196 /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0520563B5D000955AE /* eas_public.c */; }; + A106398D216EF7C700BDE196 /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF920563B5B000955AE /* eas_wavefiledata.c */; }; + A106398E216EF7C700BDE196 /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; + A106398F216EF7C700BDE196 /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; + A1063990216EF7C700BDE196 /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED720563B54000955AE /* eas_mixer.c */; }; + A1063991216EF7C700BDE196 /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; + A1063992216EF7C700BDE196 /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFF20563B5C000955AE /* eas_rtttldata.c */; }; + A1063993216EF7C700BDE196 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; + A1063994216EF7C700BDE196 /* wt_22khz.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE420563B56000955AE /* wt_22khz.c */; }; + A1063995216EF7C700BDE196 /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063996216EF7C700BDE196 /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; + A1063997216EF7C700BDE196 /* ControlsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */; }; + A1063998216EF7C700BDE196 /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; + A1063999216EF7C700BDE196 /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; + A106399A216EF7C700BDE196 /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; + A106399B216EF7C700BDE196 /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0E20563B5F000955AE /* eas_reverb.c */; }; + A106399C216EF7C700BDE196 /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE820563B58000955AE /* eas_wtsynth.c */; }; + A106399D216EF7C700BDE196 /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; + A106399E216EF7C700BDE196 /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1220563B60000955AE /* eas_mdls.c */; }; + A106399F216EF7C700BDE196 /* SettingsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */; }; + A10639A0216EF7C700BDE196 /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; + A10639A1216EF7C700BDE196 /* i_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2320563253000955AE /* i_sound.c */; }; + A10639A2216EF7C700BDE196 /* CreditsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */; }; + A10639A3216EF7C700BDE196 /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; + A10639A4216EF7C700BDE196 /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; + A10639A5216EF7C700BDE196 /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; + A10639A6216EF7C700BDE196 /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; + A10639A7216EF7C700BDE196 /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; + A10639A8216EF7C700BDE196 /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; + A10639A9216EF7C700BDE196 /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; + A10639AA216EF7C700BDE196 /* iphone_sound.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0920562FAF000955AE /* iphone_sound.mm */; }; + A10639AB216EF7C700BDE196 /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; + A10639AD216EF7C700BDE196 /* iphone_glViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */; }; + A10639AE216EF7C700BDE196 /* mmus2mid.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2B20563344000955AE /* mmus2mid.c */; }; + A10639AF216EF7C700BDE196 /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; + A10639B0216EF7C700BDE196 /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; + A10639B1216EF7C700BDE196 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; + A10639B2216EF7C700BDE196 /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DE205737F40075CBAD /* Localization.mm */; }; + A10639B3216EF7C700BDE196 /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE320563B56000955AE /* eas_midi.c */; }; + A10639B4216EF7C700BDE196 /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; + A10639B5216EF7C700BDE196 /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; + A10639B6216EF7C700BDE196 /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; + A10639B7216EF7C700BDE196 /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF020563B5A000955AE /* eas_pcm.c */; }; + A10639B8216EF7C700BDE196 /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; + A10639B9216EF7C700BDE196 /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; + A10639BA216EF7C700BDE196 /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; + A10639BB216EF7C700BDE196 /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F3205738560075CBAD /* Carousel.mm */; }; + A10639BC216EF7C700BDE196 /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; + A10639BD216EF7C700BDE196 /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0D20563B5F000955AE /* eas_pan.c */; }; + A10639BE216EF7C700BDE196 /* iphone_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0520562FAF000955AE /* iphone_start.cpp */; }; + A10639BF216EF7C700BDE196 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; + A10639C1216EF7C700BDE196 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1EA3B84207F1D310038650E /* AVFoundation.framework */; }; + A10639C2216EF7C700BDE196 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E01207EFF8A00827A46 /* QuartzCore.framework */; }; + A10639C3216EF7C700BDE196 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E02207EFF8A00827A46 /* AudioToolbox.framework */; }; + A10639C4216EF7C700BDE196 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E03207EFF8A00827A46 /* OpenGLES.framework */; }; + A10639C5216EF7C700BDE196 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E05207EFF8A00827A46 /* UIKit.framework */; }; + A10639C6216EF7C700BDE196 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E06207EFF8A00827A46 /* Foundation.framework */; }; + A10639C7216EF7C700BDE196 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E07207EFF8A00827A46 /* CoreGraphics.framework */; }; + A10639C8216EF7C700BDE196 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E08207EFF8B00827A46 /* GameController.framework */; }; + A10639C9216EF7C700BDE196 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E09207EFF8B00827A46 /* OpenAL.framework */; }; + A10639D4216EF86700BDE196 /* doom2.wad in Resources */ = {isa = PBXBuildFile; fileRef = A10638C2216EBC5A00BDE196 /* doom2.wad */; }; + A10639D7216EFCEE00BDE196 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; + A10639D8216EFCEE00BDE196 /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; + A10639D9216EFCEE00BDE196 /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; + A10639DA216EFCEE00BDE196 /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; + A10639DB216EFCEE00BDE196 /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; + A10639DC216EFCEE00BDE196 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; + A10639DD216EFCEE00BDE196 /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; + A10639DE216EFCEE00BDE196 /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; + A10639DF216EFCEE00BDE196 /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; + A10639E0216EFCEE00BDE196 /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; + A10639E1216EFCEE00BDE196 /* CreditsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1E89C8D2067469D00760204 /* CreditsMenuView.xib */; }; + A10639E2216EFCEE00BDE196 /* CreditsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBA20562B2B000955AE /* CreditsMenuView~ipad.xib */; }; + A10639E3216EFCEE00BDE196 /* SecretMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBC20562B2B000955AE /* SecretMenuView.xib */; }; + A10639E4216EFCEE00BDE196 /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; + A10639E5216EFCEE00BDE196 /* EpisodeCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A184252063E63200302393 /* EpisodeCell.xib */; }; + A10639E6216EFCEE00BDE196 /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; + A10639E7216EFCEE00BDE196 /* ControlsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBB20562B2B000955AE /* ControlsMenuView~ipad.xib */; }; + A10639E8216EFCEE00BDE196 /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; + A10639E9216EFCEE00BDE196 /* SettingsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DC920562B73000955AE /* SettingsMenuView~ipad.xib */; }; + A10639EA216EFCEE00BDE196 /* MainMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCE20562B73000955AE /* MainMenuView.xib */; }; + A10639EB216EFCEE00BDE196 /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; + A10639EC216EFCEE00BDE196 /* MainMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD920562B75000955AE /* MainMenuView~ipad.xib */; }; + A10639ED216EFCEE00BDE196 /* DOOM_144.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1620562FC3000955AE /* DOOM_144.png */; }; + A10639EE216EFCEE00BDE196 /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; + A10639EF216EFCEE00BDE196 /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; + A10639F0216EFCEE00BDE196 /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; + A10639F1216EFCEE00BDE196 /* r_drawcolpipeline.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */; }; + A10639F2216EFCEE00BDE196 /* ControlsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DB620562B2B000955AE /* ControlsMenuView.xib */; }; + A10639F3216EFCEE00BDE196 /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; + A10639F4216EFCEE00BDE196 /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; + A10639F5216EFCEE00BDE196 /* EpisodeMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCA20562B73000955AE /* EpisodeMenuView.xib */; }; + A10639F6216EFCEE00BDE196 /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2E20563345000955AE /* Makefile.am */; }; + A10639F7216EFCEE00BDE196 /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; + A10639F8216EFCEE00BDE196 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; + A10639F9216EFCEE00BDE196 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; + A10639FA216EFCEE00BDE196 /* SettingsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD620562B74000955AE /* SettingsMenuView.xib */; }; + A10639FB216EFCEE00BDE196 /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; + A10639FC216EFCEE00BDE196 /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; + A10639FD216EFCEE00BDE196 /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; + A10639FE216EFCEE00BDE196 /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; + A10639FF216EFCEE00BDE196 /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; + A1063A00216EFCEE00BDE196 /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; + A1063A01216EFCEE00BDE196 /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; + A1063A02216EFCEE00BDE196 /* EpisodeMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DDA20562B75000955AE /* EpisodeMenuView~ipad.xib */; }; + A1063A03216EFCEE00BDE196 /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; + A1063A04216EFCEE00BDE196 /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; + A1063A05216EFCEE00BDE196 /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; + A1063A06216EFCEE00BDE196 /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; + A1063A07216EFCEE00BDE196 /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; + A1063A08216EFCEE00BDE196 /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; + A1063A09216EFCEE00BDE196 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E0720562FAF000955AE /* Localizable.strings */; }; + A1063A0A216EFCEE00BDE196 /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; + A1063A0B216EFCEE00BDE196 /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; + A1063A0C216EFCEE00BDE196 /* DOOMLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A112904F2069B62B00BEDEB5 /* DOOMLaunchScreen.storyboard */; }; + A1063A0D216EFCEE00BDE196 /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; + A1063A0E216EFCEE00BDE196 /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; + A1063A0F216EFCEE00BDE196 /* r_drawspan.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3120563345000955AE /* r_drawspan.inl */; }; + A1063A10216EFCEE00BDE196 /* DOOM_400.png in Resources */ = {isa = PBXBuildFile; fileRef = A1EA3B86207F9DE20038650E /* DOOM_400.png */; }; + A1063A11216EFCEE00BDE196 /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; + A1063A12216EFCEE00BDE196 /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; + A1063A13216EFCEE00BDE196 /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; + A1063A14216EFCEE00BDE196 /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; + A1063A15216EFCEE00BDE196 /* MissionMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DC620562B73000955AE /* MissionMenuView~ipad.xib */; }; + A1063A16216EFCEE00BDE196 /* OpenGLView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DE220562B76000955AE /* OpenGLView~ipad.xib */; }; + A1063A17216EFCEE00BDE196 /* EpisodeCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A176AC08206492DD00A96B7E /* EpisodeCell~ipad.xib */; }; + A1063A18216EFCEE00BDE196 /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; + A1063A19216EFCEE00BDE196 /* LegalMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCB20562B73000955AE /* LegalMenuView~ipad.xib */; }; + A1063A1A216EFCEE00BDE196 /* DOOM_76.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1820562FC4000955AE /* DOOM_76.png */; }; + A1063A1B216EFCEE00BDE196 /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; + A1063A1C216EFCEE00BDE196 /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; + A1063A1D216EFCEE00BDE196 /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; + A1063A1E216EFCEE00BDE196 /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; + A1063A1F216EFCEE00BDE196 /* DOOM_120.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1720562FC3000955AE /* DOOM_120.png */; }; + A1063A20216EFCEE00BDE196 /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; + A1063A21216EFCEE00BDE196 /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; + A1063A22216EFCEE00BDE196 /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; + A1063A23216EFCEE00BDE196 /* r_drawflush.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3020563345000955AE /* r_drawflush.inl */; }; + A1063A24216EFCEE00BDE196 /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; + A1063A25216EFCEE00BDE196 /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; + A1063A26216EFCEE00BDE196 /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; + A1063A27216EFCEE00BDE196 /* DOOM_152.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1520562FC3000955AE /* DOOM_152.png */; }; + A1063A28216EFCEE00BDE196 /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; + A1063A29216EFCEE00BDE196 /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; + A1063A2A216EFCEE00BDE196 /* prboom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F8205783E70075CBAD /* prboom.wad */; }; + A1063A2C216EFCEE00BDE196 /* base.iPack in Resources */ = {isa = PBXBuildFile; fileRef = A12302FA205783E70075CBAD /* base.iPack */; }; + A1063A2D216EFCEE00BDE196 /* OpenGLView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD220562B74000955AE /* OpenGLView.xib */; }; + A1063A2E216EFCEE00BDE196 /* r_drawcolumn.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2D20563344000955AE /* r_drawcolumn.inl */; }; + A1063A2F216EFCEE00BDE196 /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; + A1063A30216EFCEE00BDE196 /* MissionMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCC20562B73000955AE /* MissionMenuView.xib */; }; + A1063A31216EFCEE00BDE196 /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; + A1063A32216EFCEE00BDE196 /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; + A1063A33216EFCEE00BDE196 /* LegalMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DE020562B76000955AE /* LegalMenuView.xib */; }; + A1063A35216EFCEE00BDE196 /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; + A1063A36216EFCEE00BDE196 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + A1063A37216EFCEE00BDE196 /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; + A1063A38216EFCEE00BDE196 /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; + A1063A39216EFCEE00BDE196 /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1220563B60000955AE /* eas_mdls.c */; }; + A1063A3A216EFCEE00BDE196 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; + A1063A3B216EFCEE00BDE196 /* Doom_App.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E1D20562FD1000955AE /* Doom_App.m */; }; + A1063A3C216EFCEE00BDE196 /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; + A1063A3D216EFCEE00BDE196 /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; + A1063A3E216EFCEE00BDE196 /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DE205737F40075CBAD /* Localization.mm */; }; + A1063A3F216EFCEE00BDE196 /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; + A1063A40216EFCEE00BDE196 /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DC205737F40075CBAD /* View.mm */; }; + A1063A41216EFCEE00BDE196 /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0F20563B5F000955AE /* eas_tcdata.c */; }; + A1063A42216EFCEE00BDE196 /* iphone_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0320562FAF000955AE /* iphone_delegate.mm */; }; + A1063A43216EFCEE00BDE196 /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; + A1063A44216EFCEE00BDE196 /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; + A1063A45216EFCEE00BDE196 /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; + A1063A46216EFCEE00BDE196 /* iphone_async.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0020562FAE000955AE /* iphone_async.cpp */; }; + A1063A47216EFCEE00BDE196 /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; + A1063A48216EFCEE00BDE196 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; + A1063A49216EFCEE00BDE196 /* eas_report.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E40205634E7000955AE /* eas_report.c */; }; + A1063A4A216EFCEE00BDE196 /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECA20563B53000955AE /* eas_xmfdata.c */; }; + A1063A4B216EFCEE00BDE196 /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; + A1063A4C216EFCEE00BDE196 /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; + A1063A4D216EFCEE00BDE196 /* iphone_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0520562FAF000955AE /* iphone_start.cpp */; }; + A1063A4E216EFCEE00BDE196 /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; + A1063A4F216EFCEE00BDE196 /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; + A1063A50216EFCEE00BDE196 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DA205737F40075CBAD /* RenderContext.mm */; }; + A1063A51216EFCEE00BDE196 /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED820563B54000955AE /* eas_ota.c */; }; + A1063A52216EFCEE00BDE196 /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; + A1063A53216EFCEE00BDE196 /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; + A1063A54216EFCEE00BDE196 /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFC20563B5C000955AE /* eas_imelodydata.c */; }; + A1063A55216EFCEE00BDE196 /* MissionMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD020562B74000955AE /* MissionMenuViewController.mm */; }; + A1063A56216EFCEE00BDE196 /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063A57216EFCEE00BDE196 /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; + A1063A58216EFCEE00BDE196 /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; + A1063A59216EFCEE00BDE196 /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; + A1063A5A216EFCEE00BDE196 /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; + A1063A5B216EFCEE00BDE196 /* iphone_common.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0620562FAF000955AE /* iphone_common.mm */; }; + A1063A5C216EFCEE00BDE196 /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; + A1063A5D216EFCEE00BDE196 /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; + A1063A5E216EFCEE00BDE196 /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; + A1063A5F216EFCEE00BDE196 /* eas_hostmm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E42205634E7000955AE /* eas_hostmm.c */; }; + A1063A60216EFCEE00BDE196 /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; + A1063A61216EFCEE00BDE196 /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; + A1063A62216EFCEE00BDE196 /* MainMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD820562B75000955AE /* MainMenuViewController.mm */; }; + A1063A63216EFCEE00BDE196 /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; + A1063A64216EFCEE00BDE196 /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECB20563B53000955AE /* eas_xmf.c */; }; + A1063A65216EFCEE00BDE196 /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECE20563B53000955AE /* eas_otadata.c */; }; + A1063A66216EFCEE00BDE196 /* EpisodeMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDB20562B75000955AE /* EpisodeMenuViewController.mm */; }; + A1063A67216EFCEE00BDE196 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; + A1063A68216EFCEE00BDE196 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; + A1063A69216EFCEE00BDE196 /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE820563B58000955AE /* eas_wtsynth.c */; }; + A1063A6A216EFCEE00BDE196 /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; + A1063A6B216EFCEE00BDE196 /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; + A1063A6C216EFCEE00BDE196 /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; + A1063A6D216EFCEE00BDE196 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063A6E216EFCEE00BDE196 /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0D20563B5F000955AE /* eas_pan.c */; }; + A1063A6F216EFCEE00BDE196 /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; + A1063A70216EFCEE00BDE196 /* mmus2mid.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2B20563344000955AE /* mmus2mid.c */; }; + A1063A71216EFCEE00BDE196 /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; + A1063A72216EFCEE00BDE196 /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F3205738560075CBAD /* Carousel.mm */; }; + A1063A73216EFCEE00BDE196 /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFF20563B5C000955AE /* eas_rtttldata.c */; }; + A1063A74216EFCEE00BDE196 /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED020563B54000955AE /* eas_imaadpcm.c */; }; + A1063A75216EFCEE00BDE196 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; + A1063A76216EFCEE00BDE196 /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; + A1063A77216EFCEE00BDE196 /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; + A1063A78216EFCEE00BDE196 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; + A1063A79216EFCEE00BDE196 /* GameController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C9520689D9500760204 /* GameController.mm */; }; + A1063A7A216EFCEE00BDE196 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; + A1063A7B216EFCEE00BDE196 /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; + A1063A7C216EFCEE00BDE196 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; + A1063A7D216EFCEE00BDE196 /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063A7E216EFCEE00BDE196 /* eas_reverbdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0420563B5D000955AE /* eas_reverbdata.c */; }; + A1063A7F216EFCEE00BDE196 /* SDL_Mixer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E27205632E2000955AE /* SDL_Mixer.m */; }; + A1063A80216EFCEE00BDE196 /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EED20563B59000955AE /* eas_smf.c */; }; + A1063A81216EFCEE00BDE196 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; + A1063A82216EFCEE00BDE196 /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFD20563B5C000955AE /* eas_mididata.c */; }; + A1063A83216EFCEE00BDE196 /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; + A1063A84216EFCEE00BDE196 /* eas_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4C205634E7000955AE /* eas_wave.c */; }; + A1063A85216EFCEE00BDE196 /* EASGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E5120563A06000955AE /* EASGlue.c */; }; + A1063A86216EFCEE00BDE196 /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE320563B56000955AE /* eas_midi.c */; }; + A1063A87216EFCEE00BDE196 /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; + A1063A88216EFCEE00BDE196 /* wt_22khz.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE420563B56000955AE /* wt_22khz.c */; }; + A1063A89216EFCEE00BDE196 /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; + A1063A8A216EFCEE00BDE196 /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED620563B54000955AE /* eas_wavefile.c */; }; + A1063A8B216EFCEE00BDE196 /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE120563B55000955AE /* eas_chorus.c */; }; + A1063A8C216EFCEE00BDE196 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; + A1063A8D216EFCEE00BDE196 /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; + A1063A8E216EFCEE00BDE196 /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF020563B5A000955AE /* eas_pcm.c */; }; + A1063A8F216EFCEE00BDE196 /* iphone_glViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */; }; + A1063A90216EFCEE00BDE196 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; + A1063A91216EFCEE00BDE196 /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; + A1063A92216EFCEE00BDE196 /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; + A1063A93216EFCEE00BDE196 /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; + A1063A94216EFCEE00BDE196 /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; + A1063A95216EFCEE00BDE196 /* CreditsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */; }; + A1063A96216EFCEE00BDE196 /* iphone_sound.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0920562FAF000955AE /* iphone_sound.mm */; }; + A1063A97216EFCEE00BDE196 /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; + A1063A98216EFCEE00BDE196 /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; + A1063A99216EFCEE00BDE196 /* SoundEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0820562FAF000955AE /* SoundEngine.cpp */; }; + A1063A9A216EFCEE00BDE196 /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEF20563B59000955AE /* eas_dlssynth.c */; }; + A1063A9B216EFCEE00BDE196 /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; + A1063A9C216EFCEE00BDE196 /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; + A1063A9D216EFCEE00BDE196 /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; + A1063A9E216EFCEE00BDE196 /* iphone_sys.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0A20562FAF000955AE /* iphone_sys.mm */; }; + A1063A9F216EFCEE00BDE196 /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; + A1063AA0216EFCEE00BDE196 /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; + A1063AA1216EFCEE00BDE196 /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; + A1063AA2216EFCEE00BDE196 /* i_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2320563253000955AE /* i_sound.c */; }; + A1063AA3216EFCEE00BDE196 /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFA20563B5B000955AE /* eas_wtengine.c */; }; + A1063AA4216EFCEE00BDE196 /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0B20563B5E000955AE /* eas_voicemgt.c */; }; + A1063AA5216EFCEE00BDE196 /* LegalMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DC720562B73000955AE /* LegalMenuViewController.mm */; }; + A1063AA6216EFCEE00BDE196 /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF920563B5B000955AE /* eas_wavefiledata.c */; }; + A1063AA7216EFCEE00BDE196 /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0C20563B5F000955AE /* eas_imelody.c */; }; + A1063AA8216EFCEE00BDE196 /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; + A1063AA9216EFCEE00BDE196 /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; + A1063AAA216EFCEE00BDE196 /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECF20563B53000955AE /* eas_data.c */; }; + A1063AAB216EFCEE00BDE196 /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; + A1063AAC216EFCEE00BDE196 /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED720563B54000955AE /* eas_mixer.c */; }; + A1063AAD216EFCEE00BDE196 /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; + A1063AAE216EFCEE00BDE196 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063AAF216EFCEE00BDE196 /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; + A1063AB0216EFCEE00BDE196 /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; + A1063AB1216EFCEE00BDE196 /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0220563B5C000955AE /* eas_flog.c */; }; + A1063AB2216EFCEE00BDE196 /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4B205634E7000955AE /* eas_config.c */; }; + A1063AB3216EFCEE00BDE196 /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; + A1063AB4216EFCEE00BDE196 /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0E20563B5F000955AE /* eas_reverb.c */; }; + A1063AB5216EFCEE00BDE196 /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; + A1063AB6216EFCEE00BDE196 /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; + A1063AB7216EFCEE00BDE196 /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; + A1063AB8216EFCEE00BDE196 /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE520563B56000955AE /* eas_smfdata.c */; }; + A1063AB9216EFCEE00BDE196 /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEC20563B59000955AE /* eas_mixbuf.c */; }; + A1063ABA216EFCEE00BDE196 /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; + A1063ABB216EFCEE00BDE196 /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0520563B5D000955AE /* eas_public.c */; }; + A1063ABC216EFCEE00BDE196 /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; + A1063ABD216EFCEE00BDE196 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; + A1063ABE216EFCEE00BDE196 /* SettingsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */; }; + A1063ABF216EFCEE00BDE196 /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; + A1063AC0216EFCEE00BDE196 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; + A1063AC1216EFCEE00BDE196 /* Slider.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F0205738270075CBAD /* Slider.mm */; }; + A1063AC2216EFCEE00BDE196 /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; + A1063AC3216EFCEE00BDE196 /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D7205737F40075CBAD /* LabelButton.mm */; }; + A1063AC4216EFCEE00BDE196 /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302E1205737F50075CBAD /* Switch.mm */; }; + A1063AC5216EFCEE00BDE196 /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED120563B54000955AE /* eas_rtttl.c */; }; + A1063AC6216EFCEE00BDE196 /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; + A1063AC7216EFCEE00BDE196 /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; + A1063AC8216EFCEE00BDE196 /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDA20563B54000955AE /* eas_pcmdata.c */; }; + A1063AC9216EFCEE00BDE196 /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; + A1063ACA216EFCEE00BDE196 /* SecretMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB720562B2B000955AE /* SecretMenuViewController.mm */; }; + A1063ACB216EFCEE00BDE196 /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF720563B5B000955AE /* eas_tonecontrol.c */; }; + A1063ACC216EFCEE00BDE196 /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; + A1063ACD216EFCEE00BDE196 /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D6205737F40075CBAD /* Label.mm */; }; + A1063ACE216EFCEE00BDE196 /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; + A1063ACF216EFCEE00BDE196 /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; + A1063AD0216EFCEE00BDE196 /* eas_chorusdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDC20563B55000955AE /* eas_chorusdata.c */; }; + A1063AD1216EFCEE00BDE196 /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1020563B5F000955AE /* eas_math.c */; }; + A1063AD2216EFCEE00BDE196 /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; + A1063AD3216EFCEE00BDE196 /* MainNavController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDC20562B75000955AE /* MainNavController.m */; }; + A1063AD4216EFCEE00BDE196 /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0620563B5D000955AE /* eas_ima_tables.c */; }; + A1063AD5216EFCEE00BDE196 /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; + A1063AD6216EFCEE00BDE196 /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; + A1063AD7216EFCEE00BDE196 /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; + A1063AD8216EFCEE00BDE196 /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; + A1063AD9216EFCEE00BDE196 /* ControlsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */; }; + A1063ADA216EFCEE00BDE196 /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; + A1063ADB216EFCEE00BDE196 /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; + A1063ADD216EFCEE00BDE196 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E89C9320689D4B00760204 /* GameController.framework */; }; + A1063ADE216EFCEE00BDE196 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A63E5420563A6D000955AE /* AVFoundation.framework */; }; + A1063ADF216EFCEE00BDE196 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */; }; + A1063AE0216EFCEE00BDE196 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */; }; + A1063AE1216EFCEE00BDE196 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */; }; + A1063AE2216EFCEE00BDE196 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */; }; + A1063AE3216EFCEE00BDE196 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760611C2B19E004A9B9B /* Foundation.framework */; }; + A1063AE4216EFCEE00BDE196 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760811C2B19E004A9B9B /* OpenGLES.framework */; }; + A1063AE5216EFCEE00BDE196 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760A11C2B19E004A9B9B /* UIKit.framework */; }; + A1063AF2216EFD9900BDE196 /* tnt.wad in Resources */ = {isa = PBXBuildFile; fileRef = A1063AF0216EFD9800BDE196 /* tnt.wad */; }; + A1063AF3216EFD9900BDE196 /* plutonia.wad in Resources */ = {isa = PBXBuildFile; fileRef = A1063AF1216EFD9800BDE196 /* plutonia.wad */; }; + A1063AF6216F012000BDE196 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; + A1063AF7216F012000BDE196 /* r_drawflush.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3020563345000955AE /* r_drawflush.inl */; }; + A1063AF8216F012000BDE196 /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; + A1063AF9216F012000BDE196 /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; + A1063AFA216F012000BDE196 /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; + A1063AFB216F012000BDE196 /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; + A1063AFC216F012000BDE196 /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; + A1063AFD216F012000BDE196 /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; + A1063AFE216F012000BDE196 /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; + A1063AFF216F012000BDE196 /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; + A1063B00216F012000BDE196 /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; + A1063B01216F012000BDE196 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E0720562FAF000955AE /* Localizable.strings */; }; + A1063B02216F012000BDE196 /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; + A1063B03216F012000BDE196 /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; + A1063B04216F012000BDE196 /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; + A1063B05216F012000BDE196 /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; + A1063B06216F012000BDE196 /* r_drawspan.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3120563345000955AE /* r_drawspan.inl */; }; + A1063B07216F012000BDE196 /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; + A1063B08216F012000BDE196 /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; + A1063B09216F012000BDE196 /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; + A1063B0A216F012000BDE196 /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; + A1063B0B216F012000BDE196 /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; + A1063B0C216F012000BDE196 /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; + A1063B0D216F012000BDE196 /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; + A1063B0E216F012000BDE196 /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; + A1063B0F216F012000BDE196 /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; + A1063B10216F012000BDE196 /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; + A1063B11216F012000BDE196 /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; + A1063B12216F012000BDE196 /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; + A1063B13216F012000BDE196 /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; + A1063B14216F012000BDE196 /* r_drawcolpipeline.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */; }; + A1063B15216F012000BDE196 /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; + A1063B16216F012000BDE196 /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; + A1063B17216F012000BDE196 /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2E20563345000955AE /* Makefile.am */; }; + A1063B18216F012000BDE196 /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; + A1063B19216F012000BDE196 /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; + A1063B1A216F012000BDE196 /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; + A1063B1B216F012000BDE196 /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; + A1063B1C216F012000BDE196 /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; + A1063B1D216F012000BDE196 /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; + A1063B1E216F012000BDE196 /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; + A1063B1F216F012000BDE196 /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; + A1063B20216F012000BDE196 /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; + A1063B21216F012000BDE196 /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; + A1063B22216F012000BDE196 /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; + A1063B23216F012000BDE196 /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; + A1063B24216F012000BDE196 /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; + A1063B25216F012000BDE196 /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; + A1063B26216F012000BDE196 /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; + A1063B27216F012000BDE196 /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; + A1063B28216F012000BDE196 /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; + A1063B29216F012000BDE196 /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; + A1063B2A216F012000BDE196 /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; + A1063B2B216F012000BDE196 /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; + A1063B2C216F012000BDE196 /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; + A1063B2D216F012000BDE196 /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; + A1063B2E216F012000BDE196 /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; + A1063B2F216F012000BDE196 /* EpisodeCell-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1EA3B8F208020B60038650E /* EpisodeCell-tvos.xib */; }; + A1063B30216F012000BDE196 /* base.iPack in Resources */ = {isa = PBXBuildFile; fileRef = A12302FA205783E70075CBAD /* base.iPack */; }; + A1063B32216F012000BDE196 /* prboom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F8205783E70075CBAD /* prboom.wad */; }; + A1063B33216F012000BDE196 /* DOOM_76.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1820562FC4000955AE /* DOOM_76.png */; }; + A1063B34216F012000BDE196 /* r_drawcolumn.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2D20563344000955AE /* r_drawcolumn.inl */; }; + A1063B35216F012000BDE196 /* DOOM_120.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1720562FC3000955AE /* DOOM_120.png */; }; + A1063B37216F012000BDE196 /* DOOM_144.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1620562FC3000955AE /* DOOM_144.png */; }; + A1063B38216F012000BDE196 /* DOOM_152.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1520562FC3000955AE /* DOOM_152.png */; }; + A1063B39216F012000BDE196 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; + A1063B3A216F012000BDE196 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; + A1063B3B216F012000BDE196 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; + A1063B3C216F012000BDE196 /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; + A1063B3D216F012000BDE196 /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; + A1063B3E216F012000BDE196 /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; + A1063B3F216F012000BDE196 /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; + A1063B40216F012000BDE196 /* MainMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E15207F016500827A46 /* MainMenuView-tvos.xib */; }; + A1063B42216F012000BDE196 /* MissionMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1B207F016600827A46 /* MissionMenuView-tvos.xib */; }; + A1063B43216F012000BDE196 /* OpenGLView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E18207F016500827A46 /* OpenGLView-tvos.xib */; }; + A1063B44216F012000BDE196 /* EpisodeMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1A207F016600827A46 /* EpisodeMenuView-tvos.xib */; }; + A1063B45216F012000BDE196 /* SettingsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E19207F016500827A46 /* SettingsMenuView-tvos.xib */; }; + A1063B46216F012000BDE196 /* CreditsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1C207F016600827A46 /* CreditsMenuView-tvos.xib */; }; + A1063B47216F012000BDE196 /* ControlsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E17207F016500827A46 /* ControlsMenuView-tvos.xib */; }; + A1063B48216F012000BDE196 /* LegalMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E16207F016500827A46 /* LegalMenuView-tvos.xib */; }; + A1063B4A216F012000BDE196 /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1020563B5F000955AE /* eas_math.c */; }; + A1063B4B216F012000BDE196 /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED120563B54000955AE /* eas_rtttl.c */; }; + A1063B4C216F012000BDE196 /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; + A1063B4D216F012000BDE196 /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; + A1063B4E216F012000BDE196 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; + A1063B4F216F012000BDE196 /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECE20563B53000955AE /* eas_otadata.c */; }; + A1063B50216F012000BDE196 /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; + A1063B51216F012000BDE196 /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0F20563B5F000955AE /* eas_tcdata.c */; }; + A1063B52216F012000BDE196 /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; + A1063B53216F012000BDE196 /* iphone_sys.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0A20562FAF000955AE /* iphone_sys.mm */; }; + A1063B54216F012000BDE196 /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; + A1063B55216F012000BDE196 /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; + A1063B56216F012000BDE196 /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; + A1063B57216F012000BDE196 /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; + A1063B58216F012000BDE196 /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; + A1063B59216F012000BDE196 /* iphone_common.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0620562FAF000955AE /* iphone_common.mm */; }; + A1063B5A216F012000BDE196 /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; + A1063B5B216F012000BDE196 /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063B5C216F012000BDE196 /* MissionMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD020562B74000955AE /* MissionMenuViewController.mm */; }; + A1063B5D216F012000BDE196 /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4B205634E7000955AE /* eas_config.c */; }; + A1063B5E216F012000BDE196 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; + A1063B5F216F012000BDE196 /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; + A1063B60216F012000BDE196 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + A1063B61216F012000BDE196 /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; + A1063B62216F012000BDE196 /* GameController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C9520689D9500760204 /* GameController.mm */; }; + A1063B63216F012000BDE196 /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEC20563B59000955AE /* eas_mixbuf.c */; }; + A1063B64216F012000BDE196 /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; + A1063B65216F012000BDE196 /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; + A1063B66216F012000BDE196 /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; + A1063B67216F012000BDE196 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; + A1063B68216F012000BDE196 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DA205737F40075CBAD /* RenderContext.mm */; }; + A1063B69216F012000BDE196 /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; + A1063B6A216F012000BDE196 /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0220563B5C000955AE /* eas_flog.c */; }; + A1063B6B216F012000BDE196 /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; + A1063B6C216F012000BDE196 /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; + A1063B6D216F012000BDE196 /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECF20563B53000955AE /* eas_data.c */; }; + A1063B6E216F012000BDE196 /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFC20563B5C000955AE /* eas_imelodydata.c */; }; + A1063B6F216F012000BDE196 /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; + A1063B70216F012000BDE196 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; + A1063B71216F012000BDE196 /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; + A1063B72216F012000BDE196 /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECA20563B53000955AE /* eas_xmfdata.c */; }; + A1063B73216F012000BDE196 /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; + A1063B74216F012000BDE196 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; + A1063B75216F012000BDE196 /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; + A1063B76216F012000BDE196 /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; + A1063B77216F012000BDE196 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063B78216F012000BDE196 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; + A1063B79216F012000BDE196 /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECB20563B53000955AE /* eas_xmf.c */; }; + A1063B7A216F012000BDE196 /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; + A1063B7B216F012000BDE196 /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED620563B54000955AE /* eas_wavefile.c */; }; + A1063B7C216F012000BDE196 /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; + A1063B7D216F012000BDE196 /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE520563B56000955AE /* eas_smfdata.c */; }; + A1063B7E216F012000BDE196 /* SoundEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0820562FAF000955AE /* SoundEngine.cpp */; }; + A1063B7F216F012000BDE196 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063B80216F012000BDE196 /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; + A1063B81216F012000BDE196 /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DC205737F40075CBAD /* View.mm */; }; + A1063B82216F012000BDE196 /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0B20563B5E000955AE /* eas_voicemgt.c */; }; + A1063B83216F012000BDE196 /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; + A1063B84216F012000BDE196 /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D6205737F40075CBAD /* Label.mm */; }; + A1063B85216F012000BDE196 /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEF20563B59000955AE /* eas_dlssynth.c */; }; + A1063B86216F012000BDE196 /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; + A1063B87216F012000BDE196 /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; + A1063B88216F012000BDE196 /* MainMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD820562B75000955AE /* MainMenuViewController.mm */; }; + A1063B89216F012000BDE196 /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; + A1063B8A216F012000BDE196 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; + A1063B8B216F012000BDE196 /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; + A1063B8C216F012000BDE196 /* eas_hostmm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E42205634E7000955AE /* eas_hostmm.c */; }; + A1063B8D216F012000BDE196 /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; + A1063B8E216F012000BDE196 /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFD20563B5C000955AE /* eas_mididata.c */; }; + A1063B8F216F012000BDE196 /* Doom_App.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E1D20562FD1000955AE /* Doom_App.m */; }; + A1063B90216F012000BDE196 /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDA20563B54000955AE /* eas_pcmdata.c */; }; + A1063B91216F012000BDE196 /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; + A1063B92216F012000BDE196 /* eas_chorusdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDC20563B55000955AE /* eas_chorusdata.c */; }; + A1063B93216F012000BDE196 /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE120563B55000955AE /* eas_chorus.c */; }; + A1063B94216F012000BDE196 /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; + A1063B95216F012000BDE196 /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; + A1063B96216F012000BDE196 /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D7205737F40075CBAD /* LabelButton.mm */; }; + A1063B97216F012000BDE196 /* SDL_Mixer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E27205632E2000955AE /* SDL_Mixer.m */; }; + A1063B98216F012000BDE196 /* EASGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E5120563A06000955AE /* EASGlue.c */; }; + A1063B99216F012000BDE196 /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302E1205737F50075CBAD /* Switch.mm */; }; + A1063B9A216F012000BDE196 /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0620563B5D000955AE /* eas_ima_tables.c */; }; + A1063B9B216F012000BDE196 /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; + A1063B9C216F012000BDE196 /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED820563B54000955AE /* eas_ota.c */; }; + A1063B9D216F012000BDE196 /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; + A1063B9E216F012000BDE196 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; + A1063B9F216F012000BDE196 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; + A1063BA0216F012000BDE196 /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; + A1063BA1216F012000BDE196 /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EED20563B59000955AE /* eas_smf.c */; }; + A1063BA2216F012000BDE196 /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; + A1063BA3216F012000BDE196 /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; + A1063BA4216F012000BDE196 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; + A1063BA5216F012000BDE196 /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; + A1063BA6216F012000BDE196 /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; + A1063BA7216F012000BDE196 /* iphone_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0320562FAF000955AE /* iphone_delegate.mm */; }; + A1063BA8216F012000BDE196 /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0C20563B5F000955AE /* eas_imelody.c */; }; + A1063BA9216F012000BDE196 /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; + A1063BAA216F012000BDE196 /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF720563B5B000955AE /* eas_tonecontrol.c */; }; + A1063BAB216F012000BDE196 /* LegalMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DC720562B73000955AE /* LegalMenuViewController.mm */; }; + A1063BAC216F012000BDE196 /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; + A1063BAD216F012000BDE196 /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; + A1063BAE216F012000BDE196 /* iphone_async.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0020562FAE000955AE /* iphone_async.cpp */; }; + A1063BAF216F012000BDE196 /* eas_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4C205634E7000955AE /* eas_wave.c */; }; + A1063BB0216F012000BDE196 /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED020563B54000955AE /* eas_imaadpcm.c */; }; + A1063BB1216F012000BDE196 /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; + A1063BB2216F012000BDE196 /* MainNavController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDC20562B75000955AE /* MainNavController.m */; }; + A1063BB3216F012000BDE196 /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; + A1063BB4216F012000BDE196 /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; + A1063BB5216F012000BDE196 /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; + A1063BB6216F012000BDE196 /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; + A1063BB7216F012000BDE196 /* eas_reverbdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0420563B5D000955AE /* eas_reverbdata.c */; }; + A1063BB8216F012000BDE196 /* eas_report.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E40205634E7000955AE /* eas_report.c */; }; + A1063BB9216F012000BDE196 /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; + A1063BBA216F012000BDE196 /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFA20563B5B000955AE /* eas_wtengine.c */; }; + A1063BBB216F012000BDE196 /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0520563B5D000955AE /* eas_public.c */; }; + A1063BBC216F012000BDE196 /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF920563B5B000955AE /* eas_wavefiledata.c */; }; + A1063BBD216F012000BDE196 /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; + A1063BBE216F012000BDE196 /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; + A1063BBF216F012000BDE196 /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED720563B54000955AE /* eas_mixer.c */; }; + A1063BC0216F012000BDE196 /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; + A1063BC1216F012000BDE196 /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFF20563B5C000955AE /* eas_rtttldata.c */; }; + A1063BC2216F012000BDE196 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; + A1063BC3216F012000BDE196 /* wt_22khz.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE420563B56000955AE /* wt_22khz.c */; }; + A1063BC4216F012000BDE196 /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1063BC5216F012000BDE196 /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; + A1063BC6216F012000BDE196 /* ControlsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */; }; + A1063BC7216F012000BDE196 /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; + A1063BC8216F012000BDE196 /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; + A1063BC9216F012000BDE196 /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; + A1063BCA216F012000BDE196 /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0E20563B5F000955AE /* eas_reverb.c */; }; + A1063BCB216F012000BDE196 /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE820563B58000955AE /* eas_wtsynth.c */; }; + A1063BCC216F012000BDE196 /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; + A1063BCD216F012000BDE196 /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1220563B60000955AE /* eas_mdls.c */; }; + A1063BCE216F012000BDE196 /* SettingsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */; }; + A1063BCF216F012000BDE196 /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; + A1063BD0216F012000BDE196 /* i_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2320563253000955AE /* i_sound.c */; }; + A1063BD1216F012000BDE196 /* CreditsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */; }; + A1063BD2216F012000BDE196 /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; + A1063BD3216F012000BDE196 /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; + A1063BD4216F012000BDE196 /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; + A1063BD5216F012000BDE196 /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; + A1063BD6216F012000BDE196 /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; + A1063BD7216F012000BDE196 /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; + A1063BD8216F012000BDE196 /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; + A1063BD9216F012000BDE196 /* iphone_sound.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0920562FAF000955AE /* iphone_sound.mm */; }; + A1063BDA216F012000BDE196 /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; + A1063BDB216F012000BDE196 /* EpisodeMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDB20562B75000955AE /* EpisodeMenuViewController.mm */; }; + A1063BDC216F012000BDE196 /* iphone_glViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */; }; + A1063BDD216F012000BDE196 /* mmus2mid.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2B20563344000955AE /* mmus2mid.c */; }; + A1063BDE216F012000BDE196 /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; + A1063BDF216F012000BDE196 /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; + A1063BE0216F012000BDE196 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; + A1063BE1216F012000BDE196 /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DE205737F40075CBAD /* Localization.mm */; }; + A1063BE2216F012000BDE196 /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE320563B56000955AE /* eas_midi.c */; }; + A1063BE3216F012000BDE196 /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; + A1063BE4216F012000BDE196 /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; + A1063BE5216F012000BDE196 /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; + A1063BE6216F012000BDE196 /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF020563B5A000955AE /* eas_pcm.c */; }; + A1063BE7216F012000BDE196 /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; + A1063BE8216F012000BDE196 /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; + A1063BE9216F012000BDE196 /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; + A1063BEA216F012000BDE196 /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F3205738560075CBAD /* Carousel.mm */; }; + A1063BEB216F012000BDE196 /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; + A1063BEC216F012000BDE196 /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0D20563B5F000955AE /* eas_pan.c */; }; + A1063BED216F012000BDE196 /* iphone_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0520562FAF000955AE /* iphone_start.cpp */; }; + A1063BEE216F012000BDE196 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; + A1063BF0216F012000BDE196 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1EA3B84207F1D310038650E /* AVFoundation.framework */; }; + A1063BF1216F012000BDE196 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E01207EFF8A00827A46 /* QuartzCore.framework */; }; + A1063BF2216F012000BDE196 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E02207EFF8A00827A46 /* AudioToolbox.framework */; }; + A1063BF3216F012000BDE196 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E03207EFF8A00827A46 /* OpenGLES.framework */; }; + A1063BF4216F012000BDE196 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E05207EFF8A00827A46 /* UIKit.framework */; }; + A1063BF5216F012000BDE196 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E06207EFF8A00827A46 /* Foundation.framework */; }; + A1063BF6216F012000BDE196 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E07207EFF8A00827A46 /* CoreGraphics.framework */; }; + A1063BF7216F012000BDE196 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E08207EFF8B00827A46 /* GameController.framework */; }; + A1063BF8216F012000BDE196 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E09207EFF8B00827A46 /* OpenAL.framework */; }; + A1063C09216F096900BDE196 /* doom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F9205783E70075CBAD /* doom.wad */; }; + A1063C0A216F096A00BDE196 /* doom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F9205783E70075CBAD /* doom.wad */; }; + A1063C0B216F0B1D00BDE196 /* plutonia.wad in Resources */ = {isa = PBXBuildFile; fileRef = A1063AF1216EFD9800BDE196 /* plutonia.wad */; }; + A1063C0C216F0B2100BDE196 /* tnt.wad in Resources */ = {isa = PBXBuildFile; fileRef = A1063AF0216EFD9800BDE196 /* tnt.wad */; }; + A11290502069B62B00BEDEB5 /* DOOMLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A112904F2069B62B00BEDEB5 /* DOOMLaunchScreen.storyboard */; }; + A12302E3205737F50075CBAD /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D6205737F40075CBAD /* Label.mm */; }; + A12302E4205737F50075CBAD /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D7205737F40075CBAD /* LabelButton.mm */; }; + A12302E7205737F50075CBAD /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DA205737F40075CBAD /* RenderContext.mm */; }; + A12302E9205737F50075CBAD /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DC205737F40075CBAD /* View.mm */; }; + A12302EB205737F50075CBAD /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DE205737F40075CBAD /* Localization.mm */; }; + A12302EE205737F50075CBAD /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302E1205737F50075CBAD /* Switch.mm */; }; + A12302F2205738270075CBAD /* Slider.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F0205738270075CBAD /* Slider.mm */; }; + A12302F5205738560075CBAD /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F3205738560075CBAD /* Carousel.mm */; }; + A12302FB205783E70075CBAD /* prboom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F8205783E70075CBAD /* prboom.wad */; }; + A12302FD205783E70075CBAD /* base.iPack in Resources */ = {isa = PBXBuildFile; fileRef = A12302FA205783E70075CBAD /* base.iPack */; }; + A176AC09206492DD00A96B7E /* EpisodeCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A176AC08206492DD00A96B7E /* EpisodeCell~ipad.xib */; }; + A1870808216EB633006C013F /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; + A1870809216EB633006C013F /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; + A187080A216EB633006C013F /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; + A187080B216EB633006C013F /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; + A187080C216EB633006C013F /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; + A187080D216EB633006C013F /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; + A187080E216EB633006C013F /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; + A187080F216EB633006C013F /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; + A1870810216EB633006C013F /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; + A1870811216EB633006C013F /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; + A1870812216EB633006C013F /* CreditsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1E89C8D2067469D00760204 /* CreditsMenuView.xib */; }; + A1870813216EB633006C013F /* CreditsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBA20562B2B000955AE /* CreditsMenuView~ipad.xib */; }; + A1870814216EB633006C013F /* SecretMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBC20562B2B000955AE /* SecretMenuView.xib */; }; + A1870815216EB633006C013F /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; + A1870816216EB633006C013F /* EpisodeCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A184252063E63200302393 /* EpisodeCell.xib */; }; + A1870817216EB633006C013F /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; + A1870818216EB633006C013F /* ControlsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBB20562B2B000955AE /* ControlsMenuView~ipad.xib */; }; + A1870819216EB633006C013F /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; + A187081A216EB633006C013F /* SettingsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DC920562B73000955AE /* SettingsMenuView~ipad.xib */; }; + A187081B216EB633006C013F /* MainMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCE20562B73000955AE /* MainMenuView.xib */; }; + A187081C216EB633006C013F /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; + A187081D216EB633006C013F /* MainMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD920562B75000955AE /* MainMenuView~ipad.xib */; }; + A187081E216EB633006C013F /* DOOM_144.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1620562FC3000955AE /* DOOM_144.png */; }; + A187081F216EB633006C013F /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; + A1870820216EB633006C013F /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; + A1870821216EB633006C013F /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; + A1870822216EB633006C013F /* r_drawcolpipeline.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */; }; + A1870823216EB633006C013F /* ControlsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DB620562B2B000955AE /* ControlsMenuView.xib */; }; + A1870824216EB633006C013F /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; + A1870825216EB633006C013F /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; + A1870826216EB633006C013F /* EpisodeMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCA20562B73000955AE /* EpisodeMenuView.xib */; }; + A1870827216EB633006C013F /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2E20563345000955AE /* Makefile.am */; }; + A1870828216EB633006C013F /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; + A1870829216EB633006C013F /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; + A187082A216EB633006C013F /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; + A187082B216EB633006C013F /* SettingsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD620562B74000955AE /* SettingsMenuView.xib */; }; + A187082C216EB633006C013F /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; + A187082D216EB633006C013F /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; + A187082E216EB633006C013F /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; + A187082F216EB633006C013F /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; + A1870830216EB633006C013F /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; + A1870831216EB633006C013F /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; + A1870832216EB633006C013F /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; + A1870833216EB633006C013F /* EpisodeMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DDA20562B75000955AE /* EpisodeMenuView~ipad.xib */; }; + A1870834216EB633006C013F /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; + A1870835216EB633006C013F /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; + A1870836216EB633006C013F /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; + A1870837216EB633006C013F /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; + A1870838216EB633006C013F /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; + A1870839216EB633006C013F /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; + A187083A216EB633006C013F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E0720562FAF000955AE /* Localizable.strings */; }; + A187083B216EB633006C013F /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; + A187083C216EB633006C013F /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; + A187083D216EB633006C013F /* DOOMLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A112904F2069B62B00BEDEB5 /* DOOMLaunchScreen.storyboard */; }; + A187083E216EB633006C013F /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; + A187083F216EB633006C013F /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; + A1870840216EB633006C013F /* r_drawspan.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3120563345000955AE /* r_drawspan.inl */; }; + A1870841216EB633006C013F /* DOOM_400.png in Resources */ = {isa = PBXBuildFile; fileRef = A1EA3B86207F9DE20038650E /* DOOM_400.png */; }; + A1870842216EB633006C013F /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; + A1870843216EB633006C013F /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; + A1870844216EB633006C013F /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; + A1870845216EB633006C013F /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; + A1870846216EB633006C013F /* MissionMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DC620562B73000955AE /* MissionMenuView~ipad.xib */; }; + A1870847216EB633006C013F /* OpenGLView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DE220562B76000955AE /* OpenGLView~ipad.xib */; }; + A1870848216EB633006C013F /* EpisodeCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A176AC08206492DD00A96B7E /* EpisodeCell~ipad.xib */; }; + A1870849216EB633006C013F /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; + A187084A216EB633006C013F /* LegalMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCB20562B73000955AE /* LegalMenuView~ipad.xib */; }; + A187084B216EB633006C013F /* DOOM_76.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1820562FC4000955AE /* DOOM_76.png */; }; + A187084C216EB633006C013F /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; + A187084D216EB633006C013F /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; + A187084E216EB633006C013F /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; + A187084F216EB633006C013F /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; + A1870850216EB633006C013F /* DOOM_120.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1720562FC3000955AE /* DOOM_120.png */; }; + A1870851216EB633006C013F /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; + A1870852216EB633006C013F /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; + A1870853216EB633006C013F /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; + A1870854216EB633006C013F /* r_drawflush.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3020563345000955AE /* r_drawflush.inl */; }; + A1870855216EB633006C013F /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; + A1870856216EB633006C013F /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; + A1870857216EB633006C013F /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; + A1870858216EB633006C013F /* DOOM_152.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1520562FC3000955AE /* DOOM_152.png */; }; + A1870859216EB633006C013F /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; + A187085A216EB633006C013F /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; + A187085B216EB633006C013F /* prboom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F8205783E70075CBAD /* prboom.wad */; }; + A187085D216EB633006C013F /* base.iPack in Resources */ = {isa = PBXBuildFile; fileRef = A12302FA205783E70075CBAD /* base.iPack */; }; + A187085E216EB633006C013F /* OpenGLView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD220562B74000955AE /* OpenGLView.xib */; }; + A187085F216EB633006C013F /* r_drawcolumn.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2D20563344000955AE /* r_drawcolumn.inl */; }; + A1870860216EB633006C013F /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; + A1870861216EB633006C013F /* MissionMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCC20562B73000955AE /* MissionMenuView.xib */; }; + A1870862216EB633006C013F /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; + A1870863216EB633006C013F /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; + A1870864216EB633006C013F /* LegalMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DE020562B76000955AE /* LegalMenuView.xib */; }; + A1870866216EB633006C013F /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; + A1870867216EB633006C013F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + A1870868216EB633006C013F /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; + A1870869216EB633006C013F /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; + A187086A216EB633006C013F /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1220563B60000955AE /* eas_mdls.c */; }; + A187086B216EB633006C013F /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; + A187086C216EB633006C013F /* Doom_App.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E1D20562FD1000955AE /* Doom_App.m */; }; + A187086D216EB633006C013F /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; + A187086E216EB633006C013F /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; + A187086F216EB633006C013F /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DE205737F40075CBAD /* Localization.mm */; }; + A1870870216EB633006C013F /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; + A1870871216EB633006C013F /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DC205737F40075CBAD /* View.mm */; }; + A1870872216EB633006C013F /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0F20563B5F000955AE /* eas_tcdata.c */; }; + A1870873216EB633006C013F /* iphone_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0320562FAF000955AE /* iphone_delegate.mm */; }; + A1870874216EB633006C013F /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; + A1870875216EB633006C013F /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; + A1870876216EB633006C013F /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; + A1870877216EB633006C013F /* iphone_async.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0020562FAE000955AE /* iphone_async.cpp */; }; + A1870878216EB633006C013F /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; + A1870879216EB633006C013F /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; + A187087A216EB633006C013F /* eas_report.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E40205634E7000955AE /* eas_report.c */; }; + A187087B216EB633006C013F /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECA20563B53000955AE /* eas_xmfdata.c */; }; + A187087C216EB633006C013F /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; + A187087D216EB633006C013F /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; + A187087E216EB633006C013F /* iphone_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0520562FAF000955AE /* iphone_start.cpp */; }; + A187087F216EB633006C013F /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; + A1870880216EB633006C013F /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; + A1870881216EB633006C013F /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DA205737F40075CBAD /* RenderContext.mm */; }; + A1870882216EB633006C013F /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED820563B54000955AE /* eas_ota.c */; }; + A1870883216EB633006C013F /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; + A1870884216EB633006C013F /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; + A1870885216EB633006C013F /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFC20563B5C000955AE /* eas_imelodydata.c */; }; + A1870886216EB633006C013F /* MissionMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD020562B74000955AE /* MissionMenuViewController.mm */; }; + A1870887216EB633006C013F /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1870888216EB633006C013F /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; + A1870889216EB633006C013F /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; + A187088A216EB633006C013F /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; + A187088B216EB633006C013F /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; + A187088C216EB633006C013F /* iphone_common.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0620562FAF000955AE /* iphone_common.mm */; }; + A187088D216EB633006C013F /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; + A187088E216EB633006C013F /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; + A187088F216EB633006C013F /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; + A1870890216EB633006C013F /* eas_hostmm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E42205634E7000955AE /* eas_hostmm.c */; }; + A1870891216EB633006C013F /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; + A1870892216EB633006C013F /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; + A1870893216EB633006C013F /* MainMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD820562B75000955AE /* MainMenuViewController.mm */; }; + A1870894216EB633006C013F /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; + A1870895216EB633006C013F /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECB20563B53000955AE /* eas_xmf.c */; }; + A1870896216EB633006C013F /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECE20563B53000955AE /* eas_otadata.c */; }; + A1870898216EB633006C013F /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; + A1870899216EB633006C013F /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; + A187089A216EB633006C013F /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE820563B58000955AE /* eas_wtsynth.c */; }; + A187089B216EB633006C013F /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; + A187089C216EB633006C013F /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; + A187089D216EB633006C013F /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; + A187089E216EB633006C013F /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A187089F216EB633006C013F /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0D20563B5F000955AE /* eas_pan.c */; }; + A18708A0216EB633006C013F /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; + A18708A1216EB633006C013F /* mmus2mid.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2B20563344000955AE /* mmus2mid.c */; }; + A18708A2216EB633006C013F /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; + A18708A3216EB633006C013F /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F3205738560075CBAD /* Carousel.mm */; }; + A18708A4216EB633006C013F /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFF20563B5C000955AE /* eas_rtttldata.c */; }; + A18708A5216EB633006C013F /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED020563B54000955AE /* eas_imaadpcm.c */; }; + A18708A6216EB633006C013F /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; + A18708A7216EB633006C013F /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; + A18708A8216EB633006C013F /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; + A18708A9216EB633006C013F /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; + A18708AA216EB633006C013F /* GameController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C9520689D9500760204 /* GameController.mm */; }; + A18708AB216EB633006C013F /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; + A18708AC216EB633006C013F /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; + A18708AD216EB633006C013F /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; + A18708AE216EB633006C013F /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A18708AF216EB633006C013F /* eas_reverbdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0420563B5D000955AE /* eas_reverbdata.c */; }; + A18708B0216EB633006C013F /* SDL_Mixer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E27205632E2000955AE /* SDL_Mixer.m */; }; + A18708B1216EB633006C013F /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EED20563B59000955AE /* eas_smf.c */; }; + A18708B2216EB633006C013F /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; + A18708B3216EB633006C013F /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFD20563B5C000955AE /* eas_mididata.c */; }; + A18708B4216EB633006C013F /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; + A18708B5216EB633006C013F /* eas_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4C205634E7000955AE /* eas_wave.c */; }; + A18708B6216EB633006C013F /* EASGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E5120563A06000955AE /* EASGlue.c */; }; + A18708B7216EB633006C013F /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE320563B56000955AE /* eas_midi.c */; }; + A18708B8216EB633006C013F /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; + A18708B9216EB633006C013F /* wt_22khz.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE420563B56000955AE /* wt_22khz.c */; }; + A18708BA216EB633006C013F /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; + A18708BB216EB633006C013F /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED620563B54000955AE /* eas_wavefile.c */; }; + A18708BC216EB633006C013F /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE120563B55000955AE /* eas_chorus.c */; }; + A18708BD216EB633006C013F /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; + A18708BE216EB633006C013F /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; + A18708BF216EB633006C013F /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF020563B5A000955AE /* eas_pcm.c */; }; + A18708C0216EB633006C013F /* iphone_glViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */; }; + A18708C1216EB633006C013F /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; + A18708C2216EB633006C013F /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; + A18708C3216EB633006C013F /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; + A18708C4216EB633006C013F /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; + A18708C5216EB633006C013F /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; + A18708C6216EB633006C013F /* CreditsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */; }; + A18708C7216EB633006C013F /* iphone_sound.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0920562FAF000955AE /* iphone_sound.mm */; }; + A18708C8216EB633006C013F /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; + A18708C9216EB633006C013F /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; + A18708CA216EB633006C013F /* SoundEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0820562FAF000955AE /* SoundEngine.cpp */; }; + A18708CB216EB633006C013F /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEF20563B59000955AE /* eas_dlssynth.c */; }; + A18708CC216EB633006C013F /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; + A18708CD216EB633006C013F /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; + A18708CE216EB633006C013F /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; + A18708CF216EB633006C013F /* iphone_sys.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0A20562FAF000955AE /* iphone_sys.mm */; }; + A18708D0216EB633006C013F /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; + A18708D1216EB633006C013F /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; + A18708D2216EB633006C013F /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; + A18708D3216EB633006C013F /* i_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2320563253000955AE /* i_sound.c */; }; + A18708D4216EB633006C013F /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFA20563B5B000955AE /* eas_wtengine.c */; }; + A18708D5216EB633006C013F /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0B20563B5E000955AE /* eas_voicemgt.c */; }; + A18708D6216EB633006C013F /* LegalMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DC720562B73000955AE /* LegalMenuViewController.mm */; }; + A18708D7216EB633006C013F /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF920563B5B000955AE /* eas_wavefiledata.c */; }; + A18708D8216EB633006C013F /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0C20563B5F000955AE /* eas_imelody.c */; }; + A18708D9216EB633006C013F /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; + A18708DA216EB633006C013F /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; + A18708DB216EB633006C013F /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECF20563B53000955AE /* eas_data.c */; }; + A18708DC216EB633006C013F /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; + A18708DD216EB633006C013F /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED720563B54000955AE /* eas_mixer.c */; }; + A18708DE216EB633006C013F /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; + A18708DF216EB633006C013F /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A18708E0216EB633006C013F /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; + A18708E1216EB633006C013F /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; + A18708E2216EB633006C013F /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0220563B5C000955AE /* eas_flog.c */; }; + A18708E3216EB633006C013F /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4B205634E7000955AE /* eas_config.c */; }; + A18708E4216EB633006C013F /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; + A18708E5216EB633006C013F /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0E20563B5F000955AE /* eas_reverb.c */; }; + A18708E6216EB633006C013F /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; + A18708E7216EB633006C013F /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; + A18708E8216EB633006C013F /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; + A18708E9216EB633006C013F /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE520563B56000955AE /* eas_smfdata.c */; }; + A18708EA216EB633006C013F /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEC20563B59000955AE /* eas_mixbuf.c */; }; + A18708EB216EB633006C013F /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; + A18708EC216EB633006C013F /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0520563B5D000955AE /* eas_public.c */; }; + A18708ED216EB633006C013F /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; + A18708EE216EB633006C013F /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; + A18708EF216EB633006C013F /* SettingsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */; }; + A18708F0216EB633006C013F /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; + A18708F1216EB633006C013F /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; + A18708F2216EB633006C013F /* Slider.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F0205738270075CBAD /* Slider.mm */; }; + A18708F3216EB633006C013F /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; + A18708F4216EB633006C013F /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D7205737F40075CBAD /* LabelButton.mm */; }; + A18708F5216EB633006C013F /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302E1205737F50075CBAD /* Switch.mm */; }; + A18708F6216EB633006C013F /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED120563B54000955AE /* eas_rtttl.c */; }; + A18708F7216EB633006C013F /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; + A18708F8216EB633006C013F /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; + A18708F9216EB633006C013F /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDA20563B54000955AE /* eas_pcmdata.c */; }; + A18708FA216EB633006C013F /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; + A18708FB216EB633006C013F /* SecretMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB720562B2B000955AE /* SecretMenuViewController.mm */; }; + A18708FC216EB633006C013F /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF720563B5B000955AE /* eas_tonecontrol.c */; }; + A18708FD216EB633006C013F /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; + A18708FE216EB633006C013F /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D6205737F40075CBAD /* Label.mm */; }; + A18708FF216EB633006C013F /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; + A1870900216EB633006C013F /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; + A1870901216EB633006C013F /* eas_chorusdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDC20563B55000955AE /* eas_chorusdata.c */; }; + A1870902216EB633006C013F /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1020563B5F000955AE /* eas_math.c */; }; + A1870903216EB633006C013F /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; + A1870904216EB633006C013F /* MainNavController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDC20562B75000955AE /* MainNavController.m */; }; + A1870905216EB633006C013F /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0620563B5D000955AE /* eas_ima_tables.c */; }; + A1870906216EB633006C013F /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; + A1870907216EB633006C013F /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; + A1870908216EB633006C013F /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; + A1870909216EB633006C013F /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; + A187090A216EB633006C013F /* ControlsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */; }; + A187090B216EB633006C013F /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; + A187090C216EB633006C013F /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; + A187090E216EB633006C013F /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E89C9320689D4B00760204 /* GameController.framework */; }; + A187090F216EB633006C013F /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A63E5420563A6D000955AE /* AVFoundation.framework */; }; + A1870910216EB633006C013F /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */; }; + A1870911216EB633006C013F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */; }; + A1870912216EB633006C013F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */; }; + A1870913216EB633006C013F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */; }; + A1870914216EB633006C013F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760611C2B19E004A9B9B /* Foundation.framework */; }; + A1870915216EB633006C013F /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760811C2B19E004A9B9B /* OpenGLES.framework */; }; + A1870916216EB633006C013F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760A11C2B19E004A9B9B /* UIKit.framework */; }; + A1A184282063E63200302393 /* EpisodeCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A184252063E63200302393 /* EpisodeCell.xib */; }; + A1A63DBD20562B2B000955AE /* ControlsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */; }; + A1A63DBF20562B2B000955AE /* ControlsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DB620562B2B000955AE /* ControlsMenuView.xib */; }; + A1A63DC020562B2B000955AE /* SecretMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB720562B2B000955AE /* SecretMenuViewController.mm */; }; + A1A63DC220562B2B000955AE /* CreditsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBA20562B2B000955AE /* CreditsMenuView~ipad.xib */; }; + A1A63DC320562B2B000955AE /* ControlsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBB20562B2B000955AE /* ControlsMenuView~ipad.xib */; }; + A1A63DC420562B2B000955AE /* SecretMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBC20562B2B000955AE /* SecretMenuView.xib */; }; + A1A63DE320562B76000955AE /* MissionMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DC620562B73000955AE /* MissionMenuView~ipad.xib */; }; + A1A63DE420562B76000955AE /* LegalMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DC720562B73000955AE /* LegalMenuViewController.mm */; }; + A1A63DE620562B76000955AE /* SettingsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DC920562B73000955AE /* SettingsMenuView~ipad.xib */; }; + A1A63DE720562B76000955AE /* EpisodeMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCA20562B73000955AE /* EpisodeMenuView.xib */; }; + A1A63DE820562B76000955AE /* LegalMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCB20562B73000955AE /* LegalMenuView~ipad.xib */; }; + A1A63DE920562B76000955AE /* MissionMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCC20562B73000955AE /* MissionMenuView.xib */; }; + A1A63DEB20562B76000955AE /* MainMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCE20562B73000955AE /* MainMenuView.xib */; }; + A1A63DED20562B76000955AE /* MissionMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD020562B74000955AE /* MissionMenuViewController.mm */; }; + A1A63DEF20562B76000955AE /* OpenGLView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD220562B74000955AE /* OpenGLView.xib */; }; + A1A63DF220562B76000955AE /* SettingsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD620562B74000955AE /* SettingsMenuView.xib */; }; + A1A63DF320562B76000955AE /* MainMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD820562B75000955AE /* MainMenuViewController.mm */; }; + A1A63DF420562B76000955AE /* MainMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD920562B75000955AE /* MainMenuView~ipad.xib */; }; + A1A63DF520562B76000955AE /* EpisodeMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DDA20562B75000955AE /* EpisodeMenuView~ipad.xib */; }; + A1A63DF620562B76000955AE /* EpisodeMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDB20562B75000955AE /* EpisodeMenuViewController.mm */; }; + A1A63DF720562B76000955AE /* MainNavController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDC20562B75000955AE /* MainNavController.m */; }; + A1A63DF820562B76000955AE /* LegalMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DE020562B76000955AE /* LegalMenuView.xib */; }; + A1A63DF920562B76000955AE /* SettingsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */; }; + A1A63DFA20562B76000955AE /* OpenGLView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DE220562B76000955AE /* OpenGLView~ipad.xib */; }; + A1A63E0C20562FB0000955AE /* iphone_glViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */; }; + A1A63E0D20562FB0000955AE /* iphone_async.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0020562FAE000955AE /* iphone_async.cpp */; }; + A1A63E0E20562FB0000955AE /* iphone_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0320562FAF000955AE /* iphone_delegate.mm */; }; + A1A63E0F20562FB0000955AE /* iphone_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0520562FAF000955AE /* iphone_start.cpp */; }; + A1A63E1020562FB0000955AE /* iphone_common.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0620562FAF000955AE /* iphone_common.mm */; }; + A1A63E1120562FB0000955AE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E0720562FAF000955AE /* Localizable.strings */; }; + A1A63E1220562FB0000955AE /* SoundEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0820562FAF000955AE /* SoundEngine.cpp */; }; + A1A63E1320562FB0000955AE /* iphone_sound.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0920562FAF000955AE /* iphone_sound.mm */; }; + A1A63E1420562FB0000955AE /* iphone_sys.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0A20562FAF000955AE /* iphone_sys.mm */; }; + A1A63E1920562FC4000955AE /* DOOM_152.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1520562FC3000955AE /* DOOM_152.png */; }; + A1A63E1A20562FC4000955AE /* DOOM_144.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1620562FC3000955AE /* DOOM_144.png */; }; + A1A63E1B20562FC4000955AE /* DOOM_120.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1720562FC3000955AE /* DOOM_120.png */; }; + A1A63E1C20562FC4000955AE /* DOOM_76.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1820562FC4000955AE /* DOOM_76.png */; }; + A1A63E1F20562FD1000955AE /* Doom_App.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E1D20562FD1000955AE /* Doom_App.m */; }; + A1A63E2420563253000955AE /* i_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2320563253000955AE /* i_sound.c */; }; + A1A63E29205632E2000955AE /* SDL_Mixer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E27205632E2000955AE /* SDL_Mixer.m */; }; + A1A63E3320563345000955AE /* r_drawcolpipeline.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */; }; + A1A63E3420563345000955AE /* mmus2mid.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2B20563344000955AE /* mmus2mid.c */; }; + A1A63E3520563345000955AE /* r_drawcolumn.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2D20563344000955AE /* r_drawcolumn.inl */; }; + A1A63E3620563345000955AE /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2E20563345000955AE /* Makefile.am */; }; + A1A63E3820563345000955AE /* r_drawflush.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3020563345000955AE /* r_drawflush.inl */; }; + A1A63E3920563345000955AE /* r_drawspan.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3120563345000955AE /* r_drawspan.inl */; }; + A1A63E4D205634E8000955AE /* eas_report.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E40205634E7000955AE /* eas_report.c */; }; + A1A63E4E205634E8000955AE /* eas_hostmm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E42205634E7000955AE /* eas_hostmm.c */; }; + A1A63E4F205634E8000955AE /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4B205634E7000955AE /* eas_config.c */; }; + A1A63E50205634E8000955AE /* eas_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4C205634E7000955AE /* eas_wave.c */; }; + A1A63E5320563A06000955AE /* EASGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E5120563A06000955AE /* EASGlue.c */; }; + A1A63E5520563A6D000955AE /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A63E5420563A6D000955AE /* AVFoundation.framework */; }; + A1A63F1320563B60000955AE /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECA20563B53000955AE /* eas_xmfdata.c */; }; + A1A63F1420563B60000955AE /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECB20563B53000955AE /* eas_xmf.c */; }; + A1A63F1520563B60000955AE /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECE20563B53000955AE /* eas_otadata.c */; }; + A1A63F1620563B60000955AE /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECF20563B53000955AE /* eas_data.c */; }; + A1A63F1720563B60000955AE /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED020563B54000955AE /* eas_imaadpcm.c */; }; + A1A63F1820563B60000955AE /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED120563B54000955AE /* eas_rtttl.c */; }; + A1A63F1920563B60000955AE /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED620563B54000955AE /* eas_wavefile.c */; }; + A1A63F1A20563B60000955AE /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED720563B54000955AE /* eas_mixer.c */; }; + A1A63F1B20563B60000955AE /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED820563B54000955AE /* eas_ota.c */; }; + A1A63F1C20563B60000955AE /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDA20563B54000955AE /* eas_pcmdata.c */; }; + A1A63F1D20563B60000955AE /* eas_chorusdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDC20563B55000955AE /* eas_chorusdata.c */; }; + A1A63F1E20563B60000955AE /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE120563B55000955AE /* eas_chorus.c */; }; + A1A63F1F20563B60000955AE /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE320563B56000955AE /* eas_midi.c */; }; + A1A63F2020563B60000955AE /* wt_22khz.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE420563B56000955AE /* wt_22khz.c */; }; + A1A63F2120563B60000955AE /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE520563B56000955AE /* eas_smfdata.c */; }; + A1A63F2220563B60000955AE /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE820563B58000955AE /* eas_wtsynth.c */; }; + A1A63F2420563B60000955AE /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEC20563B59000955AE /* eas_mixbuf.c */; }; + A1A63F2520563B60000955AE /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EED20563B59000955AE /* eas_smf.c */; }; + A1A63F2620563B60000955AE /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEF20563B59000955AE /* eas_dlssynth.c */; }; + A1A63F2720563B60000955AE /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF020563B5A000955AE /* eas_pcm.c */; }; + A1A63F2820563B60000955AE /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF720563B5B000955AE /* eas_tonecontrol.c */; }; + A1A63F2920563B60000955AE /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF920563B5B000955AE /* eas_wavefiledata.c */; }; + A1A63F2A20563B60000955AE /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFA20563B5B000955AE /* eas_wtengine.c */; }; + A1A63F2B20563B60000955AE /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFC20563B5C000955AE /* eas_imelodydata.c */; }; + A1A63F2C20563B60000955AE /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFD20563B5C000955AE /* eas_mididata.c */; }; + A1A63F2D20563B60000955AE /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFF20563B5C000955AE /* eas_rtttldata.c */; }; + A1A63F2E20563B60000955AE /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0220563B5C000955AE /* eas_flog.c */; }; + A1A63F2F20563B60000955AE /* eas_reverbdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0420563B5D000955AE /* eas_reverbdata.c */; }; + A1A63F3020563B60000955AE /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0520563B5D000955AE /* eas_public.c */; }; + A1A63F3120563B60000955AE /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0620563B5D000955AE /* eas_ima_tables.c */; }; + A1A63F3220563B60000955AE /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0B20563B5E000955AE /* eas_voicemgt.c */; }; + A1A63F3320563B60000955AE /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0C20563B5F000955AE /* eas_imelody.c */; }; + A1A63F3420563B60000955AE /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0D20563B5F000955AE /* eas_pan.c */; }; + A1A63F3520563B60000955AE /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0E20563B5F000955AE /* eas_reverb.c */; }; + A1A63F3620563B60000955AE /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0F20563B5F000955AE /* eas_tcdata.c */; }; + A1A63F3720563B60000955AE /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1020563B5F000955AE /* eas_math.c */; }; + A1A63F3820563B60000955AE /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1220563B60000955AE /* eas_mdls.c */; }; + A1B98E0A207EFF8B00827A46 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E01207EFF8A00827A46 /* QuartzCore.framework */; }; + A1B98E0B207EFF8B00827A46 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E02207EFF8A00827A46 /* AudioToolbox.framework */; }; + A1B98E0C207EFF8B00827A46 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E03207EFF8A00827A46 /* OpenGLES.framework */; }; + A1B98E0E207EFF8B00827A46 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E05207EFF8A00827A46 /* UIKit.framework */; }; + A1B98E0F207EFF8B00827A46 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E06207EFF8A00827A46 /* Foundation.framework */; }; + A1B98E10207EFF8B00827A46 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E07207EFF8A00827A46 /* CoreGraphics.framework */; }; + A1B98E11207EFF8B00827A46 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E08207EFF8B00827A46 /* GameController.framework */; }; + A1B98E12207EFF8B00827A46 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E09207EFF8B00827A46 /* OpenAL.framework */; }; + A1B98E1D207F016600827A46 /* MainMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E15207F016500827A46 /* MainMenuView-tvos.xib */; }; + A1B98E1E207F016600827A46 /* LegalMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E16207F016500827A46 /* LegalMenuView-tvos.xib */; }; + A1B98E1F207F016600827A46 /* ControlsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E17207F016500827A46 /* ControlsMenuView-tvos.xib */; }; + A1B98E20207F016600827A46 /* OpenGLView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E18207F016500827A46 /* OpenGLView-tvos.xib */; }; + A1B98E21207F016600827A46 /* SettingsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E19207F016500827A46 /* SettingsMenuView-tvos.xib */; }; + A1B98E22207F016600827A46 /* EpisodeMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1A207F016600827A46 /* EpisodeMenuView-tvos.xib */; }; + A1B98E23207F016600827A46 /* MissionMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1B207F016600827A46 /* MissionMenuView-tvos.xib */; }; + A1B98E24207F016600827A46 /* CreditsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1C207F016600827A46 /* CreditsMenuView-tvos.xib */; }; + A1B98E25207F021900827A46 /* DOOM_76.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1820562FC4000955AE /* DOOM_76.png */; }; + A1B98E26207F021900827A46 /* DOOM_120.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1720562FC3000955AE /* DOOM_120.png */; }; + A1B98E27207F021900827A46 /* DOOM_144.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1620562FC3000955AE /* DOOM_144.png */; }; + A1B98E28207F021900827A46 /* DOOM_152.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1520562FC3000955AE /* DOOM_152.png */; }; + A1B98E29207F021900827A46 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; + A1B98E2A207F021900827A46 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; + A1B98E2B207F021900827A46 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; + A1B98E2C207F021900827A46 /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; + A1B98E2D207F021900827A46 /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; + A1B98E2E207F021900827A46 /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; + A1B98E2F207F021900827A46 /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; + A1B98E30207F024400827A46 /* base.iPack in Resources */ = {isa = PBXBuildFile; fileRef = A12302FA205783E70075CBAD /* base.iPack */; }; + A1B98E32207F024400827A46 /* prboom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F8205783E70075CBAD /* prboom.wad */; }; + A1B98E33207F025600827A46 /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; + A1B98E34207F025600827A46 /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; + A1B98E35207F025600827A46 /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; + A1B98E36207F025600827A46 /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; + A1B98E37207F025600827A46 /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; + A1B98E38207F025600827A46 /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; + A1B98E39207F025600827A46 /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; + A1B98E3A207F025600827A46 /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; + A1B98E3B207F025600827A46 /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; + A1B98E3C207F025600827A46 /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; + A1B98E3D207F025600827A46 /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; + A1B98E3E207F025600827A46 /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; + A1B98E3F207F025600827A46 /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; + A1B98E40207F025600827A46 /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; + A1B98E41207F025600827A46 /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; + A1B98E42207F025600827A46 /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; + A1B98E43207F025600827A46 /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; + A1B98E44207F025600827A46 /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; + A1B98E45207F025600827A46 /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; + A1B98E46207F025600827A46 /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; + A1B98E47207F025600827A46 /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; + A1B98E48207F025600827A46 /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; + A1B98E49207F025600827A46 /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; + A1B98E4A207F025600827A46 /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; + A1B98E4B207F025600827A46 /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; + A1B98E4C207F025600827A46 /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; + A1B98E4D207F025600827A46 /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; + A1B98E4E207F025600827A46 /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; + A1B98E4F207F025600827A46 /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; + A1B98E50207F025600827A46 /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; + A1B98E51207F025600827A46 /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; + A1B98E52207F025600827A46 /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; + A1B98E53207F025600827A46 /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; + A1B98E54207F025600827A46 /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; + A1B98E55207F025600827A46 /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; + A1B98E56207F025600827A46 /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; + A1B98E57207F025600827A46 /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; + A1B98E58207F025600827A46 /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; + A1B98E59207F025600827A46 /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; + A1B98E5A207F025600827A46 /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; + A1B98E5B207F025600827A46 /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; + A1B98E5C207F025600827A46 /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; + A1B98E5D207F025600827A46 /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; + A1B98E5E207F025600827A46 /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; + A1B98E5F207F025600827A46 /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; + A1B98E60207F025600827A46 /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; + A1B98E61207F025600827A46 /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; + A1B98E62207F025600827A46 /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; + A1B98E63207F025600827A46 /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; + A1B98E64207F025600827A46 /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; + A1B98E65207F026900827A46 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; + A1B98E66207F031B00827A46 /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; + A1B98E67207F04B900827A46 /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F3205738560075CBAD /* Carousel.mm */; }; + A1B98E69207F04BE00827A46 /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D6205737F40075CBAD /* Label.mm */; }; + A1B98E6A207F04BE00827A46 /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D7205737F40075CBAD /* LabelButton.mm */; }; + A1B98E6B207F04C600827A46 /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DE205737F40075CBAD /* Localization.mm */; }; + A1B98E6C207F04C600827A46 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DA205737F40075CBAD /* RenderContext.mm */; }; + A1B98E6D207F04C600827A46 /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302E1205737F50075CBAD /* Switch.mm */; }; + A1B98E6E207F04C600827A46 /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DC205737F40075CBAD /* View.mm */; }; + A1B98E6F207F04D000827A46 /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; + A1B98E70207F04D800827A46 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; + A1B98E71207F04D800827A46 /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; + A1B98E72207F050200827A46 /* Doom_App.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E1D20562FD1000955AE /* Doom_App.m */; }; + A1B98E73207F050200827A46 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; + A1B98E74207F050200827A46 /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; + A1B98E75207F050200827A46 /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; + A1B98E76207F055400827A46 /* ControlsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */; }; + A1B98E77207F057600827A46 /* CreditsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */; }; + A1B98E78207F057E00827A46 /* EpisodeMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDB20562B75000955AE /* EpisodeMenuViewController.mm */; }; + A1B98E79207F058200827A46 /* LegalMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DC720562B73000955AE /* LegalMenuViewController.mm */; }; + A1B98E7A207F058600827A46 /* MainMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD820562B75000955AE /* MainMenuViewController.mm */; }; + A1B98E7B207F058E00827A46 /* MainNavController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDC20562B75000955AE /* MainNavController.m */; }; + A1B98E7C207F05A300827A46 /* MissionMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD020562B74000955AE /* MissionMenuViewController.mm */; }; + A1B98E7E207F05AC00827A46 /* SettingsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */; }; + A1B98E7F207F05B000827A46 /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; + A1B98E80207F05B500827A46 /* iphone_async.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0020562FAE000955AE /* iphone_async.cpp */; }; + A1B98E81207F05BD00827A46 /* iphone_common.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0620562FAF000955AE /* iphone_common.mm */; }; + A1B98E82207F05C100827A46 /* iphone_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0320562FAF000955AE /* iphone_delegate.mm */; }; + A1B98E83207F05C700827A46 /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; + A1B98E84207F05CB00827A46 /* iphone_glViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */; }; + A1B98E85207F05CF00827A46 /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; + A1B98E86207F05D400827A46 /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; + A1B98E87207F05D400827A46 /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; + A1B98E88207F05D400827A46 /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; + A1B98E89207F05DB00827A46 /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; + A1B98E8A207F05DB00827A46 /* iphone_sound.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0920562FAF000955AE /* iphone_sound.mm */; }; + A1B98E8B207F05DB00827A46 /* iphone_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0520562FAF000955AE /* iphone_start.cpp */; }; + A1B98E8C207F05DB00827A46 /* iphone_sys.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0A20562FAF000955AE /* iphone_sys.mm */; }; + A1B98E8D207F05E200827A46 /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; + A1B98E8E207F05F000827A46 /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; + A1B98E8F207F05F000827A46 /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; + A1B98E90207F05F000827A46 /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; + A1B98E91207F05F000827A46 /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; + A1B98E92207F05F000827A46 /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; + A1B98E93207F05F000827A46 /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; + A1B98E94207F05F000827A46 /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; + A1B98E95207F05F000827A46 /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; + A1B98E96207F05F000827A46 /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; + A1B98E97207F05F500827A46 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E0720562FAF000955AE /* Localizable.strings */; }; + A1B98E98207F05F900827A46 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + A1B98E99207F05FC00827A46 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; + A1B98E9B207F060800827A46 /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; + A1B98E9C207F060C00827A46 /* SoundEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0820562FAF000955AE /* SoundEngine.cpp */; }; + A1B98E9D207F061E00827A46 /* GameController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C9520689D9500760204 /* GameController.mm */; }; + A1B98E9E207F062A00827A46 /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; + A1B98F53207F07D400827A46 /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; + A1B98F54207F07D400827A46 /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; + A1B98F55207F07D400827A46 /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; + A1B98F56207F07D400827A46 /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; + A1B98F57207F07D400827A46 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; + A1B98F58207F07D400827A46 /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; + A1B98F59207F07D400827A46 /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; + A1B98F5A207F07D400827A46 /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; + A1B98F5B207F07D400827A46 /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; + A1B98F5C207F07D400827A46 /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; + A1B98F5D207F07D400827A46 /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; + A1B98F5E207F07D400827A46 /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1B98F5F207F07D400827A46 /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; + A1B98F60207F07D400827A46 /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; + A1B98F61207F07D400827A46 /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; + A1B98F62207F07D400827A46 /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; + A1B98F63207F07D400827A46 /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; + A1B98F64207F07D400827A46 /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; + A1B98F65207F07D400827A46 /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; + A1B98F66207F07D400827A46 /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; + A1B98F67207F07D400827A46 /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; + A1B98F68207F07D400827A46 /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; + A1B98F69207F07D400827A46 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; + A1B98F6A207F07D400827A46 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; + A1B98F6B207F07D400827A46 /* mmus2mid.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2B20563344000955AE /* mmus2mid.c */; }; + A1B98F6C207F07D400827A46 /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; + A1B98F6D207F07D400827A46 /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; + A1B98F6E207F07D400827A46 /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; + A1B98F6F207F07D400827A46 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1B98F70207F07D400827A46 /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; + A1B98F71207F07D400827A46 /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; + A1B98F72207F07D400827A46 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; + A1B98F73207F07D400827A46 /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; + A1B98F74207F07D400827A46 /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; + A1B98F75207F07D400827A46 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; + A1B98F76207F07D400827A46 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; + A1B98F77207F07D400827A46 /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; + A1B98F78207F07D400827A46 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; + A1B98F79207F07D400827A46 /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1B98F7A207F07D400827A46 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; + A1B98F7B207F07D400827A46 /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; + A1B98F7C207F07D400827A46 /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; + A1B98F7D207F07D400827A46 /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; + A1B98F7E207F07D400827A46 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; + A1B98F7F207F07D400827A46 /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; + A1B98F80207F07D400827A46 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; + A1B98F81207F07D400827A46 /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; + A1B98F82207F07D400827A46 /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; + A1B98F83207F07D400827A46 /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; + A1B98F84207F07D400827A46 /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; + A1B98F85207F07D400827A46 /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; + A1B98F86207F07D400827A46 /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; + A1B98F87207F07D400827A46 /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; + A1B98F88207F07D400827A46 /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; + A1B98F89207F07D400827A46 /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; + A1B98F8A207F07D400827A46 /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; + A1B98F8B207F07D400827A46 /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; + A1B98F8C207F07D400827A46 /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; + A1B98F8D207F07D400827A46 /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; + A1B98F8E207F07E300827A46 /* r_drawcolpipeline.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */; }; + A1B98F8F207F07E300827A46 /* r_drawcolumn.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2D20563344000955AE /* r_drawcolumn.inl */; }; + A1B98F90207F07E300827A46 /* r_drawflush.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3020563345000955AE /* r_drawflush.inl */; }; + A1B98F91207F07E300827A46 /* r_drawspan.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3120563345000955AE /* r_drawspan.inl */; }; + A1B98F92207F07F900827A46 /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2E20563345000955AE /* Makefile.am */; }; + A1B98F93207F08CA00827A46 /* EASGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E5120563A06000955AE /* EASGlue.c */; }; + A1B98F94207F090600827A46 /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE120563B55000955AE /* eas_chorus.c */; }; + A1B98F95207F090600827A46 /* eas_chorusdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDC20563B55000955AE /* eas_chorusdata.c */; }; + A1B98F96207F090600827A46 /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECF20563B53000955AE /* eas_data.c */; }; + A1B98F97207F090600827A46 /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEF20563B59000955AE /* eas_dlssynth.c */; }; + A1B98F98207F090600827A46 /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0220563B5C000955AE /* eas_flog.c */; }; + A1B98F99207F090600827A46 /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0620563B5D000955AE /* eas_ima_tables.c */; }; + A1B98F9A207F090600827A46 /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED020563B54000955AE /* eas_imaadpcm.c */; }; + A1B98F9B207F090600827A46 /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0C20563B5F000955AE /* eas_imelody.c */; }; + A1B98F9C207F090600827A46 /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFC20563B5C000955AE /* eas_imelodydata.c */; }; + A1B98F9D207F090600827A46 /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1020563B5F000955AE /* eas_math.c */; }; + A1B98F9E207F090600827A46 /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1220563B60000955AE /* eas_mdls.c */; }; + A1B98F9F207F090600827A46 /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE320563B56000955AE /* eas_midi.c */; }; + A1B98FA0207F090600827A46 /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFD20563B5C000955AE /* eas_mididata.c */; }; + A1B98FA1207F090600827A46 /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEC20563B59000955AE /* eas_mixbuf.c */; }; + A1B98FA2207F090600827A46 /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED720563B54000955AE /* eas_mixer.c */; }; + A1B98FA3207F090600827A46 /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED820563B54000955AE /* eas_ota.c */; }; + A1B98FA4207F090600827A46 /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECE20563B53000955AE /* eas_otadata.c */; }; + A1B98FA5207F090600827A46 /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0D20563B5F000955AE /* eas_pan.c */; }; + A1B98FA6207F090600827A46 /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF020563B5A000955AE /* eas_pcm.c */; }; + A1B98FA7207F090600827A46 /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDA20563B54000955AE /* eas_pcmdata.c */; }; + A1B98FA8207F090600827A46 /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0520563B5D000955AE /* eas_public.c */; }; + A1B98FA9207F090600827A46 /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0E20563B5F000955AE /* eas_reverb.c */; }; + A1B98FAA207F090600827A46 /* eas_reverbdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0420563B5D000955AE /* eas_reverbdata.c */; }; + A1B98FAB207F090600827A46 /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED120563B54000955AE /* eas_rtttl.c */; }; + A1B98FAC207F090600827A46 /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFF20563B5C000955AE /* eas_rtttldata.c */; }; + A1B98FAD207F090600827A46 /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EED20563B59000955AE /* eas_smf.c */; }; + A1B98FAE207F090600827A46 /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE520563B56000955AE /* eas_smfdata.c */; }; + A1B98FAF207F090600827A46 /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0F20563B5F000955AE /* eas_tcdata.c */; }; + A1B98FB0207F090600827A46 /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF720563B5B000955AE /* eas_tonecontrol.c */; }; + A1B98FB1207F090700827A46 /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0B20563B5E000955AE /* eas_voicemgt.c */; }; + A1B98FB2207F090700827A46 /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED620563B54000955AE /* eas_wavefile.c */; }; + A1B98FB3207F090700827A46 /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF920563B5B000955AE /* eas_wavefiledata.c */; }; + A1B98FB4207F090700827A46 /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFA20563B5B000955AE /* eas_wtengine.c */; }; + A1B98FB5207F090700827A46 /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE820563B58000955AE /* eas_wtsynth.c */; }; + A1B98FB6207F090700827A46 /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECB20563B53000955AE /* eas_xmf.c */; }; + A1B98FB7207F090700827A46 /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECA20563B53000955AE /* eas_xmfdata.c */; }; + A1B98FB8207F090E00827A46 /* wt_22khz.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE420563B56000955AE /* wt_22khz.c */; }; + A1B98FB9207F091B00827A46 /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4B205634E7000955AE /* eas_config.c */; }; + A1B98FBA207F091B00827A46 /* eas_hostmm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E42205634E7000955AE /* eas_hostmm.c */; }; + A1B98FBB207F091B00827A46 /* eas_report.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E40205634E7000955AE /* eas_report.c */; }; + A1B98FBC207F091B00827A46 /* eas_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4C205634E7000955AE /* eas_wave.c */; }; + A1B9E45D21700601003E9731 /* DOOM-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1B9E45C21700601003E9731 /* DOOM-iOS.xcassets */; }; + A1B9E45F217006D2003E9731 /* DOOM2-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1B9E45E217006D2003E9731 /* DOOM2-iOS.xcassets */; }; + A1CF62A3207F13640096F91C /* i_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2320563253000955AE /* i_sound.c */; }; + A1CF62AD207F138A0096F91C /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; + A1CF62AE207F138A0096F91C /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; + A1CF62AF207F138A0096F91C /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; + A1CF62B0207F138A0096F91C /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1CF62B1207F138A0096F91C /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; + A1CF62B2207F138A0096F91C /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; + A1CF62B3207F138A0096F91C /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; + A1CF62B4207F138A0096F91C /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; + A1CF62B5207F138A0096F91C /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; + A1CF62B6207F138A0096F91C /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; + A1CF62B7207F138A0096F91C /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; + A1CF62B8207F143F0096F91C /* SDL_Mixer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E27205632E2000955AE /* SDL_Mixer.m */; }; + A1D39933217144A800FD11C3 /* FinalDOOMLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A1D39932217144A800FD11C3 /* FinalDOOMLaunchScreen.storyboard */; }; + A1D39934217144B500FD11C3 /* FinalDOOM-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1B9E4602170078A003E9731 /* FinalDOOM-iOS.xcassets */; }; + A1D399362171462F00FD11C3 /* DOOM2LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A1D399352171462F00FD11C3 /* DOOM2LaunchScreen.storyboard */; }; + A1D3993A2171A0A800FD11C3 /* DOOM2-tvOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1D399392171A0A800FD11C3 /* DOOM2-tvOS.xcassets */; }; + A1D3993B2171A0AD00FD11C3 /* DOOM-tvOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1D399372171A08C00FD11C3 /* DOOM-tvOS.xcassets */; }; + A1D3993D2171A0FD00FD11C3 /* FinalDOOM-tvOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1D3993C2171A0FD00FD11C3 /* FinalDOOM-tvOS.xcassets */; }; + A1DE84A0229F60BE0041E450 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; + A1DE84A1229F60BE0041E450 /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; + A1DE84A3229F60BE0041E450 /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; + A1DE84A4229F60BE0041E450 /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; + A1DE84A5229F60BE0041E450 /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; + A1DE84A6229F60BE0041E450 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; + A1DE84A7229F60BE0041E450 /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; + A1DE84A8229F60BE0041E450 /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; + A1DE84A9229F60BE0041E450 /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; + A1DE84AA229F60BE0041E450 /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; + A1DE84AB229F60BE0041E450 /* CreditsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1E89C8D2067469D00760204 /* CreditsMenuView.xib */; }; + A1DE84AC229F60BE0041E450 /* CreditsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBA20562B2B000955AE /* CreditsMenuView~ipad.xib */; }; + A1DE84AD229F60BE0041E450 /* SecretMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBC20562B2B000955AE /* SecretMenuView.xib */; }; + A1DE84AE229F60BE0041E450 /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; + A1DE84AF229F60BE0041E450 /* EpisodeCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A184252063E63200302393 /* EpisodeCell.xib */; }; + A1DE84B0229F60BE0041E450 /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; + A1DE84B1229F60BE0041E450 /* ControlsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DBB20562B2B000955AE /* ControlsMenuView~ipad.xib */; }; + A1DE84B2229F60BE0041E450 /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; + A1DE84B3229F60BE0041E450 /* SettingsMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DC920562B73000955AE /* SettingsMenuView~ipad.xib */; }; + A1DE84B4229F60BE0041E450 /* MainMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCE20562B73000955AE /* MainMenuView.xib */; }; + A1DE84B5229F60BE0041E450 /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; + A1DE84B6229F60BE0041E450 /* MainMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD920562B75000955AE /* MainMenuView~ipad.xib */; }; + A1DE84B7229F60BE0041E450 /* DOOM_144.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1620562FC3000955AE /* DOOM_144.png */; }; + A1DE84B8229F60BE0041E450 /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; + A1DE84B9229F60BE0041E450 /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; + A1DE84BA229F60BE0041E450 /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; + A1DE84BB229F60BE0041E450 /* r_drawcolpipeline.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */; }; + A1DE84BC229F60BE0041E450 /* doom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F9205783E70075CBAD /* doom.wad */; }; + A1DE84BD229F60BE0041E450 /* ControlsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DB620562B2B000955AE /* ControlsMenuView.xib */; }; + A1DE84BE229F60BE0041E450 /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; + A1DE84BF229F60BE0041E450 /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; + A1DE84C0229F60BE0041E450 /* EpisodeMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCA20562B73000955AE /* EpisodeMenuView.xib */; }; + A1DE84C1229F60BE0041E450 /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2E20563345000955AE /* Makefile.am */; }; + A1DE84C2229F60BE0041E450 /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; + A1DE84C3229F60BE0041E450 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; + A1DE84C4229F60BE0041E450 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; + A1DE84C5229F60BE0041E450 /* SettingsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD620562B74000955AE /* SettingsMenuView.xib */; }; + A1DE84C6229F60BE0041E450 /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; + A1DE84C7229F60BE0041E450 /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; + A1DE84C8229F60BE0041E450 /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; + A1DE84C9229F60BE0041E450 /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; + A1DE84CA229F60BE0041E450 /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; + A1DE84CB229F60BE0041E450 /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; + A1DE84CC229F60BE0041E450 /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; + A1DE84CD229F60BE0041E450 /* EpisodeMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DDA20562B75000955AE /* EpisodeMenuView~ipad.xib */; }; + A1DE84CE229F60BE0041E450 /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; + A1DE84CF229F60BE0041E450 /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; + A1DE84D0229F60BE0041E450 /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; + A1DE84D1229F60BE0041E450 /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; + A1DE84D2229F60BE0041E450 /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; + A1DE84D3229F60BE0041E450 /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; + A1DE84D4229F60BE0041E450 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E0720562FAF000955AE /* Localizable.strings */; }; + A1DE84D5229F60BE0041E450 /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; + A1DE84D6229F60BE0041E450 /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; + A1DE84D7229F60BE0041E450 /* DOOMLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A112904F2069B62B00BEDEB5 /* DOOMLaunchScreen.storyboard */; }; + A1DE84D8229F60BE0041E450 /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; + A1DE84D9229F60BE0041E450 /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; + A1DE84DA229F60BE0041E450 /* r_drawspan.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3120563345000955AE /* r_drawspan.inl */; }; + A1DE84DB229F60BE0041E450 /* DOOM_400.png in Resources */ = {isa = PBXBuildFile; fileRef = A1EA3B86207F9DE20038650E /* DOOM_400.png */; }; + A1DE84DC229F60BE0041E450 /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; + A1DE84DD229F60BE0041E450 /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; + A1DE84DE229F60BE0041E450 /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; + A1DE84DF229F60BE0041E450 /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; + A1DE84E0229F60BE0041E450 /* MissionMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DC620562B73000955AE /* MissionMenuView~ipad.xib */; }; + A1DE84E1229F60BE0041E450 /* OpenGLView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DE220562B76000955AE /* OpenGLView~ipad.xib */; }; + A1DE84E2229F60BE0041E450 /* EpisodeCell~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A176AC08206492DD00A96B7E /* EpisodeCell~ipad.xib */; }; + A1DE84E3229F60BE0041E450 /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; + A1DE84E4229F60BE0041E450 /* LegalMenuView~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCB20562B73000955AE /* LegalMenuView~ipad.xib */; }; + A1DE84E5229F60BE0041E450 /* DOOM_76.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1820562FC4000955AE /* DOOM_76.png */; }; + A1DE84E6229F60BE0041E450 /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; + A1DE84E7229F60BE0041E450 /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; + A1DE84E8229F60BE0041E450 /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; + A1DE84E9229F60BE0041E450 /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; + A1DE84EA229F60BE0041E450 /* DOOM_120.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1720562FC3000955AE /* DOOM_120.png */; }; + A1DE84EB229F60BE0041E450 /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; + A1DE84EC229F60BE0041E450 /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; + A1DE84ED229F60BE0041E450 /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; + A1DE84EE229F60BE0041E450 /* r_drawflush.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3020563345000955AE /* r_drawflush.inl */; }; + A1DE84EF229F60BE0041E450 /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; + A1DE84F0229F60BE0041E450 /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; + A1DE84F1229F60BE0041E450 /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; + A1DE84F2229F60BE0041E450 /* DOOM_152.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1520562FC3000955AE /* DOOM_152.png */; }; + A1DE84F3229F60BE0041E450 /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; + A1DE84F4229F60BE0041E450 /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; + A1DE84F5229F60BE0041E450 /* prboom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F8205783E70075CBAD /* prboom.wad */; }; + A1DE84F6229F60BE0041E450 /* base.iPack in Resources */ = {isa = PBXBuildFile; fileRef = A12302FA205783E70075CBAD /* base.iPack */; }; + A1DE84F7229F60BE0041E450 /* OpenGLView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DD220562B74000955AE /* OpenGLView.xib */; }; + A1DE84F8229F60BE0041E450 /* r_drawcolumn.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2D20563344000955AE /* r_drawcolumn.inl */; }; + A1DE84F9229F60BE0041E450 /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; + A1DE84FA229F60BE0041E450 /* MissionMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DCC20562B73000955AE /* MissionMenuView.xib */; }; + A1DE84FB229F60BE0041E450 /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; + A1DE84FC229F60BE0041E450 /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; + A1DE84FD229F60BE0041E450 /* LegalMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1A63DE020562B76000955AE /* LegalMenuView.xib */; }; + A1DE84FF229F60BE0041E450 /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; + A1DE8500229F60BE0041E450 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + A1DE8501229F60BE0041E450 /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; + A1DE8502229F60BE0041E450 /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; + A1DE8503229F60BE0041E450 /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1220563B60000955AE /* eas_mdls.c */; }; + A1DE8504229F60BE0041E450 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; + A1DE8505229F60BE0041E450 /* Doom_App.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E1D20562FD1000955AE /* Doom_App.m */; }; + A1DE8506229F60BE0041E450 /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; + A1DE8507229F60BE0041E450 /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; + A1DE8508229F60BE0041E450 /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DE205737F40075CBAD /* Localization.mm */; }; + A1DE8509229F60BE0041E450 /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; + A1DE850A229F60BE0041E450 /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DC205737F40075CBAD /* View.mm */; }; + A1DE850B229F60BE0041E450 /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0F20563B5F000955AE /* eas_tcdata.c */; }; + A1DE850C229F60BE0041E450 /* iphone_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0320562FAF000955AE /* iphone_delegate.mm */; }; + A1DE850D229F60BE0041E450 /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; + A1DE850E229F60BE0041E450 /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; + A1DE850F229F60BE0041E450 /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; + A1DE8510229F60BE0041E450 /* iphone_async.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0020562FAE000955AE /* iphone_async.cpp */; }; + A1DE8511229F60BE0041E450 /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; + A1DE8512229F60BE0041E450 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; + A1DE8513229F60BE0041E450 /* eas_report.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E40205634E7000955AE /* eas_report.c */; }; + A1DE8514229F60BE0041E450 /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECA20563B53000955AE /* eas_xmfdata.c */; }; + A1DE8515229F60BE0041E450 /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; + A1DE8516229F60BE0041E450 /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; + A1DE8517229F60BE0041E450 /* iphone_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0520562FAF000955AE /* iphone_start.cpp */; }; + A1DE8518229F60BE0041E450 /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; + A1DE8519229F60BE0041E450 /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; + A1DE851A229F60BE0041E450 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DA205737F40075CBAD /* RenderContext.mm */; }; + A1DE851B229F60BE0041E450 /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED820563B54000955AE /* eas_ota.c */; }; + A1DE851C229F60BE0041E450 /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; + A1DE851D229F60BE0041E450 /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; + A1DE851E229F60BE0041E450 /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFC20563B5C000955AE /* eas_imelodydata.c */; }; + A1DE851F229F60BE0041E450 /* MissionMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD020562B74000955AE /* MissionMenuViewController.mm */; }; + A1DE8520229F60BE0041E450 /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1DE8521229F60BE0041E450 /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; + A1DE8522229F60BE0041E450 /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; + A1DE8523229F60BE0041E450 /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; + A1DE8524229F60BE0041E450 /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; + A1DE8525229F60BE0041E450 /* iphone_common.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0620562FAF000955AE /* iphone_common.mm */; }; + A1DE8526229F60BE0041E450 /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; + A1DE8527229F60BE0041E450 /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; + A1DE8528229F60BE0041E450 /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; + A1DE8529229F60BE0041E450 /* eas_hostmm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E42205634E7000955AE /* eas_hostmm.c */; }; + A1DE852A229F60BE0041E450 /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; + A1DE852B229F60BE0041E450 /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; + A1DE852C229F60BE0041E450 /* MainMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD820562B75000955AE /* MainMenuViewController.mm */; }; + A1DE852D229F60BE0041E450 /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; + A1DE852E229F60BE0041E450 /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECB20563B53000955AE /* eas_xmf.c */; }; + A1DE852F229F60BE0041E450 /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECE20563B53000955AE /* eas_otadata.c */; }; + A1DE8531229F60BE0041E450 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; + A1DE8532229F60BE0041E450 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; + A1DE8533229F60BE0041E450 /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE820563B58000955AE /* eas_wtsynth.c */; }; + A1DE8534229F60BE0041E450 /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; + A1DE8535229F60BE0041E450 /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; + A1DE8536229F60BE0041E450 /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; + A1DE8537229F60BE0041E450 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1DE8538229F60BE0041E450 /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0D20563B5F000955AE /* eas_pan.c */; }; + A1DE8539229F60BE0041E450 /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; + A1DE853A229F60BE0041E450 /* mmus2mid.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2B20563344000955AE /* mmus2mid.c */; }; + A1DE853B229F60BE0041E450 /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; + A1DE853C229F60BE0041E450 /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F3205738560075CBAD /* Carousel.mm */; }; + A1DE853D229F60BE0041E450 /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFF20563B5C000955AE /* eas_rtttldata.c */; }; + A1DE853E229F60BE0041E450 /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED020563B54000955AE /* eas_imaadpcm.c */; }; + A1DE853F229F60BE0041E450 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; + A1DE8540229F60BE0041E450 /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; + A1DE8541229F60BE0041E450 /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; + A1DE8542229F60BE0041E450 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; + A1DE8543229F60BE0041E450 /* GameController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C9520689D9500760204 /* GameController.mm */; }; + A1DE8544229F60BE0041E450 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; + A1DE8545229F60BE0041E450 /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; + A1DE8546229F60BE0041E450 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; + A1DE8547229F60BE0041E450 /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1DE8548229F60BE0041E450 /* eas_reverbdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0420563B5D000955AE /* eas_reverbdata.c */; }; + A1DE8549229F60BE0041E450 /* SDL_Mixer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E27205632E2000955AE /* SDL_Mixer.m */; }; + A1DE854A229F60BE0041E450 /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EED20563B59000955AE /* eas_smf.c */; }; + A1DE854B229F60BE0041E450 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; + A1DE854C229F60BE0041E450 /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFD20563B5C000955AE /* eas_mididata.c */; }; + A1DE854D229F60BE0041E450 /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; + A1DE854E229F60BE0041E450 /* eas_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4C205634E7000955AE /* eas_wave.c */; }; + A1DE854F229F60BE0041E450 /* EASGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E5120563A06000955AE /* EASGlue.c */; }; + A1DE8550229F60BE0041E450 /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE320563B56000955AE /* eas_midi.c */; }; + A1DE8551229F60BE0041E450 /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; + A1DE8552229F60BE0041E450 /* wt_22khz.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE420563B56000955AE /* wt_22khz.c */; }; + A1DE8553229F60BE0041E450 /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; + A1DE8554229F60BE0041E450 /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED620563B54000955AE /* eas_wavefile.c */; }; + A1DE8555229F60BE0041E450 /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE120563B55000955AE /* eas_chorus.c */; }; + A1DE8556229F60BE0041E450 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; + A1DE8557229F60BE0041E450 /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; + A1DE8558229F60BE0041E450 /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF020563B5A000955AE /* eas_pcm.c */; }; + A1DE8559229F60BE0041E450 /* iphone_glViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */; }; + A1DE855A229F60BE0041E450 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; + A1DE855B229F60BE0041E450 /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; + A1DE855C229F60BE0041E450 /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; + A1DE855D229F60BE0041E450 /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; + A1DE855E229F60BE0041E450 /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; + A1DE855F229F60BE0041E450 /* CreditsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */; }; + A1DE8560229F60BE0041E450 /* iphone_sound.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0920562FAF000955AE /* iphone_sound.mm */; }; + A1DE8561229F60BE0041E450 /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; + A1DE8562229F60BE0041E450 /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; + A1DE8563229F60BE0041E450 /* SoundEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0820562FAF000955AE /* SoundEngine.cpp */; }; + A1DE8564229F60BE0041E450 /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEF20563B59000955AE /* eas_dlssynth.c */; }; + A1DE8565229F60BE0041E450 /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; + A1DE8566229F60BE0041E450 /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; + A1DE8567229F60BE0041E450 /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; + A1DE8568229F60BE0041E450 /* iphone_sys.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0A20562FAF000955AE /* iphone_sys.mm */; }; + A1DE8569229F60BE0041E450 /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; + A1DE856A229F60BE0041E450 /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; + A1DE856B229F60BE0041E450 /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; + A1DE856C229F60BE0041E450 /* i_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2320563253000955AE /* i_sound.c */; }; + A1DE856D229F60BE0041E450 /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFA20563B5B000955AE /* eas_wtengine.c */; }; + A1DE856E229F60BE0041E450 /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0B20563B5E000955AE /* eas_voicemgt.c */; }; + A1DE856F229F60BE0041E450 /* LegalMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DC720562B73000955AE /* LegalMenuViewController.mm */; }; + A1DE8570229F60BE0041E450 /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF920563B5B000955AE /* eas_wavefiledata.c */; }; + A1DE8571229F60BE0041E450 /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0C20563B5F000955AE /* eas_imelody.c */; }; + A1DE8572229F60BE0041E450 /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; + A1DE8573229F60BE0041E450 /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; + A1DE8574229F60BE0041E450 /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECF20563B53000955AE /* eas_data.c */; }; + A1DE8575229F60BE0041E450 /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; + A1DE8576229F60BE0041E450 /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED720563B54000955AE /* eas_mixer.c */; }; + A1DE8577229F60BE0041E450 /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; + A1DE8578229F60BE0041E450 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1DE8579229F60BE0041E450 /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; + A1DE857A229F60BE0041E450 /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; + A1DE857B229F60BE0041E450 /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0220563B5C000955AE /* eas_flog.c */; }; + A1DE857C229F60BE0041E450 /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4B205634E7000955AE /* eas_config.c */; }; + A1DE857D229F60BE0041E450 /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; + A1DE857E229F60BE0041E450 /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0E20563B5F000955AE /* eas_reverb.c */; }; + A1DE857F229F60BE0041E450 /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; + A1DE8580229F60BE0041E450 /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; + A1DE8581229F60BE0041E450 /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; + A1DE8582229F60BE0041E450 /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE520563B56000955AE /* eas_smfdata.c */; }; + A1DE8583229F60BE0041E450 /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEC20563B59000955AE /* eas_mixbuf.c */; }; + A1DE8584229F60BE0041E450 /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; + A1DE8585229F60BE0041E450 /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0520563B5D000955AE /* eas_public.c */; }; + A1DE8586229F60BE0041E450 /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; + A1DE8587229F60BE0041E450 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; + A1DE8588229F60BE0041E450 /* SettingsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */; }; + A1DE8589229F60BE0041E450 /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; + A1DE858A229F60BE0041E450 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; + A1DE858B229F60BE0041E450 /* Slider.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F0205738270075CBAD /* Slider.mm */; }; + A1DE858C229F60BE0041E450 /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; + A1DE858D229F60BE0041E450 /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D7205737F40075CBAD /* LabelButton.mm */; }; + A1DE858E229F60BE0041E450 /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302E1205737F50075CBAD /* Switch.mm */; }; + A1DE858F229F60BE0041E450 /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED120563B54000955AE /* eas_rtttl.c */; }; + A1DE8590229F60BE0041E450 /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; + A1DE8591229F60BE0041E450 /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; + A1DE8592229F60BE0041E450 /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDA20563B54000955AE /* eas_pcmdata.c */; }; + A1DE8593229F60BE0041E450 /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; + A1DE8594229F60BE0041E450 /* SecretMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB720562B2B000955AE /* SecretMenuViewController.mm */; }; + A1DE8595229F60BE0041E450 /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF720563B5B000955AE /* eas_tonecontrol.c */; }; + A1DE8596229F60BE0041E450 /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; + A1DE8597229F60BE0041E450 /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D6205737F40075CBAD /* Label.mm */; }; + A1DE8598229F60BE0041E450 /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; + A1DE8599229F60BE0041E450 /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; + A1DE859A229F60BE0041E450 /* eas_chorusdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDC20563B55000955AE /* eas_chorusdata.c */; }; + A1DE859B229F60BE0041E450 /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1020563B5F000955AE /* eas_math.c */; }; + A1DE859C229F60BE0041E450 /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; + A1DE859D229F60BE0041E450 /* MainNavController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDC20562B75000955AE /* MainNavController.m */; }; + A1DE859E229F60BE0041E450 /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0620563B5D000955AE /* eas_ima_tables.c */; }; + A1DE859F229F60BE0041E450 /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; + A1DE85A0229F60BE0041E450 /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; + A1DE85A1229F60BE0041E450 /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; + A1DE85A2229F60BE0041E450 /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; + A1DE85A3229F60BE0041E450 /* ControlsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */; }; + A1DE85A4229F60BE0041E450 /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; + A1DE85A5229F60BE0041E450 /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; + A1DE85A7229F60BE0041E450 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E89C9320689D4B00760204 /* GameController.framework */; }; + A1DE85A8229F60BE0041E450 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A63E5420563A6D000955AE /* AVFoundation.framework */; }; + A1DE85A9229F60BE0041E450 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */; }; + A1DE85AA229F60BE0041E450 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */; }; + A1DE85AB229F60BE0041E450 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */; }; + A1DE85AC229F60BE0041E450 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */; }; + A1DE85AD229F60BE0041E450 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760611C2B19E004A9B9B /* Foundation.framework */; }; + A1DE85AE229F60BE0041E450 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760811C2B19E004A9B9B /* OpenGLES.framework */; }; + A1DE85AF229F60BE0041E450 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760A11C2B19E004A9B9B /* UIKit.framework */; }; + A1DE85BD229F610C0041E450 /* SIGIL.wad in Resources */ = {isa = PBXBuildFile; fileRef = A1DE85BB229F610B0041E450 /* SIGIL.wad */; }; + A1DE85C3229F73950041E450 /* SIGIL-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1DE85C2229F73950041E450 /* SIGIL-iOS.xcassets */; }; + A1DE85C7229F874F0041E450 /* SIGILLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A1DE85C6229F874F0041E450 /* SIGILLaunchScreen.storyboard */; }; + A1DE85CA229F88D20041E450 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; + A1DE85CB229F88D20041E450 /* r_drawflush.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3020563345000955AE /* r_drawflush.inl */; }; + A1DE85CC229F88D20041E450 /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; + A1DE85CD229F88D20041E450 /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; + A1DE85CE229F88D20041E450 /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; + A1DE85CF229F88D20041E450 /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; + A1DE85D0229F88D20041E450 /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; + A1DE85D1229F88D20041E450 /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; + A1DE85D2229F88D20041E450 /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; + A1DE85D3229F88D20041E450 /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; + A1DE85D4229F88D20041E450 /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; + A1DE85D5229F88D20041E450 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E0720562FAF000955AE /* Localizable.strings */; }; + A1DE85D6229F88D20041E450 /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; + A1DE85D7229F88D20041E450 /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; + A1DE85D8229F88D20041E450 /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; + A1DE85D9229F88D20041E450 /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; + A1DE85DA229F88D20041E450 /* r_drawspan.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E3120563345000955AE /* r_drawspan.inl */; }; + A1DE85DB229F88D20041E450 /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; + A1DE85DC229F88D20041E450 /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; + A1DE85DD229F88D20041E450 /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; + A1DE85DE229F88D20041E450 /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; + A1DE85DF229F88D20041E450 /* doom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F9205783E70075CBAD /* doom.wad */; }; + A1DE85E0229F88D20041E450 /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; + A1DE85E1229F88D20041E450 /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; + A1DE85E2229F88D20041E450 /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; + A1DE85E3229F88D20041E450 /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; + A1DE85E4229F88D20041E450 /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; + A1DE85E5229F88D20041E450 /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; + A1DE85E6229F88D20041E450 /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; + A1DE85E7229F88D20041E450 /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; + A1DE85E8229F88D20041E450 /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; + A1DE85E9229F88D20041E450 /* r_drawcolpipeline.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */; }; + A1DE85EA229F88D20041E450 /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; + A1DE85EB229F88D20041E450 /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; + A1DE85EC229F88D20041E450 /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2E20563345000955AE /* Makefile.am */; }; + A1DE85ED229F88D20041E450 /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; + A1DE85EE229F88D20041E450 /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; + A1DE85EF229F88D20041E450 /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; + A1DE85F0229F88D20041E450 /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; + A1DE85F1229F88D20041E450 /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; + A1DE85F2229F88D20041E450 /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; + A1DE85F3229F88D20041E450 /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; + A1DE85F4229F88D20041E450 /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; + A1DE85F5229F88D20041E450 /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; + A1DE85F6229F88D20041E450 /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; + A1DE85F7229F88D20041E450 /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; + A1DE85F8229F88D20041E450 /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; + A1DE85F9229F88D20041E450 /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; + A1DE85FA229F88D20041E450 /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; + A1DE85FB229F88D20041E450 /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; + A1DE85FC229F88D20041E450 /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; + A1DE85FD229F88D20041E450 /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; + A1DE85FE229F88D20041E450 /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; + A1DE85FF229F88D20041E450 /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; + A1DE8600229F88D20041E450 /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; + A1DE8601229F88D20041E450 /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; + A1DE8602229F88D20041E450 /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; + A1DE8603229F88D20041E450 /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; + A1DE8604229F88D20041E450 /* EpisodeCell-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1EA3B8F208020B60038650E /* EpisodeCell-tvos.xib */; }; + A1DE8605229F88D20041E450 /* base.iPack in Resources */ = {isa = PBXBuildFile; fileRef = A12302FA205783E70075CBAD /* base.iPack */; }; + A1DE8606229F88D20041E450 /* prboom.wad in Resources */ = {isa = PBXBuildFile; fileRef = A12302F8205783E70075CBAD /* prboom.wad */; }; + A1DE8607229F88D20041E450 /* DOOM_76.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1820562FC4000955AE /* DOOM_76.png */; }; + A1DE8608229F88D20041E450 /* r_drawcolumn.inl in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E2D20563344000955AE /* r_drawcolumn.inl */; }; + A1DE8609229F88D20041E450 /* DOOM_120.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1720562FC3000955AE /* DOOM_120.png */; }; + A1DE860A229F88D20041E450 /* DOOM_144.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1620562FC3000955AE /* DOOM_144.png */; }; + A1DE860B229F88D20041E450 /* DOOM_152.png in Resources */ = {isa = PBXBuildFile; fileRef = A1A63E1520562FC3000955AE /* DOOM_152.png */; }; + A1DE860C229F88D20041E450 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; + A1DE860D229F88D20041E450 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; + A1DE860E229F88D20041E450 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; + A1DE8610229F88D20041E450 /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; + A1DE8611229F88D20041E450 /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; + A1DE8612229F88D20041E450 /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; + A1DE8613229F88D20041E450 /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; + A1DE8614229F88D20041E450 /* MainMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E15207F016500827A46 /* MainMenuView-tvos.xib */; }; + A1DE8615229F88D20041E450 /* MissionMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1B207F016600827A46 /* MissionMenuView-tvos.xib */; }; + A1DE8616229F88D20041E450 /* OpenGLView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E18207F016500827A46 /* OpenGLView-tvos.xib */; }; + A1DE8617229F88D20041E450 /* EpisodeMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1A207F016600827A46 /* EpisodeMenuView-tvos.xib */; }; + A1DE8618229F88D20041E450 /* SettingsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E19207F016500827A46 /* SettingsMenuView-tvos.xib */; }; + A1DE8619229F88D20041E450 /* CreditsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E1C207F016600827A46 /* CreditsMenuView-tvos.xib */; }; + A1DE861A229F88D20041E450 /* ControlsMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E17207F016500827A46 /* ControlsMenuView-tvos.xib */; }; + A1DE861B229F88D20041E450 /* LegalMenuView-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1B98E16207F016500827A46 /* LegalMenuView-tvos.xib */; }; + A1DE861D229F88D20041E450 /* eas_math.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1020563B5F000955AE /* eas_math.c */; }; + A1DE861E229F88D20041E450 /* eas_rtttl.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED120563B54000955AE /* eas_rtttl.c */; }; + A1DE861F229F88D20041E450 /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; + A1DE8620229F88D20041E450 /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; + A1DE8621229F88D20041E450 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; + A1DE8622229F88D20041E450 /* eas_otadata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECE20563B53000955AE /* eas_otadata.c */; }; + A1DE8623229F88D20041E450 /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; + A1DE8624229F88D20041E450 /* eas_tcdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0F20563B5F000955AE /* eas_tcdata.c */; }; + A1DE8625229F88D20041E450 /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; + A1DE8626229F88D20041E450 /* iphone_sys.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0A20562FAF000955AE /* iphone_sys.mm */; }; + A1DE8627229F88D20041E450 /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; + A1DE8628229F88D20041E450 /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; + A1DE8629229F88D20041E450 /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; + A1DE862A229F88D20041E450 /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; + A1DE862B229F88D20041E450 /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; + A1DE862C229F88D20041E450 /* iphone_common.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0620562FAF000955AE /* iphone_common.mm */; }; + A1DE862D229F88D20041E450 /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; + A1DE862E229F88D20041E450 /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1DE862F229F88D20041E450 /* MissionMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD020562B74000955AE /* MissionMenuViewController.mm */; }; + A1DE8630229F88D20041E450 /* eas_config.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4B205634E7000955AE /* eas_config.c */; }; + A1DE8631229F88D20041E450 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; + A1DE8632229F88D20041E450 /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; + A1DE8633229F88D20041E450 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + A1DE8634229F88D20041E450 /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; + A1DE8635229F88D20041E450 /* GameController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C9520689D9500760204 /* GameController.mm */; }; + A1DE8636229F88D20041E450 /* eas_mixbuf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEC20563B59000955AE /* eas_mixbuf.c */; }; + A1DE8637229F88D20041E450 /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; + A1DE8638229F88D20041E450 /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; + A1DE8639229F88D20041E450 /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; + A1DE863A229F88D20041E450 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; + A1DE863B229F88D20041E450 /* RenderContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DA205737F40075CBAD /* RenderContext.mm */; }; + A1DE863C229F88D20041E450 /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; + A1DE863D229F88D20041E450 /* eas_flog.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0220563B5C000955AE /* eas_flog.c */; }; + A1DE863E229F88D20041E450 /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; + A1DE863F229F88D20041E450 /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; + A1DE8640229F88D20041E450 /* eas_data.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECF20563B53000955AE /* eas_data.c */; }; + A1DE8641229F88D20041E450 /* eas_imelodydata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFC20563B5C000955AE /* eas_imelodydata.c */; }; + A1DE8642229F88D20041E450 /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; + A1DE8643229F88D20041E450 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; + A1DE8644229F88D20041E450 /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; + A1DE8645229F88D20041E450 /* eas_xmfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECA20563B53000955AE /* eas_xmfdata.c */; }; + A1DE8646229F88D20041E450 /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; + A1DE8647229F88D20041E450 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; + A1DE8648229F88D20041E450 /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; + A1DE8649229F88D20041E450 /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; + A1DE864A229F88D20041E450 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1DE864B229F88D20041E450 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; + A1DE864C229F88D20041E450 /* eas_xmf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ECB20563B53000955AE /* eas_xmf.c */; }; + A1DE864D229F88D20041E450 /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; + A1DE864E229F88D20041E450 /* eas_wavefile.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED620563B54000955AE /* eas_wavefile.c */; }; + A1DE864F229F88D20041E450 /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; + A1DE8650229F88D20041E450 /* eas_smfdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE520563B56000955AE /* eas_smfdata.c */; }; + A1DE8651229F88D20041E450 /* SoundEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0820562FAF000955AE /* SoundEngine.cpp */; }; + A1DE8652229F88D20041E450 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1DE8653229F88D20041E450 /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; + A1DE8654229F88D20041E450 /* View.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DC205737F40075CBAD /* View.mm */; }; + A1DE8655229F88D20041E450 /* eas_voicemgt.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0B20563B5E000955AE /* eas_voicemgt.c */; }; + A1DE8656229F88D20041E450 /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; + A1DE8657229F88D20041E450 /* Label.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D6205737F40075CBAD /* Label.mm */; }; + A1DE8658229F88D20041E450 /* eas_dlssynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EEF20563B59000955AE /* eas_dlssynth.c */; }; + A1DE8659229F88D20041E450 /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; + A1DE865A229F88D20041E450 /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; + A1DE865B229F88D20041E450 /* MainMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DD820562B75000955AE /* MainMenuViewController.mm */; }; + A1DE865C229F88D20041E450 /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; + A1DE865D229F88D20041E450 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; + A1DE865E229F88D20041E450 /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; + A1DE865F229F88D20041E450 /* eas_hostmm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E42205634E7000955AE /* eas_hostmm.c */; }; + A1DE8660229F88D20041E450 /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; + A1DE8661229F88D20041E450 /* eas_mididata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFD20563B5C000955AE /* eas_mididata.c */; }; + A1DE8662229F88D20041E450 /* Doom_App.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E1D20562FD1000955AE /* Doom_App.m */; }; + A1DE8663229F88D20041E450 /* eas_pcmdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDA20563B54000955AE /* eas_pcmdata.c */; }; + A1DE8664229F88D20041E450 /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; + A1DE8665229F88D20041E450 /* eas_chorusdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EDC20563B55000955AE /* eas_chorusdata.c */; }; + A1DE8666229F88D20041E450 /* eas_chorus.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE120563B55000955AE /* eas_chorus.c */; }; + A1DE8667229F88D20041E450 /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; + A1DE8668229F88D20041E450 /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; + A1DE8669229F88D20041E450 /* LabelButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302D7205737F40075CBAD /* LabelButton.mm */; }; + A1DE866A229F88D20041E450 /* SDL_Mixer.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E27205632E2000955AE /* SDL_Mixer.m */; }; + A1DE866B229F88D20041E450 /* EASGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E5120563A06000955AE /* EASGlue.c */; }; + A1DE866C229F88D20041E450 /* Switch.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302E1205737F50075CBAD /* Switch.mm */; }; + A1DE866D229F88D20041E450 /* eas_ima_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0620563B5D000955AE /* eas_ima_tables.c */; }; + A1DE866E229F88D20041E450 /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; + A1DE866F229F88D20041E450 /* eas_ota.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED820563B54000955AE /* eas_ota.c */; }; + A1DE8670229F88D20041E450 /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; + A1DE8671229F88D20041E450 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; + A1DE8672229F88D20041E450 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; + A1DE8673229F88D20041E450 /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; + A1DE8674229F88D20041E450 /* eas_smf.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EED20563B59000955AE /* eas_smf.c */; }; + A1DE8675229F88D20041E450 /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; + A1DE8676229F88D20041E450 /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; + A1DE8677229F88D20041E450 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; + A1DE8678229F88D20041E450 /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; + A1DE8679229F88D20041E450 /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; + A1DE867A229F88D20041E450 /* iphone_delegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0320562FAF000955AE /* iphone_delegate.mm */; }; + A1DE867B229F88D20041E450 /* eas_imelody.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0C20563B5F000955AE /* eas_imelody.c */; }; + A1DE867C229F88D20041E450 /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; + A1DE867D229F88D20041E450 /* eas_tonecontrol.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF720563B5B000955AE /* eas_tonecontrol.c */; }; + A1DE867E229F88D20041E450 /* LegalMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DC720562B73000955AE /* LegalMenuViewController.mm */; }; + A1DE867F229F88D20041E450 /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; + A1DE8680229F88D20041E450 /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; + A1DE8681229F88D20041E450 /* iphone_async.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0020562FAE000955AE /* iphone_async.cpp */; }; + A1DE8682229F88D20041E450 /* eas_wave.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E4C205634E7000955AE /* eas_wave.c */; }; + A1DE8683229F88D20041E450 /* eas_imaadpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED020563B54000955AE /* eas_imaadpcm.c */; }; + A1DE8684229F88D20041E450 /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; + A1DE8685229F88D20041E450 /* MainNavController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DDC20562B75000955AE /* MainNavController.m */; }; + A1DE8686229F88D20041E450 /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; + A1DE8687229F88D20041E450 /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; + A1DE8688229F88D20041E450 /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; + A1DE8689229F88D20041E450 /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; + A1DE868A229F88D20041E450 /* eas_reverbdata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0420563B5D000955AE /* eas_reverbdata.c */; }; + A1DE868B229F88D20041E450 /* eas_report.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E40205634E7000955AE /* eas_report.c */; }; + A1DE868C229F88D20041E450 /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; + A1DE868D229F88D20041E450 /* eas_wtengine.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFA20563B5B000955AE /* eas_wtengine.c */; }; + A1DE868E229F88D20041E450 /* eas_public.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0520563B5D000955AE /* eas_public.c */; }; + A1DE868F229F88D20041E450 /* eas_wavefiledata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF920563B5B000955AE /* eas_wavefiledata.c */; }; + A1DE8690229F88D20041E450 /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; + A1DE8691229F88D20041E450 /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; + A1DE8692229F88D20041E450 /* eas_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63ED720563B54000955AE /* eas_mixer.c */; }; + A1DE8693229F88D20041E450 /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; + A1DE8694229F88D20041E450 /* eas_rtttldata.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EFF20563B5C000955AE /* eas_rtttldata.c */; }; + A1DE8695229F88D20041E450 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; + A1DE8696229F88D20041E450 /* wt_22khz.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE420563B56000955AE /* wt_22khz.c */; }; + A1DE8697229F88D20041E450 /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; settings = {COMPILER_FLAGS = "-w"; }; }; + A1DE8698229F88D20041E450 /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; + A1DE8699229F88D20041E450 /* ControlsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */; }; + A1DE869A229F88D20041E450 /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; + A1DE869B229F88D20041E450 /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; + A1DE869C229F88D20041E450 /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; + A1DE869D229F88D20041E450 /* eas_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0E20563B5F000955AE /* eas_reverb.c */; }; + A1DE869E229F88D20041E450 /* eas_wtsynth.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE820563B58000955AE /* eas_wtsynth.c */; }; + A1DE869F229F88D20041E450 /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; + A1DE86A0229F88D20041E450 /* eas_mdls.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F1220563B60000955AE /* eas_mdls.c */; }; + A1DE86A1229F88D20041E450 /* SettingsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */; }; + A1DE86A2229F88D20041E450 /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; + A1DE86A3229F88D20041E450 /* i_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2320563253000955AE /* i_sound.c */; }; + A1DE86A4229F88D20041E450 /* CreditsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */; }; + A1DE86A5229F88D20041E450 /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; + A1DE86A6229F88D20041E450 /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; + A1DE86A7229F88D20041E450 /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; + A1DE86A8229F88D20041E450 /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; + A1DE86A9229F88D20041E450 /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; + A1DE86AA229F88D20041E450 /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; + A1DE86AB229F88D20041E450 /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; + A1DE86AC229F88D20041E450 /* iphone_sound.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0920562FAF000955AE /* iphone_sound.mm */; }; + A1DE86AD229F88D20041E450 /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; + A1DE86AF229F88D20041E450 /* iphone_glViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */; }; + A1DE86B0229F88D20041E450 /* mmus2mid.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E2B20563344000955AE /* mmus2mid.c */; }; + A1DE86B1229F88D20041E450 /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; + A1DE86B2229F88D20041E450 /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; + A1DE86B3229F88D20041E450 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; + A1DE86B4229F88D20041E450 /* Localization.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302DE205737F40075CBAD /* Localization.mm */; }; + A1DE86B5229F88D20041E450 /* eas_midi.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EE320563B56000955AE /* eas_midi.c */; }; + A1DE86B6229F88D20041E450 /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; + A1DE86B7229F88D20041E450 /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; + A1DE86B8229F88D20041E450 /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; + A1DE86B9229F88D20041E450 /* eas_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63EF020563B5A000955AE /* eas_pcm.c */; }; + A1DE86BA229F88D20041E450 /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; + A1DE86BB229F88D20041E450 /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; + A1DE86BC229F88D20041E450 /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; + A1DE86BD229F88D20041E450 /* Carousel.mm in Sources */ = {isa = PBXBuildFile; fileRef = A12302F3205738560075CBAD /* Carousel.mm */; }; + A1DE86BE229F88D20041E450 /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; + A1DE86BF229F88D20041E450 /* eas_pan.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A63F0D20563B5F000955AE /* eas_pan.c */; }; + A1DE86C0229F88D20041E450 /* iphone_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A63E0520562FAF000955AE /* iphone_start.cpp */; }; + A1DE86C1229F88D20041E450 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; + A1DE86C3229F88D20041E450 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1EA3B84207F1D310038650E /* AVFoundation.framework */; }; + A1DE86C4229F88D20041E450 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E01207EFF8A00827A46 /* QuartzCore.framework */; }; + A1DE86C5229F88D20041E450 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E02207EFF8A00827A46 /* AudioToolbox.framework */; }; + A1DE86C6229F88D20041E450 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E03207EFF8A00827A46 /* OpenGLES.framework */; }; + A1DE86C7229F88D20041E450 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E05207EFF8A00827A46 /* UIKit.framework */; }; + A1DE86C8229F88D20041E450 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E06207EFF8A00827A46 /* Foundation.framework */; }; + A1DE86C9229F88D20041E450 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E07207EFF8A00827A46 /* CoreGraphics.framework */; }; + A1DE86CA229F88D20041E450 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E08207EFF8B00827A46 /* GameController.framework */; }; + A1DE86CB229F88D20041E450 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B98E09207EFF8B00827A46 /* OpenAL.framework */; }; + A1DE86D7229F8A830041E450 /* SIGIL.wad in Resources */ = {isa = PBXBuildFile; fileRef = A1DE85BB229F610B0041E450 /* SIGIL.wad */; }; + A1DE86DA229F8B090041E450 /* SIGIL-tvOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1DE86D8229F8B090041E450 /* SIGIL-tvOS.xcassets */; }; + A1E89C8F2067469D00760204 /* CreditsMenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */; }; + A1E89C902067469D00760204 /* CreditsMenuView.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1E89C8D2067469D00760204 /* CreditsMenuView.xib */; }; + A1E89C9420689D4C00760204 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1E89C9320689D4B00760204 /* GameController.framework */; }; + A1E89C9620689D9500760204 /* GameController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1E89C9520689D9500760204 /* GameController.mm */; }; + A1EA3B85207F1D320038650E /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1EA3B84207F1D310038650E /* AVFoundation.framework */; }; + A1EA3B87207F9DE20038650E /* DOOM_400.png in Resources */ = {isa = PBXBuildFile; fileRef = A1EA3B86207F9DE20038650E /* DOOM_400.png */; }; + A1EA3B90208020B60038650E /* EpisodeCell-tvos.xib in Resources */ = {isa = PBXBuildFile; fileRef = A1EA3B8F208020B60038650E /* EpisodeCell-tvos.xib */; }; + C8139AB313FADA800094C2C0 /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; + C8139AB513FADA9D0094C2C0 /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; + C81E0E5E13E076E400B1049A /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; + C81E104C13E1CCA000B1049A /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; + C81E104D13E1CCA000B1049A /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; + C81E104E13E1CCA000B1049A /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; + C81E104F13E1CCA000B1049A /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; + C81E105013E1CCA000B1049A /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; + C81E105113E1CCA000B1049A /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; + C81E105213E1CCA000B1049A /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; + C81E105313E1CCA000B1049A /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; + C81E105413E1CCA000B1049A /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; + C81E105513E1CCA000B1049A /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; + C81E105613E1CCA000B1049A /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; + C81E105713E1CCA000B1049A /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; + C8792ED813F5AFE5003D834F /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; + C8792ED913F5AFE6003D834F /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; + C8792EDA13F5AFE6003D834F /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; + C8792EDB13F5AFE6003D834F /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; + C8792EDC13F5AFE6003D834F /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; + C8792EDD13F5AFE6003D834F /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; + C8792EDE13F5AFE6003D834F /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; + C879308F13F5D8AA003D834F /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; + C879309013F5D8AA003D834F /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; + C879309113F5D8AA003D834F /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; + C879309213F5D8AA003D834F /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; + C879309313F5D8AA003D834F /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; + C879309413F5D8AA003D834F /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; + C879309513F5D8AA003D834F /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; + C879309613F5D8AA003D834F /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; + C879309713F5D8AA003D834F /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; + C879309813F5D8AA003D834F /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; + C87930E513F5EC1B003D834F /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; + C87930E613F5EC1B003D834F /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; + C87930E713F5EC1B003D834F /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; + C87930E813F5EC1B003D834F /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; + C87931EC13F610B9003D834F /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; + C87931ED13F610B9003D834F /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; + C87931EE13F610B9003D834F /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; + C87931EF13F610B9003D834F /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; + C87931F013F610B9003D834F /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; + C87931F113F610B9003D834F /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; + C87931F213F610B9003D834F /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; + C87931F313F610B9003D834F /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; + C87931F413F610B9003D834F /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; + C87931F513F610B9003D834F /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; + C87931F613F610B9003D834F /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; + C87931F713F610B9003D834F /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; + C87931F813F610B9003D834F /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; + C87931F913F610B9003D834F /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; + C8D1CF6813DE1EB600F0EAC6 /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; + C8D1CF6A13DE1EF500F0EAC6 /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; + C8D1CF6C13DE1F0600F0EAC6 /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; + C8D1CF8613DF792D00F0EAC6 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; + C8D1CF8813DF79BC00F0EAC6 /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; + C8D1CFA813E1CDBD00F0EAC6 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; + C8D1CFAA13E1CDC600F0EAC6 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; + ED9AB3D110966E85000B5852 /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; + EDD2760511C2B19E004A9B9B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */; }; + EDD2760711C2B19E004A9B9B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760611C2B19E004A9B9B /* Foundation.framework */; }; + EDD2760911C2B19E004A9B9B /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760811C2B19E004A9B9B /* OpenGLES.framework */; }; + EDD2760B11C2B19E004A9B9B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760A11C2B19E004A9B9B /* UIKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D6058910D05DD3D006BFB54 /* DOOM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DOOM.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; + 434669A30F8D08C000EA7D6D /* doom_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doom_Prefix.pch; sourceTree = ""; }; + 4364BF3E0F5CB25900F29317 /* dist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = dist.plist; sourceTree = ""; }; + 43CF02FE0F56974E00E4A23D /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; + 43CF03090F56D5C200E4A23D /* iphone_loop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_loop.c; sourceTree = ""; }; + 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_main.c; sourceTree = ""; }; + 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = /System/Library/Frameworks/OpenAL.framework; sourceTree = ""; }; + 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = ""; }; + 7229CC8E0F6B3363004123C5 /* doomiphone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomiphone.h; path = ../doomiphone.h; sourceTree = SOURCE_ROOT; }; + 7229CE450F6C89F8004123C5 /* EAGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EAGLView.h; sourceTree = ""; }; + 7229CE460F6C89F8004123C5 /* EAGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EAGLView.m; sourceTree = ""; }; + 7229CE540F6C8CDE004123C5 /* gles_glue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gles_glue.c; sourceTree = ""; }; + 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_mapSelect.c; sourceTree = ""; }; + 72484E5D0FB0E99900124E1C /* iphone_render.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_render.c; sourceTree = ""; }; + 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackgroundMusic.cpp; sourceTree = ""; }; + 727886A20FBDBA740020D469 /* gles_glue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gles_glue.h; sourceTree = ""; }; + 72A560E11004FAEE00F788A5 /* iphone_net.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_net.c; sourceTree = ""; }; + 72A7E8F30F5F2001005B83C0 /* iphone_doom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_doom.h; sourceTree = ""; }; + 72B5FF380F7E5C3D00C8A372 /* hud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hud.c; sourceTree = ""; }; + 72D50DBA0F8ED98000BB49E6 /* ipak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipak.h; sourceTree = ""; }; + 72D50DBB0F8ED98000BB49E6 /* ipak.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ipak.c; sourceTree = ""; }; + 72E847640F93C61900AB3C99 /* am_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = am_map.c; path = ../prboom/am_map.c; sourceTree = SOURCE_ROOT; }; + 72E847680F93FF2F00AB3C99 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../prboom/config.h; sourceTree = SOURCE_ROOT; }; + 72E8476E0F93FFDB00AB3C99 /* am_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = am_map.h; path = ../prboom/am_map.h; sourceTree = SOURCE_ROOT; }; + 72E8476F0F93FFDB00AB3C99 /* d_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = d_client.c; path = ../prboom/d_client.c; sourceTree = SOURCE_ROOT; }; + 72E847700F93FFDB00AB3C99 /* d_deh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = d_deh.c; path = ../prboom/d_deh.c; sourceTree = SOURCE_ROOT; }; + 72E847710F93FFDB00AB3C99 /* d_deh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_deh.h; path = ../prboom/d_deh.h; sourceTree = SOURCE_ROOT; }; + 72E847720F93FFDB00AB3C99 /* d_englsh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_englsh.h; path = ../prboom/d_englsh.h; sourceTree = SOURCE_ROOT; }; + 72E847730F93FFDB00AB3C99 /* d_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_event.h; path = ../prboom/d_event.h; sourceTree = SOURCE_ROOT; }; + 72E8477A0F9400D700AB3C99 /* d_items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = d_items.c; path = ../prboom/d_items.c; sourceTree = SOURCE_ROOT; }; + 72E8477B0F9400D700AB3C99 /* d_items.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_items.h; path = ../prboom/d_items.h; sourceTree = SOURCE_ROOT; }; + 72E8477C0F9400D700AB3C99 /* d_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = d_main.c; path = ../prboom/d_main.c; sourceTree = SOURCE_ROOT; }; + 72E8477D0F9400D700AB3C99 /* d_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_main.h; path = ../prboom/d_main.h; sourceTree = SOURCE_ROOT; }; + 72E8477E0F9400D700AB3C99 /* d_net.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_net.h; path = ../prboom/d_net.h; sourceTree = SOURCE_ROOT; }; + 72E8477F0F9400D700AB3C99 /* d_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_player.h; path = ../prboom/d_player.h; sourceTree = SOURCE_ROOT; }; + 72E847810F9400D700AB3C99 /* d_think.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_think.h; path = ../prboom/d_think.h; sourceTree = SOURCE_ROOT; }; + 72E847820F9400D700AB3C99 /* d_ticcmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_ticcmd.h; path = ../prboom/d_ticcmd.h; sourceTree = SOURCE_ROOT; }; + 72E847830F9400D700AB3C99 /* doomdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomdata.h; path = ../prboom/doomdata.h; sourceTree = SOURCE_ROOT; }; + 72E847840F9400D700AB3C99 /* doomdef.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = doomdef.c; path = ../prboom/doomdef.c; sourceTree = SOURCE_ROOT; }; + 72E847850F9400D700AB3C99 /* doomdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomdef.h; path = ../prboom/doomdef.h; sourceTree = SOURCE_ROOT; }; + 72E847860F9400D700AB3C99 /* doomstat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = doomstat.c; path = ../prboom/doomstat.c; sourceTree = SOURCE_ROOT; }; + 72E847870F9400D700AB3C99 /* doomstat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomstat.h; path = ../prboom/doomstat.h; sourceTree = SOURCE_ROOT; }; + 72E847880F9400D700AB3C99 /* doomtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomtype.h; path = ../prboom/doomtype.h; sourceTree = SOURCE_ROOT; }; + 72E847890F9400D700AB3C99 /* dstrings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dstrings.c; path = ../prboom/dstrings.c; sourceTree = SOURCE_ROOT; }; + 72E8478A0F9400D700AB3C99 /* dstrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dstrings.h; path = ../prboom/dstrings.h; sourceTree = SOURCE_ROOT; }; + 72E8478B0F9400D700AB3C99 /* f_finale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = f_finale.c; path = ../prboom/f_finale.c; sourceTree = SOURCE_ROOT; }; + 72E8478C0F9400D700AB3C99 /* f_finale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = f_finale.h; path = ../prboom/f_finale.h; sourceTree = SOURCE_ROOT; }; + 72E8478D0F9400D700AB3C99 /* f_wipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = f_wipe.c; path = ../prboom/f_wipe.c; sourceTree = SOURCE_ROOT; }; + 72E8478E0F9400D700AB3C99 /* f_wipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = f_wipe.h; path = ../prboom/f_wipe.h; sourceTree = SOURCE_ROOT; }; + 72E8478F0F9400D700AB3C99 /* g_game.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = g_game.c; path = ../prboom/g_game.c; sourceTree = SOURCE_ROOT; }; + 72E847900F9400D700AB3C99 /* g_game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = g_game.h; path = ../prboom/g_game.h; sourceTree = SOURCE_ROOT; }; + 72E847910F9400D700AB3C99 /* gl_intern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gl_intern.h; path = ../prboom/gl_intern.h; sourceTree = SOURCE_ROOT; }; + 72E847920F9400D700AB3C99 /* gl_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = gl_main.c; path = ../prboom/gl_main.c; sourceTree = SOURCE_ROOT; }; + 72E847930F9400D700AB3C99 /* gl_struct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gl_struct.h; path = ../prboom/gl_struct.h; sourceTree = SOURCE_ROOT; }; + 72E847940F9400D700AB3C99 /* gl_texture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = gl_texture.c; path = ../prboom/gl_texture.c; sourceTree = SOURCE_ROOT; }; + 72E847950F9400D700AB3C99 /* hu_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hu_lib.c; path = ../prboom/hu_lib.c; sourceTree = SOURCE_ROOT; }; + 72E847960F9400D700AB3C99 /* hu_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hu_lib.h; path = ../prboom/hu_lib.h; sourceTree = SOURCE_ROOT; }; + 72E847970F9400D700AB3C99 /* hu_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hu_stuff.c; path = ../prboom/hu_stuff.c; sourceTree = SOURCE_ROOT; }; + 72E847980F9400D700AB3C99 /* hu_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hu_stuff.h; path = ../prboom/hu_stuff.h; sourceTree = SOURCE_ROOT; }; + 72E847990F9400D700AB3C99 /* i_joy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_joy.h; path = ../prboom/i_joy.h; sourceTree = SOURCE_ROOT; }; + 72E8479A0F9400D700AB3C99 /* i_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_main.h; path = ../prboom/i_main.h; sourceTree = SOURCE_ROOT; }; + 72E8479B0F9400D700AB3C99 /* i_network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_network.h; path = ../prboom/i_network.h; sourceTree = SOURCE_ROOT; }; + 72E8479C0F9400D700AB3C99 /* i_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_sound.h; path = ../prboom/i_sound.h; sourceTree = SOURCE_ROOT; }; + 72E8479D0F9400D700AB3C99 /* i_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_system.h; path = ../prboom/i_system.h; sourceTree = SOURCE_ROOT; }; + 72E8479E0F9400D700AB3C99 /* i_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_video.h; path = ../prboom/i_video.h; sourceTree = SOURCE_ROOT; }; + 72E8479F0F9400D700AB3C99 /* info.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = info.c; path = ../prboom/info.c; sourceTree = SOURCE_ROOT; }; + 72E847A00F9400D700AB3C99 /* info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = info.h; path = ../prboom/info.h; sourceTree = SOURCE_ROOT; }; + 72E847A10F9400D700AB3C99 /* lprintf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lprintf.c; path = ../prboom/lprintf.c; sourceTree = SOURCE_ROOT; }; + 72E847A20F9400D700AB3C99 /* lprintf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lprintf.h; path = ../prboom/lprintf.h; sourceTree = SOURCE_ROOT; }; + 72E847A30F9400D700AB3C99 /* m_argv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_argv.c; path = ../prboom/m_argv.c; sourceTree = SOURCE_ROOT; }; + 72E847A40F9400D700AB3C99 /* m_argv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_argv.h; path = ../prboom/m_argv.h; sourceTree = SOURCE_ROOT; }; + 72E847A50F9400D700AB3C99 /* m_bbox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_bbox.c; path = ../prboom/m_bbox.c; sourceTree = SOURCE_ROOT; }; + 72E847A60F9400D700AB3C99 /* m_bbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_bbox.h; path = ../prboom/m_bbox.h; sourceTree = SOURCE_ROOT; }; + 72E847A70F9400D700AB3C99 /* m_cheat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_cheat.c; path = ../prboom/m_cheat.c; sourceTree = SOURCE_ROOT; }; + 72E847A80F9400D700AB3C99 /* m_cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_cheat.h; path = ../prboom/m_cheat.h; sourceTree = SOURCE_ROOT; }; + 72E847A90F9400D700AB3C99 /* m_fixed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_fixed.h; path = ../prboom/m_fixed.h; sourceTree = SOURCE_ROOT; }; + 72E847AA0F9400D700AB3C99 /* m_menu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_menu.c; path = ../prboom/m_menu.c; sourceTree = SOURCE_ROOT; }; + 72E847AB0F9400D700AB3C99 /* m_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_menu.h; path = ../prboom/m_menu.h; sourceTree = SOURCE_ROOT; }; + 72E847AC0F9400D700AB3C99 /* m_misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_misc.c; path = ../prboom/m_misc.c; sourceTree = SOURCE_ROOT; }; + 72E847AD0F9400D700AB3C99 /* m_misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_misc.h; path = ../prboom/m_misc.h; sourceTree = SOURCE_ROOT; }; + 72E847AE0F9400D700AB3C99 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_random.c; path = ../prboom/m_random.c; sourceTree = SOURCE_ROOT; }; + 72E847AF0F9400D700AB3C99 /* m_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_random.h; path = ../prboom/m_random.h; sourceTree = SOURCE_ROOT; }; + 72E847B00F9400D700AB3C99 /* m_swap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_swap.h; path = ../prboom/m_swap.h; sourceTree = SOURCE_ROOT; }; + 72E847CA0F94096C00AB3C99 /* SDL_opengl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengl.h; path = ../prboom/SDL_opengl.h; sourceTree = SOURCE_ROOT; }; + 72E847E00F941A5900AB3C99 /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.c; path = ../prboom/md5.c; sourceTree = SOURCE_ROOT; }; + 72E847E10F941A5900AB3C99 /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = md5.h; path = ../prboom/md5.h; sourceTree = SOURCE_ROOT; }; + 72E847E40F941A5900AB3C99 /* p_ceilng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_ceilng.c; path = ../prboom/p_ceilng.c; sourceTree = SOURCE_ROOT; }; + 72E847E50F941A5900AB3C99 /* p_checksum.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_checksum.c; path = ../prboom/p_checksum.c; sourceTree = SOURCE_ROOT; }; + 72E847E60F941A5900AB3C99 /* p_checksum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_checksum.h; path = ../prboom/p_checksum.h; sourceTree = SOURCE_ROOT; }; + 72E847E70F941A5900AB3C99 /* p_doors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_doors.c; path = ../prboom/p_doors.c; sourceTree = SOURCE_ROOT; }; + 72E847E80F941A5900AB3C99 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_enemy.c; path = ../prboom/p_enemy.c; sourceTree = SOURCE_ROOT; }; + 72E847E90F941A5900AB3C99 /* p_enemy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_enemy.h; path = ../prboom/p_enemy.h; sourceTree = SOURCE_ROOT; }; + 72E847EA0F941A5900AB3C99 /* p_floor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_floor.c; path = ../prboom/p_floor.c; sourceTree = SOURCE_ROOT; }; + 72E847EB0F941A5900AB3C99 /* p_genlin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_genlin.c; path = ../prboom/p_genlin.c; sourceTree = SOURCE_ROOT; }; + 72E847EC0F941A5900AB3C99 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_inter.c; path = ../prboom/p_inter.c; sourceTree = SOURCE_ROOT; }; + 72E847ED0F941A5900AB3C99 /* p_inter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_inter.h; path = ../prboom/p_inter.h; sourceTree = SOURCE_ROOT; }; + 72E847EE0F941A5900AB3C99 /* p_lights.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_lights.c; path = ../prboom/p_lights.c; sourceTree = SOURCE_ROOT; }; + 72E847EF0F941A5900AB3C99 /* p_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_map.c; path = ../prboom/p_map.c; sourceTree = SOURCE_ROOT; }; + 72E847F00F941A5900AB3C99 /* p_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_map.h; path = ../prboom/p_map.h; sourceTree = SOURCE_ROOT; }; + 72E847F10F941A5900AB3C99 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_maputl.c; path = ../prboom/p_maputl.c; sourceTree = SOURCE_ROOT; }; + 72E847F20F941A5900AB3C99 /* p_maputl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_maputl.h; path = ../prboom/p_maputl.h; sourceTree = SOURCE_ROOT; }; + 72E847F30F941A5900AB3C99 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_mobj.c; path = ../prboom/p_mobj.c; sourceTree = SOURCE_ROOT; }; + 72E847F40F941A5900AB3C99 /* p_mobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_mobj.h; path = ../prboom/p_mobj.h; sourceTree = SOURCE_ROOT; }; + 72E847F50F941A5900AB3C99 /* p_plats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_plats.c; path = ../prboom/p_plats.c; sourceTree = SOURCE_ROOT; }; + 72E847F60F941A5900AB3C99 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_pspr.c; path = ../prboom/p_pspr.c; sourceTree = SOURCE_ROOT; }; + 72E847F70F941A5900AB3C99 /* p_pspr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_pspr.h; path = ../prboom/p_pspr.h; sourceTree = SOURCE_ROOT; }; + 72E847F80F941A5900AB3C99 /* p_saveg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_saveg.c; path = ../prboom/p_saveg.c; sourceTree = SOURCE_ROOT; }; + 72E847F90F941A5900AB3C99 /* p_saveg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_saveg.h; path = ../prboom/p_saveg.h; sourceTree = SOURCE_ROOT; }; + 72E847FA0F941A5900AB3C99 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_setup.c; path = ../prboom/p_setup.c; sourceTree = SOURCE_ROOT; }; + 72E847FB0F941A5900AB3C99 /* p_setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_setup.h; path = ../prboom/p_setup.h; sourceTree = SOURCE_ROOT; }; + 72E847FC0F941A5900AB3C99 /* p_sight.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_sight.c; path = ../prboom/p_sight.c; sourceTree = SOURCE_ROOT; }; + 72E847FD0F941A5900AB3C99 /* p_spec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_spec.c; path = ../prboom/p_spec.c; sourceTree = SOURCE_ROOT; }; + 72E847FE0F941A5900AB3C99 /* p_spec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_spec.h; path = ../prboom/p_spec.h; sourceTree = SOURCE_ROOT; }; + 72E847FF0F941A5900AB3C99 /* p_switch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_switch.c; path = ../prboom/p_switch.c; sourceTree = SOURCE_ROOT; }; + 72E848000F941A5900AB3C99 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_telept.c; path = ../prboom/p_telept.c; sourceTree = SOURCE_ROOT; }; + 72E848010F941A5900AB3C99 /* p_tick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_tick.c; path = ../prboom/p_tick.c; sourceTree = SOURCE_ROOT; }; + 72E848020F941A5900AB3C99 /* p_tick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_tick.h; path = ../prboom/p_tick.h; sourceTree = SOURCE_ROOT; }; + 72E848030F941A5900AB3C99 /* p_user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_user.c; path = ../prboom/p_user.c; sourceTree = SOURCE_ROOT; }; + 72E848040F941A5900AB3C99 /* p_user.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_user.h; path = ../prboom/p_user.h; sourceTree = SOURCE_ROOT; }; + 72E8481C0F941A8300AB3C99 /* protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = protocol.h; path = ../prboom/protocol.h; sourceTree = SOURCE_ROOT; }; + 72E8481D0F941A8300AB3C99 /* r_bsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_bsp.c; path = ../prboom/r_bsp.c; sourceTree = SOURCE_ROOT; }; + 72E8481E0F941A8300AB3C99 /* r_bsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_bsp.h; path = ../prboom/r_bsp.h; sourceTree = SOURCE_ROOT; }; + 72E8481F0F941A8300AB3C99 /* r_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_data.c; path = ../prboom/r_data.c; sourceTree = SOURCE_ROOT; }; + 72E848200F941A8300AB3C99 /* r_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_data.h; path = ../prboom/r_data.h; sourceTree = SOURCE_ROOT; }; + 72E848210F941A8300AB3C99 /* r_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_defs.h; path = ../prboom/r_defs.h; sourceTree = SOURCE_ROOT; }; + 72E848220F941A8300AB3C99 /* r_demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_demo.c; path = ../prboom/r_demo.c; sourceTree = SOURCE_ROOT; }; + 72E848230F941A8300AB3C99 /* r_demo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_demo.h; path = ../prboom/r_demo.h; sourceTree = SOURCE_ROOT; }; + 72E848240F941A8300AB3C99 /* r_draw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_draw.c; path = ../prboom/r_draw.c; sourceTree = SOURCE_ROOT; }; + 72E848250F941A8300AB3C99 /* r_draw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_draw.h; path = ../prboom/r_draw.h; sourceTree = SOURCE_ROOT; }; + 72E8482A0F941AAC00AB3C99 /* r_filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_filter.c; path = ../prboom/r_filter.c; sourceTree = SOURCE_ROOT; }; + 72E8482B0F941AAC00AB3C99 /* r_filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_filter.h; path = ../prboom/r_filter.h; sourceTree = SOURCE_ROOT; }; + 72E8482C0F941AAC00AB3C99 /* r_fps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_fps.c; path = ../prboom/r_fps.c; sourceTree = SOURCE_ROOT; }; + 72E8482D0F941AAC00AB3C99 /* r_fps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_fps.h; path = ../prboom/r_fps.h; sourceTree = SOURCE_ROOT; }; + 72E8482E0F941AAC00AB3C99 /* r_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_main.c; path = ../prboom/r_main.c; sourceTree = SOURCE_ROOT; }; + 72E8482F0F941AAC00AB3C99 /* r_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_main.h; path = ../prboom/r_main.h; sourceTree = SOURCE_ROOT; }; + 72E848300F941AAC00AB3C99 /* r_patch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_patch.c; path = ../prboom/r_patch.c; sourceTree = SOURCE_ROOT; }; + 72E848310F941AAC00AB3C99 /* r_patch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_patch.h; path = ../prboom/r_patch.h; sourceTree = SOURCE_ROOT; }; + 72E848320F941AAC00AB3C99 /* r_plane.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_plane.c; path = ../prboom/r_plane.c; sourceTree = SOURCE_ROOT; }; + 72E848330F941AAC00AB3C99 /* r_plane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_plane.h; path = ../prboom/r_plane.h; sourceTree = SOURCE_ROOT; }; + 72E848340F941AAC00AB3C99 /* r_segs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_segs.c; path = ../prboom/r_segs.c; sourceTree = SOURCE_ROOT; }; + 72E848350F941AAC00AB3C99 /* r_segs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_segs.h; path = ../prboom/r_segs.h; sourceTree = SOURCE_ROOT; }; + 72E848360F941AAC00AB3C99 /* r_sky.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_sky.c; path = ../prboom/r_sky.c; sourceTree = SOURCE_ROOT; }; + 72E848370F941AAC00AB3C99 /* r_sky.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_sky.h; path = ../prboom/r_sky.h; sourceTree = SOURCE_ROOT; }; + 72E848380F941AAC00AB3C99 /* r_state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_state.h; path = ../prboom/r_state.h; sourceTree = SOURCE_ROOT; }; + 72E848390F941AAC00AB3C99 /* r_things.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_things.c; path = ../prboom/r_things.c; sourceTree = SOURCE_ROOT; }; + 72E8483A0F941AAC00AB3C99 /* r_things.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_things.h; path = ../prboom/r_things.h; sourceTree = SOURCE_ROOT; }; + 72E8483B0F941AAC00AB3C99 /* s_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = s_sound.c; path = ../prboom/s_sound.c; sourceTree = SOURCE_ROOT; }; + 72E8483C0F941AAC00AB3C99 /* s_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = s_sound.h; path = ../prboom/s_sound.h; sourceTree = SOURCE_ROOT; }; + 72E848460F941ADC00AB3C99 /* sounds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sounds.c; path = ../prboom/sounds.c; sourceTree = SOURCE_ROOT; }; + 72E848470F941ADC00AB3C99 /* sounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sounds.h; path = ../prboom/sounds.h; sourceTree = SOURCE_ROOT; }; + 72E848480F941ADC00AB3C99 /* st_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = st_lib.c; path = ../prboom/st_lib.c; sourceTree = SOURCE_ROOT; }; + 72E848490F941ADC00AB3C99 /* st_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = st_lib.h; path = ../prboom/st_lib.h; sourceTree = SOURCE_ROOT; }; + 72E8484A0F941ADC00AB3C99 /* st_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = st_stuff.c; path = ../prboom/st_stuff.c; sourceTree = SOURCE_ROOT; }; + 72E8484B0F941ADC00AB3C99 /* st_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = st_stuff.h; path = ../prboom/st_stuff.h; sourceTree = SOURCE_ROOT; }; + 72E8484C0F941ADC00AB3C99 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tables.c; path = ../prboom/tables.c; sourceTree = SOURCE_ROOT; }; + 72E8484D0F941ADC00AB3C99 /* tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tables.h; path = ../prboom/tables.h; sourceTree = SOURCE_ROOT; }; + 72E8484E0F941ADC00AB3C99 /* v_video.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = v_video.c; path = ../prboom/v_video.c; sourceTree = SOURCE_ROOT; }; + 72E8484F0F941ADC00AB3C99 /* v_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = v_video.h; path = ../prboom/v_video.h; sourceTree = SOURCE_ROOT; }; + 72E848500F941ADC00AB3C99 /* version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = version.c; path = ../prboom/version.c; sourceTree = SOURCE_ROOT; }; + 72E848510F941ADC00AB3C99 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = ../prboom/version.h; sourceTree = SOURCE_ROOT; }; + 72E848530F941ADC00AB3C99 /* w_mmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = w_mmap.c; path = ../prboom/w_mmap.c; sourceTree = SOURCE_ROOT; }; + 72E848540F941ADC00AB3C99 /* w_wad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = w_wad.c; path = ../prboom/w_wad.c; sourceTree = SOURCE_ROOT; }; + 72E848550F941ADC00AB3C99 /* w_wad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = w_wad.h; path = ../prboom/w_wad.h; sourceTree = SOURCE_ROOT; }; + 72E848560F941ADC00AB3C99 /* wi_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wi_stuff.c; path = ../prboom/wi_stuff.c; sourceTree = SOURCE_ROOT; }; + 72E848570F941ADC00AB3C99 /* wi_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wi_stuff.h; path = ../prboom/wi_stuff.h; sourceTree = SOURCE_ROOT; }; + 72E848580F941ADC00AB3C99 /* z_bmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = z_bmalloc.c; path = ../prboom/z_bmalloc.c; sourceTree = SOURCE_ROOT; }; + 72E848590F941ADC00AB3C99 /* z_bmalloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = z_bmalloc.h; path = ../prboom/z_bmalloc.h; sourceTree = SOURCE_ROOT; }; + 72E8485A0F941ADC00AB3C99 /* z_zone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = z_zone.c; path = ../prboom/z_zone.c; sourceTree = SOURCE_ROOT; }; + 72E8485B0F941ADC00AB3C99 /* z_zone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = z_zone.h; path = ../prboom/z_zone.h; sourceTree = SOURCE_ROOT; }; + 72E8495C0F942B9300AB3C99 /* cvar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cvar.c; sourceTree = ""; }; + 72E8495D0F942B9300AB3C99 /* cvar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cvar.h; sourceTree = ""; }; + 72E8495E0F942B9300AB3C99 /* misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = misc.c; sourceTree = ""; }; + 72E8495F0F942B9300AB3C99 /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = ""; }; + 72E849F50F94ED1100AB3C99 /* prboomInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prboomInterface.c; sourceTree = ""; }; + 72E84A280F9503F100AB3C99 /* cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmd.c; sourceTree = ""; }; + 72F1F99C0F96C18800AD49AC /* dict-list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "dict-list.h"; path = "../libtess/dict-list.h"; sourceTree = SOURCE_ROOT; }; + 72F1F99D0F96C18800AD49AC /* dict.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dict.c; path = ../libtess/dict.c; sourceTree = SOURCE_ROOT; }; + 72F1F99E0F96C18800AD49AC /* dict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dict.h; path = ../libtess/dict.h; sourceTree = SOURCE_ROOT; }; + 72F1F99F0F96C18800AD49AC /* geom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = geom.c; path = ../libtess/geom.c; sourceTree = SOURCE_ROOT; }; + 72F1F9A00F96C18800AD49AC /* geom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = geom.h; path = ../libtess/geom.h; sourceTree = SOURCE_ROOT; }; + 72F1F9A10F96C18800AD49AC /* memalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = memalloc.c; path = ../libtess/memalloc.c; sourceTree = SOURCE_ROOT; }; + 72F1F9A20F96C18800AD49AC /* memalloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memalloc.h; path = ../libtess/memalloc.h; sourceTree = SOURCE_ROOT; }; + 72F1F9A30F96C18800AD49AC /* mesh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mesh.c; path = ../libtess/mesh.c; sourceTree = SOURCE_ROOT; }; + 72F1F9A40F96C18800AD49AC /* mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mesh.h; path = ../libtess/mesh.h; sourceTree = SOURCE_ROOT; }; + 72F1F9A50F96C18800AD49AC /* normal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = normal.c; path = ../libtess/normal.c; sourceTree = SOURCE_ROOT; }; + 72F1F9A60F96C18800AD49AC /* normal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = normal.h; path = ../libtess/normal.h; sourceTree = SOURCE_ROOT; }; + 72F1F9A80F96C18800AD49AC /* priorityq-heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "priorityq-heap.h"; path = "../libtess/priorityq-heap.h"; sourceTree = SOURCE_ROOT; }; + 72F1F9A90F96C18800AD49AC /* priorityq-sort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "priorityq-sort.h"; path = "../libtess/priorityq-sort.h"; sourceTree = SOURCE_ROOT; }; + 72F1F9AA0F96C18800AD49AC /* priorityq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = priorityq.c; path = ../libtess/priorityq.c; sourceTree = SOURCE_ROOT; }; + 72F1F9AB0F96C18800AD49AC /* priorityq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = priorityq.h; path = ../libtess/priorityq.h; sourceTree = SOURCE_ROOT; }; + 72F1F9AC0F96C18800AD49AC /* render.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = render.c; path = ../libtess/render.c; sourceTree = SOURCE_ROOT; }; + 72F1F9AD0F96C18800AD49AC /* render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = render.h; path = ../libtess/render.h; sourceTree = SOURCE_ROOT; }; + 72F1F9AE0F96C18800AD49AC /* sweep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sweep.c; path = ../libtess/sweep.c; sourceTree = SOURCE_ROOT; }; + 72F1F9AF0F96C18800AD49AC /* sweep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sweep.h; path = ../libtess/sweep.h; sourceTree = SOURCE_ROOT; }; + 72F1F9B00F96C18800AD49AC /* tess.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tess.c; path = ../libtess/tess.c; sourceTree = SOURCE_ROOT; }; + 72F1F9B10F96C18800AD49AC /* tess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tess.h; path = ../libtess/tess.h; sourceTree = SOURCE_ROOT; }; + 72F1F9B20F96C18800AD49AC /* tessmono.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tessmono.c; path = ../libtess/tessmono.c; sourceTree = SOURCE_ROOT; }; + 72F1F9B30F96C18800AD49AC /* tessmono.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tessmono.h; path = ../libtess/tessmono.h; sourceTree = SOURCE_ROOT; }; + A10638C2216EBC5A00BDE196 /* doom2.wad */ = {isa = PBXFileReference; lastKnownFileType = file; name = doom2.wad; path = ../../base/doom2.wad; sourceTree = ""; }; + A10639D2216EF7C700BDE196 /* DOOM II.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DOOM II.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + A1063AEE216EFCEE00BDE196 /* FInal DOOM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "FInal DOOM.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + A1063AF0216EFD9800BDE196 /* tnt.wad */ = {isa = PBXFileReference; lastKnownFileType = file; name = tnt.wad; path = ../../base/tnt.wad; sourceTree = ""; }; + A1063AF1216EFD9800BDE196 /* plutonia.wad */ = {isa = PBXFileReference; lastKnownFileType = file; name = plutonia.wad; path = ../../base/plutonia.wad; sourceTree = ""; }; + A1063C01216F012000BDE196 /* Final DOOM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Final DOOM.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + A1063C03216F030900BDE196 /* FinalDOOM-tvOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FinalDOOM-tvOS-Info.plist"; sourceTree = SOURCE_ROOT; }; + A1063C04216F030900BDE196 /* DOOM-tvOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DOOM-tvOS-Info.plist"; sourceTree = SOURCE_ROOT; }; + A1063C05216F030900BDE196 /* DOOM2-tvOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DOOM2-tvOS-Info.plist"; sourceTree = SOURCE_ROOT; }; + A1063C06216F032300BDE196 /* DOOM-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DOOM-iOS-Info.plist"; sourceTree = ""; }; + A1063C07216F032300BDE196 /* DOOM2-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DOOM2-iOS-Info.plist"; sourceTree = ""; }; + A1063C08216F032300BDE196 /* FinalDOOM-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FinalDOOM-iOS-Info.plist"; sourceTree = ""; }; + A112904F2069B62B00BEDEB5 /* DOOMLaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = DOOMLaunchScreen.storyboard; sourceTree = ""; }; + A12302D5205737F40075CBAD /* LocalizationObjectiveC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LocalizationObjectiveC.h; path = ../ios/LocalizationObjectiveC.h; sourceTree = ""; }; + A12302D6205737F40075CBAD /* Label.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Label.mm; path = ../ios/Label.mm; sourceTree = ""; }; + A12302D7205737F40075CBAD /* LabelButton.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = LabelButton.mm; path = ../ios/LabelButton.mm; sourceTree = ""; }; + A12302D8205737F40075CBAD /* RenderContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RenderContext.h; path = ../ios/RenderContext.h; sourceTree = ""; }; + A12302D9205737F40075CBAD /* Localization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Localization.h; path = ../ios/Localization.h; sourceTree = ""; }; + A12302DA205737F40075CBAD /* RenderContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RenderContext.mm; path = ../ios/RenderContext.mm; sourceTree = ""; }; + A12302DB205737F40075CBAD /* Switch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Switch.h; path = ../ios/Switch.h; sourceTree = ""; }; + A12302DC205737F40075CBAD /* View.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = View.mm; path = ../ios/View.mm; sourceTree = ""; }; + A12302DD205737F40075CBAD /* LabelButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LabelButton.h; path = ../ios/LabelButton.h; sourceTree = ""; }; + A12302DE205737F40075CBAD /* Localization.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Localization.mm; path = ../ios/Localization.mm; sourceTree = ""; }; + A12302DF205737F50075CBAD /* Label.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Label.h; path = ../ios/Label.h; sourceTree = ""; }; + A12302E0205737F50075CBAD /* View.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = View.h; path = ../ios/View.h; sourceTree = ""; }; + A12302E1205737F50075CBAD /* Switch.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Switch.mm; path = ../ios/Switch.mm; sourceTree = ""; }; + A12302EF205738270075CBAD /* Slider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Slider.h; path = ../ios/Slider.h; sourceTree = ""; }; + A12302F0205738270075CBAD /* Slider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Slider.mm; path = ../ios/Slider.mm; sourceTree = ""; }; + A12302F3205738560075CBAD /* Carousel.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Carousel.mm; path = ../ios/Carousel.mm; sourceTree = ""; }; + A12302F4205738560075CBAD /* Carousel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Carousel.h; path = ../ios/Carousel.h; sourceTree = ""; }; + A12302F8205783E70075CBAD /* prboom.wad */ = {isa = PBXFileReference; lastKnownFileType = file; name = prboom.wad; path = ../../base/prboom.wad; sourceTree = ""; }; + A12302F9205783E70075CBAD /* doom.wad */ = {isa = PBXFileReference; lastKnownFileType = file; name = doom.wad; path = ../../base/doom.wad; sourceTree = ""; }; + A12302FA205783E70075CBAD /* base.iPack */ = {isa = PBXFileReference; lastKnownFileType = file; name = base.iPack; path = ../../base/base.iPack; sourceTree = ""; }; + A176AC08206492DD00A96B7E /* EpisodeCell~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "EpisodeCell~ipad.xib"; sourceTree = ""; }; + A187091F216EB633006C013F /* DOOM II.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DOOM II.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + A1A184252063E63200302393 /* EpisodeCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EpisodeCell.xib; sourceTree = ""; }; + A1A63DB320562B2A000955AE /* SecretMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecretMenuViewController.h; sourceTree = ""; }; + A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ControlsMenuViewController.mm; sourceTree = ""; }; + A1A63DB620562B2B000955AE /* ControlsMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ControlsMenuView.xib; sourceTree = ""; }; + A1A63DB720562B2B000955AE /* SecretMenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SecretMenuViewController.mm; sourceTree = ""; }; + A1A63DB820562B2B000955AE /* ControlsMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlsMenuViewController.h; sourceTree = ""; }; + A1A63DBA20562B2B000955AE /* CreditsMenuView~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "CreditsMenuView~ipad.xib"; sourceTree = ""; }; + A1A63DBB20562B2B000955AE /* ControlsMenuView~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "ControlsMenuView~ipad.xib"; sourceTree = ""; }; + A1A63DBC20562B2B000955AE /* SecretMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SecretMenuView.xib; sourceTree = ""; }; + A1A63DC520562B72000955AE /* SettingsMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsMenuViewController.h; sourceTree = ""; }; + A1A63DC620562B73000955AE /* MissionMenuView~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "MissionMenuView~ipad.xib"; sourceTree = ""; }; + A1A63DC720562B73000955AE /* LegalMenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LegalMenuViewController.mm; sourceTree = ""; }; + A1A63DC920562B73000955AE /* SettingsMenuView~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "SettingsMenuView~ipad.xib"; sourceTree = ""; }; + A1A63DCA20562B73000955AE /* EpisodeMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EpisodeMenuView.xib; sourceTree = ""; }; + A1A63DCB20562B73000955AE /* LegalMenuView~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "LegalMenuView~ipad.xib"; sourceTree = ""; }; + A1A63DCC20562B73000955AE /* MissionMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MissionMenuView.xib; sourceTree = ""; }; + A1A63DCE20562B73000955AE /* MainMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenuView.xib; sourceTree = ""; }; + A1A63DD020562B74000955AE /* MissionMenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MissionMenuViewController.mm; sourceTree = ""; }; + A1A63DD220562B74000955AE /* OpenGLView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OpenGLView.xib; sourceTree = ""; }; + A1A63DD420562B74000955AE /* LegalMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegalMenuViewController.h; sourceTree = ""; }; + A1A63DD620562B74000955AE /* SettingsMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsMenuView.xib; sourceTree = ""; }; + A1A63DD720562B75000955AE /* MainNavController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainNavController.h; sourceTree = ""; }; + A1A63DD820562B75000955AE /* MainMenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MainMenuViewController.mm; sourceTree = ""; }; + A1A63DD920562B75000955AE /* MainMenuView~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "MainMenuView~ipad.xib"; sourceTree = ""; }; + A1A63DDA20562B75000955AE /* EpisodeMenuView~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "EpisodeMenuView~ipad.xib"; sourceTree = ""; }; + A1A63DDB20562B75000955AE /* EpisodeMenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EpisodeMenuViewController.mm; sourceTree = ""; }; + A1A63DDC20562B75000955AE /* MainNavController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainNavController.m; sourceTree = ""; }; + A1A63DDD20562B75000955AE /* MissionMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MissionMenuViewController.h; sourceTree = ""; }; + A1A63DDE20562B75000955AE /* MainMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainMenuViewController.h; sourceTree = ""; }; + A1A63DDF20562B76000955AE /* EpisodeMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EpisodeMenuViewController.h; sourceTree = ""; }; + A1A63DE020562B76000955AE /* LegalMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LegalMenuView.xib; sourceTree = ""; }; + A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SettingsMenuViewController.mm; sourceTree = ""; }; + A1A63DE220562B76000955AE /* OpenGLView~ipad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "OpenGLView~ipad.xib"; sourceTree = ""; }; + A1A63DFB20562FAE000955AE /* SoundEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SoundEngine.h; sourceTree = ""; }; + A1A63DFC20562FAE000955AE /* iphone_wolf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_wolf.h; sourceTree = ""; }; + A1A63DFD20562FAE000955AE /* iphone_delegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_delegate.h; sourceTree = ""; }; + A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iphone_glViewController.mm; sourceTree = ""; }; + A1A63DFF20562FAE000955AE /* iphone_qgl_enumerants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_qgl_enumerants.h; sourceTree = ""; }; + A1A63E0020562FAE000955AE /* iphone_async.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iphone_async.cpp; sourceTree = ""; }; + A1A63E0120562FAE000955AE /* iphone_qgl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_qgl.h; sourceTree = ""; }; + A1A63E0220562FAE000955AE /* iphone_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_common.h; sourceTree = ""; }; + A1A63E0320562FAF000955AE /* iphone_delegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iphone_delegate.mm; sourceTree = ""; }; + A1A63E0420562FAF000955AE /* iphone_glViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_glViewController.h; sourceTree = ""; }; + A1A63E0520562FAF000955AE /* iphone_start.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iphone_start.cpp; sourceTree = ""; }; + A1A63E0620562FAF000955AE /* iphone_common.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iphone_common.mm; sourceTree = ""; }; + A1A63E0720562FAF000955AE /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; }; + A1A63E0820562FAF000955AE /* SoundEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SoundEngine.cpp; sourceTree = ""; }; + A1A63E0920562FAF000955AE /* iphone_sound.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iphone_sound.mm; sourceTree = ""; }; + A1A63E0A20562FAF000955AE /* iphone_sys.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iphone_sys.mm; sourceTree = ""; }; + A1A63E0B20562FB0000955AE /* arialGlyphRects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arialGlyphRects.h; sourceTree = ""; }; + A1A63E1520562FC3000955AE /* DOOM_152.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_152.png; sourceTree = ""; }; + A1A63E1620562FC3000955AE /* DOOM_144.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_144.png; sourceTree = ""; }; + A1A63E1720562FC3000955AE /* DOOM_120.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_120.png; sourceTree = ""; }; + A1A63E1820562FC4000955AE /* DOOM_76.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_76.png; sourceTree = ""; }; + A1A63E1D20562FD1000955AE /* Doom_App.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Doom_App.m; sourceTree = ""; }; + A1A63E1E20562FD1000955AE /* Doom_App.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Doom_App.h; sourceTree = ""; }; + A1A63E2320563253000955AE /* i_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = i_sound.c; sourceTree = ""; }; + A1A63E27205632E2000955AE /* SDL_Mixer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_Mixer.m; sourceTree = ""; }; + A1A63E28205632E2000955AE /* SDL_Mixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_Mixer.h; sourceTree = ""; }; + A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = r_drawcolpipeline.inl; path = ../prboom/r_drawcolpipeline.inl; sourceTree = ""; }; + A1A63E2B20563344000955AE /* mmus2mid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mmus2mid.c; path = ../prboom/mmus2mid.c; sourceTree = ""; }; + A1A63E2C20563344000955AE /* mmus2mid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mmus2mid.h; path = ../prboom/mmus2mid.h; sourceTree = ""; }; + A1A63E2D20563344000955AE /* r_drawcolumn.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = r_drawcolumn.inl; path = ../prboom/r_drawcolumn.inl; sourceTree = ""; }; + A1A63E2E20563345000955AE /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Makefile.am; path = ../prboom/Makefile.am; sourceTree = ""; }; + A1A63E3020563345000955AE /* r_drawflush.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = r_drawflush.inl; path = ../prboom/r_drawflush.inl; sourceTree = ""; }; + A1A63E3120563345000955AE /* r_drawspan.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = r_drawspan.inl; path = ../prboom/r_drawspan.inl; sourceTree = ""; }; + A1A63E3E205634E7000955AE /* eas_reverb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_reverb.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_reverb.h"; sourceTree = ""; }; + A1A63E3F205634E7000955AE /* eas_debugmsgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_debugmsgs.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_debugmsgs.h"; sourceTree = ""; }; + A1A63E40205634E7000955AE /* eas_report.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_report.c; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_report.c"; sourceTree = ""; }; + A1A63E41205634E7000955AE /* eas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas.h"; sourceTree = ""; }; + A1A63E42205634E7000955AE /* eas_hostmm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_hostmm.c; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_hostmm.c"; sourceTree = ""; }; + A1A63E43205634E7000955AE /* eas_chorus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_chorus.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_chorus.h"; sourceTree = ""; }; + A1A63E44205634E7000955AE /* eas_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_types.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_types.h"; sourceTree = ""; }; + A1A63E45205634E7000955AE /* eas_build.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_build.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_build.h"; sourceTree = ""; }; + A1A63E46205634E7000955AE /* eas_host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_host.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_host.h"; sourceTree = ""; }; + A1A63E47205634E7000955AE /* eas_report.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_report.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_report.h"; sourceTree = ""; }; + A1A63E48205634E7000955AE /* eas_wave.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_wave.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_wave.h"; sourceTree = ""; }; + A1A63E49205634E7000955AE /* jet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jet.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/jet.h"; sourceTree = ""; }; + A1A63E4A205634E7000955AE /* eas_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_config.h; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_config.h"; sourceTree = ""; }; + A1A63E4B205634E7000955AE /* eas_config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_config.c; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_config.c"; sourceTree = ""; }; + A1A63E4C205634E7000955AE /* eas_wave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wave.c; path = "../embeddedaudiosynthesis/arm-wt-22k/host_src/eas_wave.c"; sourceTree = ""; }; + A1A63E5120563A06000955AE /* EASGlue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = EASGlue.c; path = ../embeddedaudiosynthesis/EASGlue.c; sourceTree = ""; }; + A1A63E5220563A06000955AE /* EASGlue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EASGlue.h; path = ../embeddedaudiosynthesis/EASGlue.h; sourceTree = ""; }; + A1A63E5420563A6D000955AE /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + A1A63EC820563B53000955AE /* eas_synth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_synth.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synth.h"; sourceTree = ""; }; + A1A63EC920563B53000955AE /* eas_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_data.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_data.h"; sourceTree = ""; }; + A1A63ECA20563B53000955AE /* eas_xmfdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_xmfdata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmfdata.c"; sourceTree = ""; }; + A1A63ECB20563B53000955AE /* eas_xmf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_xmf.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmf.c"; sourceTree = ""; }; + A1A63ECC20563B53000955AE /* dls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dls.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/dls.h"; sourceTree = ""; }; + A1A63ECD20563B53000955AE /* eas_rtttldata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_rtttldata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttldata.h"; sourceTree = ""; }; + A1A63ECE20563B53000955AE /* eas_otadata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_otadata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_otadata.c"; sourceTree = ""; }; + A1A63ECF20563B53000955AE /* eas_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_data.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_data.c"; sourceTree = ""; }; + A1A63ED020563B54000955AE /* eas_imaadpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_imaadpcm.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imaadpcm.c"; sourceTree = ""; }; + A1A63ED120563B54000955AE /* eas_rtttl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_rtttl.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttl.c"; sourceTree = ""; }; + A1A63ED220563B54000955AE /* eas_smfdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_smfdata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smfdata.h"; sourceTree = ""; }; + A1A63ED320563B54000955AE /* eas_midi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_midi.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midi.h"; sourceTree = ""; }; + A1A63ED420563B54000955AE /* eas_tcdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_tcdata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tcdata.h"; sourceTree = ""; }; + A1A63ED520563B54000955AE /* eas_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_parser.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_parser.h"; sourceTree = ""; }; + A1A63ED620563B54000955AE /* eas_wavefile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wavefile.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefile.c"; sourceTree = ""; }; + A1A63ED720563B54000955AE /* eas_mixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_mixer.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixer.c"; sourceTree = ""; }; + A1A63ED820563B54000955AE /* eas_ota.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_ota.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ota.c"; sourceTree = ""; }; + A1A63ED920563B54000955AE /* eas_pan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_pan.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pan.h"; sourceTree = ""; }; + A1A63EDA20563B54000955AE /* eas_pcmdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_pcmdata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcmdata.c"; sourceTree = ""; }; + A1A63EDB20563B55000955AE /* eas_xmfdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_xmfdata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmfdata.h"; sourceTree = ""; }; + A1A63EDC20563B55000955AE /* eas_chorusdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_chorusdata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorusdata.c"; sourceTree = ""; }; + A1A63EDD20563B55000955AE /* eas_mdls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_mdls.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mdls.h"; sourceTree = ""; }; + A1A63EDE20563B55000955AE /* eas_audioconst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_audioconst.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_audioconst.h"; sourceTree = ""; }; + A1A63EDF20563B55000955AE /* eas_synthcfg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_synthcfg.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synthcfg.h"; sourceTree = ""; }; + A1A63EE020563B55000955AE /* eas_wt_IPC_frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_wt_IPC_frame.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wt_IPC_frame.h"; sourceTree = ""; }; + A1A63EE120563B55000955AE /* eas_chorus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_chorus.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorus.c"; sourceTree = ""; }; + A1A63EE220563B56000955AE /* eas_chorusdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_chorusdata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_chorusdata.h"; sourceTree = ""; }; + A1A63EE320563B56000955AE /* eas_midi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_midi.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midi.c"; sourceTree = ""; }; + A1A63EE420563B56000955AE /* wt_22khz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wt_22khz.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/wt_22khz.c"; sourceTree = ""; }; + A1A63EE520563B56000955AE /* eas_smfdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_smfdata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smfdata.c"; sourceTree = ""; }; + A1A63EE620563B58000955AE /* eas_pcmdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_pcmdata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcmdata.h"; sourceTree = ""; }; + A1A63EE720563B58000955AE /* eas_wtengine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_wtengine.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtengine.h"; sourceTree = ""; }; + A1A63EE820563B58000955AE /* eas_wtsynth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wtsynth.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtsynth.c"; sourceTree = ""; }; + A1A63EE920563B59000955AE /* jet_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jet_data.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/jet_data.h"; sourceTree = ""; }; + A1A63EEA20563B59000955AE /* eas_xmf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_xmf.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_xmf.h"; sourceTree = ""; }; + A1A63EEB20563B59000955AE /* jet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = jet.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/jet.c"; sourceTree = ""; }; + A1A63EEC20563B59000955AE /* eas_mixbuf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_mixbuf.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixbuf.c"; sourceTree = ""; }; + A1A63EED20563B59000955AE /* eas_smf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_smf.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smf.c"; sourceTree = ""; }; + A1A63EEE20563B59000955AE /* eas_math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_math.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_math.h"; sourceTree = ""; }; + A1A63EEF20563B59000955AE /* eas_dlssynth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_dlssynth.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_dlssynth.c"; sourceTree = ""; }; + A1A63EF020563B5A000955AE /* eas_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_pcm.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcm.c"; sourceTree = ""; }; + A1A63EF120563B5A000955AE /* eas_mixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_mixer.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mixer.h"; sourceTree = ""; }; + A1A63EF220563B5A000955AE /* eas_dlssynth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_dlssynth.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_dlssynth.h"; sourceTree = ""; }; + A1A63EF320563B5A000955AE /* eas_synth_protos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_synth_protos.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_synth_protos.h"; sourceTree = ""; }; + A1A63EF420563B5A000955AE /* eas_wtsynth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_wtsynth.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtsynth.h"; sourceTree = ""; }; + A1A63EF520563B5A000955AE /* eas_sndlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_sndlib.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_sndlib.h"; sourceTree = ""; }; + A1A63EF620563B5B000955AE /* eas_reverbdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_reverbdata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverbdata.h"; sourceTree = ""; }; + A1A63EF720563B5B000955AE /* eas_tonecontrol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_tonecontrol.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tonecontrol.c"; sourceTree = ""; }; + A1A63EF820563B5B000955AE /* eas_imelodydata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_imelodydata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelodydata.h"; sourceTree = ""; }; + A1A63EF920563B5B000955AE /* eas_wavefiledata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wavefiledata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefiledata.c"; sourceTree = ""; }; + A1A63EFA20563B5B000955AE /* eas_wtengine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_wtengine.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wtengine.c"; sourceTree = ""; }; + A1A63EFB20563B5B000955AE /* eas_vm_protos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_vm_protos.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_vm_protos.h"; sourceTree = ""; }; + A1A63EFC20563B5C000955AE /* eas_imelodydata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_imelodydata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelodydata.c"; sourceTree = ""; }; + A1A63EFD20563B5C000955AE /* eas_mididata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_mididata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mididata.c"; sourceTree = ""; }; + A1A63EFE20563B5C000955AE /* eas_midictrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_midictrl.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_midictrl.h"; sourceTree = ""; }; + A1A63EFF20563B5C000955AE /* eas_rtttldata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_rtttldata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_rtttldata.c"; sourceTree = ""; }; + A1A63F0020563B5C000955AE /* eas_ctype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_ctype.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ctype.h"; sourceTree = ""; }; + A1A63F0120563B5C000955AE /* eas_wavefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_wavefile.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_wavefile.h"; sourceTree = ""; }; + A1A63F0220563B5C000955AE /* eas_flog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_flog.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_flog.c"; sourceTree = ""; }; + A1A63F0320563B5D000955AE /* eas_pcm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_pcm.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pcm.h"; sourceTree = ""; }; + A1A63F0420563B5D000955AE /* eas_reverbdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_reverbdata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverbdata.c"; sourceTree = ""; }; + A1A63F0520563B5D000955AE /* eas_public.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_public.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_public.c"; sourceTree = ""; }; + A1A63F0620563B5D000955AE /* eas_ima_tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_ima_tables.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_ima_tables.c"; sourceTree = ""; }; + A1A63F0720563B5E000955AE /* dls2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dls2.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/dls2.h"; sourceTree = ""; }; + A1A63F0820563B5E000955AE /* eas_effects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_effects.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_effects.h"; sourceTree = ""; }; + A1A63F0920563B5E000955AE /* eas_smf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_smf.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_smf.h"; sourceTree = ""; }; + A1A63F0A20563B5E000955AE /* eas_otadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_otadata.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_otadata.h"; sourceTree = ""; }; + A1A63F0B20563B5E000955AE /* eas_voicemgt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_voicemgt.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_voicemgt.c"; sourceTree = ""; }; + A1A63F0C20563B5F000955AE /* eas_imelody.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_imelody.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_imelody.c"; sourceTree = ""; }; + A1A63F0D20563B5F000955AE /* eas_pan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_pan.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_pan.c"; sourceTree = ""; }; + A1A63F0E20563B5F000955AE /* eas_reverb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_reverb.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_reverb.c"; sourceTree = ""; }; + A1A63F0F20563B5F000955AE /* eas_tcdata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_tcdata.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_tcdata.c"; sourceTree = ""; }; + A1A63F1020563B5F000955AE /* eas_math.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_math.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_math.c"; sourceTree = ""; }; + A1A63F1120563B60000955AE /* eas_miditypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eas_miditypes.h; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_miditypes.h"; sourceTree = ""; }; + A1A63F1220563B60000955AE /* eas_mdls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = eas_mdls.c; path = "../embeddedaudiosynthesis/arm-wt-22k/lib_src/eas_mdls.c"; sourceTree = ""; }; + A1B98DEA207EFEE800827A46 /* DOOM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DOOM.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A1B98E01207EFF8A00827A46 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E02207EFF8A00827A46 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/AudioToolbox.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E03207EFF8A00827A46 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E04207EFF8A00827A46 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/GameKit.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E05207EFF8A00827A46 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E06207EFF8A00827A46 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E07207EFF8A00827A46 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E08207EFF8B00827A46 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E09207EFF8B00827A46 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/OpenAL.framework; sourceTree = DEVELOPER_DIR; }; + A1B98E15207F016500827A46 /* MainMenuView-tvos.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "MainMenuView-tvos.xib"; sourceTree = ""; }; + A1B98E16207F016500827A46 /* LegalMenuView-tvos.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "LegalMenuView-tvos.xib"; sourceTree = ""; }; + A1B98E17207F016500827A46 /* ControlsMenuView-tvos.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "ControlsMenuView-tvos.xib"; sourceTree = ""; }; + A1B98E18207F016500827A46 /* OpenGLView-tvos.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "OpenGLView-tvos.xib"; sourceTree = ""; }; + A1B98E19207F016500827A46 /* SettingsMenuView-tvos.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "SettingsMenuView-tvos.xib"; sourceTree = ""; }; + A1B98E1A207F016600827A46 /* EpisodeMenuView-tvos.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "EpisodeMenuView-tvos.xib"; sourceTree = ""; }; + A1B98E1B207F016600827A46 /* MissionMenuView-tvos.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "MissionMenuView-tvos.xib"; sourceTree = ""; }; + A1B98E1C207F016600827A46 /* CreditsMenuView-tvos.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "CreditsMenuView-tvos.xib"; sourceTree = ""; }; + A1B9E45C21700601003E9731 /* DOOM-iOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "DOOM-iOS.xcassets"; sourceTree = ""; }; + A1B9E45E217006D2003E9731 /* DOOM2-iOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "DOOM2-iOS.xcassets"; sourceTree = ""; }; + A1B9E4602170078A003E9731 /* FinalDOOM-iOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "FinalDOOM-iOS.xcassets"; sourceTree = ""; }; + A1D39932217144A800FD11C3 /* FinalDOOMLaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = FinalDOOMLaunchScreen.storyboard; sourceTree = ""; }; + A1D399352171462F00FD11C3 /* DOOM2LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = DOOM2LaunchScreen.storyboard; sourceTree = ""; }; + A1D399372171A08C00FD11C3 /* DOOM-tvOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "DOOM-tvOS.xcassets"; sourceTree = ""; }; + A1D399392171A0A800FD11C3 /* DOOM2-tvOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "DOOM2-tvOS.xcassets"; sourceTree = ""; }; + A1D3993C2171A0FD00FD11C3 /* FinalDOOM-tvOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "FinalDOOM-tvOS.xcassets"; sourceTree = ""; }; + A1DE85B8229F60BE0041E450 /* SIGIL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SIGIL.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A1DE85B9229F60BE0041E450 /* SIGIL-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "SIGIL-iOS-Info.plist"; path = "/Users/tomkidd/Documents/GitHub/DOOM-iOS/code/iphone/SIGIL-iOS-Info.plist"; sourceTree = ""; }; + A1DE85BA229F610B0041E450 /* SIGIL_SHREDS.wad */ = {isa = PBXFileReference; lastKnownFileType = file; name = SIGIL_SHREDS.wad; path = ../../base/SIGIL_SHREDS.wad; sourceTree = ""; }; + A1DE85BB229F610B0041E450 /* SIGIL.wad */ = {isa = PBXFileReference; lastKnownFileType = file; name = SIGIL.wad; path = ../../base/SIGIL.wad; sourceTree = ""; }; + A1DE85C2229F73950041E450 /* SIGIL-iOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "SIGIL-iOS.xcassets"; sourceTree = ""; }; + A1DE85C6229F874F0041E450 /* SIGILLaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = SIGILLaunchScreen.storyboard; sourceTree = ""; }; + A1DE86D4229F88D20041E450 /* SIGL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SIGL.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A1DE86D5229F88D20041E450 /* SIGIL-tvOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "SIGIL-tvOS-Info.plist"; path = "/Users/tomkidd/Documents/GitHub/DOOM-iOS/code/iphone/SIGIL-tvOS-Info.plist"; sourceTree = ""; }; + A1DE86D8229F8B090041E450 /* SIGIL-tvOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "SIGIL-tvOS.xcassets"; sourceTree = ""; }; + A1E89C8B2067469D00760204 /* CreditsMenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CreditsMenuViewController.h; sourceTree = ""; }; + A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CreditsMenuViewController.mm; sourceTree = ""; }; + A1E89C8D2067469D00760204 /* CreditsMenuView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CreditsMenuView.xib; sourceTree = ""; }; + A1E89C9320689D4B00760204 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; + A1E89C9520689D9500760204 /* GameController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GameController.mm; sourceTree = ""; }; + A1E89C9720689DB100760204 /* GameController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameController.h; sourceTree = ""; }; + A1EA3B84207F1D310038650E /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS11.3.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; }; + A1EA3B86207F9DE20038650E /* DOOM_400.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_400.png; sourceTree = ""; }; + A1EA3B8F208020B60038650E /* EpisodeCell-tvos.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = "EpisodeCell-tvos.xib"; sourceTree = ""; }; + C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "SliderSkull@2x.png"; path = "../../IB Images/SliderSkull@2x.png"; sourceTree = SOURCE_ROOT; }; + C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "SliderSkull~ipad.png"; path = "../../IB Images/SliderSkull~ipad.png"; sourceTree = SOURCE_ROOT; }; + C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "idGinzaNar-Md2.otf"; path = "../../idGinzaNar-Md2.otf"; sourceTree = SOURCE_ROOT; }; + C81E104013E1CCA000B1049A /* BackButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = BackButton.png; path = "../../IB Images/BackButton.png"; sourceTree = SOURCE_ROOT; }; + C81E104113E1CCA000B1049A /* Button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Button.png; path = "../../IB Images/Button.png"; sourceTree = SOURCE_ROOT; }; + C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DOOM_sigil_decal.png; path = "../../IB Images/DOOM_sigil_decal.png"; sourceTree = SOURCE_ROOT; }; + C81E104313E1CCA000B1049A /* DoomLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DoomLogo.png; path = "../../IB Images/DoomLogo.png"; sourceTree = SOURCE_ROOT; }; + C81E104413E1CCA000B1049A /* Easy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Easy.png; path = "../../IB Images/Easy.png"; sourceTree = SOURCE_ROOT; }; + C81E104513E1CCA000B1049A /* Hard.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Hard.png; path = "../../IB Images/Hard.png"; sourceTree = SOURCE_ROOT; }; + C81E104613E1CCA000B1049A /* MapOverlay.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = MapOverlay.png; path = "../../IB Images/MapOverlay.png"; sourceTree = SOURCE_ROOT; }; + C81E104713E1CCA000B1049A /* Medium.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Medium.png; path = "../../IB Images/Medium.png"; sourceTree = SOURCE_ROOT; }; + C81E104813E1CCA000B1049A /* MenuBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = MenuBackground.png; path = "../../IB Images/MenuBackground.png"; sourceTree = SOURCE_ROOT; }; + C81E104913E1CCA000B1049A /* Nightmare.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Nightmare.png; path = "../../IB Images/Nightmare.png"; sourceTree = SOURCE_ROOT; }; + C81E104A13E1CCA000B1049A /* ResumeButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ResumeButton.png; path = "../../IB Images/ResumeButton.png"; sourceTree = SOURCE_ROOT; }; + C81E104B13E1CCA000B1049A /* SelectedBracket.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SelectedBracket.png; path = "../../IB Images/SelectedBracket.png"; sourceTree = SOURCE_ROOT; }; + C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = BackButton_Highlighted.png; path = "../../IB Images/BackButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C8792ED213F5AFE5003D834F /* Button_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Button_Highlighted.png; path = "../../IB Images/Button_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = NextButton_Highlighted.png; path = "../../IB Images/NextButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C8792ED413F5AFE5003D834F /* NextButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = NextButton.png; path = "../../IB Images/NextButton.png"; sourceTree = SOURCE_ROOT; }; + C8792ED513F5AFE5003D834F /* SubMenuBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SubMenuBackground.png; path = "../../IB Images/SubMenuBackground.png"; sourceTree = SOURCE_ROOT; }; + C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SubMenuButton_Highlighted.png; path = "../../IB Images/SubMenuButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C8792ED713F5AFE5003D834F /* SubMenuButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SubMenuButton.png; path = "../../IB Images/SubMenuButton.png"; sourceTree = SOURCE_ROOT; }; + C879308513F5D8AA003D834F /* DifficultyBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DifficultyBackground.png; path = "../../IB Images/DifficultyBackground.png"; sourceTree = SOURCE_ROOT; }; + C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DownArrow_Highlighted.png; path = "../../IB Images/DownArrow_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C879308713F5D8AA003D834F /* DownArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DownArrow.png; path = "../../IB Images/DownArrow.png"; sourceTree = SOURCE_ROOT; }; + C879308813F5D8AA003D834F /* Episode1Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode1Background.png; path = "../../IB Images/Episode1Background.png"; sourceTree = SOURCE_ROOT; }; + C879308913F5D8AA003D834F /* Episode2Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode2Background.png; path = "../../IB Images/Episode2Background.png"; sourceTree = SOURCE_ROOT; }; + C879308A13F5D8AA003D834F /* Episode3Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode3Background.png; path = "../../IB Images/Episode3Background.png"; sourceTree = SOURCE_ROOT; }; + C879308B13F5D8AA003D834F /* Episode4Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode4Background.png; path = "../../IB Images/Episode4Background.png"; sourceTree = SOURCE_ROOT; }; + C879308C13F5D8AA003D834F /* MissonBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = MissonBackground.png; path = "../../IB Images/MissonBackground.png"; sourceTree = SOURCE_ROOT; }; + C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = UpArrow_Highlighted.png; path = "../../IB Images/UpArrow_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C879308E13F5D8AA003D834F /* UpArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = UpArrow.png; path = "../../IB Images/UpArrow.png"; sourceTree = SOURCE_ROOT; }; + C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode1Background_Highlighted.png; path = "../../IB Images/Episode1Background_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode2Background_Highlighted.png; path = "../../IB Images/Episode2Background_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode3Background_Highlighted.png; path = "../../IB Images/Episode3Background_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode4Background_Highlighted.png; path = "../../IB Images/Episode4Background_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = AdvancedButton_Highlighted.png; path = "../../IB Images/AdvancedButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87931DF13F610B9003D834F /* AdvancedButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = AdvancedButton.png; path = "../../IB Images/AdvancedButton.png"; sourceTree = SOURCE_ROOT; }; + C87931E013F610B9003D834F /* Divide.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Divide.png; path = "../../IB Images/Divide.png"; sourceTree = SOURCE_ROOT; }; + C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutDualButton_Highlighted.png; path = "../../IB Images/LayoutDualButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87931E213F610B9003D834F /* LayoutDualButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutDualButton.png; path = "../../IB Images/LayoutDualButton.png"; sourceTree = SOURCE_ROOT; }; + C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutSingleButton_Highlighted.png; path = "../../IB Images/LayoutSingleButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87931E413F610B9003D834F /* LayoutSingleButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutSingleButton.png; path = "../../IB Images/LayoutSingleButton.png"; sourceTree = SOURCE_ROOT; }; + C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutWheelButton_Highlighted.png; path = "../../IB Images/LayoutWheelButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87931E613F610B9003D834F /* LayoutWheelButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutWheelButton.png; path = "../../IB Images/LayoutWheelButton.png"; sourceTree = SOURCE_ROOT; }; + C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SettingsButton_Highlighted.png; path = "../../IB Images/SettingsButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; + C87931E813F610B9003D834F /* SettingsButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SettingsButton.png; path = "../../IB Images/SettingsButton.png"; sourceTree = SOURCE_ROOT; }; + C87931E913F610B9003D834F /* SliderBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SliderBackground.png; path = "../../IB Images/SliderBackground.png"; sourceTree = SOURCE_ROOT; }; + C87931EA13F610B9003D834F /* SliderBar.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SliderBar.png; path = "../../IB Images/SliderBar.png"; sourceTree = SOURCE_ROOT; }; + C87931EB13F610B9003D834F /* SliderSkull.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SliderSkull.png; path = "../../IB Images/SliderSkull.png"; sourceTree = SOURCE_ROOT; }; + C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_57.png; sourceTree = ""; }; + C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_114.png; sourceTree = ""; }; + C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_72.png; sourceTree = ""; }; + C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; + C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default~ipad.png"; sourceTree = ""; }; + C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait~ipad.png"; sourceTree = ""; }; + C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape~ipad.png"; sourceTree = ""; }; + ED9AB3CF10966E85000B5852 /* iphone_email.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_email.h; sourceTree = ""; }; + ED9AB3D010966E85000B5852 /* iphone_email.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iphone_email.m; sourceTree = ""; }; + EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + EDD2760611C2B19E004A9B9B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + EDD2760811C2B19E004A9B9B /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + EDD2760A11C2B19E004A9B9B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1E89C9420689D4C00760204 /* GameController.framework in Frameworks */, + A1A63E5520563A6D000955AE /* AVFoundation.framework in Frameworks */, + 43E8D4E00F51B48B003F09B2 /* OpenAL.framework in Frameworks */, + 4333CCE80F5CC23E00AE2B6F /* AudioToolbox.framework in Frameworks */, + 720EBBAE0F82E0BB003F989A /* QuartzCore.framework in Frameworks */, + EDD2760511C2B19E004A9B9B /* CoreGraphics.framework in Frameworks */, + EDD2760711C2B19E004A9B9B /* Foundation.framework in Frameworks */, + EDD2760911C2B19E004A9B9B /* OpenGLES.framework in Frameworks */, + EDD2760B11C2B19E004A9B9B /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A10639C0216EF7C700BDE196 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A10639C1216EF7C700BDE196 /* AVFoundation.framework in Frameworks */, + A10639C2216EF7C700BDE196 /* QuartzCore.framework in Frameworks */, + A10639C3216EF7C700BDE196 /* AudioToolbox.framework in Frameworks */, + A10639C4216EF7C700BDE196 /* OpenGLES.framework in Frameworks */, + A10639C5216EF7C700BDE196 /* UIKit.framework in Frameworks */, + A10639C6216EF7C700BDE196 /* Foundation.framework in Frameworks */, + A10639C7216EF7C700BDE196 /* CoreGraphics.framework in Frameworks */, + A10639C8216EF7C700BDE196 /* GameController.framework in Frameworks */, + A10639C9216EF7C700BDE196 /* OpenAL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1063ADC216EFCEE00BDE196 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1063ADD216EFCEE00BDE196 /* GameController.framework in Frameworks */, + A1063ADE216EFCEE00BDE196 /* AVFoundation.framework in Frameworks */, + A1063ADF216EFCEE00BDE196 /* OpenAL.framework in Frameworks */, + A1063AE0216EFCEE00BDE196 /* AudioToolbox.framework in Frameworks */, + A1063AE1216EFCEE00BDE196 /* QuartzCore.framework in Frameworks */, + A1063AE2216EFCEE00BDE196 /* CoreGraphics.framework in Frameworks */, + A1063AE3216EFCEE00BDE196 /* Foundation.framework in Frameworks */, + A1063AE4216EFCEE00BDE196 /* OpenGLES.framework in Frameworks */, + A1063AE5216EFCEE00BDE196 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1063BEF216F012000BDE196 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1063BF0216F012000BDE196 /* AVFoundation.framework in Frameworks */, + A1063BF1216F012000BDE196 /* QuartzCore.framework in Frameworks */, + A1063BF2216F012000BDE196 /* AudioToolbox.framework in Frameworks */, + A1063BF3216F012000BDE196 /* OpenGLES.framework in Frameworks */, + A1063BF4216F012000BDE196 /* UIKit.framework in Frameworks */, + A1063BF5216F012000BDE196 /* Foundation.framework in Frameworks */, + A1063BF6216F012000BDE196 /* CoreGraphics.framework in Frameworks */, + A1063BF7216F012000BDE196 /* GameController.framework in Frameworks */, + A1063BF8216F012000BDE196 /* OpenAL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A187090D216EB633006C013F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A187090E216EB633006C013F /* GameController.framework in Frameworks */, + A187090F216EB633006C013F /* AVFoundation.framework in Frameworks */, + A1870910216EB633006C013F /* OpenAL.framework in Frameworks */, + A1870911216EB633006C013F /* AudioToolbox.framework in Frameworks */, + A1870912216EB633006C013F /* QuartzCore.framework in Frameworks */, + A1870913216EB633006C013F /* CoreGraphics.framework in Frameworks */, + A1870914216EB633006C013F /* Foundation.framework in Frameworks */, + A1870915216EB633006C013F /* OpenGLES.framework in Frameworks */, + A1870916216EB633006C013F /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1B98DE7207EFEE800827A46 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1EA3B85207F1D320038650E /* AVFoundation.framework in Frameworks */, + A1B98E0A207EFF8B00827A46 /* QuartzCore.framework in Frameworks */, + A1B98E0B207EFF8B00827A46 /* AudioToolbox.framework in Frameworks */, + A1B98E0C207EFF8B00827A46 /* OpenGLES.framework in Frameworks */, + A1B98E0E207EFF8B00827A46 /* UIKit.framework in Frameworks */, + A1B98E0F207EFF8B00827A46 /* Foundation.framework in Frameworks */, + A1B98E10207EFF8B00827A46 /* CoreGraphics.framework in Frameworks */, + A1B98E11207EFF8B00827A46 /* GameController.framework in Frameworks */, + A1B98E12207EFF8B00827A46 /* OpenAL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1DE85A6229F60BE0041E450 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1DE85A7229F60BE0041E450 /* GameController.framework in Frameworks */, + A1DE85A8229F60BE0041E450 /* AVFoundation.framework in Frameworks */, + A1DE85A9229F60BE0041E450 /* OpenAL.framework in Frameworks */, + A1DE85AA229F60BE0041E450 /* AudioToolbox.framework in Frameworks */, + A1DE85AB229F60BE0041E450 /* QuartzCore.framework in Frameworks */, + A1DE85AC229F60BE0041E450 /* CoreGraphics.framework in Frameworks */, + A1DE85AD229F60BE0041E450 /* Foundation.framework in Frameworks */, + A1DE85AE229F60BE0041E450 /* OpenGLES.framework in Frameworks */, + A1DE85AF229F60BE0041E450 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1DE86C2229F88D20041E450 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1DE86C3229F88D20041E450 /* AVFoundation.framework in Frameworks */, + A1DE86C4229F88D20041E450 /* QuartzCore.framework in Frameworks */, + A1DE86C5229F88D20041E450 /* AudioToolbox.framework in Frameworks */, + A1DE86C6229F88D20041E450 /* OpenGLES.framework in Frameworks */, + A1DE86C7229F88D20041E450 /* UIKit.framework in Frameworks */, + A1DE86C8229F88D20041E450 /* Foundation.framework in Frameworks */, + A1DE86C9229F88D20041E450 /* CoreGraphics.framework in Frameworks */, + A1DE86CA229F88D20041E450 /* GameController.framework in Frameworks */, + A1DE86CB229F88D20041E450 /* OpenAL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* DOOM.app */, + 4364BF3E0F5CB25900F29317 /* dist.plist */, + A1B98DEA207EFEE800827A46 /* DOOM.app */, + A187091F216EB633006C013F /* DOOM II.app */, + A10639D2216EF7C700BDE196 /* DOOM II.app */, + A1063AEE216EFCEE00BDE196 /* FInal DOOM.app */, + A1063C01216F012000BDE196 /* Final DOOM.app */, + A1DE85B8229F60BE0041E450 /* SIGIL.app */, + A1DE86D4229F88D20041E450 /* SIGL.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 29B97315FDCFA39411CA2CEA /* DOOM-iOS */, + A1B9E45B216FFD6A003E9731 /* DOOM-tvOS */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + 29B97317FDCFA39411CA2CEA /* Resources */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* DOOM-iOS */ = { + isa = PBXGroup; + children = ( + A1A63E0B20562FB0000955AE /* arialGlyphRects.h */, + 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */, + 72E84A280F9503F100AB3C99 /* cmd.c */, + 72E8495C0F942B9300AB3C99 /* cvar.c */, + 72E8495D0F942B9300AB3C99 /* cvar.h */, + A1A63E1E20562FD1000955AE /* Doom_App.h */, + A1A63E1D20562FD1000955AE /* Doom_App.m */, + 434669A30F8D08C000EA7D6D /* doom_Prefix.pch */, + A1063C06216F032300BDE196 /* DOOM-iOS-Info.plist */, + A1063C07216F032300BDE196 /* DOOM2-iOS-Info.plist */, + 7229CC8E0F6B3363004123C5 /* doomiphone.h */, + 7229CE450F6C89F8004123C5 /* EAGLView.h */, + 7229CE460F6C89F8004123C5 /* EAGLView.m */, + A1A63E3B2056341C000955AE /* EAS */, + A1063C08216F032300BDE196 /* FinalDOOM-iOS-Info.plist */, + A1E89C9720689DB100760204 /* GameController.h */, + A1E89C9520689D9500760204 /* GameController.mm */, + 7229CE540F6C8CDE004123C5 /* gles_glue.c */, + 727886A20FBDBA740020D469 /* gles_glue.h */, + 72B5FF380F7E5C3D00C8A372 /* hud.c */, + C86F965213D615BB0069B7B6 /* InterfaceBuilder */, + A12302D4205737DE0075CBAD /* iOS */, + 72D50DBB0F8ED98000BB49E6 /* ipak.c */, + 72D50DBA0F8ED98000BB49E6 /* ipak.h */, + A1A63E0020562FAE000955AE /* iphone_async.cpp */, + A1A63E0220562FAE000955AE /* iphone_common.h */, + A1A63E0620562FAF000955AE /* iphone_common.mm */, + A1A63DFD20562FAE000955AE /* iphone_delegate.h */, + A1A63E0320562FAF000955AE /* iphone_delegate.mm */, + 72A7E8F30F5F2001005B83C0 /* iphone_doom.h */, + ED9AB3CF10966E85000B5852 /* iphone_email.h */, + ED9AB3D010966E85000B5852 /* iphone_email.m */, + A1A63E0420562FAF000955AE /* iphone_glViewController.h */, + A1A63DFE20562FAE000955AE /* iphone_glViewController.mm */, + 43CF03090F56D5C200E4A23D /* iphone_loop.c */, + 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */, + 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */, + 72A560E11004FAEE00F788A5 /* iphone_net.c */, + A1A63DFF20562FAE000955AE /* iphone_qgl_enumerants.h */, + A1A63E0120562FAE000955AE /* iphone_qgl.h */, + 72484E5D0FB0E99900124E1C /* iphone_render.c */, + A1A63E0920562FAF000955AE /* iphone_sound.mm */, + A1A63E0520562FAF000955AE /* iphone_start.cpp */, + A1A63E0A20562FAF000955AE /* iphone_sys.mm */, + A1A63DFC20562FAE000955AE /* iphone_wolf.h */, + 72F1F94B0F96B55B00AD49AC /* libtess */, + A1A63E0720562FAF000955AE /* Localizable.strings */, + 29B97316FDCFA39411CA2CEA /* main.m */, + 72E8495E0F942B9300AB3C99 /* misc.c */, + 72E8495F0F942B9300AB3C99 /* misc.h */, + 72E847620F93C5F900AB3C99 /* prboom */, + 72E849F50F94ED1100AB3C99 /* prboomInterface.c */, + A1A63E25205632E2000955AE /* SDL_shim */, + A1DE85B9229F60BE0041E450 /* SIGIL-iOS-Info.plist */, + A1A63E0820562FAF000955AE /* SoundEngine.cpp */, + A1A63DFB20562FAE000955AE /* SoundEngine.h */, + ); + name = "DOOM-iOS"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + A12302FA205783E70075CBAD /* base.iPack */, + C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */, + C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */, + 43CF02FE0F56974E00E4A23D /* Default.png */, + C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */, + C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */, + C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */, + C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */, + A1A63E1820562FC4000955AE /* DOOM_76.png */, + C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */, + A1A63E1720562FC3000955AE /* DOOM_120.png */, + A1A63E1620562FC3000955AE /* DOOM_144.png */, + A1A63E1520562FC3000955AE /* DOOM_152.png */, + A1EA3B86207F9DE20038650E /* DOOM_400.png */, + A1B9E45C21700601003E9731 /* DOOM-iOS.xcassets */, + A1D399372171A08C00FD11C3 /* DOOM-tvOS.xcassets */, + A12302F9205783E70075CBAD /* doom.wad */, + A1B9E45E217006D2003E9731 /* DOOM2-iOS.xcassets */, + A1D399392171A0A800FD11C3 /* DOOM2-tvOS.xcassets */, + A10638C2216EBC5A00BDE196 /* doom2.wad */, + A1D399352171462F00FD11C3 /* DOOM2LaunchScreen.storyboard */, + A112904F2069B62B00BEDEB5 /* DOOMLaunchScreen.storyboard */, + A1B9E4602170078A003E9731 /* FinalDOOM-iOS.xcassets */, + A1D3993C2171A0FD00FD11C3 /* FinalDOOM-tvOS.xcassets */, + A1D39932217144A800FD11C3 /* FinalDOOMLaunchScreen.storyboard */, + C84F820613D73D28006D01AB /* Interface Builder Images */, + A1063AF1216EFD9800BDE196 /* plutonia.wad */, + A12302F8205783E70075CBAD /* prboom.wad */, + A1DE85BA229F610B0041E450 /* SIGIL_SHREDS.wad */, + A1DE85C2229F73950041E450 /* SIGIL-iOS.xcassets */, + A1DE86D8229F8B090041E450 /* SIGIL-tvOS.xcassets */, + A1DE85BB229F610B0041E450 /* SIGIL.wad */, + A1DE85C6229F874F0041E450 /* SIGILLaunchScreen.storyboard */, + A1063AF0216EFD9800BDE196 /* tnt.wad */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + A1EA3B84207F1D310038650E /* AVFoundation.framework */, + A1E89C9320689D4B00760204 /* GameController.framework */, + A1B98E02207EFF8A00827A46 /* AudioToolbox.framework */, + A1B98E07207EFF8A00827A46 /* CoreGraphics.framework */, + A1B98E06207EFF8A00827A46 /* Foundation.framework */, + A1B98E08207EFF8B00827A46 /* GameController.framework */, + A1B98E04207EFF8A00827A46 /* GameKit.framework */, + A1B98E09207EFF8B00827A46 /* OpenAL.framework */, + A1B98E03207EFF8A00827A46 /* OpenGLES.framework */, + A1B98E01207EFF8A00827A46 /* QuartzCore.framework */, + A1B98E05207EFF8A00827A46 /* UIKit.framework */, + A1A63E5420563A6D000955AE /* AVFoundation.framework */, + 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */, + 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */, + 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */, + EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */, + EDD2760611C2B19E004A9B9B /* Foundation.framework */, + EDD2760811C2B19E004A9B9B /* OpenGLES.framework */, + EDD2760A11C2B19E004A9B9B /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 72E847620F93C5F900AB3C99 /* prboom */ = { + isa = PBXGroup; + children = ( + 72E847640F93C61900AB3C99 /* am_map.c */, + 72E8476E0F93FFDB00AB3C99 /* am_map.h */, + 72E847680F93FF2F00AB3C99 /* config.h */, + 72E8476F0F93FFDB00AB3C99 /* d_client.c */, + 72E847700F93FFDB00AB3C99 /* d_deh.c */, + 72E847710F93FFDB00AB3C99 /* d_deh.h */, + 72E847720F93FFDB00AB3C99 /* d_englsh.h */, + 72E847730F93FFDB00AB3C99 /* d_event.h */, + 72E8477A0F9400D700AB3C99 /* d_items.c */, + 72E8477B0F9400D700AB3C99 /* d_items.h */, + 72E8477C0F9400D700AB3C99 /* d_main.c */, + 72E8477D0F9400D700AB3C99 /* d_main.h */, + 72E8477E0F9400D700AB3C99 /* d_net.h */, + 72E8477F0F9400D700AB3C99 /* d_player.h */, + 72E847810F9400D700AB3C99 /* d_think.h */, + 72E847820F9400D700AB3C99 /* d_ticcmd.h */, + 72E847830F9400D700AB3C99 /* doomdata.h */, + 72E847840F9400D700AB3C99 /* doomdef.c */, + 72E847850F9400D700AB3C99 /* doomdef.h */, + 72E847860F9400D700AB3C99 /* doomstat.c */, + 72E847870F9400D700AB3C99 /* doomstat.h */, + 72E847880F9400D700AB3C99 /* doomtype.h */, + 72E847890F9400D700AB3C99 /* dstrings.c */, + 72E8478A0F9400D700AB3C99 /* dstrings.h */, + 72E8478B0F9400D700AB3C99 /* f_finale.c */, + 72E8478C0F9400D700AB3C99 /* f_finale.h */, + 72E8478D0F9400D700AB3C99 /* f_wipe.c */, + 72E8478E0F9400D700AB3C99 /* f_wipe.h */, + 72E8478F0F9400D700AB3C99 /* g_game.c */, + 72E847900F9400D700AB3C99 /* g_game.h */, + 72E847910F9400D700AB3C99 /* gl_intern.h */, + 72E847920F9400D700AB3C99 /* gl_main.c */, + 72E847930F9400D700AB3C99 /* gl_struct.h */, + 72E847940F9400D700AB3C99 /* gl_texture.c */, + 72E847950F9400D700AB3C99 /* hu_lib.c */, + 72E847960F9400D700AB3C99 /* hu_lib.h */, + 72E847970F9400D700AB3C99 /* hu_stuff.c */, + 72E847980F9400D700AB3C99 /* hu_stuff.h */, + 72E847990F9400D700AB3C99 /* i_joy.h */, + 72E8479A0F9400D700AB3C99 /* i_main.h */, + 72E8479B0F9400D700AB3C99 /* i_network.h */, + 72E8479C0F9400D700AB3C99 /* i_sound.h */, + 72E8479D0F9400D700AB3C99 /* i_system.h */, + 72E8479E0F9400D700AB3C99 /* i_video.h */, + 72E8479F0F9400D700AB3C99 /* info.c */, + 72E847A00F9400D700AB3C99 /* info.h */, + 72E847A10F9400D700AB3C99 /* lprintf.c */, + 72E847A20F9400D700AB3C99 /* lprintf.h */, + 72E847A30F9400D700AB3C99 /* m_argv.c */, + 72E847A40F9400D700AB3C99 /* m_argv.h */, + 72E847A50F9400D700AB3C99 /* m_bbox.c */, + 72E847A60F9400D700AB3C99 /* m_bbox.h */, + 72E847A70F9400D700AB3C99 /* m_cheat.c */, + 72E847A80F9400D700AB3C99 /* m_cheat.h */, + 72E847A90F9400D700AB3C99 /* m_fixed.h */, + 72E847AA0F9400D700AB3C99 /* m_menu.c */, + 72E847AB0F9400D700AB3C99 /* m_menu.h */, + 72E847AC0F9400D700AB3C99 /* m_misc.c */, + 72E847AD0F9400D700AB3C99 /* m_misc.h */, + 72E847AE0F9400D700AB3C99 /* m_random.c */, + 72E847AF0F9400D700AB3C99 /* m_random.h */, + 72E847B00F9400D700AB3C99 /* m_swap.h */, + A1A63E2E20563345000955AE /* Makefile.am */, + 72E847E00F941A5900AB3C99 /* md5.c */, + 72E847E10F941A5900AB3C99 /* md5.h */, + A1A63E2B20563344000955AE /* mmus2mid.c */, + A1A63E2C20563344000955AE /* mmus2mid.h */, + 72E847E40F941A5900AB3C99 /* p_ceilng.c */, + 72E847E50F941A5900AB3C99 /* p_checksum.c */, + 72E847E60F941A5900AB3C99 /* p_checksum.h */, + 72E847E70F941A5900AB3C99 /* p_doors.c */, + 72E847E80F941A5900AB3C99 /* p_enemy.c */, + 72E847E90F941A5900AB3C99 /* p_enemy.h */, + 72E847EA0F941A5900AB3C99 /* p_floor.c */, + 72E847EB0F941A5900AB3C99 /* p_genlin.c */, + 72E847EC0F941A5900AB3C99 /* p_inter.c */, + 72E847ED0F941A5900AB3C99 /* p_inter.h */, + 72E847EE0F941A5900AB3C99 /* p_lights.c */, + 72E847EF0F941A5900AB3C99 /* p_map.c */, + 72E847F00F941A5900AB3C99 /* p_map.h */, + 72E847F10F941A5900AB3C99 /* p_maputl.c */, + 72E847F20F941A5900AB3C99 /* p_maputl.h */, + 72E847F30F941A5900AB3C99 /* p_mobj.c */, + 72E847F40F941A5900AB3C99 /* p_mobj.h */, + 72E847F50F941A5900AB3C99 /* p_plats.c */, + 72E847F60F941A5900AB3C99 /* p_pspr.c */, + 72E847F70F941A5900AB3C99 /* p_pspr.h */, + 72E847F80F941A5900AB3C99 /* p_saveg.c */, + 72E847F90F941A5900AB3C99 /* p_saveg.h */, + 72E847FA0F941A5900AB3C99 /* p_setup.c */, + 72E847FB0F941A5900AB3C99 /* p_setup.h */, + 72E847FC0F941A5900AB3C99 /* p_sight.c */, + 72E847FD0F941A5900AB3C99 /* p_spec.c */, + 72E847FE0F941A5900AB3C99 /* p_spec.h */, + 72E847FF0F941A5900AB3C99 /* p_switch.c */, + 72E848000F941A5900AB3C99 /* p_telept.c */, + 72E848010F941A5900AB3C99 /* p_tick.c */, + 72E848020F941A5900AB3C99 /* p_tick.h */, + 72E848030F941A5900AB3C99 /* p_user.c */, + 72E848040F941A5900AB3C99 /* p_user.h */, + 72E8481C0F941A8300AB3C99 /* protocol.h */, + 72E8481D0F941A8300AB3C99 /* r_bsp.c */, + 72E8481E0F941A8300AB3C99 /* r_bsp.h */, + 72E8481F0F941A8300AB3C99 /* r_data.c */, + 72E848200F941A8300AB3C99 /* r_data.h */, + 72E848210F941A8300AB3C99 /* r_defs.h */, + 72E848220F941A8300AB3C99 /* r_demo.c */, + 72E848230F941A8300AB3C99 /* r_demo.h */, + 72E848240F941A8300AB3C99 /* r_draw.c */, + 72E848250F941A8300AB3C99 /* r_draw.h */, + A1A63E2A20563344000955AE /* r_drawcolpipeline.inl */, + A1A63E2D20563344000955AE /* r_drawcolumn.inl */, + A1A63E3020563345000955AE /* r_drawflush.inl */, + A1A63E3120563345000955AE /* r_drawspan.inl */, + 72E8482A0F941AAC00AB3C99 /* r_filter.c */, + 72E8482B0F941AAC00AB3C99 /* r_filter.h */, + 72E8482C0F941AAC00AB3C99 /* r_fps.c */, + 72E8482D0F941AAC00AB3C99 /* r_fps.h */, + 72E8482E0F941AAC00AB3C99 /* r_main.c */, + 72E8482F0F941AAC00AB3C99 /* r_main.h */, + 72E848300F941AAC00AB3C99 /* r_patch.c */, + 72E848310F941AAC00AB3C99 /* r_patch.h */, + 72E848320F941AAC00AB3C99 /* r_plane.c */, + 72E848330F941AAC00AB3C99 /* r_plane.h */, + 72E848340F941AAC00AB3C99 /* r_segs.c */, + 72E848350F941AAC00AB3C99 /* r_segs.h */, + 72E848360F941AAC00AB3C99 /* r_sky.c */, + 72E848370F941AAC00AB3C99 /* r_sky.h */, + 72E848380F941AAC00AB3C99 /* r_state.h */, + 72E848390F941AAC00AB3C99 /* r_things.c */, + 72E8483A0F941AAC00AB3C99 /* r_things.h */, + 72E8483B0F941AAC00AB3C99 /* s_sound.c */, + 72E8483C0F941AAC00AB3C99 /* s_sound.h */, + A1A63E2220563253000955AE /* SDL */, + 72E847CA0F94096C00AB3C99 /* SDL_opengl.h */, + 72E848460F941ADC00AB3C99 /* sounds.c */, + 72E848470F941ADC00AB3C99 /* sounds.h */, + 72E848480F941ADC00AB3C99 /* st_lib.c */, + 72E848490F941ADC00AB3C99 /* st_lib.h */, + 72E8484A0F941ADC00AB3C99 /* st_stuff.c */, + 72E8484B0F941ADC00AB3C99 /* st_stuff.h */, + 72E8484C0F941ADC00AB3C99 /* tables.c */, + 72E8484D0F941ADC00AB3C99 /* tables.h */, + 72E8484E0F941ADC00AB3C99 /* v_video.c */, + 72E8484F0F941ADC00AB3C99 /* v_video.h */, + 72E848500F941ADC00AB3C99 /* version.c */, + 72E848510F941ADC00AB3C99 /* version.h */, + 72E848530F941ADC00AB3C99 /* w_mmap.c */, + 72E848540F941ADC00AB3C99 /* w_wad.c */, + 72E848550F941ADC00AB3C99 /* w_wad.h */, + 72E848560F941ADC00AB3C99 /* wi_stuff.c */, + 72E848570F941ADC00AB3C99 /* wi_stuff.h */, + 72E848580F941ADC00AB3C99 /* z_bmalloc.c */, + 72E848590F941ADC00AB3C99 /* z_bmalloc.h */, + 72E8485A0F941ADC00AB3C99 /* z_zone.c */, + 72E8485B0F941ADC00AB3C99 /* z_zone.h */, + ); + name = prboom; + sourceTree = ""; + }; + 72F1F94B0F96B55B00AD49AC /* libtess */ = { + isa = PBXGroup; + children = ( + 72F1F99C0F96C18800AD49AC /* dict-list.h */, + 72F1F99D0F96C18800AD49AC /* dict.c */, + 72F1F99E0F96C18800AD49AC /* dict.h */, + 72F1F99F0F96C18800AD49AC /* geom.c */, + 72F1F9A00F96C18800AD49AC /* geom.h */, + 72F1F9A10F96C18800AD49AC /* memalloc.c */, + 72F1F9A20F96C18800AD49AC /* memalloc.h */, + 72F1F9A30F96C18800AD49AC /* mesh.c */, + 72F1F9A40F96C18800AD49AC /* mesh.h */, + 72F1F9A50F96C18800AD49AC /* normal.c */, + 72F1F9A60F96C18800AD49AC /* normal.h */, + 72F1F9A80F96C18800AD49AC /* priorityq-heap.h */, + 72F1F9A90F96C18800AD49AC /* priorityq-sort.h */, + 72F1F9AA0F96C18800AD49AC /* priorityq.c */, + 72F1F9AB0F96C18800AD49AC /* priorityq.h */, + 72F1F9AC0F96C18800AD49AC /* render.c */, + 72F1F9AD0F96C18800AD49AC /* render.h */, + 72F1F9AE0F96C18800AD49AC /* sweep.c */, + 72F1F9AF0F96C18800AD49AC /* sweep.h */, + 72F1F9B00F96C18800AD49AC /* tess.c */, + 72F1F9B10F96C18800AD49AC /* tess.h */, + 72F1F9B20F96C18800AD49AC /* tessmono.c */, + 72F1F9B30F96C18800AD49AC /* tessmono.h */, + ); + name = libtess; + sourceTree = ""; + }; + A12302D4205737DE0075CBAD /* iOS */ = { + isa = PBXGroup; + children = ( + A12302F4205738560075CBAD /* Carousel.h */, + A12302F3205738560075CBAD /* Carousel.mm */, + A12302EF205738270075CBAD /* Slider.h */, + A12302F0205738270075CBAD /* Slider.mm */, + A12302DF205737F50075CBAD /* Label.h */, + A12302D6205737F40075CBAD /* Label.mm */, + A12302DD205737F40075CBAD /* LabelButton.h */, + A12302D7205737F40075CBAD /* LabelButton.mm */, + A12302D9205737F40075CBAD /* Localization.h */, + A12302DE205737F40075CBAD /* Localization.mm */, + A12302D5205737F40075CBAD /* LocalizationObjectiveC.h */, + A12302D8205737F40075CBAD /* RenderContext.h */, + A12302DA205737F40075CBAD /* RenderContext.mm */, + A12302DB205737F40075CBAD /* Switch.h */, + A12302E1205737F50075CBAD /* Switch.mm */, + A12302E0205737F50075CBAD /* View.h */, + A12302DC205737F40075CBAD /* View.mm */, + ); + name = iOS; + sourceTree = ""; + }; + A1A63E2220563253000955AE /* SDL */ = { + isa = PBXGroup; + children = ( + A1A63E2320563253000955AE /* i_sound.c */, + ); + name = SDL; + path = ../prboom/SDL; + sourceTree = ""; + }; + A1A63E25205632E2000955AE /* SDL_shim */ = { + isa = PBXGroup; + children = ( + A1A63E26205632E2000955AE /* ios */, + A1A63E28205632E2000955AE /* SDL_Mixer.h */, + ); + name = SDL_shim; + path = ../SDL_shim; + sourceTree = ""; + }; + A1A63E26205632E2000955AE /* ios */ = { + isa = PBXGroup; + children = ( + A1A63E27205632E2000955AE /* SDL_Mixer.m */, + ); + path = ios; + sourceTree = ""; + }; + A1A63E3B2056341C000955AE /* EAS */ = { + isa = PBXGroup; + children = ( + A1A63E5120563A06000955AE /* EASGlue.c */, + A1A63E5220563A06000955AE /* EASGlue.h */, + A1A63E3C2056342A000955AE /* arm-wt-22k */, + ); + name = EAS; + sourceTree = ""; + }; + A1A63E3C2056342A000955AE /* arm-wt-22k */ = { + isa = PBXGroup; + children = ( + A1A63E5620563ACC000955AE /* lib_src */, + A1A63E3D20563436000955AE /* host_src */, + ); + name = "arm-wt-22k"; + sourceTree = ""; + }; + A1A63E3D20563436000955AE /* host_src */ = { + isa = PBXGroup; + children = ( + A1A63E45205634E7000955AE /* eas_build.h */, + A1A63E43205634E7000955AE /* eas_chorus.h */, + A1A63E4B205634E7000955AE /* eas_config.c */, + A1A63E4A205634E7000955AE /* eas_config.h */, + A1A63E3F205634E7000955AE /* eas_debugmsgs.h */, + A1A63E46205634E7000955AE /* eas_host.h */, + A1A63E42205634E7000955AE /* eas_hostmm.c */, + A1A63E40205634E7000955AE /* eas_report.c */, + A1A63E47205634E7000955AE /* eas_report.h */, + A1A63E3E205634E7000955AE /* eas_reverb.h */, + A1A63E44205634E7000955AE /* eas_types.h */, + A1A63E4C205634E7000955AE /* eas_wave.c */, + A1A63E48205634E7000955AE /* eas_wave.h */, + A1A63E41205634E7000955AE /* eas.h */, + A1A63E49205634E7000955AE /* jet.h */, + ); + name = host_src; + sourceTree = ""; + }; + A1A63E5620563ACC000955AE /* lib_src */ = { + isa = PBXGroup; + children = ( + A1A63ECC20563B53000955AE /* dls.h */, + A1A63F0720563B5E000955AE /* dls2.h */, + A1A63EDE20563B55000955AE /* eas_audioconst.h */, + A1A63EE120563B55000955AE /* eas_chorus.c */, + A1A63EDC20563B55000955AE /* eas_chorusdata.c */, + A1A63EE220563B56000955AE /* eas_chorusdata.h */, + A1A63F0020563B5C000955AE /* eas_ctype.h */, + A1A63ECF20563B53000955AE /* eas_data.c */, + A1A63EC920563B53000955AE /* eas_data.h */, + A1A63EEF20563B59000955AE /* eas_dlssynth.c */, + A1A63EF220563B5A000955AE /* eas_dlssynth.h */, + A1A63F0820563B5E000955AE /* eas_effects.h */, + A1A63F0220563B5C000955AE /* eas_flog.c */, + A1A63F0620563B5D000955AE /* eas_ima_tables.c */, + A1A63ED020563B54000955AE /* eas_imaadpcm.c */, + A1A63F0C20563B5F000955AE /* eas_imelody.c */, + A1A63EFC20563B5C000955AE /* eas_imelodydata.c */, + A1A63EF820563B5B000955AE /* eas_imelodydata.h */, + A1A63F1020563B5F000955AE /* eas_math.c */, + A1A63EEE20563B59000955AE /* eas_math.h */, + A1A63F1220563B60000955AE /* eas_mdls.c */, + A1A63EDD20563B55000955AE /* eas_mdls.h */, + A1A63EE320563B56000955AE /* eas_midi.c */, + A1A63ED320563B54000955AE /* eas_midi.h */, + A1A63EFE20563B5C000955AE /* eas_midictrl.h */, + A1A63EFD20563B5C000955AE /* eas_mididata.c */, + A1A63F1120563B60000955AE /* eas_miditypes.h */, + A1A63EEC20563B59000955AE /* eas_mixbuf.c */, + A1A63ED720563B54000955AE /* eas_mixer.c */, + A1A63EF120563B5A000955AE /* eas_mixer.h */, + A1A63ED820563B54000955AE /* eas_ota.c */, + A1A63ECE20563B53000955AE /* eas_otadata.c */, + A1A63F0A20563B5E000955AE /* eas_otadata.h */, + A1A63F0D20563B5F000955AE /* eas_pan.c */, + A1A63ED920563B54000955AE /* eas_pan.h */, + A1A63ED520563B54000955AE /* eas_parser.h */, + A1A63EF020563B5A000955AE /* eas_pcm.c */, + A1A63F0320563B5D000955AE /* eas_pcm.h */, + A1A63EDA20563B54000955AE /* eas_pcmdata.c */, + A1A63EE620563B58000955AE /* eas_pcmdata.h */, + A1A63F0520563B5D000955AE /* eas_public.c */, + A1A63F0E20563B5F000955AE /* eas_reverb.c */, + A1A63F0420563B5D000955AE /* eas_reverbdata.c */, + A1A63EF620563B5B000955AE /* eas_reverbdata.h */, + A1A63ED120563B54000955AE /* eas_rtttl.c */, + A1A63EFF20563B5C000955AE /* eas_rtttldata.c */, + A1A63ECD20563B53000955AE /* eas_rtttldata.h */, + A1A63EED20563B59000955AE /* eas_smf.c */, + A1A63F0920563B5E000955AE /* eas_smf.h */, + A1A63EE520563B56000955AE /* eas_smfdata.c */, + A1A63ED220563B54000955AE /* eas_smfdata.h */, + A1A63EF520563B5A000955AE /* eas_sndlib.h */, + A1A63EF320563B5A000955AE /* eas_synth_protos.h */, + A1A63EC820563B53000955AE /* eas_synth.h */, + A1A63EDF20563B55000955AE /* eas_synthcfg.h */, + A1A63F0F20563B5F000955AE /* eas_tcdata.c */, + A1A63ED420563B54000955AE /* eas_tcdata.h */, + A1A63EF720563B5B000955AE /* eas_tonecontrol.c */, + A1A63EFB20563B5B000955AE /* eas_vm_protos.h */, + A1A63F0B20563B5E000955AE /* eas_voicemgt.c */, + A1A63ED620563B54000955AE /* eas_wavefile.c */, + A1A63F0120563B5C000955AE /* eas_wavefile.h */, + A1A63EF920563B5B000955AE /* eas_wavefiledata.c */, + A1A63EE020563B55000955AE /* eas_wt_IPC_frame.h */, + A1A63EFA20563B5B000955AE /* eas_wtengine.c */, + A1A63EE720563B58000955AE /* eas_wtengine.h */, + A1A63EE820563B58000955AE /* eas_wtsynth.c */, + A1A63EF420563B5A000955AE /* eas_wtsynth.h */, + A1A63ECB20563B53000955AE /* eas_xmf.c */, + A1A63EEA20563B59000955AE /* eas_xmf.h */, + A1A63ECA20563B53000955AE /* eas_xmfdata.c */, + A1A63EDB20563B55000955AE /* eas_xmfdata.h */, + A1A63EE920563B59000955AE /* jet_data.h */, + A1A63EEB20563B59000955AE /* jet.c */, + A1A63EE420563B56000955AE /* wt_22khz.c */, + ); + name = lib_src; + sourceTree = ""; + }; + A1B9E45B216FFD6A003E9731 /* DOOM-tvOS */ = { + isa = PBXGroup; + children = ( + A1063C04216F030900BDE196 /* DOOM-tvOS-Info.plist */, + A1063C05216F030900BDE196 /* DOOM2-tvOS-Info.plist */, + A1063C03216F030900BDE196 /* FinalDOOM-tvOS-Info.plist */, + A1DE86D5229F88D20041E450 /* SIGIL-tvOS-Info.plist */, + ); + name = "DOOM-tvOS"; + sourceTree = ""; + }; + C84F820613D73D28006D01AB /* Interface Builder Images */ = { + isa = PBXGroup; + children = ( + C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */, + C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */, + C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */, + C87931DF13F610B9003D834F /* AdvancedButton.png */, + C87931E013F610B9003D834F /* Divide.png */, + C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */, + C87931E213F610B9003D834F /* LayoutDualButton.png */, + C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */, + C87931E413F610B9003D834F /* LayoutSingleButton.png */, + C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */, + C87931E613F610B9003D834F /* LayoutWheelButton.png */, + C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */, + C87931E813F610B9003D834F /* SettingsButton.png */, + C87931E913F610B9003D834F /* SliderBackground.png */, + C87931EA13F610B9003D834F /* SliderBar.png */, + C87931EB13F610B9003D834F /* SliderSkull.png */, + C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */, + C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */, + C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */, + C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */, + C879308513F5D8AA003D834F /* DifficultyBackground.png */, + C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */, + C879308713F5D8AA003D834F /* DownArrow.png */, + C879308813F5D8AA003D834F /* Episode1Background.png */, + C879308913F5D8AA003D834F /* Episode2Background.png */, + C879308A13F5D8AA003D834F /* Episode3Background.png */, + C879308B13F5D8AA003D834F /* Episode4Background.png */, + C879308C13F5D8AA003D834F /* MissonBackground.png */, + C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */, + C879308E13F5D8AA003D834F /* UpArrow.png */, + C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */, + C8792ED213F5AFE5003D834F /* Button_Highlighted.png */, + C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */, + C8792ED413F5AFE5003D834F /* NextButton.png */, + C8792ED513F5AFE5003D834F /* SubMenuBackground.png */, + C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */, + C8792ED713F5AFE5003D834F /* SubMenuButton.png */, + C81E104013E1CCA000B1049A /* BackButton.png */, + C81E104113E1CCA000B1049A /* Button.png */, + C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */, + C81E104313E1CCA000B1049A /* DoomLogo.png */, + C81E104413E1CCA000B1049A /* Easy.png */, + C81E104513E1CCA000B1049A /* Hard.png */, + C81E104613E1CCA000B1049A /* MapOverlay.png */, + C81E104713E1CCA000B1049A /* Medium.png */, + C81E104813E1CCA000B1049A /* MenuBackground.png */, + C81E104913E1CCA000B1049A /* Nightmare.png */, + C81E104A13E1CCA000B1049A /* ResumeButton.png */, + C81E104B13E1CCA000B1049A /* SelectedBracket.png */, + C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */, + ); + name = "Interface Builder Images"; + sourceTree = ""; + }; + C86F965213D615BB0069B7B6 /* InterfaceBuilder */ = { + isa = PBXGroup; + children = ( + A1B98E17207F016500827A46 /* ControlsMenuView-tvos.xib */, + A1A63DB620562B2B000955AE /* ControlsMenuView.xib */, + A1A63DBB20562B2B000955AE /* ControlsMenuView~ipad.xib */, + A1A63DB820562B2B000955AE /* ControlsMenuViewController.h */, + A1A63DB420562B2A000955AE /* ControlsMenuViewController.mm */, + A1B98E1C207F016600827A46 /* CreditsMenuView-tvos.xib */, + A1E89C8D2067469D00760204 /* CreditsMenuView.xib */, + A1A63DBA20562B2B000955AE /* CreditsMenuView~ipad.xib */, + A1E89C8B2067469D00760204 /* CreditsMenuViewController.h */, + A1E89C8C2067469D00760204 /* CreditsMenuViewController.mm */, + A1EA3B8F208020B60038650E /* EpisodeCell-tvos.xib */, + A1A184252063E63200302393 /* EpisodeCell.xib */, + A176AC08206492DD00A96B7E /* EpisodeCell~ipad.xib */, + A1B98E1A207F016600827A46 /* EpisodeMenuView-tvos.xib */, + A1A63DCA20562B73000955AE /* EpisodeMenuView.xib */, + A1A63DDA20562B75000955AE /* EpisodeMenuView~ipad.xib */, + A1A63DDF20562B76000955AE /* EpisodeMenuViewController.h */, + A1A63DDB20562B75000955AE /* EpisodeMenuViewController.mm */, + A1B98E16207F016500827A46 /* LegalMenuView-tvos.xib */, + A1A63DE020562B76000955AE /* LegalMenuView.xib */, + A1A63DCB20562B73000955AE /* LegalMenuView~ipad.xib */, + A1A63DD420562B74000955AE /* LegalMenuViewController.h */, + A1A63DC720562B73000955AE /* LegalMenuViewController.mm */, + A1B98E15207F016500827A46 /* MainMenuView-tvos.xib */, + A1A63DCE20562B73000955AE /* MainMenuView.xib */, + A1A63DD920562B75000955AE /* MainMenuView~ipad.xib */, + A1A63DDE20562B75000955AE /* MainMenuViewController.h */, + A1A63DD820562B75000955AE /* MainMenuViewController.mm */, + A1A63DD720562B75000955AE /* MainNavController.h */, + A1A63DDC20562B75000955AE /* MainNavController.m */, + A1B98E1B207F016600827A46 /* MissionMenuView-tvos.xib */, + A1A63DCC20562B73000955AE /* MissionMenuView.xib */, + A1A63DC620562B73000955AE /* MissionMenuView~ipad.xib */, + A1A63DDD20562B75000955AE /* MissionMenuViewController.h */, + A1A63DD020562B74000955AE /* MissionMenuViewController.mm */, + A1B98E18207F016500827A46 /* OpenGLView-tvos.xib */, + A1A63DD220562B74000955AE /* OpenGLView.xib */, + A1A63DE220562B76000955AE /* OpenGLView~ipad.xib */, + A1A63DBC20562B2B000955AE /* SecretMenuView.xib */, + A1A63DB320562B2A000955AE /* SecretMenuViewController.h */, + A1A63DB720562B2B000955AE /* SecretMenuViewController.mm */, + A1B98E19207F016500827A46 /* SettingsMenuView-tvos.xib */, + A1A63DD620562B74000955AE /* SettingsMenuView.xib */, + A1A63DC920562B73000955AE /* SettingsMenuView~ipad.xib */, + A1A63DC520562B72000955AE /* SettingsMenuViewController.h */, + A1A63DE120562B76000955AE /* SettingsMenuViewController.mm */, + ); + name = InterfaceBuilder; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + A10639CA216EF7C700BDE196 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1063AE6216EFCEE00BDE196 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1063BF9216F012000BDE196 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A12302A32057365B0075CBAD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1870917216EB633006C013F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1B98E9F207F066300827A46 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1DE85B0229F60BE0041E450 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1DE86CC229F88D20041E450 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* DOOM-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "DOOM-iOS" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + A12302A32057365B0075CBAD /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "DOOM-iOS"; + productName = Doom; + productReference = 1D6058910D05DD3D006BFB54 /* DOOM.app */; + productType = "com.apple.product-type.application"; + }; + A10638C6216EF7C700BDE196 /* DOOM2-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A10639CB216EF7C700BDE196 /* Build configuration list for PBXNativeTarget "DOOM2-tvOS" */; + buildPhases = ( + A10638C7216EF7C700BDE196 /* Resources */, + A106391A216EF7C700BDE196 /* Sources */, + A10639C0216EF7C700BDE196 /* Frameworks */, + A10639CA216EF7C700BDE196 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "DOOM2-tvOS"; + productName = DoomTV; + productReference = A10639D2216EF7C700BDE196 /* DOOM II.app */; + productType = "com.apple.product-type.application"; + }; + A10639D5216EFCEE00BDE196 /* FInalDOOM-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1063AE7216EFCEE00BDE196 /* Build configuration list for PBXNativeTarget "FInalDOOM-iOS" */; + buildPhases = ( + A10639D6216EFCEE00BDE196 /* Resources */, + A1063A34216EFCEE00BDE196 /* Sources */, + A1063ADC216EFCEE00BDE196 /* Frameworks */, + A1063AE6216EFCEE00BDE196 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "FInalDOOM-iOS"; + productName = Doom; + productReference = A1063AEE216EFCEE00BDE196 /* FInal DOOM.app */; + productType = "com.apple.product-type.application"; + }; + A1063AF4216F012000BDE196 /* FInalDOOM-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1063BFA216F012000BDE196 /* Build configuration list for PBXNativeTarget "FInalDOOM-tvOS" */; + buildPhases = ( + A1063AF5216F012000BDE196 /* Resources */, + A1063B49216F012000BDE196 /* Sources */, + A1063BEF216F012000BDE196 /* Frameworks */, + A1063BF9216F012000BDE196 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "FInalDOOM-tvOS"; + productName = DoomTV; + productReference = A1063C01216F012000BDE196 /* Final DOOM.app */; + productType = "com.apple.product-type.application"; + }; + A1870806216EB633006C013F /* DOOM2-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1870918216EB633006C013F /* Build configuration list for PBXNativeTarget "DOOM2-iOS" */; + buildPhases = ( + A1870807216EB633006C013F /* Resources */, + A1870865216EB633006C013F /* Sources */, + A187090D216EB633006C013F /* Frameworks */, + A1870917216EB633006C013F /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "DOOM2-iOS"; + productName = Doom; + productReference = A187091F216EB633006C013F /* DOOM II.app */; + productType = "com.apple.product-type.application"; + }; + A1B98DE9207EFEE800827A46 /* DOOM-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1B98E00207EFEEA00827A46 /* Build configuration list for PBXNativeTarget "DOOM-tvOS" */; + buildPhases = ( + A1B98DE8207EFEE800827A46 /* Resources */, + A1B98DE6207EFEE800827A46 /* Sources */, + A1B98DE7207EFEE800827A46 /* Frameworks */, + A1B98E9F207F066300827A46 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "DOOM-tvOS"; + productName = DoomTV; + productReference = A1B98DEA207EFEE800827A46 /* DOOM.app */; + productType = "com.apple.product-type.application"; + }; + A1DE849E229F60BE0041E450 /* SIGIL-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1DE85B1229F60BE0041E450 /* Build configuration list for PBXNativeTarget "SIGIL-iOS" */; + buildPhases = ( + A1DE849F229F60BE0041E450 /* Resources */, + A1DE84FE229F60BE0041E450 /* Sources */, + A1DE85A6229F60BE0041E450 /* Frameworks */, + A1DE85B0229F60BE0041E450 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SIGIL-iOS"; + productName = Doom; + productReference = A1DE85B8229F60BE0041E450 /* SIGIL.app */; + productType = "com.apple.product-type.application"; + }; + A1DE85C8229F88D20041E450 /* SIGL-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1DE86CD229F88D20041E450 /* Build configuration list for PBXNativeTarget "SIGL-tvOS" */; + buildPhases = ( + A1DE85C9229F88D20041E450 /* Resources */, + A1DE861C229F88D20041E450 /* Sources */, + A1DE86C2229F88D20041E450 /* Frameworks */, + A1DE86CC229F88D20041E450 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "SIGL-tvOS"; + productName = DoomTV; + productReference = A1DE86D4229F88D20041E450 /* SIGL.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1340; + TargetAttributes = { + A1B98DE9207EFEE800827A46 = { + CreatedOnToolsVersion = 9.3; + }; + }; + }; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DOOM" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = en; + hasScannedForEncodings = 1; + knownRegions = ( + Base, + de, + en, + ja, + fr, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ../..; + targets = ( + 1D6058900D05DD3D006BFB54 /* DOOM-iOS */, + A1B98DE9207EFEE800827A46 /* DOOM-tvOS */, + A1870806216EB633006C013F /* DOOM2-iOS */, + A10638C6216EF7C700BDE196 /* DOOM2-tvOS */, + A10639D5216EFCEE00BDE196 /* FInalDOOM-iOS */, + A1063AF4216F012000BDE196 /* FInalDOOM-tvOS */, + A1DE849E229F60BE0041E450 /* SIGIL-iOS */, + A1DE85C8229F88D20041E450 /* SIGL-tvOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 43CF02FF0F56974E00E4A23D /* Default.png in Resources */, + 4364BF3F0F5CB25900F29317 /* dist.plist in Resources */, + A1B9E45D21700601003E9731 /* DOOM-iOS.xcassets in Resources */, + C8D1CF6813DE1EB600F0EAC6 /* DOOM_57.png in Resources */, + C8D1CF6A13DE1EF500F0EAC6 /* DOOM_114.png in Resources */, + C8D1CF6C13DE1F0600F0EAC6 /* DOOM_72.png in Resources */, + C8D1CF8613DF792D00F0EAC6 /* Default@2x.png in Resources */, + C8D1CF8813DF79BC00F0EAC6 /* Default~ipad.png in Resources */, + C81E0E5E13E076E400B1049A /* idGinzaNar-Md2.otf in Resources */, + C81E104C13E1CCA000B1049A /* BackButton.png in Resources */, + C81E104D13E1CCA000B1049A /* Button.png in Resources */, + A1E89C902067469D00760204 /* CreditsMenuView.xib in Resources */, + A1A63DC220562B2B000955AE /* CreditsMenuView~ipad.xib in Resources */, + A1A63DC420562B2B000955AE /* SecretMenuView.xib in Resources */, + C81E104E13E1CCA000B1049A /* DOOM_sigil_decal.png in Resources */, + A1A184282063E63200302393 /* EpisodeCell.xib in Resources */, + C81E104F13E1CCA000B1049A /* DoomLogo.png in Resources */, + A1A63DC320562B2B000955AE /* ControlsMenuView~ipad.xib in Resources */, + C81E105013E1CCA000B1049A /* Easy.png in Resources */, + A1A63DE620562B76000955AE /* SettingsMenuView~ipad.xib in Resources */, + A1A63DEB20562B76000955AE /* MainMenuView.xib in Resources */, + C81E105113E1CCA000B1049A /* Hard.png in Resources */, + A1A63DF420562B76000955AE /* MainMenuView~ipad.xib in Resources */, + A1A63E1A20562FC4000955AE /* DOOM_144.png in Resources */, + C81E105213E1CCA000B1049A /* MapOverlay.png in Resources */, + C81E105313E1CCA000B1049A /* Medium.png in Resources */, + C81E105413E1CCA000B1049A /* MenuBackground.png in Resources */, + A1A63E3320563345000955AE /* r_drawcolpipeline.inl in Resources */, + A1063C09216F096900BDE196 /* doom.wad in Resources */, + A1A63DBF20562B2B000955AE /* ControlsMenuView.xib in Resources */, + C81E105513E1CCA000B1049A /* Nightmare.png in Resources */, + C81E105613E1CCA000B1049A /* ResumeButton.png in Resources */, + A1A63DE720562B76000955AE /* EpisodeMenuView.xib in Resources */, + A1A63E3620563345000955AE /* Makefile.am in Resources */, + C81E105713E1CCA000B1049A /* SelectedBracket.png in Resources */, + C8D1CFA813E1CDBD00F0EAC6 /* Default-Portrait~ipad.png in Resources */, + C8D1CFAA13E1CDC600F0EAC6 /* Default-Landscape~ipad.png in Resources */, + A1A63DF220562B76000955AE /* SettingsMenuView.xib in Resources */, + C8792ED813F5AFE5003D834F /* BackButton_Highlighted.png in Resources */, + C8792ED913F5AFE6003D834F /* Button_Highlighted.png in Resources */, + C8792EDA13F5AFE6003D834F /* NextButton_Highlighted.png in Resources */, + C8792EDB13F5AFE6003D834F /* NextButton.png in Resources */, + C8792EDC13F5AFE6003D834F /* SubMenuBackground.png in Resources */, + C8792EDD13F5AFE6003D834F /* SubMenuButton_Highlighted.png in Resources */, + C8792EDE13F5AFE6003D834F /* SubMenuButton.png in Resources */, + A1A63DF520562B76000955AE /* EpisodeMenuView~ipad.xib in Resources */, + C879308F13F5D8AA003D834F /* DifficultyBackground.png in Resources */, + C879309013F5D8AA003D834F /* DownArrow_Highlighted.png in Resources */, + C879309113F5D8AA003D834F /* DownArrow.png in Resources */, + C879309213F5D8AA003D834F /* Episode1Background.png in Resources */, + C879309313F5D8AA003D834F /* Episode2Background.png in Resources */, + C879309413F5D8AA003D834F /* Episode3Background.png in Resources */, + A1A63E1120562FB0000955AE /* Localizable.strings in Resources */, + C879309513F5D8AA003D834F /* Episode4Background.png in Resources */, + C879309613F5D8AA003D834F /* MissonBackground.png in Resources */, + A11290502069B62B00BEDEB5 /* DOOMLaunchScreen.storyboard in Resources */, + C879309713F5D8AA003D834F /* UpArrow_Highlighted.png in Resources */, + C879309813F5D8AA003D834F /* UpArrow.png in Resources */, + A1A63E3920563345000955AE /* r_drawspan.inl in Resources */, + A1EA3B87207F9DE20038650E /* DOOM_400.png in Resources */, + C87930E513F5EC1B003D834F /* Episode1Background_Highlighted.png in Resources */, + C87930E613F5EC1B003D834F /* Episode2Background_Highlighted.png in Resources */, + C87930E713F5EC1B003D834F /* Episode3Background_Highlighted.png in Resources */, + C87930E813F5EC1B003D834F /* Episode4Background_Highlighted.png in Resources */, + A1A63DE320562B76000955AE /* MissionMenuView~ipad.xib in Resources */, + A1A63DFA20562B76000955AE /* OpenGLView~ipad.xib in Resources */, + A176AC09206492DD00A96B7E /* EpisodeCell~ipad.xib in Resources */, + C87931EC13F610B9003D834F /* AdvancedButton_Highlighted.png in Resources */, + A1A63DE820562B76000955AE /* LegalMenuView~ipad.xib in Resources */, + A1A63E1C20562FC4000955AE /* DOOM_76.png in Resources */, + C87931ED13F610B9003D834F /* AdvancedButton.png in Resources */, + C87931EE13F610B9003D834F /* Divide.png in Resources */, + C87931EF13F610B9003D834F /* LayoutDualButton_Highlighted.png in Resources */, + C87931F013F610B9003D834F /* LayoutDualButton.png in Resources */, + A1A63E1B20562FC4000955AE /* DOOM_120.png in Resources */, + C87931F113F610B9003D834F /* LayoutSingleButton_Highlighted.png in Resources */, + C87931F213F610B9003D834F /* LayoutSingleButton.png in Resources */, + C87931F313F610B9003D834F /* LayoutWheelButton_Highlighted.png in Resources */, + A1A63E3820563345000955AE /* r_drawflush.inl in Resources */, + C87931F413F610B9003D834F /* LayoutWheelButton.png in Resources */, + C87931F513F610B9003D834F /* SettingsButton_Highlighted.png in Resources */, + C87931F613F610B9003D834F /* SettingsButton.png in Resources */, + A1A63E1920562FC4000955AE /* DOOM_152.png in Resources */, + C87931F713F610B9003D834F /* SliderBackground.png in Resources */, + C87931F813F610B9003D834F /* SliderBar.png in Resources */, + A12302FB205783E70075CBAD /* prboom.wad in Resources */, + A12302FD205783E70075CBAD /* base.iPack in Resources */, + A1A63DEF20562B76000955AE /* OpenGLView.xib in Resources */, + A1A63E3520563345000955AE /* r_drawcolumn.inl in Resources */, + C87931F913F610B9003D834F /* SliderSkull.png in Resources */, + A1A63DE920562B76000955AE /* MissionMenuView.xib in Resources */, + C8139AB313FADA800094C2C0 /* SliderSkull@2x.png in Resources */, + C8139AB513FADA9D0094C2C0 /* SliderSkull~ipad.png in Resources */, + A1A63DF820562B76000955AE /* LegalMenuView.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A10638C7216EF7C700BDE196 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A10638C8216EF7C700BDE196 /* Default.png in Resources */, + A10638C9216EF7C700BDE196 /* r_drawflush.inl in Resources */, + A10638CA216EF7C700BDE196 /* SliderSkull~ipad.png in Resources */, + A10638CB216EF7C700BDE196 /* SliderSkull@2x.png in Resources */, + A10638CC216EF7C700BDE196 /* AdvancedButton_Highlighted.png in Resources */, + A10638CD216EF7C700BDE196 /* AdvancedButton.png in Resources */, + A10638CE216EF7C700BDE196 /* Divide.png in Resources */, + A10638CF216EF7C700BDE196 /* LayoutDualButton_Highlighted.png in Resources */, + A10638D0216EF7C700BDE196 /* LayoutDualButton.png in Resources */, + A10638D1216EF7C700BDE196 /* LayoutSingleButton_Highlighted.png in Resources */, + A10638D2216EF7C700BDE196 /* LayoutSingleButton.png in Resources */, + A10638D3216EF7C700BDE196 /* Localizable.strings in Resources */, + A10638D4216EF7C700BDE196 /* LayoutWheelButton_Highlighted.png in Resources */, + A10638D5216EF7C700BDE196 /* LayoutWheelButton.png in Resources */, + A10638D6216EF7C700BDE196 /* SettingsButton_Highlighted.png in Resources */, + A10638D7216EF7C700BDE196 /* SettingsButton.png in Resources */, + A10638D8216EF7C700BDE196 /* r_drawspan.inl in Resources */, + A10638D9216EF7C700BDE196 /* SliderBackground.png in Resources */, + A10638DA216EF7C700BDE196 /* SliderBar.png in Resources */, + A10638DB216EF7C700BDE196 /* SliderSkull.png in Resources */, + A10638DC216EF7C700BDE196 /* Episode1Background_Highlighted.png in Resources */, + A10638DD216EF7C700BDE196 /* Episode2Background_Highlighted.png in Resources */, + A10638DE216EF7C700BDE196 /* Episode3Background_Highlighted.png in Resources */, + A10638DF216EF7C700BDE196 /* Episode4Background_Highlighted.png in Resources */, + A10638E0216EF7C700BDE196 /* DifficultyBackground.png in Resources */, + A10638E1216EF7C700BDE196 /* DownArrow_Highlighted.png in Resources */, + A10638E2216EF7C700BDE196 /* DownArrow.png in Resources */, + A10638E3216EF7C700BDE196 /* Episode1Background.png in Resources */, + A10638E4216EF7C700BDE196 /* Episode2Background.png in Resources */, + A10638E5216EF7C700BDE196 /* Episode3Background.png in Resources */, + A10638E6216EF7C700BDE196 /* r_drawcolpipeline.inl in Resources */, + A10638E7216EF7C700BDE196 /* Episode4Background.png in Resources */, + A10638E8216EF7C700BDE196 /* MissonBackground.png in Resources */, + A10638E9216EF7C700BDE196 /* Makefile.am in Resources */, + A10638EA216EF7C700BDE196 /* UpArrow_Highlighted.png in Resources */, + A10638EB216EF7C700BDE196 /* UpArrow.png in Resources */, + A10638EC216EF7C700BDE196 /* BackButton_Highlighted.png in Resources */, + A10638ED216EF7C700BDE196 /* Button_Highlighted.png in Resources */, + A10638EE216EF7C700BDE196 /* NextButton_Highlighted.png in Resources */, + A10638EF216EF7C700BDE196 /* NextButton.png in Resources */, + A10638F0216EF7C700BDE196 /* SubMenuBackground.png in Resources */, + A10638F1216EF7C700BDE196 /* SubMenuButton_Highlighted.png in Resources */, + A10638F2216EF7C700BDE196 /* SubMenuButton.png in Resources */, + A10638F3216EF7C700BDE196 /* BackButton.png in Resources */, + A10638F4216EF7C700BDE196 /* Button.png in Resources */, + A10638F5216EF7C700BDE196 /* DOOM_sigil_decal.png in Resources */, + A10638F6216EF7C700BDE196 /* DoomLogo.png in Resources */, + A1D3993A2171A0A800FD11C3 /* DOOM2-tvOS.xcassets in Resources */, + A10638F7216EF7C700BDE196 /* Easy.png in Resources */, + A10638F8216EF7C700BDE196 /* Hard.png in Resources */, + A10638F9216EF7C700BDE196 /* MapOverlay.png in Resources */, + A10638FA216EF7C700BDE196 /* Medium.png in Resources */, + A10638FB216EF7C700BDE196 /* MenuBackground.png in Resources */, + A10638FC216EF7C700BDE196 /* Nightmare.png in Resources */, + A10638FD216EF7C700BDE196 /* ResumeButton.png in Resources */, + A10638FE216EF7C700BDE196 /* SelectedBracket.png in Resources */, + A10638FF216EF7C700BDE196 /* idGinzaNar-Md2.otf in Resources */, + A1063900216EF7C700BDE196 /* dist.plist in Resources */, + A1063901216EF7C700BDE196 /* EpisodeCell-tvos.xib in Resources */, + A1063902216EF7C700BDE196 /* base.iPack in Resources */, + A1063904216EF7C700BDE196 /* prboom.wad in Resources */, + A1063905216EF7C700BDE196 /* DOOM_76.png in Resources */, + A1063906216EF7C700BDE196 /* r_drawcolumn.inl in Resources */, + A1063907216EF7C700BDE196 /* DOOM_120.png in Resources */, + A10639D4216EF86700BDE196 /* doom2.wad in Resources */, + A1063908216EF7C700BDE196 /* DOOM_144.png in Resources */, + A1063909216EF7C700BDE196 /* DOOM_152.png in Resources */, + A106390A216EF7C700BDE196 /* Default-Landscape~ipad.png in Resources */, + A106390B216EF7C700BDE196 /* Default-Portrait~ipad.png in Resources */, + A106390C216EF7C700BDE196 /* Default@2x.png in Resources */, + A106390D216EF7C700BDE196 /* Default~ipad.png in Resources */, + A106390E216EF7C700BDE196 /* DOOM_57.png in Resources */, + A106390F216EF7C700BDE196 /* DOOM_72.png in Resources */, + A1063910216EF7C700BDE196 /* DOOM_114.png in Resources */, + A1063911216EF7C700BDE196 /* MainMenuView-tvos.xib in Resources */, + A1063913216EF7C700BDE196 /* MissionMenuView-tvos.xib in Resources */, + A1063914216EF7C700BDE196 /* OpenGLView-tvos.xib in Resources */, + A1063915216EF7C700BDE196 /* EpisodeMenuView-tvos.xib in Resources */, + A1063916216EF7C700BDE196 /* SettingsMenuView-tvos.xib in Resources */, + A1063917216EF7C700BDE196 /* CreditsMenuView-tvos.xib in Resources */, + A1063918216EF7C700BDE196 /* ControlsMenuView-tvos.xib in Resources */, + A1063919216EF7C700BDE196 /* LegalMenuView-tvos.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A10639D6216EFCEE00BDE196 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A10639D7216EFCEE00BDE196 /* Default.png in Resources */, + A10639D8216EFCEE00BDE196 /* dist.plist in Resources */, + A10639D9216EFCEE00BDE196 /* DOOM_57.png in Resources */, + A10639DA216EFCEE00BDE196 /* DOOM_114.png in Resources */, + A10639DB216EFCEE00BDE196 /* DOOM_72.png in Resources */, + A10639DC216EFCEE00BDE196 /* Default@2x.png in Resources */, + A10639DD216EFCEE00BDE196 /* Default~ipad.png in Resources */, + A10639DE216EFCEE00BDE196 /* idGinzaNar-Md2.otf in Resources */, + A10639DF216EFCEE00BDE196 /* BackButton.png in Resources */, + A10639E0216EFCEE00BDE196 /* Button.png in Resources */, + A10639E1216EFCEE00BDE196 /* CreditsMenuView.xib in Resources */, + A10639E2216EFCEE00BDE196 /* CreditsMenuView~ipad.xib in Resources */, + A10639E3216EFCEE00BDE196 /* SecretMenuView.xib in Resources */, + A10639E4216EFCEE00BDE196 /* DOOM_sigil_decal.png in Resources */, + A10639E5216EFCEE00BDE196 /* EpisodeCell.xib in Resources */, + A10639E6216EFCEE00BDE196 /* DoomLogo.png in Resources */, + A10639E7216EFCEE00BDE196 /* ControlsMenuView~ipad.xib in Resources */, + A10639E8216EFCEE00BDE196 /* Easy.png in Resources */, + A10639E9216EFCEE00BDE196 /* SettingsMenuView~ipad.xib in Resources */, + A10639EA216EFCEE00BDE196 /* MainMenuView.xib in Resources */, + A10639EB216EFCEE00BDE196 /* Hard.png in Resources */, + A10639EC216EFCEE00BDE196 /* MainMenuView~ipad.xib in Resources */, + A1D39933217144A800FD11C3 /* FinalDOOMLaunchScreen.storyboard in Resources */, + A10639ED216EFCEE00BDE196 /* DOOM_144.png in Resources */, + A10639EE216EFCEE00BDE196 /* MapOverlay.png in Resources */, + A10639EF216EFCEE00BDE196 /* Medium.png in Resources */, + A10639F0216EFCEE00BDE196 /* MenuBackground.png in Resources */, + A1063AF3216EFD9900BDE196 /* plutonia.wad in Resources */, + A10639F1216EFCEE00BDE196 /* r_drawcolpipeline.inl in Resources */, + A10639F2216EFCEE00BDE196 /* ControlsMenuView.xib in Resources */, + A10639F3216EFCEE00BDE196 /* Nightmare.png in Resources */, + A10639F4216EFCEE00BDE196 /* ResumeButton.png in Resources */, + A10639F5216EFCEE00BDE196 /* EpisodeMenuView.xib in Resources */, + A10639F6216EFCEE00BDE196 /* Makefile.am in Resources */, + A10639F7216EFCEE00BDE196 /* SelectedBracket.png in Resources */, + A10639F8216EFCEE00BDE196 /* Default-Portrait~ipad.png in Resources */, + A10639F9216EFCEE00BDE196 /* Default-Landscape~ipad.png in Resources */, + A10639FA216EFCEE00BDE196 /* SettingsMenuView.xib in Resources */, + A1D39934217144B500FD11C3 /* FinalDOOM-iOS.xcassets in Resources */, + A10639FB216EFCEE00BDE196 /* BackButton_Highlighted.png in Resources */, + A1063AF2216EFD9900BDE196 /* tnt.wad in Resources */, + A10639FC216EFCEE00BDE196 /* Button_Highlighted.png in Resources */, + A10639FD216EFCEE00BDE196 /* NextButton_Highlighted.png in Resources */, + A10639FE216EFCEE00BDE196 /* NextButton.png in Resources */, + A10639FF216EFCEE00BDE196 /* SubMenuBackground.png in Resources */, + A1063A00216EFCEE00BDE196 /* SubMenuButton_Highlighted.png in Resources */, + A1063A01216EFCEE00BDE196 /* SubMenuButton.png in Resources */, + A1063A02216EFCEE00BDE196 /* EpisodeMenuView~ipad.xib in Resources */, + A1063A03216EFCEE00BDE196 /* DifficultyBackground.png in Resources */, + A1063A04216EFCEE00BDE196 /* DownArrow_Highlighted.png in Resources */, + A1063A05216EFCEE00BDE196 /* DownArrow.png in Resources */, + A1063A06216EFCEE00BDE196 /* Episode1Background.png in Resources */, + A1063A07216EFCEE00BDE196 /* Episode2Background.png in Resources */, + A1063A08216EFCEE00BDE196 /* Episode3Background.png in Resources */, + A1063A09216EFCEE00BDE196 /* Localizable.strings in Resources */, + A1063A0A216EFCEE00BDE196 /* Episode4Background.png in Resources */, + A1063A0B216EFCEE00BDE196 /* MissonBackground.png in Resources */, + A1063A0C216EFCEE00BDE196 /* DOOMLaunchScreen.storyboard in Resources */, + A1063A0D216EFCEE00BDE196 /* UpArrow_Highlighted.png in Resources */, + A1063A0E216EFCEE00BDE196 /* UpArrow.png in Resources */, + A1063A0F216EFCEE00BDE196 /* r_drawspan.inl in Resources */, + A1063A10216EFCEE00BDE196 /* DOOM_400.png in Resources */, + A1063A11216EFCEE00BDE196 /* Episode1Background_Highlighted.png in Resources */, + A1063A12216EFCEE00BDE196 /* Episode2Background_Highlighted.png in Resources */, + A1063A13216EFCEE00BDE196 /* Episode3Background_Highlighted.png in Resources */, + A1063A14216EFCEE00BDE196 /* Episode4Background_Highlighted.png in Resources */, + A1063A15216EFCEE00BDE196 /* MissionMenuView~ipad.xib in Resources */, + A1063A16216EFCEE00BDE196 /* OpenGLView~ipad.xib in Resources */, + A1063A17216EFCEE00BDE196 /* EpisodeCell~ipad.xib in Resources */, + A1063A18216EFCEE00BDE196 /* AdvancedButton_Highlighted.png in Resources */, + A1063A19216EFCEE00BDE196 /* LegalMenuView~ipad.xib in Resources */, + A1063A1A216EFCEE00BDE196 /* DOOM_76.png in Resources */, + A1063A1B216EFCEE00BDE196 /* AdvancedButton.png in Resources */, + A1063A1C216EFCEE00BDE196 /* Divide.png in Resources */, + A1063A1D216EFCEE00BDE196 /* LayoutDualButton_Highlighted.png in Resources */, + A1063A1E216EFCEE00BDE196 /* LayoutDualButton.png in Resources */, + A1063A1F216EFCEE00BDE196 /* DOOM_120.png in Resources */, + A1063A20216EFCEE00BDE196 /* LayoutSingleButton_Highlighted.png in Resources */, + A1063A21216EFCEE00BDE196 /* LayoutSingleButton.png in Resources */, + A1063A22216EFCEE00BDE196 /* LayoutWheelButton_Highlighted.png in Resources */, + A1063A23216EFCEE00BDE196 /* r_drawflush.inl in Resources */, + A1063A24216EFCEE00BDE196 /* LayoutWheelButton.png in Resources */, + A1063A25216EFCEE00BDE196 /* SettingsButton_Highlighted.png in Resources */, + A1063A26216EFCEE00BDE196 /* SettingsButton.png in Resources */, + A1063A27216EFCEE00BDE196 /* DOOM_152.png in Resources */, + A1063A28216EFCEE00BDE196 /* SliderBackground.png in Resources */, + A1063A29216EFCEE00BDE196 /* SliderBar.png in Resources */, + A1063A2A216EFCEE00BDE196 /* prboom.wad in Resources */, + A1063A2C216EFCEE00BDE196 /* base.iPack in Resources */, + A1063A2D216EFCEE00BDE196 /* OpenGLView.xib in Resources */, + A1063A2E216EFCEE00BDE196 /* r_drawcolumn.inl in Resources */, + A1063A2F216EFCEE00BDE196 /* SliderSkull.png in Resources */, + A1063A30216EFCEE00BDE196 /* MissionMenuView.xib in Resources */, + A1063A31216EFCEE00BDE196 /* SliderSkull@2x.png in Resources */, + A1063A32216EFCEE00BDE196 /* SliderSkull~ipad.png in Resources */, + A1063A33216EFCEE00BDE196 /* LegalMenuView.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1063AF5216F012000BDE196 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1063AF6216F012000BDE196 /* Default.png in Resources */, + A1063AF7216F012000BDE196 /* r_drawflush.inl in Resources */, + A1063AF8216F012000BDE196 /* SliderSkull~ipad.png in Resources */, + A1063AF9216F012000BDE196 /* SliderSkull@2x.png in Resources */, + A1063AFA216F012000BDE196 /* AdvancedButton_Highlighted.png in Resources */, + A1063AFB216F012000BDE196 /* AdvancedButton.png in Resources */, + A1063AFC216F012000BDE196 /* Divide.png in Resources */, + A1063AFD216F012000BDE196 /* LayoutDualButton_Highlighted.png in Resources */, + A1063AFE216F012000BDE196 /* LayoutDualButton.png in Resources */, + A1063AFF216F012000BDE196 /* LayoutSingleButton_Highlighted.png in Resources */, + A1063B00216F012000BDE196 /* LayoutSingleButton.png in Resources */, + A1063B01216F012000BDE196 /* Localizable.strings in Resources */, + A1063B02216F012000BDE196 /* LayoutWheelButton_Highlighted.png in Resources */, + A1063B03216F012000BDE196 /* LayoutWheelButton.png in Resources */, + A1063B04216F012000BDE196 /* SettingsButton_Highlighted.png in Resources */, + A1063B05216F012000BDE196 /* SettingsButton.png in Resources */, + A1063B06216F012000BDE196 /* r_drawspan.inl in Resources */, + A1063B07216F012000BDE196 /* SliderBackground.png in Resources */, + A1063B08216F012000BDE196 /* SliderBar.png in Resources */, + A1063B09216F012000BDE196 /* SliderSkull.png in Resources */, + A1063B0A216F012000BDE196 /* Episode1Background_Highlighted.png in Resources */, + A1063B0B216F012000BDE196 /* Episode2Background_Highlighted.png in Resources */, + A1063B0C216F012000BDE196 /* Episode3Background_Highlighted.png in Resources */, + A1063B0D216F012000BDE196 /* Episode4Background_Highlighted.png in Resources */, + A1063B0E216F012000BDE196 /* DifficultyBackground.png in Resources */, + A1063B0F216F012000BDE196 /* DownArrow_Highlighted.png in Resources */, + A1063B10216F012000BDE196 /* DownArrow.png in Resources */, + A1063B11216F012000BDE196 /* Episode1Background.png in Resources */, + A1063B12216F012000BDE196 /* Episode2Background.png in Resources */, + A1063B13216F012000BDE196 /* Episode3Background.png in Resources */, + A1063B14216F012000BDE196 /* r_drawcolpipeline.inl in Resources */, + A1063B15216F012000BDE196 /* Episode4Background.png in Resources */, + A1063B16216F012000BDE196 /* MissonBackground.png in Resources */, + A1063B17216F012000BDE196 /* Makefile.am in Resources */, + A1063B18216F012000BDE196 /* UpArrow_Highlighted.png in Resources */, + A1063B19216F012000BDE196 /* UpArrow.png in Resources */, + A1063B1A216F012000BDE196 /* BackButton_Highlighted.png in Resources */, + A1063B1B216F012000BDE196 /* Button_Highlighted.png in Resources */, + A1063B1C216F012000BDE196 /* NextButton_Highlighted.png in Resources */, + A1063B1D216F012000BDE196 /* NextButton.png in Resources */, + A1063B1E216F012000BDE196 /* SubMenuBackground.png in Resources */, + A1063B1F216F012000BDE196 /* SubMenuButton_Highlighted.png in Resources */, + A1063B20216F012000BDE196 /* SubMenuButton.png in Resources */, + A1063B21216F012000BDE196 /* BackButton.png in Resources */, + A1063B22216F012000BDE196 /* Button.png in Resources */, + A1063B23216F012000BDE196 /* DOOM_sigil_decal.png in Resources */, + A1063B24216F012000BDE196 /* DoomLogo.png in Resources */, + A1063B25216F012000BDE196 /* Easy.png in Resources */, + A1063B26216F012000BDE196 /* Hard.png in Resources */, + A1063B27216F012000BDE196 /* MapOverlay.png in Resources */, + A1063B28216F012000BDE196 /* Medium.png in Resources */, + A1063B29216F012000BDE196 /* MenuBackground.png in Resources */, + A1063B2A216F012000BDE196 /* Nightmare.png in Resources */, + A1063B2B216F012000BDE196 /* ResumeButton.png in Resources */, + A1063C0B216F0B1D00BDE196 /* plutonia.wad in Resources */, + A1063B2C216F012000BDE196 /* SelectedBracket.png in Resources */, + A1063B2D216F012000BDE196 /* idGinzaNar-Md2.otf in Resources */, + A1063B2E216F012000BDE196 /* dist.plist in Resources */, + A1063B2F216F012000BDE196 /* EpisodeCell-tvos.xib in Resources */, + A1063B30216F012000BDE196 /* base.iPack in Resources */, + A1063B32216F012000BDE196 /* prboom.wad in Resources */, + A1063B33216F012000BDE196 /* DOOM_76.png in Resources */, + A1063B34216F012000BDE196 /* r_drawcolumn.inl in Resources */, + A1063B35216F012000BDE196 /* DOOM_120.png in Resources */, + A1063B37216F012000BDE196 /* DOOM_144.png in Resources */, + A1D3993D2171A0FD00FD11C3 /* FinalDOOM-tvOS.xcassets in Resources */, + A1063B38216F012000BDE196 /* DOOM_152.png in Resources */, + A1063B39216F012000BDE196 /* Default-Landscape~ipad.png in Resources */, + A1063B3A216F012000BDE196 /* Default-Portrait~ipad.png in Resources */, + A1063B3B216F012000BDE196 /* Default@2x.png in Resources */, + A1063B3C216F012000BDE196 /* Default~ipad.png in Resources */, + A1063B3D216F012000BDE196 /* DOOM_57.png in Resources */, + A1063B3E216F012000BDE196 /* DOOM_72.png in Resources */, + A1063B3F216F012000BDE196 /* DOOM_114.png in Resources */, + A1063B40216F012000BDE196 /* MainMenuView-tvos.xib in Resources */, + A1063B42216F012000BDE196 /* MissionMenuView-tvos.xib in Resources */, + A1063B43216F012000BDE196 /* OpenGLView-tvos.xib in Resources */, + A1063B44216F012000BDE196 /* EpisodeMenuView-tvos.xib in Resources */, + A1063B45216F012000BDE196 /* SettingsMenuView-tvos.xib in Resources */, + A1063B46216F012000BDE196 /* CreditsMenuView-tvos.xib in Resources */, + A1063C0C216F0B2100BDE196 /* tnt.wad in Resources */, + A1063B47216F012000BDE196 /* ControlsMenuView-tvos.xib in Resources */, + A1063B48216F012000BDE196 /* LegalMenuView-tvos.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1870807216EB633006C013F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1870808216EB633006C013F /* Default.png in Resources */, + A1870809216EB633006C013F /* dist.plist in Resources */, + A187080A216EB633006C013F /* DOOM_57.png in Resources */, + A187080B216EB633006C013F /* DOOM_114.png in Resources */, + A187080C216EB633006C013F /* DOOM_72.png in Resources */, + A187080D216EB633006C013F /* Default@2x.png in Resources */, + A1D399362171462F00FD11C3 /* DOOM2LaunchScreen.storyboard in Resources */, + A187080E216EB633006C013F /* Default~ipad.png in Resources */, + A187080F216EB633006C013F /* idGinzaNar-Md2.otf in Resources */, + A1870810216EB633006C013F /* BackButton.png in Resources */, + A1870811216EB633006C013F /* Button.png in Resources */, + A1870812216EB633006C013F /* CreditsMenuView.xib in Resources */, + A1870813216EB633006C013F /* CreditsMenuView~ipad.xib in Resources */, + A1870814216EB633006C013F /* SecretMenuView.xib in Resources */, + A1870815216EB633006C013F /* DOOM_sigil_decal.png in Resources */, + A1870816216EB633006C013F /* EpisodeCell.xib in Resources */, + A1870817216EB633006C013F /* DoomLogo.png in Resources */, + A1870818216EB633006C013F /* ControlsMenuView~ipad.xib in Resources */, + A1870819216EB633006C013F /* Easy.png in Resources */, + A187081A216EB633006C013F /* SettingsMenuView~ipad.xib in Resources */, + A187081B216EB633006C013F /* MainMenuView.xib in Resources */, + A187081C216EB633006C013F /* Hard.png in Resources */, + A187081D216EB633006C013F /* MainMenuView~ipad.xib in Resources */, + A187081E216EB633006C013F /* DOOM_144.png in Resources */, + A187081F216EB633006C013F /* MapOverlay.png in Resources */, + A1870820216EB633006C013F /* Medium.png in Resources */, + A1870821216EB633006C013F /* MenuBackground.png in Resources */, + A1870822216EB633006C013F /* r_drawcolpipeline.inl in Resources */, + A1870823216EB633006C013F /* ControlsMenuView.xib in Resources */, + A1870824216EB633006C013F /* Nightmare.png in Resources */, + A1870825216EB633006C013F /* ResumeButton.png in Resources */, + A1870826216EB633006C013F /* EpisodeMenuView.xib in Resources */, + A1870827216EB633006C013F /* Makefile.am in Resources */, + A1870828216EB633006C013F /* SelectedBracket.png in Resources */, + A1870829216EB633006C013F /* Default-Portrait~ipad.png in Resources */, + A187082A216EB633006C013F /* Default-Landscape~ipad.png in Resources */, + A187082B216EB633006C013F /* SettingsMenuView.xib in Resources */, + A187082C216EB633006C013F /* BackButton_Highlighted.png in Resources */, + A1B9E45F217006D2003E9731 /* DOOM2-iOS.xcassets in Resources */, + A187082D216EB633006C013F /* Button_Highlighted.png in Resources */, + A187082E216EB633006C013F /* NextButton_Highlighted.png in Resources */, + A187082F216EB633006C013F /* NextButton.png in Resources */, + A1870830216EB633006C013F /* SubMenuBackground.png in Resources */, + A1870831216EB633006C013F /* SubMenuButton_Highlighted.png in Resources */, + A1870832216EB633006C013F /* SubMenuButton.png in Resources */, + A1870833216EB633006C013F /* EpisodeMenuView~ipad.xib in Resources */, + A1870834216EB633006C013F /* DifficultyBackground.png in Resources */, + A1870835216EB633006C013F /* DownArrow_Highlighted.png in Resources */, + A1870836216EB633006C013F /* DownArrow.png in Resources */, + A1870837216EB633006C013F /* Episode1Background.png in Resources */, + A1870838216EB633006C013F /* Episode2Background.png in Resources */, + A1870839216EB633006C013F /* Episode3Background.png in Resources */, + A187083A216EB633006C013F /* Localizable.strings in Resources */, + A187083B216EB633006C013F /* Episode4Background.png in Resources */, + A187083C216EB633006C013F /* MissonBackground.png in Resources */, + A187083D216EB633006C013F /* DOOMLaunchScreen.storyboard in Resources */, + A187083E216EB633006C013F /* UpArrow_Highlighted.png in Resources */, + A187083F216EB633006C013F /* UpArrow.png in Resources */, + A1870840216EB633006C013F /* r_drawspan.inl in Resources */, + A1870841216EB633006C013F /* DOOM_400.png in Resources */, + A1870842216EB633006C013F /* Episode1Background_Highlighted.png in Resources */, + A1870843216EB633006C013F /* Episode2Background_Highlighted.png in Resources */, + A1870844216EB633006C013F /* Episode3Background_Highlighted.png in Resources */, + A1870845216EB633006C013F /* Episode4Background_Highlighted.png in Resources */, + A1870846216EB633006C013F /* MissionMenuView~ipad.xib in Resources */, + A1870847216EB633006C013F /* OpenGLView~ipad.xib in Resources */, + A1870848216EB633006C013F /* EpisodeCell~ipad.xib in Resources */, + A1870849216EB633006C013F /* AdvancedButton_Highlighted.png in Resources */, + A187084A216EB633006C013F /* LegalMenuView~ipad.xib in Resources */, + A187084B216EB633006C013F /* DOOM_76.png in Resources */, + A187084C216EB633006C013F /* AdvancedButton.png in Resources */, + A187084D216EB633006C013F /* Divide.png in Resources */, + A187084E216EB633006C013F /* LayoutDualButton_Highlighted.png in Resources */, + A187084F216EB633006C013F /* LayoutDualButton.png in Resources */, + A1870850216EB633006C013F /* DOOM_120.png in Resources */, + A1870851216EB633006C013F /* LayoutSingleButton_Highlighted.png in Resources */, + A1870852216EB633006C013F /* LayoutSingleButton.png in Resources */, + A1870853216EB633006C013F /* LayoutWheelButton_Highlighted.png in Resources */, + A1870854216EB633006C013F /* r_drawflush.inl in Resources */, + A1870855216EB633006C013F /* LayoutWheelButton.png in Resources */, + A1870856216EB633006C013F /* SettingsButton_Highlighted.png in Resources */, + A1870857216EB633006C013F /* SettingsButton.png in Resources */, + A1870858216EB633006C013F /* DOOM_152.png in Resources */, + A1870859216EB633006C013F /* SliderBackground.png in Resources */, + A187085A216EB633006C013F /* SliderBar.png in Resources */, + A187085B216EB633006C013F /* prboom.wad in Resources */, + A10638C3216EBC5A00BDE196 /* doom2.wad in Resources */, + A187085D216EB633006C013F /* base.iPack in Resources */, + A187085E216EB633006C013F /* OpenGLView.xib in Resources */, + A187085F216EB633006C013F /* r_drawcolumn.inl in Resources */, + A1870860216EB633006C013F /* SliderSkull.png in Resources */, + A1870861216EB633006C013F /* MissionMenuView.xib in Resources */, + A1870862216EB633006C013F /* SliderSkull@2x.png in Resources */, + A1870863216EB633006C013F /* SliderSkull~ipad.png in Resources */, + A1870864216EB633006C013F /* LegalMenuView.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1B98DE8207EFEE800827A46 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1B98E65207F026900827A46 /* Default.png in Resources */, + A1B98F90207F07E300827A46 /* r_drawflush.inl in Resources */, + A1B98E33207F025600827A46 /* SliderSkull~ipad.png in Resources */, + A1B98E34207F025600827A46 /* SliderSkull@2x.png in Resources */, + A1B98E35207F025600827A46 /* AdvancedButton_Highlighted.png in Resources */, + A1B98E36207F025600827A46 /* AdvancedButton.png in Resources */, + A1B98E37207F025600827A46 /* Divide.png in Resources */, + A1B98E38207F025600827A46 /* LayoutDualButton_Highlighted.png in Resources */, + A1B98E39207F025600827A46 /* LayoutDualButton.png in Resources */, + A1B98E3A207F025600827A46 /* LayoutSingleButton_Highlighted.png in Resources */, + A1B98E3B207F025600827A46 /* LayoutSingleButton.png in Resources */, + A1B98E97207F05F500827A46 /* Localizable.strings in Resources */, + A1B98E3C207F025600827A46 /* LayoutWheelButton_Highlighted.png in Resources */, + A1B98E3D207F025600827A46 /* LayoutWheelButton.png in Resources */, + A1B98E3E207F025600827A46 /* SettingsButton_Highlighted.png in Resources */, + A1B98E3F207F025600827A46 /* SettingsButton.png in Resources */, + A1B98F91207F07E300827A46 /* r_drawspan.inl in Resources */, + A1B98E40207F025600827A46 /* SliderBackground.png in Resources */, + A1B98E41207F025600827A46 /* SliderBar.png in Resources */, + A1B98E42207F025600827A46 /* SliderSkull.png in Resources */, + A1B98E43207F025600827A46 /* Episode1Background_Highlighted.png in Resources */, + A1063C0A216F096A00BDE196 /* doom.wad in Resources */, + A1B98E44207F025600827A46 /* Episode2Background_Highlighted.png in Resources */, + A1B98E45207F025600827A46 /* Episode3Background_Highlighted.png in Resources */, + A1B98E46207F025600827A46 /* Episode4Background_Highlighted.png in Resources */, + A1B98E47207F025600827A46 /* DifficultyBackground.png in Resources */, + A1B98E48207F025600827A46 /* DownArrow_Highlighted.png in Resources */, + A1B98E49207F025600827A46 /* DownArrow.png in Resources */, + A1B98E4A207F025600827A46 /* Episode1Background.png in Resources */, + A1B98E4B207F025600827A46 /* Episode2Background.png in Resources */, + A1B98E4C207F025600827A46 /* Episode3Background.png in Resources */, + A1B98F8E207F07E300827A46 /* r_drawcolpipeline.inl in Resources */, + A1B98E4D207F025600827A46 /* Episode4Background.png in Resources */, + A1B98E4E207F025600827A46 /* MissonBackground.png in Resources */, + A1B98F92207F07F900827A46 /* Makefile.am in Resources */, + A1B98E4F207F025600827A46 /* UpArrow_Highlighted.png in Resources */, + A1B98E50207F025600827A46 /* UpArrow.png in Resources */, + A1B98E51207F025600827A46 /* BackButton_Highlighted.png in Resources */, + A1B98E52207F025600827A46 /* Button_Highlighted.png in Resources */, + A1B98E53207F025600827A46 /* NextButton_Highlighted.png in Resources */, + A1B98E54207F025600827A46 /* NextButton.png in Resources */, + A1B98E55207F025600827A46 /* SubMenuBackground.png in Resources */, + A1B98E56207F025600827A46 /* SubMenuButton_Highlighted.png in Resources */, + A1B98E57207F025600827A46 /* SubMenuButton.png in Resources */, + A1B98E58207F025600827A46 /* BackButton.png in Resources */, + A1B98E59207F025600827A46 /* Button.png in Resources */, + A1B98E5A207F025600827A46 /* DOOM_sigil_decal.png in Resources */, + A1B98E5B207F025600827A46 /* DoomLogo.png in Resources */, + A1B98E5C207F025600827A46 /* Easy.png in Resources */, + A1B98E5D207F025600827A46 /* Hard.png in Resources */, + A1B98E5E207F025600827A46 /* MapOverlay.png in Resources */, + A1B98E5F207F025600827A46 /* Medium.png in Resources */, + A1B98E60207F025600827A46 /* MenuBackground.png in Resources */, + A1B98E61207F025600827A46 /* Nightmare.png in Resources */, + A1B98E62207F025600827A46 /* ResumeButton.png in Resources */, + A1B98E63207F025600827A46 /* SelectedBracket.png in Resources */, + A1B98E64207F025600827A46 /* idGinzaNar-Md2.otf in Resources */, + A1B98E9E207F062A00827A46 /* dist.plist in Resources */, + A1EA3B90208020B60038650E /* EpisodeCell-tvos.xib in Resources */, + A1B98E30207F024400827A46 /* base.iPack in Resources */, + A1B98E32207F024400827A46 /* prboom.wad in Resources */, + A1B98E25207F021900827A46 /* DOOM_76.png in Resources */, + A1B98F8F207F07E300827A46 /* r_drawcolumn.inl in Resources */, + A1B98E26207F021900827A46 /* DOOM_120.png in Resources */, + A1B98E27207F021900827A46 /* DOOM_144.png in Resources */, + A1B98E28207F021900827A46 /* DOOM_152.png in Resources */, + A1B98E29207F021900827A46 /* Default-Landscape~ipad.png in Resources */, + A1B98E2A207F021900827A46 /* Default-Portrait~ipad.png in Resources */, + A1B98E2B207F021900827A46 /* Default@2x.png in Resources */, + A1D3993B2171A0AD00FD11C3 /* DOOM-tvOS.xcassets in Resources */, + A1B98E2C207F021900827A46 /* Default~ipad.png in Resources */, + A1B98E2D207F021900827A46 /* DOOM_57.png in Resources */, + A1B98E2E207F021900827A46 /* DOOM_72.png in Resources */, + A1B98E2F207F021900827A46 /* DOOM_114.png in Resources */, + A1B98E1D207F016600827A46 /* MainMenuView-tvos.xib in Resources */, + A1B98E23207F016600827A46 /* MissionMenuView-tvos.xib in Resources */, + A1B98E20207F016600827A46 /* OpenGLView-tvos.xib in Resources */, + A1B98E22207F016600827A46 /* EpisodeMenuView-tvos.xib in Resources */, + A1B98E21207F016600827A46 /* SettingsMenuView-tvos.xib in Resources */, + A1B98E24207F016600827A46 /* CreditsMenuView-tvos.xib in Resources */, + A1B98E1F207F016600827A46 /* ControlsMenuView-tvos.xib in Resources */, + A1B98E1E207F016600827A46 /* LegalMenuView-tvos.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1DE849F229F60BE0041E450 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1DE84A0229F60BE0041E450 /* Default.png in Resources */, + A1DE84A1229F60BE0041E450 /* dist.plist in Resources */, + A1DE84A3229F60BE0041E450 /* DOOM_57.png in Resources */, + A1DE84A4229F60BE0041E450 /* DOOM_114.png in Resources */, + A1DE84A5229F60BE0041E450 /* DOOM_72.png in Resources */, + A1DE85C3229F73950041E450 /* SIGIL-iOS.xcassets in Resources */, + A1DE84A6229F60BE0041E450 /* Default@2x.png in Resources */, + A1DE84A7229F60BE0041E450 /* Default~ipad.png in Resources */, + A1DE84A8229F60BE0041E450 /* idGinzaNar-Md2.otf in Resources */, + A1DE84A9229F60BE0041E450 /* BackButton.png in Resources */, + A1DE84AA229F60BE0041E450 /* Button.png in Resources */, + A1DE84AB229F60BE0041E450 /* CreditsMenuView.xib in Resources */, + A1DE84AC229F60BE0041E450 /* CreditsMenuView~ipad.xib in Resources */, + A1DE84AD229F60BE0041E450 /* SecretMenuView.xib in Resources */, + A1DE84AE229F60BE0041E450 /* DOOM_sigil_decal.png in Resources */, + A1DE84AF229F60BE0041E450 /* EpisodeCell.xib in Resources */, + A1DE84B0229F60BE0041E450 /* DoomLogo.png in Resources */, + A1DE84B1229F60BE0041E450 /* ControlsMenuView~ipad.xib in Resources */, + A1DE84B2229F60BE0041E450 /* Easy.png in Resources */, + A1DE84B3229F60BE0041E450 /* SettingsMenuView~ipad.xib in Resources */, + A1DE84B4229F60BE0041E450 /* MainMenuView.xib in Resources */, + A1DE84B5229F60BE0041E450 /* Hard.png in Resources */, + A1DE84B6229F60BE0041E450 /* MainMenuView~ipad.xib in Resources */, + A1DE84B7229F60BE0041E450 /* DOOM_144.png in Resources */, + A1DE84B8229F60BE0041E450 /* MapOverlay.png in Resources */, + A1DE84B9229F60BE0041E450 /* Medium.png in Resources */, + A1DE84BA229F60BE0041E450 /* MenuBackground.png in Resources */, + A1DE84BB229F60BE0041E450 /* r_drawcolpipeline.inl in Resources */, + A1DE84BC229F60BE0041E450 /* doom.wad in Resources */, + A1DE84BD229F60BE0041E450 /* ControlsMenuView.xib in Resources */, + A1DE84BE229F60BE0041E450 /* Nightmare.png in Resources */, + A1DE84BF229F60BE0041E450 /* ResumeButton.png in Resources */, + A1DE84C0229F60BE0041E450 /* EpisodeMenuView.xib in Resources */, + A1DE84C1229F60BE0041E450 /* Makefile.am in Resources */, + A1DE84C2229F60BE0041E450 /* SelectedBracket.png in Resources */, + A1DE84C3229F60BE0041E450 /* Default-Portrait~ipad.png in Resources */, + A1DE84C4229F60BE0041E450 /* Default-Landscape~ipad.png in Resources */, + A1DE84C5229F60BE0041E450 /* SettingsMenuView.xib in Resources */, + A1DE84C6229F60BE0041E450 /* BackButton_Highlighted.png in Resources */, + A1DE84C7229F60BE0041E450 /* Button_Highlighted.png in Resources */, + A1DE84C8229F60BE0041E450 /* NextButton_Highlighted.png in Resources */, + A1DE84C9229F60BE0041E450 /* NextButton.png in Resources */, + A1DE84CA229F60BE0041E450 /* SubMenuBackground.png in Resources */, + A1DE84CB229F60BE0041E450 /* SubMenuButton_Highlighted.png in Resources */, + A1DE84CC229F60BE0041E450 /* SubMenuButton.png in Resources */, + A1DE84CD229F60BE0041E450 /* EpisodeMenuView~ipad.xib in Resources */, + A1DE84CE229F60BE0041E450 /* DifficultyBackground.png in Resources */, + A1DE84CF229F60BE0041E450 /* DownArrow_Highlighted.png in Resources */, + A1DE84D0229F60BE0041E450 /* DownArrow.png in Resources */, + A1DE84D1229F60BE0041E450 /* Episode1Background.png in Resources */, + A1DE84D2229F60BE0041E450 /* Episode2Background.png in Resources */, + A1DE84D3229F60BE0041E450 /* Episode3Background.png in Resources */, + A1DE84D4229F60BE0041E450 /* Localizable.strings in Resources */, + A1DE84D5229F60BE0041E450 /* Episode4Background.png in Resources */, + A1DE84D6229F60BE0041E450 /* MissonBackground.png in Resources */, + A1DE84D7229F60BE0041E450 /* DOOMLaunchScreen.storyboard in Resources */, + A1DE84D8229F60BE0041E450 /* UpArrow_Highlighted.png in Resources */, + A1DE84D9229F60BE0041E450 /* UpArrow.png in Resources */, + A1DE84DA229F60BE0041E450 /* r_drawspan.inl in Resources */, + A1DE84DB229F60BE0041E450 /* DOOM_400.png in Resources */, + A1DE84DC229F60BE0041E450 /* Episode1Background_Highlighted.png in Resources */, + A1DE85C7229F874F0041E450 /* SIGILLaunchScreen.storyboard in Resources */, + A1DE84DD229F60BE0041E450 /* Episode2Background_Highlighted.png in Resources */, + A1DE84DE229F60BE0041E450 /* Episode3Background_Highlighted.png in Resources */, + A1DE84DF229F60BE0041E450 /* Episode4Background_Highlighted.png in Resources */, + A1DE84E0229F60BE0041E450 /* MissionMenuView~ipad.xib in Resources */, + A1DE84E1229F60BE0041E450 /* OpenGLView~ipad.xib in Resources */, + A1DE84E2229F60BE0041E450 /* EpisodeCell~ipad.xib in Resources */, + A1DE84E3229F60BE0041E450 /* AdvancedButton_Highlighted.png in Resources */, + A1DE84E4229F60BE0041E450 /* LegalMenuView~ipad.xib in Resources */, + A1DE84E5229F60BE0041E450 /* DOOM_76.png in Resources */, + A1DE84E6229F60BE0041E450 /* AdvancedButton.png in Resources */, + A1DE84E7229F60BE0041E450 /* Divide.png in Resources */, + A1DE84E8229F60BE0041E450 /* LayoutDualButton_Highlighted.png in Resources */, + A1DE84E9229F60BE0041E450 /* LayoutDualButton.png in Resources */, + A1DE85BD229F610C0041E450 /* SIGIL.wad in Resources */, + A1DE84EA229F60BE0041E450 /* DOOM_120.png in Resources */, + A1DE84EB229F60BE0041E450 /* LayoutSingleButton_Highlighted.png in Resources */, + A1DE84EC229F60BE0041E450 /* LayoutSingleButton.png in Resources */, + A1DE84ED229F60BE0041E450 /* LayoutWheelButton_Highlighted.png in Resources */, + A1DE84EE229F60BE0041E450 /* r_drawflush.inl in Resources */, + A1DE84EF229F60BE0041E450 /* LayoutWheelButton.png in Resources */, + A1DE84F0229F60BE0041E450 /* SettingsButton_Highlighted.png in Resources */, + A1DE84F1229F60BE0041E450 /* SettingsButton.png in Resources */, + A1DE84F2229F60BE0041E450 /* DOOM_152.png in Resources */, + A1DE84F3229F60BE0041E450 /* SliderBackground.png in Resources */, + A1DE84F4229F60BE0041E450 /* SliderBar.png in Resources */, + A1DE84F5229F60BE0041E450 /* prboom.wad in Resources */, + A1DE84F6229F60BE0041E450 /* base.iPack in Resources */, + A1DE84F7229F60BE0041E450 /* OpenGLView.xib in Resources */, + A1DE84F8229F60BE0041E450 /* r_drawcolumn.inl in Resources */, + A1DE84F9229F60BE0041E450 /* SliderSkull.png in Resources */, + A1DE84FA229F60BE0041E450 /* MissionMenuView.xib in Resources */, + A1DE84FB229F60BE0041E450 /* SliderSkull@2x.png in Resources */, + A1DE84FC229F60BE0041E450 /* SliderSkull~ipad.png in Resources */, + A1DE84FD229F60BE0041E450 /* LegalMenuView.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1DE85C9229F88D20041E450 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1DE85CA229F88D20041E450 /* Default.png in Resources */, + A1DE85CB229F88D20041E450 /* r_drawflush.inl in Resources */, + A1DE85CC229F88D20041E450 /* SliderSkull~ipad.png in Resources */, + A1DE85CD229F88D20041E450 /* SliderSkull@2x.png in Resources */, + A1DE85CE229F88D20041E450 /* AdvancedButton_Highlighted.png in Resources */, + A1DE85CF229F88D20041E450 /* AdvancedButton.png in Resources */, + A1DE85D0229F88D20041E450 /* Divide.png in Resources */, + A1DE85D1229F88D20041E450 /* LayoutDualButton_Highlighted.png in Resources */, + A1DE86DA229F8B090041E450 /* SIGIL-tvOS.xcassets in Resources */, + A1DE85D2229F88D20041E450 /* LayoutDualButton.png in Resources */, + A1DE85D3229F88D20041E450 /* LayoutSingleButton_Highlighted.png in Resources */, + A1DE85D4229F88D20041E450 /* LayoutSingleButton.png in Resources */, + A1DE85D5229F88D20041E450 /* Localizable.strings in Resources */, + A1DE85D6229F88D20041E450 /* LayoutWheelButton_Highlighted.png in Resources */, + A1DE85D7229F88D20041E450 /* LayoutWheelButton.png in Resources */, + A1DE85D8229F88D20041E450 /* SettingsButton_Highlighted.png in Resources */, + A1DE85D9229F88D20041E450 /* SettingsButton.png in Resources */, + A1DE85DA229F88D20041E450 /* r_drawspan.inl in Resources */, + A1DE85DB229F88D20041E450 /* SliderBackground.png in Resources */, + A1DE85DC229F88D20041E450 /* SliderBar.png in Resources */, + A1DE85DD229F88D20041E450 /* SliderSkull.png in Resources */, + A1DE85DE229F88D20041E450 /* Episode1Background_Highlighted.png in Resources */, + A1DE85DF229F88D20041E450 /* doom.wad in Resources */, + A1DE85E0229F88D20041E450 /* Episode2Background_Highlighted.png in Resources */, + A1DE85E1229F88D20041E450 /* Episode3Background_Highlighted.png in Resources */, + A1DE85E2229F88D20041E450 /* Episode4Background_Highlighted.png in Resources */, + A1DE85E3229F88D20041E450 /* DifficultyBackground.png in Resources */, + A1DE85E4229F88D20041E450 /* DownArrow_Highlighted.png in Resources */, + A1DE85E5229F88D20041E450 /* DownArrow.png in Resources */, + A1DE85E6229F88D20041E450 /* Episode1Background.png in Resources */, + A1DE85E7229F88D20041E450 /* Episode2Background.png in Resources */, + A1DE85E8229F88D20041E450 /* Episode3Background.png in Resources */, + A1DE85E9229F88D20041E450 /* r_drawcolpipeline.inl in Resources */, + A1DE85EA229F88D20041E450 /* Episode4Background.png in Resources */, + A1DE85EB229F88D20041E450 /* MissonBackground.png in Resources */, + A1DE85EC229F88D20041E450 /* Makefile.am in Resources */, + A1DE85ED229F88D20041E450 /* UpArrow_Highlighted.png in Resources */, + A1DE85EE229F88D20041E450 /* UpArrow.png in Resources */, + A1DE85EF229F88D20041E450 /* BackButton_Highlighted.png in Resources */, + A1DE85F0229F88D20041E450 /* Button_Highlighted.png in Resources */, + A1DE85F1229F88D20041E450 /* NextButton_Highlighted.png in Resources */, + A1DE85F2229F88D20041E450 /* NextButton.png in Resources */, + A1DE85F3229F88D20041E450 /* SubMenuBackground.png in Resources */, + A1DE85F4229F88D20041E450 /* SubMenuButton_Highlighted.png in Resources */, + A1DE85F5229F88D20041E450 /* SubMenuButton.png in Resources */, + A1DE85F6229F88D20041E450 /* BackButton.png in Resources */, + A1DE85F7229F88D20041E450 /* Button.png in Resources */, + A1DE85F8229F88D20041E450 /* DOOM_sigil_decal.png in Resources */, + A1DE85F9229F88D20041E450 /* DoomLogo.png in Resources */, + A1DE85FA229F88D20041E450 /* Easy.png in Resources */, + A1DE85FB229F88D20041E450 /* Hard.png in Resources */, + A1DE86D7229F8A830041E450 /* SIGIL.wad in Resources */, + A1DE85FC229F88D20041E450 /* MapOverlay.png in Resources */, + A1DE85FD229F88D20041E450 /* Medium.png in Resources */, + A1DE85FE229F88D20041E450 /* MenuBackground.png in Resources */, + A1DE85FF229F88D20041E450 /* Nightmare.png in Resources */, + A1DE8600229F88D20041E450 /* ResumeButton.png in Resources */, + A1DE8601229F88D20041E450 /* SelectedBracket.png in Resources */, + A1DE8602229F88D20041E450 /* idGinzaNar-Md2.otf in Resources */, + A1DE8603229F88D20041E450 /* dist.plist in Resources */, + A1DE8604229F88D20041E450 /* EpisodeCell-tvos.xib in Resources */, + A1DE8605229F88D20041E450 /* base.iPack in Resources */, + A1DE8606229F88D20041E450 /* prboom.wad in Resources */, + A1DE8607229F88D20041E450 /* DOOM_76.png in Resources */, + A1DE8608229F88D20041E450 /* r_drawcolumn.inl in Resources */, + A1DE8609229F88D20041E450 /* DOOM_120.png in Resources */, + A1DE860A229F88D20041E450 /* DOOM_144.png in Resources */, + A1DE860B229F88D20041E450 /* DOOM_152.png in Resources */, + A1DE860C229F88D20041E450 /* Default-Landscape~ipad.png in Resources */, + A1DE860D229F88D20041E450 /* Default-Portrait~ipad.png in Resources */, + A1DE860E229F88D20041E450 /* Default@2x.png in Resources */, + A1DE8610229F88D20041E450 /* Default~ipad.png in Resources */, + A1DE8611229F88D20041E450 /* DOOM_57.png in Resources */, + A1DE8612229F88D20041E450 /* DOOM_72.png in Resources */, + A1DE8613229F88D20041E450 /* DOOM_114.png in Resources */, + A1DE8614229F88D20041E450 /* MainMenuView-tvos.xib in Resources */, + A1DE8615229F88D20041E450 /* MissionMenuView-tvos.xib in Resources */, + A1DE8616229F88D20041E450 /* OpenGLView-tvos.xib in Resources */, + A1DE8617229F88D20041E450 /* EpisodeMenuView-tvos.xib in Resources */, + A1DE8618229F88D20041E450 /* SettingsMenuView-tvos.xib in Resources */, + A1DE8619229F88D20041E450 /* CreditsMenuView-tvos.xib in Resources */, + A1DE861A229F88D20041E450 /* ControlsMenuView-tvos.xib in Resources */, + A1DE861B229F88D20041E450 /* LegalMenuView-tvos.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1B98E66207F031B00827A46 /* BackgroundMusic.cpp in Sources */, + 1D60589B0D05DD56006BFB54 /* main.m in Sources */, + 43E8D2E10F4FC61E003F09B2 /* iphone_main.c in Sources */, + 43CF030A0F56D5C200E4A23D /* iphone_loop.c in Sources */, + A1A63F3820563B60000955AE /* eas_mdls.c in Sources */, + 7229CE4A0F6C89F8004123C5 /* EAGLView.m in Sources */, + A1A63E1F20562FD1000955AE /* Doom_App.m in Sources */, + 7229CE550F6C8CDE004123C5 /* gles_glue.c in Sources */, + 72B5FF390F7E5C3D00C8A372 /* hud.c in Sources */, + A12302EB205737F50075CBAD /* Localization.mm in Sources */, + 72D50DBC0F8ED98000BB49E6 /* ipak.c in Sources */, + A12302E9205737F50075CBAD /* View.mm in Sources */, + A1A63F3620563B60000955AE /* eas_tcdata.c in Sources */, + A1A63E0E20562FB0000955AE /* iphone_delegate.mm in Sources */, + 72E847650F93C61900AB3C99 /* am_map.c in Sources */, + 72E847740F93FFDB00AB3C99 /* d_client.c in Sources */, + 72E847750F93FFDB00AB3C99 /* d_deh.c in Sources */, + A1A63E0D20562FB0000955AE /* iphone_async.cpp in Sources */, + 72E847B20F9400D700AB3C99 /* d_items.c in Sources */, + 72E847B30F9400D700AB3C99 /* d_main.c in Sources */, + A1A63E4D205634E8000955AE /* eas_report.c in Sources */, + A1A63F1320563B60000955AE /* eas_xmfdata.c in Sources */, + 72E847B50F9400D700AB3C99 /* doomdef.c in Sources */, + 72E847B60F9400D700AB3C99 /* doomstat.c in Sources */, + A1A63E0F20562FB0000955AE /* iphone_start.cpp in Sources */, + 72E847B70F9400D700AB3C99 /* dstrings.c in Sources */, + 72E847B80F9400D700AB3C99 /* f_finale.c in Sources */, + A12302E7205737F50075CBAD /* RenderContext.mm in Sources */, + A1A63F1B20563B60000955AE /* eas_ota.c in Sources */, + 72E847B90F9400D700AB3C99 /* f_wipe.c in Sources */, + 72E847BA0F9400D700AB3C99 /* g_game.c in Sources */, + A1A63F2B20563B60000955AE /* eas_imelodydata.c in Sources */, + A1A63DED20562B76000955AE /* MissionMenuViewController.mm in Sources */, + 72E847BB0F9400D700AB3C99 /* gl_main.c in Sources */, + 72E847BC0F9400D700AB3C99 /* gl_texture.c in Sources */, + 72E847BD0F9400D700AB3C99 /* hu_lib.c in Sources */, + 72E847BE0F9400D700AB3C99 /* hu_stuff.c in Sources */, + 72E847BF0F9400D700AB3C99 /* info.c in Sources */, + A1A63E1020562FB0000955AE /* iphone_common.mm in Sources */, + 72E847C00F9400D700AB3C99 /* lprintf.c in Sources */, + 72E847C10F9400D700AB3C99 /* m_argv.c in Sources */, + 72E847C20F9400D700AB3C99 /* m_bbox.c in Sources */, + A1A63E4E205634E8000955AE /* eas_hostmm.c in Sources */, + 72E847C30F9400D700AB3C99 /* m_cheat.c in Sources */, + 72E847C40F9400D700AB3C99 /* m_menu.c in Sources */, + A1A63DF320562B76000955AE /* MainMenuViewController.mm in Sources */, + 72E847C50F9400D700AB3C99 /* m_misc.c in Sources */, + A1A63F1420563B60000955AE /* eas_xmf.c in Sources */, + A1A63F1520563B60000955AE /* eas_otadata.c in Sources */, + A1A63DF620562B76000955AE /* EpisodeMenuViewController.mm in Sources */, + 72E847C60F9400D700AB3C99 /* m_random.c in Sources */, + 72E848050F941A5900AB3C99 /* md5.c in Sources */, + A1A63F2220563B60000955AE /* eas_wtsynth.c in Sources */, + 72E848070F941A5900AB3C99 /* p_ceilng.c in Sources */, + 72E848080F941A5900AB3C99 /* p_checksum.c in Sources */, + 72E848090F941A5900AB3C99 /* p_doors.c in Sources */, + 72E8480A0F941A5900AB3C99 /* p_enemy.c in Sources */, + A1A63F3420563B60000955AE /* eas_pan.c in Sources */, + 72E8480B0F941A5900AB3C99 /* p_floor.c in Sources */, + A1A63E3420563345000955AE /* mmus2mid.c in Sources */, + 72E8480C0F941A5900AB3C99 /* p_genlin.c in Sources */, + A12302F5205738560075CBAD /* Carousel.mm in Sources */, + A1A63F2D20563B60000955AE /* eas_rtttldata.c in Sources */, + A1A63F1720563B60000955AE /* eas_imaadpcm.c in Sources */, + 72E8480D0F941A5900AB3C99 /* p_inter.c in Sources */, + 72E8480E0F941A5900AB3C99 /* p_lights.c in Sources */, + 72E8480F0F941A5900AB3C99 /* p_map.c in Sources */, + 72E848100F941A5900AB3C99 /* p_maputl.c in Sources */, + A1E89C9620689D9500760204 /* GameController.mm in Sources */, + 72E848110F941A5900AB3C99 /* p_mobj.c in Sources */, + 72E848120F941A5900AB3C99 /* p_plats.c in Sources */, + 72E848130F941A5900AB3C99 /* p_pspr.c in Sources */, + 72E848140F941A5900AB3C99 /* p_saveg.c in Sources */, + A1A63F2F20563B60000955AE /* eas_reverbdata.c in Sources */, + A1A63E29205632E2000955AE /* SDL_Mixer.m in Sources */, + A1A63F2520563B60000955AE /* eas_smf.c in Sources */, + 72E848150F941A5900AB3C99 /* p_setup.c in Sources */, + A1A63F2C20563B60000955AE /* eas_mididata.c in Sources */, + 72E848160F941A5900AB3C99 /* p_sight.c in Sources */, + A1A63E50205634E8000955AE /* eas_wave.c in Sources */, + A1A63E5320563A06000955AE /* EASGlue.c in Sources */, + A1A63F1F20563B60000955AE /* eas_midi.c in Sources */, + 72E848170F941A5900AB3C99 /* p_spec.c in Sources */, + A1A63F2020563B60000955AE /* wt_22khz.c in Sources */, + 72E848180F941A5900AB3C99 /* p_switch.c in Sources */, + A1A63F1920563B60000955AE /* eas_wavefile.c in Sources */, + A1A63F1E20563B60000955AE /* eas_chorus.c in Sources */, + 72E848190F941A5900AB3C99 /* p_telept.c in Sources */, + 72E8481A0F941A5900AB3C99 /* p_tick.c in Sources */, + A1A63F2720563B60000955AE /* eas_pcm.c in Sources */, + A1A63E0C20562FB0000955AE /* iphone_glViewController.mm in Sources */, + 72E8481B0F941A5900AB3C99 /* p_user.c in Sources */, + 72E848260F941A8300AB3C99 /* r_bsp.c in Sources */, + 72E848270F941A8300AB3C99 /* r_data.c in Sources */, + 72E848280F941A8300AB3C99 /* r_demo.c in Sources */, + 72E848290F941A8300AB3C99 /* r_draw.c in Sources */, + A1E89C8F2067469D00760204 /* CreditsMenuViewController.mm in Sources */, + A1A63E1320562FB0000955AE /* iphone_sound.mm in Sources */, + 72E8483D0F941AAC00AB3C99 /* r_filter.c in Sources */, + 72E8483E0F941AAC00AB3C99 /* r_fps.c in Sources */, + A1A63E1220562FB0000955AE /* SoundEngine.cpp in Sources */, + A1A63F2620563B60000955AE /* eas_dlssynth.c in Sources */, + 72E8483F0F941AAC00AB3C99 /* r_main.c in Sources */, + 72E848400F941AAC00AB3C99 /* r_patch.c in Sources */, + 72E848410F941AAC00AB3C99 /* r_plane.c in Sources */, + A1A63E1420562FB0000955AE /* iphone_sys.mm in Sources */, + 72E848420F941AAC00AB3C99 /* r_segs.c in Sources */, + 72E848430F941AAC00AB3C99 /* r_sky.c in Sources */, + 72E848440F941AAC00AB3C99 /* r_things.c in Sources */, + A1A63E2420563253000955AE /* i_sound.c in Sources */, + A1A63F2A20563B60000955AE /* eas_wtengine.c in Sources */, + A1A63F3220563B60000955AE /* eas_voicemgt.c in Sources */, + A1A63DE420562B76000955AE /* LegalMenuViewController.mm in Sources */, + A1A63F2920563B60000955AE /* eas_wavefiledata.c in Sources */, + A1A63F3320563B60000955AE /* eas_imelody.c in Sources */, + 72E848450F941AAC00AB3C99 /* s_sound.c in Sources */, + 72E8485C0F941ADC00AB3C99 /* sounds.c in Sources */, + A1A63F1620563B60000955AE /* eas_data.c in Sources */, + 72E8485D0F941ADC00AB3C99 /* st_lib.c in Sources */, + A1A63F1A20563B60000955AE /* eas_mixer.c in Sources */, + 72E8485E0F941ADC00AB3C99 /* st_stuff.c in Sources */, + 72E8485F0F941ADC00AB3C99 /* tables.c in Sources */, + 72E848600F941ADC00AB3C99 /* v_video.c in Sources */, + 72E848610F941ADC00AB3C99 /* version.c in Sources */, + A1A63F2E20563B60000955AE /* eas_flog.c in Sources */, + A1A63E4F205634E8000955AE /* eas_config.c in Sources */, + 72E848630F941ADC00AB3C99 /* w_mmap.c in Sources */, + A1A63F3520563B60000955AE /* eas_reverb.c in Sources */, + 72E848640F941ADC00AB3C99 /* w_wad.c in Sources */, + 72E848650F941ADC00AB3C99 /* wi_stuff.c in Sources */, + 72E848660F941ADC00AB3C99 /* z_bmalloc.c in Sources */, + A1A63F2120563B60000955AE /* eas_smfdata.c in Sources */, + A1A63F2420563B60000955AE /* eas_mixbuf.c in Sources */, + 72E848670F941ADC00AB3C99 /* z_zone.c in Sources */, + A1A63F3020563B60000955AE /* eas_public.c in Sources */, + 72E849600F942B9300AB3C99 /* cvar.c in Sources */, + 72E849610F942B9300AB3C99 /* misc.c in Sources */, + A1A63DF920562B76000955AE /* SettingsMenuViewController.mm in Sources */, + 72E849F60F94ED1100AB3C99 /* prboomInterface.c in Sources */, + 72E84A290F9503F100AB3C99 /* cmd.c in Sources */, + A12302F2205738270075CBAD /* Slider.mm in Sources */, + 72F1F9B40F96C18800AD49AC /* dict.c in Sources */, + A12302E4205737F50075CBAD /* LabelButton.mm in Sources */, + A12302EE205737F50075CBAD /* Switch.mm in Sources */, + A1A63F1820563B60000955AE /* eas_rtttl.c in Sources */, + 72F1F9B50F96C18800AD49AC /* geom.c in Sources */, + 72F1F9B60F96C18800AD49AC /* memalloc.c in Sources */, + A1A63F1C20563B60000955AE /* eas_pcmdata.c in Sources */, + 72F1F9B70F96C18800AD49AC /* mesh.c in Sources */, + A1A63DC020562B2B000955AE /* SecretMenuViewController.mm in Sources */, + A1A63F2820563B60000955AE /* eas_tonecontrol.c in Sources */, + 72F1F9B80F96C18800AD49AC /* normal.c in Sources */, + A12302E3205737F50075CBAD /* Label.mm in Sources */, + 72F1F9BA0F96C18800AD49AC /* priorityq.c in Sources */, + 72F1F9BB0F96C18800AD49AC /* render.c in Sources */, + A1A63F1D20563B60000955AE /* eas_chorusdata.c in Sources */, + A1A63F3720563B60000955AE /* eas_math.c in Sources */, + 72F1F9BC0F96C18800AD49AC /* sweep.c in Sources */, + A1A63DF720562B76000955AE /* MainNavController.m in Sources */, + A1A63F3120563B60000955AE /* eas_ima_tables.c in Sources */, + 72F1F9BD0F96C18800AD49AC /* tess.c in Sources */, + 72F1F9BE0F96C18800AD49AC /* tessmono.c in Sources */, + 7239452C0F9C0E7500EADD62 /* iphone_mapSelect.c in Sources */, + 72484E5E0FB0E99900124E1C /* iphone_render.c in Sources */, + A1A63DBD20562B2B000955AE /* ControlsMenuViewController.mm in Sources */, + 72A560E21004FAEE00F788A5 /* iphone_net.c in Sources */, + ED9AB3D110966E85000B5852 /* iphone_email.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A106391A216EF7C700BDE196 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A106391B216EF7C700BDE196 /* eas_math.c in Sources */, + A106391C216EF7C700BDE196 /* eas_rtttl.c in Sources */, + A106391D216EF7C700BDE196 /* wi_stuff.c in Sources */, + A106391E216EF7C700BDE196 /* z_bmalloc.c in Sources */, + A106391F216EF7C700BDE196 /* md5.c in Sources */, + A1063920216EF7C700BDE196 /* eas_otadata.c in Sources */, + A1063921216EF7C700BDE196 /* st_lib.c in Sources */, + A1063922216EF7C700BDE196 /* eas_tcdata.c in Sources */, + A1063923216EF7C700BDE196 /* dict.c in Sources */, + A1063924216EF7C700BDE196 /* iphone_sys.mm in Sources */, + A1063925216EF7C700BDE196 /* r_main.c in Sources */, + A1063926216EF7C700BDE196 /* p_floor.c in Sources */, + A1063927216EF7C700BDE196 /* v_video.c in Sources */, + A1063928216EF7C700BDE196 /* d_client.c in Sources */, + A1063929216EF7C700BDE196 /* p_plats.c in Sources */, + A106392A216EF7C700BDE196 /* iphone_common.mm in Sources */, + A106392B216EF7C700BDE196 /* gl_texture.c in Sources */, + A106392C216EF7C700BDE196 /* gl_main.c in Sources */, + A106392D216EF7C700BDE196 /* MissionMenuViewController.mm in Sources */, + A106392E216EF7C700BDE196 /* eas_config.c in Sources */, + A106392F216EF7C700BDE196 /* m_random.c in Sources */, + A1063930216EF7C700BDE196 /* info.c in Sources */, + A1063931216EF7C700BDE196 /* main.m in Sources */, + A1063932216EF7C700BDE196 /* d_items.c in Sources */, + A1063933216EF7C700BDE196 /* GameController.mm in Sources */, + A1063934216EF7C700BDE196 /* eas_mixbuf.c in Sources */, + A1063935216EF7C700BDE196 /* m_misc.c in Sources */, + A1063936216EF7C700BDE196 /* p_checksum.c in Sources */, + A1063937216EF7C700BDE196 /* f_finale.c in Sources */, + A1063938216EF7C700BDE196 /* EAGLView.m in Sources */, + A1063939216EF7C700BDE196 /* RenderContext.mm in Sources */, + A106393A216EF7C700BDE196 /* r_things.c in Sources */, + A106393B216EF7C700BDE196 /* eas_flog.c in Sources */, + A106393C216EF7C700BDE196 /* r_segs.c in Sources */, + A106393D216EF7C700BDE196 /* iphone_main.c in Sources */, + A106393E216EF7C700BDE196 /* eas_data.c in Sources */, + A106393F216EF7C700BDE196 /* eas_imelodydata.c in Sources */, + A1063940216EF7C700BDE196 /* hud.c in Sources */, + A1063941216EF7C700BDE196 /* p_setup.c in Sources */, + A1063942216EF7C700BDE196 /* d_deh.c in Sources */, + A1063943216EF7C700BDE196 /* eas_xmfdata.c in Sources */, + A1063944216EF7C700BDE196 /* m_menu.c in Sources */, + A1063945216EF7C700BDE196 /* p_mobj.c in Sources */, + A1063946216EF7C700BDE196 /* p_tick.c in Sources */, + A1063947216EF7C700BDE196 /* p_doors.c in Sources */, + A1063948216EF7C700BDE196 /* tables.c in Sources */, + A1063949216EF7C700BDE196 /* p_telept.c in Sources */, + A106394A216EF7C700BDE196 /* eas_xmf.c in Sources */, + A106394B216EF7C700BDE196 /* doomstat.c in Sources */, + A106394C216EF7C700BDE196 /* eas_wavefile.c in Sources */, + A106394D216EF7C700BDE196 /* ipak.c in Sources */, + A106394E216EF7C700BDE196 /* eas_smfdata.c in Sources */, + A106394F216EF7C700BDE196 /* SoundEngine.cpp in Sources */, + A1063950216EF7C700BDE196 /* p_enemy.c in Sources */, + A1063951216EF7C700BDE196 /* r_filter.c in Sources */, + A1063952216EF7C700BDE196 /* View.mm in Sources */, + A1063953216EF7C700BDE196 /* eas_voicemgt.c in Sources */, + A1063954216EF7C700BDE196 /* priorityq.c in Sources */, + A1063955216EF7C700BDE196 /* Label.mm in Sources */, + A1063956216EF7C700BDE196 /* eas_dlssynth.c in Sources */, + A1063957216EF7C700BDE196 /* w_mmap.c in Sources */, + A1063958216EF7C700BDE196 /* render.c in Sources */, + A1063959216EF7C700BDE196 /* MainMenuViewController.mm in Sources */, + A106395A216EF7C700BDE196 /* iphone_render.c in Sources */, + A106395B216EF7C700BDE196 /* p_inter.c in Sources */, + A106395C216EF7C700BDE196 /* prboomInterface.c in Sources */, + A106395D216EF7C700BDE196 /* eas_hostmm.c in Sources */, + A106395E216EF7C700BDE196 /* r_data.c in Sources */, + A106395F216EF7C700BDE196 /* eas_mididata.c in Sources */, + A1063960216EF7C700BDE196 /* Doom_App.m in Sources */, + A1063961216EF7C700BDE196 /* eas_pcmdata.c in Sources */, + A1063962216EF7C700BDE196 /* normal.c in Sources */, + A1063963216EF7C700BDE196 /* eas_chorusdata.c in Sources */, + A1063964216EF7C700BDE196 /* eas_chorus.c in Sources */, + A1063965216EF7C700BDE196 /* geom.c in Sources */, + A1063966216EF7C700BDE196 /* iphone_loop.c in Sources */, + A1063967216EF7C700BDE196 /* LabelButton.mm in Sources */, + A1063968216EF7C700BDE196 /* SDL_Mixer.m in Sources */, + A1063969216EF7C700BDE196 /* EASGlue.c in Sources */, + A106396A216EF7C700BDE196 /* Switch.mm in Sources */, + A106396B216EF7C700BDE196 /* eas_ima_tables.c in Sources */, + A106396C216EF7C700BDE196 /* s_sound.c in Sources */, + A106396D216EF7C700BDE196 /* eas_ota.c in Sources */, + A106396E216EF7C700BDE196 /* am_map.c in Sources */, + A106396F216EF7C700BDE196 /* p_user.c in Sources */, + A1063970216EF7C700BDE196 /* cmd.c in Sources */, + A1063971216EF7C700BDE196 /* p_map.c in Sources */, + A1063972216EF7C700BDE196 /* eas_smf.c in Sources */, + A1063973216EF7C700BDE196 /* r_plane.c in Sources */, + A1063974216EF7C700BDE196 /* cvar.c in Sources */, + A1063975216EF7C700BDE196 /* misc.c in Sources */, + A1063976216EF7C700BDE196 /* sweep.c in Sources */, + A1063977216EF7C700BDE196 /* iphone_email.m in Sources */, + A1063978216EF7C700BDE196 /* iphone_delegate.mm in Sources */, + A1063979216EF7C700BDE196 /* eas_imelody.c in Sources */, + A106397A216EF7C700BDE196 /* version.c in Sources */, + A106397B216EF7C700BDE196 /* eas_tonecontrol.c in Sources */, + A106397C216EF7C700BDE196 /* LegalMenuViewController.mm in Sources */, + A106397D216EF7C700BDE196 /* r_fps.c in Sources */, + A106397E216EF7C700BDE196 /* m_cheat.c in Sources */, + A106397F216EF7C700BDE196 /* iphone_async.cpp in Sources */, + A1063980216EF7C700BDE196 /* eas_wave.c in Sources */, + A1063981216EF7C700BDE196 /* eas_imaadpcm.c in Sources */, + A1063982216EF7C700BDE196 /* z_zone.c in Sources */, + A1063983216EF7C700BDE196 /* MainNavController.m in Sources */, + A1063984216EF7C700BDE196 /* BackgroundMusic.cpp in Sources */, + A1063985216EF7C700BDE196 /* doomdef.c in Sources */, + A1063986216EF7C700BDE196 /* r_patch.c in Sources */, + A1063987216EF7C700BDE196 /* p_switch.c in Sources */, + A1063988216EF7C700BDE196 /* eas_reverbdata.c in Sources */, + A1063989216EF7C700BDE196 /* eas_report.c in Sources */, + A106398A216EF7C700BDE196 /* memalloc.c in Sources */, + A106398B216EF7C700BDE196 /* eas_wtengine.c in Sources */, + A106398C216EF7C700BDE196 /* eas_public.c in Sources */, + A106398D216EF7C700BDE196 /* eas_wavefiledata.c in Sources */, + A106398E216EF7C700BDE196 /* gles_glue.c in Sources */, + A106398F216EF7C700BDE196 /* iphone_net.c in Sources */, + A1063990216EF7C700BDE196 /* eas_mixer.c in Sources */, + A1063991216EF7C700BDE196 /* sounds.c in Sources */, + A1063992216EF7C700BDE196 /* eas_rtttldata.c in Sources */, + A1063993216EF7C700BDE196 /* d_main.c in Sources */, + A1063994216EF7C700BDE196 /* wt_22khz.c in Sources */, + A1063995216EF7C700BDE196 /* p_saveg.c in Sources */, + A1063996216EF7C700BDE196 /* p_genlin.c in Sources */, + A1063997216EF7C700BDE196 /* ControlsMenuViewController.mm in Sources */, + A1063998216EF7C700BDE196 /* tessmono.c in Sources */, + A1063999216EF7C700BDE196 /* tess.c in Sources */, + A106399A216EF7C700BDE196 /* iphone_mapSelect.c in Sources */, + A106399B216EF7C700BDE196 /* eas_reverb.c in Sources */, + A106399C216EF7C700BDE196 /* eas_wtsynth.c in Sources */, + A106399D216EF7C700BDE196 /* r_draw.c in Sources */, + A106399E216EF7C700BDE196 /* eas_mdls.c in Sources */, + A106399F216EF7C700BDE196 /* SettingsMenuViewController.mm in Sources */, + A10639A0216EF7C700BDE196 /* st_stuff.c in Sources */, + A10639A1216EF7C700BDE196 /* i_sound.c in Sources */, + A10639A2216EF7C700BDE196 /* CreditsMenuViewController.mm in Sources */, + A10639A3216EF7C700BDE196 /* p_lights.c in Sources */, + A10639A4216EF7C700BDE196 /* w_wad.c in Sources */, + A10639A5216EF7C700BDE196 /* p_spec.c in Sources */, + A10639A6216EF7C700BDE196 /* m_bbox.c in Sources */, + A10639A7216EF7C700BDE196 /* dstrings.c in Sources */, + A10639A8216EF7C700BDE196 /* r_sky.c in Sources */, + A10639A9216EF7C700BDE196 /* hu_lib.c in Sources */, + A10639AA216EF7C700BDE196 /* iphone_sound.mm in Sources */, + A10639AB216EF7C700BDE196 /* r_bsp.c in Sources */, + A10639AD216EF7C700BDE196 /* iphone_glViewController.mm in Sources */, + A10639AE216EF7C700BDE196 /* mmus2mid.c in Sources */, + A10639AF216EF7C700BDE196 /* r_demo.c in Sources */, + A10639B0216EF7C700BDE196 /* g_game.c in Sources */, + A10639B1216EF7C700BDE196 /* p_maputl.c in Sources */, + A10639B2216EF7C700BDE196 /* Localization.mm in Sources */, + A10639B3216EF7C700BDE196 /* eas_midi.c in Sources */, + A10639B4216EF7C700BDE196 /* m_argv.c in Sources */, + A10639B5216EF7C700BDE196 /* p_ceilng.c in Sources */, + A10639B6216EF7C700BDE196 /* mesh.c in Sources */, + A10639B7216EF7C700BDE196 /* eas_pcm.c in Sources */, + A10639B8216EF7C700BDE196 /* p_sight.c in Sources */, + A10639B9216EF7C700BDE196 /* hu_stuff.c in Sources */, + A10639BA216EF7C700BDE196 /* lprintf.c in Sources */, + A10639BB216EF7C700BDE196 /* Carousel.mm in Sources */, + A10639BC216EF7C700BDE196 /* f_wipe.c in Sources */, + A10639BD216EF7C700BDE196 /* eas_pan.c in Sources */, + A10639BE216EF7C700BDE196 /* iphone_start.cpp in Sources */, + A10639BF216EF7C700BDE196 /* p_pspr.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1063A34216EFCEE00BDE196 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1063A35216EFCEE00BDE196 /* BackgroundMusic.cpp in Sources */, + A1063A36216EFCEE00BDE196 /* main.m in Sources */, + A1063A37216EFCEE00BDE196 /* iphone_main.c in Sources */, + A1063A38216EFCEE00BDE196 /* iphone_loop.c in Sources */, + A1063A39216EFCEE00BDE196 /* eas_mdls.c in Sources */, + A1063A3A216EFCEE00BDE196 /* EAGLView.m in Sources */, + A1063A3B216EFCEE00BDE196 /* Doom_App.m in Sources */, + A1063A3C216EFCEE00BDE196 /* gles_glue.c in Sources */, + A1063A3D216EFCEE00BDE196 /* hud.c in Sources */, + A1063A3E216EFCEE00BDE196 /* Localization.mm in Sources */, + A1063A3F216EFCEE00BDE196 /* ipak.c in Sources */, + A1063A40216EFCEE00BDE196 /* View.mm in Sources */, + A1063A41216EFCEE00BDE196 /* eas_tcdata.c in Sources */, + A1063A42216EFCEE00BDE196 /* iphone_delegate.mm in Sources */, + A1063A43216EFCEE00BDE196 /* am_map.c in Sources */, + A1063A44216EFCEE00BDE196 /* d_client.c in Sources */, + A1063A45216EFCEE00BDE196 /* d_deh.c in Sources */, + A1063A46216EFCEE00BDE196 /* iphone_async.cpp in Sources */, + A1063A47216EFCEE00BDE196 /* d_items.c in Sources */, + A1063A48216EFCEE00BDE196 /* d_main.c in Sources */, + A1063A49216EFCEE00BDE196 /* eas_report.c in Sources */, + A1063A4A216EFCEE00BDE196 /* eas_xmfdata.c in Sources */, + A1063A4B216EFCEE00BDE196 /* doomdef.c in Sources */, + A1063A4C216EFCEE00BDE196 /* doomstat.c in Sources */, + A1063A4D216EFCEE00BDE196 /* iphone_start.cpp in Sources */, + A1063A4E216EFCEE00BDE196 /* dstrings.c in Sources */, + A1063A4F216EFCEE00BDE196 /* f_finale.c in Sources */, + A1063A50216EFCEE00BDE196 /* RenderContext.mm in Sources */, + A1063A51216EFCEE00BDE196 /* eas_ota.c in Sources */, + A1063A52216EFCEE00BDE196 /* f_wipe.c in Sources */, + A1063A53216EFCEE00BDE196 /* g_game.c in Sources */, + A1063A54216EFCEE00BDE196 /* eas_imelodydata.c in Sources */, + A1063A55216EFCEE00BDE196 /* MissionMenuViewController.mm in Sources */, + A1063A56216EFCEE00BDE196 /* gl_main.c in Sources */, + A1063A57216EFCEE00BDE196 /* gl_texture.c in Sources */, + A1063A58216EFCEE00BDE196 /* hu_lib.c in Sources */, + A1063A59216EFCEE00BDE196 /* hu_stuff.c in Sources */, + A1063A5A216EFCEE00BDE196 /* info.c in Sources */, + A1063A5B216EFCEE00BDE196 /* iphone_common.mm in Sources */, + A1063A5C216EFCEE00BDE196 /* lprintf.c in Sources */, + A1063A5D216EFCEE00BDE196 /* m_argv.c in Sources */, + A1063A5E216EFCEE00BDE196 /* m_bbox.c in Sources */, + A1063A5F216EFCEE00BDE196 /* eas_hostmm.c in Sources */, + A1063A60216EFCEE00BDE196 /* m_cheat.c in Sources */, + A1063A61216EFCEE00BDE196 /* m_menu.c in Sources */, + A1063A62216EFCEE00BDE196 /* MainMenuViewController.mm in Sources */, + A1063A63216EFCEE00BDE196 /* m_misc.c in Sources */, + A1063A64216EFCEE00BDE196 /* eas_xmf.c in Sources */, + A1063A65216EFCEE00BDE196 /* eas_otadata.c in Sources */, + A1063A66216EFCEE00BDE196 /* EpisodeMenuViewController.mm in Sources */, + A1063A67216EFCEE00BDE196 /* m_random.c in Sources */, + A1063A68216EFCEE00BDE196 /* md5.c in Sources */, + A1063A69216EFCEE00BDE196 /* eas_wtsynth.c in Sources */, + A1063A6A216EFCEE00BDE196 /* p_ceilng.c in Sources */, + A1063A6B216EFCEE00BDE196 /* p_checksum.c in Sources */, + A1063A6C216EFCEE00BDE196 /* p_doors.c in Sources */, + A1063A6D216EFCEE00BDE196 /* p_enemy.c in Sources */, + A1063A6E216EFCEE00BDE196 /* eas_pan.c in Sources */, + A1063A6F216EFCEE00BDE196 /* p_floor.c in Sources */, + A1063A70216EFCEE00BDE196 /* mmus2mid.c in Sources */, + A1063A71216EFCEE00BDE196 /* p_genlin.c in Sources */, + A1063A72216EFCEE00BDE196 /* Carousel.mm in Sources */, + A1063A73216EFCEE00BDE196 /* eas_rtttldata.c in Sources */, + A1063A74216EFCEE00BDE196 /* eas_imaadpcm.c in Sources */, + A1063A75216EFCEE00BDE196 /* p_inter.c in Sources */, + A1063A76216EFCEE00BDE196 /* p_lights.c in Sources */, + A1063A77216EFCEE00BDE196 /* p_map.c in Sources */, + A1063A78216EFCEE00BDE196 /* p_maputl.c in Sources */, + A1063A79216EFCEE00BDE196 /* GameController.mm in Sources */, + A1063A7A216EFCEE00BDE196 /* p_mobj.c in Sources */, + A1063A7B216EFCEE00BDE196 /* p_plats.c in Sources */, + A1063A7C216EFCEE00BDE196 /* p_pspr.c in Sources */, + A1063A7D216EFCEE00BDE196 /* p_saveg.c in Sources */, + A1063A7E216EFCEE00BDE196 /* eas_reverbdata.c in Sources */, + A1063A7F216EFCEE00BDE196 /* SDL_Mixer.m in Sources */, + A1063A80216EFCEE00BDE196 /* eas_smf.c in Sources */, + A1063A81216EFCEE00BDE196 /* p_setup.c in Sources */, + A1063A82216EFCEE00BDE196 /* eas_mididata.c in Sources */, + A1063A83216EFCEE00BDE196 /* p_sight.c in Sources */, + A1063A84216EFCEE00BDE196 /* eas_wave.c in Sources */, + A1063A85216EFCEE00BDE196 /* EASGlue.c in Sources */, + A1063A86216EFCEE00BDE196 /* eas_midi.c in Sources */, + A1063A87216EFCEE00BDE196 /* p_spec.c in Sources */, + A1063A88216EFCEE00BDE196 /* wt_22khz.c in Sources */, + A1063A89216EFCEE00BDE196 /* p_switch.c in Sources */, + A1063A8A216EFCEE00BDE196 /* eas_wavefile.c in Sources */, + A1063A8B216EFCEE00BDE196 /* eas_chorus.c in Sources */, + A1063A8C216EFCEE00BDE196 /* p_telept.c in Sources */, + A1063A8D216EFCEE00BDE196 /* p_tick.c in Sources */, + A1063A8E216EFCEE00BDE196 /* eas_pcm.c in Sources */, + A1063A8F216EFCEE00BDE196 /* iphone_glViewController.mm in Sources */, + A1063A90216EFCEE00BDE196 /* p_user.c in Sources */, + A1063A91216EFCEE00BDE196 /* r_bsp.c in Sources */, + A1063A92216EFCEE00BDE196 /* r_data.c in Sources */, + A1063A93216EFCEE00BDE196 /* r_demo.c in Sources */, + A1063A94216EFCEE00BDE196 /* r_draw.c in Sources */, + A1063A95216EFCEE00BDE196 /* CreditsMenuViewController.mm in Sources */, + A1063A96216EFCEE00BDE196 /* iphone_sound.mm in Sources */, + A1063A97216EFCEE00BDE196 /* r_filter.c in Sources */, + A1063A98216EFCEE00BDE196 /* r_fps.c in Sources */, + A1063A99216EFCEE00BDE196 /* SoundEngine.cpp in Sources */, + A1063A9A216EFCEE00BDE196 /* eas_dlssynth.c in Sources */, + A1063A9B216EFCEE00BDE196 /* r_main.c in Sources */, + A1063A9C216EFCEE00BDE196 /* r_patch.c in Sources */, + A1063A9D216EFCEE00BDE196 /* r_plane.c in Sources */, + A1063A9E216EFCEE00BDE196 /* iphone_sys.mm in Sources */, + A1063A9F216EFCEE00BDE196 /* r_segs.c in Sources */, + A1063AA0216EFCEE00BDE196 /* r_sky.c in Sources */, + A1063AA1216EFCEE00BDE196 /* r_things.c in Sources */, + A1063AA2216EFCEE00BDE196 /* i_sound.c in Sources */, + A1063AA3216EFCEE00BDE196 /* eas_wtengine.c in Sources */, + A1063AA4216EFCEE00BDE196 /* eas_voicemgt.c in Sources */, + A1063AA5216EFCEE00BDE196 /* LegalMenuViewController.mm in Sources */, + A1063AA6216EFCEE00BDE196 /* eas_wavefiledata.c in Sources */, + A1063AA7216EFCEE00BDE196 /* eas_imelody.c in Sources */, + A1063AA8216EFCEE00BDE196 /* s_sound.c in Sources */, + A1063AA9216EFCEE00BDE196 /* sounds.c in Sources */, + A1063AAA216EFCEE00BDE196 /* eas_data.c in Sources */, + A1063AAB216EFCEE00BDE196 /* st_lib.c in Sources */, + A1063AAC216EFCEE00BDE196 /* eas_mixer.c in Sources */, + A1063AAD216EFCEE00BDE196 /* st_stuff.c in Sources */, + A1063AAE216EFCEE00BDE196 /* tables.c in Sources */, + A1063AAF216EFCEE00BDE196 /* v_video.c in Sources */, + A1063AB0216EFCEE00BDE196 /* version.c in Sources */, + A1063AB1216EFCEE00BDE196 /* eas_flog.c in Sources */, + A1063AB2216EFCEE00BDE196 /* eas_config.c in Sources */, + A1063AB3216EFCEE00BDE196 /* w_mmap.c in Sources */, + A1063AB4216EFCEE00BDE196 /* eas_reverb.c in Sources */, + A1063AB5216EFCEE00BDE196 /* w_wad.c in Sources */, + A1063AB6216EFCEE00BDE196 /* wi_stuff.c in Sources */, + A1063AB7216EFCEE00BDE196 /* z_bmalloc.c in Sources */, + A1063AB8216EFCEE00BDE196 /* eas_smfdata.c in Sources */, + A1063AB9216EFCEE00BDE196 /* eas_mixbuf.c in Sources */, + A1063ABA216EFCEE00BDE196 /* z_zone.c in Sources */, + A1063ABB216EFCEE00BDE196 /* eas_public.c in Sources */, + A1063ABC216EFCEE00BDE196 /* cvar.c in Sources */, + A1063ABD216EFCEE00BDE196 /* misc.c in Sources */, + A1063ABE216EFCEE00BDE196 /* SettingsMenuViewController.mm in Sources */, + A1063ABF216EFCEE00BDE196 /* prboomInterface.c in Sources */, + A1063AC0216EFCEE00BDE196 /* cmd.c in Sources */, + A1063AC1216EFCEE00BDE196 /* Slider.mm in Sources */, + A1063AC2216EFCEE00BDE196 /* dict.c in Sources */, + A1063AC3216EFCEE00BDE196 /* LabelButton.mm in Sources */, + A1063AC4216EFCEE00BDE196 /* Switch.mm in Sources */, + A1063AC5216EFCEE00BDE196 /* eas_rtttl.c in Sources */, + A1063AC6216EFCEE00BDE196 /* geom.c in Sources */, + A1063AC7216EFCEE00BDE196 /* memalloc.c in Sources */, + A1063AC8216EFCEE00BDE196 /* eas_pcmdata.c in Sources */, + A1063AC9216EFCEE00BDE196 /* mesh.c in Sources */, + A1063ACA216EFCEE00BDE196 /* SecretMenuViewController.mm in Sources */, + A1063ACB216EFCEE00BDE196 /* eas_tonecontrol.c in Sources */, + A1063ACC216EFCEE00BDE196 /* normal.c in Sources */, + A1063ACD216EFCEE00BDE196 /* Label.mm in Sources */, + A1063ACE216EFCEE00BDE196 /* priorityq.c in Sources */, + A1063ACF216EFCEE00BDE196 /* render.c in Sources */, + A1063AD0216EFCEE00BDE196 /* eas_chorusdata.c in Sources */, + A1063AD1216EFCEE00BDE196 /* eas_math.c in Sources */, + A1063AD2216EFCEE00BDE196 /* sweep.c in Sources */, + A1063AD3216EFCEE00BDE196 /* MainNavController.m in Sources */, + A1063AD4216EFCEE00BDE196 /* eas_ima_tables.c in Sources */, + A1063AD5216EFCEE00BDE196 /* tess.c in Sources */, + A1063AD6216EFCEE00BDE196 /* tessmono.c in Sources */, + A1063AD7216EFCEE00BDE196 /* iphone_mapSelect.c in Sources */, + A1063AD8216EFCEE00BDE196 /* iphone_render.c in Sources */, + A1063AD9216EFCEE00BDE196 /* ControlsMenuViewController.mm in Sources */, + A1063ADA216EFCEE00BDE196 /* iphone_net.c in Sources */, + A1063ADB216EFCEE00BDE196 /* iphone_email.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1063B49216F012000BDE196 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1063B4A216F012000BDE196 /* eas_math.c in Sources */, + A1063B4B216F012000BDE196 /* eas_rtttl.c in Sources */, + A1063B4C216F012000BDE196 /* wi_stuff.c in Sources */, + A1063B4D216F012000BDE196 /* z_bmalloc.c in Sources */, + A1063B4E216F012000BDE196 /* md5.c in Sources */, + A1063B4F216F012000BDE196 /* eas_otadata.c in Sources */, + A1063B50216F012000BDE196 /* st_lib.c in Sources */, + A1063B51216F012000BDE196 /* eas_tcdata.c in Sources */, + A1063B52216F012000BDE196 /* dict.c in Sources */, + A1063B53216F012000BDE196 /* iphone_sys.mm in Sources */, + A1063B54216F012000BDE196 /* r_main.c in Sources */, + A1063B55216F012000BDE196 /* p_floor.c in Sources */, + A1063B56216F012000BDE196 /* v_video.c in Sources */, + A1063B57216F012000BDE196 /* d_client.c in Sources */, + A1063B58216F012000BDE196 /* p_plats.c in Sources */, + A1063B59216F012000BDE196 /* iphone_common.mm in Sources */, + A1063B5A216F012000BDE196 /* gl_texture.c in Sources */, + A1063B5B216F012000BDE196 /* gl_main.c in Sources */, + A1063B5C216F012000BDE196 /* MissionMenuViewController.mm in Sources */, + A1063B5D216F012000BDE196 /* eas_config.c in Sources */, + A1063B5E216F012000BDE196 /* m_random.c in Sources */, + A1063B5F216F012000BDE196 /* info.c in Sources */, + A1063B60216F012000BDE196 /* main.m in Sources */, + A1063B61216F012000BDE196 /* d_items.c in Sources */, + A1063B62216F012000BDE196 /* GameController.mm in Sources */, + A1063B63216F012000BDE196 /* eas_mixbuf.c in Sources */, + A1063B64216F012000BDE196 /* m_misc.c in Sources */, + A1063B65216F012000BDE196 /* p_checksum.c in Sources */, + A1063B66216F012000BDE196 /* f_finale.c in Sources */, + A1063B67216F012000BDE196 /* EAGLView.m in Sources */, + A1063B68216F012000BDE196 /* RenderContext.mm in Sources */, + A1063B69216F012000BDE196 /* r_things.c in Sources */, + A1063B6A216F012000BDE196 /* eas_flog.c in Sources */, + A1063B6B216F012000BDE196 /* r_segs.c in Sources */, + A1063B6C216F012000BDE196 /* iphone_main.c in Sources */, + A1063B6D216F012000BDE196 /* eas_data.c in Sources */, + A1063B6E216F012000BDE196 /* eas_imelodydata.c in Sources */, + A1063B6F216F012000BDE196 /* hud.c in Sources */, + A1063B70216F012000BDE196 /* p_setup.c in Sources */, + A1063B71216F012000BDE196 /* d_deh.c in Sources */, + A1063B72216F012000BDE196 /* eas_xmfdata.c in Sources */, + A1063B73216F012000BDE196 /* m_menu.c in Sources */, + A1063B74216F012000BDE196 /* p_mobj.c in Sources */, + A1063B75216F012000BDE196 /* p_tick.c in Sources */, + A1063B76216F012000BDE196 /* p_doors.c in Sources */, + A1063B77216F012000BDE196 /* tables.c in Sources */, + A1063B78216F012000BDE196 /* p_telept.c in Sources */, + A1063B79216F012000BDE196 /* eas_xmf.c in Sources */, + A1063B7A216F012000BDE196 /* doomstat.c in Sources */, + A1063B7B216F012000BDE196 /* eas_wavefile.c in Sources */, + A1063B7C216F012000BDE196 /* ipak.c in Sources */, + A1063B7D216F012000BDE196 /* eas_smfdata.c in Sources */, + A1063B7E216F012000BDE196 /* SoundEngine.cpp in Sources */, + A1063B7F216F012000BDE196 /* p_enemy.c in Sources */, + A1063B80216F012000BDE196 /* r_filter.c in Sources */, + A1063B81216F012000BDE196 /* View.mm in Sources */, + A1063B82216F012000BDE196 /* eas_voicemgt.c in Sources */, + A1063B83216F012000BDE196 /* priorityq.c in Sources */, + A1063B84216F012000BDE196 /* Label.mm in Sources */, + A1063B85216F012000BDE196 /* eas_dlssynth.c in Sources */, + A1063B86216F012000BDE196 /* w_mmap.c in Sources */, + A1063B87216F012000BDE196 /* render.c in Sources */, + A1063B88216F012000BDE196 /* MainMenuViewController.mm in Sources */, + A1063B89216F012000BDE196 /* iphone_render.c in Sources */, + A1063B8A216F012000BDE196 /* p_inter.c in Sources */, + A1063B8B216F012000BDE196 /* prboomInterface.c in Sources */, + A1063B8C216F012000BDE196 /* eas_hostmm.c in Sources */, + A1063B8D216F012000BDE196 /* r_data.c in Sources */, + A1063B8E216F012000BDE196 /* eas_mididata.c in Sources */, + A1063B8F216F012000BDE196 /* Doom_App.m in Sources */, + A1063B90216F012000BDE196 /* eas_pcmdata.c in Sources */, + A1063B91216F012000BDE196 /* normal.c in Sources */, + A1063B92216F012000BDE196 /* eas_chorusdata.c in Sources */, + A1063B93216F012000BDE196 /* eas_chorus.c in Sources */, + A1063B94216F012000BDE196 /* geom.c in Sources */, + A1063B95216F012000BDE196 /* iphone_loop.c in Sources */, + A1063B96216F012000BDE196 /* LabelButton.mm in Sources */, + A1063B97216F012000BDE196 /* SDL_Mixer.m in Sources */, + A1063B98216F012000BDE196 /* EASGlue.c in Sources */, + A1063B99216F012000BDE196 /* Switch.mm in Sources */, + A1063B9A216F012000BDE196 /* eas_ima_tables.c in Sources */, + A1063B9B216F012000BDE196 /* s_sound.c in Sources */, + A1063B9C216F012000BDE196 /* eas_ota.c in Sources */, + A1063B9D216F012000BDE196 /* am_map.c in Sources */, + A1063B9E216F012000BDE196 /* p_user.c in Sources */, + A1063B9F216F012000BDE196 /* cmd.c in Sources */, + A1063BA0216F012000BDE196 /* p_map.c in Sources */, + A1063BA1216F012000BDE196 /* eas_smf.c in Sources */, + A1063BA2216F012000BDE196 /* r_plane.c in Sources */, + A1063BA3216F012000BDE196 /* cvar.c in Sources */, + A1063BA4216F012000BDE196 /* misc.c in Sources */, + A1063BA5216F012000BDE196 /* sweep.c in Sources */, + A1063BA6216F012000BDE196 /* iphone_email.m in Sources */, + A1063BA7216F012000BDE196 /* iphone_delegate.mm in Sources */, + A1063BA8216F012000BDE196 /* eas_imelody.c in Sources */, + A1063BA9216F012000BDE196 /* version.c in Sources */, + A1063BAA216F012000BDE196 /* eas_tonecontrol.c in Sources */, + A1063BAB216F012000BDE196 /* LegalMenuViewController.mm in Sources */, + A1063BAC216F012000BDE196 /* r_fps.c in Sources */, + A1063BAD216F012000BDE196 /* m_cheat.c in Sources */, + A1063BAE216F012000BDE196 /* iphone_async.cpp in Sources */, + A1063BAF216F012000BDE196 /* eas_wave.c in Sources */, + A1063BB0216F012000BDE196 /* eas_imaadpcm.c in Sources */, + A1063BB1216F012000BDE196 /* z_zone.c in Sources */, + A1063BB2216F012000BDE196 /* MainNavController.m in Sources */, + A1063BB3216F012000BDE196 /* BackgroundMusic.cpp in Sources */, + A1063BB4216F012000BDE196 /* doomdef.c in Sources */, + A1063BB5216F012000BDE196 /* r_patch.c in Sources */, + A1063BB6216F012000BDE196 /* p_switch.c in Sources */, + A1063BB7216F012000BDE196 /* eas_reverbdata.c in Sources */, + A1063BB8216F012000BDE196 /* eas_report.c in Sources */, + A1063BB9216F012000BDE196 /* memalloc.c in Sources */, + A1063BBA216F012000BDE196 /* eas_wtengine.c in Sources */, + A1063BBB216F012000BDE196 /* eas_public.c in Sources */, + A1063BBC216F012000BDE196 /* eas_wavefiledata.c in Sources */, + A1063BBD216F012000BDE196 /* gles_glue.c in Sources */, + A1063BBE216F012000BDE196 /* iphone_net.c in Sources */, + A1063BBF216F012000BDE196 /* eas_mixer.c in Sources */, + A1063BC0216F012000BDE196 /* sounds.c in Sources */, + A1063BC1216F012000BDE196 /* eas_rtttldata.c in Sources */, + A1063BC2216F012000BDE196 /* d_main.c in Sources */, + A1063BC3216F012000BDE196 /* wt_22khz.c in Sources */, + A1063BC4216F012000BDE196 /* p_saveg.c in Sources */, + A1063BC5216F012000BDE196 /* p_genlin.c in Sources */, + A1063BC6216F012000BDE196 /* ControlsMenuViewController.mm in Sources */, + A1063BC7216F012000BDE196 /* tessmono.c in Sources */, + A1063BC8216F012000BDE196 /* tess.c in Sources */, + A1063BC9216F012000BDE196 /* iphone_mapSelect.c in Sources */, + A1063BCA216F012000BDE196 /* eas_reverb.c in Sources */, + A1063BCB216F012000BDE196 /* eas_wtsynth.c in Sources */, + A1063BCC216F012000BDE196 /* r_draw.c in Sources */, + A1063BCD216F012000BDE196 /* eas_mdls.c in Sources */, + A1063BCE216F012000BDE196 /* SettingsMenuViewController.mm in Sources */, + A1063BCF216F012000BDE196 /* st_stuff.c in Sources */, + A1063BD0216F012000BDE196 /* i_sound.c in Sources */, + A1063BD1216F012000BDE196 /* CreditsMenuViewController.mm in Sources */, + A1063BD2216F012000BDE196 /* p_lights.c in Sources */, + A1063BD3216F012000BDE196 /* w_wad.c in Sources */, + A1063BD4216F012000BDE196 /* p_spec.c in Sources */, + A1063BD5216F012000BDE196 /* m_bbox.c in Sources */, + A1063BD6216F012000BDE196 /* dstrings.c in Sources */, + A1063BD7216F012000BDE196 /* r_sky.c in Sources */, + A1063BD8216F012000BDE196 /* hu_lib.c in Sources */, + A1063BD9216F012000BDE196 /* iphone_sound.mm in Sources */, + A1063BDA216F012000BDE196 /* r_bsp.c in Sources */, + A1063BDB216F012000BDE196 /* EpisodeMenuViewController.mm in Sources */, + A1063BDC216F012000BDE196 /* iphone_glViewController.mm in Sources */, + A1063BDD216F012000BDE196 /* mmus2mid.c in Sources */, + A1063BDE216F012000BDE196 /* r_demo.c in Sources */, + A1063BDF216F012000BDE196 /* g_game.c in Sources */, + A1063BE0216F012000BDE196 /* p_maputl.c in Sources */, + A1063BE1216F012000BDE196 /* Localization.mm in Sources */, + A1063BE2216F012000BDE196 /* eas_midi.c in Sources */, + A1063BE3216F012000BDE196 /* m_argv.c in Sources */, + A1063BE4216F012000BDE196 /* p_ceilng.c in Sources */, + A1063BE5216F012000BDE196 /* mesh.c in Sources */, + A1063BE6216F012000BDE196 /* eas_pcm.c in Sources */, + A1063BE7216F012000BDE196 /* p_sight.c in Sources */, + A1063BE8216F012000BDE196 /* hu_stuff.c in Sources */, + A1063BE9216F012000BDE196 /* lprintf.c in Sources */, + A1063BEA216F012000BDE196 /* Carousel.mm in Sources */, + A1063BEB216F012000BDE196 /* f_wipe.c in Sources */, + A1063BEC216F012000BDE196 /* eas_pan.c in Sources */, + A1063BED216F012000BDE196 /* iphone_start.cpp in Sources */, + A1063BEE216F012000BDE196 /* p_pspr.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1870865216EB633006C013F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1870866216EB633006C013F /* BackgroundMusic.cpp in Sources */, + A1870867216EB633006C013F /* main.m in Sources */, + A1870868216EB633006C013F /* iphone_main.c in Sources */, + A1870869216EB633006C013F /* iphone_loop.c in Sources */, + A187086A216EB633006C013F /* eas_mdls.c in Sources */, + A187086B216EB633006C013F /* EAGLView.m in Sources */, + A187086C216EB633006C013F /* Doom_App.m in Sources */, + A187086D216EB633006C013F /* gles_glue.c in Sources */, + A187086E216EB633006C013F /* hud.c in Sources */, + A187086F216EB633006C013F /* Localization.mm in Sources */, + A1870870216EB633006C013F /* ipak.c in Sources */, + A1870871216EB633006C013F /* View.mm in Sources */, + A1870872216EB633006C013F /* eas_tcdata.c in Sources */, + A1870873216EB633006C013F /* iphone_delegate.mm in Sources */, + A1870874216EB633006C013F /* am_map.c in Sources */, + A1870875216EB633006C013F /* d_client.c in Sources */, + A1870876216EB633006C013F /* d_deh.c in Sources */, + A1870877216EB633006C013F /* iphone_async.cpp in Sources */, + A1870878216EB633006C013F /* d_items.c in Sources */, + A1870879216EB633006C013F /* d_main.c in Sources */, + A187087A216EB633006C013F /* eas_report.c in Sources */, + A187087B216EB633006C013F /* eas_xmfdata.c in Sources */, + A187087C216EB633006C013F /* doomdef.c in Sources */, + A187087D216EB633006C013F /* doomstat.c in Sources */, + A187087E216EB633006C013F /* iphone_start.cpp in Sources */, + A187087F216EB633006C013F /* dstrings.c in Sources */, + A1870880216EB633006C013F /* f_finale.c in Sources */, + A1870881216EB633006C013F /* RenderContext.mm in Sources */, + A1870882216EB633006C013F /* eas_ota.c in Sources */, + A1870883216EB633006C013F /* f_wipe.c in Sources */, + A1870884216EB633006C013F /* g_game.c in Sources */, + A1870885216EB633006C013F /* eas_imelodydata.c in Sources */, + A1870886216EB633006C013F /* MissionMenuViewController.mm in Sources */, + A1870887216EB633006C013F /* gl_main.c in Sources */, + A1870888216EB633006C013F /* gl_texture.c in Sources */, + A1870889216EB633006C013F /* hu_lib.c in Sources */, + A187088A216EB633006C013F /* hu_stuff.c in Sources */, + A187088B216EB633006C013F /* info.c in Sources */, + A187088C216EB633006C013F /* iphone_common.mm in Sources */, + A187088D216EB633006C013F /* lprintf.c in Sources */, + A187088E216EB633006C013F /* m_argv.c in Sources */, + A187088F216EB633006C013F /* m_bbox.c in Sources */, + A1870890216EB633006C013F /* eas_hostmm.c in Sources */, + A1870891216EB633006C013F /* m_cheat.c in Sources */, + A1870892216EB633006C013F /* m_menu.c in Sources */, + A1870893216EB633006C013F /* MainMenuViewController.mm in Sources */, + A1870894216EB633006C013F /* m_misc.c in Sources */, + A1870895216EB633006C013F /* eas_xmf.c in Sources */, + A1870896216EB633006C013F /* eas_otadata.c in Sources */, + A1870898216EB633006C013F /* m_random.c in Sources */, + A1870899216EB633006C013F /* md5.c in Sources */, + A187089A216EB633006C013F /* eas_wtsynth.c in Sources */, + A187089B216EB633006C013F /* p_ceilng.c in Sources */, + A187089C216EB633006C013F /* p_checksum.c in Sources */, + A187089D216EB633006C013F /* p_doors.c in Sources */, + A187089E216EB633006C013F /* p_enemy.c in Sources */, + A187089F216EB633006C013F /* eas_pan.c in Sources */, + A18708A0216EB633006C013F /* p_floor.c in Sources */, + A18708A1216EB633006C013F /* mmus2mid.c in Sources */, + A18708A2216EB633006C013F /* p_genlin.c in Sources */, + A18708A3216EB633006C013F /* Carousel.mm in Sources */, + A18708A4216EB633006C013F /* eas_rtttldata.c in Sources */, + A18708A5216EB633006C013F /* eas_imaadpcm.c in Sources */, + A18708A6216EB633006C013F /* p_inter.c in Sources */, + A18708A7216EB633006C013F /* p_lights.c in Sources */, + A18708A8216EB633006C013F /* p_map.c in Sources */, + A18708A9216EB633006C013F /* p_maputl.c in Sources */, + A18708AA216EB633006C013F /* GameController.mm in Sources */, + A18708AB216EB633006C013F /* p_mobj.c in Sources */, + A18708AC216EB633006C013F /* p_plats.c in Sources */, + A18708AD216EB633006C013F /* p_pspr.c in Sources */, + A18708AE216EB633006C013F /* p_saveg.c in Sources */, + A18708AF216EB633006C013F /* eas_reverbdata.c in Sources */, + A18708B0216EB633006C013F /* SDL_Mixer.m in Sources */, + A18708B1216EB633006C013F /* eas_smf.c in Sources */, + A18708B2216EB633006C013F /* p_setup.c in Sources */, + A18708B3216EB633006C013F /* eas_mididata.c in Sources */, + A18708B4216EB633006C013F /* p_sight.c in Sources */, + A18708B5216EB633006C013F /* eas_wave.c in Sources */, + A18708B6216EB633006C013F /* EASGlue.c in Sources */, + A18708B7216EB633006C013F /* eas_midi.c in Sources */, + A18708B8216EB633006C013F /* p_spec.c in Sources */, + A18708B9216EB633006C013F /* wt_22khz.c in Sources */, + A18708BA216EB633006C013F /* p_switch.c in Sources */, + A18708BB216EB633006C013F /* eas_wavefile.c in Sources */, + A18708BC216EB633006C013F /* eas_chorus.c in Sources */, + A18708BD216EB633006C013F /* p_telept.c in Sources */, + A18708BE216EB633006C013F /* p_tick.c in Sources */, + A18708BF216EB633006C013F /* eas_pcm.c in Sources */, + A18708C0216EB633006C013F /* iphone_glViewController.mm in Sources */, + A18708C1216EB633006C013F /* p_user.c in Sources */, + A18708C2216EB633006C013F /* r_bsp.c in Sources */, + A18708C3216EB633006C013F /* r_data.c in Sources */, + A18708C4216EB633006C013F /* r_demo.c in Sources */, + A18708C5216EB633006C013F /* r_draw.c in Sources */, + A18708C6216EB633006C013F /* CreditsMenuViewController.mm in Sources */, + A18708C7216EB633006C013F /* iphone_sound.mm in Sources */, + A18708C8216EB633006C013F /* r_filter.c in Sources */, + A18708C9216EB633006C013F /* r_fps.c in Sources */, + A18708CA216EB633006C013F /* SoundEngine.cpp in Sources */, + A18708CB216EB633006C013F /* eas_dlssynth.c in Sources */, + A18708CC216EB633006C013F /* r_main.c in Sources */, + A18708CD216EB633006C013F /* r_patch.c in Sources */, + A18708CE216EB633006C013F /* r_plane.c in Sources */, + A18708CF216EB633006C013F /* iphone_sys.mm in Sources */, + A18708D0216EB633006C013F /* r_segs.c in Sources */, + A18708D1216EB633006C013F /* r_sky.c in Sources */, + A18708D2216EB633006C013F /* r_things.c in Sources */, + A18708D3216EB633006C013F /* i_sound.c in Sources */, + A18708D4216EB633006C013F /* eas_wtengine.c in Sources */, + A18708D5216EB633006C013F /* eas_voicemgt.c in Sources */, + A18708D6216EB633006C013F /* LegalMenuViewController.mm in Sources */, + A18708D7216EB633006C013F /* eas_wavefiledata.c in Sources */, + A18708D8216EB633006C013F /* eas_imelody.c in Sources */, + A18708D9216EB633006C013F /* s_sound.c in Sources */, + A18708DA216EB633006C013F /* sounds.c in Sources */, + A18708DB216EB633006C013F /* eas_data.c in Sources */, + A18708DC216EB633006C013F /* st_lib.c in Sources */, + A18708DD216EB633006C013F /* eas_mixer.c in Sources */, + A18708DE216EB633006C013F /* st_stuff.c in Sources */, + A18708DF216EB633006C013F /* tables.c in Sources */, + A18708E0216EB633006C013F /* v_video.c in Sources */, + A18708E1216EB633006C013F /* version.c in Sources */, + A18708E2216EB633006C013F /* eas_flog.c in Sources */, + A18708E3216EB633006C013F /* eas_config.c in Sources */, + A18708E4216EB633006C013F /* w_mmap.c in Sources */, + A18708E5216EB633006C013F /* eas_reverb.c in Sources */, + A18708E6216EB633006C013F /* w_wad.c in Sources */, + A18708E7216EB633006C013F /* wi_stuff.c in Sources */, + A18708E8216EB633006C013F /* z_bmalloc.c in Sources */, + A18708E9216EB633006C013F /* eas_smfdata.c in Sources */, + A18708EA216EB633006C013F /* eas_mixbuf.c in Sources */, + A18708EB216EB633006C013F /* z_zone.c in Sources */, + A18708EC216EB633006C013F /* eas_public.c in Sources */, + A18708ED216EB633006C013F /* cvar.c in Sources */, + A18708EE216EB633006C013F /* misc.c in Sources */, + A18708EF216EB633006C013F /* SettingsMenuViewController.mm in Sources */, + A18708F0216EB633006C013F /* prboomInterface.c in Sources */, + A18708F1216EB633006C013F /* cmd.c in Sources */, + A18708F2216EB633006C013F /* Slider.mm in Sources */, + A18708F3216EB633006C013F /* dict.c in Sources */, + A18708F4216EB633006C013F /* LabelButton.mm in Sources */, + A18708F5216EB633006C013F /* Switch.mm in Sources */, + A18708F6216EB633006C013F /* eas_rtttl.c in Sources */, + A18708F7216EB633006C013F /* geom.c in Sources */, + A18708F8216EB633006C013F /* memalloc.c in Sources */, + A18708F9216EB633006C013F /* eas_pcmdata.c in Sources */, + A18708FA216EB633006C013F /* mesh.c in Sources */, + A18708FB216EB633006C013F /* SecretMenuViewController.mm in Sources */, + A18708FC216EB633006C013F /* eas_tonecontrol.c in Sources */, + A18708FD216EB633006C013F /* normal.c in Sources */, + A18708FE216EB633006C013F /* Label.mm in Sources */, + A18708FF216EB633006C013F /* priorityq.c in Sources */, + A1870900216EB633006C013F /* render.c in Sources */, + A1870901216EB633006C013F /* eas_chorusdata.c in Sources */, + A1870902216EB633006C013F /* eas_math.c in Sources */, + A1870903216EB633006C013F /* sweep.c in Sources */, + A1870904216EB633006C013F /* MainNavController.m in Sources */, + A1870905216EB633006C013F /* eas_ima_tables.c in Sources */, + A1870906216EB633006C013F /* tess.c in Sources */, + A1870907216EB633006C013F /* tessmono.c in Sources */, + A1870908216EB633006C013F /* iphone_mapSelect.c in Sources */, + A1870909216EB633006C013F /* iphone_render.c in Sources */, + A187090A216EB633006C013F /* ControlsMenuViewController.mm in Sources */, + A187090B216EB633006C013F /* iphone_net.c in Sources */, + A187090C216EB633006C013F /* iphone_email.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1B98DE6207EFEE800827A46 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1B98F9D207F090600827A46 /* eas_math.c in Sources */, + A1B98FAB207F090600827A46 /* eas_rtttl.c in Sources */, + A1CF62B5207F138A0096F91C /* wi_stuff.c in Sources */, + A1CF62B6207F138A0096F91C /* z_bmalloc.c in Sources */, + A1B98F6A207F07D400827A46 /* md5.c in Sources */, + A1B98FA4207F090600827A46 /* eas_otadata.c in Sources */, + A1CF62AE207F138A0096F91C /* st_lib.c in Sources */, + A1B98FAF207F090600827A46 /* eas_tcdata.c in Sources */, + A1B98E8D207F05E200827A46 /* dict.c in Sources */, + A1B98E8C207F05DB00827A46 /* iphone_sys.mm in Sources */, + A1B98F87207F07D400827A46 /* r_main.c in Sources */, + A1B98F70207F07D400827A46 /* p_floor.c in Sources */, + A1CF62B1207F138A0096F91C /* v_video.c in Sources */, + A1B98F54207F07D400827A46 /* d_client.c in Sources */, + A1B98F77207F07D400827A46 /* p_plats.c in Sources */, + A1B98E81207F05BD00827A46 /* iphone_common.mm in Sources */, + A1B98F5F207F07D400827A46 /* gl_texture.c in Sources */, + A1B98F5E207F07D400827A46 /* gl_main.c in Sources */, + A1B98E7C207F05A300827A46 /* MissionMenuViewController.mm in Sources */, + A1B98FB9207F091B00827A46 /* eas_config.c in Sources */, + A1B98F69207F07D400827A46 /* m_random.c in Sources */, + A1B98F62207F07D400827A46 /* info.c in Sources */, + A1B98E98207F05F900827A46 /* main.m in Sources */, + A1B98F56207F07D400827A46 /* d_items.c in Sources */, + A1B98E9D207F061E00827A46 /* GameController.mm in Sources */, + A1B98FA1207F090600827A46 /* eas_mixbuf.c in Sources */, + A1B98F68207F07D400827A46 /* m_misc.c in Sources */, + A1B98F6D207F07D400827A46 /* p_checksum.c in Sources */, + A1B98F5B207F07D400827A46 /* f_finale.c in Sources */, + A1B98E73207F050200827A46 /* EAGLView.m in Sources */, + A1B98E6C207F04C600827A46 /* RenderContext.mm in Sources */, + A1B98F8C207F07D400827A46 /* r_things.c in Sources */, + A1B98F98207F090600827A46 /* eas_flog.c in Sources */, + A1B98F8A207F07D400827A46 /* r_segs.c in Sources */, + A1B98E86207F05D400827A46 /* iphone_main.c in Sources */, + A1B98F96207F090600827A46 /* eas_data.c in Sources */, + A1B98F9C207F090600827A46 /* eas_imelodydata.c in Sources */, + A1B98E75207F050200827A46 /* hud.c in Sources */, + A1B98F7A207F07D400827A46 /* p_setup.c in Sources */, + A1B98F55207F07D400827A46 /* d_deh.c in Sources */, + A1B98FB7207F090700827A46 /* eas_xmfdata.c in Sources */, + A1B98F67207F07D400827A46 /* m_menu.c in Sources */, + A1B98F76207F07D400827A46 /* p_mobj.c in Sources */, + A1B98F7F207F07D400827A46 /* p_tick.c in Sources */, + A1B98F6E207F07D400827A46 /* p_doors.c in Sources */, + A1CF62B0207F138A0096F91C /* tables.c in Sources */, + A1B98F7E207F07D400827A46 /* p_telept.c in Sources */, + A1B98FB6207F090700827A46 /* eas_xmf.c in Sources */, + A1B98F59207F07D400827A46 /* doomstat.c in Sources */, + A1B98FB2207F090700827A46 /* eas_wavefile.c in Sources */, + A1B98E7F207F05B000827A46 /* ipak.c in Sources */, + A1B98FAE207F090600827A46 /* eas_smfdata.c in Sources */, + A1B98E9C207F060C00827A46 /* SoundEngine.cpp in Sources */, + A1B98F6F207F07D400827A46 /* p_enemy.c in Sources */, + A1B98F85207F07D400827A46 /* r_filter.c in Sources */, + A1B98E6E207F04C600827A46 /* View.mm in Sources */, + A1B98FB1207F090700827A46 /* eas_voicemgt.c in Sources */, + A1B98E92207F05F000827A46 /* priorityq.c in Sources */, + A1B98E69207F04BE00827A46 /* Label.mm in Sources */, + A1B98F97207F090600827A46 /* eas_dlssynth.c in Sources */, + A1CF62B3207F138A0096F91C /* w_mmap.c in Sources */, + A1B98E93207F05F000827A46 /* render.c in Sources */, + A1B98E7A207F058600827A46 /* MainMenuViewController.mm in Sources */, + A1B98E89207F05DB00827A46 /* iphone_render.c in Sources */, + A1B98F72207F07D400827A46 /* p_inter.c in Sources */, + A1B98E9B207F060800827A46 /* prboomInterface.c in Sources */, + A1B98FBA207F091B00827A46 /* eas_hostmm.c in Sources */, + A1B98F82207F07D400827A46 /* r_data.c in Sources */, + A1B98FA0207F090600827A46 /* eas_mididata.c in Sources */, + A1B98E72207F050200827A46 /* Doom_App.m in Sources */, + A1B98FA7207F090600827A46 /* eas_pcmdata.c in Sources */, + A1B98E91207F05F000827A46 /* normal.c in Sources */, + A1B98F95207F090600827A46 /* eas_chorusdata.c in Sources */, + A1B98F94207F090600827A46 /* eas_chorus.c in Sources */, + A1B98E8E207F05F000827A46 /* geom.c in Sources */, + A1B98E85207F05CF00827A46 /* iphone_loop.c in Sources */, + A1B98E6A207F04BE00827A46 /* LabelButton.mm in Sources */, + A1CF62B8207F143F0096F91C /* SDL_Mixer.m in Sources */, + A1B98F93207F08CA00827A46 /* EASGlue.c in Sources */, + A1B98E6D207F04C600827A46 /* Switch.mm in Sources */, + A1B98F99207F090600827A46 /* eas_ima_tables.c in Sources */, + A1B98F8D207F07D400827A46 /* s_sound.c in Sources */, + A1B98FA3207F090600827A46 /* eas_ota.c in Sources */, + A1B98F53207F07D400827A46 /* am_map.c in Sources */, + A1B98F80207F07D400827A46 /* p_user.c in Sources */, + A1B98E70207F04D800827A46 /* cmd.c in Sources */, + A1B98F74207F07D400827A46 /* p_map.c in Sources */, + A1B98FAD207F090600827A46 /* eas_smf.c in Sources */, + A1B98F89207F07D400827A46 /* r_plane.c in Sources */, + A1B98E71207F04D800827A46 /* cvar.c in Sources */, + A1B98E99207F05FC00827A46 /* misc.c in Sources */, + A1B98E94207F05F000827A46 /* sweep.c in Sources */, + A1B98E83207F05C700827A46 /* iphone_email.m in Sources */, + A1B98E82207F05C100827A46 /* iphone_delegate.mm in Sources */, + A1B98F9B207F090600827A46 /* eas_imelody.c in Sources */, + A1CF62B2207F138A0096F91C /* version.c in Sources */, + A1B98FB0207F090600827A46 /* eas_tonecontrol.c in Sources */, + A1B98E79207F058200827A46 /* LegalMenuViewController.mm in Sources */, + A1B98F86207F07D400827A46 /* r_fps.c in Sources */, + A1B98F66207F07D400827A46 /* m_cheat.c in Sources */, + A1B98E80207F05B500827A46 /* iphone_async.cpp in Sources */, + A1B98FBC207F091B00827A46 /* eas_wave.c in Sources */, + A1B98F9A207F090600827A46 /* eas_imaadpcm.c in Sources */, + A1CF62B7207F138A0096F91C /* z_zone.c in Sources */, + A1B98E7B207F058E00827A46 /* MainNavController.m in Sources */, + A1B98E6F207F04D000827A46 /* BackgroundMusic.cpp in Sources */, + A1B98F58207F07D400827A46 /* doomdef.c in Sources */, + A1B98F88207F07D400827A46 /* r_patch.c in Sources */, + A1B98F7D207F07D400827A46 /* p_switch.c in Sources */, + A1B98FAA207F090600827A46 /* eas_reverbdata.c in Sources */, + A1B98FBB207F091B00827A46 /* eas_report.c in Sources */, + A1B98E8F207F05F000827A46 /* memalloc.c in Sources */, + A1B98FB4207F090700827A46 /* eas_wtengine.c in Sources */, + A1B98FA8207F090600827A46 /* eas_public.c in Sources */, + A1B98FB3207F090700827A46 /* eas_wavefiledata.c in Sources */, + A1B98E74207F050200827A46 /* gles_glue.c in Sources */, + A1B98E88207F05D400827A46 /* iphone_net.c in Sources */, + A1B98FA2207F090600827A46 /* eas_mixer.c in Sources */, + A1CF62AD207F138A0096F91C /* sounds.c in Sources */, + A1B98FAC207F090600827A46 /* eas_rtttldata.c in Sources */, + A1B98F57207F07D400827A46 /* d_main.c in Sources */, + A1B98FB8207F090E00827A46 /* wt_22khz.c in Sources */, + A1B98F79207F07D400827A46 /* p_saveg.c in Sources */, + A1B98F71207F07D400827A46 /* p_genlin.c in Sources */, + A1B98E76207F055400827A46 /* ControlsMenuViewController.mm in Sources */, + A1B98E96207F05F000827A46 /* tessmono.c in Sources */, + A1B98E95207F05F000827A46 /* tess.c in Sources */, + A1B98E87207F05D400827A46 /* iphone_mapSelect.c in Sources */, + A1B98FA9207F090600827A46 /* eas_reverb.c in Sources */, + A1B98FB5207F090700827A46 /* eas_wtsynth.c in Sources */, + A1B98F84207F07D400827A46 /* r_draw.c in Sources */, + A1B98F9E207F090600827A46 /* eas_mdls.c in Sources */, + A1B98E7E207F05AC00827A46 /* SettingsMenuViewController.mm in Sources */, + A1CF62AF207F138A0096F91C /* st_stuff.c in Sources */, + A1CF62A3207F13640096F91C /* i_sound.c in Sources */, + A1B98E77207F057600827A46 /* CreditsMenuViewController.mm in Sources */, + A1B98F73207F07D400827A46 /* p_lights.c in Sources */, + A1CF62B4207F138A0096F91C /* w_wad.c in Sources */, + A1B98F7C207F07D400827A46 /* p_spec.c in Sources */, + A1B98F65207F07D400827A46 /* m_bbox.c in Sources */, + A1B98F5A207F07D400827A46 /* dstrings.c in Sources */, + A1B98F8B207F07D400827A46 /* r_sky.c in Sources */, + A1B98F60207F07D400827A46 /* hu_lib.c in Sources */, + A1B98E8A207F05DB00827A46 /* iphone_sound.mm in Sources */, + A1B98F81207F07D400827A46 /* r_bsp.c in Sources */, + A1B98E78207F057E00827A46 /* EpisodeMenuViewController.mm in Sources */, + A1B98E84207F05CB00827A46 /* iphone_glViewController.mm in Sources */, + A1B98F6B207F07D400827A46 /* mmus2mid.c in Sources */, + A1B98F83207F07D400827A46 /* r_demo.c in Sources */, + A1B98F5D207F07D400827A46 /* g_game.c in Sources */, + A1B98F75207F07D400827A46 /* p_maputl.c in Sources */, + A1B98E6B207F04C600827A46 /* Localization.mm in Sources */, + A1B98F9F207F090600827A46 /* eas_midi.c in Sources */, + A1B98F64207F07D400827A46 /* m_argv.c in Sources */, + A1B98F6C207F07D400827A46 /* p_ceilng.c in Sources */, + A1B98E90207F05F000827A46 /* mesh.c in Sources */, + A1B98FA6207F090600827A46 /* eas_pcm.c in Sources */, + A1B98F7B207F07D400827A46 /* p_sight.c in Sources */, + A1B98F61207F07D400827A46 /* hu_stuff.c in Sources */, + A1B98F63207F07D400827A46 /* lprintf.c in Sources */, + A1B98E67207F04B900827A46 /* Carousel.mm in Sources */, + A1B98F5C207F07D400827A46 /* f_wipe.c in Sources */, + A1B98FA5207F090600827A46 /* eas_pan.c in Sources */, + A1B98E8B207F05DB00827A46 /* iphone_start.cpp in Sources */, + A1B98F78207F07D400827A46 /* p_pspr.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1DE84FE229F60BE0041E450 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1DE84FF229F60BE0041E450 /* BackgroundMusic.cpp in Sources */, + A1DE8500229F60BE0041E450 /* main.m in Sources */, + A1DE8501229F60BE0041E450 /* iphone_main.c in Sources */, + A1DE8502229F60BE0041E450 /* iphone_loop.c in Sources */, + A1DE8503229F60BE0041E450 /* eas_mdls.c in Sources */, + A1DE8504229F60BE0041E450 /* EAGLView.m in Sources */, + A1DE8505229F60BE0041E450 /* Doom_App.m in Sources */, + A1DE8506229F60BE0041E450 /* gles_glue.c in Sources */, + A1DE8507229F60BE0041E450 /* hud.c in Sources */, + A1DE8508229F60BE0041E450 /* Localization.mm in Sources */, + A1DE8509229F60BE0041E450 /* ipak.c in Sources */, + A1DE850A229F60BE0041E450 /* View.mm in Sources */, + A1DE850B229F60BE0041E450 /* eas_tcdata.c in Sources */, + A1DE850C229F60BE0041E450 /* iphone_delegate.mm in Sources */, + A1DE850D229F60BE0041E450 /* am_map.c in Sources */, + A1DE850E229F60BE0041E450 /* d_client.c in Sources */, + A1DE850F229F60BE0041E450 /* d_deh.c in Sources */, + A1DE8510229F60BE0041E450 /* iphone_async.cpp in Sources */, + A1DE8511229F60BE0041E450 /* d_items.c in Sources */, + A1DE8512229F60BE0041E450 /* d_main.c in Sources */, + A1DE8513229F60BE0041E450 /* eas_report.c in Sources */, + A1DE8514229F60BE0041E450 /* eas_xmfdata.c in Sources */, + A1DE8515229F60BE0041E450 /* doomdef.c in Sources */, + A1DE8516229F60BE0041E450 /* doomstat.c in Sources */, + A1DE8517229F60BE0041E450 /* iphone_start.cpp in Sources */, + A1DE8518229F60BE0041E450 /* dstrings.c in Sources */, + A1DE8519229F60BE0041E450 /* f_finale.c in Sources */, + A1DE851A229F60BE0041E450 /* RenderContext.mm in Sources */, + A1DE851B229F60BE0041E450 /* eas_ota.c in Sources */, + A1DE851C229F60BE0041E450 /* f_wipe.c in Sources */, + A1DE851D229F60BE0041E450 /* g_game.c in Sources */, + A1DE851E229F60BE0041E450 /* eas_imelodydata.c in Sources */, + A1DE851F229F60BE0041E450 /* MissionMenuViewController.mm in Sources */, + A1DE8520229F60BE0041E450 /* gl_main.c in Sources */, + A1DE8521229F60BE0041E450 /* gl_texture.c in Sources */, + A1DE8522229F60BE0041E450 /* hu_lib.c in Sources */, + A1DE8523229F60BE0041E450 /* hu_stuff.c in Sources */, + A1DE8524229F60BE0041E450 /* info.c in Sources */, + A1DE8525229F60BE0041E450 /* iphone_common.mm in Sources */, + A1DE8526229F60BE0041E450 /* lprintf.c in Sources */, + A1DE8527229F60BE0041E450 /* m_argv.c in Sources */, + A1DE8528229F60BE0041E450 /* m_bbox.c in Sources */, + A1DE8529229F60BE0041E450 /* eas_hostmm.c in Sources */, + A1DE852A229F60BE0041E450 /* m_cheat.c in Sources */, + A1DE852B229F60BE0041E450 /* m_menu.c in Sources */, + A1DE852C229F60BE0041E450 /* MainMenuViewController.mm in Sources */, + A1DE852D229F60BE0041E450 /* m_misc.c in Sources */, + A1DE852E229F60BE0041E450 /* eas_xmf.c in Sources */, + A1DE852F229F60BE0041E450 /* eas_otadata.c in Sources */, + A1DE8531229F60BE0041E450 /* m_random.c in Sources */, + A1DE8532229F60BE0041E450 /* md5.c in Sources */, + A1DE8533229F60BE0041E450 /* eas_wtsynth.c in Sources */, + A1DE8534229F60BE0041E450 /* p_ceilng.c in Sources */, + A1DE8535229F60BE0041E450 /* p_checksum.c in Sources */, + A1DE8536229F60BE0041E450 /* p_doors.c in Sources */, + A1DE8537229F60BE0041E450 /* p_enemy.c in Sources */, + A1DE8538229F60BE0041E450 /* eas_pan.c in Sources */, + A1DE8539229F60BE0041E450 /* p_floor.c in Sources */, + A1DE853A229F60BE0041E450 /* mmus2mid.c in Sources */, + A1DE853B229F60BE0041E450 /* p_genlin.c in Sources */, + A1DE853C229F60BE0041E450 /* Carousel.mm in Sources */, + A1DE853D229F60BE0041E450 /* eas_rtttldata.c in Sources */, + A1DE853E229F60BE0041E450 /* eas_imaadpcm.c in Sources */, + A1DE853F229F60BE0041E450 /* p_inter.c in Sources */, + A1DE8540229F60BE0041E450 /* p_lights.c in Sources */, + A1DE8541229F60BE0041E450 /* p_map.c in Sources */, + A1DE8542229F60BE0041E450 /* p_maputl.c in Sources */, + A1DE8543229F60BE0041E450 /* GameController.mm in Sources */, + A1DE8544229F60BE0041E450 /* p_mobj.c in Sources */, + A1DE8545229F60BE0041E450 /* p_plats.c in Sources */, + A1DE8546229F60BE0041E450 /* p_pspr.c in Sources */, + A1DE8547229F60BE0041E450 /* p_saveg.c in Sources */, + A1DE8548229F60BE0041E450 /* eas_reverbdata.c in Sources */, + A1DE8549229F60BE0041E450 /* SDL_Mixer.m in Sources */, + A1DE854A229F60BE0041E450 /* eas_smf.c in Sources */, + A1DE854B229F60BE0041E450 /* p_setup.c in Sources */, + A1DE854C229F60BE0041E450 /* eas_mididata.c in Sources */, + A1DE854D229F60BE0041E450 /* p_sight.c in Sources */, + A1DE854E229F60BE0041E450 /* eas_wave.c in Sources */, + A1DE854F229F60BE0041E450 /* EASGlue.c in Sources */, + A1DE8550229F60BE0041E450 /* eas_midi.c in Sources */, + A1DE8551229F60BE0041E450 /* p_spec.c in Sources */, + A1DE8552229F60BE0041E450 /* wt_22khz.c in Sources */, + A1DE8553229F60BE0041E450 /* p_switch.c in Sources */, + A1DE8554229F60BE0041E450 /* eas_wavefile.c in Sources */, + A1DE8555229F60BE0041E450 /* eas_chorus.c in Sources */, + A1DE8556229F60BE0041E450 /* p_telept.c in Sources */, + A1DE8557229F60BE0041E450 /* p_tick.c in Sources */, + A1DE8558229F60BE0041E450 /* eas_pcm.c in Sources */, + A1DE8559229F60BE0041E450 /* iphone_glViewController.mm in Sources */, + A1DE855A229F60BE0041E450 /* p_user.c in Sources */, + A1DE855B229F60BE0041E450 /* r_bsp.c in Sources */, + A1DE855C229F60BE0041E450 /* r_data.c in Sources */, + A1DE855D229F60BE0041E450 /* r_demo.c in Sources */, + A1DE855E229F60BE0041E450 /* r_draw.c in Sources */, + A1DE855F229F60BE0041E450 /* CreditsMenuViewController.mm in Sources */, + A1DE8560229F60BE0041E450 /* iphone_sound.mm in Sources */, + A1DE8561229F60BE0041E450 /* r_filter.c in Sources */, + A1DE8562229F60BE0041E450 /* r_fps.c in Sources */, + A1DE8563229F60BE0041E450 /* SoundEngine.cpp in Sources */, + A1DE8564229F60BE0041E450 /* eas_dlssynth.c in Sources */, + A1DE8565229F60BE0041E450 /* r_main.c in Sources */, + A1DE8566229F60BE0041E450 /* r_patch.c in Sources */, + A1DE8567229F60BE0041E450 /* r_plane.c in Sources */, + A1DE8568229F60BE0041E450 /* iphone_sys.mm in Sources */, + A1DE8569229F60BE0041E450 /* r_segs.c in Sources */, + A1DE856A229F60BE0041E450 /* r_sky.c in Sources */, + A1DE856B229F60BE0041E450 /* r_things.c in Sources */, + A1DE856C229F60BE0041E450 /* i_sound.c in Sources */, + A1DE856D229F60BE0041E450 /* eas_wtengine.c in Sources */, + A1DE856E229F60BE0041E450 /* eas_voicemgt.c in Sources */, + A1DE856F229F60BE0041E450 /* LegalMenuViewController.mm in Sources */, + A1DE8570229F60BE0041E450 /* eas_wavefiledata.c in Sources */, + A1DE8571229F60BE0041E450 /* eas_imelody.c in Sources */, + A1DE8572229F60BE0041E450 /* s_sound.c in Sources */, + A1DE8573229F60BE0041E450 /* sounds.c in Sources */, + A1DE8574229F60BE0041E450 /* eas_data.c in Sources */, + A1DE8575229F60BE0041E450 /* st_lib.c in Sources */, + A1DE8576229F60BE0041E450 /* eas_mixer.c in Sources */, + A1DE8577229F60BE0041E450 /* st_stuff.c in Sources */, + A1DE8578229F60BE0041E450 /* tables.c in Sources */, + A1DE8579229F60BE0041E450 /* v_video.c in Sources */, + A1DE857A229F60BE0041E450 /* version.c in Sources */, + A1DE857B229F60BE0041E450 /* eas_flog.c in Sources */, + A1DE857C229F60BE0041E450 /* eas_config.c in Sources */, + A1DE857D229F60BE0041E450 /* w_mmap.c in Sources */, + A1DE857E229F60BE0041E450 /* eas_reverb.c in Sources */, + A1DE857F229F60BE0041E450 /* w_wad.c in Sources */, + A1DE8580229F60BE0041E450 /* wi_stuff.c in Sources */, + A1DE8581229F60BE0041E450 /* z_bmalloc.c in Sources */, + A1DE8582229F60BE0041E450 /* eas_smfdata.c in Sources */, + A1DE8583229F60BE0041E450 /* eas_mixbuf.c in Sources */, + A1DE8584229F60BE0041E450 /* z_zone.c in Sources */, + A1DE8585229F60BE0041E450 /* eas_public.c in Sources */, + A1DE8586229F60BE0041E450 /* cvar.c in Sources */, + A1DE8587229F60BE0041E450 /* misc.c in Sources */, + A1DE8588229F60BE0041E450 /* SettingsMenuViewController.mm in Sources */, + A1DE8589229F60BE0041E450 /* prboomInterface.c in Sources */, + A1DE858A229F60BE0041E450 /* cmd.c in Sources */, + A1DE858B229F60BE0041E450 /* Slider.mm in Sources */, + A1DE858C229F60BE0041E450 /* dict.c in Sources */, + A1DE858D229F60BE0041E450 /* LabelButton.mm in Sources */, + A1DE858E229F60BE0041E450 /* Switch.mm in Sources */, + A1DE858F229F60BE0041E450 /* eas_rtttl.c in Sources */, + A1DE8590229F60BE0041E450 /* geom.c in Sources */, + A1DE8591229F60BE0041E450 /* memalloc.c in Sources */, + A1DE8592229F60BE0041E450 /* eas_pcmdata.c in Sources */, + A1DE8593229F60BE0041E450 /* mesh.c in Sources */, + A1DE8594229F60BE0041E450 /* SecretMenuViewController.mm in Sources */, + A1DE8595229F60BE0041E450 /* eas_tonecontrol.c in Sources */, + A1DE8596229F60BE0041E450 /* normal.c in Sources */, + A1DE8597229F60BE0041E450 /* Label.mm in Sources */, + A1DE8598229F60BE0041E450 /* priorityq.c in Sources */, + A1DE8599229F60BE0041E450 /* render.c in Sources */, + A1DE859A229F60BE0041E450 /* eas_chorusdata.c in Sources */, + A1DE859B229F60BE0041E450 /* eas_math.c in Sources */, + A1DE859C229F60BE0041E450 /* sweep.c in Sources */, + A1DE859D229F60BE0041E450 /* MainNavController.m in Sources */, + A1DE859E229F60BE0041E450 /* eas_ima_tables.c in Sources */, + A1DE859F229F60BE0041E450 /* tess.c in Sources */, + A1DE85A0229F60BE0041E450 /* tessmono.c in Sources */, + A1DE85A1229F60BE0041E450 /* iphone_mapSelect.c in Sources */, + A1DE85A2229F60BE0041E450 /* iphone_render.c in Sources */, + A1DE85A3229F60BE0041E450 /* ControlsMenuViewController.mm in Sources */, + A1DE85A4229F60BE0041E450 /* iphone_net.c in Sources */, + A1DE85A5229F60BE0041E450 /* iphone_email.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1DE861C229F88D20041E450 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1DE861D229F88D20041E450 /* eas_math.c in Sources */, + A1DE861E229F88D20041E450 /* eas_rtttl.c in Sources */, + A1DE861F229F88D20041E450 /* wi_stuff.c in Sources */, + A1DE8620229F88D20041E450 /* z_bmalloc.c in Sources */, + A1DE8621229F88D20041E450 /* md5.c in Sources */, + A1DE8622229F88D20041E450 /* eas_otadata.c in Sources */, + A1DE8623229F88D20041E450 /* st_lib.c in Sources */, + A1DE8624229F88D20041E450 /* eas_tcdata.c in Sources */, + A1DE8625229F88D20041E450 /* dict.c in Sources */, + A1DE8626229F88D20041E450 /* iphone_sys.mm in Sources */, + A1DE8627229F88D20041E450 /* r_main.c in Sources */, + A1DE8628229F88D20041E450 /* p_floor.c in Sources */, + A1DE8629229F88D20041E450 /* v_video.c in Sources */, + A1DE862A229F88D20041E450 /* d_client.c in Sources */, + A1DE862B229F88D20041E450 /* p_plats.c in Sources */, + A1DE862C229F88D20041E450 /* iphone_common.mm in Sources */, + A1DE862D229F88D20041E450 /* gl_texture.c in Sources */, + A1DE862E229F88D20041E450 /* gl_main.c in Sources */, + A1DE862F229F88D20041E450 /* MissionMenuViewController.mm in Sources */, + A1DE8630229F88D20041E450 /* eas_config.c in Sources */, + A1DE8631229F88D20041E450 /* m_random.c in Sources */, + A1DE8632229F88D20041E450 /* info.c in Sources */, + A1DE8633229F88D20041E450 /* main.m in Sources */, + A1DE8634229F88D20041E450 /* d_items.c in Sources */, + A1DE8635229F88D20041E450 /* GameController.mm in Sources */, + A1DE8636229F88D20041E450 /* eas_mixbuf.c in Sources */, + A1DE8637229F88D20041E450 /* m_misc.c in Sources */, + A1DE8638229F88D20041E450 /* p_checksum.c in Sources */, + A1DE8639229F88D20041E450 /* f_finale.c in Sources */, + A1DE863A229F88D20041E450 /* EAGLView.m in Sources */, + A1DE863B229F88D20041E450 /* RenderContext.mm in Sources */, + A1DE863C229F88D20041E450 /* r_things.c in Sources */, + A1DE863D229F88D20041E450 /* eas_flog.c in Sources */, + A1DE863E229F88D20041E450 /* r_segs.c in Sources */, + A1DE863F229F88D20041E450 /* iphone_main.c in Sources */, + A1DE8640229F88D20041E450 /* eas_data.c in Sources */, + A1DE8641229F88D20041E450 /* eas_imelodydata.c in Sources */, + A1DE8642229F88D20041E450 /* hud.c in Sources */, + A1DE8643229F88D20041E450 /* p_setup.c in Sources */, + A1DE8644229F88D20041E450 /* d_deh.c in Sources */, + A1DE8645229F88D20041E450 /* eas_xmfdata.c in Sources */, + A1DE8646229F88D20041E450 /* m_menu.c in Sources */, + A1DE8647229F88D20041E450 /* p_mobj.c in Sources */, + A1DE8648229F88D20041E450 /* p_tick.c in Sources */, + A1DE8649229F88D20041E450 /* p_doors.c in Sources */, + A1DE864A229F88D20041E450 /* tables.c in Sources */, + A1DE864B229F88D20041E450 /* p_telept.c in Sources */, + A1DE864C229F88D20041E450 /* eas_xmf.c in Sources */, + A1DE864D229F88D20041E450 /* doomstat.c in Sources */, + A1DE864E229F88D20041E450 /* eas_wavefile.c in Sources */, + A1DE864F229F88D20041E450 /* ipak.c in Sources */, + A1DE8650229F88D20041E450 /* eas_smfdata.c in Sources */, + A1DE8651229F88D20041E450 /* SoundEngine.cpp in Sources */, + A1DE8652229F88D20041E450 /* p_enemy.c in Sources */, + A1DE8653229F88D20041E450 /* r_filter.c in Sources */, + A1DE8654229F88D20041E450 /* View.mm in Sources */, + A1DE8655229F88D20041E450 /* eas_voicemgt.c in Sources */, + A1DE8656229F88D20041E450 /* priorityq.c in Sources */, + A1DE8657229F88D20041E450 /* Label.mm in Sources */, + A1DE8658229F88D20041E450 /* eas_dlssynth.c in Sources */, + A1DE8659229F88D20041E450 /* w_mmap.c in Sources */, + A1DE865A229F88D20041E450 /* render.c in Sources */, + A1DE865B229F88D20041E450 /* MainMenuViewController.mm in Sources */, + A1DE865C229F88D20041E450 /* iphone_render.c in Sources */, + A1DE865D229F88D20041E450 /* p_inter.c in Sources */, + A1DE865E229F88D20041E450 /* prboomInterface.c in Sources */, + A1DE865F229F88D20041E450 /* eas_hostmm.c in Sources */, + A1DE8660229F88D20041E450 /* r_data.c in Sources */, + A1DE8661229F88D20041E450 /* eas_mididata.c in Sources */, + A1DE8662229F88D20041E450 /* Doom_App.m in Sources */, + A1DE8663229F88D20041E450 /* eas_pcmdata.c in Sources */, + A1DE8664229F88D20041E450 /* normal.c in Sources */, + A1DE8665229F88D20041E450 /* eas_chorusdata.c in Sources */, + A1DE8666229F88D20041E450 /* eas_chorus.c in Sources */, + A1DE8667229F88D20041E450 /* geom.c in Sources */, + A1DE8668229F88D20041E450 /* iphone_loop.c in Sources */, + A1DE8669229F88D20041E450 /* LabelButton.mm in Sources */, + A1DE866A229F88D20041E450 /* SDL_Mixer.m in Sources */, + A1DE866B229F88D20041E450 /* EASGlue.c in Sources */, + A1DE866C229F88D20041E450 /* Switch.mm in Sources */, + A1DE866D229F88D20041E450 /* eas_ima_tables.c in Sources */, + A1DE866E229F88D20041E450 /* s_sound.c in Sources */, + A1DE866F229F88D20041E450 /* eas_ota.c in Sources */, + A1DE8670229F88D20041E450 /* am_map.c in Sources */, + A1DE8671229F88D20041E450 /* p_user.c in Sources */, + A1DE8672229F88D20041E450 /* cmd.c in Sources */, + A1DE8673229F88D20041E450 /* p_map.c in Sources */, + A1DE8674229F88D20041E450 /* eas_smf.c in Sources */, + A1DE8675229F88D20041E450 /* r_plane.c in Sources */, + A1DE8676229F88D20041E450 /* cvar.c in Sources */, + A1DE8677229F88D20041E450 /* misc.c in Sources */, + A1DE8678229F88D20041E450 /* sweep.c in Sources */, + A1DE8679229F88D20041E450 /* iphone_email.m in Sources */, + A1DE867A229F88D20041E450 /* iphone_delegate.mm in Sources */, + A1DE867B229F88D20041E450 /* eas_imelody.c in Sources */, + A1DE867C229F88D20041E450 /* version.c in Sources */, + A1DE867D229F88D20041E450 /* eas_tonecontrol.c in Sources */, + A1DE867E229F88D20041E450 /* LegalMenuViewController.mm in Sources */, + A1DE867F229F88D20041E450 /* r_fps.c in Sources */, + A1DE8680229F88D20041E450 /* m_cheat.c in Sources */, + A1DE8681229F88D20041E450 /* iphone_async.cpp in Sources */, + A1DE8682229F88D20041E450 /* eas_wave.c in Sources */, + A1DE8683229F88D20041E450 /* eas_imaadpcm.c in Sources */, + A1DE8684229F88D20041E450 /* z_zone.c in Sources */, + A1DE8685229F88D20041E450 /* MainNavController.m in Sources */, + A1DE8686229F88D20041E450 /* BackgroundMusic.cpp in Sources */, + A1DE8687229F88D20041E450 /* doomdef.c in Sources */, + A1DE8688229F88D20041E450 /* r_patch.c in Sources */, + A1DE8689229F88D20041E450 /* p_switch.c in Sources */, + A1DE868A229F88D20041E450 /* eas_reverbdata.c in Sources */, + A1DE868B229F88D20041E450 /* eas_report.c in Sources */, + A1DE868C229F88D20041E450 /* memalloc.c in Sources */, + A1DE868D229F88D20041E450 /* eas_wtengine.c in Sources */, + A1DE868E229F88D20041E450 /* eas_public.c in Sources */, + A1DE868F229F88D20041E450 /* eas_wavefiledata.c in Sources */, + A1DE8690229F88D20041E450 /* gles_glue.c in Sources */, + A1DE8691229F88D20041E450 /* iphone_net.c in Sources */, + A1DE8692229F88D20041E450 /* eas_mixer.c in Sources */, + A1DE8693229F88D20041E450 /* sounds.c in Sources */, + A1DE8694229F88D20041E450 /* eas_rtttldata.c in Sources */, + A1DE8695229F88D20041E450 /* d_main.c in Sources */, + A1DE8696229F88D20041E450 /* wt_22khz.c in Sources */, + A1DE8697229F88D20041E450 /* p_saveg.c in Sources */, + A1DE8698229F88D20041E450 /* p_genlin.c in Sources */, + A1DE8699229F88D20041E450 /* ControlsMenuViewController.mm in Sources */, + A1DE869A229F88D20041E450 /* tessmono.c in Sources */, + A1DE869B229F88D20041E450 /* tess.c in Sources */, + A1DE869C229F88D20041E450 /* iphone_mapSelect.c in Sources */, + A1DE869D229F88D20041E450 /* eas_reverb.c in Sources */, + A1DE869E229F88D20041E450 /* eas_wtsynth.c in Sources */, + A1DE869F229F88D20041E450 /* r_draw.c in Sources */, + A1DE86A0229F88D20041E450 /* eas_mdls.c in Sources */, + A1DE86A1229F88D20041E450 /* SettingsMenuViewController.mm in Sources */, + A1DE86A2229F88D20041E450 /* st_stuff.c in Sources */, + A1DE86A3229F88D20041E450 /* i_sound.c in Sources */, + A1DE86A4229F88D20041E450 /* CreditsMenuViewController.mm in Sources */, + A1DE86A5229F88D20041E450 /* p_lights.c in Sources */, + A1DE86A6229F88D20041E450 /* w_wad.c in Sources */, + A1DE86A7229F88D20041E450 /* p_spec.c in Sources */, + A1DE86A8229F88D20041E450 /* m_bbox.c in Sources */, + A1DE86A9229F88D20041E450 /* dstrings.c in Sources */, + A1DE86AA229F88D20041E450 /* r_sky.c in Sources */, + A1DE86AB229F88D20041E450 /* hu_lib.c in Sources */, + A1DE86AC229F88D20041E450 /* iphone_sound.mm in Sources */, + A1DE86AD229F88D20041E450 /* r_bsp.c in Sources */, + A1DE86AF229F88D20041E450 /* iphone_glViewController.mm in Sources */, + A1DE86B0229F88D20041E450 /* mmus2mid.c in Sources */, + A1DE86B1229F88D20041E450 /* r_demo.c in Sources */, + A1DE86B2229F88D20041E450 /* g_game.c in Sources */, + A1DE86B3229F88D20041E450 /* p_maputl.c in Sources */, + A1DE86B4229F88D20041E450 /* Localization.mm in Sources */, + A1DE86B5229F88D20041E450 /* eas_midi.c in Sources */, + A1DE86B6229F88D20041E450 /* m_argv.c in Sources */, + A1DE86B7229F88D20041E450 /* p_ceilng.c in Sources */, + A1DE86B8229F88D20041E450 /* mesh.c in Sources */, + A1DE86B9229F88D20041E450 /* eas_pcm.c in Sources */, + A1DE86BA229F88D20041E450 /* p_sight.c in Sources */, + A1DE86BB229F88D20041E450 /* hu_stuff.c in Sources */, + A1DE86BC229F88D20041E450 /* lprintf.c in Sources */, + A1DE86BD229F88D20041E450 /* Carousel.mm in Sources */, + A1DE86BE229F88D20041E450 /* f_wipe.c in Sources */, + A1DE86BF229F88D20041E450 /* eas_pan.c in Sources */, + A1DE86C0229F88D20041E450 /* iphone_start.cpp in Sources */, + A1DE86C1229F88D20041E450 /* p_pspr.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _DEBUG, + _SAMPLE_RATE_22050, + EAS_WT_SYNTH, + _8_BIT_SAMPLES, + _REVERB_ENABLED, + _CHORUS_ENABLED, + _FILTER_ENABLED, + "MAX_SYNTH_VOICES=32", + "NUM_OUTPUT_CHANNELS=2", + UNIFIED_DEBUG_MESSAGES, + DLS_SYNTHESIZER, + GAME_DOOM, + GLES_SILENCE_DEPRECATION, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.idsoftware.${PRODUCT_NAME:identifier}"; + PRODUCT_NAME = DOOM; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM, + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + HAVE_CONFIG_H, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.idsoftware.${PRODUCT_NAME:identifier}"; + PRODUCT_NAME = DOOM; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 4364BF480F5CB27300F29317 /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = dist.plist; + CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_THUMB_SUPPORT = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + PRODUCT_NAME = Doom; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + SDKROOT = iphoneos; + VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES; + }; + name = AdHocDist; + }; + 4364BF490F5CB27300F29317 /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.idsoftware.${PRODUCT_NAME:identifier}"; + PRODUCT_NAME = DOOM; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = AdHocDist; + }; + 43AE7CA40F61EC4E00B2F562 /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer: Gregory Hodges (255R7FQ4L3)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Gregory Hodges (255R7FQ4L3)"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_THUMB_SUPPORT = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + PRODUCT_NAME = Doom; + SDKROOT = iphoneos; + VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES; + }; + name = ReleaseLite; + }; + 43AE7CA50F61EC4E00B2F562 /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.idsoftware.${PRODUCT_NAME:identifier}"; + PRODUCT_NAME = DOOM; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = ReleaseLite; + }; + 43AE7CAE0F61FC9200B2F562 /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer: Gregory Hodges (255R7FQ4L3)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Gregory Hodges (255R7FQ4L3)"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = Doom; + SDKROOT = iphoneos; + VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES; + }; + name = DebugLite; + }; + 43AE7CAF0F61FC9200B2F562 /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.idsoftware.${PRODUCT_NAME:identifier}"; + PRODUCT_NAME = DOOM; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugLite; + }; + A10639CC216EF7C700BDE196 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _DEBUG, + _SAMPLE_RATE_22050, + EAS_WT_SYNTH, + _8_BIT_SAMPLES, + _REVERB_ENABLED, + _CHORUS_ENABLED, + _FILTER_ENABLED, + "MAX_SYNTH_VOICES=32", + "NUM_OUTPUT_CHANNELS=2", + UNIFIED_DEBUG_MESSAGES, + DLS_SYNTHESIZER, + GAME_DOOM2, + GLES_SILENCE_DEPRECATION, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM2-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.Doom2TV; + PRODUCT_NAME = "DOOM II"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Debug; + }; + A10639CD216EF7C700BDE196 /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM2-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.Doom2TV; + PRODUCT_NAME = "DOOM II"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = DebugLite; + }; + A10639CE216EF7C700BDE196 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM2, + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + HAVE_CONFIG_H, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM2-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.Doom2TV; + PRODUCT_NAME = "DOOM II"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Release; + }; + A10639CF216EF7C700BDE196 /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM2-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.Doom2TV; + PRODUCT_NAME = "DOOM II"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = ReleaseLite; + }; + A10639D0216EF7C700BDE196 /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM2-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.Doom2TV; + PRODUCT_NAME = "DOOM II"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = AdHocDist; + }; + A10639D1216EF7C700BDE196 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM2, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM2-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.Doom2TV; + PRODUCT_NAME = "DOOM II"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Distribution; + }; + A1063AE8216EFCEE00BDE196 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _DEBUG, + _SAMPLE_RATE_22050, + EAS_WT_SYNTH, + _8_BIT_SAMPLES, + _REVERB_ENABLED, + _CHORUS_ENABLED, + _FILTER_ENABLED, + "MAX_SYNTH_VOICES=32", + "NUM_OUTPUT_CHANNELS=2", + UNIFIED_DEBUG_MESSAGES, + DLS_SYNTHESIZER, + GAME_FINALDOOM, + GLES_SILENCE_DEPRECATION, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "FinalDOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.FInalDOOM; + PRODUCT_NAME = "FInal DOOM"; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A1063AE9216EFCEE00BDE196 /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "FinalDOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.FInalDOOM; + PRODUCT_NAME = "FInal DOOM"; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugLite; + }; + A1063AEA216EFCEE00BDE196 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_FINALDOOM, + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + HAVE_CONFIG_H, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "FinalDOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.FInalDOOM; + PRODUCT_NAME = "FInal DOOM"; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + A1063AEB216EFCEE00BDE196 /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "FinalDOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.FInalDOOM; + PRODUCT_NAME = "FInal DOOM"; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = ReleaseLite; + }; + A1063AEC216EFCEE00BDE196 /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "FinalDOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.FInalDOOM; + PRODUCT_NAME = "FInal DOOM"; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = AdHocDist; + }; + A1063AED216EFCEE00BDE196 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Distribution: id Software"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "FinalDOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.FInalDOOM; + PRODUCT_NAME = "FInal DOOM"; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "18BCE49D-8823-4A0C-B597-CFE83C7820BE"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Distribution; + }; + A1063BFB216F012000BDE196 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _DEBUG, + _SAMPLE_RATE_22050, + EAS_WT_SYNTH, + _8_BIT_SAMPLES, + _REVERB_ENABLED, + _CHORUS_ENABLED, + _FILTER_ENABLED, + "MAX_SYNTH_VOICES=32", + "NUM_OUTPUT_CHANNELS=2", + UNIFIED_DEBUG_MESSAGES, + DLS_SYNTHESIZER, + GAME_FINALDOOM, + GLES_SILENCE_DEPRECATION, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "FinalDOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.FinalDoomTV; + PRODUCT_NAME = "Final DOOM"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Debug; + }; + A1063BFC216F012000BDE196 /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "FinalDOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.FinalDoomTV; + PRODUCT_NAME = "Final DOOM"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = DebugLite; + }; + A1063BFD216F012000BDE196 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_FINALDOOM, + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + HAVE_CONFIG_H, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "FinalDOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.FinalDoomTV; + PRODUCT_NAME = "Final DOOM"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Release; + }; + A1063BFE216F012000BDE196 /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "FinalDOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.FinalDoomTV; + PRODUCT_NAME = "Final DOOM"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = ReleaseLite; + }; + A1063BFF216F012000BDE196 /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "FinalDOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.FinalDoomTV; + PRODUCT_NAME = "Final DOOM"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = AdHocDist; + }; + A1063C00216F012000BDE196 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_FINALDOOM, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "FinalDOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.FinalDoomTV; + PRODUCT_NAME = "Final DOOM"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Distribution; + }; + A1870919216EB633006C013F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _DEBUG, + _SAMPLE_RATE_22050, + EAS_WT_SYNTH, + _8_BIT_SAMPLES, + _REVERB_ENABLED, + _CHORUS_ENABLED, + _FILTER_ENABLED, + "MAX_SYNTH_VOICES=32", + "NUM_OUTPUT_CHANNELS=2", + UNIFIED_DEBUG_MESSAGES, + DLS_SYNTHESIZER, + GAME_DOOM2, + GLES_SILENCE_DEPRECATION, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM2-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.DOOM2; + PRODUCT_NAME = "DOOM II"; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A187091A216EB633006C013F /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM2-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.DOOM2; + PRODUCT_NAME = "DOOM II"; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugLite; + }; + A187091B216EB633006C013F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM2, + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + HAVE_CONFIG_H, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM2-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.DOOM2; + PRODUCT_NAME = "DOOM II"; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + A187091C216EB633006C013F /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM2-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.DOOM2; + PRODUCT_NAME = "DOOM II"; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = ReleaseLite; + }; + A187091D216EB633006C013F /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM2-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.DOOM2; + PRODUCT_NAME = "DOOM II"; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = AdHocDist; + }; + A187091E216EB633006C013F /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Distribution: id Software"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM2, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM2-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.DOOM2; + PRODUCT_NAME = "DOOM II"; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "18BCE49D-8823-4A0C-B597-CFE83C7820BE"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Distribution; + }; + A1B98DFA207EFEEA00827A46 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _DEBUG, + _SAMPLE_RATE_22050, + EAS_WT_SYNTH, + _8_BIT_SAMPLES, + _REVERB_ENABLED, + _CHORUS_ENABLED, + _FILTER_ENABLED, + "MAX_SYNTH_VOICES=32", + "NUM_OUTPUT_CHANNELS=2", + UNIFIED_DEBUG_MESSAGES, + DLS_SYNTHESIZER, + GAME_DOOM, + GLES_SILENCE_DEPRECATION, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.DoomTV; + PRODUCT_NAME = DOOM; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Debug; + }; + A1B98DFB207EFEEA00827A46 /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.DoomTV; + PRODUCT_NAME = DOOM; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = DebugLite; + }; + A1B98DFC207EFEEA00827A46 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM, + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + HAVE_CONFIG_H, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.DoomTV; + PRODUCT_NAME = DOOM; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Release; + }; + A1B98DFD207EFEEA00827A46 /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.DoomTV; + PRODUCT_NAME = DOOM; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = ReleaseLite; + }; + A1B98DFE207EFEEA00827A46 /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.DoomTV; + PRODUCT_NAME = DOOM; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = AdHocDist; + }; + A1B98DFF207EFEEA00827A46 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "DOOM-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.DoomTV; + PRODUCT_NAME = DOOM; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Distribution; + }; + A1DE85B2229F60BE0041E450 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _DEBUG, + _SAMPLE_RATE_22050, + EAS_WT_SYNTH, + _8_BIT_SAMPLES, + _REVERB_ENABLED, + _CHORUS_ENABLED, + _FILTER_ENABLED, + "MAX_SYNTH_VOICES=32", + "NUM_OUTPUT_CHANNELS=2", + UNIFIED_DEBUG_MESSAGES, + DLS_SYNTHESIZER, + GAME_SIGIL, + GLES_SILENCE_DEPRECATION, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "SIGIL-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.SIGIL; + PRODUCT_NAME = SIGIL; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A1DE85B3229F60BE0041E450 /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "SIGIL-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.SIGIL; + PRODUCT_NAME = SIGIL; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = DebugLite; + }; + A1DE85B4229F60BE0041E450 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_SIGIL, + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + HAVE_CONFIG_H, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "SIGIL-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.SIGIL; + PRODUCT_NAME = SIGIL; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + A1DE85B5229F60BE0041E450 /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "SIGIL-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.SIGIL; + PRODUCT_NAME = SIGIL; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = ReleaseLite; + }; + A1DE85B6229F60BE0041E450 /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "SIGIL-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.SIGIL; + PRODUCT_NAME = SIGIL; + PROFILE_PREFIX = com.idsoftware; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = AdHocDist; + }; + A1DE85B7229F60BE0041E450 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Distribution: id Software"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_SIGIL, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "SIGIL-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = com.idsoftware.SIGIL; + PRODUCT_NAME = SIGIL; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "18BCE49D-8823-4A0C-B597-CFE83C7820BE"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Distribution; + }; + A1DE86CE229F88D20041E450 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _DEBUG, + _SAMPLE_RATE_22050, + EAS_WT_SYNTH, + _8_BIT_SAMPLES, + _REVERB_ENABLED, + _CHORUS_ENABLED, + _FILTER_ENABLED, + "MAX_SYNTH_VOICES=32", + "NUM_OUTPUT_CHANNELS=2", + UNIFIED_DEBUG_MESSAGES, + DLS_SYNTHESIZER, + GAME_SIGIL, + GLES_SILENCE_DEPRECATION, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "SIGIL-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.SIGILTV; + PRODUCT_NAME = SIGL; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Debug; + }; + A1DE86CF229F88D20041E450 /* DebugLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "SIGIL-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.SIGILTV; + PRODUCT_NAME = SIGL; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = DebugLite; + }; + A1DE86D0229F88D20041E450 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_SIGIL, + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + HAVE_CONFIG_H, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "SIGIL-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.SIGILTV; + PRODUCT_NAME = SIGL; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Release; + }; + A1DE86D1229F88D20041E450 /* ReleaseLite */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + EPISODE1, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "SIGIL-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.SIGILTV; + PRODUCT_NAME = SIGL; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = ReleaseLite; + }; + A1DE86D2229F88D20041E450 /* AdHocDist */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "SIGIL-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.SIGILTV; + PRODUCT_NAME = SIGL; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = AdHocDist; + }; + A1DE86D3229F88D20041E450 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = "Brand Assets"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ANALYZER_NONNULL = YES_NONAGGRESSIVE; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = NO; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_SIGIL, + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + INFOPLIST_FILE = "SIGIL-tvOS-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.tomkiddconsulting.SIGILTV; + PRODUCT_NAME = SIGL; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 12.0; + VALIDATE_PRODUCT = NO; + }; + name = Distribution; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "HAVE_CONFIG_H=1", + UNIFIED_DEBUG_MESSAGES, + _SAMPLE_RATE_22050, + GLES_SILENCE_DEPRECATION, + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = Doom; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + SDKROOT = iphoneos; + VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + UNIFIED_DEBUG_MESSAGES, + _SAMPLE_RATE_22050, + ); + GCC_THUMB_SUPPORT = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + PRODUCT_NAME = Doom; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + SDKROOT = iphoneos; + VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES; + }; + name = Release; + }; + ED06595B1087C51800E5450B /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution: id Software"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: id Software"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + UNIFIED_DEBUG_MESSAGES, + _SAMPLE_RATE_22050, + ); + GCC_THUMB_SUPPORT = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + PRODUCT_NAME = Doom; + PROVISIONING_PROFILE = "31C73095-0DD9-4ABA-BB25-8D23F661F10F"; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "31C73095-0DD9-4ABA-BB25-8D23F661F10F"; + SDKROOT = iphoneos; + VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES; + }; + name = Distribution; + }; + ED06595C1087C51800E5450B /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_STRICT_PROTOTYPES = NO; + CODE_SIGN_IDENTITY = "iPhone Distribution: id Software"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = 9UY8SFDNQ8; + ENABLE_STRICT_OBJC_MSGSEND = NO; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = doom_Prefix.pch; + GCC_PREPROCESSOR_DEFINITIONS = ( + HAVE_CONFIG_H, + IPHONE, + _SAMPLE_RATE_22050, + GAME_DOOM, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = "DOOM-iOS-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.idsoftware.${PRODUCT_NAME:identifier}"; + PRODUCT_NAME = DOOM; + PROFILE_PREFIX = com.idsoftware; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = "18BCE49D-8823-4A0C-B597-CFE83C7820BE"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Distribution; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "DOOM-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 43AE7CAF0F61FC9200B2F562 /* DebugLite */, + 1D6058950D05DD3E006BFB54 /* Release */, + 43AE7CA50F61EC4E00B2F562 /* ReleaseLite */, + 4364BF490F5CB27300F29317 /* AdHocDist */, + ED06595C1087C51800E5450B /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A10639CB216EF7C700BDE196 /* Build configuration list for PBXNativeTarget "DOOM2-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A10639CC216EF7C700BDE196 /* Debug */, + A10639CD216EF7C700BDE196 /* DebugLite */, + A10639CE216EF7C700BDE196 /* Release */, + A10639CF216EF7C700BDE196 /* ReleaseLite */, + A10639D0216EF7C700BDE196 /* AdHocDist */, + A10639D1216EF7C700BDE196 /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1063AE7216EFCEE00BDE196 /* Build configuration list for PBXNativeTarget "FInalDOOM-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1063AE8216EFCEE00BDE196 /* Debug */, + A1063AE9216EFCEE00BDE196 /* DebugLite */, + A1063AEA216EFCEE00BDE196 /* Release */, + A1063AEB216EFCEE00BDE196 /* ReleaseLite */, + A1063AEC216EFCEE00BDE196 /* AdHocDist */, + A1063AED216EFCEE00BDE196 /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1063BFA216F012000BDE196 /* Build configuration list for PBXNativeTarget "FInalDOOM-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1063BFB216F012000BDE196 /* Debug */, + A1063BFC216F012000BDE196 /* DebugLite */, + A1063BFD216F012000BDE196 /* Release */, + A1063BFE216F012000BDE196 /* ReleaseLite */, + A1063BFF216F012000BDE196 /* AdHocDist */, + A1063C00216F012000BDE196 /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1870918216EB633006C013F /* Build configuration list for PBXNativeTarget "DOOM2-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1870919216EB633006C013F /* Debug */, + A187091A216EB633006C013F /* DebugLite */, + A187091B216EB633006C013F /* Release */, + A187091C216EB633006C013F /* ReleaseLite */, + A187091D216EB633006C013F /* AdHocDist */, + A187091E216EB633006C013F /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1B98E00207EFEEA00827A46 /* Build configuration list for PBXNativeTarget "DOOM-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1B98DFA207EFEEA00827A46 /* Debug */, + A1B98DFB207EFEEA00827A46 /* DebugLite */, + A1B98DFC207EFEEA00827A46 /* Release */, + A1B98DFD207EFEEA00827A46 /* ReleaseLite */, + A1B98DFE207EFEEA00827A46 /* AdHocDist */, + A1B98DFF207EFEEA00827A46 /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1DE85B1229F60BE0041E450 /* Build configuration list for PBXNativeTarget "SIGIL-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1DE85B2229F60BE0041E450 /* Debug */, + A1DE85B3229F60BE0041E450 /* DebugLite */, + A1DE85B4229F60BE0041E450 /* Release */, + A1DE85B5229F60BE0041E450 /* ReleaseLite */, + A1DE85B6229F60BE0041E450 /* AdHocDist */, + A1DE85B7229F60BE0041E450 /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1DE86CD229F88D20041E450 /* Build configuration list for PBXNativeTarget "SIGL-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1DE86CE229F88D20041E450 /* Debug */, + A1DE86CF229F88D20041E450 /* DebugLite */, + A1DE86D0229F88D20041E450 /* Release */, + A1DE86D1229F88D20041E450 /* ReleaseLite */, + A1DE86D2229F88D20041E450 /* AdHocDist */, + A1DE86D3229F88D20041E450 /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DOOM" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + 43AE7CAE0F61FC9200B2F562 /* DebugLite */, + C01FCF5008A954540054247B /* Release */, + 43AE7CA40F61EC4E00B2F562 /* ReleaseLite */, + 4364BF480F5CB27300F29317 /* AdHocDist */, + ED06595B1087C51800E5450B /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/code/iphone/Doom.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/code/iphone/DOOM.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 53% rename from code/iphone/Doom.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to code/iphone/DOOM.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 618f2d7..22b175d 100644 --- a/code/iphone/Doom.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/code/iphone/DOOM.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:/Users/tomkidd/Documents/GitHub/DOOM-iOS/code/iphone/DOOM.xcodeproj"> diff --git a/code/iphone/DOOM.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/code/iphone/DOOM.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/code/iphone/Doom.xcodeproj/project.xcworkspace/xcuserdata/jeff.farrand.xcuserdatad/WorkspaceSettings.xcsettings b/code/iphone/DOOM.xcodeproj/project.xcworkspace/xcuserdata/jeff.farrand.xcuserdatad/WorkspaceSettings.xcsettings similarity index 100% rename from code/iphone/Doom.xcodeproj/project.xcworkspace/xcuserdata/jeff.farrand.xcuserdatad/WorkspaceSettings.xcsettings rename to code/iphone/DOOM.xcodeproj/project.xcworkspace/xcuserdata/jeff.farrand.xcuserdatad/WorkspaceSettings.xcsettings diff --git a/code/iphone/DOOM.xcodeproj/project.xcworkspace/xcuserdata/tomkidd.xcuserdatad/IDEFindNavigatorScopes.plist b/code/iphone/DOOM.xcodeproj/project.xcworkspace/xcuserdata/tomkidd.xcuserdatad/IDEFindNavigatorScopes.plist new file mode 100644 index 0000000..5dd5da8 --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/project.xcworkspace/xcuserdata/tomkidd.xcuserdatad/IDEFindNavigatorScopes.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/code/iphone/Doom.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/Doom.xcscheme b/code/iphone/DOOM.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/Doom.xcscheme similarity index 100% rename from code/iphone/Doom.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/Doom.xcscheme rename to code/iphone/DOOM.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/Doom.xcscheme diff --git a/code/iphone/Doom.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist b/code/iphone/DOOM.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist similarity index 100% rename from code/iphone/Doom.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist rename to code/iphone/DOOM.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM-iOS.xcscheme b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM-iOS.xcscheme new file mode 100644 index 0000000..d03a39b --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM-iOS.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM-tvOS.xcscheme b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM-tvOS.xcscheme new file mode 100644 index 0000000..2554725 --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM-tvOS.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM2-iOS.xcscheme b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM2-iOS.xcscheme new file mode 100644 index 0000000..fe0e23a --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM2-iOS.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM2-tvOS.xcscheme b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM2-tvOS.xcscheme new file mode 100644 index 0000000..31d168d --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/DOOM2-tvOS.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/FinalDOOM-iOS.xcscheme b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/FinalDOOM-iOS.xcscheme new file mode 100644 index 0000000..e9ec09f --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/FinalDOOM-iOS.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/FinalDOOM-tvOS.xcscheme b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/FinalDOOM-tvOS.xcscheme new file mode 100644 index 0000000..db1698f --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/FinalDOOM-tvOS.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/xcschememanagement.plist b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..2b78556 --- /dev/null +++ b/code/iphone/DOOM.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,67 @@ + + + + + SchemeUserState + + DOOM-iOS.xcscheme + + orderHint + 0 + + DOOM-tvOS.xcscheme + + orderHint + 1 + + DOOM2-iOS.xcscheme + + orderHint + 2 + + DOOM2-tvOS.xcscheme + + orderHint + 3 + + FinalDOOM-iOS.xcscheme + + orderHint + 4 + + FinalDOOM-tvOS.xcscheme + + orderHint + 5 + + SIGIL-iOS.xcscheme + + orderHint + 6 + + SIGIL-iOS.xcscheme_^#shared#^_ + + orderHint + 6 + + SIGIL-tvOS.xcscheme + + orderHint + 7 + + SIGL-tvOS.xcscheme_^#shared#^_ + + orderHint + 7 + + + SuppressBuildableAutocreation + + A1870806216EB633006C013F + + primary + + + + + diff --git a/code/iphone/DOOM2-iOS-Info.plist b/code/iphone/DOOM2-iOS-Info.plist new file mode 100755 index 0000000..a771361 --- /dev/null +++ b/code/iphone/DOOM2-iOS-Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + DOOM_57.png + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 2.7 + CFBundleSignature + ???? + CFBundleVersion + 2.7 + LSRequiresIPhoneOS + + UIAppFonts + + idGinzaNar-Md2.otf + + UIFileSharingEnabled + + UIInterfaceOrientation + UIInterfaceOrientationLandscapeLeft + UILaunchStoryboardName + DOOM2LaunchScreen + UIPrerenderedIcon + + UIRequiresFullScreen + + UIRequiresPersistentWiFi + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Contents.json b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..0cc2196 --- /dev/null +++ b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-40.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-60.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-58.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-87.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-80.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-120.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-121.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-180.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-41.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-59.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-42.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-81.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-152.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-167.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-1024.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-1024.png new file mode 100755 index 0000000..4602530 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-1024.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-120.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-120.png new file mode 100755 index 0000000..dfbcfcc Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-120.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-121.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-121.png new file mode 100644 index 0000000..dfbcfcc Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-121.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-152.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-152.png new file mode 100755 index 0000000..833a2e3 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-152.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-167.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-167.png new file mode 100755 index 0000000..9ba8f0a Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-167.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-180.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-180.png new file mode 100755 index 0000000..64ae991 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-180.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-20.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-20.png new file mode 100755 index 0000000..61ae685 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-20.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-29.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-29.png new file mode 100755 index 0000000..4f7deed Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-29.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-40.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-40.png new file mode 100755 index 0000000..2a82ac5 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-40.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-41.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-41.png new file mode 100644 index 0000000..2a82ac5 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-41.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-42.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-42.png new file mode 100644 index 0000000..2a82ac5 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-42.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-58.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-58.png new file mode 100755 index 0000000..0d3e410 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-58.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-59.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-59.png new file mode 100644 index 0000000..0d3e410 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-59.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-60.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-60.png new file mode 100755 index 0000000..973b56d Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-60.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-76.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100755 index 0000000..e1d0122 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-80.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-80.png new file mode 100755 index 0000000..8d17d1a Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-80.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-81.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-81.png new file mode 100644 index 0000000..8d17d1a Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-81.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-87.png b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-87.png new file mode 100755 index 0000000..f7056b3 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/AppIcon.appiconset/Icon-87.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/Contents.json b/code/iphone/DOOM2-iOS.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM2-iOS.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-iOS.xcassets/background.imageset/Contents.json b/code/iphone/DOOM2-iOS.xcassets/background.imageset/Contents.json new file mode 100644 index 0000000..ee3dcd2 --- /dev/null +++ b/code/iphone/DOOM2-iOS.xcassets/background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doom2_background.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-iOS.xcassets/background.imageset/doom2_background.png b/code/iphone/DOOM2-iOS.xcassets/background.imageset/doom2_background.png new file mode 100644 index 0000000..11d57f6 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/background.imageset/doom2_background.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/logo.imageset/Contents.json b/code/iphone/DOOM2-iOS.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..3cd2b6b --- /dev/null +++ b/code/iphone/DOOM2-iOS.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doom2logo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-iOS.xcassets/logo.imageset/doom2logo.png b/code/iphone/DOOM2-iOS.xcassets/logo.imageset/doom2logo.png new file mode 100644 index 0000000..86ca2ee Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/logo.imageset/doom2logo.png differ diff --git a/code/iphone/DOOM2-iOS.xcassets/splash.imageset/Contents.json b/code/iphone/DOOM2-iOS.xcassets/splash.imageset/Contents.json new file mode 100644 index 0000000..febe501 --- /dev/null +++ b/code/iphone/DOOM2-iOS.xcassets/splash.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doom2cover.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-iOS.xcassets/splash.imageset/doom2cover.jpg b/code/iphone/DOOM2-iOS.xcassets/splash.imageset/doom2cover.jpg new file mode 100644 index 0000000..6c1c3a7 Binary files /dev/null and b/code/iphone/DOOM2-iOS.xcassets/splash.imageset/doom2cover.jpg differ diff --git a/code/iphone/DOOM2-tvOS-Info.plist b/code/iphone/DOOM2-tvOS-Info.plist new file mode 100644 index 0000000..cfd92bf --- /dev/null +++ b/code/iphone/DOOM2-tvOS-Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIAppFonts + + idGinzaNar-Md2.otf + + UIRequiredDeviceCapabilities + + arm64 + + UIUserInterfaceStyle + Automatic + + diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..846597c --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "doom2_tvos_icon_back.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/doom2_tvos_icon_back.png b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/doom2_tvos_icon_back.png new file mode 100644 index 0000000..6603e4d Binary files /dev/null and b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/doom2_tvos_icon_back.png differ diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..b64157f --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "doom2_tvos_icon_front.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/doom2_tvos_icon_front.png b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/doom2_tvos_icon_front.png new file mode 100644 index 0000000..23b4337 Binary files /dev/null and b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/doom2_tvos_icon_front.png differ diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..a94fbcd --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "doom2_tvos_icon_middle.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/doom2_tvos_icon_middle.png b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/doom2_tvos_icon_middle.png new file mode 100644 index 0000000..fece3ba Binary files /dev/null and b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/doom2_tvos_icon_middle.png differ diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Contents.json new file mode 100644 index 0000000..2cdcef1 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Contents.json @@ -0,0 +1,35 @@ +{ + "assets" : [ + { + "size" : "1280x768", + "idiom" : "tv", + "filename" : "App Icon - App Store.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "400x240", + "idiom" : "tv", + "filename" : "App Icon.imagestack", + "role" : "primary-app-icon" + }, + { + "filename" : "LaunchImage.launchimage" + }, + { + "size" : "2320x720", + "idiom" : "tv", + "filename" : "Top Shelf Image Wide.imageset", + "role" : "top-shelf-image-wide" + }, + { + "size" : "1920x720", + "idiom" : "tv", + "filename" : "Top Shelf Image.imageset", + "role" : "top-shelf-image" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..071695b --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "orientation" : "landscape", + "idiom" : "tv", + "extent" : "full-screen", + "minimum-system-version" : "11.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "tv", + "filename" : "doom2_tvos_launch.jpg", + "extent" : "full-screen", + "minimum-system-version" : "9.0", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/doom2_tvos_launch.jpg b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/doom2_tvos_launch.jpg new file mode 100644 index 0000000..87e82b5 Binary files /dev/null and b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/doom2_tvos_launch.jpg differ diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..fe6cc4c --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "doom_banner_2.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/doom_banner_2.png b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/doom_banner_2.png new file mode 100644 index 0000000..c5c202f Binary files /dev/null and b/code/iphone/DOOM2-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/doom_banner_2.png differ diff --git a/code/iphone/DOOM2-tvOS.xcassets/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/background.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/background.imageset/Contents.json new file mode 100644 index 0000000..ee3dcd2 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "doom2_background.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/background.imageset/doom2_background.png b/code/iphone/DOOM2-tvOS.xcassets/background.imageset/doom2_background.png new file mode 100644 index 0000000..11d57f6 Binary files /dev/null and b/code/iphone/DOOM2-tvOS.xcassets/background.imageset/doom2_background.png differ diff --git a/code/iphone/DOOM2-tvOS.xcassets/logo.imageset/Contents.json b/code/iphone/DOOM2-tvOS.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..404bbe2 --- /dev/null +++ b/code/iphone/DOOM2-tvOS.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "DoomII.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/DOOM2-tvOS.xcassets/logo.imageset/DoomII.png b/code/iphone/DOOM2-tvOS.xcassets/logo.imageset/DoomII.png new file mode 100644 index 0000000..5713fe0 Binary files /dev/null and b/code/iphone/DOOM2-tvOS.xcassets/logo.imageset/DoomII.png differ diff --git a/code/iphone/DOOM2LaunchScreen.storyboard b/code/iphone/DOOM2LaunchScreen.storyboard new file mode 100644 index 0000000..08acdd0 --- /dev/null +++ b/code/iphone/DOOM2LaunchScreen.storyboard @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/DOOMLaunchScreen.storyboard b/code/iphone/DOOMLaunchScreen.storyboard new file mode 100644 index 0000000..cb18412 --- /dev/null +++ b/code/iphone/DOOMLaunchScreen.storyboard @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/DOOM_114.png b/code/iphone/DOOM_114.png new file mode 100644 index 0000000..ec3978d Binary files /dev/null and b/code/iphone/DOOM_114.png differ diff --git a/code/iphone/DOOM_120.png b/code/iphone/DOOM_120.png new file mode 100644 index 0000000..d479d63 Binary files /dev/null and b/code/iphone/DOOM_120.png differ diff --git a/code/iphone/DOOM_144.png b/code/iphone/DOOM_144.png new file mode 100644 index 0000000..35de5ec Binary files /dev/null and b/code/iphone/DOOM_144.png differ diff --git a/code/iphone/DOOM_152.png b/code/iphone/DOOM_152.png new file mode 100644 index 0000000..e4dfb30 Binary files /dev/null and b/code/iphone/DOOM_152.png differ diff --git a/code/iphone/DOOM_400.png b/code/iphone/DOOM_400.png new file mode 100644 index 0000000..e4dfb30 Binary files /dev/null and b/code/iphone/DOOM_400.png differ diff --git a/code/iphone/DOOM_57.png b/code/iphone/DOOM_57.png new file mode 100644 index 0000000..0a205eb Binary files /dev/null and b/code/iphone/DOOM_57.png differ diff --git a/code/iphone/DOOM_72.png b/code/iphone/DOOM_72.png new file mode 100644 index 0000000..88c176f Binary files /dev/null and b/code/iphone/DOOM_72.png differ diff --git a/code/iphone/DOOM_76.png b/code/iphone/DOOM_76.png new file mode 100644 index 0000000..ea6913c Binary files /dev/null and b/code/iphone/DOOM_76.png differ diff --git a/code/iphone/DOOM_sigil_decal.png b/code/iphone/DOOM_sigil_decal.png new file mode 100644 index 0000000..2fc60ed Binary files /dev/null and b/code/iphone/DOOM_sigil_decal.png differ diff --git a/code/iphone/Default-568h@2x.png b/code/iphone/Default-568h@2x.png new file mode 100644 index 0000000..0891b7a Binary files /dev/null and b/code/iphone/Default-568h@2x.png differ diff --git a/code/iphone/Default-Landscape~ipad.png b/code/iphone/Default-Landscape~ipad.png new file mode 100644 index 0000000..a298062 Binary files /dev/null and b/code/iphone/Default-Landscape~ipad.png differ diff --git a/code/iphone/Default-Portrait~ipad.png b/code/iphone/Default-Portrait~ipad.png new file mode 100644 index 0000000..f5da61e Binary files /dev/null and b/code/iphone/Default-Portrait~ipad.png differ diff --git a/code/iphone/Default@2x.png b/code/iphone/Default@2x.png new file mode 100644 index 0000000..879be24 Binary files /dev/null and b/code/iphone/Default@2x.png differ diff --git a/code/iphone/Default~ipad.png b/code/iphone/Default~ipad.png new file mode 100644 index 0000000..324a53a Binary files /dev/null and b/code/iphone/Default~ipad.png differ diff --git a/code/iphone/Doom.xcodeproj/project.pbxproj b/code/iphone/Doom.xcodeproj/project.pbxproj deleted file mode 100644 index afd5e90..0000000 --- a/code/iphone/Doom.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1430 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 45; - objects = { - -/* Begin PBXBuildFile section */ - 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; - 4333CCE80F5CC23E00AE2B6F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */; }; - 434669A60F8D08C000EA7D6D /* doomAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 434669A50F8D08C000EA7D6D /* doomAppDelegate.m */; }; - 4364BF3F0F5CB25900F29317 /* dist.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4364BF3E0F5CB25900F29317 /* dist.plist */; }; - 43A945150F82D75900FFD32E /* iphone_sys.c in Sources */ = {isa = PBXBuildFile; fileRef = 43A945140F82D75900FFD32E /* iphone_sys.c */; }; - 43CF02FF0F56974E00E4A23D /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 43CF02FE0F56974E00E4A23D /* Default.png */; }; - 43CF030A0F56D5C200E4A23D /* iphone_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 43CF03090F56D5C200E4A23D /* iphone_loop.c */; }; - 43DD8392100295F70006E1DD /* iphone_async.c in Sources */ = {isa = PBXBuildFile; fileRef = 43DD8391100295F70006E1DD /* iphone_async.c */; }; - 43E8D2E10F4FC61E003F09B2 /* iphone_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */; }; - 43E8D4E00F51B48B003F09B2 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */; }; - 720EBBAE0F82E0BB003F989A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */; }; - 7229CE4A0F6C89F8004123C5 /* EAGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE460F6C89F8004123C5 /* EAGLView.m */; }; - 7229CE550F6C8CDE004123C5 /* gles_glue.c in Sources */ = {isa = PBXBuildFile; fileRef = 7229CE540F6C8CDE004123C5 /* gles_glue.c */; }; - 7239452C0F9C0E7500EADD62 /* iphone_mapSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */; }; - 72484E5E0FB0E99900124E1C /* iphone_render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72484E5D0FB0E99900124E1C /* iphone_render.c */; }; - 724C531F0FBDBCEE000E4348 /* BackgroundMusic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */; }; - 72A55EEF1003A94300F788A5 /* iphone_start.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A55EEE1003A94300F788A5 /* iphone_start.c */; }; - 72A560E21004FAEE00F788A5 /* iphone_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A560E11004FAEE00F788A5 /* iphone_net.c */; }; - 72A7E8F70F5F2063005B83C0 /* iphone_menus.c in Sources */ = {isa = PBXBuildFile; fileRef = 72A7E8F60F5F2063005B83C0 /* iphone_menus.c */; }; - 72B5FF390F7E5C3D00C8A372 /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 72B5FF380F7E5C3D00C8A372 /* hud.c */; }; - 72D50DBC0F8ED98000BB49E6 /* ipak.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D50DBB0F8ED98000BB49E6 /* ipak.c */; }; - 72E731EB0F97E68100E702CD /* iphone_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E731EA0F97E68100E702CD /* iphone_sound.c */; }; - 72E847650F93C61900AB3C99 /* am_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847640F93C61900AB3C99 /* am_map.c */; }; - 72E847740F93FFDB00AB3C99 /* d_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8476F0F93FFDB00AB3C99 /* d_client.c */; }; - 72E847750F93FFDB00AB3C99 /* d_deh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847700F93FFDB00AB3C99 /* d_deh.c */; }; - 72E847B20F9400D700AB3C99 /* d_items.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477A0F9400D700AB3C99 /* d_items.c */; }; - 72E847B30F9400D700AB3C99 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8477C0F9400D700AB3C99 /* d_main.c */; }; - 72E847B50F9400D700AB3C99 /* doomdef.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847840F9400D700AB3C99 /* doomdef.c */; }; - 72E847B60F9400D700AB3C99 /* doomstat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847860F9400D700AB3C99 /* doomstat.c */; }; - 72E847B70F9400D700AB3C99 /* dstrings.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847890F9400D700AB3C99 /* dstrings.c */; }; - 72E847B80F9400D700AB3C99 /* f_finale.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478B0F9400D700AB3C99 /* f_finale.c */; }; - 72E847B90F9400D700AB3C99 /* f_wipe.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478D0F9400D700AB3C99 /* f_wipe.c */; }; - 72E847BA0F9400D700AB3C99 /* g_game.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8478F0F9400D700AB3C99 /* g_game.c */; }; - 72E847BB0F9400D700AB3C99 /* gl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847920F9400D700AB3C99 /* gl_main.c */; }; - 72E847BC0F9400D700AB3C99 /* gl_texture.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847940F9400D700AB3C99 /* gl_texture.c */; }; - 72E847BD0F9400D700AB3C99 /* hu_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847950F9400D700AB3C99 /* hu_lib.c */; }; - 72E847BE0F9400D700AB3C99 /* hu_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847970F9400D700AB3C99 /* hu_stuff.c */; }; - 72E847BF0F9400D700AB3C99 /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8479F0F9400D700AB3C99 /* info.c */; }; - 72E847C00F9400D700AB3C99 /* lprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A10F9400D700AB3C99 /* lprintf.c */; }; - 72E847C10F9400D700AB3C99 /* m_argv.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A30F9400D700AB3C99 /* m_argv.c */; }; - 72E847C20F9400D700AB3C99 /* m_bbox.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A50F9400D700AB3C99 /* m_bbox.c */; }; - 72E847C30F9400D700AB3C99 /* m_cheat.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847A70F9400D700AB3C99 /* m_cheat.c */; }; - 72E847C40F9400D700AB3C99 /* m_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AA0F9400D700AB3C99 /* m_menu.c */; }; - 72E847C50F9400D700AB3C99 /* m_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AC0F9400D700AB3C99 /* m_misc.c */; }; - 72E847C60F9400D700AB3C99 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847AE0F9400D700AB3C99 /* m_random.c */; }; - 72E848050F941A5900AB3C99 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E00F941A5900AB3C99 /* md5.c */; }; - 72E848070F941A5900AB3C99 /* p_ceilng.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E40F941A5900AB3C99 /* p_ceilng.c */; }; - 72E848080F941A5900AB3C99 /* p_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E50F941A5900AB3C99 /* p_checksum.c */; }; - 72E848090F941A5900AB3C99 /* p_doors.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E70F941A5900AB3C99 /* p_doors.c */; }; - 72E8480A0F941A5900AB3C99 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847E80F941A5900AB3C99 /* p_enemy.c */; }; - 72E8480B0F941A5900AB3C99 /* p_floor.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EA0F941A5900AB3C99 /* p_floor.c */; }; - 72E8480C0F941A5900AB3C99 /* p_genlin.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EB0F941A5900AB3C99 /* p_genlin.c */; }; - 72E8480D0F941A5900AB3C99 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EC0F941A5900AB3C99 /* p_inter.c */; }; - 72E8480E0F941A5900AB3C99 /* p_lights.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EE0F941A5900AB3C99 /* p_lights.c */; }; - 72E8480F0F941A5900AB3C99 /* p_map.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847EF0F941A5900AB3C99 /* p_map.c */; }; - 72E848100F941A5900AB3C99 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F10F941A5900AB3C99 /* p_maputl.c */; }; - 72E848110F941A5900AB3C99 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F30F941A5900AB3C99 /* p_mobj.c */; }; - 72E848120F941A5900AB3C99 /* p_plats.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F50F941A5900AB3C99 /* p_plats.c */; }; - 72E848130F941A5900AB3C99 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F60F941A5900AB3C99 /* p_pspr.c */; }; - 72E848140F941A5900AB3C99 /* p_saveg.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847F80F941A5900AB3C99 /* p_saveg.c */; }; - 72E848150F941A5900AB3C99 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FA0F941A5900AB3C99 /* p_setup.c */; }; - 72E848160F941A5900AB3C99 /* p_sight.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FC0F941A5900AB3C99 /* p_sight.c */; }; - 72E848170F941A5900AB3C99 /* p_spec.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FD0F941A5900AB3C99 /* p_spec.c */; }; - 72E848180F941A5900AB3C99 /* p_switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E847FF0F941A5900AB3C99 /* p_switch.c */; }; - 72E848190F941A5900AB3C99 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848000F941A5900AB3C99 /* p_telept.c */; }; - 72E8481A0F941A5900AB3C99 /* p_tick.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848010F941A5900AB3C99 /* p_tick.c */; }; - 72E8481B0F941A5900AB3C99 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848030F941A5900AB3C99 /* p_user.c */; }; - 72E848260F941A8300AB3C99 /* r_bsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481D0F941A8300AB3C99 /* r_bsp.c */; }; - 72E848270F941A8300AB3C99 /* r_data.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8481F0F941A8300AB3C99 /* r_data.c */; }; - 72E848280F941A8300AB3C99 /* r_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848220F941A8300AB3C99 /* r_demo.c */; }; - 72E848290F941A8300AB3C99 /* r_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848240F941A8300AB3C99 /* r_draw.c */; }; - 72E8483D0F941AAC00AB3C99 /* r_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482A0F941AAC00AB3C99 /* r_filter.c */; }; - 72E8483E0F941AAC00AB3C99 /* r_fps.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482C0F941AAC00AB3C99 /* r_fps.c */; }; - 72E8483F0F941AAC00AB3C99 /* r_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8482E0F941AAC00AB3C99 /* r_main.c */; }; - 72E848400F941AAC00AB3C99 /* r_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848300F941AAC00AB3C99 /* r_patch.c */; }; - 72E848410F941AAC00AB3C99 /* r_plane.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848320F941AAC00AB3C99 /* r_plane.c */; }; - 72E848420F941AAC00AB3C99 /* r_segs.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848340F941AAC00AB3C99 /* r_segs.c */; }; - 72E848430F941AAC00AB3C99 /* r_sky.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848360F941AAC00AB3C99 /* r_sky.c */; }; - 72E848440F941AAC00AB3C99 /* r_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848390F941AAC00AB3C99 /* r_things.c */; }; - 72E848450F941AAC00AB3C99 /* s_sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8483B0F941AAC00AB3C99 /* s_sound.c */; }; - 72E8485C0F941ADC00AB3C99 /* sounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848460F941ADC00AB3C99 /* sounds.c */; }; - 72E8485D0F941ADC00AB3C99 /* st_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848480F941ADC00AB3C99 /* st_lib.c */; }; - 72E8485E0F941ADC00AB3C99 /* st_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484A0F941ADC00AB3C99 /* st_stuff.c */; }; - 72E8485F0F941ADC00AB3C99 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484C0F941ADC00AB3C99 /* tables.c */; }; - 72E848600F941ADC00AB3C99 /* v_video.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8484E0F941ADC00AB3C99 /* v_video.c */; }; - 72E848610F941ADC00AB3C99 /* version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848500F941ADC00AB3C99 /* version.c */; }; - 72E848630F941ADC00AB3C99 /* w_mmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848530F941ADC00AB3C99 /* w_mmap.c */; }; - 72E848640F941ADC00AB3C99 /* w_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848540F941ADC00AB3C99 /* w_wad.c */; }; - 72E848650F941ADC00AB3C99 /* wi_stuff.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848560F941ADC00AB3C99 /* wi_stuff.c */; }; - 72E848660F941ADC00AB3C99 /* z_bmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E848580F941ADC00AB3C99 /* z_bmalloc.c */; }; - 72E848670F941ADC00AB3C99 /* z_zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8485A0F941ADC00AB3C99 /* z_zone.c */; }; - 72E849600F942B9300AB3C99 /* cvar.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495C0F942B9300AB3C99 /* cvar.c */; }; - 72E849610F942B9300AB3C99 /* misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E8495E0F942B9300AB3C99 /* misc.c */; }; - 72E849F60F94ED1100AB3C99 /* prboomInterface.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E849F50F94ED1100AB3C99 /* prboomInterface.c */; }; - 72E84A290F9503F100AB3C99 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E84A280F9503F100AB3C99 /* cmd.c */; }; - 72F1F9B40F96C18800AD49AC /* dict.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99D0F96C18800AD49AC /* dict.c */; }; - 72F1F9B50F96C18800AD49AC /* geom.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F99F0F96C18800AD49AC /* geom.c */; }; - 72F1F9B60F96C18800AD49AC /* memalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A10F96C18800AD49AC /* memalloc.c */; }; - 72F1F9B70F96C18800AD49AC /* mesh.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A30F96C18800AD49AC /* mesh.c */; }; - 72F1F9B80F96C18800AD49AC /* normal.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9A50F96C18800AD49AC /* normal.c */; }; - 72F1F9BA0F96C18800AD49AC /* priorityq.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AA0F96C18800AD49AC /* priorityq.c */; }; - 72F1F9BB0F96C18800AD49AC /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AC0F96C18800AD49AC /* render.c */; }; - 72F1F9BC0F96C18800AD49AC /* sweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9AE0F96C18800AD49AC /* sweep.c */; }; - 72F1F9BD0F96C18800AD49AC /* tess.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B00F96C18800AD49AC /* tess.c */; }; - 72F1F9BE0F96C18800AD49AC /* tessmono.c in Sources */ = {isa = PBXBuildFile; fileRef = 72F1F9B20F96C18800AD49AC /* tessmono.c */; }; - C8139A7913F9E0440094C2C0 /* UICustomSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = C8139A7813F9E0440094C2C0 /* UICustomSlider.m */; }; - C8139AB313FADA800094C2C0 /* SliderSkull@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */; }; - C8139AB513FADA9D0094C2C0 /* SliderSkull~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */; }; - C81E0C7213DF471000B1049A /* UIFontButton.m in Sources */ = {isa = PBXBuildFile; fileRef = C81E0C7113DF471000B1049A /* UIFontButton.m */; }; - C81E0C8F13DF4A1B00B1049A /* UIFontLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = C81E0C8E13DF4A1B00B1049A /* UIFontLabel.m */; }; - C81E0E5E13E076E400B1049A /* idGinzaNar-Md2.otf in Resources */ = {isa = PBXBuildFile; fileRef = C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */; }; - C81E104C13E1CCA000B1049A /* BackButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104013E1CCA000B1049A /* BackButton.png */; }; - C81E104D13E1CCA000B1049A /* Button.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104113E1CCA000B1049A /* Button.png */; }; - C81E104E13E1CCA000B1049A /* DOOM_sigil_decal.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */; }; - C81E104F13E1CCA000B1049A /* DoomLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104313E1CCA000B1049A /* DoomLogo.png */; }; - C81E105013E1CCA000B1049A /* Easy.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104413E1CCA000B1049A /* Easy.png */; }; - C81E105113E1CCA000B1049A /* Hard.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104513E1CCA000B1049A /* Hard.png */; }; - C81E105213E1CCA000B1049A /* MapOverlay.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104613E1CCA000B1049A /* MapOverlay.png */; }; - C81E105313E1CCA000B1049A /* Medium.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104713E1CCA000B1049A /* Medium.png */; }; - C81E105413E1CCA000B1049A /* MenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104813E1CCA000B1049A /* MenuBackground.png */; }; - C81E105513E1CCA000B1049A /* Nightmare.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104913E1CCA000B1049A /* Nightmare.png */; }; - C81E105613E1CCA000B1049A /* ResumeButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104A13E1CCA000B1049A /* ResumeButton.png */; }; - C81E105713E1CCA000B1049A /* SelectedBracket.png in Resources */ = {isa = PBXBuildFile; fileRef = C81E104B13E1CCA000B1049A /* SelectedBracket.png */; }; - C84F829213D76E96006D01AB /* MapMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = C84F829013D76E96006D01AB /* MapMenuView.m */; }; - C84F83F613D7A99C006D01AB /* GenericMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = C84F83F513D7A99C006D01AB /* GenericMenuView.m */; }; - C84F855913D8B55C006D01AB /* SettingsMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = C84F855813D8B55C006D01AB /* SettingsMenuView.m */; }; - C861F27213BD2DC600DB34A8 /* MainWindow-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = C861F27113BD2DC600DB34A8 /* MainWindow-iPad.xib */; }; - C86F966813D617740069B7B6 /* MenuViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = C86F966713D617740069B7B6 /* MenuViewController.mm */; }; - C86F975E13D6377B0069B7B6 /* IBGlue.m in Sources */ = {isa = PBXBuildFile; fileRef = C86F975D13D6377B0069B7B6 /* IBGlue.m */; }; - C8792ED813F5AFE5003D834F /* BackButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */; }; - C8792ED913F5AFE6003D834F /* Button_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED213F5AFE5003D834F /* Button_Highlighted.png */; }; - C8792EDA13F5AFE6003D834F /* NextButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */; }; - C8792EDB13F5AFE6003D834F /* NextButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED413F5AFE5003D834F /* NextButton.png */; }; - C8792EDC13F5AFE6003D834F /* SubMenuBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED513F5AFE5003D834F /* SubMenuBackground.png */; }; - C8792EDD13F5AFE6003D834F /* SubMenuButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */; }; - C8792EDE13F5AFE6003D834F /* SubMenuButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C8792ED713F5AFE5003D834F /* SubMenuButton.png */; }; - C879308F13F5D8AA003D834F /* DifficultyBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308513F5D8AA003D834F /* DifficultyBackground.png */; }; - C879309013F5D8AA003D834F /* DownArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */; }; - C879309113F5D8AA003D834F /* DownArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308713F5D8AA003D834F /* DownArrow.png */; }; - C879309213F5D8AA003D834F /* Episode1Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308813F5D8AA003D834F /* Episode1Background.png */; }; - C879309313F5D8AA003D834F /* Episode2Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308913F5D8AA003D834F /* Episode2Background.png */; }; - C879309413F5D8AA003D834F /* Episode3Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308A13F5D8AA003D834F /* Episode3Background.png */; }; - C879309513F5D8AA003D834F /* Episode4Background.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308B13F5D8AA003D834F /* Episode4Background.png */; }; - C879309613F5D8AA003D834F /* MissonBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308C13F5D8AA003D834F /* MissonBackground.png */; }; - C879309713F5D8AA003D834F /* UpArrow_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */; }; - C879309813F5D8AA003D834F /* UpArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = C879308E13F5D8AA003D834F /* UpArrow.png */; }; - C87930E513F5EC1B003D834F /* Episode1Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */; }; - C87930E613F5EC1B003D834F /* Episode2Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */; }; - C87930E713F5EC1B003D834F /* Episode3Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */; }; - C87930E813F5EC1B003D834F /* Episode4Background_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */; }; - C87931EC13F610B9003D834F /* AdvancedButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */; }; - C87931ED13F610B9003D834F /* AdvancedButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931DF13F610B9003D834F /* AdvancedButton.png */; }; - C87931EE13F610B9003D834F /* Divide.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E013F610B9003D834F /* Divide.png */; }; - C87931EF13F610B9003D834F /* LayoutDualButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */; }; - C87931F013F610B9003D834F /* LayoutDualButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E213F610B9003D834F /* LayoutDualButton.png */; }; - C87931F113F610B9003D834F /* LayoutSingleButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */; }; - C87931F213F610B9003D834F /* LayoutSingleButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E413F610B9003D834F /* LayoutSingleButton.png */; }; - C87931F313F610B9003D834F /* LayoutWheelButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */; }; - C87931F413F610B9003D834F /* LayoutWheelButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E613F610B9003D834F /* LayoutWheelButton.png */; }; - C87931F513F610B9003D834F /* SettingsButton_Highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */; }; - C87931F613F610B9003D834F /* SettingsButton.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E813F610B9003D834F /* SettingsButton.png */; }; - C87931F713F610B9003D834F /* SliderBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931E913F610B9003D834F /* SliderBackground.png */; }; - C87931F813F610B9003D834F /* SliderBar.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EA13F610B9003D834F /* SliderBar.png */; }; - C87931F913F610B9003D834F /* SliderSkull.png in Resources */ = {isa = PBXBuildFile; fileRef = C87931EB13F610B9003D834F /* SliderSkull.png */; }; - C879320113F6143C003D834F /* UICustomSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = C879320013F6143C003D834F /* UICustomSwitch.m */; }; - C88530C913D8CBEA00A5FBF7 /* MainMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = C88530C813D8CBEA00A5FBF7 /* MainMenuView.m */; }; - C885314413D8D79400A5FBF7 /* ControlsMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = C885314213D8D79400A5FBF7 /* ControlsMenuView.m */; }; - C8D1CF6813DE1EB600F0EAC6 /* DOOM_57.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */; }; - C8D1CF6A13DE1EF500F0EAC6 /* DOOM_114.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */; }; - C8D1CF6C13DE1F0600F0EAC6 /* DOOM_72.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */; }; - C8D1CF8613DF792D00F0EAC6 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */; }; - C8D1CF8813DF79BC00F0EAC6 /* Default~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */; }; - C8D1CFA813E1CDBD00F0EAC6 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */; }; - C8D1CFAA13E1CDC600F0EAC6 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */; }; - ED9AB3D110966E85000B5852 /* iphone_email.m in Sources */ = {isa = PBXBuildFile; fileRef = ED9AB3D010966E85000B5852 /* iphone_email.m */; }; - EDD2760511C2B19E004A9B9B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */; }; - EDD2760711C2B19E004A9B9B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760611C2B19E004A9B9B /* Foundation.framework */; }; - EDD2760911C2B19E004A9B9B /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760811C2B19E004A9B9B /* OpenGLES.framework */; }; - EDD2760B11C2B19E004A9B9B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDD2760A11C2B19E004A9B9B /* UIKit.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 1D6058910D05DD3D006BFB54 /* Doom.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Doom.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; - 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; - 434669A30F8D08C000EA7D6D /* doom_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doom_Prefix.pch; sourceTree = ""; }; - 434669A40F8D08C000EA7D6D /* doomAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomAppDelegate.h; sourceTree = ""; }; - 434669A50F8D08C000EA7D6D /* doomAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = doomAppDelegate.m; sourceTree = ""; }; - 4364BF3E0F5CB25900F29317 /* dist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = dist.plist; sourceTree = ""; }; - 43A945140F82D75900FFD32E /* iphone_sys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_sys.c; sourceTree = ""; }; - 43CF02FE0F56974E00E4A23D /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; - 43CF03090F56D5C200E4A23D /* iphone_loop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_loop.c; sourceTree = ""; }; - 43DD8391100295F70006E1DD /* iphone_async.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_async.c; sourceTree = ""; }; - 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_main.c; sourceTree = ""; }; - 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = /System/Library/Frameworks/OpenAL.framework; sourceTree = ""; }; - 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = ""; }; - 7229CC8E0F6B3363004123C5 /* doomiphone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomiphone.h; path = ../doomiphone.h; sourceTree = SOURCE_ROOT; }; - 7229CE450F6C89F8004123C5 /* EAGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EAGLView.h; sourceTree = ""; }; - 7229CE460F6C89F8004123C5 /* EAGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EAGLView.m; sourceTree = ""; }; - 7229CE540F6C8CDE004123C5 /* gles_glue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gles_glue.c; sourceTree = ""; }; - 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_mapSelect.c; sourceTree = ""; }; - 72484E5D0FB0E99900124E1C /* iphone_render.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_render.c; sourceTree = ""; }; - 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackgroundMusic.cpp; sourceTree = ""; }; - 727886A20FBDBA740020D469 /* gles_glue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gles_glue.h; sourceTree = ""; }; - 72A55EEE1003A94300F788A5 /* iphone_start.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_start.c; sourceTree = ""; }; - 72A560E11004FAEE00F788A5 /* iphone_net.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_net.c; sourceTree = ""; }; - 72A7E8F30F5F2001005B83C0 /* iphone_doom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_doom.h; sourceTree = ""; }; - 72A7E8F60F5F2063005B83C0 /* iphone_menus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_menus.c; sourceTree = ""; }; - 72B5FF380F7E5C3D00C8A372 /* hud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hud.c; sourceTree = ""; }; - 72D50DBA0F8ED98000BB49E6 /* ipak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipak.h; sourceTree = ""; }; - 72D50DBB0F8ED98000BB49E6 /* ipak.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ipak.c; sourceTree = ""; }; - 72E731EA0F97E68100E702CD /* iphone_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iphone_sound.c; sourceTree = ""; }; - 72E847640F93C61900AB3C99 /* am_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = am_map.c; path = ../prboom/am_map.c; sourceTree = SOURCE_ROOT; }; - 72E847680F93FF2F00AB3C99 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../prboom/config.h; sourceTree = SOURCE_ROOT; }; - 72E8476E0F93FFDB00AB3C99 /* am_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = am_map.h; path = ../prboom/am_map.h; sourceTree = SOURCE_ROOT; }; - 72E8476F0F93FFDB00AB3C99 /* d_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = d_client.c; path = ../prboom/d_client.c; sourceTree = SOURCE_ROOT; }; - 72E847700F93FFDB00AB3C99 /* d_deh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = d_deh.c; path = ../prboom/d_deh.c; sourceTree = SOURCE_ROOT; }; - 72E847710F93FFDB00AB3C99 /* d_deh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_deh.h; path = ../prboom/d_deh.h; sourceTree = SOURCE_ROOT; }; - 72E847720F93FFDB00AB3C99 /* d_englsh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_englsh.h; path = ../prboom/d_englsh.h; sourceTree = SOURCE_ROOT; }; - 72E847730F93FFDB00AB3C99 /* d_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_event.h; path = ../prboom/d_event.h; sourceTree = SOURCE_ROOT; }; - 72E8477A0F9400D700AB3C99 /* d_items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = d_items.c; path = ../prboom/d_items.c; sourceTree = SOURCE_ROOT; }; - 72E8477B0F9400D700AB3C99 /* d_items.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_items.h; path = ../prboom/d_items.h; sourceTree = SOURCE_ROOT; }; - 72E8477C0F9400D700AB3C99 /* d_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = d_main.c; path = ../prboom/d_main.c; sourceTree = SOURCE_ROOT; }; - 72E8477D0F9400D700AB3C99 /* d_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_main.h; path = ../prboom/d_main.h; sourceTree = SOURCE_ROOT; }; - 72E8477E0F9400D700AB3C99 /* d_net.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_net.h; path = ../prboom/d_net.h; sourceTree = SOURCE_ROOT; }; - 72E8477F0F9400D700AB3C99 /* d_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_player.h; path = ../prboom/d_player.h; sourceTree = SOURCE_ROOT; }; - 72E847810F9400D700AB3C99 /* d_think.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_think.h; path = ../prboom/d_think.h; sourceTree = SOURCE_ROOT; }; - 72E847820F9400D700AB3C99 /* d_ticcmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = d_ticcmd.h; path = ../prboom/d_ticcmd.h; sourceTree = SOURCE_ROOT; }; - 72E847830F9400D700AB3C99 /* doomdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomdata.h; path = ../prboom/doomdata.h; sourceTree = SOURCE_ROOT; }; - 72E847840F9400D700AB3C99 /* doomdef.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = doomdef.c; path = ../prboom/doomdef.c; sourceTree = SOURCE_ROOT; }; - 72E847850F9400D700AB3C99 /* doomdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomdef.h; path = ../prboom/doomdef.h; sourceTree = SOURCE_ROOT; }; - 72E847860F9400D700AB3C99 /* doomstat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = doomstat.c; path = ../prboom/doomstat.c; sourceTree = SOURCE_ROOT; }; - 72E847870F9400D700AB3C99 /* doomstat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomstat.h; path = ../prboom/doomstat.h; sourceTree = SOURCE_ROOT; }; - 72E847880F9400D700AB3C99 /* doomtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomtype.h; path = ../prboom/doomtype.h; sourceTree = SOURCE_ROOT; }; - 72E847890F9400D700AB3C99 /* dstrings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dstrings.c; path = ../prboom/dstrings.c; sourceTree = SOURCE_ROOT; }; - 72E8478A0F9400D700AB3C99 /* dstrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dstrings.h; path = ../prboom/dstrings.h; sourceTree = SOURCE_ROOT; }; - 72E8478B0F9400D700AB3C99 /* f_finale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = f_finale.c; path = ../prboom/f_finale.c; sourceTree = SOURCE_ROOT; }; - 72E8478C0F9400D700AB3C99 /* f_finale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = f_finale.h; path = ../prboom/f_finale.h; sourceTree = SOURCE_ROOT; }; - 72E8478D0F9400D700AB3C99 /* f_wipe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = f_wipe.c; path = ../prboom/f_wipe.c; sourceTree = SOURCE_ROOT; }; - 72E8478E0F9400D700AB3C99 /* f_wipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = f_wipe.h; path = ../prboom/f_wipe.h; sourceTree = SOURCE_ROOT; }; - 72E8478F0F9400D700AB3C99 /* g_game.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = g_game.c; path = ../prboom/g_game.c; sourceTree = SOURCE_ROOT; }; - 72E847900F9400D700AB3C99 /* g_game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = g_game.h; path = ../prboom/g_game.h; sourceTree = SOURCE_ROOT; }; - 72E847910F9400D700AB3C99 /* gl_intern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gl_intern.h; path = ../prboom/gl_intern.h; sourceTree = SOURCE_ROOT; }; - 72E847920F9400D700AB3C99 /* gl_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = gl_main.c; path = ../prboom/gl_main.c; sourceTree = SOURCE_ROOT; }; - 72E847930F9400D700AB3C99 /* gl_struct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gl_struct.h; path = ../prboom/gl_struct.h; sourceTree = SOURCE_ROOT; }; - 72E847940F9400D700AB3C99 /* gl_texture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = gl_texture.c; path = ../prboom/gl_texture.c; sourceTree = SOURCE_ROOT; }; - 72E847950F9400D700AB3C99 /* hu_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hu_lib.c; path = ../prboom/hu_lib.c; sourceTree = SOURCE_ROOT; }; - 72E847960F9400D700AB3C99 /* hu_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hu_lib.h; path = ../prboom/hu_lib.h; sourceTree = SOURCE_ROOT; }; - 72E847970F9400D700AB3C99 /* hu_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hu_stuff.c; path = ../prboom/hu_stuff.c; sourceTree = SOURCE_ROOT; }; - 72E847980F9400D700AB3C99 /* hu_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hu_stuff.h; path = ../prboom/hu_stuff.h; sourceTree = SOURCE_ROOT; }; - 72E847990F9400D700AB3C99 /* i_joy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_joy.h; path = ../prboom/i_joy.h; sourceTree = SOURCE_ROOT; }; - 72E8479A0F9400D700AB3C99 /* i_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_main.h; path = ../prboom/i_main.h; sourceTree = SOURCE_ROOT; }; - 72E8479B0F9400D700AB3C99 /* i_network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_network.h; path = ../prboom/i_network.h; sourceTree = SOURCE_ROOT; }; - 72E8479C0F9400D700AB3C99 /* i_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_sound.h; path = ../prboom/i_sound.h; sourceTree = SOURCE_ROOT; }; - 72E8479D0F9400D700AB3C99 /* i_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_system.h; path = ../prboom/i_system.h; sourceTree = SOURCE_ROOT; }; - 72E8479E0F9400D700AB3C99 /* i_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = i_video.h; path = ../prboom/i_video.h; sourceTree = SOURCE_ROOT; }; - 72E8479F0F9400D700AB3C99 /* info.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = info.c; path = ../prboom/info.c; sourceTree = SOURCE_ROOT; }; - 72E847A00F9400D700AB3C99 /* info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = info.h; path = ../prboom/info.h; sourceTree = SOURCE_ROOT; }; - 72E847A10F9400D700AB3C99 /* lprintf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lprintf.c; path = ../prboom/lprintf.c; sourceTree = SOURCE_ROOT; }; - 72E847A20F9400D700AB3C99 /* lprintf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lprintf.h; path = ../prboom/lprintf.h; sourceTree = SOURCE_ROOT; }; - 72E847A30F9400D700AB3C99 /* m_argv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_argv.c; path = ../prboom/m_argv.c; sourceTree = SOURCE_ROOT; }; - 72E847A40F9400D700AB3C99 /* m_argv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_argv.h; path = ../prboom/m_argv.h; sourceTree = SOURCE_ROOT; }; - 72E847A50F9400D700AB3C99 /* m_bbox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_bbox.c; path = ../prboom/m_bbox.c; sourceTree = SOURCE_ROOT; }; - 72E847A60F9400D700AB3C99 /* m_bbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_bbox.h; path = ../prboom/m_bbox.h; sourceTree = SOURCE_ROOT; }; - 72E847A70F9400D700AB3C99 /* m_cheat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_cheat.c; path = ../prboom/m_cheat.c; sourceTree = SOURCE_ROOT; }; - 72E847A80F9400D700AB3C99 /* m_cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_cheat.h; path = ../prboom/m_cheat.h; sourceTree = SOURCE_ROOT; }; - 72E847A90F9400D700AB3C99 /* m_fixed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_fixed.h; path = ../prboom/m_fixed.h; sourceTree = SOURCE_ROOT; }; - 72E847AA0F9400D700AB3C99 /* m_menu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_menu.c; path = ../prboom/m_menu.c; sourceTree = SOURCE_ROOT; }; - 72E847AB0F9400D700AB3C99 /* m_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_menu.h; path = ../prboom/m_menu.h; sourceTree = SOURCE_ROOT; }; - 72E847AC0F9400D700AB3C99 /* m_misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_misc.c; path = ../prboom/m_misc.c; sourceTree = SOURCE_ROOT; }; - 72E847AD0F9400D700AB3C99 /* m_misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_misc.h; path = ../prboom/m_misc.h; sourceTree = SOURCE_ROOT; }; - 72E847AE0F9400D700AB3C99 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_random.c; path = ../prboom/m_random.c; sourceTree = SOURCE_ROOT; }; - 72E847AF0F9400D700AB3C99 /* m_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_random.h; path = ../prboom/m_random.h; sourceTree = SOURCE_ROOT; }; - 72E847B00F9400D700AB3C99 /* m_swap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = m_swap.h; path = ../prboom/m_swap.h; sourceTree = SOURCE_ROOT; }; - 72E847CA0F94096C00AB3C99 /* SDL_opengl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengl.h; path = ../prboom/SDL_opengl.h; sourceTree = SOURCE_ROOT; }; - 72E847E00F941A5900AB3C99 /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.c; path = ../prboom/md5.c; sourceTree = SOURCE_ROOT; }; - 72E847E10F941A5900AB3C99 /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = md5.h; path = ../prboom/md5.h; sourceTree = SOURCE_ROOT; }; - 72E847E40F941A5900AB3C99 /* p_ceilng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_ceilng.c; path = ../prboom/p_ceilng.c; sourceTree = SOURCE_ROOT; }; - 72E847E50F941A5900AB3C99 /* p_checksum.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_checksum.c; path = ../prboom/p_checksum.c; sourceTree = SOURCE_ROOT; }; - 72E847E60F941A5900AB3C99 /* p_checksum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_checksum.h; path = ../prboom/p_checksum.h; sourceTree = SOURCE_ROOT; }; - 72E847E70F941A5900AB3C99 /* p_doors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_doors.c; path = ../prboom/p_doors.c; sourceTree = SOURCE_ROOT; }; - 72E847E80F941A5900AB3C99 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_enemy.c; path = ../prboom/p_enemy.c; sourceTree = SOURCE_ROOT; }; - 72E847E90F941A5900AB3C99 /* p_enemy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_enemy.h; path = ../prboom/p_enemy.h; sourceTree = SOURCE_ROOT; }; - 72E847EA0F941A5900AB3C99 /* p_floor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_floor.c; path = ../prboom/p_floor.c; sourceTree = SOURCE_ROOT; }; - 72E847EB0F941A5900AB3C99 /* p_genlin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_genlin.c; path = ../prboom/p_genlin.c; sourceTree = SOURCE_ROOT; }; - 72E847EC0F941A5900AB3C99 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_inter.c; path = ../prboom/p_inter.c; sourceTree = SOURCE_ROOT; }; - 72E847ED0F941A5900AB3C99 /* p_inter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_inter.h; path = ../prboom/p_inter.h; sourceTree = SOURCE_ROOT; }; - 72E847EE0F941A5900AB3C99 /* p_lights.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_lights.c; path = ../prboom/p_lights.c; sourceTree = SOURCE_ROOT; }; - 72E847EF0F941A5900AB3C99 /* p_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_map.c; path = ../prboom/p_map.c; sourceTree = SOURCE_ROOT; }; - 72E847F00F941A5900AB3C99 /* p_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_map.h; path = ../prboom/p_map.h; sourceTree = SOURCE_ROOT; }; - 72E847F10F941A5900AB3C99 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_maputl.c; path = ../prboom/p_maputl.c; sourceTree = SOURCE_ROOT; }; - 72E847F20F941A5900AB3C99 /* p_maputl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_maputl.h; path = ../prboom/p_maputl.h; sourceTree = SOURCE_ROOT; }; - 72E847F30F941A5900AB3C99 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_mobj.c; path = ../prboom/p_mobj.c; sourceTree = SOURCE_ROOT; }; - 72E847F40F941A5900AB3C99 /* p_mobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_mobj.h; path = ../prboom/p_mobj.h; sourceTree = SOURCE_ROOT; }; - 72E847F50F941A5900AB3C99 /* p_plats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_plats.c; path = ../prboom/p_plats.c; sourceTree = SOURCE_ROOT; }; - 72E847F60F941A5900AB3C99 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_pspr.c; path = ../prboom/p_pspr.c; sourceTree = SOURCE_ROOT; }; - 72E847F70F941A5900AB3C99 /* p_pspr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_pspr.h; path = ../prboom/p_pspr.h; sourceTree = SOURCE_ROOT; }; - 72E847F80F941A5900AB3C99 /* p_saveg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_saveg.c; path = ../prboom/p_saveg.c; sourceTree = SOURCE_ROOT; }; - 72E847F90F941A5900AB3C99 /* p_saveg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_saveg.h; path = ../prboom/p_saveg.h; sourceTree = SOURCE_ROOT; }; - 72E847FA0F941A5900AB3C99 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_setup.c; path = ../prboom/p_setup.c; sourceTree = SOURCE_ROOT; }; - 72E847FB0F941A5900AB3C99 /* p_setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_setup.h; path = ../prboom/p_setup.h; sourceTree = SOURCE_ROOT; }; - 72E847FC0F941A5900AB3C99 /* p_sight.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_sight.c; path = ../prboom/p_sight.c; sourceTree = SOURCE_ROOT; }; - 72E847FD0F941A5900AB3C99 /* p_spec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_spec.c; path = ../prboom/p_spec.c; sourceTree = SOURCE_ROOT; }; - 72E847FE0F941A5900AB3C99 /* p_spec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_spec.h; path = ../prboom/p_spec.h; sourceTree = SOURCE_ROOT; }; - 72E847FF0F941A5900AB3C99 /* p_switch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_switch.c; path = ../prboom/p_switch.c; sourceTree = SOURCE_ROOT; }; - 72E848000F941A5900AB3C99 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_telept.c; path = ../prboom/p_telept.c; sourceTree = SOURCE_ROOT; }; - 72E848010F941A5900AB3C99 /* p_tick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_tick.c; path = ../prboom/p_tick.c; sourceTree = SOURCE_ROOT; }; - 72E848020F941A5900AB3C99 /* p_tick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_tick.h; path = ../prboom/p_tick.h; sourceTree = SOURCE_ROOT; }; - 72E848030F941A5900AB3C99 /* p_user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_user.c; path = ../prboom/p_user.c; sourceTree = SOURCE_ROOT; }; - 72E848040F941A5900AB3C99 /* p_user.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = p_user.h; path = ../prboom/p_user.h; sourceTree = SOURCE_ROOT; }; - 72E8481C0F941A8300AB3C99 /* protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = protocol.h; path = ../prboom/protocol.h; sourceTree = SOURCE_ROOT; }; - 72E8481D0F941A8300AB3C99 /* r_bsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_bsp.c; path = ../prboom/r_bsp.c; sourceTree = SOURCE_ROOT; }; - 72E8481E0F941A8300AB3C99 /* r_bsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_bsp.h; path = ../prboom/r_bsp.h; sourceTree = SOURCE_ROOT; }; - 72E8481F0F941A8300AB3C99 /* r_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_data.c; path = ../prboom/r_data.c; sourceTree = SOURCE_ROOT; }; - 72E848200F941A8300AB3C99 /* r_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_data.h; path = ../prboom/r_data.h; sourceTree = SOURCE_ROOT; }; - 72E848210F941A8300AB3C99 /* r_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_defs.h; path = ../prboom/r_defs.h; sourceTree = SOURCE_ROOT; }; - 72E848220F941A8300AB3C99 /* r_demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_demo.c; path = ../prboom/r_demo.c; sourceTree = SOURCE_ROOT; }; - 72E848230F941A8300AB3C99 /* r_demo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_demo.h; path = ../prboom/r_demo.h; sourceTree = SOURCE_ROOT; }; - 72E848240F941A8300AB3C99 /* r_draw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_draw.c; path = ../prboom/r_draw.c; sourceTree = SOURCE_ROOT; }; - 72E848250F941A8300AB3C99 /* r_draw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_draw.h; path = ../prboom/r_draw.h; sourceTree = SOURCE_ROOT; }; - 72E8482A0F941AAC00AB3C99 /* r_filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_filter.c; path = ../prboom/r_filter.c; sourceTree = SOURCE_ROOT; }; - 72E8482B0F941AAC00AB3C99 /* r_filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_filter.h; path = ../prboom/r_filter.h; sourceTree = SOURCE_ROOT; }; - 72E8482C0F941AAC00AB3C99 /* r_fps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_fps.c; path = ../prboom/r_fps.c; sourceTree = SOURCE_ROOT; }; - 72E8482D0F941AAC00AB3C99 /* r_fps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_fps.h; path = ../prboom/r_fps.h; sourceTree = SOURCE_ROOT; }; - 72E8482E0F941AAC00AB3C99 /* r_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_main.c; path = ../prboom/r_main.c; sourceTree = SOURCE_ROOT; }; - 72E8482F0F941AAC00AB3C99 /* r_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_main.h; path = ../prboom/r_main.h; sourceTree = SOURCE_ROOT; }; - 72E848300F941AAC00AB3C99 /* r_patch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_patch.c; path = ../prboom/r_patch.c; sourceTree = SOURCE_ROOT; }; - 72E848310F941AAC00AB3C99 /* r_patch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_patch.h; path = ../prboom/r_patch.h; sourceTree = SOURCE_ROOT; }; - 72E848320F941AAC00AB3C99 /* r_plane.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_plane.c; path = ../prboom/r_plane.c; sourceTree = SOURCE_ROOT; }; - 72E848330F941AAC00AB3C99 /* r_plane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_plane.h; path = ../prboom/r_plane.h; sourceTree = SOURCE_ROOT; }; - 72E848340F941AAC00AB3C99 /* r_segs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_segs.c; path = ../prboom/r_segs.c; sourceTree = SOURCE_ROOT; }; - 72E848350F941AAC00AB3C99 /* r_segs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_segs.h; path = ../prboom/r_segs.h; sourceTree = SOURCE_ROOT; }; - 72E848360F941AAC00AB3C99 /* r_sky.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_sky.c; path = ../prboom/r_sky.c; sourceTree = SOURCE_ROOT; }; - 72E848370F941AAC00AB3C99 /* r_sky.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_sky.h; path = ../prboom/r_sky.h; sourceTree = SOURCE_ROOT; }; - 72E848380F941AAC00AB3C99 /* r_state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_state.h; path = ../prboom/r_state.h; sourceTree = SOURCE_ROOT; }; - 72E848390F941AAC00AB3C99 /* r_things.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_things.c; path = ../prboom/r_things.c; sourceTree = SOURCE_ROOT; }; - 72E8483A0F941AAC00AB3C99 /* r_things.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = r_things.h; path = ../prboom/r_things.h; sourceTree = SOURCE_ROOT; }; - 72E8483B0F941AAC00AB3C99 /* s_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = s_sound.c; path = ../prboom/s_sound.c; sourceTree = SOURCE_ROOT; }; - 72E8483C0F941AAC00AB3C99 /* s_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = s_sound.h; path = ../prboom/s_sound.h; sourceTree = SOURCE_ROOT; }; - 72E848460F941ADC00AB3C99 /* sounds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sounds.c; path = ../prboom/sounds.c; sourceTree = SOURCE_ROOT; }; - 72E848470F941ADC00AB3C99 /* sounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sounds.h; path = ../prboom/sounds.h; sourceTree = SOURCE_ROOT; }; - 72E848480F941ADC00AB3C99 /* st_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = st_lib.c; path = ../prboom/st_lib.c; sourceTree = SOURCE_ROOT; }; - 72E848490F941ADC00AB3C99 /* st_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = st_lib.h; path = ../prboom/st_lib.h; sourceTree = SOURCE_ROOT; }; - 72E8484A0F941ADC00AB3C99 /* st_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = st_stuff.c; path = ../prboom/st_stuff.c; sourceTree = SOURCE_ROOT; }; - 72E8484B0F941ADC00AB3C99 /* st_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = st_stuff.h; path = ../prboom/st_stuff.h; sourceTree = SOURCE_ROOT; }; - 72E8484C0F941ADC00AB3C99 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tables.c; path = ../prboom/tables.c; sourceTree = SOURCE_ROOT; }; - 72E8484D0F941ADC00AB3C99 /* tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tables.h; path = ../prboom/tables.h; sourceTree = SOURCE_ROOT; }; - 72E8484E0F941ADC00AB3C99 /* v_video.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = v_video.c; path = ../prboom/v_video.c; sourceTree = SOURCE_ROOT; }; - 72E8484F0F941ADC00AB3C99 /* v_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = v_video.h; path = ../prboom/v_video.h; sourceTree = SOURCE_ROOT; }; - 72E848500F941ADC00AB3C99 /* version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = version.c; path = ../prboom/version.c; sourceTree = SOURCE_ROOT; }; - 72E848510F941ADC00AB3C99 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = ../prboom/version.h; sourceTree = SOURCE_ROOT; }; - 72E848530F941ADC00AB3C99 /* w_mmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = w_mmap.c; path = ../prboom/w_mmap.c; sourceTree = SOURCE_ROOT; }; - 72E848540F941ADC00AB3C99 /* w_wad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = w_wad.c; path = ../prboom/w_wad.c; sourceTree = SOURCE_ROOT; }; - 72E848550F941ADC00AB3C99 /* w_wad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = w_wad.h; path = ../prboom/w_wad.h; sourceTree = SOURCE_ROOT; }; - 72E848560F941ADC00AB3C99 /* wi_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wi_stuff.c; path = ../prboom/wi_stuff.c; sourceTree = SOURCE_ROOT; }; - 72E848570F941ADC00AB3C99 /* wi_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wi_stuff.h; path = ../prboom/wi_stuff.h; sourceTree = SOURCE_ROOT; }; - 72E848580F941ADC00AB3C99 /* z_bmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = z_bmalloc.c; path = ../prboom/z_bmalloc.c; sourceTree = SOURCE_ROOT; }; - 72E848590F941ADC00AB3C99 /* z_bmalloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = z_bmalloc.h; path = ../prboom/z_bmalloc.h; sourceTree = SOURCE_ROOT; }; - 72E8485A0F941ADC00AB3C99 /* z_zone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = z_zone.c; path = ../prboom/z_zone.c; sourceTree = SOURCE_ROOT; }; - 72E8485B0F941ADC00AB3C99 /* z_zone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = z_zone.h; path = ../prboom/z_zone.h; sourceTree = SOURCE_ROOT; }; - 72E8495C0F942B9300AB3C99 /* cvar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cvar.c; sourceTree = ""; }; - 72E8495D0F942B9300AB3C99 /* cvar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cvar.h; sourceTree = ""; }; - 72E8495E0F942B9300AB3C99 /* misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = misc.c; sourceTree = ""; }; - 72E8495F0F942B9300AB3C99 /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = ""; }; - 72E849F50F94ED1100AB3C99 /* prboomInterface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prboomInterface.c; sourceTree = ""; }; - 72E84A280F9503F100AB3C99 /* cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmd.c; sourceTree = ""; }; - 72F1F99C0F96C18800AD49AC /* dict-list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "dict-list.h"; path = "../libtess/dict-list.h"; sourceTree = SOURCE_ROOT; }; - 72F1F99D0F96C18800AD49AC /* dict.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dict.c; path = ../libtess/dict.c; sourceTree = SOURCE_ROOT; }; - 72F1F99E0F96C18800AD49AC /* dict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dict.h; path = ../libtess/dict.h; sourceTree = SOURCE_ROOT; }; - 72F1F99F0F96C18800AD49AC /* geom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = geom.c; path = ../libtess/geom.c; sourceTree = SOURCE_ROOT; }; - 72F1F9A00F96C18800AD49AC /* geom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = geom.h; path = ../libtess/geom.h; sourceTree = SOURCE_ROOT; }; - 72F1F9A10F96C18800AD49AC /* memalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = memalloc.c; path = ../libtess/memalloc.c; sourceTree = SOURCE_ROOT; }; - 72F1F9A20F96C18800AD49AC /* memalloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memalloc.h; path = ../libtess/memalloc.h; sourceTree = SOURCE_ROOT; }; - 72F1F9A30F96C18800AD49AC /* mesh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mesh.c; path = ../libtess/mesh.c; sourceTree = SOURCE_ROOT; }; - 72F1F9A40F96C18800AD49AC /* mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mesh.h; path = ../libtess/mesh.h; sourceTree = SOURCE_ROOT; }; - 72F1F9A50F96C18800AD49AC /* normal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = normal.c; path = ../libtess/normal.c; sourceTree = SOURCE_ROOT; }; - 72F1F9A60F96C18800AD49AC /* normal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = normal.h; path = ../libtess/normal.h; sourceTree = SOURCE_ROOT; }; - 72F1F9A80F96C18800AD49AC /* priorityq-heap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "priorityq-heap.h"; path = "../libtess/priorityq-heap.h"; sourceTree = SOURCE_ROOT; }; - 72F1F9A90F96C18800AD49AC /* priorityq-sort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "priorityq-sort.h"; path = "../libtess/priorityq-sort.h"; sourceTree = SOURCE_ROOT; }; - 72F1F9AA0F96C18800AD49AC /* priorityq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = priorityq.c; path = ../libtess/priorityq.c; sourceTree = SOURCE_ROOT; }; - 72F1F9AB0F96C18800AD49AC /* priorityq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = priorityq.h; path = ../libtess/priorityq.h; sourceTree = SOURCE_ROOT; }; - 72F1F9AC0F96C18800AD49AC /* render.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = render.c; path = ../libtess/render.c; sourceTree = SOURCE_ROOT; }; - 72F1F9AD0F96C18800AD49AC /* render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = render.h; path = ../libtess/render.h; sourceTree = SOURCE_ROOT; }; - 72F1F9AE0F96C18800AD49AC /* sweep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sweep.c; path = ../libtess/sweep.c; sourceTree = SOURCE_ROOT; }; - 72F1F9AF0F96C18800AD49AC /* sweep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sweep.h; path = ../libtess/sweep.h; sourceTree = SOURCE_ROOT; }; - 72F1F9B00F96C18800AD49AC /* tess.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tess.c; path = ../libtess/tess.c; sourceTree = SOURCE_ROOT; }; - 72F1F9B10F96C18800AD49AC /* tess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tess.h; path = ../libtess/tess.h; sourceTree = SOURCE_ROOT; }; - 72F1F9B20F96C18800AD49AC /* tessmono.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tessmono.c; path = ../libtess/tessmono.c; sourceTree = SOURCE_ROOT; }; - 72F1F9B30F96C18800AD49AC /* tessmono.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tessmono.h; path = ../libtess/tessmono.h; sourceTree = SOURCE_ROOT; }; - 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C8139A7713F9E0440094C2C0 /* UICustomSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UICustomSlider.h; sourceTree = ""; }; - C8139A7813F9E0440094C2C0 /* UICustomSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UICustomSlider.m; sourceTree = ""; }; - C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "SliderSkull@2x.png"; path = "../../IB Images/SliderSkull@2x.png"; sourceTree = SOURCE_ROOT; }; - C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "SliderSkull~ipad.png"; path = "../../IB Images/SliderSkull~ipad.png"; sourceTree = SOURCE_ROOT; }; - C81E0C7013DF471000B1049A /* UIFontButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIFontButton.h; sourceTree = ""; }; - C81E0C7113DF471000B1049A /* UIFontButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIFontButton.m; sourceTree = ""; }; - C81E0C8D13DF4A1B00B1049A /* UIFontLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIFontLabel.h; sourceTree = ""; }; - C81E0C8E13DF4A1B00B1049A /* UIFontLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIFontLabel.m; sourceTree = ""; }; - C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "idGinzaNar-Md2.otf"; path = "../../idGinzaNar-Md2.otf"; sourceTree = SOURCE_ROOT; }; - C81E104013E1CCA000B1049A /* BackButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = BackButton.png; path = "../../IB Images/BackButton.png"; sourceTree = SOURCE_ROOT; }; - C81E104113E1CCA000B1049A /* Button.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Button.png; path = "../../IB Images/Button.png"; sourceTree = SOURCE_ROOT; }; - C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DOOM_sigil_decal.png; path = "../../IB Images/DOOM_sigil_decal.png"; sourceTree = SOURCE_ROOT; }; - C81E104313E1CCA000B1049A /* DoomLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DoomLogo.png; path = "../../IB Images/DoomLogo.png"; sourceTree = SOURCE_ROOT; }; - C81E104413E1CCA000B1049A /* Easy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Easy.png; path = "../../IB Images/Easy.png"; sourceTree = SOURCE_ROOT; }; - C81E104513E1CCA000B1049A /* Hard.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Hard.png; path = "../../IB Images/Hard.png"; sourceTree = SOURCE_ROOT; }; - C81E104613E1CCA000B1049A /* MapOverlay.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = MapOverlay.png; path = "../../IB Images/MapOverlay.png"; sourceTree = SOURCE_ROOT; }; - C81E104713E1CCA000B1049A /* Medium.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Medium.png; path = "../../IB Images/Medium.png"; sourceTree = SOURCE_ROOT; }; - C81E104813E1CCA000B1049A /* MenuBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = MenuBackground.png; path = "../../IB Images/MenuBackground.png"; sourceTree = SOURCE_ROOT; }; - C81E104913E1CCA000B1049A /* Nightmare.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Nightmare.png; path = "../../IB Images/Nightmare.png"; sourceTree = SOURCE_ROOT; }; - C81E104A13E1CCA000B1049A /* ResumeButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ResumeButton.png; path = "../../IB Images/ResumeButton.png"; sourceTree = SOURCE_ROOT; }; - C81E104B13E1CCA000B1049A /* SelectedBracket.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SelectedBracket.png; path = "../../IB Images/SelectedBracket.png"; sourceTree = SOURCE_ROOT; }; - C84F829013D76E96006D01AB /* MapMenuView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MapMenuView.m; sourceTree = ""; }; - C84F829113D76E96006D01AB /* MapMenuView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapMenuView.h; sourceTree = ""; }; - C84F83F413D7A99C006D01AB /* GenericMenuView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericMenuView.h; sourceTree = ""; }; - C84F83F513D7A99C006D01AB /* GenericMenuView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GenericMenuView.m; sourceTree = ""; }; - C84F855713D8B55C006D01AB /* SettingsMenuView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsMenuView.h; sourceTree = ""; }; - C84F855813D8B55C006D01AB /* SettingsMenuView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsMenuView.m; sourceTree = ""; }; - C861F27113BD2DC600DB34A8 /* MainWindow-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "MainWindow-iPad.xib"; path = "Resources-iPad/MainWindow-iPad.xib"; sourceTree = ""; }; - C86F965513D615F70069B7B6 /* MainMenuView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainMenuView.h; sourceTree = ""; }; - C86F966613D617740069B7B6 /* MenuViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenuViewController.h; sourceTree = ""; }; - C86F966713D617740069B7B6 /* MenuViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MenuViewController.mm; sourceTree = ""; }; - C86F975C13D6377B0069B7B6 /* IBGlue.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = IBGlue.h; sourceTree = ""; }; - C86F975D13D6377B0069B7B6 /* IBGlue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IBGlue.m; sourceTree = ""; }; - C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = BackButton_Highlighted.png; path = "../../IB Images/BackButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C8792ED213F5AFE5003D834F /* Button_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Button_Highlighted.png; path = "../../IB Images/Button_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = NextButton_Highlighted.png; path = "../../IB Images/NextButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C8792ED413F5AFE5003D834F /* NextButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = NextButton.png; path = "../../IB Images/NextButton.png"; sourceTree = SOURCE_ROOT; }; - C8792ED513F5AFE5003D834F /* SubMenuBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SubMenuBackground.png; path = "../../IB Images/SubMenuBackground.png"; sourceTree = SOURCE_ROOT; }; - C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SubMenuButton_Highlighted.png; path = "../../IB Images/SubMenuButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C8792ED713F5AFE5003D834F /* SubMenuButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SubMenuButton.png; path = "../../IB Images/SubMenuButton.png"; sourceTree = SOURCE_ROOT; }; - C879308513F5D8AA003D834F /* DifficultyBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DifficultyBackground.png; path = "../../IB Images/DifficultyBackground.png"; sourceTree = SOURCE_ROOT; }; - C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DownArrow_Highlighted.png; path = "../../IB Images/DownArrow_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C879308713F5D8AA003D834F /* DownArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DownArrow.png; path = "../../IB Images/DownArrow.png"; sourceTree = SOURCE_ROOT; }; - C879308813F5D8AA003D834F /* Episode1Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode1Background.png; path = "../../IB Images/Episode1Background.png"; sourceTree = SOURCE_ROOT; }; - C879308913F5D8AA003D834F /* Episode2Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode2Background.png; path = "../../IB Images/Episode2Background.png"; sourceTree = SOURCE_ROOT; }; - C879308A13F5D8AA003D834F /* Episode3Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode3Background.png; path = "../../IB Images/Episode3Background.png"; sourceTree = SOURCE_ROOT; }; - C879308B13F5D8AA003D834F /* Episode4Background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode4Background.png; path = "../../IB Images/Episode4Background.png"; sourceTree = SOURCE_ROOT; }; - C879308C13F5D8AA003D834F /* MissonBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = MissonBackground.png; path = "../../IB Images/MissonBackground.png"; sourceTree = SOURCE_ROOT; }; - C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = UpArrow_Highlighted.png; path = "../../IB Images/UpArrow_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C879308E13F5D8AA003D834F /* UpArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = UpArrow.png; path = "../../IB Images/UpArrow.png"; sourceTree = SOURCE_ROOT; }; - C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode1Background_Highlighted.png; path = "../../IB Images/Episode1Background_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode2Background_Highlighted.png; path = "../../IB Images/Episode2Background_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode3Background_Highlighted.png; path = "../../IB Images/Episode3Background_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Episode4Background_Highlighted.png; path = "../../IB Images/Episode4Background_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = AdvancedButton_Highlighted.png; path = "../../IB Images/AdvancedButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87931DF13F610B9003D834F /* AdvancedButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = AdvancedButton.png; path = "../../IB Images/AdvancedButton.png"; sourceTree = SOURCE_ROOT; }; - C87931E013F610B9003D834F /* Divide.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Divide.png; path = "../../IB Images/Divide.png"; sourceTree = SOURCE_ROOT; }; - C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutDualButton_Highlighted.png; path = "../../IB Images/LayoutDualButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87931E213F610B9003D834F /* LayoutDualButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutDualButton.png; path = "../../IB Images/LayoutDualButton.png"; sourceTree = SOURCE_ROOT; }; - C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutSingleButton_Highlighted.png; path = "../../IB Images/LayoutSingleButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87931E413F610B9003D834F /* LayoutSingleButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutSingleButton.png; path = "../../IB Images/LayoutSingleButton.png"; sourceTree = SOURCE_ROOT; }; - C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutWheelButton_Highlighted.png; path = "../../IB Images/LayoutWheelButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87931E613F610B9003D834F /* LayoutWheelButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = LayoutWheelButton.png; path = "../../IB Images/LayoutWheelButton.png"; sourceTree = SOURCE_ROOT; }; - C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SettingsButton_Highlighted.png; path = "../../IB Images/SettingsButton_Highlighted.png"; sourceTree = SOURCE_ROOT; }; - C87931E813F610B9003D834F /* SettingsButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SettingsButton.png; path = "../../IB Images/SettingsButton.png"; sourceTree = SOURCE_ROOT; }; - C87931E913F610B9003D834F /* SliderBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SliderBackground.png; path = "../../IB Images/SliderBackground.png"; sourceTree = SOURCE_ROOT; }; - C87931EA13F610B9003D834F /* SliderBar.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SliderBar.png; path = "../../IB Images/SliderBar.png"; sourceTree = SOURCE_ROOT; }; - C87931EB13F610B9003D834F /* SliderSkull.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = SliderSkull.png; path = "../../IB Images/SliderSkull.png"; sourceTree = SOURCE_ROOT; }; - C87931FF13F6143C003D834F /* UICustomSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UICustomSwitch.h; sourceTree = ""; }; - C879320013F6143C003D834F /* UICustomSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UICustomSwitch.m; sourceTree = ""; }; - C88530C813D8CBEA00A5FBF7 /* MainMenuView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainMenuView.m; sourceTree = ""; }; - C885314213D8D79400A5FBF7 /* ControlsMenuView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ControlsMenuView.m; sourceTree = ""; }; - C885314313D8D79400A5FBF7 /* ControlsMenuView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlsMenuView.h; sourceTree = ""; }; - C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_57.png; sourceTree = ""; }; - C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_114.png; sourceTree = ""; }; - C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DOOM_72.png; sourceTree = ""; }; - C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; - C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default~ipad.png"; sourceTree = ""; }; - C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait~ipad.png"; sourceTree = ""; }; - C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape~ipad.png"; sourceTree = ""; }; - ED9AB3CF10966E85000B5852 /* iphone_email.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iphone_email.h; sourceTree = ""; }; - ED9AB3D010966E85000B5852 /* iphone_email.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iphone_email.m; sourceTree = ""; }; - EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - EDD2760611C2B19E004A9B9B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - EDD2760811C2B19E004A9B9B /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; - EDD2760A11C2B19E004A9B9B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 43E8D4E00F51B48B003F09B2 /* OpenAL.framework in Frameworks */, - 4333CCE80F5CC23E00AE2B6F /* AudioToolbox.framework in Frameworks */, - 720EBBAE0F82E0BB003F989A /* QuartzCore.framework in Frameworks */, - EDD2760511C2B19E004A9B9B /* CoreGraphics.framework in Frameworks */, - EDD2760711C2B19E004A9B9B /* Foundation.framework in Frameworks */, - EDD2760911C2B19E004A9B9B /* OpenGLES.framework in Frameworks */, - EDD2760B11C2B19E004A9B9B /* UIKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* Doom.app */, - 4364BF3E0F5CB25900F29317 /* dist.plist */, - ); - name = Products; - sourceTree = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - C8D1CFA913E1CDC600F0EAC6 /* Default-Landscape~ipad.png */, - C8D1CFA713E1CDBD00F0EAC6 /* Default-Portrait~ipad.png */, - C8D1CF8713DF79BC00F0EAC6 /* Default~ipad.png */, - C8D1CF8513DF792D00F0EAC6 /* Default@2x.png */, - C8D1CF6B13DE1F0600F0EAC6 /* DOOM_72.png */, - C8D1CF6913DE1EF500F0EAC6 /* DOOM_114.png */, - C8D1CF6713DE1EB600F0EAC6 /* DOOM_57.png */, - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - C86F965213D615BB0069B7B6 /* InterfaceBuilder */, - 72F1F94B0F96B55B00AD49AC /* libtess */, - 72E847620F93C5F900AB3C99 /* prboom */, - 72E8495C0F942B9300AB3C99 /* cvar.c */, - 72E8495D0F942B9300AB3C99 /* cvar.h */, - 72E84A280F9503F100AB3C99 /* cmd.c */, - 72E8495E0F942B9300AB3C99 /* misc.c */, - 72E8495F0F942B9300AB3C99 /* misc.h */, - 434669A30F8D08C000EA7D6D /* doom_Prefix.pch */, - 434669A40F8D08C000EA7D6D /* doomAppDelegate.h */, - 434669A50F8D08C000EA7D6D /* doomAppDelegate.m */, - 29B97316FDCFA39411CA2CEA /* main.m */, - 724C531E0FBDBCEE000E4348 /* BackgroundMusic.cpp */, - 7229CE540F6C8CDE004123C5 /* gles_glue.c */, - 727886A20FBDBA740020D469 /* gles_glue.h */, - 7229CE450F6C89F8004123C5 /* EAGLView.h */, - 7229CE460F6C89F8004123C5 /* EAGLView.m */, - 72B5FF380F7E5C3D00C8A372 /* hud.c */, - 7229CC8E0F6B3363004123C5 /* doomiphone.h */, - 72D50DBA0F8ED98000BB49E6 /* ipak.h */, - 72D50DBB0F8ED98000BB49E6 /* ipak.c */, - 72E849F50F94ED1100AB3C99 /* prboomInterface.c */, - 43A945140F82D75900FFD32E /* iphone_sys.c */, - 72A7E8F60F5F2063005B83C0 /* iphone_menus.c */, - 72A560E11004FAEE00F788A5 /* iphone_net.c */, - 72E731EA0F97E68100E702CD /* iphone_sound.c */, - 7239452B0F9C0E7500EADD62 /* iphone_mapSelect.c */, - 72484E5D0FB0E99900124E1C /* iphone_render.c */, - 43CF03090F56D5C200E4A23D /* iphone_loop.c */, - 72A7E8F30F5F2001005B83C0 /* iphone_doom.h */, - 43E8D2DF0F4FC61E003F09B2 /* iphone_main.c */, - 43DD8391100295F70006E1DD /* iphone_async.c */, - 72A55EEE1003A94300F788A5 /* iphone_start.c */, - ED9AB3CF10966E85000B5852 /* iphone_email.h */, - ED9AB3D010966E85000B5852 /* iphone_email.m */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - C84F820613D73D28006D01AB /* Interface Builder Images */, - C861F27113BD2DC600DB34A8 /* MainWindow-iPad.xib */, - 43CF02FE0F56974E00E4A23D /* Default.png */, - 28AD733E0D9D9553002E5188 /* MainWindow.xib */, - 8D1107310486CEB800E47090 /* Info.plist */, - ); - name = Resources; - sourceTree = ""; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 720EBBAD0F82E0BB003F989A /* QuartzCore.framework */, - 4333CCE70F5CC23E00AE2B6F /* AudioToolbox.framework */, - 43E8D4DF0F51B48B003F09B2 /* OpenAL.framework */, - EDD2760411C2B19E004A9B9B /* CoreGraphics.framework */, - EDD2760611C2B19E004A9B9B /* Foundation.framework */, - EDD2760811C2B19E004A9B9B /* OpenGLES.framework */, - EDD2760A11C2B19E004A9B9B /* UIKit.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 72E847620F93C5F900AB3C99 /* prboom */ = { - isa = PBXGroup; - children = ( - 72E848460F941ADC00AB3C99 /* sounds.c */, - 72E848470F941ADC00AB3C99 /* sounds.h */, - 72E848480F941ADC00AB3C99 /* st_lib.c */, - 72E848490F941ADC00AB3C99 /* st_lib.h */, - 72E8484A0F941ADC00AB3C99 /* st_stuff.c */, - 72E8484B0F941ADC00AB3C99 /* st_stuff.h */, - 72E8484C0F941ADC00AB3C99 /* tables.c */, - 72E8484D0F941ADC00AB3C99 /* tables.h */, - 72E8484E0F941ADC00AB3C99 /* v_video.c */, - 72E8484F0F941ADC00AB3C99 /* v_video.h */, - 72E848500F941ADC00AB3C99 /* version.c */, - 72E848510F941ADC00AB3C99 /* version.h */, - 72E848530F941ADC00AB3C99 /* w_mmap.c */, - 72E848540F941ADC00AB3C99 /* w_wad.c */, - 72E848550F941ADC00AB3C99 /* w_wad.h */, - 72E848560F941ADC00AB3C99 /* wi_stuff.c */, - 72E848570F941ADC00AB3C99 /* wi_stuff.h */, - 72E848580F941ADC00AB3C99 /* z_bmalloc.c */, - 72E848590F941ADC00AB3C99 /* z_bmalloc.h */, - 72E8485A0F941ADC00AB3C99 /* z_zone.c */, - 72E8485B0F941ADC00AB3C99 /* z_zone.h */, - 72E8482A0F941AAC00AB3C99 /* r_filter.c */, - 72E8482B0F941AAC00AB3C99 /* r_filter.h */, - 72E8482C0F941AAC00AB3C99 /* r_fps.c */, - 72E8482D0F941AAC00AB3C99 /* r_fps.h */, - 72E8482E0F941AAC00AB3C99 /* r_main.c */, - 72E8482F0F941AAC00AB3C99 /* r_main.h */, - 72E848300F941AAC00AB3C99 /* r_patch.c */, - 72E848310F941AAC00AB3C99 /* r_patch.h */, - 72E848320F941AAC00AB3C99 /* r_plane.c */, - 72E848330F941AAC00AB3C99 /* r_plane.h */, - 72E848340F941AAC00AB3C99 /* r_segs.c */, - 72E848350F941AAC00AB3C99 /* r_segs.h */, - 72E848360F941AAC00AB3C99 /* r_sky.c */, - 72E848370F941AAC00AB3C99 /* r_sky.h */, - 72E848380F941AAC00AB3C99 /* r_state.h */, - 72E848390F941AAC00AB3C99 /* r_things.c */, - 72E8483A0F941AAC00AB3C99 /* r_things.h */, - 72E8483B0F941AAC00AB3C99 /* s_sound.c */, - 72E8483C0F941AAC00AB3C99 /* s_sound.h */, - 72E8481C0F941A8300AB3C99 /* protocol.h */, - 72E8481D0F941A8300AB3C99 /* r_bsp.c */, - 72E8481E0F941A8300AB3C99 /* r_bsp.h */, - 72E8481F0F941A8300AB3C99 /* r_data.c */, - 72E848200F941A8300AB3C99 /* r_data.h */, - 72E848210F941A8300AB3C99 /* r_defs.h */, - 72E848220F941A8300AB3C99 /* r_demo.c */, - 72E848230F941A8300AB3C99 /* r_demo.h */, - 72E848240F941A8300AB3C99 /* r_draw.c */, - 72E848250F941A8300AB3C99 /* r_draw.h */, - 72E847E00F941A5900AB3C99 /* md5.c */, - 72E847E10F941A5900AB3C99 /* md5.h */, - 72E847E40F941A5900AB3C99 /* p_ceilng.c */, - 72E847E50F941A5900AB3C99 /* p_checksum.c */, - 72E847E60F941A5900AB3C99 /* p_checksum.h */, - 72E847E70F941A5900AB3C99 /* p_doors.c */, - 72E847E80F941A5900AB3C99 /* p_enemy.c */, - 72E847E90F941A5900AB3C99 /* p_enemy.h */, - 72E847EA0F941A5900AB3C99 /* p_floor.c */, - 72E847EB0F941A5900AB3C99 /* p_genlin.c */, - 72E847EC0F941A5900AB3C99 /* p_inter.c */, - 72E847ED0F941A5900AB3C99 /* p_inter.h */, - 72E847EE0F941A5900AB3C99 /* p_lights.c */, - 72E847EF0F941A5900AB3C99 /* p_map.c */, - 72E847F00F941A5900AB3C99 /* p_map.h */, - 72E847F10F941A5900AB3C99 /* p_maputl.c */, - 72E847F20F941A5900AB3C99 /* p_maputl.h */, - 72E847F30F941A5900AB3C99 /* p_mobj.c */, - 72E847F40F941A5900AB3C99 /* p_mobj.h */, - 72E847F50F941A5900AB3C99 /* p_plats.c */, - 72E847F60F941A5900AB3C99 /* p_pspr.c */, - 72E847F70F941A5900AB3C99 /* p_pspr.h */, - 72E847F80F941A5900AB3C99 /* p_saveg.c */, - 72E847F90F941A5900AB3C99 /* p_saveg.h */, - 72E847FA0F941A5900AB3C99 /* p_setup.c */, - 72E847FB0F941A5900AB3C99 /* p_setup.h */, - 72E847FC0F941A5900AB3C99 /* p_sight.c */, - 72E847FD0F941A5900AB3C99 /* p_spec.c */, - 72E847FE0F941A5900AB3C99 /* p_spec.h */, - 72E847FF0F941A5900AB3C99 /* p_switch.c */, - 72E848000F941A5900AB3C99 /* p_telept.c */, - 72E848010F941A5900AB3C99 /* p_tick.c */, - 72E848020F941A5900AB3C99 /* p_tick.h */, - 72E848030F941A5900AB3C99 /* p_user.c */, - 72E848040F941A5900AB3C99 /* p_user.h */, - 72E847CA0F94096C00AB3C99 /* SDL_opengl.h */, - 72E8477A0F9400D700AB3C99 /* d_items.c */, - 72E8477B0F9400D700AB3C99 /* d_items.h */, - 72E8477C0F9400D700AB3C99 /* d_main.c */, - 72E8477D0F9400D700AB3C99 /* d_main.h */, - 72E8477E0F9400D700AB3C99 /* d_net.h */, - 72E8477F0F9400D700AB3C99 /* d_player.h */, - 72E847810F9400D700AB3C99 /* d_think.h */, - 72E847820F9400D700AB3C99 /* d_ticcmd.h */, - 72E847830F9400D700AB3C99 /* doomdata.h */, - 72E847840F9400D700AB3C99 /* doomdef.c */, - 72E847850F9400D700AB3C99 /* doomdef.h */, - 72E847860F9400D700AB3C99 /* doomstat.c */, - 72E847870F9400D700AB3C99 /* doomstat.h */, - 72E847880F9400D700AB3C99 /* doomtype.h */, - 72E847890F9400D700AB3C99 /* dstrings.c */, - 72E8478A0F9400D700AB3C99 /* dstrings.h */, - 72E8478B0F9400D700AB3C99 /* f_finale.c */, - 72E8478C0F9400D700AB3C99 /* f_finale.h */, - 72E8478D0F9400D700AB3C99 /* f_wipe.c */, - 72E8478E0F9400D700AB3C99 /* f_wipe.h */, - 72E8478F0F9400D700AB3C99 /* g_game.c */, - 72E847900F9400D700AB3C99 /* g_game.h */, - 72E847950F9400D700AB3C99 /* hu_lib.c */, - 72E847960F9400D700AB3C99 /* hu_lib.h */, - 72E847970F9400D700AB3C99 /* hu_stuff.c */, - 72E847980F9400D700AB3C99 /* hu_stuff.h */, - 72E847990F9400D700AB3C99 /* i_joy.h */, - 72E8479A0F9400D700AB3C99 /* i_main.h */, - 72E8479B0F9400D700AB3C99 /* i_network.h */, - 72E8479C0F9400D700AB3C99 /* i_sound.h */, - 72E8479D0F9400D700AB3C99 /* i_system.h */, - 72E8479E0F9400D700AB3C99 /* i_video.h */, - 72E8479F0F9400D700AB3C99 /* info.c */, - 72E847A00F9400D700AB3C99 /* info.h */, - 72E847A10F9400D700AB3C99 /* lprintf.c */, - 72E847A20F9400D700AB3C99 /* lprintf.h */, - 72E847A30F9400D700AB3C99 /* m_argv.c */, - 72E847A40F9400D700AB3C99 /* m_argv.h */, - 72E847A50F9400D700AB3C99 /* m_bbox.c */, - 72E847A60F9400D700AB3C99 /* m_bbox.h */, - 72E847A70F9400D700AB3C99 /* m_cheat.c */, - 72E847A80F9400D700AB3C99 /* m_cheat.h */, - 72E847AA0F9400D700AB3C99 /* m_menu.c */, - 72E847A90F9400D700AB3C99 /* m_fixed.h */, - 72E847AB0F9400D700AB3C99 /* m_menu.h */, - 72E847AC0F9400D700AB3C99 /* m_misc.c */, - 72E847AD0F9400D700AB3C99 /* m_misc.h */, - 72E847AE0F9400D700AB3C99 /* m_random.c */, - 72E847AF0F9400D700AB3C99 /* m_random.h */, - 72E847B00F9400D700AB3C99 /* m_swap.h */, - 72E8476E0F93FFDB00AB3C99 /* am_map.h */, - 72E8476F0F93FFDB00AB3C99 /* d_client.c */, - 72E847700F93FFDB00AB3C99 /* d_deh.c */, - 72E847710F93FFDB00AB3C99 /* d_deh.h */, - 72E847720F93FFDB00AB3C99 /* d_englsh.h */, - 72E847730F93FFDB00AB3C99 /* d_event.h */, - 72E847640F93C61900AB3C99 /* am_map.c */, - 72E847680F93FF2F00AB3C99 /* config.h */, - 72E847910F9400D700AB3C99 /* gl_intern.h */, - 72E847930F9400D700AB3C99 /* gl_struct.h */, - 72E847940F9400D700AB3C99 /* gl_texture.c */, - 72E847920F9400D700AB3C99 /* gl_main.c */, - ); - name = prboom; - sourceTree = ""; - }; - 72F1F94B0F96B55B00AD49AC /* libtess */ = { - isa = PBXGroup; - children = ( - 72F1F99C0F96C18800AD49AC /* dict-list.h */, - 72F1F99D0F96C18800AD49AC /* dict.c */, - 72F1F99E0F96C18800AD49AC /* dict.h */, - 72F1F99F0F96C18800AD49AC /* geom.c */, - 72F1F9A00F96C18800AD49AC /* geom.h */, - 72F1F9A10F96C18800AD49AC /* memalloc.c */, - 72F1F9A20F96C18800AD49AC /* memalloc.h */, - 72F1F9A30F96C18800AD49AC /* mesh.c */, - 72F1F9A40F96C18800AD49AC /* mesh.h */, - 72F1F9A50F96C18800AD49AC /* normal.c */, - 72F1F9A60F96C18800AD49AC /* normal.h */, - 72F1F9A80F96C18800AD49AC /* priorityq-heap.h */, - 72F1F9A90F96C18800AD49AC /* priorityq-sort.h */, - 72F1F9AA0F96C18800AD49AC /* priorityq.c */, - 72F1F9AB0F96C18800AD49AC /* priorityq.h */, - 72F1F9AC0F96C18800AD49AC /* render.c */, - 72F1F9AD0F96C18800AD49AC /* render.h */, - 72F1F9AE0F96C18800AD49AC /* sweep.c */, - 72F1F9AF0F96C18800AD49AC /* sweep.h */, - 72F1F9B00F96C18800AD49AC /* tess.c */, - 72F1F9B10F96C18800AD49AC /* tess.h */, - 72F1F9B20F96C18800AD49AC /* tessmono.c */, - 72F1F9B30F96C18800AD49AC /* tessmono.h */, - ); - name = libtess; - sourceTree = ""; - }; - C84F820613D73D28006D01AB /* Interface Builder Images */ = { - isa = PBXGroup; - children = ( - C8139AB413FADA9D0094C2C0 /* SliderSkull~ipad.png */, - C8139AB213FADA800094C2C0 /* SliderSkull@2x.png */, - C87931DE13F610B9003D834F /* AdvancedButton_Highlighted.png */, - C87931DF13F610B9003D834F /* AdvancedButton.png */, - C87931E013F610B9003D834F /* Divide.png */, - C87931E113F610B9003D834F /* LayoutDualButton_Highlighted.png */, - C87931E213F610B9003D834F /* LayoutDualButton.png */, - C87931E313F610B9003D834F /* LayoutSingleButton_Highlighted.png */, - C87931E413F610B9003D834F /* LayoutSingleButton.png */, - C87931E513F610B9003D834F /* LayoutWheelButton_Highlighted.png */, - C87931E613F610B9003D834F /* LayoutWheelButton.png */, - C87931E713F610B9003D834F /* SettingsButton_Highlighted.png */, - C87931E813F610B9003D834F /* SettingsButton.png */, - C87931E913F610B9003D834F /* SliderBackground.png */, - C87931EA13F610B9003D834F /* SliderBar.png */, - C87931EB13F610B9003D834F /* SliderSkull.png */, - C87930E113F5EC1B003D834F /* Episode1Background_Highlighted.png */, - C87930E213F5EC1B003D834F /* Episode2Background_Highlighted.png */, - C87930E313F5EC1B003D834F /* Episode3Background_Highlighted.png */, - C87930E413F5EC1B003D834F /* Episode4Background_Highlighted.png */, - C879308513F5D8AA003D834F /* DifficultyBackground.png */, - C879308613F5D8AA003D834F /* DownArrow_Highlighted.png */, - C879308713F5D8AA003D834F /* DownArrow.png */, - C879308813F5D8AA003D834F /* Episode1Background.png */, - C879308913F5D8AA003D834F /* Episode2Background.png */, - C879308A13F5D8AA003D834F /* Episode3Background.png */, - C879308B13F5D8AA003D834F /* Episode4Background.png */, - C879308C13F5D8AA003D834F /* MissonBackground.png */, - C879308D13F5D8AA003D834F /* UpArrow_Highlighted.png */, - C879308E13F5D8AA003D834F /* UpArrow.png */, - C8792ED113F5AFE5003D834F /* BackButton_Highlighted.png */, - C8792ED213F5AFE5003D834F /* Button_Highlighted.png */, - C8792ED313F5AFE5003D834F /* NextButton_Highlighted.png */, - C8792ED413F5AFE5003D834F /* NextButton.png */, - C8792ED513F5AFE5003D834F /* SubMenuBackground.png */, - C8792ED613F5AFE5003D834F /* SubMenuButton_Highlighted.png */, - C8792ED713F5AFE5003D834F /* SubMenuButton.png */, - C81E104013E1CCA000B1049A /* BackButton.png */, - C81E104113E1CCA000B1049A /* Button.png */, - C81E104213E1CCA000B1049A /* DOOM_sigil_decal.png */, - C81E104313E1CCA000B1049A /* DoomLogo.png */, - C81E104413E1CCA000B1049A /* Easy.png */, - C81E104513E1CCA000B1049A /* Hard.png */, - C81E104613E1CCA000B1049A /* MapOverlay.png */, - C81E104713E1CCA000B1049A /* Medium.png */, - C81E104813E1CCA000B1049A /* MenuBackground.png */, - C81E104913E1CCA000B1049A /* Nightmare.png */, - C81E104A13E1CCA000B1049A /* ResumeButton.png */, - C81E104B13E1CCA000B1049A /* SelectedBracket.png */, - C81E0E5D13E076E400B1049A /* idGinzaNar-Md2.otf */, - ); - name = "Interface Builder Images"; - sourceTree = ""; - }; - C86F965213D615BB0069B7B6 /* InterfaceBuilder */ = { - isa = PBXGroup; - children = ( - C8139A7713F9E0440094C2C0 /* UICustomSlider.h */, - C8139A7813F9E0440094C2C0 /* UICustomSlider.m */, - C84F83F413D7A99C006D01AB /* GenericMenuView.h */, - C84F83F513D7A99C006D01AB /* GenericMenuView.m */, - C84F829013D76E96006D01AB /* MapMenuView.m */, - C84F829113D76E96006D01AB /* MapMenuView.h */, - C84F855713D8B55C006D01AB /* SettingsMenuView.h */, - C84F855813D8B55C006D01AB /* SettingsMenuView.m */, - C885314213D8D79400A5FBF7 /* ControlsMenuView.m */, - C885314313D8D79400A5FBF7 /* ControlsMenuView.h */, - C86F966613D617740069B7B6 /* MenuViewController.h */, - C86F966713D617740069B7B6 /* MenuViewController.mm */, - C86F965513D615F70069B7B6 /* MainMenuView.h */, - C88530C813D8CBEA00A5FBF7 /* MainMenuView.m */, - C86F975C13D6377B0069B7B6 /* IBGlue.h */, - C86F975D13D6377B0069B7B6 /* IBGlue.m */, - C81E0C7013DF471000B1049A /* UIFontButton.h */, - C81E0C7113DF471000B1049A /* UIFontButton.m */, - C81E0C8D13DF4A1B00B1049A /* UIFontLabel.h */, - C81E0C8E13DF4A1B00B1049A /* UIFontLabel.m */, - C87931FF13F6143C003D834F /* UICustomSwitch.h */, - C879320013F6143C003D834F /* UICustomSwitch.m */, - ); - name = InterfaceBuilder; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* Doom */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Doom" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - 435F41A90F532CA300887552 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Doom; - productName = Doom; - productReference = 1D6058910D05DD3D006BFB54 /* Doom.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Doom" */; - compatibilityVersion = "Xcode 3.1"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectRoot = ../..; - targets = ( - 1D6058900D05DD3D006BFB54 /* Doom */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, - 43CF02FF0F56974E00E4A23D /* Default.png in Resources */, - 4364BF3F0F5CB25900F29317 /* dist.plist in Resources */, - C861F27213BD2DC600DB34A8 /* MainWindow-iPad.xib in Resources */, - C8D1CF6813DE1EB600F0EAC6 /* DOOM_57.png in Resources */, - C8D1CF6A13DE1EF500F0EAC6 /* DOOM_114.png in Resources */, - C8D1CF6C13DE1F0600F0EAC6 /* DOOM_72.png in Resources */, - C8D1CF8613DF792D00F0EAC6 /* Default@2x.png in Resources */, - C8D1CF8813DF79BC00F0EAC6 /* Default~ipad.png in Resources */, - C81E0E5E13E076E400B1049A /* idGinzaNar-Md2.otf in Resources */, - C81E104C13E1CCA000B1049A /* BackButton.png in Resources */, - C81E104D13E1CCA000B1049A /* Button.png in Resources */, - C81E104E13E1CCA000B1049A /* DOOM_sigil_decal.png in Resources */, - C81E104F13E1CCA000B1049A /* DoomLogo.png in Resources */, - C81E105013E1CCA000B1049A /* Easy.png in Resources */, - C81E105113E1CCA000B1049A /* Hard.png in Resources */, - C81E105213E1CCA000B1049A /* MapOverlay.png in Resources */, - C81E105313E1CCA000B1049A /* Medium.png in Resources */, - C81E105413E1CCA000B1049A /* MenuBackground.png in Resources */, - C81E105513E1CCA000B1049A /* Nightmare.png in Resources */, - C81E105613E1CCA000B1049A /* ResumeButton.png in Resources */, - C81E105713E1CCA000B1049A /* SelectedBracket.png in Resources */, - C8D1CFA813E1CDBD00F0EAC6 /* Default-Portrait~ipad.png in Resources */, - C8D1CFAA13E1CDC600F0EAC6 /* Default-Landscape~ipad.png in Resources */, - C8792ED813F5AFE5003D834F /* BackButton_Highlighted.png in Resources */, - C8792ED913F5AFE6003D834F /* Button_Highlighted.png in Resources */, - C8792EDA13F5AFE6003D834F /* NextButton_Highlighted.png in Resources */, - C8792EDB13F5AFE6003D834F /* NextButton.png in Resources */, - C8792EDC13F5AFE6003D834F /* SubMenuBackground.png in Resources */, - C8792EDD13F5AFE6003D834F /* SubMenuButton_Highlighted.png in Resources */, - C8792EDE13F5AFE6003D834F /* SubMenuButton.png in Resources */, - C879308F13F5D8AA003D834F /* DifficultyBackground.png in Resources */, - C879309013F5D8AA003D834F /* DownArrow_Highlighted.png in Resources */, - C879309113F5D8AA003D834F /* DownArrow.png in Resources */, - C879309213F5D8AA003D834F /* Episode1Background.png in Resources */, - C879309313F5D8AA003D834F /* Episode2Background.png in Resources */, - C879309413F5D8AA003D834F /* Episode3Background.png in Resources */, - C879309513F5D8AA003D834F /* Episode4Background.png in Resources */, - C879309613F5D8AA003D834F /* MissonBackground.png in Resources */, - C879309713F5D8AA003D834F /* UpArrow_Highlighted.png in Resources */, - C879309813F5D8AA003D834F /* UpArrow.png in Resources */, - C87930E513F5EC1B003D834F /* Episode1Background_Highlighted.png in Resources */, - C87930E613F5EC1B003D834F /* Episode2Background_Highlighted.png in Resources */, - C87930E713F5EC1B003D834F /* Episode3Background_Highlighted.png in Resources */, - C87930E813F5EC1B003D834F /* Episode4Background_Highlighted.png in Resources */, - C87931EC13F610B9003D834F /* AdvancedButton_Highlighted.png in Resources */, - C87931ED13F610B9003D834F /* AdvancedButton.png in Resources */, - C87931EE13F610B9003D834F /* Divide.png in Resources */, - C87931EF13F610B9003D834F /* LayoutDualButton_Highlighted.png in Resources */, - C87931F013F610B9003D834F /* LayoutDualButton.png in Resources */, - C87931F113F610B9003D834F /* LayoutSingleButton_Highlighted.png in Resources */, - C87931F213F610B9003D834F /* LayoutSingleButton.png in Resources */, - C87931F313F610B9003D834F /* LayoutWheelButton_Highlighted.png in Resources */, - C87931F413F610B9003D834F /* LayoutWheelButton.png in Resources */, - C87931F513F610B9003D834F /* SettingsButton_Highlighted.png in Resources */, - C87931F613F610B9003D834F /* SettingsButton.png in Resources */, - C87931F713F610B9003D834F /* SliderBackground.png in Resources */, - C87931F813F610B9003D834F /* SliderBar.png in Resources */, - C87931F913F610B9003D834F /* SliderSkull.png in Resources */, - C8139AB313FADA800094C2C0 /* SliderSkull@2x.png in Resources */, - C8139AB513FADA9D0094C2C0 /* SliderSkull~ipad.png in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 435F41A90F532CA300887552 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = "/bin/sh -x"; - shellScript = "PBXCP=${DEVELOPER_DIR}/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp\n${PBXCP} -exclude .svn \"${PROJECT_DIR}/../../base\" \"${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/\"\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 43E8D2E10F4FC61E003F09B2 /* iphone_main.c in Sources */, - C86F975E13D6377B0069B7B6 /* IBGlue.m in Sources */, - 43CF030A0F56D5C200E4A23D /* iphone_loop.c in Sources */, - 72A7E8F70F5F2063005B83C0 /* iphone_menus.c in Sources */, - 7229CE4A0F6C89F8004123C5 /* EAGLView.m in Sources */, - 7229CE550F6C8CDE004123C5 /* gles_glue.c in Sources */, - 72B5FF390F7E5C3D00C8A372 /* hud.c in Sources */, - 43A945150F82D75900FFD32E /* iphone_sys.c in Sources */, - 434669A60F8D08C000EA7D6D /* doomAppDelegate.m in Sources */, - 72D50DBC0F8ED98000BB49E6 /* ipak.c in Sources */, - 72E847650F93C61900AB3C99 /* am_map.c in Sources */, - 72E847740F93FFDB00AB3C99 /* d_client.c in Sources */, - 72E847750F93FFDB00AB3C99 /* d_deh.c in Sources */, - 72E847B20F9400D700AB3C99 /* d_items.c in Sources */, - 72E847B30F9400D700AB3C99 /* d_main.c in Sources */, - 72E847B50F9400D700AB3C99 /* doomdef.c in Sources */, - 72E847B60F9400D700AB3C99 /* doomstat.c in Sources */, - 72E847B70F9400D700AB3C99 /* dstrings.c in Sources */, - 72E847B80F9400D700AB3C99 /* f_finale.c in Sources */, - 72E847B90F9400D700AB3C99 /* f_wipe.c in Sources */, - 72E847BA0F9400D700AB3C99 /* g_game.c in Sources */, - 72E847BB0F9400D700AB3C99 /* gl_main.c in Sources */, - 72E847BC0F9400D700AB3C99 /* gl_texture.c in Sources */, - 72E847BD0F9400D700AB3C99 /* hu_lib.c in Sources */, - 72E847BE0F9400D700AB3C99 /* hu_stuff.c in Sources */, - 72E847BF0F9400D700AB3C99 /* info.c in Sources */, - 72E847C00F9400D700AB3C99 /* lprintf.c in Sources */, - 72E847C10F9400D700AB3C99 /* m_argv.c in Sources */, - 72E847C20F9400D700AB3C99 /* m_bbox.c in Sources */, - 72E847C30F9400D700AB3C99 /* m_cheat.c in Sources */, - 72E847C40F9400D700AB3C99 /* m_menu.c in Sources */, - 72E847C50F9400D700AB3C99 /* m_misc.c in Sources */, - 72E847C60F9400D700AB3C99 /* m_random.c in Sources */, - 72E848050F941A5900AB3C99 /* md5.c in Sources */, - 72E848070F941A5900AB3C99 /* p_ceilng.c in Sources */, - 72E848080F941A5900AB3C99 /* p_checksum.c in Sources */, - 72E848090F941A5900AB3C99 /* p_doors.c in Sources */, - 72E8480A0F941A5900AB3C99 /* p_enemy.c in Sources */, - 72E8480B0F941A5900AB3C99 /* p_floor.c in Sources */, - 72E8480C0F941A5900AB3C99 /* p_genlin.c in Sources */, - 72E8480D0F941A5900AB3C99 /* p_inter.c in Sources */, - 72E8480E0F941A5900AB3C99 /* p_lights.c in Sources */, - 72E8480F0F941A5900AB3C99 /* p_map.c in Sources */, - 72E848100F941A5900AB3C99 /* p_maputl.c in Sources */, - 72E848110F941A5900AB3C99 /* p_mobj.c in Sources */, - 72E848120F941A5900AB3C99 /* p_plats.c in Sources */, - 72E848130F941A5900AB3C99 /* p_pspr.c in Sources */, - 72E848140F941A5900AB3C99 /* p_saveg.c in Sources */, - 72E848150F941A5900AB3C99 /* p_setup.c in Sources */, - 72E848160F941A5900AB3C99 /* p_sight.c in Sources */, - 72E848170F941A5900AB3C99 /* p_spec.c in Sources */, - 72E848180F941A5900AB3C99 /* p_switch.c in Sources */, - 72E848190F941A5900AB3C99 /* p_telept.c in Sources */, - 72E8481A0F941A5900AB3C99 /* p_tick.c in Sources */, - 72E8481B0F941A5900AB3C99 /* p_user.c in Sources */, - 72E848260F941A8300AB3C99 /* r_bsp.c in Sources */, - 72E848270F941A8300AB3C99 /* r_data.c in Sources */, - 72E848280F941A8300AB3C99 /* r_demo.c in Sources */, - 72E848290F941A8300AB3C99 /* r_draw.c in Sources */, - 72E8483D0F941AAC00AB3C99 /* r_filter.c in Sources */, - 72E8483E0F941AAC00AB3C99 /* r_fps.c in Sources */, - 72E8483F0F941AAC00AB3C99 /* r_main.c in Sources */, - 72E848400F941AAC00AB3C99 /* r_patch.c in Sources */, - 72E848410F941AAC00AB3C99 /* r_plane.c in Sources */, - 72E848420F941AAC00AB3C99 /* r_segs.c in Sources */, - 72E848430F941AAC00AB3C99 /* r_sky.c in Sources */, - 72E848440F941AAC00AB3C99 /* r_things.c in Sources */, - 72E848450F941AAC00AB3C99 /* s_sound.c in Sources */, - 72E8485C0F941ADC00AB3C99 /* sounds.c in Sources */, - 72E8485D0F941ADC00AB3C99 /* st_lib.c in Sources */, - 72E8485E0F941ADC00AB3C99 /* st_stuff.c in Sources */, - 72E8485F0F941ADC00AB3C99 /* tables.c in Sources */, - 72E848600F941ADC00AB3C99 /* v_video.c in Sources */, - 72E848610F941ADC00AB3C99 /* version.c in Sources */, - 72E848630F941ADC00AB3C99 /* w_mmap.c in Sources */, - 72E848640F941ADC00AB3C99 /* w_wad.c in Sources */, - 72E848650F941ADC00AB3C99 /* wi_stuff.c in Sources */, - 72E848660F941ADC00AB3C99 /* z_bmalloc.c in Sources */, - 72E848670F941ADC00AB3C99 /* z_zone.c in Sources */, - 72E849600F942B9300AB3C99 /* cvar.c in Sources */, - 72E849610F942B9300AB3C99 /* misc.c in Sources */, - 72E849F60F94ED1100AB3C99 /* prboomInterface.c in Sources */, - 72E84A290F9503F100AB3C99 /* cmd.c in Sources */, - 72F1F9B40F96C18800AD49AC /* dict.c in Sources */, - 72F1F9B50F96C18800AD49AC /* geom.c in Sources */, - 72F1F9B60F96C18800AD49AC /* memalloc.c in Sources */, - 72F1F9B70F96C18800AD49AC /* mesh.c in Sources */, - 72F1F9B80F96C18800AD49AC /* normal.c in Sources */, - 72F1F9BA0F96C18800AD49AC /* priorityq.c in Sources */, - 72F1F9BB0F96C18800AD49AC /* render.c in Sources */, - 72F1F9BC0F96C18800AD49AC /* sweep.c in Sources */, - 72F1F9BD0F96C18800AD49AC /* tess.c in Sources */, - 72F1F9BE0F96C18800AD49AC /* tessmono.c in Sources */, - 72E731EB0F97E68100E702CD /* iphone_sound.c in Sources */, - 7239452C0F9C0E7500EADD62 /* iphone_mapSelect.c in Sources */, - 72484E5E0FB0E99900124E1C /* iphone_render.c in Sources */, - 43DD8392100295F70006E1DD /* iphone_async.c in Sources */, - 72A55EEF1003A94300F788A5 /* iphone_start.c in Sources */, - 72A560E21004FAEE00F788A5 /* iphone_net.c in Sources */, - ED9AB3D110966E85000B5852 /* iphone_email.m in Sources */, - C86F966813D617740069B7B6 /* MenuViewController.mm in Sources */, - C84F829213D76E96006D01AB /* MapMenuView.m in Sources */, - C84F83F613D7A99C006D01AB /* GenericMenuView.m in Sources */, - C84F855913D8B55C006D01AB /* SettingsMenuView.m in Sources */, - 724C531F0FBDBCEE000E4348 /* BackgroundMusic.cpp in Sources */, - C88530C913D8CBEA00A5FBF7 /* MainMenuView.m in Sources */, - C885314413D8D79400A5FBF7 /* ControlsMenuView.m in Sources */, - C81E0C7213DF471000B1049A /* UIFontButton.m in Sources */, - C81E0C8F13DF4A1B00B1049A /* UIFontLabel.m in Sources */, - C879320113F6143C003D834F /* UICustomSwitch.m in Sources */, - C8139A7913F9E0440094C2C0 /* UICustomSlider.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = doom_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - _DEBUG, - HAVE_CONFIG_H, - IPHONE, - ); - HEADER_SEARCH_PATHS = ""; - INFOPLIST_FILE = Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 3.2; - PRODUCT_NAME = Doom; - PROFILE_PREFIX = com.idsoftware; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = doom_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - HAVE_CONFIG_H, - IPHONE, - ); - HEADER_SEARCH_PATHS = ""; - INFOPLIST_FILE = Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 3.2; - PRODUCT_NAME = Doom; - PROFILE_PREFIX = com.idsoftware; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 4364BF480F5CB27300F29317 /* AdHocDist */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_ENTITLEMENTS = dist.plist; - CODE_SIGN_IDENTITY = "iPhone Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_THUMB_SUPPORT = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = ""; - PREBINDING = NO; - PRODUCT_NAME = Doom; - PROVISIONING_PROFILE = ""; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos3.0; - }; - name = AdHocDist; - }; - 4364BF490F5CB27300F29317 /* AdHocDist */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = doom_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - HAVE_CONFIG_H, - IPHONE, - ); - HEADER_SEARCH_PATHS = ""; - INFOPLIST_FILE = Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 3.2; - PRODUCT_NAME = Doom; - PROFILE_PREFIX = com.idsoftware; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = AdHocDist; - }; - 43AE7CA40F61EC4E00B2F562 /* ReleaseLite */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Developer: Gregory Hodges (255R7FQ4L3)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Gregory Hodges (255R7FQ4L3)"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_THUMB_SUPPORT = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = ""; - PREBINDING = NO; - PRODUCT_NAME = Doom; - SDKROOT = iphoneos3.0; - }; - name = ReleaseLite; - }; - 43AE7CA50F61EC4E00B2F562 /* ReleaseLite */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = doom_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - EPISODE1, - IPHONE, - ); - HEADER_SEARCH_PATHS = ""; - INFOPLIST_FILE = Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 3.2; - PRODUCT_NAME = DoomLite; - PROFILE_PREFIX = com.idsoftware; - PROVISIONING_PROFILE = ""; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = ReleaseLite; - }; - 43AE7CAE0F61FC9200B2F562 /* DebugLite */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Developer: Gregory Hodges (255R7FQ4L3)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Gregory Hodges (255R7FQ4L3)"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = ""; - ONLY_ACTIVE_ARCH = YES; - PREBINDING = NO; - PRODUCT_NAME = Doom; - SDKROOT = iphoneos3.0; - }; - name = DebugLite; - }; - 43AE7CAF0F61FC9200B2F562 /* DebugLite */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = doom_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - EPISODE1, - IPHONE, - ); - HEADER_SEARCH_PATHS = ""; - INFOPLIST_FILE = Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 3.2; - PRODUCT_NAME = DoomLite; - PROFILE_PREFIX = com.idsoftware; - PROVISIONING_PROFILE = ""; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = DebugLite; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = "HAVE_CONFIG_H=1"; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = ""; - ONLY_ACTIVE_ARCH = YES; - PREBINDING = NO; - PRODUCT_NAME = Doom; - PROVISIONING_PROFILE = ""; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = HAVE_CONFIG_H; - GCC_THUMB_SUPPORT = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = ""; - PREBINDING = NO; - PRODUCT_NAME = Doom; - PROVISIONING_PROFILE = ""; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos3.0; - }; - name = Release; - }; - ED06595B1087C51800E5450B /* Distribution */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Distribution: id Software"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: id Software"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_PREPROCESSOR_DEFINITIONS = HAVE_CONFIG_H; - GCC_THUMB_SUPPORT = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = ""; - PREBINDING = NO; - PRODUCT_NAME = Doom; - PROVISIONING_PROFILE = "31C73095-0DD9-4ABA-BB25-8D23F661F10F"; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = "31C73095-0DD9-4ABA-BB25-8D23F661F10F"; - SDKROOT = iphoneos3.0; - }; - name = Distribution; - }; - ED06595C1087C51800E5450B /* Distribution */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CODE_SIGN_IDENTITY = "iPhone Distribution: id Software"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: id Software"; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = doom_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = ( - HAVE_CONFIG_H, - IPHONE, - ); - HEADER_SEARCH_PATHS = ""; - INFOPLIST_FILE = Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 3.2; - PRODUCT_NAME = Doom; - PROFILE_PREFIX = com.idsoftware; - PROVISIONING_PROFILE = "2ADBE5F0-FC02-4DBF-BEC1-220CF6D12D16"; - "PROVISIONING_PROFILE[sdk=iphoneos*]" = "18BCE49D-8823-4A0C-B597-CFE83C7820BE"; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Distribution; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Doom" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 43AE7CAF0F61FC9200B2F562 /* DebugLite */, - 1D6058950D05DD3E006BFB54 /* Release */, - 43AE7CA50F61EC4E00B2F562 /* ReleaseLite */, - 4364BF490F5CB27300F29317 /* AdHocDist */, - ED06595C1087C51800E5450B /* Distribution */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Doom" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - 43AE7CAE0F61FC9200B2F562 /* DebugLite */, - C01FCF5008A954540054247B /* Release */, - 43AE7CA40F61EC4E00B2F562 /* ReleaseLite */, - 4364BF480F5CB27300F29317 /* AdHocDist */, - ED06595B1087C51800E5450B /* Distribution */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/code/iphone/Doom.xcodeproj/project.xcworkspace/xcuserdata/jeff.farrand.xcuserdatad/UserInterfaceState.xcuserstate b/code/iphone/Doom.xcodeproj/project.xcworkspace/xcuserdata/jeff.farrand.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 0e67159..0000000 --- a/code/iphone/Doom.xcodeproj/project.xcworkspace/xcuserdata/jeff.farrand.xcuserdatad/UserInterfaceState.xcuserstate +++ /dev/null @@ -1,16752 +0,0 @@ - - - - - $archiver - NSKeyedArchiver - $objects - - $null - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 2 - - - CF$UID - 3 - - - CF$UID - 4 - - - CF$UID - 5 - - - CF$UID - 6 - - - CF$UID - 7 - - - NS.objects - - - CF$UID - 8 - - - CF$UID - 205 - - - CF$UID - 357 - - - CF$UID - 447 - - - CF$UID - 527 - - - CF$UID - 612 - - - - F620643C-D996-4514-A5EC-32FA5319E3DF - 3389C048-DD3B-44D1-902F-60508F9DAB33 - F250263C-8A31-4895-A3EE-4376EBF8104C - 65CBB683-F3F0-4A75-BFB7-71FDE4195621 - AE63F0E4-6A65-4B22-B927-D6D8F1317553 - IDEWorkspaceDocument - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 9 - - - CF$UID - 10 - - - CF$UID - 11 - - - CF$UID - 12 - - - CF$UID - 13 - - - CF$UID - 14 - - - NS.objects - - - CF$UID - 2 - - - CF$UID - 15 - - - CF$UID - 17 - - - CF$UID - 14 - - - CF$UID - 18 - - - CF$UID - 19 - - - - IDEWorkspaceWindowControllerUniqueIdentifier - IDEOrderedWorkspaceTabControllers - IDEWindowToolbarIsVisible - IDEActiveWorkspaceTabController - IDEWindowFrame - IDEWorkspaceTabController_82449F16-BA75-4815-8930-B45D67BCE0FA - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 14 - - - - - $classes - - NSArray - NSObject - - $classname - NSArray - - - {{627, 378}, {1400, 944}} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 20 - - - CF$UID - 21 - - - CF$UID - 22 - - - CF$UID - 23 - - - CF$UID - 24 - - - CF$UID - 25 - - - CF$UID - 26 - - - CF$UID - 27 - - - NS.objects - - - CF$UID - 28 - - - CF$UID - 17 - - - CF$UID - 29 - - - CF$UID - 30 - - - CF$UID - 43 - - - CF$UID - 91 - - - CF$UID - 17 - - - CF$UID - 100 - - - - AssistantEditorsLayout - IDEShowNavigator - IDETabLabel - IDEWorkspaceTabControllerUtilityAreaSplitView - IDENavigatorArea - IDEWorkspaceTabControllerDesignAreaSplitView - IDEShowUtilities - IDEEditorArea - 0 - st_stuff.c - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 31 - - - NS.objects - - - CF$UID - 32 - - - - DVTSplitViewItems - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 33 - - - CF$UID - 39 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 36 - - - CF$UID - 37 - - - - DVTIdentifier - DVTViewMagnitude - - 622 - - $classes - - NSDictionary - NSObject - - $classname - NSDictionary - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 36 - - - CF$UID - 40 - - - - 224 - - $classes - - NSMutableArray - NSArray - NSObject - - $classname - NSMutableArray - - - $classes - - NSMutableDictionary - NSDictionary - NSObject - - $classname - NSMutableDictionary - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 44 - - - CF$UID - 45 - - - CF$UID - 46 - - - CF$UID - 47 - - - NS.objects - - - CF$UID - 48 - - - CF$UID - 68 - - - CF$UID - 83 - - - CF$UID - 44 - - - - Xcode.IDEKit.Navigator.Structure - Xcode.IDEKit.Navigator.BatchFind - Xcode.IDEKit.Navigator.Logs - SelectedNavigator - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 49 - - - CF$UID - 50 - - - CF$UID - 51 - - - CF$UID - 52 - - - CF$UID - 53 - - - CF$UID - 54 - - - CF$UID - 55 - - - NS.objects - - - CF$UID - 56 - - - CF$UID - 57 - - - CF$UID - 58 - - - CF$UID - 57 - - - CF$UID - 57 - - - CF$UID - 60 - - - CF$UID - 61 - - - - IDEVisibleRect - IDEUnsavedDocumentFilteringEnabled - IDENavigatorExpandedItemsBeforeFilteringSet - IDERecentDocumentFilteringEnabled - IDESCMStatusFilteringEnabled - IDESelectedObjects - IDEExpandedItemsSet - {{0, 47}, {244, 802}} - - - $class - - CF$UID - 59 - - NS.objects - - - - $classes - - NSSet - NSObject - - $classname - NSSet - - - $class - - CF$UID - 16 - - NS.objects - - - - $class - - CF$UID - 59 - - NS.objects - - - CF$UID - 62 - - - CF$UID - 65 - - - CF$UID - 66 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 63 - - - CF$UID - 64 - - - - Doom - Other Sources - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 63 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 63 - - - CF$UID - 67 - - - - Resources - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 69 - - - CF$UID - 70 - - - CF$UID - 71 - - - CF$UID - 72 - - - CF$UID - 73 - - - CF$UID - 74 - - - CF$UID - 75 - - - NS.objects - - - CF$UID - 28 - - - CF$UID - 57 - - - CF$UID - 76 - - - CF$UID - 77 - - - CF$UID - 78 - - - CF$UID - 80 - - - CF$UID - 81 - - - - IDEBatchFindNavigatorScrollPosition - IDEBatchFindNavigatorShowsOptions - IDEBatchFindNavigatorReplaceString - IDEBatchFindNavigatorFindString - IDEBatchFindNavigatorSelectedRowIndexes - IDEBatchFindNavigatorFindMode - IDEBatchFindNavigatorCollapsedGroups - 2009-2011 - XXXX-2011 - - $class - - CF$UID - 79 - - NSRangeCount - 0 - - - $classes - - NSIndexSet - NSObject - - $classname - NSIndexSet - - 1 - - $class - - CF$UID - 82 - - NSRangeCount - 0 - - - $classes - - NSMutableIndexSet - NSIndexSet - NSObject - - $classname - NSMutableIndexSet - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 84 - - - CF$UID - 85 - - - CF$UID - 86 - - - CF$UID - 87 - - - NS.objects - - - CF$UID - 88 - - - CF$UID - 89 - - - CF$UID - 57 - - - CF$UID - 90 - - - - IDELogNavigatorExpandedItemsStateKey - IDELogNavigatorSelectedObjectsStateKey - IDELogNavigatorRecentFilterStateKey - IDELogNavigatorVisibleRectStateKey - - $class - - CF$UID - 41 - - NS.objects - - - - $class - - CF$UID - 41 - - NS.objects - - - {{0, 0}, {259, 832}} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 31 - - - NS.objects - - - CF$UID - 92 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 93 - - - CF$UID - 95 - - - CF$UID - 97 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 24 - - - CF$UID - 94 - - - - 260 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 27 - - - CF$UID - 96 - - - - 880 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 98 - - - CF$UID - 99 - - - - IDEUtilitiesArea - 260 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 101 - - - CF$UID - 102 - - - CF$UID - 103 - - - CF$UID - 104 - - - CF$UID - 105 - - - CF$UID - 106 - - - CF$UID - 107 - - - CF$UID - 108 - - - NS.objects - - - CF$UID - 109 - - - CF$UID - 131 - - - CF$UID - 170 - - - CF$UID - 17 - - - CF$UID - 28 - - - CF$UID - 196 - - - CF$UID - 204 - - - CF$UID - 17 - - - - layoutTree - IDEEditorMode_Standard - IDEEDitorArea_DebugArea - IDEShowEditor - EditorMode - DebuggerSplitView - DefaultPersistentRepresentations - ShowDebuggerArea - - $class - - CF$UID - 130 - - geniusEditorContextNode - - CF$UID - 0 - - primaryEditorContextNode - - CF$UID - 110 - - rootLayoutTreeNode - - CF$UID - 127 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 0 - - contentType - 1 - documentArchivableRepresentation - - CF$UID - 111 - - orientation - 0 - parent - - CF$UID - 127 - - - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 122 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 113 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - Xcode.IDENavigableItemDomain.WorkspaceStructure - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 114 - - - CF$UID - 117 - - - CF$UID - 119 - - - CF$UID - 120 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 115 - - - st_stuff.c - - $classes - - IDEArchivableStringIndexPair - NSObject - - $classname - IDEArchivableStringIndexPair - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 118 - - - prboom - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 64 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 121 - - - Doom - - $class - - CF$UID - 125 - - documentURL - - CF$UID - 123 - - timestamp - - CF$UID - 0 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/prboom/st_stuff.c - - - $classes - - NSMutableString - NSString - NSObject - - $classname - NSMutableString - - - $classes - - DVTDocumentLocation - NSObject - - $classname - DVTDocumentLocation - - - $classes - - IDENavigableItemArchivableRepresentation - NSObject - - $classname - IDENavigableItemArchivableRepresentation - - - $class - - CF$UID - 129 - - children - - CF$UID - 128 - - contentType - 0 - documentArchivableRepresentation - - CF$UID - 0 - - orientation - 0 - parent - - CF$UID - 0 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 110 - - - - - $classes - - IDEWorkspaceTabControllerLayoutTreeNode - NSObject - - $classname - IDEWorkspaceTabControllerLayoutTreeNode - - - $classes - - IDEWorkspaceTabControllerLayoutTree - NSObject - - $classname - IDEWorkspaceTabControllerLayoutTree - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 132 - - - NS.objects - - - CF$UID - 133 - - - - EditorLayout_PersistentRepresentation - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 134 - - - NS.objects - - - CF$UID - 135 - - - - Main - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 136 - - - CF$UID - 137 - - - CF$UID - 138 - - - NS.objects - - - CF$UID - 139 - - - CF$UID - 28 - - - CF$UID - 168 - - - - EditorLayout_StateSavingStateDictionaries - EditorLayout_Selected - EditorLayout_Geometry - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 140 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 141 - - - CF$UID - 142 - - - CF$UID - 143 - - - CF$UID - 144 - - - CF$UID - 145 - - - CF$UID - 146 - - - CF$UID - 147 - - - NS.objects - - - CF$UID - 148 - - - CF$UID - 149 - - - CF$UID - 156 - - - CF$UID - 115 - - - CF$UID - 115 - - - CF$UID - 164 - - - CF$UID - 165 - - - - FileDataType - ArchivableRepresentation - EditorState - NavigableItemName - DocumentNavigableItemName - DocumentExtensionIdentifier - DocumentURL - public.c-source - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 122 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 150 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 151 - - - CF$UID - 152 - - - CF$UID - 153 - - - CF$UID - 154 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 115 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 118 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 64 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 155 - - - Doom - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 161 - - - CF$UID - 162 - - - CF$UID - 57 - - - CF$UID - 163 - - - - PrimaryDocumentTimestamp - PrimaryDocumentVisibleCharacterRange - HideAllIssues - PrimaryDocumentSelectedCharacterRange - 336003577.77755398 - {0, 1681} - {0, 0} - Xcode.IDEKit.EditorDocument.SourceCode - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 166 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/prboom/st_stuff.c - - $classes - - NSURL - NSObject - - $classname - NSURL - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 169 - - - - {{0, 0}, {880, 586}} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 171 - - - CF$UID - 172 - - - CF$UID - 173 - - - CF$UID - 174 - - - CF$UID - 175 - - - CF$UID - 176 - - - NS.objects - - - CF$UID - 80 - - - CF$UID - 177 - - - CF$UID - 179 - - - CF$UID - 80 - - - CF$UID - 182 - - - CF$UID - 190 - - - - LayoutFocusMode - console - variables - LayoutMode - IDEDebugArea_SplitView - IDEDebuggerAreaSplitView - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 178 - - - NS.objects - - - CF$UID - 28 - - - - ConsoleFilterMode - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 180 - - - NS.objects - - - CF$UID - 181 - - - - DBGVariablesViewFilterMode - 2 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 31 - - - NS.objects - - - CF$UID - 183 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 184 - - - CF$UID - 187 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 185 - - - CF$UID - 186 - - - - VariablesView - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 188 - - - CF$UID - 189 - - - - ConsoleArea - 581 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 31 - - - NS.objects - - - CF$UID - 191 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 192 - - - CF$UID - 194 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 185 - - - CF$UID - 193 - - - - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 188 - - - CF$UID - 195 - - - - 581 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 31 - - - NS.objects - - - CF$UID - 197 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 198 - - - CF$UID - 201 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 199 - - - CF$UID - 200 - - - - IDEEditor - 608 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 202 - - - CF$UID - 203 - - - - IDEDebuggerArea - 238 - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 206 - - - CF$UID - 207 - - - CF$UID - 208 - - - CF$UID - 209 - - - CF$UID - 210 - - - CF$UID - 9 - - - NS.objects - - - CF$UID - 211 - - - CF$UID - 355 - - - CF$UID - 57 - - - CF$UID - 356 - - - CF$UID - 206 - - - CF$UID - 3 - - - - IDEWorkspaceTabController_4C97C6F3-2C36-4427-8CFE-360199404C66 - IDEOrderedWorkspaceTabControllers - IDEWindowToolbarIsVisible - IDEWindowFrame - IDEActiveWorkspaceTabController - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 212 - - - CF$UID - 213 - - - CF$UID - 214 - - - CF$UID - 215 - - - CF$UID - 216 - - - CF$UID - 217 - - - CF$UID - 218 - - - CF$UID - 219 - - - NS.objects - - - CF$UID - 220 - - - CF$UID - 57 - - - CF$UID - 250 - - - CF$UID - 320 - - - CF$UID - 327 - - - CF$UID - 346 - - - CF$UID - 57 - - - CF$UID - 28 - - - - IDEEditorArea - IDEShowNavigator - IDETabLabel - IDEWorkspaceTabControllerUtilityAreaSplitView - IDENavigatorArea - IDEWorkspaceTabControllerDesignAreaSplitView - IDEShowUtilities - AssistantEditorsLayout - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 221 - - - CF$UID - 222 - - - CF$UID - 223 - - - CF$UID - 224 - - - CF$UID - 225 - - - CF$UID - 226 - - - CF$UID - 227 - - - CF$UID - 228 - - - NS.objects - - - CF$UID - 57 - - - CF$UID - 229 - - - CF$UID - 273 - - - CF$UID - 17 - - - CF$UID - 28 - - - CF$UID - 301 - - - CF$UID - 309 - - - CF$UID - 310 - - - - ShowDebuggerArea - IDEEditorMode_Standard - IDEEDitorArea_DebugArea - IDEShowEditor - EditorMode - DebuggerSplitView - DefaultPersistentRepresentations - layoutTree - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 230 - - - NS.objects - - - CF$UID - 231 - - - - EditorLayout_PersistentRepresentation - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 232 - - - NS.objects - - - CF$UID - 233 - - - - Main - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 234 - - - CF$UID - 235 - - - CF$UID - 236 - - - NS.objects - - - CF$UID - 237 - - - CF$UID - 28 - - - CF$UID - 271 - - - - EditorLayout_StateSavingStateDictionaries - EditorLayout_Selected - EditorLayout_Geometry - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 238 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 239 - - - CF$UID - 240 - - - CF$UID - 241 - - - CF$UID - 242 - - - CF$UID - 243 - - - CF$UID - 244 - - - CF$UID - 245 - - - NS.objects - - - CF$UID - 246 - - - CF$UID - 247 - - - CF$UID - 259 - - - CF$UID - 267 - - - CF$UID - 250 - - - CF$UID - 268 - - - CF$UID - 269 - - - - FileDataType - ArchivableRepresentation - EditorState - NavigableItemName - DocumentNavigableItemName - DocumentExtensionIdentifier - DocumentURL - public.objective-c-source - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 257 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 248 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 249 - - - CF$UID - 251 - - - CF$UID - 253 - - - CF$UID - 255 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 250 - - - GenericMenuView.m - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 252 - - - InterfaceBuilder - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 254 - - - Other Sources - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 256 - - - Doom - - $class - - CF$UID - 125 - - documentURL - - CF$UID - 258 - - timestamp - - CF$UID - 0 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/GenericMenuView.m - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 264 - - - CF$UID - 265 - - - CF$UID - 57 - - - CF$UID - 266 - - - - PrimaryDocumentTimestamp - PrimaryDocumentVisibleCharacterRange - HideAllIssues - PrimaryDocumentSelectedCharacterRange - 333326399.194489 - {187, 767} - {945, 0} - -BackToMain - Xcode.IDEKit.EditorDocument.SourceCode - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 270 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/GenericMenuView.m - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 272 - - - - {{0, 0}, {600, 600}} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 274 - - - CF$UID - 275 - - - CF$UID - 276 - - - CF$UID - 277 - - - CF$UID - 278 - - - CF$UID - 279 - - - NS.objects - - - CF$UID - 80 - - - CF$UID - 280 - - - CF$UID - 282 - - - CF$UID - 80 - - - CF$UID - 293 - - - CF$UID - 299 - - - - LayoutFocusMode - console - IDEDebugArea_SplitView - LayoutMode - IDEDebuggerAreaSplitView - variables - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 281 - - - NS.objects - - - CF$UID - 28 - - - - ConsoleFilterMode - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 284 - - - - DVTSplitViewItems - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 285 - - - CF$UID - 290 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 288 - - - CF$UID - 289 - - - - DVTIdentifier - DVTViewMagnitude - VariablesView - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 291 - - - CF$UID - 292 - - - - ConsoleArea - 301 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 294 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 295 - - - CF$UID - 297 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 288 - - - CF$UID - 296 - - - - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 291 - - - CF$UID - 298 - - - - 301 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 300 - - - NS.objects - - - CF$UID - 181 - - - - DBGVariablesViewFilterMode - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 302 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 303 - - - CF$UID - 306 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 304 - - - CF$UID - 305 - - - - IDEEditor - 203 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 307 - - - CF$UID - 308 - - - - IDEDebuggerArea - 115 - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 130 - - geniusEditorContextNode - - CF$UID - 0 - - primaryEditorContextNode - - CF$UID - 311 - - rootLayoutTreeNode - - CF$UID - 318 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 0 - - contentType - 1 - documentArchivableRepresentation - - CF$UID - 312 - - orientation - 0 - parent - - CF$UID - 318 - - - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 257 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 313 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 314 - - - CF$UID - 315 - - - CF$UID - 316 - - - CF$UID - 317 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 250 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 252 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 254 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 256 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 319 - - contentType - 0 - documentArchivableRepresentation - - CF$UID - 0 - - orientation - 0 - parent - - CF$UID - 0 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 311 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 321 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 322 - - - CF$UID - 325 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 324 - - - - - 411 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 326 - - - - 211 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 328 - - - CF$UID - 329 - - - NS.objects - - - CF$UID - 329 - - - CF$UID - 330 - - - - SelectedNavigator - Xcode.IDEKit.Navigator.Structure - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 331 - - - CF$UID - 332 - - - CF$UID - 333 - - - CF$UID - 334 - - - CF$UID - 335 - - - CF$UID - 336 - - - CF$UID - 337 - - - NS.objects - - - CF$UID - 338 - - - CF$UID - 57 - - - CF$UID - 58 - - - CF$UID - 57 - - - CF$UID - 57 - - - CF$UID - 339 - - - CF$UID - 341 - - - - IDEVisibleRect - IDEUnsavedDocumentFilteringEnabled - IDENavigatorExpandedItemsBeforeFilteringSet - IDERecentDocumentFilteringEnabled - IDESCMStatusFilteringEnabled - IDESelectedObjects - IDEExpandedItemsSet - {{0, 0}, {0, 0}} - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 340 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 254 - - - CF$UID - 252 - - - CF$UID - 250 - - - - - $class - - CF$UID - 59 - - NS.objects - - - CF$UID - 342 - - - CF$UID - 343 - - - CF$UID - 344 - - - CF$UID - 345 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 254 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 254 - - - CF$UID - 252 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 67 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 347 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 348 - - - CF$UID - 350 - - - CF$UID - 352 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 216 - - - CF$UID - 349 - - - - 260 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 212 - - - CF$UID - 351 - - - - 1341 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 353 - - - CF$UID - 354 - - - - IDEUtilitiesArea - 260 - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 206 - - - - {{327, 333}, {600, 668}} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 210 - - - CF$UID - 208 - - - CF$UID - 358 - - - CF$UID - 209 - - - CF$UID - 207 - - - CF$UID - 9 - - - NS.objects - - - CF$UID - 358 - - - CF$UID - 57 - - - CF$UID - 359 - - - CF$UID - 445 - - - CF$UID - 446 - - - CF$UID - 4 - - - - IDEWorkspaceTabController_2E57CB2E-881C-48BE-803E-9AA60543F8D6 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 212 - - - CF$UID - 213 - - - CF$UID - 219 - - - CF$UID - 215 - - - CF$UID - 216 - - - CF$UID - 217 - - - CF$UID - 218 - - - CF$UID - 214 - - - NS.objects - - - CF$UID - 360 - - - CF$UID - 57 - - - CF$UID - 28 - - - CF$UID - 424 - - - CF$UID - 430 - - - CF$UID - 437 - - - CF$UID - 57 - - - CF$UID - 370 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 221 - - - CF$UID - 222 - - - CF$UID - 223 - - - CF$UID - 224 - - - CF$UID - 225 - - - CF$UID - 226 - - - CF$UID - 227 - - - CF$UID - 228 - - - NS.objects - - - CF$UID - 57 - - - CF$UID - 361 - - - CF$UID - 393 - - - CF$UID - 17 - - - CF$UID - 28 - - - CF$UID - 408 - - - CF$UID - 414 - - - CF$UID - 415 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 230 - - - NS.objects - - - CF$UID - 362 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 232 - - - NS.objects - - - CF$UID - 363 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 234 - - - CF$UID - 235 - - - CF$UID - 236 - - - NS.objects - - - CF$UID - 364 - - - CF$UID - 28 - - - CF$UID - 392 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 365 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 239 - - - CF$UID - 240 - - - CF$UID - 241 - - - CF$UID - 242 - - - CF$UID - 243 - - - CF$UID - 244 - - - CF$UID - 245 - - - NS.objects - - - CF$UID - 366 - - - CF$UID - 367 - - - CF$UID - 375 - - - CF$UID - 370 - - - CF$UID - 370 - - - CF$UID - 389 - - - CF$UID - 390 - - - - com.apple.InterfaceBuilder3.CocoaTouch.XIB - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 373 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 368 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 369 - - - CF$UID - 371 - - - CF$UID - 372 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 370 - - - MainWindow.xib - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 67 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 256 - - - - $class - - CF$UID - 125 - - documentURL - - CF$UID - 374 - - timestamp - - CF$UID - 0 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/MainWindow.xib - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 376 - - - CF$UID - 377 - - - CF$UID - 378 - - - CF$UID - 379 - - - NS.objects - - - CF$UID - 380 - - - CF$UID - 381 - - - CF$UID - 379 - - - CF$UID - 382 - - - - IBDockViewController - SelectedObjectIDs - SelectionProvider - IBCanvasViewController - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 16 - - NS.objects - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 383 - - - CF$UID - 384 - - - NS.objects - - - CF$UID - 385 - - - CF$UID - 388 - - - - ObjectIDToLastKnownCanvasPositionMap - EditedTopLevelObjectIDs - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 386 - - - NS.objects - - - CF$UID - 387 - - - - 170 - {53, 163} - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 181 - - - - Xcode.IDEKit.CocoaTouchIntegration.EditorDocument.CocoaTouch - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 391 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/MainWindow.xib - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 272 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 274 - - - CF$UID - 275 - - - CF$UID - 276 - - - CF$UID - 277 - - - CF$UID - 278 - - - CF$UID - 279 - - - NS.objects - - - CF$UID - 80 - - - CF$UID - 394 - - - CF$UID - 395 - - - CF$UID - 80 - - - CF$UID - 401 - - - CF$UID - 407 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 281 - - - NS.objects - - - CF$UID - 28 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 396 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 397 - - - CF$UID - 399 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 288 - - - CF$UID - 398 - - - - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 291 - - - CF$UID - 400 - - - - 301 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 402 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 403 - - - CF$UID - 405 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 288 - - - CF$UID - 404 - - - - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 291 - - - CF$UID - 406 - - - - 301 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 300 - - - NS.objects - - - CF$UID - 181 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 409 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 410 - - - CF$UID - 412 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 304 - - - CF$UID - 411 - - - - 203 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 307 - - - CF$UID - 413 - - - - 115 - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 130 - - geniusEditorContextNode - - CF$UID - 0 - - primaryEditorContextNode - - CF$UID - 416 - - rootLayoutTreeNode - - CF$UID - 422 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 0 - - contentType - 1 - documentArchivableRepresentation - - CF$UID - 417 - - orientation - 0 - parent - - CF$UID - 422 - - - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 373 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 418 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 419 - - - CF$UID - 420 - - - CF$UID - 421 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 370 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 67 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 256 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 423 - - contentType - 0 - documentArchivableRepresentation - - CF$UID - 0 - - orientation - 0 - parent - - CF$UID - 0 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 416 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 425 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 426 - - - CF$UID - 428 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 427 - - - - 398 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 429 - - - - 224 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 328 - - - CF$UID - 329 - - - NS.objects - - - CF$UID - 329 - - - CF$UID - 431 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 331 - - - CF$UID - 332 - - - CF$UID - 333 - - - CF$UID - 334 - - - CF$UID - 335 - - - CF$UID - 336 - - - CF$UID - 337 - - - NS.objects - - - CF$UID - 338 - - - CF$UID - 57 - - - CF$UID - 58 - - - CF$UID - 57 - - - CF$UID - 57 - - - CF$UID - 432 - - - CF$UID - 434 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 433 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 67 - - - CF$UID - 370 - - - - - $class - - CF$UID - 59 - - NS.objects - - - CF$UID - 435 - - - CF$UID - 436 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 67 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 438 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 439 - - - CF$UID - 441 - - - CF$UID - 443 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 216 - - - CF$UID - 440 - - - - 260 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 212 - - - CF$UID - 442 - - - - 1140 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 353 - - - CF$UID - 444 - - - - 260 - {{285, 379}, {600, 668}} - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 358 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 210 - - - CF$UID - 208 - - - CF$UID - 448 - - - CF$UID - 209 - - - CF$UID - 207 - - - CF$UID - 9 - - - NS.objects - - - CF$UID - 448 - - - CF$UID - 57 - - - CF$UID - 449 - - - CF$UID - 525 - - - CF$UID - 526 - - - CF$UID - 5 - - - - IDEWorkspaceTabController_EB14B1F1-732B-4B6C-B2A1-050CB7EF3E11 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 212 - - - CF$UID - 213 - - - CF$UID - 214 - - - CF$UID - 215 - - - CF$UID - 216 - - - CF$UID - 217 - - - CF$UID - 218 - - - CF$UID - 219 - - - NS.objects - - - CF$UID - 450 - - - CF$UID - 57 - - - CF$UID - 460 - - - CF$UID - 502 - - - CF$UID - 508 - - - CF$UID - 517 - - - CF$UID - 57 - - - CF$UID - 28 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 221 - - - CF$UID - 222 - - - CF$UID - 223 - - - CF$UID - 224 - - - CF$UID - 225 - - - CF$UID - 226 - - - CF$UID - 227 - - - CF$UID - 228 - - - NS.objects - - - CF$UID - 57 - - - CF$UID - 451 - - - CF$UID - 471 - - - CF$UID - 17 - - - CF$UID - 28 - - - CF$UID - 486 - - - CF$UID - 492 - - - CF$UID - 493 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 230 - - - NS.objects - - - CF$UID - 452 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 232 - - - NS.objects - - - CF$UID - 453 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 234 - - - CF$UID - 235 - - - CF$UID - 236 - - - NS.objects - - - CF$UID - 454 - - - CF$UID - 28 - - - CF$UID - 470 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 455 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 239 - - - CF$UID - 240 - - - CF$UID - 241 - - - CF$UID - 242 - - - CF$UID - 243 - - - CF$UID - 244 - - - CF$UID - 245 - - - NS.objects - - - CF$UID - 456 - - - CF$UID - 457 - - - CF$UID - 465 - - - CF$UID - 460 - - - CF$UID - 460 - - - CF$UID - 268 - - - CF$UID - 468 - - - - public.c-source - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 463 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 458 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 459 - - - CF$UID - 461 - - - CF$UID - 462 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 460 - - - iphone_menus.c - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 254 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 256 - - - - $class - - CF$UID - 125 - - documentURL - - CF$UID - 464 - - timestamp - - CF$UID - 0 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/iphone_menus.c - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 466 - - - CF$UID - 467 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 333326075.250848 - {0, 1636} - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 469 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/iphone_menus.c - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 272 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 274 - - - CF$UID - 275 - - - CF$UID - 276 - - - CF$UID - 277 - - - CF$UID - 278 - - - CF$UID - 279 - - - NS.objects - - - CF$UID - 80 - - - CF$UID - 472 - - - CF$UID - 473 - - - CF$UID - 80 - - - CF$UID - 479 - - - CF$UID - 485 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 281 - - - NS.objects - - - CF$UID - 28 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 474 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 475 - - - CF$UID - 477 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 288 - - - CF$UID - 476 - - - - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 291 - - - CF$UID - 478 - - - - 301 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 480 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 481 - - - CF$UID - 483 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 288 - - - CF$UID - 482 - - - - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 291 - - - CF$UID - 484 - - - - 301 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 300 - - - NS.objects - - - CF$UID - 181 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 487 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 488 - - - CF$UID - 490 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 304 - - - CF$UID - 489 - - - - 203 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 307 - - - CF$UID - 491 - - - - 115 - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 130 - - geniusEditorContextNode - - CF$UID - 0 - - primaryEditorContextNode - - CF$UID - 494 - - rootLayoutTreeNode - - CF$UID - 500 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 0 - - contentType - 1 - documentArchivableRepresentation - - CF$UID - 495 - - orientation - 0 - parent - - CF$UID - 500 - - - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 463 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 496 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 497 - - - CF$UID - 498 - - - CF$UID - 499 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 460 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 254 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 256 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 501 - - contentType - 0 - documentArchivableRepresentation - - CF$UID - 0 - - orientation - 0 - parent - - CF$UID - 0 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 494 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 503 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 504 - - - CF$UID - 506 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 505 - - - - 411 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 507 - - - - 211 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 328 - - - CF$UID - 329 - - - NS.objects - - - CF$UID - 329 - - - CF$UID - 509 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 331 - - - CF$UID - 332 - - - CF$UID - 333 - - - CF$UID - 334 - - - CF$UID - 335 - - - CF$UID - 336 - - - CF$UID - 337 - - - NS.objects - - - CF$UID - 338 - - - CF$UID - 57 - - - CF$UID - 58 - - - CF$UID - 57 - - - CF$UID - 57 - - - CF$UID - 510 - - - CF$UID - 512 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 511 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 254 - - - CF$UID - 460 - - - - - $class - - CF$UID - 59 - - NS.objects - - - CF$UID - 513 - - - CF$UID - 514 - - - CF$UID - 515 - - - CF$UID - 516 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 67 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 254 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 254 - - - CF$UID - 252 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 518 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 519 - - - CF$UID - 521 - - - CF$UID - 523 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 216 - - - CF$UID - 520 - - - - 260 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 212 - - - CF$UID - 522 - - - - 1341 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 353 - - - CF$UID - 524 - - - - 260 - {{306, 356}, {600, 668}} - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 448 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 210 - - - CF$UID - 208 - - - CF$UID - 528 - - - CF$UID - 209 - - - CF$UID - 207 - - - CF$UID - 9 - - - NS.objects - - - CF$UID - 528 - - - CF$UID - 57 - - - CF$UID - 529 - - - CF$UID - 610 - - - CF$UID - 611 - - - CF$UID - 6 - - - - IDEWorkspaceTabController_B0E0B3DC-5AAF-4BFF-AF1E-B69835241B26 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 212 - - - CF$UID - 213 - - - CF$UID - 214 - - - CF$UID - 215 - - - CF$UID - 216 - - - CF$UID - 217 - - - CF$UID - 218 - - - CF$UID - 219 - - - NS.objects - - - CF$UID - 530 - - - CF$UID - 57 - - - CF$UID - 540 - - - CF$UID - 589 - - - CF$UID - 595 - - - CF$UID - 602 - - - CF$UID - 57 - - - CF$UID - 28 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 221 - - - CF$UID - 222 - - - CF$UID - 223 - - - CF$UID - 224 - - - CF$UID - 225 - - - CF$UID - 226 - - - CF$UID - 227 - - - CF$UID - 228 - - - NS.objects - - - CF$UID - 57 - - - CF$UID - 531 - - - CF$UID - 558 - - - CF$UID - 17 - - - CF$UID - 28 - - - CF$UID - 573 - - - CF$UID - 579 - - - CF$UID - 580 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 230 - - - NS.objects - - - CF$UID - 532 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 232 - - - NS.objects - - - CF$UID - 533 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 234 - - - CF$UID - 235 - - - CF$UID - 236 - - - NS.objects - - - CF$UID - 534 - - - CF$UID - 28 - - - CF$UID - 557 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 535 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 239 - - - CF$UID - 240 - - - CF$UID - 241 - - - CF$UID - 242 - - - CF$UID - 243 - - - CF$UID - 244 - - - CF$UID - 245 - - - NS.objects - - - CF$UID - 536 - - - CF$UID - 537 - - - CF$UID - 545 - - - CF$UID - 540 - - - CF$UID - 540 - - - CF$UID - 554 - - - CF$UID - 555 - - - - com.apple.xml-property-list - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 543 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 538 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 539 - - - CF$UID - 541 - - - CF$UID - 542 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 540 - - - Info.plist - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 67 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 256 - - - - $class - - CF$UID - 125 - - documentURL - - CF$UID - 544 - - timestamp - - CF$UID - 0 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Info.plist - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 546 - - - CF$UID - 547 - - - CF$UID - 548 - - - NS.objects - - - CF$UID - 549 - - - CF$UID - 551 - - - CF$UID - 553 - - - - IDE_PLIST_EDITOR_SELECTION_KEY - IDE_PLIST_EDITOR_EXPANSION_KEY - IDE_PLIST_EDITOR_VISIBLERECT_KEY - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 550 - - - - CFBundleIconFile - - $class - - CF$UID - 552 - - NS.objects - - - - $classes - - NSMutableSet - NSSet - NSObject - - $classname - NSMutableSet - - {{0, 0}, {600, 561}} - Xcode.IDEKit.EditorDocument.PlistEditor - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 556 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Info.plist - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 272 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 274 - - - CF$UID - 275 - - - CF$UID - 276 - - - CF$UID - 277 - - - CF$UID - 278 - - - CF$UID - 279 - - - NS.objects - - - CF$UID - 80 - - - CF$UID - 559 - - - CF$UID - 560 - - - CF$UID - 80 - - - CF$UID - 566 - - - CF$UID - 572 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 281 - - - NS.objects - - - CF$UID - 28 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 561 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 562 - - - CF$UID - 564 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 288 - - - CF$UID - 563 - - - - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 291 - - - CF$UID - 565 - - - - 301 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 567 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 568 - - - CF$UID - 570 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 288 - - - CF$UID - 569 - - - - 298 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 291 - - - CF$UID - 571 - - - - 301 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 300 - - - NS.objects - - - CF$UID - 181 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 574 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 575 - - - CF$UID - 577 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 304 - - - CF$UID - 576 - - - - 203 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 307 - - - CF$UID - 578 - - - - 115 - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 130 - - geniusEditorContextNode - - CF$UID - 0 - - primaryEditorContextNode - - CF$UID - 581 - - rootLayoutTreeNode - - CF$UID - 587 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 0 - - contentType - 1 - documentArchivableRepresentation - - CF$UID - 582 - - orientation - 0 - parent - - CF$UID - 587 - - - - $class - - CF$UID - 126 - - DocumentLocation - - CF$UID - 543 - - DomainIdentifier - - CF$UID - 112 - - IdentifierPath - - CF$UID - 583 - - IndexOfDocumentIdentifier - - CF$UID - 28 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 584 - - - CF$UID - 585 - - - CF$UID - 586 - - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 540 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 67 - - - - $class - - CF$UID - 116 - - Identifier - - CF$UID - 256 - - - - $class - - CF$UID - 129 - - children - - CF$UID - 588 - - contentType - 0 - documentArchivableRepresentation - - CF$UID - 0 - - orientation - 0 - parent - - CF$UID - 0 - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 581 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 590 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 591 - - - CF$UID - 593 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 592 - - - - 376 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 594 - - - - 224 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 328 - - - CF$UID - 329 - - - NS.objects - - - CF$UID - 329 - - - CF$UID - 596 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 331 - - - CF$UID - 332 - - - CF$UID - 333 - - - CF$UID - 334 - - - CF$UID - 335 - - - CF$UID - 336 - - - CF$UID - 337 - - - NS.objects - - - CF$UID - 338 - - - CF$UID - 57 - - - CF$UID - 58 - - - CF$UID - 57 - - - CF$UID - 57 - - - CF$UID - 597 - - - CF$UID - 599 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 598 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 67 - - - CF$UID - 540 - - - - - $class - - CF$UID - 59 - - NS.objects - - - CF$UID - 600 - - - CF$UID - 601 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 256 - - - CF$UID - 67 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 603 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 604 - - - CF$UID - 606 - - - CF$UID - 608 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 216 - - - CF$UID - 605 - - - - 260 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 212 - - - CF$UID - 607 - - - - 1140 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 353 - - - CF$UID - 609 - - - - 260 - {{264, 424}, {600, 646}} - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 528 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 613 - - - CF$UID - 614 - - - CF$UID - 615 - - - CF$UID - 616 - - - CF$UID - 617 - - - CF$UID - 618 - - - CF$UID - 619 - - - CF$UID - 620 - - - CF$UID - 621 - - - CF$UID - 622 - - - CF$UID - 623 - - - NS.objects - - - CF$UID - 57 - - - CF$UID - 624 - - - CF$UID - 28 - - - CF$UID - 1138 - - - CF$UID - 1143 - - - CF$UID - 1146 - - - CF$UID - 1176 - - - CF$UID - 1177 - - - CF$UID - 1196 - - - CF$UID - 57 - - - CF$UID - 57 - - - - BreakpointsActivated - DefaultEditorStatesForURLs - DebuggingWindowBehavior - ActiveRunDestination - ActiveScheme - LastCompletedPersistentSchemeBasedActivityReport - DocumentWindows - DefaultEditorFrameSizeForURLs - RecentEditorDocumentURLs - AppFocusInMiniDebugging - MiniDebuggingConsole - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 389 - - - CF$UID - 554 - - - CF$UID - 625 - - - CF$UID - 268 - - - CF$UID - 626 - - - CF$UID - 627 - - - NS.objects - - - CF$UID - 628 - - - CF$UID - 652 - - - CF$UID - 658 - - - CF$UID - 710 - - - CF$UID - 1096 - - - CF$UID - 1101 - - - - Xcode.Xcode3ProjectSupport.EditorDocument.Xcode3Project - Xcode.IDEKit.EditorDocument.LogDocument - IDEQuickLookEditor.Editor - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 629 - - - CF$UID - 631 - - - NS.objects - - - CF$UID - 633 - - - CF$UID - 643 - - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 630 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Resources-iPad/MainWindow-iPad.xib - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 632 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/MainWindow.xib - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 376 - - - CF$UID - 377 - - - CF$UID - 378 - - - CF$UID - 379 - - - NS.objects - - - CF$UID - 634 - - - CF$UID - 635 - - - CF$UID - 637 - - - CF$UID - 638 - - - - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 636 - - - - 8 - IBStructureViewController - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 383 - - - CF$UID - 384 - - - NS.objects - - - CF$UID - 639 - - - CF$UID - 640 - - - - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 641 - - - CF$UID - 642 - - - CF$UID - 636 - - - - 325 - 11 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 376 - - - CF$UID - 377 - - - CF$UID - 378 - - - CF$UID - 379 - - - NS.objects - - - CF$UID - 644 - - - CF$UID - 647 - - - CF$UID - 379 - - - CF$UID - 649 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 645 - - - NS.objects - - - CF$UID - 646 - - - - LastKnownOutlineViewWidth - 270 - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 648 - - - - 252 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 383 - - - CF$UID - 384 - - - NS.objects - - - CF$UID - 385 - - - CF$UID - 650 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 651 - - - - 170 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 653 - - - NS.objects - - - CF$UID - 655 - - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 654 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Info.plist - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 546 - - - CF$UID - 547 - - - CF$UID - 548 - - - NS.objects - - - CF$UID - 381 - - - CF$UID - 656 - - - CF$UID - 657 - - - - - $class - - CF$UID - 552 - - NS.objects - - - {{0, 0}, {880, 547}} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 659 - - - CF$UID - 661 - - - NS.objects - - - CF$UID - 663 - - - CF$UID - 688 - - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 660 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Doom.xcodeproj/ - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 662 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/Doom.xcodeproj/ - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 664 - - - CF$UID - 665 - - - CF$UID - 666 - - - CF$UID - 667 - - - CF$UID - 668 - - - CF$UID - 669 - - - NS.objects - - - CF$UID - 670 - - - CF$UID - 671 - - - CF$UID - 677 - - - CF$UID - 678 - - - CF$UID - 686 - - - CF$UID - 687 - - - - Xcode3ProjectEditorPreviousProjectEditorClass - Xcode3ProjectEditor.sourceList.splitview - Xcode3ProjectEditorPreviousTargetEditorClass - Xcode3ProjectEditorSelectedDocumentLocations - Xcode3ProjectEditor_Xcode3ProjectInfoEditor - Xcode3ProjectEditor_Xcode3TargetEditor - Xcode3ProjectInfoEditor - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 283 - - - NS.objects - - - CF$UID - 672 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 673 - - - CF$UID - 675 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 674 - - - - 170 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 286 - - - CF$UID - 287 - - - NS.objects - - - CF$UID - 323 - - - CF$UID - 676 - - - - 710 - Xcode3TargetEditor - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 679 - - - - - $class - - CF$UID - 685 - - documentURL - - CF$UID - 680 - - selection - - CF$UID - 682 - - timestamp - - CF$UID - 681 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Doom.xcodeproj/ - 333652380.06829602 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 683 - - - CF$UID - 684 - - - NS.objects - - - CF$UID - 256 - - - CF$UID - 670 - - - - Project - Editor - - $classes - - Xcode3ProjectDocumentLocation - DVTDocumentLocation - NSObject - - $classname - Xcode3ProjectDocumentLocation - - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 42 - - NS.keys - - NS.objects - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 689 - - - CF$UID - 690 - - - CF$UID - 691 - - - CF$UID - 692 - - - NS.objects - - - CF$UID - 693 - - - CF$UID - 694 - - - CF$UID - 700 - - - CF$UID - 701 - - - - Xcode3ProjectEditorPreviousProjectEditorClass - Xcode3ProjectEditor.sourceList.splitview - Xcode3ProjectEditorPreviousTargetEditorClass - Xcode3ProjectEditorSelectedDocumentLocations - Xcode3ProjectInfoEditor - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 31 - - - NS.objects - - - CF$UID - 695 - - - - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 696 - - - CF$UID - 698 - - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 36 - - - CF$UID - 697 - - - - 170 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 34 - - - CF$UID - 35 - - - NS.objects - - - CF$UID - 36 - - - CF$UID - 699 - - - - 710 - Xcode3TargetEditor - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 702 - - - - - $class - - CF$UID - 685 - - documentURL - - CF$UID - 703 - - selection - - CF$UID - 705 - - timestamp - - CF$UID - 704 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/Doom.xcodeproj/ - 336002240.356359 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 706 - - - CF$UID - 707 - - - NS.objects - - - CF$UID - 708 - - - CF$UID - 709 - - - - Project - Editor - Doom - Xcode3ProjectInfoEditor - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 711 - - - CF$UID - 713 - - - CF$UID - 715 - - - CF$UID - 717 - - - CF$UID - 719 - - - CF$UID - 721 - - - CF$UID - 723 - - - CF$UID - 725 - - - CF$UID - 727 - - - CF$UID - 729 - - - CF$UID - 731 - - - CF$UID - 733 - - - CF$UID - 735 - - - CF$UID - 737 - - - CF$UID - 739 - - - CF$UID - 741 - - - CF$UID - 743 - - - CF$UID - 745 - - - CF$UID - 747 - - - CF$UID - 749 - - - CF$UID - 751 - - - CF$UID - 753 - - - CF$UID - 755 - - - CF$UID - 757 - - - CF$UID - 759 - - - CF$UID - 761 - - - CF$UID - 763 - - - CF$UID - 765 - - - CF$UID - 767 - - - CF$UID - 769 - - - CF$UID - 771 - - - CF$UID - 773 - - - CF$UID - 775 - - - CF$UID - 777 - - - CF$UID - 778 - - - CF$UID - 780 - - - CF$UID - 782 - - - CF$UID - 784 - - - CF$UID - 786 - - - CF$UID - 788 - - - CF$UID - 790 - - - CF$UID - 792 - - - CF$UID - 794 - - - CF$UID - 796 - - - CF$UID - 798 - - - CF$UID - 800 - - - CF$UID - 802 - - - CF$UID - 804 - - - CF$UID - 806 - - - CF$UID - 808 - - - CF$UID - 810 - - - CF$UID - 812 - - - CF$UID - 814 - - - CF$UID - 816 - - - CF$UID - 818 - - - CF$UID - 820 - - - CF$UID - 822 - - - CF$UID - 824 - - - CF$UID - 826 - - - CF$UID - 828 - - - CF$UID - 830 - - - CF$UID - 832 - - - CF$UID - 834 - - - CF$UID - 836 - - - CF$UID - 838 - - - CF$UID - 840 - - - NS.objects - - - CF$UID - 842 - - - CF$UID - 845 - - - CF$UID - 849 - - - CF$UID - 853 - - - CF$UID - 857 - - - CF$UID - 861 - - - CF$UID - 865 - - - CF$UID - 869 - - - CF$UID - 873 - - - CF$UID - 877 - - - CF$UID - 880 - - - CF$UID - 884 - - - CF$UID - 888 - - - CF$UID - 892 - - - CF$UID - 896 - - - CF$UID - 900 - - - CF$UID - 904 - - - CF$UID - 908 - - - CF$UID - 912 - - - CF$UID - 915 - - - CF$UID - 918 - - - CF$UID - 922 - - - CF$UID - 926 - - - CF$UID - 930 - - - CF$UID - 934 - - - CF$UID - 938 - - - CF$UID - 942 - - - CF$UID - 946 - - - CF$UID - 949 - - - CF$UID - 953 - - - CF$UID - 957 - - - CF$UID - 961 - - - CF$UID - 965 - - - CF$UID - 969 - - - CF$UID - 972 - - - CF$UID - 976 - - - CF$UID - 980 - - - CF$UID - 983 - - - CF$UID - 987 - - - CF$UID - 991 - - - CF$UID - 995 - - - CF$UID - 999 - - - CF$UID - 1003 - - - CF$UID - 1007 - - - CF$UID - 1011 - - - CF$UID - 1015 - - - CF$UID - 1019 - - - CF$UID - 1023 - - - CF$UID - 1026 - - - CF$UID - 1030 - - - CF$UID - 1032 - - - CF$UID - 1036 - - - CF$UID - 1040 - - - CF$UID - 1044 - - - CF$UID - 1048 - - - CF$UID - 1052 - - - CF$UID - 1056 - - - CF$UID - 1060 - - - CF$UID - 1064 - - - CF$UID - 1068 - - - CF$UID - 1072 - - - CF$UID - 1076 - - - CF$UID - 1080 - - - CF$UID - 1084 - - - CF$UID - 1088 - - - CF$UID - 1092 - - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 712 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/libtess/dict-list.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 714 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/ipak.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 716 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UIFontLabel.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 718 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UIFontButton.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 720 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UIFontButton.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 722 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/SettingsMenuView.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 724 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UICustomSwitch.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 726 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_doom.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 728 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_async.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 730 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/GenericMenuView.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 732 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/GenericMenuView.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 734 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/EAGLView.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 736 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_loop.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 738 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_menus.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 740 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/IBGlue.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 742 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/cvar.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 744 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/ControlsMenuView.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 746 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/iphone_menus.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 748 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/prboom/sounds.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 750 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/prboom/st_lib.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 752 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/doomAppDelegate.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 754 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UICustomSlider.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 756 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_render.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 758 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_start.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 760 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/doomiphone.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 762 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/BackgroundMusic.cpp - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 764 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/MapMenuView.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 766 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/ControlsMenuView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 768 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/ControlsMenuView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 770 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/misc.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 772 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UICustomSlider.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 774 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/doom_Prefix.pch - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 776 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/SettingsMenuView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 123 - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 779 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/iphone_mapSelect.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 781 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_mapSelect.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 783 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/iphone_net.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 785 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_net.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 787 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UIFontLabel.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 789 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/gles_glue.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 791 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_email.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 793 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/MenuViewController.mm - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 795 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_main.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 797 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/prboomInterface.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 799 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/gles_glue.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 801 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/MainMenuView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 803 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/MainMenuView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 805 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/MainMenuView.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 807 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/MainMenuView.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 809 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/GenericMenuView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 811 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_email.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 813 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/cvar.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 815 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/GenericMenuView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 817 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/MapMenuView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 819 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_sys.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 821 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/IBGlue.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 823 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/ipak.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 825 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/cmd.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 827 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/MenuViewController.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 829 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UICustomSwitch.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 831 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/hud.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 833 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/iphone_sound.c - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 835 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/main.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 837 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/misc.h - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 839 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/EAGLView.m - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 841 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/doomAppDelegate.m - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 843 - - - CF$UID - 844 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 336002591.99091798 - {0, 1815} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 846 - - - CF$UID - 847 - - - CF$UID - 57 - - - CF$UID - 848 - - - - 336003283.39560902 - {0, 1267} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 850 - - - CF$UID - 851 - - - CF$UID - 57 - - - CF$UID - 852 - - - - 336003525.233962 - {0, 552} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 854 - - - CF$UID - 855 - - - CF$UID - 57 - - - CF$UID - 856 - - - - 336003519.47071499 - {0, 1185} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 858 - - - CF$UID - 859 - - - CF$UID - 57 - - - CF$UID - 860 - - - - 336003516.85570198 - {0, 826} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 862 - - - CF$UID - 863 - - - CF$UID - 57 - - - CF$UID - 864 - - - - 336003494.41240001 - {0, 1203} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 866 - - - CF$UID - 867 - - - CF$UID - 57 - - - CF$UID - 868 - - - - 336003527.667539 - {0, 486} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 870 - - - CF$UID - 871 - - - CF$UID - 57 - - - CF$UID - 872 - - - - 336003200.256679 - {0, 1259} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 874 - - - CF$UID - 875 - - - CF$UID - 57 - - - CF$UID - 876 - - - - 336003173.69523603 - {0, 1222} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 878 - - - CF$UID - 879 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 333399353.99927002 - {0, 354} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 881 - - - CF$UID - 882 - - - CF$UID - 57 - - - CF$UID - 883 - - - - 336003484.86052102 - {0, 1066} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 885 - - - CF$UID - 886 - - - CF$UID - 57 - - - CF$UID - 887 - - - - 336003316.226161 - {0, 1501} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 889 - - - CF$UID - 890 - - - CF$UID - 57 - - - CF$UID - 891 - - - - 336003208.41365898 - {0, 1390} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 893 - - - CF$UID - 894 - - - CF$UID - 57 - - - CF$UID - 895 - - - - 336003258.69106299 - {0, 1620} - {6, 65} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 897 - - - CF$UID - 898 - - - CF$UID - 57 - - - CF$UID - 899 - - - - 336003514.40766299 - {0, 470} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 901 - - - CF$UID - 902 - - - CF$UID - 57 - - - CF$UID - 903 - - - - 336003416.012914 - {0, 1285} - {155, 670} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 905 - - - CF$UID - 906 - - - CF$UID - 57 - - - CF$UID - 907 - - - - 336003502.03982198 - {0, 1152} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 909 - - - CF$UID - 910 - - - CF$UID - 57 - - - CF$UID - 911 - - - - 333326121.00765198 - {3309, 1668} - {4660, 21} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 913 - - - CF$UID - 914 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 336003567.55591202 - {0, 1564} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 916 - - - CF$UID - 917 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 336003572.93805498 - {0, 1645} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 919 - - - CF$UID - 920 - - - CF$UID - 57 - - - CF$UID - 921 - - - - 336003357.127424 - {0, 1590} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 923 - - - CF$UID - 924 - - - CF$UID - 57 - - - CF$UID - 925 - - - - 336003482.49308699 - {0, 695} - {437, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 927 - - - CF$UID - 928 - - - CF$UID - 57 - - - CF$UID - 929 - - - - 336003221.67643201 - {0, 1261} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 931 - - - CF$UID - 932 - - - CF$UID - 57 - - - CF$UID - 933 - - - - 336003161.09867799 - {0, 1193} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 935 - - - CF$UID - 936 - - - CF$UID - 57 - - - CF$UID - 937 - - - - 336003299.121907 - {0, 1239} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 939 - - - CF$UID - 940 - - - CF$UID - 57 - - - CF$UID - 941 - - - - 336003342.73242998 - {0, 1338} - {71, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 943 - - - CF$UID - 944 - - - CF$UID - 57 - - - CF$UID - 945 - - - - 336003492.168419 - {0, 1326} - {399, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 947 - - - CF$UID - 948 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 333565450.35472602 - {0, 1464} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 950 - - - CF$UID - 951 - - - CF$UID - 57 - - - CF$UID - 952 - - - - 336003563.90690303 - {0, 1289} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 954 - - - CF$UID - 955 - - - CF$UID - 57 - - - CF$UID - 956 - - - - 336003378.00827402 - {0, 1252} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 958 - - - CF$UID - 959 - - - CF$UID - 57 - - - CF$UID - 960 - - - - 336003479.89460802 - {0, 427} - {0, 341} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 962 - - - CF$UID - 963 - - - CF$UID - 57 - - - CF$UID - 964 - - - - 336003361.18302101 - {0, 977} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 966 - - - CF$UID - 967 - - - CF$UID - 57 - - - CF$UID - 968 - - - - 336003496.61318702 - {0, 1030} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 970 - - - CF$UID - 971 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 336003577.773956 - {0, 1681} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 973 - - - CF$UID - 974 - - - CF$UID - 57 - - - CF$UID - 975 - - - - 333326166.33271098 - {11410, 1723} - {12411, 92} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 977 - - - CF$UID - 978 - - - CF$UID - 57 - - - CF$UID - 979 - - - - 336003233.81921899 - {0, 1388} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 981 - - - CF$UID - 982 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 333326077.15981197 - {0, 1833} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 984 - - - CF$UID - 985 - - - CF$UID - 57 - - - CF$UID - 986 - - - - 336003255.64048398 - {0, 1254} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 988 - - - CF$UID - 989 - - - CF$UID - 57 - - - CF$UID - 990 - - - - 336003522.09041798 - {0, 426} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 992 - - - CF$UID - 993 - - - CF$UID - 57 - - - CF$UID - 994 - - - - 336003326.633205 - {0, 1169} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 996 - - - CF$UID - 997 - - - CF$UID - 57 - - - CF$UID - 998 - - - - 336003137.50509799 - {0, 1347} - {71, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1000 - - - CF$UID - 1001 - - - CF$UID - 57 - - - CF$UID - 1002 - - - - 336003506.68427998 - {0, 654} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1004 - - - CF$UID - 1005 - - - CF$UID - 57 - - - CF$UID - 1006 - - - - 336003193.205217 - {0, 1509} - {7, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1008 - - - CF$UID - 1009 - - - CF$UID - 57 - - - CF$UID - 1010 - - - - 336003275.90984899 - {0, 1275} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1012 - - - CF$UID - 1013 - - - CF$UID - 57 - - - CF$UID - 1014 - - - - 336003322.496683 - {0, 1383} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 1016 - - - CF$UID - 1017 - - - CF$UID - 57 - - - CF$UID - 1018 - - - - 333326321.58882499 - {664, 1881} - {5662, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1020 - - - CF$UID - 1021 - - - CF$UID - 57 - - - CF$UID - 1022 - - - - 336003511.77923 - {0, 799} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 1024 - - - CF$UID - 1025 - - - CF$UID - 57 - - - CF$UID - 163 - - - - 333325963.820427 - {0, 1403} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1027 - - - CF$UID - 1028 - - - CF$UID - 57 - - - CF$UID - 1029 - - - - 336003509.58842301 - {0, 853} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 260 - - - CF$UID - 261 - - - CF$UID - 262 - - - CF$UID - 263 - - - NS.objects - - - CF$UID - 1031 - - - CF$UID - 265 - - - CF$UID - 57 - - - CF$UID - 266 - - - - 333326387.39224499 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1033 - - - CF$UID - 1034 - - - CF$UID - 57 - - - CF$UID - 1035 - - - - 336003149.90180397 - {0, 995} - {71, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1037 - - - CF$UID - 1038 - - - CF$UID - 57 - - - CF$UID - 1039 - - - - 336003397.06169999 - {0, 1313} - {72, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1041 - - - CF$UID - 1042 - - - CF$UID - 57 - - - CF$UID - 1043 - - - - 336003487.35798699 - {0, 1067} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1045 - - - CF$UID - 1046 - - - CF$UID - 57 - - - CF$UID - 1047 - - - - 336003489.78055602 - {0, 1560} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1049 - - - CF$UID - 1050 - - - CF$UID - 57 - - - CF$UID - 1051 - - - - 336003264.69425899 - {0, 1221} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1053 - - - CF$UID - 1054 - - - CF$UID - 57 - - - CF$UID - 1055 - - - - 336003478.49769199 - {0, 528} - {118, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1057 - - - CF$UID - 1058 - - - CF$UID - 57 - - - CF$UID - 1059 - - - - 336003290.63301599 - {0, 1533} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1061 - - - CF$UID - 1062 - - - CF$UID - 57 - - - CF$UID - 1063 - - - - 336003390.44503701 - {0, 1172} - {71, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1065 - - - CF$UID - 1066 - - - CF$UID - 57 - - - CF$UID - 1067 - - - - 336003504.46932298 - {0, 466} - {345, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1069 - - - CF$UID - 1070 - - - CF$UID - 57 - - - CF$UID - 1071 - - - - 336003551.24057001 - {0, 818} - {423, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1073 - - - CF$UID - 1074 - - - CF$UID - 57 - - - CF$UID - 1075 - - - - 336003304.231143 - {0, 1225} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1077 - - - CF$UID - 1078 - - - CF$UID - 57 - - - CF$UID - 1079 - - - - 336003244.964001 - {0, 1299} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1081 - - - CF$UID - 1082 - - - CF$UID - 57 - - - CF$UID - 1083 - - - - 336003347.623909 - {0, 1316} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1085 - - - CF$UID - 1086 - - - CF$UID - 57 - - - CF$UID - 1087 - - - - 336003369.09020603 - {0, 1565} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1089 - - - CF$UID - 1090 - - - CF$UID - 57 - - - CF$UID - 1091 - - - - 336003311.73046899 - {0, 1137} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 157 - - - CF$UID - 158 - - - CF$UID - 159 - - - CF$UID - 160 - - - NS.objects - - - CF$UID - 1093 - - - CF$UID - 1094 - - - CF$UID - 57 - - - CF$UID - 1095 - - - - 336003352.91726798 - {0, 1342} - {69, 0} - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1097 - - - NS.objects - - - CF$UID - 1099 - - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1098 - - - x-xcode-log://DFDD5CA1-7D47-4609-9C5C-B32E826175D7 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1100 - - - NS.objects - - - CF$UID - 381 - - - - SelectedDocumentLocations - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1102 - - - CF$UID - 1104 - - - CF$UID - 1106 - - - CF$UID - 1108 - - - CF$UID - 1110 - - - NS.objects - - - CF$UID - 1112 - - - CF$UID - 1118 - - - CF$UID - 1123 - - - CF$UID - 1128 - - - CF$UID - 1133 - - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1103 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Doom_icon.png - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1105 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/DOOM_57.png - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1107 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Default.png - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1109 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/DOOM_72.png - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1111 - - - - $class - - CF$UID - 124 - - NS.string - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/DOOM_114.png - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1100 - - - NS.objects - - - CF$UID - 1113 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 1114 - - - - - $class - - CF$UID - 1117 - - IDEQuickLookPageNumber - - CF$UID - 28 - - documentURL - - CF$UID - 1115 - - timestamp - - CF$UID - 1116 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Doom_icon.png - 333323936.54352701 - - $classes - - IDEQuickLookDocumentLocation - DVTDocumentLocation - NSObject - - $classname - IDEQuickLookDocumentLocation - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1100 - - - NS.objects - - - CF$UID - 1119 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 1120 - - - - - $class - - CF$UID - 1117 - - IDEQuickLookPageNumber - - CF$UID - 28 - - documentURL - - CF$UID - 1121 - - timestamp - - CF$UID - 1122 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/DOOM_57.png - 333323944.43125302 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1100 - - - NS.objects - - - CF$UID - 1124 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 1125 - - - - - $class - - CF$UID - 1117 - - IDEQuickLookPageNumber - - CF$UID - 28 - - documentURL - - CF$UID - 1126 - - timestamp - - CF$UID - 1127 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/Default.png - 333578761.91734701 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1100 - - - NS.objects - - - CF$UID - 1129 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 1130 - - - - - $class - - CF$UID - 1117 - - IDEQuickLookPageNumber - - CF$UID - 28 - - documentURL - - CF$UID - 1131 - - timestamp - - CF$UID - 1132 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/DOOM_72.png - 333323919.06361401 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1100 - - - NS.objects - - - CF$UID - 1134 - - - - - $class - - CF$UID - 16 - - NS.objects - - - CF$UID - 1135 - - - - - $class - - CF$UID - 1117 - - IDEQuickLookPageNumber - - CF$UID - 28 - - documentURL - - CF$UID - 1136 - - timestamp - - CF$UID - 1137 - - - file://localhost/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/code/iphone/DOOM_114.png - 333323919.79163003 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1139 - - - CF$UID - 1140 - - - NS.objects - - - CF$UID - 1141 - - - CF$UID - 1142 - - - - IDEDeviceLocation - IDEDeviceArchitecture - dvtdevice-iphone:2826d1c37988eed0d2318d50b590ecba088e5c32 - armv7 - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1144 - - - NS.objects - - - CF$UID - 1145 - - - - IDENameString - Doom - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1147 - - - CF$UID - 1148 - - - CF$UID - 1149 - - - NS.objects - - - CF$UID - 1150 - - - CF$UID - 1175 - - - CF$UID - 1157 - - - - IDEActivityReportCompletionSummaryStringSegments - IDEActivityReportOptions - IDEActivityReportTitle - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 1151 - - - CF$UID - 1158 - - - CF$UID - 1161 - - - CF$UID - 1166 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1152 - - - CF$UID - 1153 - - - CF$UID - 1154 - - - NS.objects - - - CF$UID - 1155 - - - CF$UID - 1156 - - - CF$UID - 1157 - - - - IDEActivityReportStringSegmentPriority - IDEActivityReportStringSegmentBackSeparator - IDEActivityReportStringSegmentStringValue - 2 - - Archive - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1152 - - - CF$UID - 1153 - - - CF$UID - 1154 - - - NS.objects - - - CF$UID - 1159 - - - CF$UID - 1160 - - - CF$UID - 256 - - - - 4 - : - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1152 - - - CF$UID - 1153 - - - CF$UID - 1154 - - - NS.objects - - - CF$UID - 1162 - - - CF$UID - 1163 - - - CF$UID - 1164 - - - - 1 - │ - - $class - - CF$UID - 1165 - - NS.data - - YnBsaXN0MDDUAQIDBAUGOzxYJHZlcnNpb25YJG9iamVjdHNZJGFy - Y2hpdmVyVCR0b3ASAAGGoK0HCA8QGhscJCUrMTQ3VSRudWxs0wkK - CwwNDlxOU0F0dHJpYnV0ZXNWJGNsYXNzWE5TU3RyaW5ngAOADIAC - WVN1Y2NlZWRlZNMKERITFBdXTlMua2V5c1pOUy5vYmplY3RzgAui - FRaABIAFohgZgAaACVZOU0ZvbnRXTlNDb2xvctQKHR4fICEiI1ZO - U05hbWVWTlNTaXplWE5TZkZsYWdzgAiAByNAJgAAAAAAABENEF8Q - EUx1Y2lkYUdyYW5kZS1Cb2xk0iYnKClaJGNsYXNzbmFtZVgkY2xh - c3Nlc1ZOU0ZvbnSiKCpYTlNPYmplY3TTCiwtLi8wXE5TQ29sb3JT - cGFjZVdOU1doaXRlgAoQA0IwANImJzIzV05TQ29sb3KiMirSJic1 - NlxOU0RpY3Rpb25hcnmiNSrSJic4OV8QEk5TQXR0cmlidXRlZFN0 - cmluZ6I6Kl8QEk5TQXR0cmlidXRlZFN0cmluZ18QD05TS2V5ZWRB - cmNoaXZlctE9PlRyb290gAEACAARABoAIwAtADIANwBFAEsAUgBf - AGYAbwBxAHMAdQB/AIYAjgCZAJsAngCgAKIApQCnAKkAsAC4AMEA - yADPANgA2gDcAOUA6AD8AQEBDAEVARwBHwEoAS8BPAFEAUYBSAFL - AVABWAFbAWABbQFwAXUBigGNAaIBtAG3AbwAAAAAAAACAQAAAAAA - AAA/AAAAAAAAAAAAAAAAAAABvg== - - - - $classes - - NSMutableData - NSData - NSObject - - $classname - NSMutableData - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1152 - - - CF$UID - 1167 - - - CF$UID - 1168 - - - CF$UID - 1154 - - - CF$UID - 1169 - - - CF$UID - 1170 - - - NS.objects - - - CF$UID - 1171 - - - CF$UID - 80 - - - CF$UID - 1172 - - - CF$UID - 1174 - - - CF$UID - 80 - - - CF$UID - 80 - - - - IDEActivityReportStringSegmentType - IDEActivityReportStringSegmentDate - IDEActivityReportStringSegmentDateStyle - IDEActivityReportStringSegmentTimeStyle - 3 - - $class - - CF$UID - 1173 - - NS.time - 333652063.56631202 - - - $classes - - NSDate - NSObject - - $classname - NSDate - - 7/29/11 at 12:07 PM - 106 - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 2 - - - - - $class - - CF$UID - 42 - - NS.keys - - - CF$UID - 1178 - - - CF$UID - 1179 - - - CF$UID - 1180 - - - CF$UID - 1181 - - - NS.objects - - - CF$UID - 1182 - - - CF$UID - 1187 - - - CF$UID - 1190 - - - CF$UID - 1193 - - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 391 - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 270 - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 469 - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 556 - - - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 1183 - - - CF$UID - 1184 - - - NS.objects - - - CF$UID - 1185 - - - CF$UID - 1186 - - - - width - height - 600 - 600 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 1183 - - - CF$UID - 1184 - - - NS.objects - - - CF$UID - 1188 - - - CF$UID - 1189 - - - - 600 - 600 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 1183 - - - CF$UID - 1184 - - - NS.objects - - - CF$UID - 1191 - - - CF$UID - 1192 - - - - 600 - 600 - - $class - - CF$UID - 38 - - NS.keys - - - CF$UID - 1183 - - - CF$UID - 1184 - - - NS.objects - - - CF$UID - 1194 - - - CF$UID - 1195 - - - - 600 - 600 - - $class - - CF$UID - 41 - - NS.objects - - - CF$UID - 1197 - - - CF$UID - 1199 - - - CF$UID - 1201 - - - CF$UID - 1203 - - - CF$UID - 1205 - - - CF$UID - 1207 - - - CF$UID - 1209 - - - CF$UID - 1211 - - - CF$UID - 1213 - - - CF$UID - 1215 - - - - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1198 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/prboom/st_stuff.c - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1200 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/prboom/st_lib.c - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1202 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/prboom/sounds.c - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1204 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/ControlsMenuView.m - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1206 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UICustomSwitch.m - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1208 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UICustomSwitch.h - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1210 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UIFontLabel.m - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1212 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UIFontLabel.h - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1214 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UIFontButton.m - - $class - - CF$UID - 167 - - NS.base - - CF$UID - 0 - - NS.relative - - CF$UID - 1216 - - - file://localhost/Users/jeff.farrand/Desktop/DoomClassicDepot/code/iphone/UIFontButton.h - - $top - - State - - CF$UID - 1 - - - $version - 100000 - - diff --git a/code/iphone/Doom.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist b/code/iphone/Doom.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist deleted file mode 100644 index 0696102..0000000 --- a/code/iphone/Doom.xcodeproj/xcuserdata/jeff.farrand.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - diff --git a/code/iphone/Doom_App.h b/code/iphone/Doom_App.h new file mode 100755 index 0000000..88e491f --- /dev/null +++ b/code/iphone/Doom_App.h @@ -0,0 +1,26 @@ +/* + + Copyright (C) 2009 Id Software, Inc. + + 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 "iphone_delegate.h" + + + + +@interface DoomApp : iphoneApp + +@end diff --git a/code/iphone/Doom_App.m b/code/iphone/Doom_App.m new file mode 100755 index 0000000..50e4dfc --- /dev/null +++ b/code/iphone/Doom_App.m @@ -0,0 +1,48 @@ +/* + + Copyright (C) 2009 Id Software, Inc. + + 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. + */ + +#import "Doom_App.h" +#import "MainMenuViewController.h" +#import "MainNavController.h" +#include "doomiphone.h" + +@implementation DoomApp + +- (void) InitializeInterfaceBuilder { + + // Create the Main Menu View controller. + +// Doom_MainMenuViewController *rootController = nil; +// rootController = [[Doom_MainMenuViewController alloc] initWithNibName:@"MainMenuView" bundle:nil]; + + NSLog(@"width: %f height: %f", [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height); + Doom_MainMenuViewController *rootController = [[Doom_MainMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"MainMenuView"] bundle:nil]; + + // Create a Navigation Controller for Pushing/Popping Views. + navigationController = [[MainNavController alloc] initWithRootViewController:rootController]; + [navigationController setNavigationBarHidden:YES]; + [rootController release]; + + // Create the OpenGLView so that our context is created. Don't push it on yet though. + openGLViewController = [ [ iphone_glViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"OpenGLView"] bundle:nil ]; + + [ openGLViewController StopDisplay]; +} + +@end diff --git a/code/iphone/EAGLView.h b/code/iphone/EAGLView.h old mode 100644 new mode 100755 index 3847aa3..82b190a --- a/code/iphone/EAGLView.h +++ b/code/iphone/EAGLView.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -41,8 +41,8 @@ Note that setting the view non-opaque will only work if the EAGL surface has an /* The pixel dimensions of the backbuffer */ GLint backingWidth; GLint backingHeight; - - } +- (void) Initialize; + @end diff --git a/code/iphone/EAGLView.m b/code/iphone/EAGLView.m old mode 100644 new mode 100755 index 811256b..7f6ae70 --- a/code/iphone/EAGLView.m +++ b/code/iphone/EAGLView.m @@ -1,5 +1,12 @@ +// +// EAGLView.m +// Doom +// +// Created by Cass Everitt on 2/20/09. +// Copyright Id Software 2009. All rights reserved. +// /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -25,7 +32,6 @@ #import #import "EAGLView.h" -#import "doomAppDelegate.h" #include "doomiphone.h" @@ -45,15 +51,15 @@ + (Class)layerClass { CAEAGLLayer *eaglLayer; -//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder: -- (id)initWithCoder:(NSCoder*)coder { - self = [super initWithCoder:coder]; - +- (void) Initialize { + eaglview = self; // allow multiple touch events - self.multipleTouchEnabled = true; - +#if !TARGET_OS_TV + self.multipleTouchEnabled = true; +#endif + // Double the resolution on iPhone 4. if ( [[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [self respondsToSelector:@selector(setContentScaleFactor:)] ) { @@ -88,7 +94,7 @@ - (id)initWithCoder:(NSCoder*)coder { if ( ![EAGLContext setCurrentContext:context]) { [self release]; - return nil; + return; } glGenFramebuffersOES(1, &mViewFramebuffer); @@ -105,8 +111,9 @@ - (id)initWithCoder:(NSCoder*)coder { glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); - displaywidth = backingHeight; - displayheight = backingWidth; + /* JDS proper fix for landscape orientation */ + displaywidth = backingWidth; + displayheight = backingHeight; glGenRenderbuffersOES(1, &mDepthRenderbuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, mDepthRenderbuffer); @@ -122,6 +129,22 @@ - (id)initWithCoder:(NSCoder*)coder { assert( 0 ); } + return; +} + +- (id) initWithCoder:(NSCoder *)aCoder{ + + if(self = [super initWithCoder:aCoder] ) { + [self Initialize]; + } + + return self; +} + +- (id) initWithFrame:(CGRect)rect{ + if(self = [super initWithFrame:rect] ) { + [self Initialize]; + } return self; } @@ -133,30 +156,21 @@ - (void) handleTouches:(UIEvent*)event { memset( touchThisSequence, 0, sizeof( touchThisSequence ) ); - NSSet *touches = [event allTouches]; + NSSet *theTouches = [event allTouches]; // printf( "count: %i\n", [touches count] ); - - // lock the game out temporarily - pthread_mutex_lock( &eventMutex ); - for (UITouch *myTouch in touches) + for (UITouch *myTouch in theTouches) { - CGPoint touchLocation = [myTouch locationInView:nil]; + CGPoint touchLocation = [myTouch locationInView:self]; // Scale Touches with the screen resolution. touchLocation.x *= screenResolutionScale; touchLocation.y *= screenResolutionScale; - // handle landscape mode and flipping - int x, y; - if ( revLand->value ) { - x = touchLocation.y; - y = ( displayheight - 1 ) - touchLocation.x; - } else { - x = ( displaywidth - 1) - touchLocation.y; - y = touchLocation.x; - } -// printf( "%i, %i\n", x, y ); + const int x = touchLocation.x; + const int y = touchLocation.y; + // JDS Debug + //printf( "%i, %i\n", x, y ); touchCount++; @@ -271,30 +285,31 @@ - (void) handleTouches:(UIEvent*)event { } } - // the game is free to copy the touches now - pthread_mutex_unlock( &eventMutex ); - previousTouchCount = touchCount; } -- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { -// printf( "touchesBegan\n" ); +- (void) touchesBegan:(NSSet*)touchSet withEvent:(UIEvent*)event { + (void)touchSet; + [self handleTouches:event]; } -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { -// printf( "touchesMoved\n" ); +- (void)touchesMoved:(NSSet *)touchSet withEvent:(UIEvent *)event { + (void)touchSet; + [self handleTouches:event]; } -- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { -// printf( "touchesEnded\n" ); +- (void) touchesEnded:(NSSet*)touchSet withEvent:(UIEvent*)event { + (void)touchSet; + [self handleTouches:event]; } -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { -// printf( "touchesCancelled\n" ); +- (void)touchesCancelled:(NSSet *)touchSet withEvent:(UIEvent *)event { + (void)touchSet; + [self handleTouches:event]; } @@ -309,6 +324,8 @@ @implementation EAGLView (UITextFieldDelegate) - (BOOL)textFieldShouldReturn:(UITextField *)_textField { + (void)_textField; + if ( eaglview->textField == nil ) { return YES; } @@ -317,9 +334,6 @@ - (BOOL)textFieldShouldReturn:(UITextField *)_textField // thread, so fetch the line and the game will catch it next time // around - // lock the game out temporarily - pthread_mutex_lock( &eventMutex ); - const char *line = [ eaglview->textField.text UTF8String ]; strncpy( consoleCommand, line, sizeof(consoleCommand)-1 ); eaglview->textField.text = [ NSString stringWithUTF8String: "" ]; @@ -329,8 +343,6 @@ - (BOOL)textFieldShouldReturn:(UITextField *)_textField [textField removeFromSuperview]; textField = nil; - // lock the game out temporarily - pthread_mutex_unlock( &eventMutex ); return YES; } @@ -359,20 +371,5 @@ void SysIPhoneSwapBuffers() { } -void SysIPhoneOpenURL( const char *url ) { - Com_Printf( "OpenURL char *: %s\n", url ); - - NSString *nss = [NSString stringWithCString: url encoding: NSASCIIStringEncoding]; - [[UIApplication sharedApplication] openURL:[NSURL URLWithString: nss]]; -} - -void SysIPhoneSetUIKitOrientation( int isLandscapeRight ) { - if ( isLandscapeRight ) { - [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight; - } else { - [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeLeft; - } -} - diff --git a/code/iphone/EpisodeCell-tvos.xib b/code/iphone/EpisodeCell-tvos.xib new file mode 100644 index 0000000..b725faf --- /dev/null +++ b/code/iphone/EpisodeCell-tvos.xib @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/EpisodeCell.xib b/code/iphone/EpisodeCell.xib new file mode 100644 index 0000000..cac9a9d --- /dev/null +++ b/code/iphone/EpisodeCell.xib @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/EpisodeCell~ipad.xib b/code/iphone/EpisodeCell~ipad.xib new file mode 100644 index 0000000..6623565 --- /dev/null +++ b/code/iphone/EpisodeCell~ipad.xib @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/EpisodeMenuView-tvos.xib b/code/iphone/EpisodeMenuView-tvos.xib new file mode 100755 index 0000000..5d332fa --- /dev/null +++ b/code/iphone/EpisodeMenuView-tvos.xib @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/EpisodeMenuView.xib b/code/iphone/EpisodeMenuView.xib new file mode 100755 index 0000000..f2b070e --- /dev/null +++ b/code/iphone/EpisodeMenuView.xib @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/EpisodeMenuViewController.h b/code/iphone/EpisodeMenuViewController.h new file mode 100755 index 0000000..9b76c8e --- /dev/null +++ b/code/iphone/EpisodeMenuViewController.h @@ -0,0 +1,45 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import +#import "../ios/LabelButton.h" + +/* + ================================================================================================ + EpisodeMenuViewController + + ================================================================================================ + */ +@interface Doom_EpisodeMenuViewController : UIViewController { + + IBOutlet UITableView *episodeList; + UITableViewCell* episodeCell; + + int episodeSelection; + IBOutlet idLabelButton * nextButton; + IBOutlet idLabel * nextLabel; +} + +@property (nonatomic, assign) IBOutlet UITableViewCell *episodeCell; + +- (IBAction) BackToMain; +- (IBAction) NextToMissions; + +@end diff --git a/code/iphone/EpisodeMenuViewController.mm b/code/iphone/EpisodeMenuViewController.mm new file mode 100755 index 0000000..495ed13 --- /dev/null +++ b/code/iphone/EpisodeMenuViewController.mm @@ -0,0 +1,314 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "EpisodeMenuViewController.h" +#include "doomiphone.h" +#include "iphone_delegate.h" +#import "MissionMenuViewController.h" + +#if GAME_DOOM + +#define TOTAL_EPISODES 4 + +static const char * const EpisodeNames[TOTAL_EPISODES][4] = { + { "Episode 1", "Knee-Deep in the Dead", "Episode1Background", "Episode1Background_Highlighted" }, + { "Episode 2", "The Shores of Hell", "Episode2Background", "Episode2Background_Highlighted" }, + { "Episode 3", "Inferno", "Episode3Background", "Episode3Background_Highlighted" }, + { "Episode 4", "Thy Flesh Consumed", "Episode4Background", "Episode4Background_Highlighted" } +}; + +#endif + +#if GAME_FINALDOOM + +#define TOTAL_EPISODES 2 + +static const char * const EpisodeNames[TOTAL_EPISODES][4] = { + { "", "TNT: Evilution", "Episode1Background", "Episode1Background_Highlighted" }, + { "", "The Plutonia Experiment", "Episode2Background", "Episode2Background_Highlighted" } +}; + +#endif + + +@interface Doom_EpisodeMenuViewController () + +@property (nonatomic, retain) UITableView *episodeList; + +@end + + +/* + ================================================================================================ + EpisodeMenuViewController + + ================================================================================================ + */ +@implementation Doom_EpisodeMenuViewController + +@synthesize episodeList; +@synthesize episodeCell; + +/* + ======================== + Doom_EpisodeMenuViewController::initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + + episodeSelection = -1; + [ nextButton setEnabled: NO ]; + [ nextLabel setEnabled: NO ]; + + } + return self; +} + +/* + ======================== + Doom_EpisodeMenuViewController::didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +#pragma mark - View lifecycle + +/* + ======================== + Doom_EpisodeMenuViewController::viewDidLoad + ======================== + */ +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view from its nib. + + [ nextButton setEnabled: NO ]; + [ nextLabel setEnabled: NO ]; + + // TODO: Select the current episode. Haven't yet figured out a good way to get the table + // view to load with a default row selected, so for now always select episode 1. +#if !TARGET_OS_TV + int initialEpisode = 0; + NSIndexPath *initialPath = [NSIndexPath indexPathForRow:initialEpisode inSection:0]; + + [self.episodeList selectRowAtIndexPath:initialPath animated:YES scrollPosition:UITableViewScrollPositionNone]; + [self handleSelectionAtIndexPath:initialPath]; + self.episodeList.separatorStyle = UITableViewCellSeparatorStyleNone; +#endif +} + +/* + ======================== + Doom_EpisodeMenuViewController::BackToMain + ======================== + */ +- (IBAction) BackToMain { + + [self.navigationController popViewControllerAnimated:NO]; + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +} + +/* + ======================== + Doom_EpisodeMenuViewController::NextToMissions + ======================== + */ +- (IBAction) NextToMissions { + + Doom_MissionMenuViewController *vc = [[Doom_MissionMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"MissionMenuView"] bundle:nil]; + +#if GAME_FINALDOOM + + if (episodeSelection == 1) { + iphoneIWADSelect("plutonia.wad"); + } else { + iphoneIWADSelect("tnt.wad"); + } + + char full_iwad[1024]; + + I_FindFile( doom_iwad, ".wad", full_iwad ); + + // fall back to default DOOM wad + if( full_iwad[0] == '\0' ) { + I_FindFile( "doom.wad", ".wad", full_iwad ); + if( doom_iwad ) free(doom_iwad); + doom_iwad = strdup(full_iwad); + } else if( strcmp(doom_iwad,full_iwad) != 0 ) { + if( doom_iwad ) free(doom_iwad); + doom_iwad = strdup( full_iwad ); + } + + iphoneDoomStartup(); + +#endif + + [self.navigationController pushViewController:vc animated:NO]; + [vc setEpisode:episodeSelection ]; + [vc release]; + + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +} + +/* + ======================== + + UITableView interface + + ======================== + */ + +- (void)handleSelectionAtIndexPath:(NSIndexPath*)indexPath { + + Cvar_SetValue( episode->name, indexPath.row ); + + [self setCellSelected:YES atIndexPath:indexPath]; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return TOTAL_EPISODES; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *MyIdentifier = @"EpisodeIdentifier"; + UITableViewCell *cell = (UITableViewCell*)[self.episodeList dequeueReusableCellWithIdentifier:MyIdentifier]; + + if (cell == nil) { + //cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease]; + [[NSBundle mainBundle] loadNibNamed:[gAppDelegate GetNibNameForDevice:@"EpisodeCell"] owner:self options:nil]; + + if ( episodeCell == nil ) { + // Couldn't create from nib file, load a default cell. + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease]; + } else { + cell = episodeCell; + self.episodeCell = nil; + + // Save the good label size here before it gets modified by the code below. +// UILabel *episodeNameLabel; +// episodeNameLabel = (UILabel *)[cell viewWithTag:2]; +// +// maximumNameLabelFrame = episodeNameLabel.frame; + } + } + + cell.selectionStyle = UITableViewCellSelectionStyleNone; + + BOOL isCellSelected = ( episode->value == indexPath.row)? YES: NO; + + [self setCellSelected:isCellSelected cell:cell]; + + UILabel *episodeNumberLabel; + episodeNumberLabel = (UILabel *)[cell viewWithTag:1]; + episodeNumberLabel.text = [NSString stringWithCString:EpisodeNames[indexPath.row][0] encoding:NSASCIIStringEncoding]; + + UILabel *episodeNameLabel; + episodeNameLabel = (UILabel *)[cell viewWithTag:2]; + NSString* episodeNameText = [NSString stringWithCString:EpisodeNames[indexPath.row][1] encoding:NSASCIIStringEncoding]; + +// CGSize expectedLabelSize = [episodeNameText boundingRectWithSize:maximumNameLabelFrame.size +// options:NSStringDrawingUsesLineFragmentOrigin +// attributes:@{NSFontAttributeName: episodeNameLabel.font} +// context:nil].size; +// +// //adjust the label the the new height. +// CGRect newFrame = maximumNameLabelFrame; +// newFrame.size.height = expectedLabelSize.height; +// episodeNameLabel.frame = newFrame; + + episodeNameLabel.text = episodeNameText; + + UIImageView* backgroundImage = (UIImageView *)[cell viewWithTag:3]; + + backgroundImage.image = [UIImage imageNamed:[NSString stringWithCString:EpisodeNames[indexPath.row][2] encoding:NSASCIIStringEncoding]]; + backgroundImage.highlightedImage = [UIImage imageNamed:[NSString stringWithCString:EpisodeNames[indexPath.row][3] encoding:NSASCIIStringEncoding]]; + + + cell.backgroundColor = UIColor.clearColor; + + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + + [self handleSelectionAtIndexPath:indexPath]; +} + +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { + [self setCellSelected:NO atIndexPath:indexPath]; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + if (IS_IPAD) { + return 158; + } else if (IS_TV) { + return 185; + } else { + return 79; + } +} + +#if TARGET_OS_TV +- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator { + + [super didUpdateFocusInContext:context withAnimationCoordinator:coordinator]; + + if ([context.nextFocusedView isKindOfClass:[UITableViewCell class]]) { + [coordinator addCoordinatedAnimations:^{ + [context.nextFocusedView setBackgroundColor:[UIColor redColor]]; + [context.previouslyFocusedView setBackgroundColor:[UIColor clearColor]]; + } completion:nil]; + } +} +#endif + +- (void)setCellSelected:(BOOL)selected atIndexPath:(NSIndexPath*)indexPath { + // Get the cell that was selected. + [ nextButton setEnabled: YES ]; + [ nextLabel setEnabled: YES ]; + episodeSelection = (int)indexPath.row; + +#if TARGET_OS_TV + [self NextToMissions]; +#else + UITableViewCell * cell = [episodeList cellForRowAtIndexPath:indexPath]; + [self setCellSelected:selected cell:cell]; +#endif +} + +- (void)setCellSelected:(BOOL)selected cell:(UITableViewCell*)cell { + // Get the "selected" image + UIImageView* selectionFrame = (UIImageView *)[cell viewWithTag:3]; + + // Show the selected image + selectionFrame.highlighted = selected; +} + +@end diff --git a/code/iphone/EpisodeMenuView~ipad.xib b/code/iphone/EpisodeMenuView~ipad.xib new file mode 100755 index 0000000..1ad8039 --- /dev/null +++ b/code/iphone/EpisodeMenuView~ipad.xib @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/FinalDOOM-iOS-Info.plist b/code/iphone/FinalDOOM-iOS-Info.plist new file mode 100755 index 0000000..a030e59 --- /dev/null +++ b/code/iphone/FinalDOOM-iOS-Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + DOOM_57.png + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 2.7 + CFBundleSignature + ???? + CFBundleVersion + 2.7 + LSRequiresIPhoneOS + + UIAppFonts + + idGinzaNar-Md2.otf + + UIFileSharingEnabled + + UIInterfaceOrientation + UIInterfaceOrientationLandscapeLeft + UILaunchStoryboardName + FinalDOOMLaunchScreen + UIPrerenderedIcon + + UIRequiresFullScreen + + UIRequiresPersistentWiFi + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Contents.json b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..0cc2196 --- /dev/null +++ b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-40.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-60.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-58.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-87.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-80.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-120.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-121.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-180.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-41.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-59.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-42.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-81.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-152.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-167.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-1024.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-1024.png new file mode 100755 index 0000000..b0377a2 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-1024.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-120.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-120.png new file mode 100755 index 0000000..ec5d937 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-120.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-121.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-121.png new file mode 100644 index 0000000..ec5d937 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-121.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-152.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-152.png new file mode 100755 index 0000000..ab81d5d Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-152.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-167.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-167.png new file mode 100755 index 0000000..e784e39 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-167.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-180.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-180.png new file mode 100755 index 0000000..2cbbb65 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-180.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-20.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-20.png new file mode 100755 index 0000000..f3fedf5 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-20.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-29.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-29.png new file mode 100755 index 0000000..0e1e43b Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-29.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-40.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-40.png new file mode 100755 index 0000000..2340c64 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-40.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-41.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-41.png new file mode 100644 index 0000000..2340c64 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-41.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-42.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-42.png new file mode 100644 index 0000000..2340c64 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-42.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-58.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-58.png new file mode 100755 index 0000000..ef80cab Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-58.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-59.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-59.png new file mode 100644 index 0000000..ef80cab Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-59.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-60.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-60.png new file mode 100755 index 0000000..f13e7cc Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-60.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-76.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100755 index 0000000..dca1193 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-80.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-80.png new file mode 100755 index 0000000..6d92baa Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-80.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-81.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-81.png new file mode 100644 index 0000000..6d92baa Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-81.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-87.png b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-87.png new file mode 100755 index 0000000..6a6b3fb Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/AppIcon.appiconset/Icon-87.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/Contents.json b/code/iphone/FinalDOOM-iOS.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/FinalDOOM-iOS.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-iOS.xcassets/background.imageset/Contents.json b/code/iphone/FinalDOOM-iOS.xcassets/background.imageset/Contents.json new file mode 100644 index 0000000..1b6e5cd --- /dev/null +++ b/code/iphone/FinalDOOM-iOS.xcassets/background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "finaldoom_background.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-iOS.xcassets/background.imageset/finaldoom_background.png b/code/iphone/FinalDOOM-iOS.xcassets/background.imageset/finaldoom_background.png new file mode 100644 index 0000000..0fa4759 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/background.imageset/finaldoom_background.png differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/fdsplash.imageset/Contents.json b/code/iphone/FinalDOOM-iOS.xcassets/fdsplash.imageset/Contents.json new file mode 100644 index 0000000..cd8a8e0 --- /dev/null +++ b/code/iphone/FinalDOOM-iOS.xcassets/fdsplash.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "finaldoomcover.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-iOS.xcassets/fdsplash.imageset/finaldoomcover.jpg b/code/iphone/FinalDOOM-iOS.xcassets/fdsplash.imageset/finaldoomcover.jpg new file mode 100644 index 0000000..fef13c3 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/fdsplash.imageset/finaldoomcover.jpg differ diff --git a/code/iphone/FinalDOOM-iOS.xcassets/logo.imageset/Contents.json b/code/iphone/FinalDOOM-iOS.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..efca686 --- /dev/null +++ b/code/iphone/FinalDOOM-iOS.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "final_doom_logo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-iOS.xcassets/logo.imageset/final_doom_logo.png b/code/iphone/FinalDOOM-iOS.xcassets/logo.imageset/final_doom_logo.png new file mode 100644 index 0000000..0815005 Binary files /dev/null and b/code/iphone/FinalDOOM-iOS.xcassets/logo.imageset/final_doom_logo.png differ diff --git a/code/iphone/FinalDOOM-tvOS-Info.plist b/code/iphone/FinalDOOM-tvOS-Info.plist new file mode 100644 index 0000000..cfd92bf --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS-Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIAppFonts + + idGinzaNar-Md2.otf + + UIRequiredDeviceCapabilities + + arm64 + + UIUserInterfaceStyle + Automatic + + diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..348d65b --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "finaldoom_tvos_icon_back.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/finaldoom_tvos_icon_back.png b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/finaldoom_tvos_icon_back.png new file mode 100644 index 0000000..7e4d615 Binary files /dev/null and b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/finaldoom_tvos_icon_back.png differ diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..25b250e --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "finaldoom_tvos_icon_front.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/finaldoom_tvos_icon_front.png b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/finaldoom_tvos_icon_front.png new file mode 100644 index 0000000..5113e20 Binary files /dev/null and b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/finaldoom_tvos_icon_front.png differ diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..437f168 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "finaldoom_tvos_icon_middle.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/finaldoom_tvos_icon_middle.png b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/finaldoom_tvos_icon_middle.png new file mode 100644 index 0000000..7e3bdc7 Binary files /dev/null and b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/finaldoom_tvos_icon_middle.png differ diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Contents.json new file mode 100644 index 0000000..2cdcef1 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Contents.json @@ -0,0 +1,35 @@ +{ + "assets" : [ + { + "size" : "1280x768", + "idiom" : "tv", + "filename" : "App Icon - App Store.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "400x240", + "idiom" : "tv", + "filename" : "App Icon.imagestack", + "role" : "primary-app-icon" + }, + { + "filename" : "LaunchImage.launchimage" + }, + { + "size" : "2320x720", + "idiom" : "tv", + "filename" : "Top Shelf Image Wide.imageset", + "role" : "top-shelf-image-wide" + }, + { + "size" : "1920x720", + "idiom" : "tv", + "filename" : "Top Shelf Image.imageset", + "role" : "top-shelf-image" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..1d219b9 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "orientation" : "landscape", + "idiom" : "tv", + "extent" : "full-screen", + "minimum-system-version" : "11.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "tv", + "filename" : "finaldoom_tvos_launch.jpg", + "extent" : "full-screen", + "minimum-system-version" : "9.0", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/finaldoom_tvos_launch.jpg b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/finaldoom_tvos_launch.jpg new file mode 100644 index 0000000..99df758 Binary files /dev/null and b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/finaldoom_tvos_launch.jpg differ diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..d36a0da --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "finaldoom_banner.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/finaldoom_banner.png b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/finaldoom_banner.png new file mode 100644 index 0000000..950d5ef Binary files /dev/null and b/code/iphone/FinalDOOM-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/finaldoom_banner.png differ diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/background.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/background.imageset/Contents.json new file mode 100644 index 0000000..1b6e5cd --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "finaldoom_background.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/background.imageset/finaldoom_background.png b/code/iphone/FinalDOOM-tvOS.xcassets/background.imageset/finaldoom_background.png new file mode 100644 index 0000000..0fa4759 Binary files /dev/null and b/code/iphone/FinalDOOM-tvOS.xcassets/background.imageset/finaldoom_background.png differ diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/logo.imageset/Contents.json b/code/iphone/FinalDOOM-tvOS.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..efca686 --- /dev/null +++ b/code/iphone/FinalDOOM-tvOS.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "final_doom_logo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/FinalDOOM-tvOS.xcassets/logo.imageset/final_doom_logo.png b/code/iphone/FinalDOOM-tvOS.xcassets/logo.imageset/final_doom_logo.png new file mode 100644 index 0000000..0815005 Binary files /dev/null and b/code/iphone/FinalDOOM-tvOS.xcassets/logo.imageset/final_doom_logo.png differ diff --git a/code/iphone/FinalDOOMLaunchScreen.storyboard b/code/iphone/FinalDOOMLaunchScreen.storyboard new file mode 100644 index 0000000..d70f486 --- /dev/null +++ b/code/iphone/FinalDOOMLaunchScreen.storyboard @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/GameController.h b/code/iphone/GameController.h new file mode 100644 index 0000000..59bbbcf --- /dev/null +++ b/code/iphone/GameController.h @@ -0,0 +1,36 @@ +// +// GameController.h +// doomengine +// +// Created by John Watson on 1/29/15. +// +// + +/* + + 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. + + */ + +#ifndef doomengine_GameController_h +#define doomengine_GameController_h + +#define TURBOTHRESHOLD 0x32 // Lifted from iphone_async.cpp, as GameController also requires this constant +#define ROTATETHRESHOLD 1500.0f // Replace magic number for scaling rotation + +bool iphoneControllerIsAvailable(); +void iphoneControllerInput(ticcmd_t* cmd); + +#endif diff --git a/code/iphone/GameController.mm b/code/iphone/GameController.mm new file mode 100644 index 0000000..8f886da --- /dev/null +++ b/code/iphone/GameController.mm @@ -0,0 +1,202 @@ +// +// GameController.mm +// doomengine +// +// Created by John Watson on 1/29/15. +// +// + +/* + + 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. + + */ + +#import + +#import "doomiphone.h" + +#import "GameController.h" + +static GCController *controller = nil; +static bool togglePause = false; + +typedef enum { + WEAPON_PREVIOUS = 0, + WEAPON_NEXT = 1, +}weaponswitch_e; + +static bool HasAmmo(int weaponType) { + // Trivial case: you've always got fist + if(weaponType == wp_fist) { + return true; + } + + player_t *player = &players[consoleplayer]; + + if(!player->weaponowned[weaponType]) { + // Don't switch to an unowned weapon + return false; + } + + int ammo = -1; + + switch ( weaponType ) { + case wp_pistol: ammo = player->ammo[am_clip]; break; + case wp_shotgun: ammo = player->ammo[am_shell]; break; + case wp_chaingun: ammo = player->ammo[am_clip]; break; + case wp_missile: ammo = player->ammo[am_misl]; break; + case wp_plasma: ammo = player->ammo[am_cell]; break; + case wp_bfg: ammo = player->ammo[am_cell]; if ( ammo < 40 ) ammo = 0; break; + case wp_supershotgun: ammo = player->ammo[am_shell]; if ( ammo < 2 ) ammo = 0; break; + } + + return ammo > 0; +} + +static int SwitchWeapon(weaponswitch_e direction) { + int index = players[consoleplayer].readyweapon; + if(direction == WEAPON_PREVIOUS) { + --index; + while(!HasAmmo(index)) { + if(--index < 0) { + index = NUMWEAPONS - 1; + } + } + } else if(direction == WEAPON_NEXT) { + ++index; + while(!HasAmmo(index)) { + if(++index >= NUMWEAPONS) { + index = 0; + } + } + } + + if(index == weaponSelected) { + return wp_nochange; + } + + return index; +} + +static void setupPauseButtonHandler(GCController *ctrl) { + if(ctrl) { + ctrl.controllerPausedHandler = ^ (GCController* c){ + togglePause = true; + }; + } +} + +/** + Lazily initialze game controller on first request + return true if controller is available + */ +bool iphoneControllerIsAvailable() { + static bool initialized = false; + if(!initialized) { + NSArray *controllers = [GCController controllers]; + if(controllers.count > 0) { +// controller = controllers[0]; // Just use the first one + + // If we have neither gamepad nor extended gamepad support, just make controller nil +// if(![controller gamepad] && ![controller extendedGamepad]) { + controller = nil; +// } + + for (int i = 0; i < controllers.count; i++) + { + if([controllers[i] gamepad] || [controllers[i] extendedGamepad]) { + controller = controllers[i]; + } + } + +#if !TARGET_OS_TV + setupPauseButtonHandler(controller); + + // Register for controller connected/disconnected notifications + NSNotificationCenter *ns = [NSNotificationCenter defaultCenter]; + [ns addObserverForName:GCControllerDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + if(!controller) { + controller = [GCController controllers][0]; + if(![controller gamepad] && ![controller extendedGamepad]) { + controller = nil; + } + + setupPauseButtonHandler(controller); + } + }]; + + [ns addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + controller = nil; + }]; +#endif + } + initialized = true; // Only need to do this once + } + return controller != nil; +} + +void iphoneControllerInput(ticcmd_t* cmd) { + if(iphoneControllerIsAvailable()) { + // Perform standard gamepad updates + GCExtendedGamepad *gamepad = controller.extendedGamepad; + + cmd->angleturn += (gamepad.rightThumbstick.xAxis.value * -ROTATETHRESHOLD); + cmd->forwardmove += (gamepad.leftThumbstick.yAxis.value * TURBOTHRESHOLD); + cmd->sidemove += (gamepad.leftThumbstick.xAxis.value * TURBOTHRESHOLD); + + if(gamepad.rightTrigger.pressed) { + cmd->buttons |= BT_ATTACK; + } + + if(gamepad.buttonA.pressed) { + cmd->buttons |= BT_USE; + } + + int newWeapon = wp_nochange; + + // Switch weapons using X and Y buttons + if(gamepad.buttonX.pressed && players[consoleplayer].pendingweapon == wp_nochange) { + newWeapon = SwitchWeapon(WEAPON_PREVIOUS); + } + + if(gamepad.buttonY.pressed && players[consoleplayer].pendingweapon == wp_nochange) { + newWeapon = SwitchWeapon(WEAPON_NEXT); + } + + // If we switched weapons, pass that info down to our frame cmd + if(newWeapon != wp_nochange) { + cmd->buttons |= BT_CHANGE; + cmd->buttons |= newWeapon << BT_WEAPONSHIFT; + } + +// if(gamepad.dpad.left.pressed && players[consoleplayer].playerstate == PST_DEAD) { +// cmd->buttons |= BT_USE; +// } +// +// if(gamepad.dpad.up.pressed && players[consoleplayer].playerstate == PST_DEAD) { +// cmd->buttons |= BT_SPECIAL; +// } +// +// if(gamepad.dpad.right.pressed && players[consoleplayer].playerstate == PST_DEAD) { +// cmd->buttons |= BT_SPECIALMASK; +// } + + if(togglePause) { + cmd->buttons |= BT_SPECIAL | (BTS_PAUSE & BT_SPECIALMASK); + togglePause = false; + } + } +} diff --git a/code/iphone/GenericMenuView.h b/code/iphone/GenericMenuView.h deleted file mode 100644 index 99e8d75..0000000 --- a/code/iphone/GenericMenuView.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import -#import -#import "UIFontButton.h" - -@interface GenericMenuView : UIView { - - IBOutlet UIScrollView * scrollView; - IBOutlet UILabel * lastItem; - - - IBOutlet UIFontButton * epi1Button; - IBOutlet UIFontButton * epi2Button; - IBOutlet UIFontButton * epi3Button; - IBOutlet UIFontButton * epi4Button; - - int episodeSelection; - IBOutlet UIFontButton * nextButton; - IBOutlet UIFontLabel * nextLabel; - -} - -- (IBAction) BackToMain; -- (IBAction) NextToMissions; - - -- (IBAction) SelectEpisode1; -- (IBAction) SelectEpisode2; -- (IBAction) SelectEpisode3; -- (IBAction) SelectEpisode4; - -@end diff --git a/code/iphone/GenericMenuView.m b/code/iphone/GenericMenuView.m deleted file mode 100644 index 8f2d8ff..0000000 --- a/code/iphone/GenericMenuView.m +++ /dev/null @@ -1,111 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import "GenericMenuView.h" -#import "doomAppDelegate.h" -#include "doomiphone.h" - -@implementation GenericMenuView - -- (void) initialize{ - - if( scrollView != nil ) { - - [scrollView setContentSize:CGSizeMake( - scrollView.bounds.size.width, - CGRectGetMaxY(lastItem.frame) - )]; - } - - episodeSelection = -1; - [ nextButton setEnabled: NO ]; - [ nextLabel setEnabled: NO ]; -} - -- (void)awakeFromNib { - - [self initialize]; - -} - -- (id) initWithCoder:(NSCoder *)aCoder{ - - if(self = [super initWithCoder:aCoder] ) { - [self initialize]; - } - - return self; -} - -- (id) initWithFrame:(CGRect)rect{ - if(self = [super initWithFrame:rect] ) { - [self initialize]; - } - return self; -} - - -- (IBAction) BackToMain { - - [gAppDelegate MainMenu]; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); -} - -- (IBAction) NextToMissions { - - [gAppDelegate SelectEpisode: episodeSelection ]; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); -} - -- (IBAction) SelectEpisode1 { - - [ nextButton setEnabled: YES ]; - [ nextLabel setEnabled: YES ]; - episodeSelection = 0; - [ epi1Button setEnabled: NO ]; - [ epi2Button setEnabled: YES ]; - [ epi3Button setEnabled: YES ]; - [ epi4Button setEnabled: YES ]; -} - -- (IBAction) SelectEpisode2 { - [ nextButton setEnabled: YES ]; - [ nextLabel setEnabled: YES ]; - episodeSelection = 1; - [ epi1Button setEnabled: YES ]; - [ epi2Button setEnabled: NO ]; - [ epi3Button setEnabled: YES ]; - [ epi4Button setEnabled: YES ]; -} - -- (IBAction) SelectEpisode3 { - [ nextButton setEnabled: YES ]; - [ nextLabel setEnabled: YES ]; - episodeSelection = 2; - [ epi1Button setEnabled: YES ]; - [ epi2Button setEnabled: YES ]; - [ epi3Button setEnabled: NO ]; - [ epi4Button setEnabled: YES ]; -} - -- (IBAction) SelectEpisode4 { - [ nextButton setEnabled: YES ]; - [ nextLabel setEnabled: YES ]; - episodeSelection = 3; - [ epi1Button setEnabled: YES ]; - [ epi2Button setEnabled: YES ]; - [ epi3Button setEnabled: YES ]; - [ epi4Button setEnabled: NO ]; -} - -@end diff --git a/code/iphone/IBGlue.h b/code/iphone/IBGlue.h deleted file mode 100644 index b7d2a86..0000000 --- a/code/iphone/IBGlue.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -// Tells Interface Builder to go to the Main Menu. -void IB_GotoMainMenu(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/code/iphone/IBGlue.m b/code/iphone/IBGlue.m deleted file mode 100644 index 5d9c89f..0000000 --- a/code/iphone/IBGlue.m +++ /dev/null @@ -1,20 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -#include "IBGlue.h" -#import "doomAppDelegate.h" -#include "doomiphone.h" - -// Tells Interface Builder to go to the Main Menu. -void IB_GotoMainMenu() { - [ gAppDelegate MainMenu]; -} diff --git a/code/iphone/LegalMenuView-tvos.xib b/code/iphone/LegalMenuView-tvos.xib new file mode 100755 index 0000000..d690ee1 --- /dev/null +++ b/code/iphone/LegalMenuView-tvos.xib @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/LegalMenuView.xib b/code/iphone/LegalMenuView.xib new file mode 100755 index 0000000..0697dd1 --- /dev/null +++ b/code/iphone/LegalMenuView.xib @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/LegalMenuViewController.h b/code/iphone/LegalMenuViewController.h new file mode 100755 index 0000000..497c85a --- /dev/null +++ b/code/iphone/LegalMenuViewController.h @@ -0,0 +1,35 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import + +/* + ================================================================================================ + Doom_LegalMenuViewController + + ================================================================================================ + */ +@interface Doom_LegalMenuViewController : UIViewController { + +} + +- (IBAction) BackToMain; + +@end diff --git a/code/iphone/LegalMenuViewController.mm b/code/iphone/LegalMenuViewController.mm new file mode 100755 index 0000000..9f50389 --- /dev/null +++ b/code/iphone/LegalMenuViewController.mm @@ -0,0 +1,78 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "LegalMenuViewController.h" +#include "doomiphone.h" +#include "iphone_delegate.h" + +@implementation Doom_LegalMenuViewController + +/* + ======================== + Doom_LegalMenuViewController::initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +/* + ======================== + Doom_LegalMenuViewController::didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +#pragma mark - View lifecycle + +/* + ======================== + Doom_LegalMenuViewController::viewDidLoad + ======================== + */ +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view from its nib. +} + +/* + ======================== + Doom_LegalMenuViewController::BackToMain + ======================== + */ +- (IBAction) BackToMain { + + [self.navigationController popViewControllerAnimated:NO]; + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +} + +@end diff --git a/code/iphone/LegalMenuView~ipad.xib b/code/iphone/LegalMenuView~ipad.xib new file mode 100755 index 0000000..7041ebb --- /dev/null +++ b/code/iphone/LegalMenuView~ipad.xib @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/Localizable.strings b/code/iphone/Localizable.strings new file mode 100755 index 0000000..cb63e36 --- /dev/null +++ b/code/iphone/Localizable.strings @@ -0,0 +1,8 @@ +/* + Localizable.strings + Doom + + Created by Rob Rohan on 20/9/17. + +*/ + diff --git a/code/iphone/MainMenuView-tvos.xib b/code/iphone/MainMenuView-tvos.xib new file mode 100755 index 0000000..99f463e --- /dev/null +++ b/code/iphone/MainMenuView-tvos.xib @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/MainMenuView.h b/code/iphone/MainMenuView.h deleted file mode 100644 index 9bea99c..0000000 --- a/code/iphone/MainMenuView.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -#import -#import -#import "UIFontLabel.h" -#import "UIFontButton.h" - -@interface Banner_SubItem : UIFontButton { -@public - -} -@end - -@interface Banner_SubMenu: UIView { -@public - - BOOL isHidden; -} - -- (void) Hide; -- (void) Show; - -@end - -@interface MainMenuView : UIView { - -@public - - IBOutlet UIFontButton * mPlayButton; - IBOutlet UIFontButton * mSettingsButton; - IBOutlet UIFontButton * mAboutButton; - IBOutlet UIFontButton * mExtrasButton; - - IBOutlet Banner_SubMenu * mPlaySubMenu; - IBOutlet Banner_SubMenu * mSettingsSubMenu; - IBOutlet Banner_SubMenu * mAboutSubMenu; - IBOutlet Banner_SubMenu * mExtrasSubMenu; -} - -// Sub Menu Banner Actions -- (IBAction) ShowPlayBanner; -- (IBAction) ShowSettingsBanner; -- (IBAction) ShowAboutBanner; -- (IBAction) ShowExtrasBanner; - -- (void) ResetMenu; - -// Interface Builder Actions ( Connected through IB ) -- (IBAction) ResumeGamePressed; -- (IBAction) NewGamePressed; -- (IBAction) MultiplayerPressed; -- (IBAction) CreditsPressed; -- (IBAction) SupportPressed; -- (IBAction) LegalPressed; -- (IBAction) DemoPressed; -- (IBAction) OtherIdGamesPressed; -- (IBAction) ControlsOptionsPressed; -- (IBAction) SettingsOptionsPressed; - -@end diff --git a/code/iphone/MainMenuView.m b/code/iphone/MainMenuView.m deleted file mode 100644 index abcb175..0000000 --- a/code/iphone/MainMenuView.m +++ /dev/null @@ -1,255 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -#import "MainMenuView.h" -#import "doomAppDelegate.h" -#include "doomiphone.h" - -@implementation Banner_SubItem - - - -@end - - - -@implementation Banner_SubMenu - -- (void)awakeFromNib { - isHidden = YES; -} - -- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { - UIView *hitView = [super hitTest:point withEvent:event]; - - if (hitView != self) { - return hitView; - } - - return nil; -} - -- (void) Hide { - - if( !isHidden ) { - - isHidden = YES; - - [UIView beginAnimations:@"Show" context:nil]; - [UIView setAnimationDuration:0.5f]; - [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; - [UIView setAnimationBeginsFromCurrentState:NO]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(Disable)]; - - self.alpha = 1.0f; - [ self viewWithTag: 0 ].alpha = 0.0f; - - [UIView commitAnimations]; - - } -} - -- (void) Show { - - if( isHidden ) { - - isHidden = NO; - - [UIView beginAnimations:@"Show" context:nil]; - [UIView setAnimationDuration:0.5f]; - [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; - [UIView setAnimationBeginsFromCurrentState:NO]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(Enable)]; - - self.alpha = 1.0f; - [ self viewWithTag: 0 ].alpha = 1.0f; - - [UIView commitAnimations]; - } -} - -@end - - - - -@implementation MainMenuView - -- (void) initialize{ - - // Hide Everything. - [self ResetMenu]; - -} - -- (void)awakeFromNib { - - [self initialize]; - -} - -- (void) ResetMenu { - - -} - - -- (IBAction) ResumeGamePressed { - - [ gAppDelegate ResumeGame ]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); -} - -- (IBAction) NewGamePressed { - - // Go to the Map Menu. - [gAppDelegate NewGame]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); - -} - -- (IBAction) MultiplayerPressed { - - // Go to the MP Menu. - // get the address for the local service, which may - // start up a bluetooth personal area network - boolean serverResolved = ResolveNetworkServer( &netServer.address ); - - // open our socket now that the network interfaces have been configured - // Explicitly open on interface 1, which is en0. If bluetooth ever starts - // working better, we can handle multiple interfaces. - if ( gameSocket <= 0 ) { - gameSocket = UDPSocket( "en0", DOOM_PORT ); - } - - // get the address for the local service - if ( !serverResolved ) { - // nobody else is acting as a server, so start one here - RegisterGameService(); - SetupEmptyNetGame(); - } - - menuState = IPM_MULTIPLAYER; - - [gAppDelegate HideIB]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); - -} - -- (IBAction) CreditsPressed { - - [gAppDelegate CreditsMenu]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); -} - -- (IBAction) SupportPressed { - - [gAppDelegate GotoSupport]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); -} - -- (IBAction) LegalPressed { - - [gAppDelegate LegalMenu]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); -} - -- (IBAction) DemoPressed { - [gAppDelegate DemoGame ]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); -} - -- (IBAction) OtherIdGamesPressed { - - [gAppDelegate idSoftwareApps]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); -} - -- (IBAction) ControlsOptionsPressed { - - [gAppDelegate ControlsMenu]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); - -} - -- (IBAction) SettingsOptionsPressed { - - [gAppDelegate SettingsMenu ]; - - Sound_StartLocalSound( "iphone/baborted_01.wav" ); -} - -- (void) ShowPlayBanner { - - [ mPlayButton setEnabled: NO ]; - [ mSettingsButton setEnabled: YES ]; - [ mAboutButton setEnabled: YES ]; - [ mExtrasButton setEnabled: YES ]; - - [ mPlaySubMenu Show ]; - [ mSettingsSubMenu Hide ]; - [ mExtrasSubMenu Hide ]; - [ mAboutSubMenu Hide ]; - -} - -- (void) ShowSettingsBanner { - - [ mPlayButton setEnabled: YES ]; - [ mSettingsButton setEnabled: NO ]; - [ mAboutButton setEnabled: YES ]; - [ mExtrasButton setEnabled: YES ]; - - [ mSettingsSubMenu Show ]; - [ mPlaySubMenu Hide ]; - [ mExtrasSubMenu Hide ]; - [ mAboutSubMenu Hide ]; -} - -- (void) ShowAboutBanner { - - [ mPlayButton setEnabled: YES ]; - [ mSettingsButton setEnabled: YES ]; - [ mAboutButton setEnabled: NO ]; - [ mExtrasButton setEnabled: YES ]; - - [ mAboutSubMenu Show ]; - [ mPlaySubMenu Hide ]; - [ mSettingsSubMenu Hide ]; - [ mExtrasSubMenu Hide ]; -} - -- (void) ShowExtrasBanner { - - [ mPlayButton setEnabled: YES ]; - [ mSettingsButton setEnabled: YES ]; - [ mAboutButton setEnabled: YES ]; - [ mExtrasButton setEnabled: NO ]; - - [ mExtrasSubMenu Show ]; - [ mPlaySubMenu Hide ]; - [ mSettingsSubMenu Hide ]; - [ mAboutSubMenu Hide ]; -} - -@end diff --git a/code/iphone/MainMenuView.xib b/code/iphone/MainMenuView.xib new file mode 100755 index 0000000..5439fe8 --- /dev/null +++ b/code/iphone/MainMenuView.xib @@ -0,0 +1,539 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/MainMenuViewController.h b/code/iphone/MainMenuViewController.h new file mode 100755 index 0000000..c0e1ac6 --- /dev/null +++ b/code/iphone/MainMenuViewController.h @@ -0,0 +1,85 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import +#include "../ios/LabelButton.h" + +/* + ================================================================================================ + Doom Sub Menu Banner Interface object + ================================================================================================ + */ +@interface Banner_SubItem : idLabelButton { +@public + +} +@end + +@interface Banner_SubMenu: UIView { +@public + + BOOL isHidden; + BOOL didInit; +} + +- (void) Hide; +- (void) Show; + +@end + +/* + ================================================================================================ + MainMenuViewController + + ================================================================================================ +*/ +@interface Doom_MainMenuViewController : UIViewController { + + + IBOutlet idLabelButton * mPlayButton; + IBOutlet idLabelButton * mSettingsButton; + IBOutlet idLabelButton * mAboutButton; + IBOutlet idLabelButton * mExtrasButton; + + IBOutlet Banner_SubMenu * mPlaySubMenu; + IBOutlet Banner_SubMenu * mSettingsSubMenu; + IBOutlet Banner_SubMenu * mAboutSubMenu; + IBOutlet Banner_SubMenu * mExtrasSubMenu; +} + +// Sub Menu Banner Actions +- (IBAction) ShowPlayBanner; +- (IBAction) ShowSettingsBanner; +- (IBAction) ShowAboutBanner; +- (IBAction) ShowExtrasBanner; + +// Interface Builder Actions ( Connected through IB ) +- (IBAction) ResumeGamePressed; +- (IBAction) NewGamePressed; +- (IBAction) MultiplayerPressed; +- (IBAction) CreditsPressed; +- (IBAction) SupportPressed; +- (IBAction) LegalPressed; +- (IBAction) DemoPressed; +- (IBAction) OtherIdGamesPressed; +- (IBAction) ControlsOptionsPressed; +- (IBAction) SettingsOptionsPressed; + +@end diff --git a/code/iphone/MainMenuViewController.mm b/code/iphone/MainMenuViewController.mm new file mode 100755 index 0000000..8eee78f --- /dev/null +++ b/code/iphone/MainMenuViewController.mm @@ -0,0 +1,606 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "MainMenuViewController.h" +#include "iphone_delegate.h" +#include "doomiphone.h" +#import "EpisodeMenuViewController.h" +#import "MissionMenuViewController.h" +#import "CreditsMenuViewController.h" +#import "SettingsMenuViewController.h" +#import "ControlsMenuViewController.h" +#import "LegalMenuViewController.h" + +/* + ================================================================================================ + Doom Sub Menu Banner Interface object + ================================================================================================ + */ + +@implementation Banner_SubItem +@end + +@implementation Banner_SubMenu + +/* + ======================== + Banner_SubMenu::awakeFromNib + ======================== + */ +- (void)awakeFromNib { + [super awakeFromNib]; + isHidden = YES; + + sigilShredsLoaded = false; + +#if GAME_DOOM + iphoneIWADSelect("doom.wad"); +#endif + +#if GAME_DOOM2 + iphoneIWADSelect("doom2.wad"); +#endif + +#if GAME_FINALDOOM + // just picking a wad file to make the startup happy + iphoneIWADSelect("tnt.wad"); +#endif + +#if GAME_SIGIL + iphoneIWADSelect("doom.wad"); + iphoneClearPWADs(); + iphonePWADAdd("SIGIL.wad"); + + NSString* filePath = [[NSBundle mainBundle] pathForResource:@"SIGIL_SHREDS" + ofType:@"wad"]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + if ([fileManager fileExistsAtPath:filePath]){ + iphonePWADAdd("SIGIL_SHREDS.wad"); + sigilShredsLoaded = true; + } + +#endif + + if( !didInit ) { + char full_iwad[1024]; + +// doom_iwad = strdup(Cvar_VariableString("iwadSelection")); +// doom_pwads = strdup(Cvar_VariableString("pwadSelection")); + + I_FindFile( doom_iwad, ".wad", full_iwad ); + + // fall back to default DOOM wad + if( full_iwad[0] == '\0' ) { + I_FindFile( "doom.wad", ".wad", full_iwad ); + if( doom_iwad ) free(doom_iwad); + doom_iwad = strdup(full_iwad); + } else if( strcmp(doom_iwad,full_iwad) != 0 ) { + if( doom_iwad ) free(doom_iwad); + doom_iwad = strdup( full_iwad ); + } + + iphoneDoomStartup(); + didInit = YES; + } +} + +/* + ======================== + Banner_SubMenu::hitTest + ======================== + */ +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + UIView *hitView = [super hitTest:point withEvent:event]; + + if (hitView != self) { + return hitView; + } + + return nil; +} + +/* + ======================== + Banner_SubMenu::Hide + ======================== + */ +- (void) Hide { + + if( !isHidden ) { + + isHidden = YES; + + [UIView beginAnimations:@"Show" context:nil]; + [UIView setAnimationDuration:0.5f]; + [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; + [UIView setAnimationBeginsFromCurrentState:NO]; + [UIView setAnimationDelegate:self]; + //[UIView setAnimationDidStopSelector:@selector(Disable)]; + + self.alpha = 1.0f; + [ self viewWithTag: 0 ].alpha = 0.0f; + + [UIView commitAnimations]; + + } +} + +/* + ======================== + Banner_SubMenu::Show + ======================== + */ +- (void) Show { + + if( isHidden ) { + + isHidden = NO; + + [UIView beginAnimations:@"Show" context:nil]; + [UIView setAnimationDuration:0.5f]; + [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; + [UIView setAnimationBeginsFromCurrentState:NO]; + [UIView setAnimationDelegate:self]; + //[UIView setAnimationDidStopSelector:@selector(Enable)]; + + self.alpha = 1.0f; + [ self viewWithTag: 0 ].alpha = 1.0f; + + [UIView commitAnimations]; + } +} + +@end + + +/* + ================================================================================================ + MainMenuViewController + ================================================================================================ + */ +@implementation Doom_MainMenuViewController + +BOOL playMenuSelected = NO; +BOOL extrasMenuSelected = NO; +BOOL aboutMenuSelected = NO; +BOOL settingsMenuSelected = NO; + +/* + ======================== + MainMenuViewController::initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + + } + return self; +} + +/* + ======================== + MainMenuViewController::didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +#pragma mark - View lifecycle + +/* + ======================== + MainMenuViewController::viewDidLoad + ======================== + */ +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view from its nib. +} + +/* + ======================== + MainMenuViewController::ResumeGamePressed + ======================== + */ +- (IBAction) ResumeGamePressed { + + [ gAppDelegate ShowGLView ]; + + ResumeGame(); + paused = false; + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); + +} + +/* + ======================== + MainMenuViewController::NewGamePressed + ======================== + */ +- (IBAction) NewGamePressed { + +#if GAME_DOOM2 + Doom_MissionMenuViewController *vc = [[Doom_MissionMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"MissionMenuView"] bundle:nil]; +#elif GAME_SIGIL + Doom_MissionMenuViewController *vc = [[Doom_MissionMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"MissionMenuView"] bundle:nil]; +#else + // Switch to episode view menu. + Doom_EpisodeMenuViewController *vc = [[Doom_EpisodeMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"EpisodeMenuView"] bundle:nil]; +#endif + + [self.navigationController pushViewController:vc animated:NO]; +#if GAME_DOOM2 + [vc setEpisode:0 ]; +#elif GAME_SIGIL + [vc setEpisode:4 ]; +#endif + [vc release]; + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); + +} + +/* + ======================== + MainMenuViewController::MultiplayerPressed + ======================== + */ +- (IBAction) MultiplayerPressed { + + + //ShowMatchmaker( self, 2, 4 ); + return; + + // Go to the MP Menu. + // get the address for the local service, which may + // start up a bluetooth personal area network + //bool serverResolved = ResolveNetworkServer( &netServer.address ); + + // open our socket now that the network interfaces have been configured + // Explicitly open on interface 1, which is en0. If bluetooth ever starts + // working better, we can handle multiple interfaces. +// if ( gameSocket <= 0 ) { +// gameSocket = UDPSocket( "en0", DOOM_PORT ); +// } + + /* + // get the address for the local service + if ( !serverResolved ) { + // nobody else is acting as a server, so start one here + RegisterGameService(); + SetupEmptyNetGame(); + } + */ + +// menuState = IPM_MULTIPLAYER; +// +// [gAppDelegate ShowGLView]; +// +// Sound_StartLocalSound( "iphone/baborted_01.wav" ); + +} + +/* + ======================== + MainMenuViewController::CreditsPressed + ======================== + */ +- (IBAction) CreditsPressed { + + Doom_CreditsMenuViewController *vc = [[Doom_CreditsMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"CreditsMenuView"] bundle:nil]; + + [self.navigationController pushViewController:vc animated:NO]; + [vc release]; + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); +} + +/* + ======================== + MainMenuViewController::SupportPressed + ======================== + */ +- (IBAction) SupportPressed { + + SysIPhoneOpenURL("http://www.idsoftware.com/doom-classic/index.html"); + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); +} + +/* + ======================== + MainMenuViewController::LegalPressed + ======================== + */ +- (IBAction) LegalPressed { + + Doom_LegalMenuViewController *vc = [[Doom_LegalMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"LegalMenuView"] bundle:nil]; + + [self.navigationController pushViewController:vc animated:NO]; + [vc release]; + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); +} + +/* + ======================== + MainMenuViewController::DemoPressed + ======================== + */ +- (IBAction) DemoPressed { + + StartDemoGame( false ); + + [gAppDelegate ShowGLView]; + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); +} + +/* + ======================== + MainMenuViewController::OtherIdGamesPressed + ======================== + */ +- (IBAction) OtherIdGamesPressed { + + SysIPhoneOpenURL("http://itunes.com/apps/idsoftware"); + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); +} + +/* + ======================== + MainMenuViewController::ControlsOptionsPressed + ======================== + */ +- (IBAction) ControlsOptionsPressed { + + Doom_ControlsMenuViewController *vc = [[Doom_ControlsMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"ControlsMenuView"] bundle:nil]; + + [self.navigationController pushViewController:vc animated:NO]; + [vc release]; + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); + +} + +/* + ======================== + MainMenuViewController::SettingsOptionsPressed + ======================== + */ +- (IBAction) SettingsOptionsPressed { + + Doom_SettingsMenuViewController *vc = [[Doom_SettingsMenuViewController alloc] initWithNibName:[gAppDelegate GetNibNameForDevice:@"SettingsMenuView"] bundle:nil]; + + [self.navigationController pushViewController:vc animated:NO]; + [vc release]; + + Sound_StartLocalSound( "iphone/baborted_01.wav" ); +} + +/* + ======================== + MainMenuViewController::ShowPlayBanner + ======================== + */ +- (void) ShowPlayBanner { + + [ mPlaySubMenu Show ]; + [ mSettingsSubMenu Hide ]; + [ mExtrasSubMenu Hide ]; + [ mAboutSubMenu Hide ]; + +#if TARGET_OS_TV + playMenuSelected = YES; + extrasMenuSelected = NO; + settingsMenuSelected = NO; + aboutMenuSelected = NO; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; +#else + [ mPlayButton setEnabled: NO ]; + [ mSettingsButton setEnabled: YES ]; + [ mAboutButton setEnabled: YES ]; + [ mExtrasButton setEnabled: YES ]; +#endif + +} + +/* + ======================== + MainMenuViewController::ShowSettingsBanner + ======================== + */ +- (void) ShowSettingsBanner { + + [ mSettingsSubMenu Show ]; + [ mPlaySubMenu Hide ]; + [ mExtrasSubMenu Hide ]; + [ mAboutSubMenu Hide ]; + +#if TARGET_OS_TV + playMenuSelected = NO; + extrasMenuSelected = NO; + settingsMenuSelected = YES; + aboutMenuSelected = NO; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; +#else + [ mPlayButton setEnabled: YES ]; + [ mSettingsButton setEnabled: NO ]; + [ mAboutButton setEnabled: YES ]; + [ mExtrasButton setEnabled: YES ]; +#endif + +} + +/* + ======================== + MainMenuViewController::ShowAboutBanner + ======================== + */ +- (void) ShowAboutBanner { + + [ mAboutSubMenu Show ]; + [ mPlaySubMenu Hide ]; + [ mSettingsSubMenu Hide ]; + [ mExtrasSubMenu Hide ]; + +#if TARGET_OS_TV + playMenuSelected = NO; + extrasMenuSelected = NO; + settingsMenuSelected = NO; + aboutMenuSelected = YES; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; +#else + [ mPlayButton setEnabled: YES ]; + [ mSettingsButton setEnabled: YES ]; + [ mAboutButton setEnabled: NO ]; + [ mExtrasButton setEnabled: YES ]; +#endif + +} + +/* + ======================== + MainMenuViewController::ShowExtrasBanner + ======================== + */ +- (void) ShowExtrasBanner { + +// Doom_CreditsMenuViewController *vc = nil; +// +// vc = [[Doom_CreditsMenuViewController alloc] initWithNibName:@"CreditsMenuView" bundle:nil]; +// +// [self.navigationController pushViewController:vc animated:NO]; +// [vc release]; +// +// Sound_StartLocalSound( "iphone/baborted_01.wav" ); + + [ mSettingsSubMenu Hide ]; + [ mPlaySubMenu Hide ]; + [ mExtrasSubMenu Show ]; + [ mAboutSubMenu Hide ]; + +#if TARGET_OS_TV + playMenuSelected = NO; + extrasMenuSelected = YES; + settingsMenuSelected = NO; + aboutMenuSelected = NO; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; +#else + [ mPlayButton setEnabled: YES ]; + [ mSettingsButton setEnabled: YES ]; + [ mAboutButton setEnabled: YES ]; + [ mExtrasButton setEnabled: NO ]; +#endif + +} + +#if TARGET_OS_TV +-(NSArray> *)preferredFocusEnvironments { + if (playMenuSelected) { + return @[mPlaySubMenu]; + } else if (extrasMenuSelected) { + return @[mExtrasSubMenu]; + } else if (settingsMenuSelected) { + return @[mSettingsSubMenu]; + } else if (aboutMenuSelected) { + return @[mAboutSubMenu]; + } else { + return @[mPlayButton]; + } +} + +- (void)pressesBegan:(NSSet *)presses withEvent:(UIPressesEvent *)event { + for (UIPress* press in presses) { + switch (press.type) { + case UIPressTypeMenu: + if (playMenuSelected || extrasMenuSelected || settingsMenuSelected || aboutMenuSelected) { + break; + } else { + [super pressesBegan: presses withEvent: event]; + } + default: + [super pressesBegan: presses withEvent: event]; + break; + } + } +} + +- (void)pressesEnded:(NSSet *)presses withEvent:(UIPressesEvent *)event { + for (UIPress* press in presses) { + switch (press.type) { + case UIPressTypeMenu: + if (playMenuSelected) { + playMenuSelected = NO; + [mPlaySubMenu Hide]; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; + } else if (extrasMenuSelected) { + extrasMenuSelected = NO; + [mExtrasSubMenu Hide]; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; + } else if (settingsMenuSelected) { + settingsMenuSelected = NO; + [mSettingsSubMenu Hide]; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; + } else if (aboutMenuSelected) { + aboutMenuSelected = NO; + [mAboutSubMenu Hide]; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; + } else { + [super pressesEnded: presses withEvent: event]; + } + break; + default: + [super pressesEnded: presses withEvent: event]; + break; + } + } +} + +- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator { + if (!context.previouslyFocusedView && [context.nextFocusedView isKindOfClass:[Banner_SubItem class]]) { + [ gAppDelegate HideGLView ]; + paused = true; + } +} + +#endif + +@end diff --git a/code/iphone/MainMenuView~ipad.xib b/code/iphone/MainMenuView~ipad.xib new file mode 100755 index 0000000..c891d8b --- /dev/null +++ b/code/iphone/MainMenuView~ipad.xib @@ -0,0 +1,545 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/MainNavController.h b/code/iphone/MainNavController.h new file mode 100755 index 0000000..25cbc8a --- /dev/null +++ b/code/iphone/MainNavController.h @@ -0,0 +1,25 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import + +@interface MainNavController : UINavigationController + +@end diff --git a/code/iphone/MainNavController.m b/code/iphone/MainNavController.m new file mode 100755 index 0000000..228c84b --- /dev/null +++ b/code/iphone/MainNavController.m @@ -0,0 +1,51 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "MainNavController.h" +//#import "doomiphone.h" + +@interface MainNavController () + +@end + +@implementation MainNavController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff --git a/code/iphone/MainWindow.xib b/code/iphone/MainWindow.xib deleted file mode 100644 index 085852f..0000000 --- a/code/iphone/MainWindow.xib +++ /dev/null @@ -1,10984 +0,0 @@ - - - - 768 - 10K549 - 851 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 141 - - - YES - - - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - IBCocoaTouchFramework - - - - 1316 - - {320, 480} - - 1 - MSAxIDEAA - - NO - IBCocoaTouchFramework - YES - - - - - 1316 - - YES - - - 1316 - {480, 320} - - NO - 2 - IBCocoaTouchFramework - - NSImage - MenuBackground.png - - - - - 1316 - {{0, 264}, {50, 50}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - Helvetica-Bold - 15 - 16 - - - 3 - MQA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - 3 - MC41AA - - - NSImage - BackButton.png - - - - - 1316 - {{171, 32}, {36, 40}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - SettingsButton_Highlighted.png - - - - NSImage - SettingsButton.png - - - - - 1316 - {{171, 77}, {36, 40}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{171, 129}, {36, 40}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{171, 184}, {36, 40}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{361, 33}, {36, 40}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{361, 77}, {36, 40}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{361, 129}, {36, 40}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{361, 184}, {36, 40}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{425, 264}, {50, 50}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - {1, 2} - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - NSImage - NextButton.png - - - - - 1316 - {{88, 41}, {75, 21}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Auto Use: - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{76, 86}, {87, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Status Bar: - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{73, 136}, {90, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Hud Audio: - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{40, 191}, {123, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Text Messages: - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{236, 40}, {117, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Draw Controls: - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{301, 86}, {52, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Music: - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{245, 136}, {108, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Center Sticks: - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{260, 191}, {93, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Ramp Turn: - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{431, 259}, {38, 20}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Reset - - Helvetica - 14 - 16 - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 1316 - {{9, 259}, {33, 20}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Back - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - {480, 320} - - 3 - MQA - - 2 - - - - 3 - - 2 - IBCocoaTouchFramework - - - 3 - - 2 - IBCocoaTouchFramework - YES - - - - - 1316 - - YES - - - 1316 - {480, 320} - - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{120, 32}, {240, 128}} - - - NO - 2 - IBCocoaTouchFramework - - NSImage - DoomLogo.png - - - - - 1316 - {{0, 264}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 1316 - {{7, 154}, {469, 98}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Doom® Classic © 2009-2011 id Software LLC, a ZeniMax Media company. DOOM, id, id Software, id Tech and related logos are registered trademarks or trademarks of id Software LLC in the U.S. and/or other countries. Bethesda, Bethesda Softworks, ZeniMax and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the U.S. and/or other countries. All Rights Reserved - - Helvetica - 13 - 16 - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 0 - 1 - 0 - - - - 1316 - {{9, 259}, {33, 20}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Back - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - {480, 320} - - - - 3 - MQA - - - - 3 - - 2 - IBCocoaTouchFramework - - - 3 - - 2 - IBCocoaTouchFramework - YES - - - - - 1316 - - YES - - - 1316 - {480, 320} - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{0, 264}, {50, 50}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 1289 - - YES - - - 1316 - {{-19, 33}, {362, 41}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Doom Classic - - Helvetica-Bold - 24 - 16 - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 68}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Programming - - Helvetica-Bold - 20 - 16 - - - - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 485}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Programming - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 104}, {362, 20}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - John Carmack - - Helvetica - 18 - 16 - - - - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 525}, {362, 20}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - John Carmack - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 543}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - John Romero - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 562}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Dave Taylor - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 860}, {375, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Ultimate Doom additional Level Design - - Helvetica-Bold - 17 - 16 - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 887}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - John Anderson - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 907}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Shawn Green - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 927}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - American McGee - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 946}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - John Romero - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 966}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Tim Willits - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 616}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Design - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 656}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - John Romero - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 676}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Sandy Peterson - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 708}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Art - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 748}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Adrian Carmack - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 768}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Kevin Cloud - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 800}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Audio - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 828}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Bobby Prince - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 125}, {362, 19}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Jeff Farrand - - - - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 145}, {362, 21}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Ryan Gerleve - - - - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 174}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Art - - - - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 252}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Audio - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 310}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Production - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-54, 431}, {432, 46}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Doom & Ultimate Doom originally created by id Software - - Helvetica-Bold - 14 - 16 - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 3 - 1 - 0 - - - - 1316 - {{-19, 366}, {362, 32}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - QA Testing - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 200}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - John Burnett - - - - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 220}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Danny Keys - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 278}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Zack Quarles - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 335}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Rafael Brown - - - - - {1, 2} - 1 - 16 - 1 - - - - 1316 - {{-19, 392}, {362, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Sean Palomino - - - - - {1, 2} - 1 - 16 - 1 - - - {{78, 16}, {324, 284}} - - YES - YES - 2 - IBCocoaTouchFramework - 2 - - - - 1316 - {{9, 259}, {33, 20}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Back - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - {480, 320} - - 3 - MQA - - - - 3 - - 2 - IBCocoaTouchFramework - - - 3 - - 2 - IBCocoaTouchFramework - YES - - - - - 1316 - - YES - - - 1316 - {480, 320} - - - 1 - MSAxIDEgMAA - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{36, 114}, {407, 7}} - - NO - 2 - IBCocoaTouchFramework - - NSImage - Divide.png - - - - - 1316 - {{36, 141}, {407, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Move Stick Size - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 3 - MCAwAA - - {0, 0} - 1 - 10 - 2 - - - - 1316 - {{34, 91}, {111, 20}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Single Thumbpad - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 1316 - {{9, 259}, {32, 18}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Back - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 1316 - {{417, 259}, {63, 18}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Advanced - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 1316 - {{184, 91}, {111, 20}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Dual Thumbpad - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 1316 - {{335, 91}, {111, 20}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Dir & Wheel - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 1316 - {{36, 175}, {407, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Turn Stick Size - - - - - {0, 0} - 1 - 10 - 2 - - - - 1316 - {{36, 208}, {407, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Tilt Move Speed - - - - - {0, 0} - 1 - 10 - 2 - - - - 1316 - {{36, 243}, {407, 23}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Tilt Turn Speed - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 2 - - - - 1316 - {{28, 7}, {123, 85}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - {1, 2} - - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - NSImage - LayoutSingleButton.png - - - - - 1316 - {{178, 7}, {123, 85}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - {1, 2} - - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - NSImage - LayoutDualButton.png - - - - - 1316 - {{329, 7}, {123, 85}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - {1, 2} - - - - - - NSImage - LayoutWheelButton.png - - - - - 1316 - {{425, 264}, {50, 50}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - {1, 2} - - - - - NSImage - AdvancedButton.png - - - - - 1316 - {{34, 132}, {411, 23}} - - - 1 - MC4wMDU0MzQ3ODI3MSAwLjAwNTQzNDc4MjcxIDAuMDA1NDM0NzgyNzEgMAA - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - 0.5 - - - - 1316 - {{34, 165}, {411, 23}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - 0.5 - - - - 1316 - {{34, 198}, {411, 23}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - 100 - 300 - - - - 1316 - {{34, 233}, {411, 23}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - 1500 - 3500 - - - - 1316 - {{0, 264}, {50, 50}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - {480, 320} - - - 3 - MQA - - - - 3 - - 2 - IBCocoaTouchFramework - - - 3 - - 2 - IBCocoaTouchFramework - YES - - - - - 1316 - - YES - - - 1316 - {480, 320} - - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{74, 26}, {328, 181}} - - - NO - 2 - IBCocoaTouchFramework - - NSImage - MissonBackground.png - - - - - 1316 - {{78, 217}, {324, 77}} - - - NO - 2 - IBCocoaTouchFramework - - NSImage - DifficultyBackground.png - - - - - 1316 - - YES - - - 1316 - {{7, 6}, {270, 26}} - - - NO - 10 - 2 - IBCocoaTouchFramework - 0 - - Helvetica-Bold - 18 - 16 - - {1, 2} - E1M1: Hanger - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - - - 1316 - {{7, 51}, {270, 26}} - - - NO - 11 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E1M2: Nuclear Plant - - - - - - - - 1316 - {{7, 96}, {270, 26}} - - - NO - 12 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E1M3: Toxin Refinery - - - - - - - - 1316 - {{7, 143}, {270, 22}} - - - NO - 13 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E1M4: Command Control - - - - - - - - 1316 - {{7, 188}, {270, 22}} - - - NO - 14 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E1M5: Phobos Lab - - - - - - - - 1316 - {{7, 233}, {270, 22}} - - - NO - 15 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E1M6: Central Processing - - - - - - - - 1316 - {{7, 278}, {270, 22}} - - - NO - 16 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E1M7: Computer Station - - - - - - - - 1316 - {{7, 323}, {270, 22}} - - - NO - 17 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E1M8: Phobos Anomaly - - - - - - - - 1316 - {{7, 368}, {270, 22}} - - - NO - 18 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E1M9: Military Base - - - - - - - {{96, 46}, {284, 137}} - - - - 1 - MSAxIDEgMAA - - YES - 0.0 - YES - 2 - IBCocoaTouchFramework - 1 - 100 - 0.0 - 0.0 - 2 - - - - 1316 - - YES - - - 1316 - {{7, 8}, {270, 22}} - - - NO - 20 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M1: Deimos Anomaly - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - - - 1316 - {{7, 53}, {270, 22}} - - - NO - 21 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M2: Containment Area - - - - - - - - 1316 - {{7, 98}, {270, 22}} - - - NO - 22 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M3: Refinery - - - - - - - - 1316 - {{7, 142}, {270, 22}} - - - NO - 23 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M4: Deimos Lab - - - - - - - - 1316 - {{7, 187}, {270, 22}} - - - NO - 24 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M5: Command Center - - - - - - - - 1316 - {{7, 232}, {270, 22}} - - - NO - 25 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M6: Halls of the Damned - - - - - - - - 1316 - {{7, 277}, {270, 22}} - - - NO - 26 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M7: Computer Station - - - - - - - - 1316 - {{7, 322}, {270, 22}} - - - NO - 27 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M8: Phobos Anomaly - - - - - - - - 1316 - {{7, 367}, {270, 22}} - - - NO - 28 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E2M9: Military Base - - - - - - - {{96, 46}, {284, 137}} - - - - 1 - MSAxIDEgMAA - - YES - 0.0 - YES - 2 - IBCocoaTouchFramework - 1 - 100 - 0.0 - 0.0 - 2 - - - - 1316 - - YES - - - 1316 - {{7, 8}, {270, 22}} - - - NO - 30 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M1: Hell Keep - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - - - 1316 - {{7, 53}, {270, 22}} - - - NO - 31 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M2: Slough of Despair - - - - - - - - 1316 - {{7, 98}, {270, 22}} - - - NO - 32 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M3: Pandemonium - - - - - - - - 1316 - {{7, 142}, {270, 22}} - - - NO - 33 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M4: House of Pain - - - - - - - - 1316 - {{7, 187}, {270, 22}} - - - NO - 34 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M5: Unholy Cathedral - - - - - - - - 1316 - {{7, 232}, {270, 22}} - - - NO - 35 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M6: Mt. Erebus - - - - - - - - 1316 - {{7, 277}, {270, 22}} - - - NO - 36 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M7: Limbo - - - - - - - - 1316 - {{7, 322}, {270, 22}} - - - NO - 37 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M8: Dis - - - - - - - - 1316 - {{7, 367}, {270, 22}} - - - NO - 38 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E3M9: Warrens - - - - - - - {{96, 46}, {284, 137}} - - - - 1 - MSAxIDEgMAA - - YES - 0.0 - YES - 2 - IBCocoaTouchFramework - 1 - 100 - 0.0 - 0.0 - 2 - - - - 1316 - - YES - - - 1316 - {{7, 8}, {270, 22}} - - - NO - 40 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M1: Hell Beneath - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - - - 1316 - {{7, 53}, {270, 22}} - - - NO - 41 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M2: Perfect Hatred - - - - - - - - 1316 - {{7, 98}, {270, 22}} - - - NO - 42 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M3: Sever The Wicked - - - - - - - - 1316 - {{7, 142}, {270, 22}} - - - NO - 43 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M4: Unruly Evil - - - - - - - - 1316 - {{7, 187}, {270, 22}} - - - NO - 44 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M5: They Will Repent - - - - - - - - 1316 - {{7, 232}, {270, 22}} - - - NO - 45 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M6: Against Thee Wickedly - - - - - - - - 1316 - {{7, 277}, {270, 22}} - - - NO - 46 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M7: And Hell Followed - - - - - - - - 1316 - {{7, 322}, {270, 22}} - - - NO - 47 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M8: Unto The Cruel - - - - - - - - 1316 - {{7, 367}, {270, 22}} - - - NO - 48 - 2 - IBCocoaTouchFramework - 0 - - {1, 2} - E4M9: Fear - - - - - - - {{96, 46}, {284, 137}} - - - - 1 - MSAxIDEgMAA - - YES - 0.0 - YES - 2 - IBCocoaTouchFramework - 1 - 100 - 0.0 - 0.0 - 2 - - - - 1316 - {{0, 264}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 1316 - {{425, 264}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - NextButton_Highlighted.png - - - - - - 1316 - {{216, 23}, {44, 21}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - UpArrow_Highlighted.png - - - NSImage - UpArrow - - - - - 1316 - {{216, 189}, {44, 21}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - DownArrow_Highlighted.png - - - NSImage - DownArrow - - - - - 1316 - {{96, 232}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Easy.png - - - - - 1316 - {{175, 232}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Medium.png - - - - - 1316 - {{250, 232}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Hard.png - - - - - 1316 - {{330, 232}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Nightmare.png - - - - - 1316 - {{96, 232}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - - NSImage - SelectedBracket.png - - - - - 1316 - {{175, 232}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{250, 232}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{330, 232}, {50, 50}} - - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{436, 259}, {28, 18}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Play - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - 1 - 10 - 1 - - - - 1316 - {{155.5, 290.5}, {169, 21}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - I'm Too Young To Die. - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - 1 - - - - 1316 - {{155.5, 290.5}, {169, 21}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Hey, Not Too Rough. - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - 1 - - - - 1316 - {{155.5, 290.5}, {169, 21}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Hurt Me Plenty. - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - 1 - - - - 1316 - {{155.5, 290.5}, {169, 21}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Ultra-Violence. - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - 1 - - - - 1316 - {{85, 206}, {65, 21}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Difficulty - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - - - - 1316 - {{85, 21}, {58, 21}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Mission - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - - - - 1316 - {{9, 259}, {32, 18}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Back - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - 1 - 10 - 1 - - - {480, 320} - - - - 3 - MQA - - - 2 - IBCocoaTouchFramework - - - 3 - - 2 - IBCocoaTouchFramework - YES - - - - - 1316 - - YES - - - 1316 - {480, 320} - - - 1 - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{95.5, 23}, {289, 185}} - - - 1 - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{15, 139.5}, {100, 100}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Button_Highlighted.png - - - - NSImage - Button.png - - - - - 1316 - {{127, 200}, {100, 100}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{250, 200}, {100, 100}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{366.5, 139.5}, {100, 100}} - - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 1316 - {{10, 224}, {110, 23}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - PLAY GAME - - idGinzaNarrow-Medium2 - 19 - 16 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - 1 - NO - 10 - 1 - - - - 1316 - {{129, 283}, {96, 23}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - SETTINGS - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - NO - 10 - 1 - - - - 1316 - {{257, 283}, {86, 23}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - ABOUT - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - NO - 10 - 1 - - - - 1316 - {{374, 224}, {86, 23}} - - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - EXTRAS - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - NO - 10 - 1 - - - - 1298 - - YES - - - 1316 - {{5, 5}, {480, 301}} - - - NO - 2 - IBCocoaTouchFramework - - NSImage - SubMenuBackground.png - - - - - 1316 - {{122, 69.5}, {104, 93}} - - - NO - 1 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - SubMenuButton_Highlighted.png - - - NSImage - SubMenuButton.png - - - - - 1316 - {{267, 69.5}, {104, 93}} - - - NO - 2 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 1316 - {{119, 133.5}, {110, 23}} - - - NO - YES - 7 - 3 - NO - 2 - IBCocoaTouchFramework - NEW GAME - - idGinzaNarrow-Medium2 - 17 - 16 - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 1316 - {{251, 133.5}, {136, 23}} - - - NO - YES - 7 - 4 - NO - 2 - IBCocoaTouchFramework - RESUME GAME - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - NO - 10 - 1 - - - {{-5, -20.5}, {480, 320}} - - - - 0.0 - 2 - IBCocoaTouchFramework - - - - 1316 - - YES - - - 1316 - {{0, -15.5}, {480, 301}} - - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{117, 49}, {104, 93}} - - - NO - 1 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 1316 - {{262, 49}, {104, 93}} - - - NO - 2 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 1316 - {{114, 113}, {110, 23}} - - - NO - YES - 7 - 3 - NO - 2 - IBCocoaTouchFramework - CONTROLS - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 1316 - {{249, 113}, {136, 23}} - - - NO - YES - 7 - 4 - NO - 2 - IBCocoaTouchFramework - OPTIONS - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - NO - 10 - 1 - - - {480, 320} - - - - 0.0 - 2 - IBCocoaTouchFramework - - - - 1316 - - YES - - - 1316 - {{0, -15.5}, {480, 301}} - - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{117, 49}, {104, 93}} - - - NO - 1 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 1316 - {{262, 49}, {104, 93}} - - - NO - 2 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 1316 - {{110, 113}, {125, 23}} - - - NO - YES - 7 - 3 - NO - 2 - IBCocoaTouchFramework - MORE GAMES - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 1316 - {{249, 113}, {136, 23}} - - - NO - YES - 7 - 4 - NO - 2 - IBCocoaTouchFramework - DEMO - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - NO - 10 - 1 - - - {480, 320} - - - - 0.0 - 2 - IBCocoaTouchFramework - - - - 1316 - - YES - - - 1316 - {{0, -15.5}, {480, 301}} - - - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{44, 49}, {104, 93}} - - - NO - 1 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 1316 - {{326, 49}, {104, 93}} - - - NO - 2 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 1316 - {{188, 49}, {104, 93}} - - - NO - 2 - 2 - IBCocoaTouchFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 1316 - {{41, 113}, {110, 23}} - - - NO - YES - 7 - 3 - NO - 2 - IBCocoaTouchFramework - LEGAL - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 1316 - {{323, 113}, {110, 23}} - - - NO - YES - 7 - 3 - NO - 2 - IBCocoaTouchFramework - CREDITS - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 1316 - {{172, 113}, {136, 23}} - - - NO - YES - 7 - 4 - NO - 2 - IBCocoaTouchFramework - SUPPORT - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - NO - 10 - 1 - - - {480, 320} - - - - 0.0 - 2 - IBCocoaTouchFramework - - - {480, 320} - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - 3 - - 2 - IBCocoaTouchFramework - - - 3 - - 2 - IBCocoaTouchFramework - YES - - - - - 1316 - - YES - - - 1316 - {480, 320} - - 1 - NO - 2 - IBCocoaTouchFramework - - - - - 1316 - {{0, 264}, {50, 50}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode1Background.png - - - - - - 1316 - {{425, 264}, {50, 50}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 1316 - {{435, 259}, {29, 18}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Next - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - 1 - 10 - 1 - - - - 1316 - {{9, 259}, {32, 18}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Back - - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - 1 - 10 - 1 - - - - 1316 - - YES - - - 1316 - {{11, 3}, {320, 79}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode1Background_Highlighted.png - - - - - - - 1316 - {{11, 75}, {320, 79}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode2Background_Highlighted.png - - - - NSImage - Episode2Background.png - - - - - 1316 - {{11, 146}, {320, 79}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode3Background_Highlighted.png - - - - NSImage - Episode3Background.png - - - - - 1316 - {{11, 219}, {320, 79}} - - NO - 2 - IBCocoaTouchFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode4Background_Highlighted.png - - - - NSImage - Episode4Background.png - - - - - 1316 - {{37, 245}, {81, 18}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - EPISODE IV - - - 1 - MC40OTQxMTc2NDc0IDAuMTkyMTU2ODY2MiAwLjAwNzg0MzEzNzcxOQA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - 10 - - - - 1316 - {{37, 260}, {192, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Thy Flesh Consumed - - Helvetica - 20 - 16 - - - 1 - MC44NTg4MjM1Mzc4IDAuMzQxMTc2NDgwMSAwAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - 1 - 10 - - - - 1316 - {{37, 188}, {63, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Inferno - - - - 1 - 10 - - - - 1316 - {{37, 173}, {79, 18}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - EPISODE III - - - - 1 - 10 - - - - 1316 - {{37, 117}, {169, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - The Shores of Hell - - - - 1 - 10 - - - - 1316 - {{37, 102}, {75, 18}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - EPISODE II - - - - 1 - 10 - - - - 1316 - {{37, 44}, {212, 24}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - Knee-Deep in the Dead - - - - 1 - 10 - - - - 1316 - {{37, 29}, {71, 18}} - - NO - YES - 7 - NO - 2 - IBCocoaTouchFramework - EPISODE I - - - - 1 - 10 - - - {{68, 8}, {344, 304}} - - YES - YES - 2 - IBCocoaTouchFramework - - - {480, 320} - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - 3 - - 2 - IBCocoaTouchFramework - - - 3 - - 2 - IBCocoaTouchFramework - YES - - - - 274 - {320, 480} - - 3 - MQA - - - NO - IBCocoaTouchFramework - - - - - YES - - - delegate - - - - 4 - - - - window - - - - 5 - - - - glView - - - - 22 - - - - mediumSelection - - - - 309 - - - - MediumPressed - - - 7 - - 312 - - - - E1M7 - - - 7 - - 317 - - - - hardSelection - - - - 318 - - - - E1M8 - - - 7 - - 326 - - - - E1M5 - - - 7 - - 329 - - - - NightmarePressed - - - 7 - - 331 - - - - easySelection - - - - 332 - - - - E1M1 - - - 7 - - 340 - - - - E1M9 - - - 7 - - 341 - - - - EasyPressed - - - 7 - - 348 - - - - BackPressed - - - 7 - - 357 - - - - E1M2 - - - 7 - - 361 - - - - E1M6 - - - 7 - - 362 - - - - NightmareSelection - - - - 369 - - - - HardPressed - - - 7 - - 371 - - - - BackToMain - - - 7 - - 381 - - - - E1M3 - - - 7 - - 383 - - - - BackToMain - - - 7 - - 390 - - - - ResetToDefaults - - - 7 - - 393 - - - - BackToMain - - - 7 - - 395 - - - - BackToMain - - - 7 - - 396 - - - - E1M4 - - - 7 - - 400 - - - - controlsMenuViewController - - - - 402 - - - - creditsMenuViewController - - - - 403 - - - - legalMenuViewController - - - - 404 - - - - mainMenuViewController - - - - 405 - - - - mapMenuViewController - - - - 406 - - - - settingsMenuViewController - - - - 407 - - - - DirWheelPressed - - - 7 - - 415 - - - - DualThumbpadPressed - - - 7 - - 416 - - - - HudLayoutPressed - - - 7 - - 417 - - - - MoveStickValChanged - - - 13 - - 418 - - - - SingleThumbpadPressed - - - 7 - - 419 - - - - TiltMoveValChanged - - - 7 - - 420 - - - - TurnStickValChanged - - - 7 - - 421 - - - - movestickSize - - - - 422 - - - - tiltMoveSpeed - - - - 423 - - - - turnstickSize - - - - 424 - - - - singleThumbButton - - - - 453 - - - - dualThumbButton - - - - 454 - - - - dirWheelButton - - - - 455 - - - - scrollView - - - - 564 - - - - lastItem - - - - 565 - - - - TiltMoveValChanged - - - 7 - - 567 - - - - tiltTurnSpeed - - - - 569 - - - - TiltTurnValChanged - - - 13 - - 570 - - - - label - - - - 599 - - - - label - - - - 600 - - - - label - - - - 601 - - - - label - - - - 602 - - - - mPlaySubMenu - - - - 607 - - - - ShowPlayBanner - - - 7 - - 608 - - - - NewGamePressed - - - 7 - - 619 - - - - ShowExtrasBanner - - - 7 - - 624 - - - - ShowAboutBanner - - - 7 - - 625 - - - - ShowSettingsBanner - - - 7 - - 626 - - - - label - - - - 627 - - - - label - - - - 628 - - - - label - - - - 635 - - - - label - - - - 636 - - - - mSettingsSubMenu - - - - 638 - - - - ControlsOptionsPressed - - - 7 - - 639 - - - - SettingsOptionsPressed - - - 7 - - 640 - - - - label - - - - 648 - - - - label - - - - 653 - - - - label - - - - 655 - - - - LegalPressed - - - 7 - - 656 - - - - CreditsPressed - - - 7 - - 657 - - - - SupportPressed - - - 7 - - 658 - - - - mAboutSubMenu - - - - 659 - - - - label - - - - 680 - - - - label - - - - 681 - - - - DemoPressed - - - 7 - - 684 - - - - OtherIdGamesPressed - - - 7 - - 685 - - - - mExtrasSubMenu - - - - 686 - - - - mPlayButton - - - - 687 - - - - mSettingsButton - - - - 688 - - - - mExtrasButton - - - - 689 - - - - mAboutButton - - - - 690 - - - - label - - - - 774 - - - - label - - - - 775 - - - - BackToMain - - - 7 - - 784 - - - - SelectEpisode1 - - - 7 - - 785 - - - - SelectEpisode2 - - - 7 - - 786 - - - - SelectEpisode3 - - - 7 - - 787 - - - - SelectEpisode4 - - - 7 - - 788 - - - - episodeMenuViewController - - - - 789 - - - - label - - - - 790 - - - - label2 - - - - 791 - - - - label - - - - 792 - - - - label2 - - - - 793 - - - - label - - - - 794 - - - - label2 - - - - 795 - - - - label - - - - 796 - - - - label2 - - - - 797 - - - - NextToMissions - - - 7 - - 798 - - - - epi1Button - - - - 799 - - - - epi2Button - - - - 800 - - - - epi3Button - - - - 801 - - - - epi4Button - - - - 802 - - - - scrollView - - - - 804 - - - - lastItem - - - - 805 - - - - nextButton - - - - 806 - - - - nextLabel - - - - 807 - - - - E2M7 - - - 7 - - 848 - - - - E2M6 - - - 7 - - 852 - - - - E2M3 - - - 7 - - 853 - - - - E2M1 - - - 7 - - 857 - - - - E2M8 - - - 7 - - 858 - - - - E2M9 - - - 7 - - 861 - - - - E2M2 - - - 7 - - 873 - - - - E2M5 - - - 7 - - 874 - - - - E2M4 - - - 7 - - 875 - - - - E3M1 - - - 7 - - 922 - - - - E3M6 - - - 7 - - 927 - - - - E3M4 - - - 7 - - 932 - - - - E3M5 - - - 7 - - 933 - - - - E3M8 - - - 7 - - 935 - - - - E3M9 - - - 7 - - 939 - - - - E3M3 - - - 7 - - 951 - - - - E3M2 - - - 7 - - 952 - - - - E3M7 - - - 7 - - 953 - - - - E4M5 - - - 7 - - 991 - - - - E4M3 - - - 7 - - 992 - - - - E4M9 - - - 7 - - 996 - - - - E4M8 - - - 7 - - 1001 - - - - E4M7 - - - 7 - - 1011 - - - - E4M1 - - - 7 - - 1014 - - - - E4M2 - - - 7 - - 1017 - - - - E4M6 - - - 7 - - 1022 - - - - E4M4 - - - 7 - - 1023 - - - - mapScroller1 - - - - 1027 - - - - mapScroller2 - - - - 1028 - - - - mapScroller3 - - - - 1029 - - - - mapScroller4 - - - - 1030 - - - - lastElement1 - - - - 1031 - - - - lastElement2 - - - - 1032 - - - - lastElement3 - - - - 1033 - - - - lastElement4 - - - - 1034 - - - - label - - - - 1039 - - - - label - - - - 1041 - - - - easySelectionLabel - - - - 1046 - - - - hardSelectionLabel - - - - 1047 - - - - mediumSelectionLabel - - - - 1048 - - - - nightmareSelectionLabel - - - - 1049 - - - - UpMission - - - 1 - - 1062 - - - - DownMission - - - 1 - - 1063 - - - - Play - - - 7 - - 1064 - - - - playButton - - - - 1065 - - - - playLabel - - - - 1066 - - - - AutoUseChanged - - - 7 - - 1114 - - - - StatusBarChanged - - - 7 - - 1115 - - - - TouchClickChanged - - - 7 - - 1116 - - - - TextMessagesChanged - - - 7 - - 1117 - - - - DrawControlsChanged - - - 7 - - 1118 - - - - MusicChanged - - - 7 - - 1119 - - - - CenterSticksChanged - - - 7 - - 1120 - - - - RampTurnChanged - - - 7 - - 1121 - - - - autoUseSwitch - - - - 1122 - - - - centerSticksSwitch - - - - 1123 - - - - drawControlsSwitch - - - - 1124 - - - - musicSwitch - - - - 1125 - - - - rampTurnSwitch - - - - 1126 - - - - statusbarSwitch - - - - 1127 - - - - textMessageSwitch - - - - 1128 - - - - touchclickSwitch - - - - 1129 - - - - label - - - - 1138 - - - - label - - - - 1139 - - - - label - - - - 1140 - - - - label - - - - 1141 - - - - label - - - - 1142 - - - - label - - - - 1145 - - - - label - - - - 1147 - - - - ResumeGamePressed - - - 7 - - 1148 - - - - - YES - - 0 - - - - - - 2 - - - YES - - - - - -1 - - - File's Owner - - - 3 - - - Game App Delegate - - - -2 - - - - - 16 - - - GameView - - - 168 - - - YES - - - - SettingsMenuViewController - - - 169 - - - YES - - - - LegalMenuViewController - - - 170 - - - YES - - - - CreditsMenuViewController - - - 171 - - - YES - - - - ControlsMenuViewController - - - 172 - - - YES - - - - MapMenuViewController - - - 173 - - - YES - - - - MainMenuViewController - - - 190 - - - YES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 191 - - - YES - - - - - - - - - - - - Map Selection Scroll - - - 192 - - - - - 193 - - - - - 194 - - - - - 195 - - - - - 196 - - - - - 197 - - - - - 198 - - - - - 199 - - - - - 200 - - - - - 201 - - - Background - - - 209 - - - - - 210 - - - - - 211 - - - - - 212 - - - - - 213 - - - - - 215 - - - - - 220 - - - - - 223 - - - - - 238 - - - YES - - - - - - - - - - - - - - - - - - - - - - - ControlsMenuView - - - 239 - - - - - 240 - - - - - 241 - - - - - 242 - - - - - 243 - - - - - 244 - - - - - 245 - - - - - 246 - - - - - 247 - - - - - 248 - - - - - 249 - - - - - 250 - - - Background - - - 284 - - - YES - - - - - - - - - - - - - - - - - - - - - - - - SettingsMenuView - - - 285 - - - - - 286 - - - - - 287 - - - - - 288 - - - - - 289 - - - - - 290 - - - - - 291 - - - - - 292 - - - - - 301 - - - - - 302 - - - - - 303 - - - Background - - - 214 - - - - - 251 - - - YES - - - - - - - CreditsMenuView - - - 253 - - - Background - - - 254 - - - - - 530 - - - YES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 563 - - - - - 562 - - - - - 561 - - - - - 560 - - - - - 559 - - - - - 558 - - - - - 557 - - - - - 556 - - - - - 555 - - - - - 554 - - - - - 553 - - - - - 552 - - - - - 551 - - - - - 550 - - - - - 549 - - - - - 548 - - - - - 547 - - - - - 546 - - - - - 545 - - - - - 544 - - - - - 543 - - - - - 542 - - - - - 541 - - - - - 540 - - - - - 539 - - - - - 538 - - - - - 537 - - - - - 536 - - - - - 535 - - - - - 534 - - - - - 533 - - - - - 532 - - - - - 531 - - - - - 566 - - - - - 568 - - - - - 174 - - - YES - - - - - - - - - - - - - - - - - MainMenuView - - - 598 - - - - - 596 - - - - - 595 - - - - - 597 - - - - - 592 - - - Settings Button - - - 593 - - - About Button - - - 594 - - - Extras Button - - - 590 - - - Play Button - - - 591 - - - Logo - - - 189 - - - Background - - - 606 - - - YES - - - - - - - - Play SubMenu - - - 605 - - - - - 609 - - - New Game Button - - - 612 - - - - - 613 - - - Resume Game Button - - - 614 - - - - - 629 - - - YES - - - - - - - - Settings SubMenu - - - 630 - - - Controls Button - - - 631 - - - - - 632 - - - - - 633 - - - SettingsButton - - - 634 - - - - - 641 - - - YES - - - - - - - - - - About SubMenu - - - 642 - - - - - 643 - - - Credits Button - - - 644 - - - - - 645 - - - - - 646 - - - Legal Button - - - 651 - - - Support Button - - - 654 - - - - - 674 - - - YES - - - - - - - - Extras SubMenu - - - 679 - - - More Games Button - - - 678 - - - - - 677 - - - - - 676 - - - Demo Button - - - 675 - - - - - 691 - - - YES - - - - EpisodeViewController - - - 692 - - - YES - - - - - - - - - EpisodeMenuView - - - 697 - - - Background - - - 770 - - - - - 771 - - - - - 772 - - - - - 773 - - - - - 803 - - - YES - - - - - - - - - - - - - - - - - 766 - - - - - 767 - - - - - 768 - - - - - 769 - - - - - 782 - - - - - 783 - - - - - 781 - - - - - 780 - - - - - 779 - - - - - 778 - - - - - 777 - - - - - 776 - - - - - 808 - - - YES - - - - - - - - - - - - Map Selection Scroll - - - 825 - - - - - 826 - - - - - 828 - - - - - 829 - - - - - 830 - - - - - 831 - - - - - 838 - - - - - 839 - - - - - 840 - - - - - 881 - - - YES - - - - - - - - - - - - Map Selection Scroll - - - 954 - - - YES - - - - - - - - - - - - Map Selection Scroll - - - 956 - - - - - 957 - - - - - 958 - - - - - 959 - - - - - 960 - - - - - 961 - - - - - 988 - - - - - 989 - - - - - 990 - - - - - 894 - - - - - 896 - - - - - 889 - - - - - 892 - - - - - 891 - - - - - 914 - - - - - 893 - - - - - 890 - - - - - 895 - - - - - 409 - - - - - 1035 - - - - - 1036 - - - - - 1038 - - - - - 1040 - - - - - 1042 - - - - - 1043 - - - - - 1044 - - - - - 1045 - - - - - 1051 - - - - - 1052 - - - - - 1055 - - - - - 1050 - - - - - 1067 - - - - - 1068 - - - - - 1096 - - - - - 1100 - - - - - 1102 - - - - - 1104 - - - - - 1106 - - - - - 1108 - - - - - 1110 - - - - - 1112 - - - - - 1131 - - - - - 1132 - - - - - 1133 - - - - - 1134 - - - - - 1136 - - - - - 1137 - - - - - 280 - - - YES - - - - - - - - LegalMenuView - - - 410 - - - - - 283 - - - Background - - - 282 - - - - - 281 - - - - - 1144 - - - - - 1146 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1035.IBPluginDependency - 1035.IBViewBoundsToFrameTransform - 1036.CustomClassName - 1036.IBPluginDependency - 1036.IBViewBoundsToFrameTransform - 1038.CustomClassName - 1038.IBPluginDependency - 1038.IBViewBoundsToFrameTransform - 1040.CustomClassName - 1040.IBPluginDependency - 1040.IBViewBoundsToFrameTransform - 1042.CustomClassName - 1042.IBPluginDependency - 1042.IBViewBoundsToFrameTransform - 1043.CustomClassName - 1043.IBPluginDependency - 1043.IBViewBoundsToFrameTransform - 1044.CustomClassName - 1044.IBPluginDependency - 1044.IBViewBoundsToFrameTransform - 1045.CustomClassName - 1045.IBPluginDependency - 1045.IBViewBoundsToFrameTransform - 1050.CustomClassName - 1050.IBPluginDependency - 1050.IBViewBoundsToFrameTransform - 1051.CustomClassName - 1051.IBPluginDependency - 1051.IBViewBoundsToFrameTransform - 1052.CustomClassName - 1052.IBPluginDependency - 1052.IBViewBoundsToFrameTransform - 1055.CustomClassName - 1055.IBPluginDependency - 1055.IBViewBoundsToFrameTransform - 1067.CustomClassName - 1067.IBPluginDependency - 1067.IBViewBoundsToFrameTransform - 1068.CustomClassName - 1068.IBPluginDependency - 1068.IBViewBoundsToFrameTransform - 1096.CustomClassName - 1096.IBPluginDependency - 1096.IBViewBoundsToFrameTransform - 1100.CustomClassName - 1100.IBPluginDependency - 1100.IBViewBoundsToFrameTransform - 1102.CustomClassName - 1102.IBPluginDependency - 1102.IBViewBoundsToFrameTransform - 1104.CustomClassName - 1104.IBPluginDependency - 1104.IBViewBoundsToFrameTransform - 1106.CustomClassName - 1106.IBPluginDependency - 1106.IBViewBoundsToFrameTransform - 1108.CustomClassName - 1108.IBPluginDependency - 1108.IBViewBoundsToFrameTransform - 1110.CustomClassName - 1110.IBPluginDependency - 1110.IBViewBoundsToFrameTransform - 1112.CustomClassName - 1112.IBPluginDependency - 1112.IBViewBoundsToFrameTransform - 1131.CustomClassName - 1131.IBPluginDependency - 1131.IBViewBoundsToFrameTransform - 1132.CustomClassName - 1132.IBPluginDependency - 1132.IBViewBoundsToFrameTransform - 1133.CustomClassName - 1133.IBPluginDependency - 1133.IBViewBoundsToFrameTransform - 1134.IBPluginDependency - 1134.IBViewBoundsToFrameTransform - 1136.CustomClassName - 1136.IBPluginDependency - 1136.IBViewBoundsToFrameTransform - 1137.CustomClassName - 1137.IBPluginDependency - 1137.IBViewBoundsToFrameTransform - 1144.CustomClassName - 1144.IBPluginDependency - 1144.IBViewBoundsToFrameTransform - 1146.CustomClassName - 1146.IBPluginDependency - 1146.IBViewBoundsToFrameTransform - 16.CustomClassName - 16.IBEditorWindowLastContentRect - 16.IBPluginDependency - 16.IBViewBoundsToFrameTransform - 168.CustomClassName - 168.IBEditorWindowLastContentRect - 168.IBPluginDependency - 169.CustomClassName - 169.IBEditorWindowLastContentRect - 169.IBPluginDependency - 170.CustomClassName - 170.IBEditorWindowLastContentRect - 170.IBPluginDependency - 171.CustomClassName - 171.IBEditorWindowLastContentRect - 171.IBPluginDependency - 172.CustomClassName - 172.IBEditorWindowLastContentRect - 172.IBPluginDependency - 173.CustomClassName - 173.IBEditorWindowLastContentRect - 173.IBPluginDependency - 174.CustomClassName - 174.IBEditorWindowLastContentRect - 174.IBPluginDependency - 174.IBViewBoundsToFrameTransform - 189.IBPluginDependency - 189.IBViewBoundsToFrameTransform - 190.CustomClassName - 190.IBPluginDependency - 191.IBViewBoundsToFrameTransform - 192.IBPluginDependency - 192.IBViewBoundsToFrameTransform - 193.IBPluginDependency - 193.IBViewBoundsToFrameTransform - 194.IBPluginDependency - 194.IBViewBoundsToFrameTransform - 195.IBPluginDependency - 195.IBViewBoundsToFrameTransform - 196.IBPluginDependency - 196.IBViewBoundsToFrameTransform - 197.IBPluginDependency - 197.IBViewBoundsToFrameTransform - 198.IBPluginDependency - 198.IBViewBoundsToFrameTransform - 199.IBPluginDependency - 199.IBViewBoundsToFrameTransform - 2.IBAttributePlaceholdersKey - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 2.IBViewBoundsToFrameTransform - 200.CustomClassName - 200.IBPluginDependency - 200.IBViewBoundsToFrameTransform - 201.IBPluginDependency - 201.IBViewBoundsToFrameTransform - 209.CustomClassName - 209.IBPluginDependency - 209.IBViewBoundsToFrameTransform - 210.CustomClassName - 210.IBPluginDependency - 210.IBViewBoundsToFrameTransform - 211.CustomClassName - 211.IBPluginDependency - 211.IBViewBoundsToFrameTransform - 212.CustomClassName - 212.IBPluginDependency - 212.IBViewBoundsToFrameTransform - 213.CustomClassName - 213.IBPluginDependency - 213.IBViewBoundsToFrameTransform - 214.CustomClassName - 214.IBPluginDependency - 214.IBViewBoundsToFrameTransform - 215.CustomClassName - 215.IBPluginDependency - 215.IBViewBoundsToFrameTransform - 220.CustomClassName - 220.IBPluginDependency - 220.IBViewBoundsToFrameTransform - 223.CustomClassName - 223.IBPluginDependency - 223.IBViewBoundsToFrameTransform - 238.CustomClassName - 238.IBEditorWindowLastContentRect - 238.IBPluginDependency - 238.IBViewBoundsToFrameTransform - 239.CustomClassName - 239.IBPluginDependency - 239.IBViewBoundsToFrameTransform - 240.CustomClassName - 240.IBPluginDependency - 240.IBViewBoundsToFrameTransform - 241.CustomClassName - 241.IBPluginDependency - 241.IBViewBoundsToFrameTransform - 242.CustomClassName - 242.IBPluginDependency - 242.IBViewBoundsToFrameTransform - 243.CustomClassName - 243.IBPluginDependency - 243.IBViewBoundsToFrameTransform - 244.CustomClassName - 244.IBPluginDependency - 244.IBViewBoundsToFrameTransform - 245.CustomClassName - 245.IBPluginDependency - 245.IBViewBoundsToFrameTransform - 246.CustomClassName - 246.IBPluginDependency - 246.IBViewBoundsToFrameTransform - 247.CustomClassName - 247.IBPluginDependency - 247.IBViewBoundsToFrameTransform - 248.CustomClassName - 248.IBPluginDependency - 248.IBViewBoundsToFrameTransform - 249.CustomClassName - 249.IBPluginDependency - 249.IBViewBoundsToFrameTransform - 250.IBPluginDependency - 250.IBViewBoundsToFrameTransform - 251.CustomClassName - 251.IBEditorWindowLastContentRect - 251.IBPluginDependency - 251.IBViewBoundsToFrameTransform - 253.IBPluginDependency - 253.IBViewBoundsToFrameTransform - 254.CustomClassName - 254.IBPluginDependency - 254.IBViewBoundsToFrameTransform - 280.CustomClassName - 280.IBEditorWindowLastContentRect - 280.IBPluginDependency - 280.IBViewBoundsToFrameTransform - 281.CustomClassName - 281.IBPluginDependency - 281.IBViewBoundsToFrameTransform - 282.CustomClassName - 282.IBPluginDependency - 283.IBPluginDependency - 283.IBViewBoundsToFrameTransform - 284.CustomClassName - 284.IBEditorWindowLastContentRect - 284.IBPluginDependency - 284.IBViewBoundsToFrameTransform - 285.CustomClassName - 285.IBPluginDependency - 285.IBViewBoundsToFrameTransform - 286.CustomClassName - 286.IBPluginDependency - 286.IBViewBoundsToFrameTransform - 287.CustomClassName - 287.IBPluginDependency - 287.IBViewBoundsToFrameTransform - 288.CustomClassName - 288.IBPluginDependency - 288.IBViewBoundsToFrameTransform - 289.CustomClassName - 289.IBPluginDependency - 289.IBViewBoundsToFrameTransform - 290.CustomClassName - 290.IBPluginDependency - 290.IBViewBoundsToFrameTransform - 291.CustomClassName - 291.IBPluginDependency - 291.IBViewBoundsToFrameTransform - 292.CustomClassName - 292.IBPluginDependency - 292.IBViewBoundsToFrameTransform - 3.CustomClassName - 3.IBPluginDependency - 301.CustomClassName - 301.IBPluginDependency - 301.IBViewBoundsToFrameTransform - 302.CustomClassName - 302.IBPluginDependency - 302.IBViewBoundsToFrameTransform - 303.IBPluginDependency - 303.IBViewBoundsToFrameTransform - 409.IBPluginDependency - 409.IBViewBoundsToFrameTransform - 410.IBPluginDependency - 410.IBViewBoundsToFrameTransform - 530.IBViewBoundsToFrameTransform - 531.CustomClassName - 531.IBPluginDependency - 531.IBViewBoundsToFrameTransform - 532.CustomClassName - 532.IBPluginDependency - 532.IBViewBoundsToFrameTransform - 533.CustomClassName - 533.IBPluginDependency - 533.IBViewBoundsToFrameTransform - 534.CustomClassName - 534.IBPluginDependency - 534.IBViewBoundsToFrameTransform - 535.CustomClassName - 535.IBPluginDependency - 535.IBViewBoundsToFrameTransform - 536.CustomClassName - 536.IBPluginDependency - 536.IBViewBoundsToFrameTransform - 537.CustomClassName - 537.IBPluginDependency - 537.IBViewBoundsToFrameTransform - 538.CustomClassName - 538.IBPluginDependency - 538.IBViewBoundsToFrameTransform - 539.CustomClassName - 539.IBPluginDependency - 539.IBViewBoundsToFrameTransform - 540.CustomClassName - 540.IBPluginDependency - 540.IBViewBoundsToFrameTransform - 541.CustomClassName - 541.IBPluginDependency - 541.IBViewBoundsToFrameTransform - 542.CustomClassName - 542.IBPluginDependency - 542.IBViewBoundsToFrameTransform - 543.CustomClassName - 543.IBPluginDependency - 543.IBViewBoundsToFrameTransform - 544.CustomClassName - 544.IBPluginDependency - 544.IBViewBoundsToFrameTransform - 545.CustomClassName - 545.IBPluginDependency - 545.IBViewBoundsToFrameTransform - 546.CustomClassName - 546.IBPluginDependency - 546.IBViewBoundsToFrameTransform - 547.CustomClassName - 547.IBPluginDependency - 547.IBViewBoundsToFrameTransform - 548.CustomClassName - 548.IBPluginDependency - 548.IBViewBoundsToFrameTransform - 549.CustomClassName - 549.IBPluginDependency - 549.IBViewBoundsToFrameTransform - 550.CustomClassName - 550.IBPluginDependency - 550.IBViewBoundsToFrameTransform - 551.CustomClassName - 551.IBPluginDependency - 551.IBViewBoundsToFrameTransform - 552.CustomClassName - 552.IBPluginDependency - 552.IBViewBoundsToFrameTransform - 553.CustomClassName - 553.IBPluginDependency - 553.IBViewBoundsToFrameTransform - 554.CustomClassName - 554.IBPluginDependency - 554.IBViewBoundsToFrameTransform - 555.CustomClassName - 555.IBPluginDependency - 555.IBViewBoundsToFrameTransform - 556.CustomClassName - 556.IBPluginDependency - 556.IBViewBoundsToFrameTransform - 557.CustomClassName - 557.IBPluginDependency - 557.IBViewBoundsToFrameTransform - 558.CustomClassName - 558.IBPluginDependency - 558.IBViewBoundsToFrameTransform - 559.CustomClassName - 559.IBPluginDependency - 559.IBViewBoundsToFrameTransform - 560.CustomClassName - 560.IBPluginDependency - 560.IBViewBoundsToFrameTransform - 561.CustomClassName - 561.IBPluginDependency - 561.IBViewBoundsToFrameTransform - 562.CustomClassName - 562.IBPluginDependency - 562.IBViewBoundsToFrameTransform - 563.CustomClassName - 563.IBPluginDependency - 563.IBViewBoundsToFrameTransform - 566.CustomClassName - 566.IBPluginDependency - 566.IBViewBoundsToFrameTransform - 568.CustomClassName - 568.IBPluginDependency - 568.IBViewBoundsToFrameTransform - 590.CustomClassName - 590.IBPluginDependency - 590.IBViewBoundsToFrameTransform - 591.IBPluginDependency - 591.IBViewBoundsToFrameTransform - 592.CustomClassName - 592.IBPluginDependency - 592.IBViewBoundsToFrameTransform - 593.CustomClassName - 593.IBPluginDependency - 593.IBViewBoundsToFrameTransform - 594.CustomClassName - 594.IBPluginDependency - 594.IBViewBoundsToFrameTransform - 595.CustomClassName - 595.IBPluginDependency - 595.IBViewBoundsToFrameTransform - 596.CustomClassName - 596.IBPluginDependency - 596.IBViewBoundsToFrameTransform - 597.CustomClassName - 597.IBPluginDependency - 597.IBViewBoundsToFrameTransform - 598.CustomClassName - 598.IBPluginDependency - 598.IBViewBoundsToFrameTransform - 605.IBPluginDependency - 605.IBViewBoundsToFrameTransform - 606.CustomClassName - 606.IBPluginDependency - 606.IBViewBoundsToFrameTransform - 609.CustomClassName - 609.IBPluginDependency - 609.IBViewBoundsToFrameTransform - 612.CustomClassName - 612.IBPluginDependency - 612.IBViewBoundsToFrameTransform - 613.CustomClassName - 613.IBPluginDependency - 613.IBViewBoundsToFrameTransform - 614.CustomClassName - 614.IBPluginDependency - 614.IBViewBoundsToFrameTransform - 629.CustomClassName - 629.IBPluginDependency - 629.IBViewBoundsToFrameTransform - 630.CustomClassName - 630.IBPluginDependency - 630.IBViewBoundsToFrameTransform - 631.CustomClassName - 631.IBPluginDependency - 631.IBViewBoundsToFrameTransform - 632.CustomClassName - 632.IBPluginDependency - 632.IBViewBoundsToFrameTransform - 633.CustomClassName - 633.IBPluginDependency - 633.IBViewBoundsToFrameTransform - 634.IBPluginDependency - 634.IBViewBoundsToFrameTransform - 641.CustomClassName - 641.IBPluginDependency - 641.IBViewBoundsToFrameTransform - 642.IBPluginDependency - 642.IBViewBoundsToFrameTransform - 643.CustomClassName - 643.IBPluginDependency - 643.IBViewBoundsToFrameTransform - 644.CustomClassName - 644.IBPluginDependency - 644.IBViewBoundsToFrameTransform - 645.CustomClassName - 645.IBPluginDependency - 645.IBViewBoundsToFrameTransform - 646.CustomClassName - 646.IBPluginDependency - 646.IBViewBoundsToFrameTransform - 651.CustomClassName - 651.IBPluginDependency - 651.IBViewBoundsToFrameTransform - 654.CustomClassName - 654.IBPluginDependency - 654.IBViewBoundsToFrameTransform - 674.CustomClassName - 674.IBPluginDependency - 674.IBViewBoundsToFrameTransform - 675.IBPluginDependency - 675.IBViewBoundsToFrameTransform - 676.CustomClassName - 676.IBPluginDependency - 676.IBViewBoundsToFrameTransform - 677.CustomClassName - 677.IBPluginDependency - 677.IBViewBoundsToFrameTransform - 678.CustomClassName - 678.IBPluginDependency - 678.IBViewBoundsToFrameTransform - 679.CustomClassName - 679.IBPluginDependency - 679.IBViewBoundsToFrameTransform - 691.CustomClassName - 691.IBEditorWindowLastContentRect - 691.IBPluginDependency - 692.CustomClassName - 692.IBEditorWindowLastContentRect - 692.IBPluginDependency - 692.IBViewBoundsToFrameTransform - 697.IBPluginDependency - 697.IBViewBoundsToFrameTransform - 766.CustomClassName - 766.IBPluginDependency - 766.IBViewBoundsToFrameTransform - 767.CustomClassName - 767.IBPluginDependency - 767.IBViewBoundsToFrameTransform - 768.CustomClassName - 768.IBPluginDependency - 768.IBViewBoundsToFrameTransform - 769.CustomClassName - 769.IBPluginDependency - 769.IBViewBoundsToFrameTransform - 770.CustomClassName - 770.IBPluginDependency - 770.IBViewBoundsToFrameTransform - 771.CustomClassName - 771.IBPluginDependency - 771.IBViewBoundsToFrameTransform - 772.CustomClassName - 772.IBPluginDependency - 772.IBViewBoundsToFrameTransform - 773.CustomClassName - 773.IBPluginDependency - 773.IBViewBoundsToFrameTransform - 776.CustomClassName - 776.IBPluginDependency - 776.IBViewBoundsToFrameTransform - 777.CustomClassName - 777.IBPluginDependency - 777.IBViewBoundsToFrameTransform - 778.CustomClassName - 778.IBPluginDependency - 778.IBViewBoundsToFrameTransform - 779.CustomClassName - 779.IBPluginDependency - 779.IBViewBoundsToFrameTransform - 780.CustomClassName - 780.IBPluginDependency - 780.IBViewBoundsToFrameTransform - 781.CustomClassName - 781.IBPluginDependency - 781.IBViewBoundsToFrameTransform - 782.CustomClassName - 782.IBPluginDependency - 782.IBViewBoundsToFrameTransform - 783.CustomClassName - 783.IBPluginDependency - 783.IBViewBoundsToFrameTransform - 803.IBViewBoundsToFrameTransform - 808.IBViewBoundsToFrameTransform - 825.CustomClassName - 825.IBPluginDependency - 825.IBViewBoundsToFrameTransform - 826.CustomClassName - 826.IBPluginDependency - 826.IBViewBoundsToFrameTransform - 828.CustomClassName - 828.IBPluginDependency - 828.IBViewBoundsToFrameTransform - 829.CustomClassName - 829.IBPluginDependency - 829.IBViewBoundsToFrameTransform - 830.CustomClassName - 830.IBPluginDependency - 830.IBViewBoundsToFrameTransform - 831.CustomClassName - 831.IBPluginDependency - 831.IBViewBoundsToFrameTransform - 838.CustomClassName - 838.IBPluginDependency - 838.IBViewBoundsToFrameTransform - 839.CustomClassName - 839.IBPluginDependency - 839.IBViewBoundsToFrameTransform - 840.CustomClassName - 840.IBPluginDependency - 840.IBViewBoundsToFrameTransform - 881.IBViewBoundsToFrameTransform - 889.CustomClassName - 889.IBPluginDependency - 889.IBViewBoundsToFrameTransform - 890.CustomClassName - 890.IBPluginDependency - 890.IBViewBoundsToFrameTransform - 891.CustomClassName - 891.IBPluginDependency - 891.IBViewBoundsToFrameTransform - 892.CustomClassName - 892.IBPluginDependency - 892.IBViewBoundsToFrameTransform - 893.CustomClassName - 893.IBPluginDependency - 893.IBViewBoundsToFrameTransform - 894.CustomClassName - 894.IBPluginDependency - 894.IBViewBoundsToFrameTransform - 895.CustomClassName - 895.IBPluginDependency - 895.IBViewBoundsToFrameTransform - 896.CustomClassName - 896.IBPluginDependency - 896.IBViewBoundsToFrameTransform - 914.CustomClassName - 914.IBPluginDependency - 914.IBViewBoundsToFrameTransform - 954.IBViewBoundsToFrameTransform - 956.CustomClassName - 956.IBPluginDependency - 956.IBViewBoundsToFrameTransform - 957.CustomClassName - 957.IBPluginDependency - 957.IBViewBoundsToFrameTransform - 958.CustomClassName - 958.IBPluginDependency - 958.IBViewBoundsToFrameTransform - 959.CustomClassName - 959.IBPluginDependency - 959.IBViewBoundsToFrameTransform - 960.CustomClassName - 960.IBPluginDependency - 960.IBViewBoundsToFrameTransform - 961.CustomClassName - 961.IBPluginDependency - 961.IBViewBoundsToFrameTransform - 988.CustomClassName - 988.IBPluginDependency - 988.IBViewBoundsToFrameTransform - 989.CustomClassName - 989.IBPluginDependency - 989.IBViewBoundsToFrameTransform - 990.CustomClassName - 990.IBPluginDependency - 990.IBViewBoundsToFrameTransform - - - YES - UIApplication - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDrQAAwzCAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUPNAABBoAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUPPAABAwAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD0EAAwdwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULIAABDkQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUNFgABDkUAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUOJgABDkQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUOxQABDkUAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCqgAAw2EAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCqgAAwiQAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDVQAAwZgAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDWAAAw1AAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUPOAABDcAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUEQAABDgYAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDKwAAwo4AAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDKwAAwuYAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDKwAAwycAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDKwAAw14AAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUO0gABCBAAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUO0gABCmgAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUO0gABDAQAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDtcAAwymAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIIAABCtgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUM4AABCtgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUOngABCtgAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIQAABC3gAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUEQAABDgYAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUPQgABDgYAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBEAAAw4qAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBEAAAw4qAAA - - EAGLView - {{608, 311}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw+8AAA - - MenuViewController - {{802, 337}, {960, 640}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{498, 435}, {960, 640}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{648, 384}, {960, 640}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{629, 342}, {960, 640}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{572, 550}, {960, 640}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{629, 790}, {960, 640}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MainMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - MapMenuView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULAAABCOAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCpgAAw0cAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDegAAw4wAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCwAAAw4wAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABB4AAAw2EAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwzQAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwvQAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCwAAAwlwAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwnAAAA - - - YES - - - YES - - - {{500, 343}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw+8AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwogAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAADDBwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDp4AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABDPAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABDiwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABCTAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABCwAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABDDwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDvgAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABAwAAAA - - ControlsMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw5wAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIQAABDUAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIQAABDLwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIQAABDDQAAA - - UICustomSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCCAAAw1EAAA - - UICustomSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCCAAAwzEAAA - - UICustomSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABB2AAAwxYAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD1IAAw5wAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDrAAAwwcAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDLAAAwwcAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAADCAgAAwxeAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - GenericMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBMAAAwlQAAA - - GenericMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - SettingsMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDggAAw1EAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDdQAAwx0AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDloAAwuwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDbAAAwpYAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBEAAAw1EAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCNAAAwx0AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCkgAAwtYAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCWAAAwmwAAA - - gameAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDegAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDkoAAw6SAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC8AAAw58AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULmAABCIAAAA - - - P4AAAL+AAABCAAAAw4UAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxBjAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEcsAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxBQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxA8AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxAkAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxAIAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxEHAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxDnAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEQAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEOwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEMQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEKQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEJAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEGgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEEgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEDUAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEA0AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABD8oAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw+2AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAw3cAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAw1EAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDXAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwrgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw6YAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw5YAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDmwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABCXAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABCtgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwykAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwyQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDLgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDSAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIkAABDqwAAA - - UICustomSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCCAAAw3cAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIQAABDcwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUFwAABDC4AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC8gAAw7IAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC8wAAw5dAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDfQAAw5oAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDe4AAw5HAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUEgAABDYAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDBgAAw5UAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUOAgABDjIAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDgcAAw5dAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AQAAAADBeAAAA - - Banner_SubMenu - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULqAABCRAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC8AAAwwYAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUODAABCRAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUN2AABC4gAAA - - Banner_SubMenu - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULqAABCRAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUN2AABC4gAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC8AAAwwYAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUODAABCRAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AQAAAADBeAAAA - - Banner_SubMenu - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AQAAAADBeAAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDgwAAwwwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIkAABC4gAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDmwAAwwYAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC6gAAwwwAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDMAAAwwwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDoAAAwygAAA - - Banner_SubMenu - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AQAAAADBeAAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUODAABCRAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCxgAAwwYAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUN2AABC4gAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULqAABCRAAAA - - MenuViewController - {{560, 793}, {960, 640}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - GenericMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUKgAABBYAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCpQAAwrsAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDToAAwzKAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDToAAwzKAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBUAAAw5mAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDywAAwoQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUPOAAAAAAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABB0AAAwZgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABCKAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABCZAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABC6gAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABDBAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABDNwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABDRgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC2QAAw0yAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC2QAAw16AAA - - - P4AAAL+AAABCiAAAw6EAAA - - - P4AAAL+AAABD1oAAw5uAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABD5QAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABDzoAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEFEAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABD+4AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDi4AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDPQAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABAwAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEKsAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDuIAAA - - - P4AAAL+AAABD1oAAw5uAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEjaAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxCsAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEYwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEV8AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEgmAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEbkAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxBSAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw/wAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxDjAAA - - - P4AAAL+AAABD1oAAw5uAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEnoAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEr2AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEpCAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxH3AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxGdAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxEWAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxImgAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEuqAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxI9AAA - - - - - YES - - - YES - - - - - YES - - - YES - - - - 1148 - - - - YES - - Banner_SubItem - UIFontButton - - IBProjectSource - MainMenuView.h - - - - Banner_SubMenu - UIView - - - - ControlsMenuView - UIView - - YES - - YES - BackToMain - DirWheelPressed - DualThumbpadPressed - HudLayoutPressed - MoveStickValChanged - SingleThumbpadPressed - TiltMoveValChanged - TiltTurnValChanged - TurnStickValChanged - - - YES - id - id - id - id - id - id - id - id - id - - - - YES - - YES - BackToMain - DirWheelPressed - DualThumbpadPressed - HudLayoutPressed - MoveStickValChanged - SingleThumbpadPressed - TiltMoveValChanged - TiltTurnValChanged - TurnStickValChanged - - - YES - - BackToMain - id - - - DirWheelPressed - id - - - DualThumbpadPressed - id - - - HudLayoutPressed - id - - - MoveStickValChanged - id - - - SingleThumbpadPressed - id - - - TiltMoveValChanged - id - - - TiltTurnValChanged - id - - - TurnStickValChanged - id - - - - - YES - - YES - dirWheelButton - dualThumbButton - movestickSize - singleThumbButton - tiltMoveSpeed - tiltTurnSpeed - turnstickSize - - - YES - UIButton - UIButton - UISlider - UIButton - UISlider - UISlider - UISlider - - - - YES - - YES - dirWheelButton - dualThumbButton - movestickSize - singleThumbButton - tiltMoveSpeed - tiltTurnSpeed - turnstickSize - - - YES - - dirWheelButton - UIButton - - - dualThumbButton - UIButton - - - movestickSize - UISlider - - - singleThumbButton - UIButton - - - tiltMoveSpeed - UISlider - - - tiltTurnSpeed - UISlider - - - turnstickSize - UISlider - - - - - IBProjectSource - ControlsMenuView.h - - - - EAGLView - UIView - - IBProjectSource - EAGLView.h - - - - GenericMenuView - UIView - - YES - - YES - BackToMain - NextToMissions - SelectEpisode1 - SelectEpisode2 - SelectEpisode3 - SelectEpisode4 - - - YES - id - id - id - id - id - id - - - - YES - - YES - BackToMain - NextToMissions - SelectEpisode1 - SelectEpisode2 - SelectEpisode3 - SelectEpisode4 - - - YES - - BackToMain - id - - - NextToMissions - id - - - SelectEpisode1 - id - - - SelectEpisode2 - id - - - SelectEpisode3 - id - - - SelectEpisode4 - id - - - - - YES - - YES - epi1Button - epi2Button - epi3Button - epi4Button - lastItem - nextButton - nextLabel - scrollView - - - YES - UIFontButton - UIFontButton - UIFontButton - UIFontButton - UILabel - UIFontButton - UIFontLabel - UIScrollView - - - - YES - - YES - epi1Button - epi2Button - epi3Button - epi4Button - lastItem - nextButton - nextLabel - scrollView - - - YES - - epi1Button - UIFontButton - - - epi2Button - UIFontButton - - - epi3Button - UIFontButton - - - epi4Button - UIFontButton - - - lastItem - UILabel - - - nextButton - UIFontButton - - - nextLabel - UIFontLabel - - - scrollView - UIScrollView - - - - - IBProjectSource - GenericMenuView.h - - - - MainMenuView - UIView - - YES - - YES - ControlsOptionsPressed - CreditsPressed - DemoPressed - LegalPressed - MultiplayerPressed - NewGamePressed - OtherIdGamesPressed - ResumeGamePressed - SettingsOptionsPressed - ShowAboutBanner - ShowExtrasBanner - ShowPlayBanner - ShowSettingsBanner - SupportPressed - - - YES - id - id - id - id - id - id - id - id - id - id - id - id - id - id - - - - YES - - YES - ControlsOptionsPressed - CreditsPressed - DemoPressed - LegalPressed - MultiplayerPressed - NewGamePressed - OtherIdGamesPressed - ResumeGamePressed - SettingsOptionsPressed - ShowAboutBanner - ShowExtrasBanner - ShowPlayBanner - ShowSettingsBanner - SupportPressed - - - YES - - ControlsOptionsPressed - id - - - CreditsPressed - id - - - DemoPressed - id - - - LegalPressed - id - - - MultiplayerPressed - id - - - NewGamePressed - id - - - OtherIdGamesPressed - id - - - ResumeGamePressed - id - - - SettingsOptionsPressed - id - - - ShowAboutBanner - id - - - ShowExtrasBanner - id - - - ShowPlayBanner - id - - - ShowSettingsBanner - id - - - SupportPressed - id - - - - - YES - - YES - mAboutButton - mAboutSubMenu - mExtrasButton - mExtrasSubMenu - mPlayButton - mPlaySubMenu - mSettingsButton - mSettingsSubMenu - - - YES - UIFontButton - Banner_SubMenu - UIFontButton - Banner_SubMenu - UIFontButton - Banner_SubMenu - UIFontButton - Banner_SubMenu - - - - YES - - YES - mAboutButton - mAboutSubMenu - mExtrasButton - mExtrasSubMenu - mPlayButton - mPlaySubMenu - mSettingsButton - mSettingsSubMenu - - - YES - - mAboutButton - UIFontButton - - - mAboutSubMenu - Banner_SubMenu - - - mExtrasButton - UIFontButton - - - mExtrasSubMenu - Banner_SubMenu - - - mPlayButton - UIFontButton - - - mPlaySubMenu - Banner_SubMenu - - - mSettingsButton - UIFontButton - - - mSettingsSubMenu - Banner_SubMenu - - - - - - - MapMenuView - UIView - - YES - - YES - BackPressed - DownMission - E1M1 - E1M2 - E1M3 - E1M4 - E1M5 - E1M6 - E1M7 - E1M8 - E1M9 - E2M1 - E2M2 - E2M3 - E2M4 - E2M5 - E2M6 - E2M7 - E2M8 - E2M9 - E3M1 - E3M2 - E3M3 - E3M4 - E3M5 - E3M6 - E3M7 - E3M8 - E3M9 - E4M1 - E4M2 - E4M3 - E4M4 - E4M5 - E4M6 - E4M7 - E4M8 - E4M9 - EasyPressed - HardPressed - MediumPressed - NightmarePressed - Play - UpMission - - - YES - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - - - - YES - - YES - BackPressed - DownMission - E1M1 - E1M2 - E1M3 - E1M4 - E1M5 - E1M6 - E1M7 - E1M8 - E1M9 - E2M1 - E2M2 - E2M3 - E2M4 - E2M5 - E2M6 - E2M7 - E2M8 - E2M9 - E3M1 - E3M2 - E3M3 - E3M4 - E3M5 - E3M6 - E3M7 - E3M8 - E3M9 - E4M1 - E4M2 - E4M3 - E4M4 - E4M5 - E4M6 - E4M7 - E4M8 - E4M9 - EasyPressed - HardPressed - MediumPressed - NightmarePressed - Play - UpMission - - - YES - - BackPressed - id - - - DownMission - id - - - E1M1 - id - - - E1M2 - id - - - E1M3 - id - - - E1M4 - id - - - E1M5 - id - - - E1M6 - id - - - E1M7 - id - - - E1M8 - id - - - E1M9 - id - - - E2M1 - id - - - E2M2 - id - - - E2M3 - id - - - E2M4 - id - - - E2M5 - id - - - E2M6 - id - - - E2M7 - id - - - E2M8 - id - - - E2M9 - id - - - E3M1 - id - - - E3M2 - id - - - E3M3 - id - - - E3M4 - id - - - E3M5 - id - - - E3M6 - id - - - E3M7 - id - - - E3M8 - id - - - E3M9 - id - - - E4M1 - id - - - E4M2 - id - - - E4M3 - id - - - E4M4 - id - - - E4M5 - id - - - E4M6 - id - - - E4M7 - id - - - E4M8 - id - - - E4M9 - id - - - EasyPressed - id - - - HardPressed - id - - - MediumPressed - id - - - NightmarePressed - id - - - Play - id - - - UpMission - id - - - - - YES - - YES - NightmareSelection - easySelection - easySelectionLabel - hardSelection - hardSelectionLabel - lastElement1 - lastElement2 - lastElement3 - lastElement4 - mapScroller1 - mapScroller2 - mapScroller3 - mapScroller4 - mediumSelection - mediumSelectionLabel - nightmareSelectionLabel - playButton - playLabel - - - YES - UIImageView - UIImageView - UIFontLabel - UIImageView - UIFontLabel - UIButton - UIButton - UIButton - UIButton - UIScrollView - UIScrollView - UIScrollView - UIScrollView - UIImageView - UIFontLabel - UIFontLabel - UIFontButton - UIFontLabel - - - - YES - - YES - NightmareSelection - easySelection - easySelectionLabel - hardSelection - hardSelectionLabel - lastElement1 - lastElement2 - lastElement3 - lastElement4 - mapScroller1 - mapScroller2 - mapScroller3 - mapScroller4 - mediumSelection - mediumSelectionLabel - nightmareSelectionLabel - playButton - playLabel - - - YES - - NightmareSelection - UIImageView - - - easySelection - UIImageView - - - easySelectionLabel - UIFontLabel - - - hardSelection - UIImageView - - - hardSelectionLabel - UIFontLabel - - - lastElement1 - UIButton - - - lastElement2 - UIButton - - - lastElement3 - UIButton - - - lastElement4 - UIButton - - - mapScroller1 - UIScrollView - - - mapScroller2 - UIScrollView - - - mapScroller3 - UIScrollView - - - mapScroller4 - UIScrollView - - - mediumSelection - UIImageView - - - mediumSelectionLabel - UIFontLabel - - - nightmareSelectionLabel - UIFontLabel - - - playButton - UIFontButton - - - playLabel - UIFontLabel - - - - - IBProjectSource - MapMenuView.h - - - - MenuViewController - UIViewController - - IBProjectSource - MenuViewController.h - - - - SettingsMenuView - UIImageView - - YES - - YES - AutoUseChanged - BackToMain - CenterSticksChanged - DrawControlsChanged - MusicChanged - RampTurnChanged - ResetToDefaults - StatusBarChanged - TextMessagesChanged - TouchClickChanged - - - YES - id - id - id - id - id - id - id - id - id - id - - - - YES - - YES - AutoUseChanged - BackToMain - CenterSticksChanged - DrawControlsChanged - MusicChanged - RampTurnChanged - ResetToDefaults - StatusBarChanged - TextMessagesChanged - TouchClickChanged - - - YES - - AutoUseChanged - id - - - BackToMain - id - - - CenterSticksChanged - id - - - DrawControlsChanged - id - - - MusicChanged - id - - - RampTurnChanged - id - - - ResetToDefaults - id - - - StatusBarChanged - id - - - TextMessagesChanged - id - - - TouchClickChanged - id - - - - - YES - - YES - autoUseSwitch - centerSticksSwitch - drawControlsSwitch - musicSwitch - rampTurnSwitch - statusbarSwitch - textMessageSwitch - touchclickSwitch - - - YES - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - - - - YES - - YES - autoUseSwitch - centerSticksSwitch - drawControlsSwitch - musicSwitch - rampTurnSwitch - statusbarSwitch - textMessageSwitch - touchclickSwitch - - - YES - - autoUseSwitch - UICustomSwitch - - - centerSticksSwitch - UICustomSwitch - - - drawControlsSwitch - UICustomSwitch - - - musicSwitch - UICustomSwitch - - - rampTurnSwitch - UICustomSwitch - - - statusbarSwitch - UICustomSwitch - - - textMessageSwitch - UICustomSwitch - - - touchclickSwitch - UICustomSwitch - - - - - IBProjectSource - SettingsMenuView.h - - - - UICustomSlider - UISlider - - IBProjectSource - UICustomSlider.h - - - - UICustomSwitch - UIButton - - IBProjectSource - UICustomSwitch.h - - - - UIFontButton - UIButton - - YES - - YES - label - label2 - - - YES - UIFontLabel - UIFontLabel - - - - YES - - YES - label - label2 - - - YES - - label - UIFontLabel - - - label2 - UIFontLabel - - - - - IBProjectSource - UIFontButton.h - - - - UIFontLabel - UILabel - - IBProjectSource - UIFontLabel.h - - - - gameAppDelegate - NSObject - - YES - - YES - controlsMenuViewController - creditsMenuViewController - displayLink - episodeMenuViewController - glView - legalMenuViewController - mainMenuViewController - mapMenuViewController - settingsMenuViewController - window - - - YES - MenuViewController - MenuViewController - CADisplayLink - MenuViewController - EAGLView - MenuViewController - MenuViewController - MenuViewController - MenuViewController - UIWindow - - - - YES - - YES - controlsMenuViewController - creditsMenuViewController - displayLink - episodeMenuViewController - glView - legalMenuViewController - mainMenuViewController - mapMenuViewController - settingsMenuViewController - window - - - YES - - controlsMenuViewController - MenuViewController - - - creditsMenuViewController - MenuViewController - - - displayLink - CADisplayLink - - - episodeMenuViewController - MenuViewController - - - glView - EAGLView - - - legalMenuViewController - MenuViewController - - - mainMenuViewController - MenuViewController - - - mapMenuViewController - MenuViewController - - - settingsMenuViewController - MenuViewController - - - window - UIWindow - - - - - IBProjectSource - doomAppDelegate.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CIImageProvider.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIApplication - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIApplication.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UILabel - UIView - - IBFrameworkSource - UIKit.framework/Headers/UILabel.h - - - - UIResponder - NSObject - - - - UIScrollView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIScrollView.h - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UISlider - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UISlider.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - UIWindow - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIWindow.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - Doom.xcodeproj - 3 - - YES - - YES - AdvancedButton.png - BackButton.png - Button.png - Button_Highlighted.png - DifficultyBackground.png - Divide.png - DoomLogo.png - DownArrow - DownArrow_Highlighted.png - Easy.png - Episode1Background.png - Episode1Background_Highlighted.png - Episode2Background.png - Episode2Background_Highlighted.png - Episode3Background.png - Episode3Background_Highlighted.png - Episode4Background.png - Episode4Background_Highlighted.png - Hard.png - LayoutDualButton.png - LayoutSingleButton.png - LayoutWheelButton.png - Medium.png - MenuBackground.png - MissonBackground.png - NextButton.png - NextButton_Highlighted.png - Nightmare.png - SelectedBracket.png - SettingsButton.png - SettingsButton_Highlighted.png - SubMenuBackground.png - SubMenuButton.png - SubMenuButton_Highlighted.png - UpArrow - UpArrow_Highlighted.png - - - YES - {93, 94} - {93, 94} - {191, 191} - {191, 191} - {636, 152} - {764, 11} - {557, 358} - {13, 13} - {80, 36} - {123, 123} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {121, 121} - {241, 166} - {241, 166} - {241, 166} - {121, 121} - {960, 640} - {656, 363} - {93, 94} - {93, 94} - {121, 121} - {133, 133} - {80, 89} - {80, 89} - {959, 574} - {195, 174} - {195, 174} - {13, 13} - {80, 36} - - - 141 - - diff --git a/code/iphone/MapMenuView.h b/code/iphone/MapMenuView.h deleted file mode 100644 index 8851b46..0000000 --- a/code/iphone/MapMenuView.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import -#import -#import "UIFontLabel.h" -#import "UIFontButton.h" - -@interface MapMenuView : UIView { -@public - - IBOutlet UIScrollView * mapScroller1; - IBOutlet UIScrollView * mapScroller2; - IBOutlet UIScrollView * mapScroller3; - IBOutlet UIScrollView * mapScroller4; - - IBOutlet UIButton * lastElement1; - IBOutlet UIButton * lastElement2; - IBOutlet UIButton * lastElement3; - IBOutlet UIButton * lastElement4; - - - IBOutlet UIImageView * easySelection; - IBOutlet UIImageView * mediumSelection; - IBOutlet UIImageView * hardSelection; - IBOutlet UIImageView * NightmareSelection; - - UIScrollView * selectedScroller; - - IBOutlet UIFontLabel * easySelectionLabel; - IBOutlet UIFontLabel * mediumSelectionLabel; - IBOutlet UIFontLabel * hardSelectionLabel; - IBOutlet UIFontLabel * nightmareSelectionLabel; - - IBOutlet UIFontButton * playButton; - IBOutlet UIFontLabel * playLabel; - - UIFontButton * selectedMap; - int episodeSelected; - int mapSelected; - -} - -- (int) getSkill; -- (void) playMap: (int) dataset: (int) episode: (int) map; -- (void) resetDifficulty; - -- (void) setEpisode: (int) episode; - --(IBAction) BackPressed; --(IBAction) Play; - --(IBAction) UpMission; --(IBAction) DownMission; - - // Difficulty Setting --(IBAction) EasyPressed; --(IBAction) MediumPressed; --(IBAction) HardPressed; --(IBAction) NightmarePressed; - - -// DOOM EPISODES --(IBAction) E1M1; --(IBAction) E1M2; --(IBAction) E1M3; --(IBAction) E1M4; --(IBAction) E1M5; --(IBAction) E1M6; --(IBAction) E1M7; --(IBAction) E1M8; --(IBAction) E1M9; - --(IBAction) E2M1; --(IBAction) E2M2; --(IBAction) E2M3; --(IBAction) E2M4; --(IBAction) E2M5; --(IBAction) E2M6; --(IBAction) E2M7; --(IBAction) E2M8; --(IBAction) E2M9; - --(IBAction) E3M1; --(IBAction) E3M2; --(IBAction) E3M3; --(IBAction) E3M4; --(IBAction) E3M5; --(IBAction) E3M6; --(IBAction) E3M7; --(IBAction) E3M8; --(IBAction) E3M9; - --(IBAction) E4M1; --(IBAction) E4M2; --(IBAction) E4M3; --(IBAction) E4M4; --(IBAction) E4M5; --(IBAction) E4M6; --(IBAction) E4M7; --(IBAction) E4M8; --(IBAction) E4M9; - -@end diff --git a/code/iphone/MapMenuView.m b/code/iphone/MapMenuView.m deleted file mode 100644 index 80e4e36..0000000 --- a/code/iphone/MapMenuView.m +++ /dev/null @@ -1,356 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -#import "MapMenuView.h" -#import "doomAppDelegate.h" - -@implementation MapMenuView - -- (void) initialize{ - - [self resetDifficulty ]; - - [mapScroller1 setContentSize:CGSizeMake( - mapScroller1.bounds.size.width, - CGRectGetMaxY(lastElement1.frame) - )]; - - [mapScroller2 setContentSize:CGSizeMake( - mapScroller2.bounds.size.width, - CGRectGetMaxY(lastElement2.frame) - )]; - - [mapScroller3 setContentSize:CGSizeMake( - mapScroller3.bounds.size.width, - CGRectGetMaxY(lastElement3.frame) - )]; - - [mapScroller4 setContentSize:CGSizeMake( - mapScroller4.bounds.size.width, - CGRectGetMaxY(lastElement4.frame) - )]; - - [ playButton setEnabled: NO ]; - [ playLabel setEnabled: NO ]; - - selectedMap = nil; - episodeSelected = -1; - mapSelected = -1; - -} - -- (void)awakeFromNib { - - [self initialize]; - -} - -- (id) initWithCoder:(NSCoder *)aCoder{ - - if(self = [super initWithCoder:aCoder] ) { - [self initialize]; - } - - return self; -} - -- (id) initWithFrame:(CGRect)rect{ - if(self = [super initWithFrame:rect] ) { - [self initialize]; - } - return self; -} - -- (void) resetDifficulty { - - easySelection.hidden = NO; - easySelectionLabel.hidden = NO; - mediumSelection.hidden = YES; - mediumSelectionLabel.hidden = YES; - hardSelection.hidden = YES; - hardSelectionLabel.hidden = YES; - NightmareSelection.hidden = YES; - nightmareSelectionLabel.hidden = YES; - -} - -- (void) setEpisode: (int) episode { - - mapScroller1.alpha = 0.0f; - mapScroller2.alpha = 0.0f; - mapScroller3.alpha = 0.0f; - mapScroller4.alpha = 0.0f; - - - switch( episode ) { - - case 0: - selectedScroller = mapScroller1; - break; - case 1: - selectedScroller = mapScroller2; - break; - case 2: - selectedScroller = mapScroller3; - break; - case 3: - selectedScroller = mapScroller4; - break; - - }; - - selectedScroller.alpha = 1.0f; -} - --(IBAction) BackPressed { - - // Go Back to MainMenu. - [gAppDelegate NewGame ]; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); - -} - -- (int) getSkill { - - if( easySelection.hidden == NO ) { - return 0; - } else if( mediumSelection.hidden == NO ) { - return 1; - } else if( hardSelection.hidden == NO ) { - return 2; - } else if( NightmareSelection.hidden == NO ) { - return 3; - } - - return 0; -} - --(IBAction) UpMission { - - - CGFloat xOffset = selectedScroller.contentOffset.x; - CGFloat yOffset = selectedScroller.contentOffset.y; - - if (selectedScroller.contentOffset.y > 10 ) - { - [selectedScroller setContentOffset:CGPointMake(xOffset, yOffset - 50 ) animated:YES]; - } -} - --(IBAction) DownMission { - - CGFloat xOffset = selectedScroller.contentOffset.x; - CGFloat yOffset = selectedScroller.contentOffset.y; - - if (selectedScroller.contentOffset.y < 300 ) - { - [selectedScroller setContentOffset:CGPointMake(xOffset, yOffset + 50 ) animated:YES]; - } - -} - --(IBAction) Play { - - int skillLevel = [self getSkill]; - - [gAppDelegate playMap: 0: episodeSelected: mapSelected: skillLevel ]; - -} - -- (void) playMap: (int) dataset: (int) episode: (int) map { - - [ playButton setEnabled: YES ]; - [ playLabel setEnabled: YES ]; - - if( selectedMap != nil ) { - [ selectedMap setEnabled: YES ]; - } - episodeSelected = episode; - mapSelected = map; - - int mapTag = episode * 10 + ( map - 1 ); - selectedMap = (UIFontButton *)[ self viewWithTag: mapTag ]; - - [selectedMap setEnabled: NO]; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); -} - -// Difficulty Setting --(IBAction) EasyPressed { - - [self resetDifficulty]; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); -} - --(IBAction) MediumPressed { - - easySelection.hidden = YES; - mediumSelection.hidden = NO; - hardSelection.hidden = YES; - NightmareSelection.hidden = YES; - - easySelectionLabel.hidden = YES; - mediumSelectionLabel.hidden = NO; - hardSelectionLabel.hidden = YES; - nightmareSelectionLabel.hidden = YES; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); - -} --(IBAction) HardPressed { - - easySelection.hidden = YES; - mediumSelection.hidden = YES; - hardSelection.hidden = NO; - NightmareSelection.hidden = YES; - - easySelectionLabel.hidden = YES; - mediumSelectionLabel.hidden = YES; - hardSelectionLabel.hidden = NO; - nightmareSelectionLabel.hidden = YES; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); - -} --(IBAction) NightmarePressed{ - - easySelection.hidden = YES; - mediumSelection.hidden = YES; - hardSelection.hidden = YES; - NightmareSelection.hidden = NO; - - easySelectionLabel.hidden = YES; - mediumSelectionLabel.hidden = YES; - hardSelectionLabel.hidden = YES; - nightmareSelectionLabel.hidden = NO; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); -} - - -// DOOM EPISODES --(IBAction) E1M1 { - [ self playMap: 0: 1: 1 ]; -} --(IBAction) E1M2{ - [ self playMap: 0: 1: 2 ]; -} --(IBAction) E1M3{ - [ self playMap: 0: 1: 3 ]; -} --(IBAction) E1M4{ - [ self playMap: 0: 1: 4 ]; -} --(IBAction) E1M5{ - [ self playMap: 0: 1: 5 ]; -} --(IBAction) E1M6{ - [ self playMap: 0: 1: 6 ]; -} --(IBAction) E1M7{ - [ self playMap: 0: 1: 7 ]; -} --(IBAction) E1M8{ - [ self playMap: 0: 1: 8 ]; -} --(IBAction) E1M9{ - [ self playMap: 0: 1: 9 ]; -} - --(IBAction) E2M1{ - [ self playMap: 0: 2: 1 ]; -} --(IBAction) E2M2{ - [ self playMap: 0: 2: 2 ]; -} --(IBAction) E2M3{ - [ self playMap: 0: 2: 3 ]; -} --(IBAction) E2M4{ - [ self playMap: 0: 2: 4 ]; -} --(IBAction) E2M5{ - [ self playMap: 0: 2: 5 ]; -} --(IBAction) E2M6{ - [ self playMap: 0: 2: 6 ]; -} --(IBAction) E2M7{ - [ self playMap: 0: 2: 7 ]; -} --(IBAction) E2M8{ - [ self playMap: 0: 2: 8 ]; -} --(IBAction) E2M9{ - [ self playMap: 0: 2: 9 ]; -} - --(IBAction) E3M1{ - [ self playMap: 0: 3: 1 ]; -} --(IBAction) E3M2{ - [ self playMap: 0: 3: 2 ]; -} --(IBAction) E3M3{ - [ self playMap: 0: 3: 3 ]; -} --(IBAction) E3M4{ - [ self playMap: 0: 3: 4 ]; -} --(IBAction) E3M5{ - [ self playMap: 0: 3: 5 ]; -} --(IBAction) E3M6{ - [ self playMap: 0: 3: 6 ]; -} --(IBAction) E3M7 { - [ self playMap: 0: 3: 7 ]; -} --(IBAction) E3M8{ - [ self playMap: 0: 3: 8 ]; -} --(IBAction) E3M9{ - [ self playMap: 0: 3: 9 ]; -} - --(IBAction) E4M1{ - [ self playMap: 0: 4: 1 ]; -} --(IBAction) E4M2{ - [ self playMap: 0: 4: 2 ]; -} --(IBAction) E4M3{ - [ self playMap: 0: 4: 3 ]; -} --(IBAction) E4M4{ - [ self playMap: 0: 4: 4 ]; -} --(IBAction) E4M5{ - [ self playMap: 0: 4: 5 ]; -} --(IBAction) E4M6{ - [ self playMap: 0: 4: 6 ]; -} --(IBAction) E4M7{ - [ self playMap: 0: 4: 7 ]; -} --(IBAction) E4M8{ - [ self playMap: 0: 4: 8 ]; -} --(IBAction) E4M9{ - [ self playMap: 0: 4: 9 ]; -} - -@end diff --git a/code/iphone/MenuViewController.h b/code/iphone/MenuViewController.h deleted file mode 100644 index 4748c6c..0000000 --- a/code/iphone/MenuViewController.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -#import -#import - -@interface MenuViewController : UIViewController { - -} - -@end diff --git a/code/iphone/MenuViewController.mm b/code/iphone/MenuViewController.mm deleted file mode 100644 index 00586d9..0000000 --- a/code/iphone/MenuViewController.mm +++ /dev/null @@ -1,21 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import "MenuViewController.h" - -@implementation MenuViewController - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - - return interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight; -} - -@end diff --git a/code/iphone/MissionMenuView-tvos.xib b/code/iphone/MissionMenuView-tvos.xib new file mode 100755 index 0000000..864f46f --- /dev/null +++ b/code/iphone/MissionMenuView-tvos.xib @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/MissionMenuView.xib b/code/iphone/MissionMenuView.xib new file mode 100755 index 0000000..af98409 --- /dev/null +++ b/code/iphone/MissionMenuView.xib @@ -0,0 +1,375 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/MissionMenuViewController.h b/code/iphone/MissionMenuViewController.h new file mode 100755 index 0000000..6ed6955 --- /dev/null +++ b/code/iphone/MissionMenuViewController.h @@ -0,0 +1,78 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import +#import "../ios/Label.h" +#import "../ios/LabelButton.h" +/* + ================================================================================================ + Doom_MissionMenuViewController + + ================================================================================================ + */ +@interface Doom_MissionMenuViewController : UIViewController { + + IBOutlet UITableView *missionList; + + IBOutlet UIImageView * easySelection; + IBOutlet UIImageView * mediumSelection; + IBOutlet UIImageView * hardSelection; + IBOutlet UIImageView * NightmareSelection; + + IBOutlet idLabel * easySelectionLabel; + IBOutlet idLabel * mediumSelectionLabel; + IBOutlet idLabel * hardSelectionLabel; + IBOutlet idLabel * nightmareSelectionLabel; + + + IBOutlet idLabelButton * easyButton; + IBOutlet idLabelButton * normalButton; + IBOutlet idLabelButton * hardButton; + IBOutlet idLabelButton * nightmareButton; + + IBOutlet idLabelButton * playButton; + IBOutlet idLabel * playLabel; + + idLabelButton * selectedMap; + int episodeSelected; + int mapSelected; + int currentCell; +} + +- (int) getSkill; +- (void) playMap:(int)dataset + :(int)episode + :(int)map; + +- (void) setEpisode: (int) episode; + +-(IBAction) BackPressed; +-(IBAction) Play; + +-(IBAction) UpMission; +-(IBAction) DownMission; + +// Difficulty Setting +-(IBAction) EasyPressed; +-(IBAction) MediumPressed; +-(IBAction) HardPressed; +-(IBAction) NightmarePressed; + +@end diff --git a/code/iphone/MissionMenuViewController.mm b/code/iphone/MissionMenuViewController.mm new file mode 100755 index 0000000..1d48b7b --- /dev/null +++ b/code/iphone/MissionMenuViewController.mm @@ -0,0 +1,505 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "MissionMenuViewController.h" +#include "doomiphone.h" +#include "iphone_delegate.h" + +@interface Doom_MissionMenuViewController () + +@property (nonatomic, retain) UITableView *missionList; + +@end + +/* + ================================================================================================ + Doom_MissionMenuViewController + + ================================================================================================ + */ +@implementation Doom_MissionMenuViewController + +BOOL levelSelected = NO; + +#if GAME_DOOM + +#define TOTAL_EPISODES 4 + +static const char * const MissionNames[TOTAL_EPISODES][9] = { + {"E1M1: Hanger", "E1M2: Nuclear Plant", "E1M3: Toxin Refinery", "E1M4: Command Control", "E1M5: Phobos Lab", "E1M6: Central Processing", "E1M7: Computer Station", "E1M8: Phobos Anomaly", "E1M9: Military Base"}, + {"E2M1: Deimos Anomaly", "E2M2: Containment Area", "E2M3: Refinery", "E2M4: Deimos Lab", "E2M5: Command Center", "E2M6: Halls of the Damned", "E2M7: Spawning Vats", "E2M8: Tower of Babel", "E2M9: Fortress of Mystery"}, + {"E3M1: Hell Keep ", "E3M2: Slough of Despair", "E3M3: Pandemonium", "E3M4: House of Pain", "E3M5: Unholy Cathedral", "E3M6: Mt. Erebus", "E3M7: Limbo", "E3M8: Dis", "E3M9: Warrens"}, + {"E4M1: Hell Beneath", "E4M2: Perfect Hatred", "E4M3: Sever The Wicked", "E4M4: Unruly Evil", "E4M5: They Will Repent", "E4M6: Against Thee Wickedly", "E4M7: And Hell Followed", "E4M8: Unto The Cruel", "E4M9: Fear"} +}; +#endif + +#if GAME_DOOM2 + +#define TOTAL_EPISODES 1 + +static const char * const MissionNames[TOTAL_EPISODES][32] = { + {"MAP01: Entryway", "MAP02: Underhalls", "MAP03: The Gauntlet", "MAP04: The Focus", "MAP05: The Waste Tunnels", "MAP06: The Crusher", "MAP07: Dead Simple", "MAP08: Tricks and Traps", "MAP09: The Pit", "MAP10: Refueling Base", "MAP11: 'O' of Destruction!", "MAP12: The Factory", "MAP13: Downtown", "MAP14: The Inmost Dens", "MAP15: Industrial Zone", "MAP16: Suburbs", "MAP17: Tenements", "MAP18: The Courtyard", "MAP19: The Citadel", "MAP20: Gotcha!", "MAP21: Nirvana", "MAP22: The Catacombs", "MAP23: Barrels o' Fun", "MAP24: The Chasm", "MAP25: Bloodfalls", "MAP26: The Abandoned Mines", "MAP27: Monster Condo", "MAP28: The Spirit World", "MAP29: The Living End", "MAP30: Icon of Sin", "MAP31: Wolfenstein", "MAP32: Grosse"} +}; +#endif + + +#if GAME_FINALDOOM + +#define TOTAL_EPISODES 2 + +static const char * const MissionNames[TOTAL_EPISODES][32] = { + {"MAP01: System Control","MAP02: Human BBQ","MAP03: Power Control","MAP04: Wormhole","MAP05: Hanger","MAP06: Open Season","MAP07: Prison","MAP08: Metal","MAP09: Stronghold","MAP10: Redemption","MAP11: Storage Facility","MAP12: Crater","MAP13: Nukage Processing","MAP14: Steel Works","MAP15: Dead Zone","MAP16: Deepest Reaches","MAP17: Processing Area","MAP18: Mill","MAP19: Shipping/Respawning","MAP20: Central Processing","MAP21: Administration Center","MAP22: Habitat","MAP23: Lunar Mining Project","MAP24: Quarry","MAP25: Baron's Den","MAP26: Ballistyx","MAP27: Mount Pain","MAP28: Heck","MAP29: River Styx","MAP30: Last Call","MAP31: Pharaoh","MAP32: Caribbean"}, + {"MAP01: Congo","MAP02: Well of Souls","MAP03: Aztec","MAP04: Caged","MAP05: Ghost Town","MAP06: Baron's Lair","MAP07: Caughtyard","MAP08: Realm","MAP09: Abattoire","MAP10: Onslaught","MAP11: Hunted","MAP12: Speed","MAP13: The Crypt","MAP14: Genesis","MAP15: The Twilight (Exit to secret level)","MAP16: The Omen","MAP17: Compound","MAP18: Neurosphere","MAP19: NME","MAP20: The Death Domain","MAP21: Slayer","MAP22: Impossible Mission","MAP23: Tombstone","MAP24: The Final Frontier","MAP25: The Temple of Darkness","MAP26: Bunker","MAP27: Anti-Christ","MAP28: The Sewers","MAP29: Odyssey of Noises","MAP30: The Gateway of Hell","MAP31: Cyberden (Exit to super secret level)","MAP32: Go 2 It"} +}; +#endif + +#if GAME_SIGIL + +#define TOTAL_EPISODES 5 + +// Just going along with the five-episode concept for now + +static const char * const MissionNames[TOTAL_EPISODES][9] = { + {"E1M1: Hanger", "E1M2: Nuclear Plant", "E1M3: Toxin Refinery", "E1M4: Command Control", "E1M5: Phobos Lab", "E1M6: Central Processing", "E1M7: Computer Station", "E1M8: Phobos Anomaly", "E1M9: Military Base"}, + {"E2M1: Deimos Anomaly", "E2M2: Containment Area", "E2M3: Refinery", "E2M4: Deimos Lab", "E2M5: Command Center", "E2M6: Halls of the Damned", "E2M7: Spawning Vats", "E2M8: Tower of Babel", "E2M9: Fortress of Mystery"}, + {"E3M1: Hell Keep ", "E3M2: Slough of Despair", "E3M3: Pandemonium", "E3M4: House of Pain", "E3M5: Unholy Cathedral", "E3M6: Mt. Erebus", "E3M7: Limbo", "E3M8: Dis", "E3M9: Warrens"}, + {"E4M1: Hell Beneath", "E4M2: Perfect Hatred", "E4M3: Sever The Wicked", "E4M4: Unruly Evil", "E4M5: They Will Repent", "E4M6: Against Thee Wickedly", "E4M7: And Hell Followed", "E4M8: Unto The Cruel", "E4M9: Fear"}, + {"Baphomet's Demesne", "Sheol", "Cages of the Damned", "Paths of Wretchedness", "Abaddon's Void", "Unspeakable Persecution", "Nightmare Underworld", "Halls of Perdition", "Realm of Iblis"} +}; +#endif + +//{"MAP01: System Control","MAP02: Human BBQ","MAP03: Power Control","MAP04: Wormhole","MAP05: Hanger","MAP06: Open Season","MAP07: Prison","MAP08: Metal","MAP09: Stronghold","MAP10: Redemption","MAP11: Storage Facility","MAP12: Crater","MAP13: Nukage Processing","MAP14: Steel Works","MAP15: Dead Zone","MAP16: Deepest Reaches","MAP17: Processing Area","MAP18: Mill","MAP19: Shipping/Respawning","MAP20: Central Processing","MAP21: Administration Center","MAP22: Habitat","MAP23: Lunar Mining Project","MAP24: Quarry","MAP25: Baron's Den","MAP26: Ballistyx","MAP27: Mount Pain","MAP28: Heck","MAP29: River Styx","MAP30: Last Call","MAP31: Pharaoh","MAP32: Caribbean"} + + + +@synthesize missionList; + +/* + ======================== + Doom_MissionMenuViewController::initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +/* + ======================== + Doom_MissionMenuViewController::didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +#pragma mark - View lifecycle + +/* + ======================== + Doom_MissionMenuViewController::viewDidLoad + ======================== + */ +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [ playButton setEnabled: NO ]; + [ playLabel setEnabled: NO ]; + + selectedMap = nil; + mapSelected = -1; + currentCell = 0; + + easySelection.hidden = NO; + easySelectionLabel.hidden = NO; + mediumSelection.hidden = YES; + mediumSelectionLabel.hidden = YES; + hardSelection.hidden = YES; + hardSelectionLabel.hidden = YES; + NightmareSelection.hidden = YES; + nightmareSelectionLabel.hidden = YES; + + [missionList reloadData]; +} + +/* + ======================== + Doom_MissionMenuViewController::setEpisode + ======================== + */ +- (void) setEpisode: (int) episode { + + episodeSelected = episode; +} + +/* + ======================== + Doom_MissionMenuViewController::BackPressed + ======================== + */ +-(IBAction) BackPressed { + + [self.navigationController popViewControllerAnimated:NO]; + + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); + +} + +/* + ======================== + Doom_MissionMenuViewController::getSkill + ======================== + */ +- (int) getSkill { + + if( easySelection.hidden == NO ) { + return 0; + } else if( mediumSelection.hidden == NO ) { + return 1; + } else if( hardSelection.hidden == NO ) { + return 2; + } else if( NightmareSelection.hidden == NO ) { + return 3; + } + + return 0; +} + +/* + ======================== + Doom_MissionMenuViewController::UpMission + ======================== + */ +-(IBAction) UpMission { + currentCell -= 1; + if (currentCell < 0) { + currentCell = 0; + } + [missionList scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:currentCell inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES]; +} + +/* + ======================== + Doom_MissionMenuViewController::DownMission + ======================== + */ +-(IBAction) DownMission { + currentCell += 1; + if (currentCell > 6) { + currentCell = 6; + } + [missionList scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:currentCell inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES]; +} + +/* + ======================== + Doom_MissionMenuViewController::Play + ======================== + */ +-(IBAction) Play { + + int skillLevel = [self getSkill]; + mapStart_t localStartmap; + + localStartmap.map = mapSelected; + localStartmap.episode = episodeSelected + 1; + localStartmap.dataset = 0; + localStartmap.skill = skillLevel; + + StartSinglePlayerGame( localStartmap ); + + [ gAppDelegate ShowGLView ]; +} + +/* + ======================== + Doom_MissionMenuViewController::playMap + ======================== + */ +- (void) playMap:(int)dataset + :(int)episode + :(int) map { + + (void)dataset; + + [ playButton setEnabled: YES ]; + [ playLabel setEnabled: YES ]; + + if( selectedMap != nil ) { + [ selectedMap setEnabled: YES ]; + } + //episodeSelected = episode; + mapSelected = map; + + int mapTag = episode * 10 + ( map - 1 ); + selectedMap = (idLabelButton *)[ self.view viewWithTag: mapTag ]; + + [selectedMap setEnabled: NO]; + + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +} + +/* + ======================== + Doom_MissionMenuViewController::EasyPressed + ======================== + */ +-(IBAction) EasyPressed { + + easySelection.hidden = NO; + easySelectionLabel.hidden = NO; + mediumSelection.hidden = YES; + mediumSelectionLabel.hidden = YES; + hardSelection.hidden = YES; + hardSelectionLabel.hidden = YES; + NightmareSelection.hidden = YES; + nightmareSelectionLabel.hidden = YES; + + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +#if TARGET_OS_TV + [self Play]; +#endif +} + +/* + ======================== + Doom_MissionMenuViewController::MediumPressed + ======================== + */ +-(IBAction) MediumPressed { + + easySelection.hidden = YES; + mediumSelection.hidden = NO; + hardSelection.hidden = YES; + NightmareSelection.hidden = YES; + + easySelectionLabel.hidden = YES; + mediumSelectionLabel.hidden = NO; + hardSelectionLabel.hidden = YES; + nightmareSelectionLabel.hidden = YES; + + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +#if TARGET_OS_TV + [self Play]; +#endif + +} + +/* + ======================== + Doom_MissionMenuViewController::HardPressed + ======================== + */ +-(IBAction) HardPressed { + + easySelection.hidden = YES; + mediumSelection.hidden = YES; + hardSelection.hidden = NO; + NightmareSelection.hidden = YES; + + easySelectionLabel.hidden = YES; + mediumSelectionLabel.hidden = YES; + hardSelectionLabel.hidden = NO; + nightmareSelectionLabel.hidden = YES; + + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +#if TARGET_OS_TV + [self Play]; +#endif + +} + +/* + ======================== + Doom_MissionMenuViewController::NightmarePressed + ======================== + */ +-(IBAction) NightmarePressed{ + + easySelection.hidden = YES; + mediumSelection.hidden = YES; + hardSelection.hidden = YES; + NightmareSelection.hidden = NO; + + easySelectionLabel.hidden = YES; + mediumSelectionLabel.hidden = YES; + hardSelectionLabel.hidden = YES; + nightmareSelectionLabel.hidden = NO; + + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +#if TARGET_OS_TV + [self Play]; +#endif +} + +/* + ======================== + + UITableView interface + + ======================== + */ + +- (void)handleSelectionAtIndexPath:(NSIndexPath*)indexPath { + +// Cvar_SetValue( episode->name, indexPath.row ); + + [self setCellSelected:YES atIndexPath:indexPath]; + + +#if TARGET_OS_TV + levelSelected = YES; + [self setNeedsFocusUpdate]; + [self updateFocusIfNeeded]; +#endif + +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { +#if GAME_DOOM + return 9; +#else + return 32; +#endif +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + static NSString *MyIdentifier = @"MissionIdentifier"; + + UITableViewCell *cell = (UITableViewCell*)[self.missionList dequeueReusableCellWithIdentifier:MyIdentifier]; + + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease]; + } + + cell.selectionStyle = UITableViewCellSelectionStyleNone; + + cell.textLabel.text = [NSString stringWithCString:MissionNames[episodeSelected][indexPath.row] encoding:NSASCIIStringEncoding]; + + cell.backgroundColor = UIColor.clearColor; + + cell.textLabel.textColor = [UIColor colorWithRed:185.0f/255.0f green:108.0f/255.0f blue:17.0f/255.0f alpha:1]; + cell.textLabel.highlightedTextColor = [UIColor colorWithRed:255.0f/255.0f green:204.0f/255.0f blue:0.0f/255.0f alpha:1]; + + CGFloat points = cell.textLabel.font.pointSize; + + if (IS_IPAD) { + cell.textLabel.font = [UIFont fontWithName:[gAppDelegate GetFontName] size:34]; + } else { + cell.textLabel.font = [UIFont fontWithName:[gAppDelegate GetFontName] size:points]; + } + + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + + [self handleSelectionAtIndexPath:indexPath]; +} + +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { + [self setCellSelected:NO atIndexPath:indexPath]; + +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + if (IS_IPAD) { + return 90; + } else { + return 45; + } +} + +- (void)setCellSelected:(BOOL)selected atIndexPath:(NSIndexPath*)indexPath { + // Get the cell that was selected. + [ playButton setEnabled: YES ]; + [ playLabel setEnabled: YES ]; + mapSelected = (int)indexPath.row + 1; + + NSLog(@"episodeSelected %i mapSelected: %i", episodeSelected, mapSelected); + + [ self playMap: 0: episodeSelected+1: mapSelected ]; + + UITableViewCell * cell = [missionList cellForRowAtIndexPath:indexPath]; + cell.textLabel.highlighted = selected; +} + +#if TARGET_OS_TV +-(NSArray> *)preferredFocusEnvironments { + if (levelSelected) { + levelSelected = NO; + return @[normalButton]; + } + else { + return @[missionList]; + } +} + +- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator { + NSLog(@"%@", context.nextFocusedView); + + if (!context.previouslyFocusedView) { + [ gAppDelegate HideGLView ]; + paused = true; + } + + [super didUpdateFocusInContext:context withAnimationCoordinator:coordinator]; + + if ([context.nextFocusedView isKindOfClass:[idLabelButton class]]) { + + if (context.nextFocusedView.tag > 0) { + easySelection.hidden = YES; + easySelectionLabel.hidden = YES; + mediumSelection.hidden = YES; + mediumSelectionLabel.hidden = YES; + hardSelection.hidden = YES; + hardSelectionLabel.hidden = YES; + NightmareSelection.hidden = YES; + nightmareSelectionLabel.hidden = YES; + + + if (context.nextFocusedView.tag == 1) { + easySelection.hidden = NO; + easySelectionLabel.hidden = NO; + } else if (context.nextFocusedView.tag == 2) { + mediumSelection.hidden = NO; + mediumSelectionLabel.hidden = NO; + } else if (context.nextFocusedView.tag == 3) { + hardSelection.hidden = NO; + hardSelectionLabel.hidden = NO; + } else if (context.nextFocusedView.tag == 4) { + NightmareSelection.hidden = NO; + nightmareSelectionLabel.hidden = NO; + } + } + } +} +#endif + +@end diff --git a/code/iphone/MissionMenuView~ipad.xib b/code/iphone/MissionMenuView~ipad.xib new file mode 100755 index 0000000..1915b88 --- /dev/null +++ b/code/iphone/MissionMenuView~ipad.xib @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/OpenGLView-tvos.xib b/code/iphone/OpenGLView-tvos.xib new file mode 100755 index 0000000..17d5d5d --- /dev/null +++ b/code/iphone/OpenGLView-tvos.xib @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/OpenGLView.xib b/code/iphone/OpenGLView.xib new file mode 100755 index 0000000..eed0881 --- /dev/null +++ b/code/iphone/OpenGLView.xib @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/OpenGLView~ipad.xib b/code/iphone/OpenGLView~ipad.xib new file mode 100755 index 0000000..71bb1ed --- /dev/null +++ b/code/iphone/OpenGLView~ipad.xib @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/Resources-iPad/MainWindow-iPad.xib b/code/iphone/Resources-iPad/MainWindow-iPad.xib deleted file mode 100644 index d420a63..0000000 --- a/code/iphone/Resources-iPad/MainWindow-iPad.xib +++ /dev/null @@ -1,10938 +0,0 @@ - - - - 768 - 10K549 - 851 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 141 - - - YES - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - YES - - YES - - - YES - - - - YES - - IBFilesOwner - IBIPadFramework - - - IBFirstResponder - IBIPadFramework - - - IBIPadFramework - - - - 1316 - - {768, 1024} - - 1 - MSAxIDEAA - - NO - IBIPadFramework - YES - YES - - - - - 292 - - YES - - - 292 - {1024, 768} - - - NO - 1 - IBIPadFramework - - NSImage - MenuBackground.png - - - - - 292 - {{20, 41}, {93, 94}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - Helvetica-Bold - 15 - 16 - - - 3 - MQA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - 3 - MC41AA - - - NSImage - BackButton.png - - - - - 292 - {{388, 146}, {80, 89}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - SettingsButton_Highlighted.png - - - - NSImage - SettingsButton.png - - - - - 292 - {{388, 262}, {80, 89}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 292 - {{388, 380}, {80, 89}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 292 - {{388, 511}, {80, 89}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 292 - {{806, 146}, {80, 89}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 292 - {{806, 262}, {80, 89}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 292 - {{806, 380}, {80, 88}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 292 - {{806, 510.5}, {80, 89}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 292 - {{899, 41}, {93, 94}} - - - NO - 1 - IBIPadFramework - 0 - 0 - - {1, 2} - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - NSImage - NextButton.png - - - - - 292 - {{230, 169}, {150, 43}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Auto Use: - - Helvetica - 34 - 16 - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 2 - - - - 292 - {{210, 285}, {170, 43}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Status Bar: - - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 2 - - - - 292 - {{210, 403}, {170, 43}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Hud Audio: - - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 2 - - - - 292 - {{138, 534}, {242, 43}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Text Messages: - - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 2 - - - - 292 - {{571, 169}, {227, 43}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Draw Controls: - - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 2 - - - - 292 - {{698, 285}, {100, 43}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Music: - - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 2 - - - - 292 - {{584, 402.5}, {214, 43}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Center Sticks: - - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 2 - - - - 292 - {{617, 533.5}, {181, 43}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Ramp Turn: - - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 2 - - - - 292 - {{910, 30}, {80, 38}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Reset - - Helvetica - 30 - 16 - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - - 292 - {{36, 30}, {68, 38}} - - - NO - YES - 7 - NO - 1 - IBIPadFramework - Back - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - {1024, 768} - - - - 3 - MQA - - 2 - - - - 3 - - 1 - IBIPadFramework - - - 3 - - 1 - IBIPadFramework - YES - - - - - 292 - - YES - - - 292 - {1024, 768} - - NO - 1 - IBIPadFramework - - - - - 292 - {{179, 74}, {666, 428}} - - NO - 1 - IBIPadFramework - - NSImage - DoomLogo.png - - - - - 292 - {{20, 40}, {93, 94}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 274 - {{127, 462}, {770, 186}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Doom® Classic © 2009-2011 id Software LLC, a ZeniMax Media company. DOOM, id, id Software, id Tech and related logos are registered trademarks or trademarks of id Software LLC in the U.S. and/or other countries. Bethesda, Bethesda Softworks, ZeniMax and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the U.S. and/or other countries. All Rights Reserved - - Helvetica - 20 - 16 - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - 0 - 1 - 0 - - - - 292 - {{35, 29}, {68, 38}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Back - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - {1024, 768} - - 3 - MQA - - - - 3 - - 1 - IBIPadFramework - - - 3 - - 1 - IBIPadFramework - YES - - - - - 292 - - YES - - - 292 - {1024, 768} - - NO - 1 - IBIPadFramework - - - - - 301 - - YES - - - 292 - {{-19, 20}, {883, 435}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Doom Classic - - Helvetica-Bold - 24 - 16 - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 55}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Programming - - Helvetica-Bold - 20 - 16 - - - - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 472}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Programming - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 91}, {883, 414}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - John Carmack - - Helvetica - 18 - 16 - - - - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 512}, {883, 414}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - John Carmack - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 530}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - John Romero - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 549}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Dave Taylor - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 847}, {896, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Ultimate Doom additional Level Design - - Helvetica-Bold - 17 - 16 - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 874}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - John Anderson - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 894}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Shawn Green - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 914}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - American McGee - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 933}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - John Romero - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 953}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Tim Willits - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 603}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Design - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 643}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - John Romero - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 663}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Sandy Peterson - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 695}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Art - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 735}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Adrian Carmack - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 755}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Kevin Cloud - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 787}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Audio - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 815}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Bobby Prince - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 112}, {883, 413}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Jeff Farrand - - - - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 132}, {883, 415}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Ryan Gerleve - - - - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 161}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Art - - - - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 239}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Audio - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 297}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Production - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-54, 418}, {953, 440}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Doom & Ultimate Doom originally created by id Software - - Helvetica-Bold - 14 - 16 - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 3 - 1 - 0 - - - - 292 - {{-19, 353}, {883, 426}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - QA Testing - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 187}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - John Burnett - - - - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 207}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Danny Keys - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 265}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Zack Quarles - - - 2 - MSAwLjczMzMzMzM0OTIgMC4yOTQxMTc2NTkzAA - - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 322}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Rafael Brown - - - - - {1, 2} - 1 - 16 - 1 - - - - 292 - {{-19, 379}, {883, 418}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Sean Palomino - - - - - {1, 2} - 1 - 16 - 1 - - - {{89, 45}, {845, 678}} - - YES - YES - 1 - IBIPadFramework - 2 - - - - 292 - {{25, 38}, {93, 94}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 292 - {{42, 29}, {68, 38}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Back - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC4wMzI2MDg2OTUzMyAwLjAzMjYwODY5NTMzIDAuMDMyNjA4Njk1MzMAA - - {1, 2} - 1 - 10 - - - {1024, 768} - - 3 - MQA - - - - 3 - - 1 - IBIPadFramework - - - 3 - - 1 - IBIPadFramework - YES - - - - - 292 - - YES - - - 274 - {1024, 768} - - - 1 - MSAxIDEgMAA - - NO - 1 - IBIPadFramework - - - - - 292 - {{130, 248}, {764, 11}} - - NO - 1 - IBIPadFramework - - NSImage - Divide.png - - - - - 308 - {{646, 327}, {215, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Move Stick Size - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 3 - MCAwAA - - {0, 0} - 1 - 10 - 2 - - - - 308 - {{136, 212}, {236, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Single Thumbpad - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 308 - {{405, 212}, {214, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Dual Thumbpad - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 308 - {{687, 212}, {162, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Dir & Wheel - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 308 - {{658, 418}, {203, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Turn Stick Size - - - - - {0, 0} - 1 - 10 - 2 - - - - 308 - {{644, 501}, {217, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Tilt Move Speed - - - - - {0, 0} - 1 - 10 - 2 - - - - 308 - {{656, 589}, {205, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Tilt Turn Speed - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 2 - - - - 308 - {{907, 52}, {93, 94}} - - NO - 1 - IBIPadFramework - 0 - 0 - - {1, 2} - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - NSImage - AdvancedButton.png - - - - - 292 - {{155, 295}, {714, 23}} - - - 1 - MC4wMDU0MzQ3ODI3MSAwLjAwNTQzNDc4MjcxIDAuMDA1NDM0NzgyNzEgMAA - - NO - 1 - IBIPadFramework - 0 - 0 - 0.5 - - - - 292 - {{155, 387}, {714, 23}} - - NO - 1 - IBIPadFramework - 0 - 0 - 0.5 - - - - 292 - {{155, 469}, {714, 23}} - - NO - 1 - IBIPadFramework - 0 - 0 - 100 - 300 - - - - 292 - {{155, 555}, {714, 23}} - - NO - 1 - IBIPadFramework - 0 - 0 - 1500 - 3500 - - - - 308 - {{22, 52}, {93, 94}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 308 - {{35, 42}, {67, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Back - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 308 - {{887, 43}, {134, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Advanced - - Helvetica - 28 - 16 - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - - {0, 0} - 1 - 10 - 1 - - - - 292 - {{134, 38}, {241, 166}} - - NO - 1 - IBIPadFramework - 0 - 0 - - {1, 2} - - - - 2 - MSAwLjY2Mjc0NTExODEgMC4xNzI1NDkwMjQyAA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - NSImage - LayoutSingleButton.png - - - - - 292 - {{392, 38}, {241, 166}} - - NO - 1 - IBIPadFramework - 0 - 0 - - {1, 2} - - - - - - NSImage - LayoutDualButton.png - - - - - 292 - {{648, 38}, {241, 166}} - - NO - 1 - IBIPadFramework - 0 - 0 - - {1, 2} - - - - - - NSImage - LayoutWheelButton.png - - - - {1024, 768} - - 3 - MQA - - - - 3 - - 1 - IBIPadFramework - - - 3 - - 1 - IBIPadFramework - YES - - - - - 292 - - YES - - - 274 - {1024, 768} - - NO - 1 - IBIPadFramework - - - - - 274 - {{184, 26}, {656, 535}} - - NO - 1 - IBIPadFramework - - NSImage - MissonBackground.png - - - - - 292 - {{194, 558}, {636, 152}} - - NO - 1 - IBIPadFramework - - NSImage - DifficultyBackground.png - - - - - 274 - {{45, 52}, {93, 94}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 274 - {{877, 52}, {93, 94}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - NextButton_Highlighted.png - - - - - - 292 - {{480.5, 33.5}, {60, 40}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - UpArrow_Highlighted.png - - - NSImage - UpArrow - - - - - 292 - {{480.5, 514.5}, {60, 40}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - DownArrow_Highlighted.png - - - NSImage - DownArrow - - - - - 292 - {{209, 578}, {123, 123}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Easy.png - - - - - 292 - {{370, 579}, {121, 121}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Medium.png - - - - - 292 - {{532, 578}, {121, 121}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Hard.png - - - - - 292 - {{683, 579}, {121, 121}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Nightmare.png - - - - - 292 - {{205, 570}, {133, 133}} - - NO - 1 - IBIPadFramework - - NSImage - SelectedBracket.png - - - - - 292 - {{365, 571}, {133, 133}} - - NO - 1 - IBIPadFramework - - - - - 292 - {{526, 571}, {133, 133}} - - NO - 1 - IBIPadFramework - - - - - 292 - {{677, 571}, {133, 133}} - - NO - 1 - IBIPadFramework - - - - - 292 - {{894, 39}, {59, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Play - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - 1 - 10 - 1 - - - - 292 - {{516, 712}, {301, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - I'm Too Young To Die. - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - 1 - - - - 292 - {{534, 712}, {282, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Hey, Not Too Rough. - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - 1 - - - - 292 - {{610, 712}, {207, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Hurt Me Plenty. - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - 1 - - - - 292 - {{618, 712}, {198, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Ultra-Violence. - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - 1 - - - - 292 - {{205, 538}, {121, 38}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Difficulty - - Helvetica - 32 - 16 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - - - - 292 - {{206, 32}, {129, 45}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Mission - - Helvetica - 38 - 16 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - 10 - - - - 292 - {{58, 39}, {67, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Back - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - 1 - 10 - 1 - - - - 288 - - YES - - - 292 - {{20, 9}, {386, 41}} - - NO - 20 - 1 - IBIPadFramework - 0 - - Helvetica-Bold - 34 - 16 - - {1, 2} - E2M1: Deimos Anomaly - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - - - 292 - {{20, 54}, {403, 41}} - - NO - 21 - 1 - IBIPadFramework - 0 - - {1, 2} - E2M2: Containment Area - - - - - - - - 292 - {{20, 99}, {256, 41}} - - NO - 22 - 1 - IBIPadFramework - 0 - - {1, 2} - E2M3: Refinery - - - - - - - - 292 - {{20, 143}, {303, 41}} - - NO - 23 - 1 - IBIPadFramework - 0 - - {1, 2} - E2M4: Deimos Lab - - - - - - - - 292 - {{20, 188}, {394, 41}} - - NO - 24 - 1 - IBIPadFramework - 0 - - {1, 2} - E2M5: Command Center - - - - - - - - 292 - {{20, 233}, {438, 41}} - - NO - 25 - 1 - IBIPadFramework - 0 - - {1, 2} - E2M6: Halls of the Damned - - - - - - - - 292 - {{20, 278}, {396, 41}} - - NO - 26 - 1 - IBIPadFramework - 0 - - {1, 2} - E2M7: Computer Station - - - - - - - - 292 - {{20, 323}, {388, 41}} - - NO - 27 - 1 - IBIPadFramework - 0 - - {1, 2} - E2M8: Phobos Anomaly - - - - - - - - 292 - {{20, 368}, {321, 41}} - - NO - 28 - 1 - IBIPadFramework - 0 - - {1, 2} - E2M9: Military Base - - - - - - - {{200, 83}, {611, 411}} - - - 1 - MSAxIDEgMAA - - YES - 0.0 - YES - 1 - IBIPadFramework - 1 - 100 - 0.0 - 0.0 - 2 - - - - 292 - - YES - - - 292 - {{20, 9}, {275, 41}} - - NO - 30 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M1: Hell Keep - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - - - 292 - {{20, 54}, {402, 41}} - - NO - 31 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M2: Slough of Despair - - - - - - - - 292 - {{20, 99}, {345, 41}} - - NO - 32 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M3: Pandemonium - - - - - - - - 292 - {{20, 143}, {346, 41}} - - NO - 33 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M4: House of Pain - - - - - - - - 292 - {{20, 188}, {392, 41}} - - NO - 34 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M5: Unholy Cathedral - - - - - - - - 292 - {{20, 233}, {285, 41}} - - NO - 35 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M6: Mt. Erebus - - - - - - - - 292 - {{20, 278}, {212, 41}} - - NO - 36 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M7: Limbo - - - - - - - - 292 - {{20, 323}, {163, 41}} - - NO - 37 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M8: Dis - - - - - - - - 292 - {{20, 368}, {247, 41}} - - NO - 38 - 1 - IBIPadFramework - 0 - - {1, 2} - E3M9: Warrens - - - - - - - {{199.5, 82.5}, {611, 412}} - - - 1 - MSAxIDEgMAA - - YES - 0.0 - YES - 1 - IBIPadFramework - 1 - 100 - 0.0 - 0.0 - 2 - - - - 292 - - YES - - - 292 - {{20, 9}, {317, 41}} - - NO - 40 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M1: Hell Beneath - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - - - 292 - {{20, 54}, {343, 41}} - - NO - 41 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M2: Perfect Hatred - - - - - - - - 292 - {{20, 99}, {411, 41}} - - NO - 42 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M3: Sever The Wicked - - - - - - - - 292 - {{20, 143}, {288, 41}} - - NO - 43 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M4: Unruly Evil - - - - - - - - 292 - {{20, 188}, {385, 41}} - - NO - 44 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M5: They Will Repent - - - - - - - - 292 - {{20, 233}, {481, 41}} - - NO - 45 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M6: Against Thee Wickedly - - - - - - - - 292 - {{20, 278}, {406, 41}} - - NO - 46 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M7: And Hell Followed - - - - - - - - 292 - {{20, 323}, {354, 41}} - - NO - 47 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M8: Unto The Cruel - - - - - - - - 292 - {{20, 368}, {182, 41}} - - NO - 48 - 1 - IBIPadFramework - 0 - - {1, 2} - E4M9: Fear - - - - - - - {{200, 82.5}, {610, 412}} - - - 1 - MSAxIDEgMAA - - YES - 0.0 - YES - 1 - IBIPadFramework - 1 - 100 - 0.0 - 0.0 - 2 - - - - 292 - - YES - - - 292 - {{20, 9}, {254, 45}} - - NO - 10 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M1: Hanger - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - - - 292 - {{20, 54}, {367, 45}} - - NO - 11 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M2: Nuclear Plant - - - - - - - - 292 - {{20, 101}, {347, 41}} - - NO - 12 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M3: Toxin Refinery - - - - - - - - 292 - {{20, 146}, {407, 41}} - - NO - 13 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M4: Command Control - - - - - - - - 292 - {{20, 191}, {314, 41}} - - NO - 14 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M5: Phobos Lab - - - - - - - - 292 - {{20, 236}, {421, 41}} - - NO - 15 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M6: Central Processing - - - - - - - - 292 - {{20, 281}, {396, 41}} - - NO - 16 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M7: Computer Station - - - - - - - - 292 - {{20, 326}, {388, 41}} - - NO - 17 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M8: Phobos Anomaly - - - - - - - - 292 - {{20, 371}, {321, 41}} - - NO - 18 - 1 - IBIPadFramework - 0 - - {1, 2} - E1M9: Military Base - - - - - - - {{200.5, 82.5}, {609, 412}} - - - 1 - MSAxIDEgMAA - - YES - 0.0 - YES - 1 - IBIPadFramework - 1 - 100 - 0.0 - 0.0 - 2 - - - {1024, 768} - - 3 - MQA - - - 1 - IBIPadFramework - - - 3 - - 1 - IBIPadFramework - YES - - - - - 292 - - YES - - - 292 - {1024, 768} - - NO - 1 - IBIPadFramework - - - - - 274 - {{179, 74}, {666, 428}} - - 1 - NO - 1 - IBIPadFramework - - - - - 274 - - YES - - - 274 - {{0, 20}, {1024, 749}} - - NO - 1 - IBIPadFramework - - NSImage - SubMenuBackground.png - - - - - 274 - {{316, 198}, {195, 174}} - - NO - 1 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - SubMenuButton_Highlighted.png - - - NSImage - SubMenuButton.png - - - - - 274 - {{549, 198}, {195, 174}} - - NO - 2 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 274 - {{296, 322}, {234, 41}} - - NO - YES - 7 - 3 - NO - 1 - IBIPadFramework - MORE GAMES - - idGinzaNarrow-Medium2 - 34 - 16 - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 274 - {{595, 322}, {102, 41}} - - NO - YES - 7 - 4 - NO - 1 - IBIPadFramework - DEMO - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - NO - 10 - 1 - - - {{-20, -2}, {1024, 768}} - - - 0.0 - 1 - IBIPadFramework - - - - 274 - - YES - - - 274 - {{0, 19.5}, {1024, 749}} - - NO - 1 - IBIPadFramework - - - - - 274 - {{163.5, 197}, {195, 174}} - - NO - 1 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 274 - {{672, 203}, {195, 174}} - - NO - 2 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 274 - {{414, 203}, {195, 174}} - - NO - 2 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 274 - {{199, 321}, {125, 50}} - - NO - YES - 7 - 3 - NO - 1 - IBIPadFramework - LEGAL - - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 274 - {{695, 321}, {150, 50}} - - NO - YES - 7 - 3 - NO - 1 - IBIPadFramework - CREDITS - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 274 - {{429, 321.5}, {165, 50}} - - NO - YES - 7 - 4 - NO - 1 - IBIPadFramework - SUPPORT - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - NO - 10 - 1 - - - {{-20, -2}, {1024, 768}} - - - 0.0 - 1 - IBIPadFramework - - - - 274 - - YES - - - 274 - {{0, 20}, {1024, 749}} - - NO - 1 - IBIPadFramework - - - - - 274 - {{316, 206}, {195, 174}} - - NO - 1 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 274 - {{541, 206}, {195, 174}} - - NO - 2 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 274 - {{319, 328}, {189, 41}} - - NO - YES - 7 - 3 - NO - 1 - IBIPadFramework - CONTROLS - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 274 - {{562, 328}, {154, 41}} - - NO - YES - 7 - 4 - NO - 1 - IBIPadFramework - OPTIONS - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - NO - 10 - 1 - - - {{-20, -2}, {1024, 768}} - - - 0.0 - 1 - IBIPadFramework - - - - 274 - - YES - - - 274 - {{0, 19.5}, {1024, 749}} - - NO - 1 - IBIPadFramework - - - - - 274 - {{265, 207}, {195, 174}} - - NO - 1 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 274 - {{591, 207}, {195, 174}} - - NO - 2 - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - 274 - {{267, 331}, {190, 41}} - - NO - YES - 7 - 3 - NO - 1 - IBIPadFramework - NEW GAME - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - NO - 10 - 1 - - - - 274 - {{560, 331}, {256, 41}} - - NO - YES - 7 - 4 - NO - 1 - IBIPadFramework - RESUME GAME - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - - 1 - NO - 10 - 1 - - - {{-20, -2}, {1024, 768}} - - - 0.0 - 1 - IBIPadFramework - - - - 274 - {{54, 426}, {191, 191}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Button_Highlighted.png - - - - NSImage - Button.png - - - - - 274 - {{292, 530}, {191, 191}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 274 - {{550, 530}, {191, 191}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 274 - {{801, 426}, {191, 191}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - - - 274 - {{821, 580.5}, {150, 50}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - EXTRAS - - idGinzaNarrow-Medium2 - 36 - 16 - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - MC44Nzg0MzEzNzk4IDAuMzg0MzEzNzMyNCAwLjExMzcyNTQ5MDkAA - - 1 - NO - 10 - 1 - - - - 274 - {{571, 686.5}, {150, 50}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - ABOUT - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - NO - 10 - 1 - - - - 292 - {{297, 686.5}, {181, 50}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - SETTINGS - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - NO - 10 - 1 - - - - 292 - {{44.5, 555.5}, {210, 100}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - PLAY GAME - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - - 1 - NO - 10 - 1 - - - {1024, 768} - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - 3 - - 1 - IBIPadFramework - - - 3 - - 1 - IBIPadFramework - YES - - - - - 292 - - YES - - - 274 - {1024, 768} - - NO - 1 - IBIPadFramework - - - - - 274 - {{41, 39}, {93, 94}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode1Background.png - - - - - - 274 - {{885, 39}, {93, 94}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - - - - 274 - {{901, 28}, {62, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Next - - - 1 - MC43MjU0OTAyMTI0IDAuNDIzNTI5NDE2MyAwLjA2NjY2NjY3MDE0AA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - 1 - 10 - 1 - - - - 274 - {{55, 28}, {67, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Back - - - - 1 - 10 - 1 - - - - 274 - - YES - - - 292 - {{0, 80}, {601, 150}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode1Background_Highlighted.png - - - - - - - 274 - {{0, 220}, {601, 150}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode2Background_Highlighted.png - - - - NSImage - Episode2Background.png - - - - - 274 - {{0, 361}, {601, 150}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode3Background_Highlighted.png - - - - NSImage - Episode3Background.png - - - - - 274 - {{0, 503}, {601, 150}} - - NO - 1 - IBIPadFramework - 0 - 0 - - - - 1 - MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA - - - - NSImage - Episode4Background_Highlighted.png - - - - NSImage - Episode4Background.png - - - - - 292 - {{46, 549}, {171, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - EPISODE IV - - - 1 - MC40OTQxMTc2NDc0IDAuMTkyMTU2ODY2MiAwLjAwNzg0MzEzNzcxOQA - - - 1 - MC44NzA1ODgyNDMgMC43MTM3MjU1MDczIDAuMzQ1MDk4MDQ4NAA - - 1 - 10 - - - - 292 - {{46, 584}, {381, 47}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Thy Flesh Consumed - - Helvetica - 40 - 16 - - - 1 - MC44NTg4MjM1Mzc4IDAuMzQxMTc2NDgwMSAwAA - - - 1 - MSAwLjgwMDAwMDAxMTkgMAA - - 1 - 10 - - - - 292 - {{46, 441}, {125, 47}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Inferno - - - - 1 - 10 - - - - 292 - {{46, 407}, {168, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - EPISODE III - - - - 1 - 10 - - - - 292 - {{46, 302}, {332, 47}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - The Shores of Hell - - - - 1 - 10 - - - - 292 - {{46, 266}, {159, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - EPISODE II - - - - 1 - 10 - - - - 292 - {{46, 162}, {421, 47}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - Knee-Deep in the Dead - - - - 1 - 10 - - - - 292 - {{46, 129}, {151, 36}} - - NO - YES - 7 - NO - 1 - IBIPadFramework - EPISODE I - - - - 1 - 10 - - - {{212, 1}, {596, 767}} - - YES - YES - 1 - IBIPadFramework - - - {1024, 768} - - 2 - MC4wMTE3NjQ3MDcwNCAwIDAAA - - - 3 - - 1 - IBIPadFramework - - - 3 - - 1 - IBIPadFramework - YES - - - - 274 - {768, 1024} - - 3 - MQA - - - NO - IBIPadFramework - - - - - YES - - - delegate - - - - 4 - - - - window - - - - 5 - - - - glView - - - - 22 - - - - mediumSelection - - - - 309 - - - - MediumPressed - - - 7 - - 312 - - - - E1M7 - - - 7 - - 317 - - - - hardSelection - - - - 318 - - - - E1M8 - - - 7 - - 326 - - - - E1M5 - - - 7 - - 329 - - - - NightmarePressed - - - 7 - - 331 - - - - easySelection - - - - 332 - - - - E1M1 - - - 7 - - 340 - - - - E1M9 - - - 7 - - 341 - - - - EasyPressed - - - 7 - - 348 - - - - BackPressed - - - 7 - - 357 - - - - E1M2 - - - 7 - - 361 - - - - E1M6 - - - 7 - - 362 - - - - NightmareSelection - - - - 369 - - - - HardPressed - - - 7 - - 371 - - - - BackToMain - - - 7 - - 381 - - - - E1M3 - - - 7 - - 383 - - - - BackToMain - - - 7 - - 390 - - - - ResetToDefaults - - - 7 - - 393 - - - - BackToMain - - - 7 - - 395 - - - - BackToMain - - - 7 - - 396 - - - - E1M4 - - - 7 - - 400 - - - - controlsMenuViewController - - - - 402 - - - - creditsMenuViewController - - - - 403 - - - - legalMenuViewController - - - - 404 - - - - mainMenuViewController - - - - 405 - - - - mapMenuViewController - - - - 406 - - - - settingsMenuViewController - - - - 407 - - - - DirWheelPressed - - - 7 - - 415 - - - - DualThumbpadPressed - - - 7 - - 416 - - - - HudLayoutPressed - - - 7 - - 417 - - - - MoveStickValChanged - - - 13 - - 418 - - - - SingleThumbpadPressed - - - 7 - - 419 - - - - TiltMoveValChanged - - - 7 - - 420 - - - - TurnStickValChanged - - - 7 - - 421 - - - - movestickSize - - - - 422 - - - - tiltMoveSpeed - - - - 423 - - - - turnstickSize - - - - 424 - - - - singleThumbButton - - - - 453 - - - - dualThumbButton - - - - 454 - - - - dirWheelButton - - - - 455 - - - - scrollView - - - - 564 - - - - lastItem - - - - 565 - - - - TiltMoveValChanged - - - 7 - - 567 - - - - tiltTurnSpeed - - - - 569 - - - - TiltTurnValChanged - - - 13 - - 570 - - - - label - - - - 599 - - - - label - - - - 600 - - - - label - - - - 601 - - - - label - - - - 602 - - - - mPlaySubMenu - - - - 607 - - - - ShowPlayBanner - - - 7 - - 608 - - - - NewGamePressed - - - 7 - - 619 - - - - ShowExtrasBanner - - - 7 - - 624 - - - - ShowAboutBanner - - - 7 - - 625 - - - - ShowSettingsBanner - - - 7 - - 626 - - - - label - - - - 627 - - - - label - - - - 628 - - - - label - - - - 635 - - - - label - - - - 636 - - - - mSettingsSubMenu - - - - 638 - - - - ControlsOptionsPressed - - - 7 - - 639 - - - - SettingsOptionsPressed - - - 7 - - 640 - - - - label - - - - 648 - - - - label - - - - 653 - - - - label - - - - 655 - - - - LegalPressed - - - 7 - - 656 - - - - CreditsPressed - - - 7 - - 657 - - - - SupportPressed - - - 7 - - 658 - - - - mAboutSubMenu - - - - 659 - - - - label - - - - 680 - - - - label - - - - 681 - - - - DemoPressed - - - 7 - - 684 - - - - OtherIdGamesPressed - - - 7 - - 685 - - - - mExtrasSubMenu - - - - 686 - - - - mPlayButton - - - - 687 - - - - mSettingsButton - - - - 688 - - - - mExtrasButton - - - - 689 - - - - mAboutButton - - - - 690 - - - - label - - - - 774 - - - - label - - - - 775 - - - - BackToMain - - - 7 - - 784 - - - - SelectEpisode1 - - - 7 - - 785 - - - - SelectEpisode2 - - - 7 - - 786 - - - - SelectEpisode3 - - - 7 - - 787 - - - - SelectEpisode4 - - - 7 - - 788 - - - - episodeMenuViewController - - - - 789 - - - - label - - - - 790 - - - - label2 - - - - 791 - - - - label - - - - 792 - - - - label2 - - - - 793 - - - - label - - - - 794 - - - - label2 - - - - 795 - - - - label - - - - 796 - - - - label2 - - - - 797 - - - - NextToMissions - - - 7 - - 798 - - - - epi1Button - - - - 799 - - - - epi2Button - - - - 800 - - - - epi3Button - - - - 801 - - - - epi4Button - - - - 802 - - - - scrollView - - - - 804 - - - - lastItem - - - - 805 - - - - nextButton - - - - 806 - - - - nextLabel - - - - 807 - - - - E2M7 - - - 7 - - 848 - - - - E2M6 - - - 7 - - 852 - - - - E2M3 - - - 7 - - 853 - - - - E2M1 - - - 7 - - 857 - - - - E2M8 - - - 7 - - 858 - - - - E2M9 - - - 7 - - 861 - - - - E2M2 - - - 7 - - 873 - - - - E2M5 - - - 7 - - 874 - - - - E2M4 - - - 7 - - 875 - - - - E3M1 - - - 7 - - 922 - - - - E3M6 - - - 7 - - 927 - - - - E3M4 - - - 7 - - 932 - - - - E3M5 - - - 7 - - 933 - - - - E3M8 - - - 7 - - 935 - - - - E3M9 - - - 7 - - 939 - - - - E3M3 - - - 7 - - 951 - - - - E3M2 - - - 7 - - 952 - - - - E3M7 - - - 7 - - 953 - - - - E4M5 - - - 7 - - 991 - - - - E4M3 - - - 7 - - 992 - - - - E4M9 - - - 7 - - 996 - - - - E4M8 - - - 7 - - 1001 - - - - E4M7 - - - 7 - - 1011 - - - - E4M1 - - - 7 - - 1014 - - - - E4M2 - - - 7 - - 1017 - - - - E4M6 - - - 7 - - 1022 - - - - E4M4 - - - 7 - - 1023 - - - - mapScroller1 - - - - 1027 - - - - mapScroller2 - - - - 1028 - - - - mapScroller3 - - - - 1029 - - - - mapScroller4 - - - - 1030 - - - - lastElement1 - - - - 1031 - - - - lastElement2 - - - - 1032 - - - - lastElement3 - - - - 1033 - - - - lastElement4 - - - - 1034 - - - - label - - - - 1039 - - - - label - - - - 1041 - - - - easySelectionLabel - - - - 1046 - - - - hardSelectionLabel - - - - 1047 - - - - mediumSelectionLabel - - - - 1048 - - - - nightmareSelectionLabel - - - - 1049 - - - - UpMission - - - 1 - - 1062 - - - - DownMission - - - 1 - - 1063 - - - - Play - - - 7 - - 1064 - - - - playButton - - - - 1065 - - - - playLabel - - - - 1066 - - - - AutoUseChanged - - - 7 - - 1114 - - - - StatusBarChanged - - - 7 - - 1115 - - - - TouchClickChanged - - - 7 - - 1116 - - - - TextMessagesChanged - - - 7 - - 1117 - - - - DrawControlsChanged - - - 7 - - 1118 - - - - MusicChanged - - - 7 - - 1119 - - - - CenterSticksChanged - - - 7 - - 1120 - - - - RampTurnChanged - - - 7 - - 1121 - - - - autoUseSwitch - - - - 1122 - - - - centerSticksSwitch - - - - 1123 - - - - drawControlsSwitch - - - - 1124 - - - - musicSwitch - - - - 1125 - - - - rampTurnSwitch - - - - 1126 - - - - statusbarSwitch - - - - 1127 - - - - textMessageSwitch - - - - 1128 - - - - touchclickSwitch - - - - 1129 - - - - label - - - - 1138 - - - - label - - - - 1139 - - - - label - - - - 1140 - - - - label - - - - 1141 - - - - label - - - - 1142 - - - - label - - - - 1145 - - - - label - - - - 1147 - - - - ResumeGamePressed - - - 7 - - 1148 - - - - - YES - - 0 - - - - - - 2 - - - YES - - - - - -1 - - - File's Owner - - - 3 - - - Game App Delegate - - - -2 - - - - - 16 - - - GameView - - - 168 - - - YES - - - - SettingsMenuViewController - - - 169 - - - YES - - - - LegalMenuViewController - - - 170 - - - YES - - - - CreditsMenuViewController - - - 171 - - - YES - - - - ControlsMenuViewController - - - 172 - - - YES - - - - MapMenuViewController - - - 173 - - - YES - - - - MainMenuViewController - - - 190 - - - YES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 192 - - - - - 193 - - - - - 194 - - - - - 195 - - - - - 196 - - - - - 197 - - - - - 198 - - - - - 199 - - - - - 200 - - - - - 201 - - - Background - - - 238 - - - YES - - - - - - - - - - - - - - - - - - - - - - - ControlsMenuView - - - 239 - - - - - 240 - - - - - 241 - - - - - 242 - - - - - 243 - - - - - 244 - - - - - 245 - - - - - 246 - - - - - 247 - - - - - 248 - - - - - 249 - - - - - 250 - - - Background - - - 284 - - - YES - - - - - - - - - - - - - - - - - - - - - - - - SettingsMenuView - - - 285 - - - - - 286 - - - - - 287 - - - - - 288 - - - - - 289 - - - - - 290 - - - - - 291 - - - - - 292 - - - - - 301 - - - - - 302 - - - - - 303 - - - Background - - - 251 - - - YES - - - - - - - CreditsMenuView - - - 253 - - - Background - - - 530 - - - YES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 563 - - - - - 562 - - - - - 561 - - - - - 560 - - - - - 559 - - - - - 558 - - - - - 557 - - - - - 556 - - - - - 555 - - - - - 554 - - - - - 553 - - - - - 552 - - - - - 551 - - - - - 550 - - - - - 549 - - - - - 548 - - - - - 547 - - - - - 546 - - - - - 545 - - - - - 544 - - - - - 543 - - - - - 542 - - - - - 541 - - - - - 540 - - - - - 539 - - - - - 538 - - - - - 537 - - - - - 536 - - - - - 535 - - - - - 534 - - - - - 533 - - - - - 532 - - - - - 531 - - - - - 566 - - - - - 568 - - - - - 174 - - - YES - - - - - - - - - - - - - - - - - MainMenuView - - - 598 - - - - - 596 - - - - - 595 - - - - - 597 - - - - - 592 - - - Settings Button - - - 593 - - - About Button - - - 594 - - - Extras Button - - - 590 - - - Play Button - - - 591 - - - Logo - - - 606 - - - YES - - - - - - - - Play SubMenu - - - 605 - - - - - 609 - - - New Game Button - - - 612 - - - - - 613 - - - Resume Game Button - - - 614 - - - - - 629 - - - YES - - - - - - - - Settings SubMenu - - - 630 - - - Controls Button - - - 631 - - - - - 632 - - - - - 633 - - - SettingsButton - - - 634 - - - - - 691 - - - YES - - - - EpisodeViewController - - - 692 - - - YES - - - - - - - - - EpisodeMenuView - - - 770 - - - - - 771 - - - - - 772 - - - - - 803 - - - YES - - - - - - - - - - - - - - - - - 766 - - - - - 767 - - - - - 768 - - - - - 769 - - - - - 782 - - - - - 783 - - - - - 781 - - - - - 780 - - - - - 779 - - - - - 778 - - - - - 777 - - - - - 776 - - - - - 808 - - - YES - - - - - - - - - - - - Map Selection Scroll - - - 825 - - - - - 826 - - - - - 828 - - - - - 829 - - - - - 830 - - - - - 831 - - - - - 838 - - - - - 839 - - - - - 840 - - - - - 881 - - - YES - - - - - - - - - - - - Map Selection Scroll - - - 894 - - - - - 896 - - - - - 889 - - - - - 892 - - - - - 891 - - - - - 914 - - - - - 893 - - - - - 890 - - - - - 895 - - - - - 409 - - - - - 1035 - - - - - 1036 - - - - - 1038 - - - - - 1040 - - - - - 1042 - - - - - 1043 - - - - - 1044 - - - - - 1045 - - - - - 1051 - - - - - 1052 - - - - - 1055 - - - - - 1050 - - - - - 1067 - - - - - 1068 - - - - - 1096 - - - - - 1100 - - - - - 1102 - - - - - 1104 - - - - - 1106 - - - - - 1108 - - - - - 1110 - - - - - 1112 - - - - - 1131 - - - - - 1132 - - - - - 1133 - - - - - 1134 - - - - - 1136 - - - - - 1137 - - - - - 280 - - - YES - - - - - - - - LegalMenuView - - - 410 - - - - - 283 - - - Background - - - 282 - - - - - 281 - - - - - 1144 - - - - - 1146 - - - - - 189 - - - Background - - - 641 - - - YES - - - - - - - - - - About SubMenu - - - 654 - - - - - 643 - - - Credits Button - - - 644 - - - - - 646 - - - Legal Button - - - 642 - - - - - 651 - - - Support Button - - - 645 - - - - - 674 - - - YES - - - - - - - - Extras SubMenu - - - 675 - - - - - 677 - - - - - 678 - - - - - 676 - - - Demo Button - - - 679 - - - More Games Button - - - 773 - - - - - 697 - - - Background - - - 954 - - - YES - - - - - - - - - - - - Map Selection Scroll - - - 989 - - - - - 957 - - - - - 958 - - - - - 956 - - - - - 990 - - - - - 988 - - - - - 961 - - - - - 960 - - - - - 959 - - - - - 191 - - - YES - - - - - - - - - - - - Map Selection Scroll - - - 209 - - - - - 210 - - - - - 220 - - - - - 223 - - - - - 213 - - - - - 214 - - - - - 215 - - - - - 211 - - - - - 212 - - - - - 254 - - - - - - - YES - - YES - -1.CustomClassName - -2.CustomClassName - 1035.IBPluginDependency - 1035.IBViewBoundsToFrameTransform - 1036.CustomClassName - 1036.IBPluginDependency - 1036.IBViewBoundsToFrameTransform - 1038.CustomClassName - 1038.IBPluginDependency - 1038.IBViewBoundsToFrameTransform - 1040.CustomClassName - 1040.IBPluginDependency - 1040.IBViewBoundsToFrameTransform - 1042.CustomClassName - 1042.IBPluginDependency - 1042.IBViewBoundsToFrameTransform - 1043.CustomClassName - 1043.IBPluginDependency - 1043.IBViewBoundsToFrameTransform - 1044.CustomClassName - 1044.IBPluginDependency - 1044.IBViewBoundsToFrameTransform - 1045.CustomClassName - 1045.IBPluginDependency - 1045.IBViewBoundsToFrameTransform - 1050.CustomClassName - 1050.IBPluginDependency - 1050.IBViewBoundsToFrameTransform - 1051.CustomClassName - 1051.IBPluginDependency - 1051.IBViewBoundsToFrameTransform - 1052.CustomClassName - 1052.IBPluginDependency - 1052.IBViewBoundsToFrameTransform - 1055.CustomClassName - 1055.IBPluginDependency - 1055.IBViewBoundsToFrameTransform - 1067.CustomClassName - 1067.IBPluginDependency - 1067.IBViewBoundsToFrameTransform - 1068.CustomClassName - 1068.IBPluginDependency - 1068.IBViewBoundsToFrameTransform - 1096.CustomClassName - 1096.IBPluginDependency - 1096.IBViewBoundsToFrameTransform - 1100.CustomClassName - 1100.IBPluginDependency - 1100.IBViewBoundsToFrameTransform - 1102.CustomClassName - 1102.IBPluginDependency - 1102.IBViewBoundsToFrameTransform - 1104.CustomClassName - 1104.IBPluginDependency - 1104.IBViewBoundsToFrameTransform - 1106.CustomClassName - 1106.IBPluginDependency - 1106.IBViewBoundsToFrameTransform - 1108.CustomClassName - 1108.IBPluginDependency - 1108.IBViewBoundsToFrameTransform - 1110.CustomClassName - 1110.IBPluginDependency - 1110.IBViewBoundsToFrameTransform - 1112.CustomClassName - 1112.IBPluginDependency - 1112.IBViewBoundsToFrameTransform - 1131.CustomClassName - 1131.IBPluginDependency - 1131.IBViewBoundsToFrameTransform - 1132.CustomClassName - 1132.IBPluginDependency - 1132.IBViewBoundsToFrameTransform - 1133.CustomClassName - 1133.IBPluginDependency - 1133.IBViewBoundsToFrameTransform - 1134.IBPluginDependency - 1134.IBViewBoundsToFrameTransform - 1136.CustomClassName - 1136.IBPluginDependency - 1136.IBViewBoundsToFrameTransform - 1137.CustomClassName - 1137.IBPluginDependency - 1137.IBViewBoundsToFrameTransform - 1144.CustomClassName - 1144.IBPluginDependency - 1144.IBViewBoundsToFrameTransform - 1146.CustomClassName - 1146.IBPluginDependency - 1146.IBViewBoundsToFrameTransform - 16.CustomClassName - 16.IBEditorWindowLastContentRect - 16.IBPluginDependency - 16.IBViewBoundsToFrameTransform - 168.CustomClassName - 168.IBEditorWindowLastContentRect - 168.IBPluginDependency - 169.CustomClassName - 169.IBEditorWindowLastContentRect - 169.IBPluginDependency - 170.CustomClassName - 170.IBEditorWindowLastContentRect - 170.IBPluginDependency - 171.CustomClassName - 171.IBEditorWindowLastContentRect - 171.IBPluginDependency - 172.CustomClassName - 172.IBEditorWindowLastContentRect - 172.IBPluginDependency - 173.CustomClassName - 173.IBEditorWindowLastContentRect - 173.IBPluginDependency - 174.CustomClassName - 174.IBEditorWindowLastContentRect - 174.IBPluginDependency - 174.IBViewBoundsToFrameTransform - 189.IBPluginDependency - 189.IBViewBoundsToFrameTransform - 190.CustomClassName - 190.IBPluginDependency - 191.IBViewBoundsToFrameTransform - 192.IBPluginDependency - 192.IBViewBoundsToFrameTransform - 193.IBPluginDependency - 193.IBViewBoundsToFrameTransform - 194.IBPluginDependency - 194.IBViewBoundsToFrameTransform - 195.IBPluginDependency - 195.IBViewBoundsToFrameTransform - 196.IBPluginDependency - 196.IBViewBoundsToFrameTransform - 197.IBPluginDependency - 197.IBViewBoundsToFrameTransform - 198.IBPluginDependency - 198.IBViewBoundsToFrameTransform - 199.IBPluginDependency - 199.IBViewBoundsToFrameTransform - 2.IBAttributePlaceholdersKey - 2.IBEditorWindowLastContentRect - 2.IBPluginDependency - 2.IBViewBoundsToFrameTransform - 200.CustomClassName - 200.IBPluginDependency - 200.IBViewBoundsToFrameTransform - 201.IBPluginDependency - 201.IBViewBoundsToFrameTransform - 209.CustomClassName - 209.IBPluginDependency - 209.IBViewBoundsToFrameTransform - 210.CustomClassName - 210.IBPluginDependency - 210.IBViewBoundsToFrameTransform - 211.CustomClassName - 211.IBPluginDependency - 211.IBViewBoundsToFrameTransform - 212.CustomClassName - 212.IBPluginDependency - 212.IBViewBoundsToFrameTransform - 213.CustomClassName - 213.IBPluginDependency - 213.IBViewBoundsToFrameTransform - 214.CustomClassName - 214.IBPluginDependency - 214.IBViewBoundsToFrameTransform - 215.CustomClassName - 215.IBPluginDependency - 215.IBViewBoundsToFrameTransform - 220.CustomClassName - 220.IBPluginDependency - 220.IBViewBoundsToFrameTransform - 223.CustomClassName - 223.IBPluginDependency - 223.IBViewBoundsToFrameTransform - 238.CustomClassName - 238.IBEditorWindowLastContentRect - 238.IBPluginDependency - 238.IBViewBoundsToFrameTransform - 239.CustomClassName - 239.IBPluginDependency - 239.IBViewBoundsToFrameTransform - 240.CustomClassName - 240.IBPluginDependency - 240.IBViewBoundsToFrameTransform - 241.CustomClassName - 241.IBPluginDependency - 241.IBViewBoundsToFrameTransform - 242.CustomClassName - 242.IBPluginDependency - 242.IBViewBoundsToFrameTransform - 243.CustomClassName - 243.IBPluginDependency - 243.IBViewBoundsToFrameTransform - 244.CustomClassName - 244.IBPluginDependency - 244.IBViewBoundsToFrameTransform - 245.CustomClassName - 245.IBPluginDependency - 245.IBViewBoundsToFrameTransform - 246.CustomClassName - 246.IBPluginDependency - 246.IBViewBoundsToFrameTransform - 247.CustomClassName - 247.IBPluginDependency - 247.IBViewBoundsToFrameTransform - 248.CustomClassName - 248.IBPluginDependency - 248.IBViewBoundsToFrameTransform - 249.CustomClassName - 249.IBPluginDependency - 249.IBViewBoundsToFrameTransform - 250.IBPluginDependency - 250.IBViewBoundsToFrameTransform - 251.CustomClassName - 251.IBEditorWindowLastContentRect - 251.IBPluginDependency - 251.IBViewBoundsToFrameTransform - 253.IBPluginDependency - 253.IBViewBoundsToFrameTransform - 254.CustomClassName - 254.IBPluginDependency - 254.IBViewBoundsToFrameTransform - 280.CustomClassName - 280.IBEditorWindowLastContentRect - 280.IBPluginDependency - 280.IBViewBoundsToFrameTransform - 281.CustomClassName - 281.IBPluginDependency - 281.IBViewBoundsToFrameTransform - 282.CustomClassName - 282.IBPluginDependency - 282.IBViewBoundsToFrameTransform - 283.IBPluginDependency - 283.IBViewBoundsToFrameTransform - 284.CustomClassName - 284.IBEditorWindowLastContentRect - 284.IBPluginDependency - 284.IBViewBoundsToFrameTransform - 285.CustomClassName - 285.IBPluginDependency - 285.IBViewBoundsToFrameTransform - 286.CustomClassName - 286.IBPluginDependency - 286.IBViewBoundsToFrameTransform - 287.CustomClassName - 287.IBPluginDependency - 287.IBViewBoundsToFrameTransform - 288.CustomClassName - 288.IBPluginDependency - 288.IBViewBoundsToFrameTransform - 289.CustomClassName - 289.IBPluginDependency - 289.IBViewBoundsToFrameTransform - 290.CustomClassName - 290.IBPluginDependency - 290.IBViewBoundsToFrameTransform - 291.CustomClassName - 291.IBPluginDependency - 291.IBViewBoundsToFrameTransform - 292.CustomClassName - 292.IBPluginDependency - 292.IBViewBoundsToFrameTransform - 3.CustomClassName - 3.IBPluginDependency - 301.CustomClassName - 301.IBPluginDependency - 301.IBViewBoundsToFrameTransform - 302.CustomClassName - 302.IBPluginDependency - 302.IBViewBoundsToFrameTransform - 303.IBPluginDependency - 303.IBViewBoundsToFrameTransform - 409.IBPluginDependency - 409.IBViewBoundsToFrameTransform - 410.IBPluginDependency - 410.IBViewBoundsToFrameTransform - 530.IBViewBoundsToFrameTransform - 531.CustomClassName - 531.IBPluginDependency - 531.IBViewBoundsToFrameTransform - 532.CustomClassName - 532.IBPluginDependency - 532.IBViewBoundsToFrameTransform - 533.CustomClassName - 533.IBPluginDependency - 533.IBViewBoundsToFrameTransform - 534.CustomClassName - 534.IBPluginDependency - 534.IBViewBoundsToFrameTransform - 535.CustomClassName - 535.IBPluginDependency - 535.IBViewBoundsToFrameTransform - 536.CustomClassName - 536.IBPluginDependency - 536.IBViewBoundsToFrameTransform - 537.CustomClassName - 537.IBPluginDependency - 537.IBViewBoundsToFrameTransform - 538.CustomClassName - 538.IBPluginDependency - 538.IBViewBoundsToFrameTransform - 539.CustomClassName - 539.IBPluginDependency - 539.IBViewBoundsToFrameTransform - 540.CustomClassName - 540.IBPluginDependency - 540.IBViewBoundsToFrameTransform - 541.CustomClassName - 541.IBPluginDependency - 541.IBViewBoundsToFrameTransform - 542.CustomClassName - 542.IBPluginDependency - 542.IBViewBoundsToFrameTransform - 543.CustomClassName - 543.IBPluginDependency - 543.IBViewBoundsToFrameTransform - 544.CustomClassName - 544.IBPluginDependency - 544.IBViewBoundsToFrameTransform - 545.CustomClassName - 545.IBPluginDependency - 545.IBViewBoundsToFrameTransform - 546.CustomClassName - 546.IBPluginDependency - 546.IBViewBoundsToFrameTransform - 547.CustomClassName - 547.IBPluginDependency - 547.IBViewBoundsToFrameTransform - 548.CustomClassName - 548.IBPluginDependency - 548.IBViewBoundsToFrameTransform - 549.CustomClassName - 549.IBPluginDependency - 549.IBViewBoundsToFrameTransform - 550.CustomClassName - 550.IBPluginDependency - 550.IBViewBoundsToFrameTransform - 551.CustomClassName - 551.IBPluginDependency - 551.IBViewBoundsToFrameTransform - 552.CustomClassName - 552.IBPluginDependency - 552.IBViewBoundsToFrameTransform - 553.CustomClassName - 553.IBPluginDependency - 553.IBViewBoundsToFrameTransform - 554.CustomClassName - 554.IBPluginDependency - 554.IBViewBoundsToFrameTransform - 555.CustomClassName - 555.IBPluginDependency - 555.IBViewBoundsToFrameTransform - 556.CustomClassName - 556.IBPluginDependency - 556.IBViewBoundsToFrameTransform - 557.CustomClassName - 557.IBPluginDependency - 557.IBViewBoundsToFrameTransform - 558.CustomClassName - 558.IBPluginDependency - 558.IBViewBoundsToFrameTransform - 559.CustomClassName - 559.IBPluginDependency - 559.IBViewBoundsToFrameTransform - 560.CustomClassName - 560.IBPluginDependency - 560.IBViewBoundsToFrameTransform - 561.CustomClassName - 561.IBPluginDependency - 561.IBViewBoundsToFrameTransform - 562.CustomClassName - 562.IBPluginDependency - 562.IBViewBoundsToFrameTransform - 563.CustomClassName - 563.IBPluginDependency - 563.IBViewBoundsToFrameTransform - 566.CustomClassName - 566.IBPluginDependency - 566.IBViewBoundsToFrameTransform - 568.CustomClassName - 568.IBPluginDependency - 568.IBViewBoundsToFrameTransform - 590.CustomClassName - 590.IBPluginDependency - 590.IBViewBoundsToFrameTransform - 591.IBPluginDependency - 591.IBViewBoundsToFrameTransform - 592.CustomClassName - 592.IBPluginDependency - 592.IBViewBoundsToFrameTransform - 593.CustomClassName - 593.IBPluginDependency - 593.IBViewBoundsToFrameTransform - 594.CustomClassName - 594.IBPluginDependency - 594.IBViewBoundsToFrameTransform - 595.CustomClassName - 595.IBPluginDependency - 595.IBViewBoundsToFrameTransform - 596.CustomClassName - 596.IBPluginDependency - 596.IBViewBoundsToFrameTransform - 597.CustomClassName - 597.IBPluginDependency - 597.IBViewBoundsToFrameTransform - 598.CustomClassName - 598.IBPluginDependency - 598.IBViewBoundsToFrameTransform - 605.IBPluginDependency - 605.IBViewBoundsToFrameTransform - 606.CustomClassName - 606.IBPluginDependency - 606.IBViewBoundsToFrameTransform - 609.CustomClassName - 609.IBPluginDependency - 609.IBViewBoundsToFrameTransform - 612.CustomClassName - 612.IBPluginDependency - 612.IBViewBoundsToFrameTransform - 613.CustomClassName - 613.IBPluginDependency - 613.IBViewBoundsToFrameTransform - 614.CustomClassName - 614.IBPluginDependency - 614.IBViewBoundsToFrameTransform - 629.CustomClassName - 629.IBPluginDependency - 629.IBViewBoundsToFrameTransform - 630.CustomClassName - 630.IBPluginDependency - 630.IBViewBoundsToFrameTransform - 631.CustomClassName - 631.IBPluginDependency - 631.IBViewBoundsToFrameTransform - 632.CustomClassName - 632.IBPluginDependency - 632.IBViewBoundsToFrameTransform - 633.CustomClassName - 633.IBPluginDependency - 633.IBViewBoundsToFrameTransform - 634.IBPluginDependency - 634.IBViewBoundsToFrameTransform - 641.CustomClassName - 641.IBPluginDependency - 641.IBViewBoundsToFrameTransform - 642.IBPluginDependency - 642.IBViewBoundsToFrameTransform - 643.CustomClassName - 643.IBPluginDependency - 643.IBViewBoundsToFrameTransform - 644.CustomClassName - 644.IBPluginDependency - 644.IBViewBoundsToFrameTransform - 645.CustomClassName - 645.IBPluginDependency - 645.IBViewBoundsToFrameTransform - 646.CustomClassName - 646.IBPluginDependency - 646.IBViewBoundsToFrameTransform - 651.CustomClassName - 651.IBPluginDependency - 651.IBViewBoundsToFrameTransform - 654.CustomClassName - 654.IBPluginDependency - 654.IBViewBoundsToFrameTransform - 674.CustomClassName - 674.IBPluginDependency - 674.IBViewBoundsToFrameTransform - 675.IBPluginDependency - 675.IBViewBoundsToFrameTransform - 676.CustomClassName - 676.IBPluginDependency - 676.IBViewBoundsToFrameTransform - 677.CustomClassName - 677.IBPluginDependency - 677.IBViewBoundsToFrameTransform - 678.CustomClassName - 678.IBPluginDependency - 678.IBViewBoundsToFrameTransform - 679.CustomClassName - 679.IBPluginDependency - 679.IBViewBoundsToFrameTransform - 691.CustomClassName - 691.IBEditorWindowLastContentRect - 691.IBPluginDependency - 692.CustomClassName - 692.IBEditorWindowLastContentRect - 692.IBPluginDependency - 692.IBViewBoundsToFrameTransform - 697.IBPluginDependency - 697.IBViewBoundsToFrameTransform - 766.CustomClassName - 766.IBPluginDependency - 766.IBViewBoundsToFrameTransform - 767.CustomClassName - 767.IBPluginDependency - 767.IBViewBoundsToFrameTransform - 768.CustomClassName - 768.IBPluginDependency - 768.IBViewBoundsToFrameTransform - 769.CustomClassName - 769.IBPluginDependency - 769.IBViewBoundsToFrameTransform - 770.CustomClassName - 770.IBPluginDependency - 770.IBViewBoundsToFrameTransform - 771.CustomClassName - 771.IBPluginDependency - 771.IBViewBoundsToFrameTransform - 772.CustomClassName - 772.IBPluginDependency - 772.IBViewBoundsToFrameTransform - 773.CustomClassName - 773.IBPluginDependency - 773.IBViewBoundsToFrameTransform - 776.CustomClassName - 776.IBPluginDependency - 776.IBViewBoundsToFrameTransform - 777.CustomClassName - 777.IBPluginDependency - 777.IBViewBoundsToFrameTransform - 778.CustomClassName - 778.IBPluginDependency - 778.IBViewBoundsToFrameTransform - 779.CustomClassName - 779.IBPluginDependency - 779.IBViewBoundsToFrameTransform - 780.CustomClassName - 780.IBPluginDependency - 780.IBViewBoundsToFrameTransform - 781.CustomClassName - 781.IBPluginDependency - 781.IBViewBoundsToFrameTransform - 782.CustomClassName - 782.IBPluginDependency - 782.IBViewBoundsToFrameTransform - 783.CustomClassName - 783.IBPluginDependency - 783.IBViewBoundsToFrameTransform - 803.IBViewBoundsToFrameTransform - 808.IBViewBoundsToFrameTransform - 825.CustomClassName - 825.IBPluginDependency - 825.IBViewBoundsToFrameTransform - 826.CustomClassName - 826.IBPluginDependency - 826.IBViewBoundsToFrameTransform - 828.CustomClassName - 828.IBPluginDependency - 828.IBViewBoundsToFrameTransform - 829.CustomClassName - 829.IBPluginDependency - 829.IBViewBoundsToFrameTransform - 830.CustomClassName - 830.IBPluginDependency - 830.IBViewBoundsToFrameTransform - 831.CustomClassName - 831.IBPluginDependency - 831.IBViewBoundsToFrameTransform - 838.CustomClassName - 838.IBPluginDependency - 838.IBViewBoundsToFrameTransform - 839.CustomClassName - 839.IBPluginDependency - 839.IBViewBoundsToFrameTransform - 840.CustomClassName - 840.IBPluginDependency - 840.IBViewBoundsToFrameTransform - 881.IBViewBoundsToFrameTransform - 889.CustomClassName - 889.IBPluginDependency - 889.IBViewBoundsToFrameTransform - 890.CustomClassName - 890.IBPluginDependency - 890.IBViewBoundsToFrameTransform - 891.CustomClassName - 891.IBPluginDependency - 891.IBViewBoundsToFrameTransform - 892.CustomClassName - 892.IBPluginDependency - 892.IBViewBoundsToFrameTransform - 893.CustomClassName - 893.IBPluginDependency - 893.IBViewBoundsToFrameTransform - 894.CustomClassName - 894.IBPluginDependency - 894.IBViewBoundsToFrameTransform - 895.CustomClassName - 895.IBPluginDependency - 895.IBViewBoundsToFrameTransform - 896.CustomClassName - 896.IBPluginDependency - 896.IBViewBoundsToFrameTransform - 914.CustomClassName - 914.IBPluginDependency - 914.IBViewBoundsToFrameTransform - 954.IBViewBoundsToFrameTransform - 956.CustomClassName - 956.IBPluginDependency - 956.IBViewBoundsToFrameTransform - 957.CustomClassName - 957.IBPluginDependency - 957.IBViewBoundsToFrameTransform - 958.CustomClassName - 958.IBPluginDependency - 958.IBViewBoundsToFrameTransform - 959.CustomClassName - 959.IBPluginDependency - 959.IBViewBoundsToFrameTransform - 960.CustomClassName - 960.IBPluginDependency - 960.IBViewBoundsToFrameTransform - 961.CustomClassName - 961.IBPluginDependency - 961.IBViewBoundsToFrameTransform - 988.CustomClassName - 988.IBPluginDependency - 988.IBViewBoundsToFrameTransform - 989.CustomClassName - 989.IBPluginDependency - 989.IBViewBoundsToFrameTransform - 990.CustomClassName - 990.IBPluginDependency - 990.IBViewBoundsToFrameTransform - - - YES - UIApplication - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCnAAAw7eAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEKQAAxAuAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD6gAAw4mAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBEAAAw4mAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDGwAAw6IAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDGwAAw6IAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDGwAAw6IAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDGwAAw6IAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCqgAAw2EAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDFQAAwmQAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDVQAAwZgAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDWAAAw1AAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEZ4AAwmAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCSAAAwnwAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDlQAAw58AAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDlQAAw9GAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDlQAAxAKAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDlQAAxB2AAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEUYAAw4BAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEUYAAw65AAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABESQAAxARAAA - - UICustomSwitch - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABESQAAxB+AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDRwAAw34AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD7AAAw8IAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABENoAAw34AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDAQAAw8uAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIcAABCPAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEa0AAwroAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDhQAAw/WAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBEAAAw5OAAA - - EAGLView - {{608, 311}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw+8AAA - - MenuViewController - {{603, 444}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{305, 372}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{289, 371}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{697, 406}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{285, 366}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MenuViewController - {{58, 385}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - MainMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - MapMenuView - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDTgAAxAHAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEKgAAxBCAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEBEAAxBCAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDuAAAxBCAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDUAAAxBBAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEH4AAxAbAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEAcAAxAbAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDwQAAxAbAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDhAAAxAcAAA - - - YES - - - YES - - - {{500, 343}, {320, 480}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw+8AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDewAAxAuAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAADDBwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDp4AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABDPAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABDiwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABCTAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABCwAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABDDwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDvgAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABAwAAAA - - ControlsMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUEQAABCVAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEQIAAw8oAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEQIAAw7mAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEQIAAw6iAAA - - UICustomSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCCAAAw2EAAA - - UICustomSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCCAAAw0AAAA - - UICustomSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCCAAAwx8AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEX4AAxCxAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUQiAABCGAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUPEAABCGAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUMGAABCGAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - GenericMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDewAAxAuAAA - - GenericMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDewAAxAuAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - SettingsMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEHIAAxAhAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEGgAAw9oAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABENoAAw6LAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEFsAAw2mAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCaAAAxASAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC3gAAw94AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC6gAAw6cAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCkgAAw5CAAA - - gameAppDelegate - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABChgAAw/gAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEKQAAxAuAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAxD+AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC8AAAw58AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULmAABCIAAAA - - - AUKyAABCNAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxBjAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEcsAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxBQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxA8AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxAkAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxAIAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxEHAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAxDnAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEQAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEOwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEMQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEKQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEJAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEGgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEEgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEDUAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABEA0AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABD8oAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw+2AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAw3cAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABByAAAw1EAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDXAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwrgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw6YAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw5YAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDmwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABCXAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABCtgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwykAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAwyQAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDLgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDSAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUIkAABDqwAAA - - UICustomSlider - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCwgAAxBnAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEQIAAw+wAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBcAAAxCzAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC8gAAw7IAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCLAAAxF1AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDegAAxDqAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDtwAAxCtAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAADDMgAAxEvAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUI0AABD0wAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUOvAABD0wAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUQRgABDrQAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AQAAAADBeAAAA - - Banner_SubMenu - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AcGgAADAAAAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDtgAAw9uAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDBgAAwzsAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD/oAAw9uAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDhQAAwzsAAA - - Banner_SubMenu - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AcGgAADAAAAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDtgAAw9uAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABELcAAw84AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDxQAAw+YAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD/oAAw9uAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AQAAAADBeAAAA - - Banner_SubMenu - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AcGgAADAAAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AQAAAADBeAAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABED0AAw9uAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDosAAw8tAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDmwAAwwYAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDkYAAw9uAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDMAAAwwwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEF+AAw8tAAA - - Banner_SubMenu - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AcGgAADAAAAAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxEjAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABD/oAAw9uAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC+AAAw70AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEEQAAw7kAAA - - Banner_SubItem - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDtgAAw9uAAA - - MenuViewController - {{283, 366}, {1024, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - GenericMenuView - {{295, 363}, {1004, 768}} - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAAAAAAAw58AAA - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCAAAAxC+AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAADDDoAAw4CAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCpQAAwrsAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDToAAwzKAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABDDgAAxAyAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAAA/gAAAxCyAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEZIAAxCyAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABEaEAAxBlAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBgAAAxBlAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCEAAAwykAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABCOAAAw08AAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABC6gAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABDBAAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABDNwAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AULUAABDRgAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC2QAAw0yAAA - - UIFontLabel - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABC2QAAw16AAA - - - P4AAAL+AAABCiAAAw6EAAA - - - P4AAAL+AAABCpgAAxBsAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABD5QAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABDzoAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEFEAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABD+4AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDi4AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDPQAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABAwAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEKsAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUGgAABDuIAAA - - - AUNNAABChAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEjaAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxCsAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEYwAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEV8AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEgmAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEbkAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxBSAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAw/wAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxDjAAA - - - AUNOAABChAAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEnoAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEr2AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEpCAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxH3AAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxGdAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAADCzgAAw2gAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxImgAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - AUDgAABEuqAAA - - UIFontButton - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - P4AAAL+AAABBoAAAxI9AAA - - - - - YES - - - YES - - - - - YES - - - YES - - - - 1148 - - - - YES - - Banner_SubItem - UIFontButton - - IBProjectSource - MainMenuView.h - - - - Banner_SubMenu - UIView - - - - ControlsMenuView - UIView - - YES - - YES - BackToMain - DirWheelPressed - DualThumbpadPressed - HudLayoutPressed - MoveStickValChanged - SingleThumbpadPressed - TiltMoveValChanged - TiltTurnValChanged - TurnStickValChanged - - - YES - id - id - id - id - id - id - id - id - id - - - - YES - - YES - BackToMain - DirWheelPressed - DualThumbpadPressed - HudLayoutPressed - MoveStickValChanged - SingleThumbpadPressed - TiltMoveValChanged - TiltTurnValChanged - TurnStickValChanged - - - YES - - BackToMain - id - - - DirWheelPressed - id - - - DualThumbpadPressed - id - - - HudLayoutPressed - id - - - MoveStickValChanged - id - - - SingleThumbpadPressed - id - - - TiltMoveValChanged - id - - - TiltTurnValChanged - id - - - TurnStickValChanged - id - - - - - YES - - YES - dirWheelButton - dualThumbButton - movestickSize - singleThumbButton - tiltMoveSpeed - tiltTurnSpeed - turnstickSize - - - YES - UIButton - UIButton - UISlider - UIButton - UISlider - UISlider - UISlider - - - - YES - - YES - dirWheelButton - dualThumbButton - movestickSize - singleThumbButton - tiltMoveSpeed - tiltTurnSpeed - turnstickSize - - - YES - - dirWheelButton - UIButton - - - dualThumbButton - UIButton - - - movestickSize - UISlider - - - singleThumbButton - UIButton - - - tiltMoveSpeed - UISlider - - - tiltTurnSpeed - UISlider - - - turnstickSize - UISlider - - - - - IBProjectSource - ControlsMenuView.h - - - - EAGLView - UIView - - IBProjectSource - EAGLView.h - - - - GenericMenuView - UIView - - YES - - YES - BackToMain - NextToMissions - SelectEpisode1 - SelectEpisode2 - SelectEpisode3 - SelectEpisode4 - - - YES - id - id - id - id - id - id - - - - YES - - YES - BackToMain - NextToMissions - SelectEpisode1 - SelectEpisode2 - SelectEpisode3 - SelectEpisode4 - - - YES - - BackToMain - id - - - NextToMissions - id - - - SelectEpisode1 - id - - - SelectEpisode2 - id - - - SelectEpisode3 - id - - - SelectEpisode4 - id - - - - - YES - - YES - epi1Button - epi2Button - epi3Button - epi4Button - lastItem - nextButton - nextLabel - scrollView - - - YES - UIFontButton - UIFontButton - UIFontButton - UIFontButton - UILabel - UIFontButton - UIFontLabel - UIScrollView - - - - YES - - YES - epi1Button - epi2Button - epi3Button - epi4Button - lastItem - nextButton - nextLabel - scrollView - - - YES - - epi1Button - UIFontButton - - - epi2Button - UIFontButton - - - epi3Button - UIFontButton - - - epi4Button - UIFontButton - - - lastItem - UILabel - - - nextButton - UIFontButton - - - nextLabel - UIFontLabel - - - scrollView - UIScrollView - - - - - IBProjectSource - GenericMenuView.h - - - - MainMenuView - UIView - - YES - - YES - ControlsOptionsPressed - CreditsPressed - DemoPressed - LegalPressed - MultiplayerPressed - NewGamePressed - OtherIdGamesPressed - ResumeGamePressed - SettingsOptionsPressed - ShowAboutBanner - ShowExtrasBanner - ShowPlayBanner - ShowSettingsBanner - SupportPressed - - - YES - id - id - id - id - id - id - id - id - id - id - id - id - id - id - - - - YES - - YES - ControlsOptionsPressed - CreditsPressed - DemoPressed - LegalPressed - MultiplayerPressed - NewGamePressed - OtherIdGamesPressed - ResumeGamePressed - SettingsOptionsPressed - ShowAboutBanner - ShowExtrasBanner - ShowPlayBanner - ShowSettingsBanner - SupportPressed - - - YES - - ControlsOptionsPressed - id - - - CreditsPressed - id - - - DemoPressed - id - - - LegalPressed - id - - - MultiplayerPressed - id - - - NewGamePressed - id - - - OtherIdGamesPressed - id - - - ResumeGamePressed - id - - - SettingsOptionsPressed - id - - - ShowAboutBanner - id - - - ShowExtrasBanner - id - - - ShowPlayBanner - id - - - ShowSettingsBanner - id - - - SupportPressed - id - - - - - YES - - YES - mAboutButton - mAboutSubMenu - mExtrasButton - mExtrasSubMenu - mPlayButton - mPlaySubMenu - mSettingsButton - mSettingsSubMenu - - - YES - UIFontButton - Banner_SubMenu - UIFontButton - Banner_SubMenu - UIFontButton - Banner_SubMenu - UIFontButton - Banner_SubMenu - - - - YES - - YES - mAboutButton - mAboutSubMenu - mExtrasButton - mExtrasSubMenu - mPlayButton - mPlaySubMenu - mSettingsButton - mSettingsSubMenu - - - YES - - mAboutButton - UIFontButton - - - mAboutSubMenu - Banner_SubMenu - - - mExtrasButton - UIFontButton - - - mExtrasSubMenu - Banner_SubMenu - - - mPlayButton - UIFontButton - - - mPlaySubMenu - Banner_SubMenu - - - mSettingsButton - UIFontButton - - - mSettingsSubMenu - Banner_SubMenu - - - - - - - MapMenuView - UIView - - YES - - YES - BackPressed - DownMission - E1M1 - E1M2 - E1M3 - E1M4 - E1M5 - E1M6 - E1M7 - E1M8 - E1M9 - E2M1 - E2M2 - E2M3 - E2M4 - E2M5 - E2M6 - E2M7 - E2M8 - E2M9 - E3M1 - E3M2 - E3M3 - E3M4 - E3M5 - E3M6 - E3M7 - E3M8 - E3M9 - E4M1 - E4M2 - E4M3 - E4M4 - E4M5 - E4M6 - E4M7 - E4M8 - E4M9 - EasyPressed - HardPressed - MediumPressed - NightmarePressed - Play - UpMission - - - YES - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - - - - YES - - YES - BackPressed - DownMission - E1M1 - E1M2 - E1M3 - E1M4 - E1M5 - E1M6 - E1M7 - E1M8 - E1M9 - E2M1 - E2M2 - E2M3 - E2M4 - E2M5 - E2M6 - E2M7 - E2M8 - E2M9 - E3M1 - E3M2 - E3M3 - E3M4 - E3M5 - E3M6 - E3M7 - E3M8 - E3M9 - E4M1 - E4M2 - E4M3 - E4M4 - E4M5 - E4M6 - E4M7 - E4M8 - E4M9 - EasyPressed - HardPressed - MediumPressed - NightmarePressed - Play - UpMission - - - YES - - BackPressed - id - - - DownMission - id - - - E1M1 - id - - - E1M2 - id - - - E1M3 - id - - - E1M4 - id - - - E1M5 - id - - - E1M6 - id - - - E1M7 - id - - - E1M8 - id - - - E1M9 - id - - - E2M1 - id - - - E2M2 - id - - - E2M3 - id - - - E2M4 - id - - - E2M5 - id - - - E2M6 - id - - - E2M7 - id - - - E2M8 - id - - - E2M9 - id - - - E3M1 - id - - - E3M2 - id - - - E3M3 - id - - - E3M4 - id - - - E3M5 - id - - - E3M6 - id - - - E3M7 - id - - - E3M8 - id - - - E3M9 - id - - - E4M1 - id - - - E4M2 - id - - - E4M3 - id - - - E4M4 - id - - - E4M5 - id - - - E4M6 - id - - - E4M7 - id - - - E4M8 - id - - - E4M9 - id - - - EasyPressed - id - - - HardPressed - id - - - MediumPressed - id - - - NightmarePressed - id - - - Play - id - - - UpMission - id - - - - - YES - - YES - NightmareSelection - easySelection - easySelectionLabel - hardSelection - hardSelectionLabel - lastElement1 - lastElement2 - lastElement3 - lastElement4 - mapScroller1 - mapScroller2 - mapScroller3 - mapScroller4 - mediumSelection - mediumSelectionLabel - nightmareSelectionLabel - playButton - playLabel - - - YES - UIImageView - UIImageView - UIFontLabel - UIImageView - UIFontLabel - UIButton - UIButton - UIButton - UIButton - UIScrollView - UIScrollView - UIScrollView - UIScrollView - UIImageView - UIFontLabel - UIFontLabel - UIFontButton - UIFontLabel - - - - YES - - YES - NightmareSelection - easySelection - easySelectionLabel - hardSelection - hardSelectionLabel - lastElement1 - lastElement2 - lastElement3 - lastElement4 - mapScroller1 - mapScroller2 - mapScroller3 - mapScroller4 - mediumSelection - mediumSelectionLabel - nightmareSelectionLabel - playButton - playLabel - - - YES - - NightmareSelection - UIImageView - - - easySelection - UIImageView - - - easySelectionLabel - UIFontLabel - - - hardSelection - UIImageView - - - hardSelectionLabel - UIFontLabel - - - lastElement1 - UIButton - - - lastElement2 - UIButton - - - lastElement3 - UIButton - - - lastElement4 - UIButton - - - mapScroller1 - UIScrollView - - - mapScroller2 - UIScrollView - - - mapScroller3 - UIScrollView - - - mapScroller4 - UIScrollView - - - mediumSelection - UIImageView - - - mediumSelectionLabel - UIFontLabel - - - nightmareSelectionLabel - UIFontLabel - - - playButton - UIFontButton - - - playLabel - UIFontLabel - - - - - IBProjectSource - MapMenuView.h - - - - MenuViewController - UIViewController - - IBProjectSource - MenuViewController.h - - - - SettingsMenuView - UIImageView - - YES - - YES - AutoUseChanged - BackToMain - CenterSticksChanged - DrawControlsChanged - MusicChanged - RampTurnChanged - ResetToDefaults - StatusBarChanged - TextMessagesChanged - TouchClickChanged - - - YES - id - id - id - id - id - id - id - id - id - id - - - - YES - - YES - AutoUseChanged - BackToMain - CenterSticksChanged - DrawControlsChanged - MusicChanged - RampTurnChanged - ResetToDefaults - StatusBarChanged - TextMessagesChanged - TouchClickChanged - - - YES - - AutoUseChanged - id - - - BackToMain - id - - - CenterSticksChanged - id - - - DrawControlsChanged - id - - - MusicChanged - id - - - RampTurnChanged - id - - - ResetToDefaults - id - - - StatusBarChanged - id - - - TextMessagesChanged - id - - - TouchClickChanged - id - - - - - YES - - YES - autoUseSwitch - centerSticksSwitch - drawControlsSwitch - musicSwitch - rampTurnSwitch - statusbarSwitch - textMessageSwitch - touchclickSwitch - - - YES - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - UICustomSwitch - - - - YES - - YES - autoUseSwitch - centerSticksSwitch - drawControlsSwitch - musicSwitch - rampTurnSwitch - statusbarSwitch - textMessageSwitch - touchclickSwitch - - - YES - - autoUseSwitch - UICustomSwitch - - - centerSticksSwitch - UICustomSwitch - - - drawControlsSwitch - UICustomSwitch - - - musicSwitch - UICustomSwitch - - - rampTurnSwitch - UICustomSwitch - - - statusbarSwitch - UICustomSwitch - - - textMessageSwitch - UICustomSwitch - - - touchclickSwitch - UICustomSwitch - - - - - IBProjectSource - SettingsMenuView.h - - - - UICustomSlider - UISlider - - IBProjectSource - UICustomSlider.h - - - - UICustomSwitch - UIButton - - IBProjectSource - UICustomSwitch.h - - - - UIFontButton - UIButton - - YES - - YES - label - label2 - - - YES - UIFontLabel - UIFontLabel - - - - YES - - YES - label - label2 - - - YES - - label - UIFontLabel - - - label2 - UIFontLabel - - - - - IBProjectSource - UIFontButton.h - - - - UIFontLabel - UILabel - - IBProjectSource - UIFontLabel.h - - - - gameAppDelegate - NSObject - - YES - - YES - controlsMenuViewController - creditsMenuViewController - displayLink - episodeMenuViewController - glView - legalMenuViewController - mainMenuViewController - mapMenuViewController - settingsMenuViewController - window - - - YES - MenuViewController - MenuViewController - CADisplayLink - MenuViewController - EAGLView - MenuViewController - MenuViewController - MenuViewController - MenuViewController - UIWindow - - - - YES - - YES - controlsMenuViewController - creditsMenuViewController - displayLink - episodeMenuViewController - glView - legalMenuViewController - mainMenuViewController - mapMenuViewController - settingsMenuViewController - window - - - YES - - controlsMenuViewController - MenuViewController - - - creditsMenuViewController - MenuViewController - - - displayLink - CADisplayLink - - - episodeMenuViewController - MenuViewController - - - glView - EAGLView - - - legalMenuViewController - MenuViewController - - - mainMenuViewController - MenuViewController - - - mapMenuViewController - MenuViewController - - - settingsMenuViewController - MenuViewController - - - window - UIWindow - - - - - IBProjectSource - doomAppDelegate.h - - - - - YES - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CIImageProvider.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIAccessibility.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UINibLoading.h - - - - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UIResponder.h - - - - UIApplication - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIApplication.h - - - - UIButton - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UIButton.h - - - - UIControl - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIControl.h - - - - UIImageView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIImageView.h - - - - UILabel - UIView - - IBFrameworkSource - UIKit.framework/Headers/UILabel.h - - - - UIResponder - NSObject - - - - UIScrollView - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIScrollView.h - - - - UISearchBar - UIView - - IBFrameworkSource - UIKit.framework/Headers/UISearchBar.h - - - - UISearchDisplayController - NSObject - - IBFrameworkSource - UIKit.framework/Headers/UISearchDisplayController.h - - - - UISlider - UIControl - - IBFrameworkSource - UIKit.framework/Headers/UISlider.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIPrintFormatter.h - - - - UIView - - IBFrameworkSource - UIKit.framework/Headers/UITextField.h - - - - UIView - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIView.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UINavigationController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UIPopoverController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UISplitViewController.h - - - - UIViewController - - IBFrameworkSource - UIKit.framework/Headers/UITabBarController.h - - - - UIViewController - UIResponder - - IBFrameworkSource - UIKit.framework/Headers/UIViewController.h - - - - UIWindow - UIView - - IBFrameworkSource - UIKit.framework/Headers/UIWindow.h - - - - - 0 - IBIPadFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - ../Doom.xcodeproj - 3 - - YES - - YES - AdvancedButton.png - BackButton.png - Button.png - Button_Highlighted.png - DifficultyBackground.png - Divide.png - DoomLogo.png - DownArrow - DownArrow_Highlighted.png - Easy.png - Episode1Background.png - Episode1Background_Highlighted.png - Episode2Background.png - Episode2Background_Highlighted.png - Episode3Background.png - Episode3Background_Highlighted.png - Episode4Background.png - Episode4Background_Highlighted.png - Hard.png - LayoutDualButton.png - LayoutSingleButton.png - LayoutWheelButton.png - Medium.png - MenuBackground.png - MissonBackground.png - NextButton.png - NextButton_Highlighted.png - Nightmare.png - SelectedBracket.png - SettingsButton.png - SettingsButton_Highlighted.png - SubMenuBackground.png - SubMenuButton.png - SubMenuButton_Highlighted.png - UpArrow - UpArrow_Highlighted.png - - - YES - {93, 94} - {93, 94} - {191, 191} - {191, 191} - {636, 152} - {764, 11} - {557, 358} - {13, 13} - {80, 36} - {123, 123} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {601, 150} - {121, 121} - {241, 166} - {241, 166} - {241, 166} - {121, 121} - {960, 640} - {656, 363} - {93, 94} - {93, 94} - {121, 121} - {133, 133} - {80, 89} - {80, 89} - {959, 574} - {195, 174} - {195, 174} - {13, 13} - {80, 36} - - - 141 - - diff --git a/code/iphone/SIGIL-iOS-Info.plist b/code/iphone/SIGIL-iOS-Info.plist new file mode 100755 index 0000000..7954cbc --- /dev/null +++ b/code/iphone/SIGIL-iOS-Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + DOOM_57.png + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 2.7 + CFBundleSignature + ???? + CFBundleVersion + 2.7 + LSRequiresIPhoneOS + + UIAppFonts + + idGinzaNar-Md2.otf + + UIFileSharingEnabled + + UIInterfaceOrientation + UIInterfaceOrientationLandscapeLeft + UILaunchStoryboardName + SIGILLaunchScreen + UIPrerenderedIcon + + UIRequiresFullScreen + + UIRequiresPersistentWiFi + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Contents.json b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..0cc2196 --- /dev/null +++ b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-40.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-60.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-58.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-87.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-80.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-120.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-121.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-180.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-41.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-59.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-42.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-81.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-152.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-167.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-1024.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-1024.png new file mode 100755 index 0000000..849689f Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-1024.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-120.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-120.png new file mode 100755 index 0000000..d28f013 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-120.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-121.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-121.png new file mode 100644 index 0000000..d28f013 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-121.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-152.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-152.png new file mode 100755 index 0000000..3db2203 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-152.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-167.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-167.png new file mode 100755 index 0000000..882ac2c Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-167.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-180.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-180.png new file mode 100755 index 0000000..b931737 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-180.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-20.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-20.png new file mode 100755 index 0000000..d398e98 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-20.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-29.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-29.png new file mode 100755 index 0000000..aef0ba7 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-29.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-40.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-40.png new file mode 100755 index 0000000..6abe766 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-40.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-41.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-41.png new file mode 100644 index 0000000..6abe766 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-41.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-42.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-42.png new file mode 100644 index 0000000..6abe766 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-42.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-58.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-58.png new file mode 100755 index 0000000..975ed05 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-58.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-59.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-59.png new file mode 100644 index 0000000..975ed05 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-59.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-60.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-60.png new file mode 100755 index 0000000..6c15f75 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-60.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-76.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100755 index 0000000..3f27dcc Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-80.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-80.png new file mode 100755 index 0000000..b46dd86 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-80.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-81.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-81.png new file mode 100644 index 0000000..b46dd86 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-81.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-87.png b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-87.png new file mode 100755 index 0000000..f0cbee9 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/AppIcon.appiconset/Icon-87.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/Contents.json b/code/iphone/SIGIL-iOS.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/SIGIL-iOS.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-iOS.xcassets/background.imageset/Contents.json b/code/iphone/SIGIL-iOS.xcassets/background.imageset/Contents.json new file mode 100644 index 0000000..5ede46e --- /dev/null +++ b/code/iphone/SIGIL-iOS.xcassets/background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sigil_background.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-iOS.xcassets/background.imageset/sigil_background.png b/code/iphone/SIGIL-iOS.xcassets/background.imageset/sigil_background.png new file mode 100644 index 0000000..f34e054 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/background.imageset/sigil_background.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/logo.imageset/Contents.json b/code/iphone/SIGIL-iOS.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..5464ed1 --- /dev/null +++ b/code/iphone/SIGIL-iOS.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sigillogo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-iOS.xcassets/logo.imageset/sigillogo.png b/code/iphone/SIGIL-iOS.xcassets/logo.imageset/sigillogo.png new file mode 100644 index 0000000..39927a4 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/logo.imageset/sigillogo.png differ diff --git a/code/iphone/SIGIL-iOS.xcassets/sigilsplash.imageset/Contents.json b/code/iphone/SIGIL-iOS.xcassets/sigilsplash.imageset/Contents.json new file mode 100644 index 0000000..65f50b1 --- /dev/null +++ b/code/iphone/SIGIL-iOS.xcassets/sigilsplash.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sigilcover.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-iOS.xcassets/sigilsplash.imageset/sigilcover.jpg b/code/iphone/SIGIL-iOS.xcassets/sigilsplash.imageset/sigilcover.jpg new file mode 100644 index 0000000..8135bd1 Binary files /dev/null and b/code/iphone/SIGIL-iOS.xcassets/sigilsplash.imageset/sigilcover.jpg differ diff --git a/code/iphone/SIGIL-tvOS-Info.plist b/code/iphone/SIGIL-tvOS-Info.plist new file mode 100644 index 0000000..cfd92bf --- /dev/null +++ b/code/iphone/SIGIL-tvOS-Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIAppFonts + + idGinzaNar-Md2.otf + + UIRequiredDeviceCapabilities + + arm64 + + UIUserInterfaceStyle + Automatic + + diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..48ecb4f --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images" : [ + { + "idiom" : "tv" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..01f1415 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "sigil_tvos_icon_back.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/sigil_tvos_icon_back.png b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/sigil_tvos_icon_back.png new file mode 100644 index 0000000..9a151b4 Binary files /dev/null and b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/sigil_tvos_icon_back.png differ diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 0000000..d29f024 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..fa421b9 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "sigil_tvos_icon_middle.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/sigil_tvos_icon_middle.png b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/sigil_tvos_icon_middle.png new file mode 100644 index 0000000..535f5c2 Binary files /dev/null and b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/sigil_tvos_icon_middle.png differ diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Contents.json new file mode 100644 index 0000000..2cdcef1 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Contents.json @@ -0,0 +1,35 @@ +{ + "assets" : [ + { + "size" : "1280x768", + "idiom" : "tv", + "filename" : "App Icon - App Store.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "400x240", + "idiom" : "tv", + "filename" : "App Icon.imagestack", + "role" : "primary-app-icon" + }, + { + "filename" : "LaunchImage.launchimage" + }, + { + "size" : "2320x720", + "idiom" : "tv", + "filename" : "Top Shelf Image Wide.imageset", + "role" : "top-shelf-image-wide" + }, + { + "size" : "1920x720", + "idiom" : "tv", + "filename" : "Top Shelf Image.imageset", + "role" : "top-shelf-image" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..8ef743f --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "orientation" : "landscape", + "idiom" : "tv", + "extent" : "full-screen", + "minimum-system-version" : "11.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "tv", + "filename" : "sigil_tvos_launch.png", + "extent" : "full-screen", + "minimum-system-version" : "9.0", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/sigil_tvos_launch.png b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/sigil_tvos_launch.png new file mode 100644 index 0000000..825d353 Binary files /dev/null and b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/LaunchImage.launchimage/sigil_tvos_launch.png differ diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 0000000..16a370d --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..4d7800e --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,17 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "sigil_banner.png", + "scale" : "1x" + }, + { + "idiom" : "tv", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/sigil_banner.png b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/sigil_banner.png new file mode 100644 index 0000000..b7f75f5 Binary files /dev/null and b/code/iphone/SIGIL-tvOS.xcassets/Brand Assets.brandassets/Top Shelf Image.imageset/sigil_banner.png differ diff --git a/code/iphone/SIGIL-tvOS.xcassets/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/LaunchImage.launchimage/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..95b5982 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,50 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default@2x.png", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "minimum-system-version" : "7.0", + "subtype" : "retina4", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/LaunchImage.launchimage/Default@2x.png b/code/iphone/SIGIL-tvOS.xcassets/LaunchImage.launchimage/Default@2x.png new file mode 100644 index 0000000..879be24 Binary files /dev/null and b/code/iphone/SIGIL-tvOS.xcassets/LaunchImage.launchimage/Default@2x.png differ diff --git a/code/iphone/SIGIL-tvOS.xcassets/background.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/background.imageset/Contents.json new file mode 100644 index 0000000..5ede46e --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/background.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sigil_background.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/background.imageset/sigil_background.png b/code/iphone/SIGIL-tvOS.xcassets/background.imageset/sigil_background.png new file mode 100644 index 0000000..f34e054 Binary files /dev/null and b/code/iphone/SIGIL-tvOS.xcassets/background.imageset/sigil_background.png differ diff --git a/code/iphone/SIGIL-tvOS.xcassets/logo.imageset/Contents.json b/code/iphone/SIGIL-tvOS.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000..5464ed1 --- /dev/null +++ b/code/iphone/SIGIL-tvOS.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "sigillogo.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/code/iphone/SIGIL-tvOS.xcassets/logo.imageset/sigillogo.png b/code/iphone/SIGIL-tvOS.xcassets/logo.imageset/sigillogo.png new file mode 100644 index 0000000..39927a4 Binary files /dev/null and b/code/iphone/SIGIL-tvOS.xcassets/logo.imageset/sigillogo.png differ diff --git a/code/iphone/SIGILLaunchScreen.storyboard b/code/iphone/SIGILLaunchScreen.storyboard new file mode 100644 index 0000000..7307cf4 --- /dev/null +++ b/code/iphone/SIGILLaunchScreen.storyboard @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/SecretMenuView.xib b/code/iphone/SecretMenuView.xib new file mode 100755 index 0000000..19e5903 --- /dev/null +++ b/code/iphone/SecretMenuView.xib @@ -0,0 +1,184 @@ + + + + + + + + + + + + + Helvetica + Helvetica-Bold + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/SecretMenuViewController.h b/code/iphone/SecretMenuViewController.h new file mode 100755 index 0000000..eb08126 --- /dev/null +++ b/code/iphone/SecretMenuViewController.h @@ -0,0 +1,51 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import + +/* + ================================================================================================ + SecretMenuViewController + + ================================================================================================ + */ +@interface Doom_SecretMenuViewController : UIViewController { + + IBOutlet UIScrollView * scrollView; + + IBOutlet UILabel *iwadLabel; + IBOutlet UILabel *pwadLabel; + IBOutlet UIScrollView *pwadScroller; + IBOutlet UIPickerView *levelPicker; + IBOutlet UIPickerView *skillPicker; + + NSArray *skillLevels; + NSArray *doomEpisodes; + NSArray *doomLevels; + NSArray *doom2Levels; +} + +- (IBAction) BackToMain; +- (IBAction)playButtonPressed:(UIButton *)sender; +- (void) updateWadLabels; +- (void) updatePwadList; +- (IBAction)pwadButtonPressed:(id)sender; + +@end diff --git a/code/iphone/SecretMenuViewController.mm b/code/iphone/SecretMenuViewController.mm new file mode 100755 index 0000000..25d0677 --- /dev/null +++ b/code/iphone/SecretMenuViewController.mm @@ -0,0 +1,342 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "SecretMenuViewController.h" +#include "doomiphone.h" +#include "iphone_delegate.h" + +@implementation Doom_SecretMenuViewController + +/* + ======================== + Doom_SecretMenuViewController::initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + + } + return self; +} + +/* + ======================== + Doom_SecretMenuViewController::didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +#pragma mark - View lifecycle + +/* + ======================== + Doom_SecretMenuViewController::viewDidLoad + ======================== + */ +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [self updateWadLabels]; + [self updatePwadList]; + + //maximumSpeed =[[NSArray alloc] initWithObjects:@"Running",@"Crying",@"Boring",@"Working",nil]; + //warningTime = [[NSArray alloc] initWithObjects: @"Happy", @"Sad" , @"Good", @"joyce",nil]; + + + doomEpisodes = [[NSArray alloc] initWithObjects:@"E1", @"E2", @"E3", @"E4",nil ]; + doomLevels = [[NSArray alloc] initWithObjects:@"M1", @"M2", @"M3", @"M4", @"M5", @"M6", @"M7", @"M8", @"M9", nil ]; + + doom2Levels = [[NSArray alloc] initWithObjects: + @"MAP01", + @"MAP02", + @"MAP03", + @"MAP04", + @"MAP05", + @"MAP06", + @"MAP07", + @"MAP08", + @"MAP09", + @"MAP10", + @"MAP11", + @"MAP12", + @"MAP13", + @"MAP14", + @"MAP15", + @"MAP16", + @"MAP17", + @"MAP18", + @"MAP19", + @"MAP20", + @"MAP21", + @"MAP22", + @"MAP23", + @"MAP24", + @"MAP25", + @"MAP26", + @"MAP27", + @"MAP28", + @"MAP29", + @"MAP30", + @"MAP31", + @"MAP32", + nil + ]; + + skillLevels = [[NSArray alloc] initWithObjects: + @"Easy", + @"Medium", + @"Hard", + @"Nightmare!", + nil + ]; + + + + self->skillPicker.dataSource = self; + self->skillPicker.delegate = self; + + self->levelPicker.dataSource = self; + self->levelPicker.delegate = self; + +} + +- (void)updateWadLabels { + iwadLabel.text = [[NSString stringWithUTF8String:doom_iwad] lastPathComponent]; + pwadLabel.text = [[[NSString stringWithUTF8String:doom_pwads] lastPathComponent] stringByReplacingOccurrencesOfString:@":" withString:@""]; + + [levelPicker reloadAllComponents]; + [levelPicker selectRow:0 inComponent:0 animated:NO]; +} + +- (void)updatePwadList { + NSFileManager *filemgr = [NSFileManager defaultManager]; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSArray *dirFiles = [filemgr contentsOfDirectoryAtPath:documentsDirectory error:nil]; + + UIButton *button = NULL; + int y = 5; + for (id dir in dirFiles) { + + NSString *value = (NSString *)dir; + + if ([[value pathExtension] caseInsensitiveCompare:@"wad"]==NSOrderedSame){ + button = [UIButton buttonWithType:UIButtonTypeCustom]; + [button addTarget:self action:@selector(pwadButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; + [button setTitle:value forState:UIControlStateNormal]; + [button.titleLabel setFont:[UIFont fontWithName:@"Helvetica" size:16.0]]; + [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; + [button setTitleColor:[UIColor greenColor] forState:UIControlStateHighlighted]; + [button setTitleColor:[UIColor greenColor] forState:UIControlStateSelected]; + + if( [[NSString stringWithUTF8String:doom_pwads] rangeOfString:dir options:NSCaseInsensitiveSearch].location != NSNotFound) { + [button setSelected:(YES)]; + } + button.frame = CGRectMake(15, y, 175, 22.0); + + [pwadScroller addSubview:button]; + y += 25; + } + } + + if( button ) { + [pwadScroller setContentSize:CGSizeMake( + pwadScroller.bounds.size.width, + CGRectGetMaxY(button.frame) + )]; + } +} + +/* + ======================== + Doom_SecretMenuViewController::BackToMain + ======================== + */ +- (IBAction) BackToMain { + + [self.navigationController popViewControllerAnimated:NO]; + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +} + +- (IBAction)loadDoomIwad:(id)sender { + + iphoneIWADSelect("doom.wad"); + [self updateWadLabels]; + +} + +- (IBAction)loadDoom2Iwad:(id)sender { + + iphoneIWADSelect("doom2.wad"); + [self updateWadLabels]; + +} + +- (IBAction)loadTNTIwad:(id)sender { + + iphoneIWADSelect("tnt.wad"); + [self updateWadLabels]; + +} + +- (IBAction)loadPlutoniaIwad:(id)sender { + + iphoneIWADSelect("plutonia.wad"); + [self updateWadLabels]; + +} + +- (IBAction)xmasPwadOn:(id)sender { + + iphonePWADAdd("spritx.wad"); + [self updateWadLabels]; + +} + +- (IBAction)clearPWADs:(id)sender { + + iphoneClearPWADs(); + + if ([[pwadScroller subviews] count] > 0) { + for( UIView* subview in [pwadScroller subviews]) { + if ([subview isKindOfClass:[UIButton class]]) { + [(UIButton*)subview setSelected:NO]; + } + } + } + [self updateWadLabels]; + +} + +- (IBAction)pwadButtonPressed:(id)sender { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + + if( [(UIButton*)sender isSelected]) { + NSString* full_pwad = [NSString pathWithComponents:[NSArray arrayWithObjects:documentsDirectory,[[(UIButton*)sender titleLabel] text], nil]]; + [(UIButton*)sender setSelected:NO]; + printf("PWAD: %s\n", [full_pwad UTF8String]); + iphonePWADRemove([full_pwad UTF8String]); + } else { + NSString* full_pwad = [NSString pathWithComponents:[NSArray arrayWithObjects:documentsDirectory,[[(UIButton*)sender titleLabel] text], nil]]; + [(UIButton*)sender setSelected:YES]; + printf("PWAD: %s\n", [full_pwad UTF8String]); + iphonePWADAdd([full_pwad UTF8String]); + } + [self updateWadLabels]; +} + +- (IBAction)playButtonPressed:(UIButton *)sender { + + mapStart_t localStartmap; + + if( [levelPicker numberOfComponents] == 2) { + localStartmap.episode = (int) ([levelPicker selectedRowInComponent:0] + 1); + localStartmap.map = (int) ([levelPicker selectedRowInComponent:1] + 1); + } else { + localStartmap.episode = 1; + localStartmap.map = (int) ([levelPicker selectedRowInComponent:0] + 1); + } + + localStartmap.dataset = 0; + localStartmap.skill = (int) [skillPicker selectedRowInComponent:0]; + + // load our selected IWAD and PWADs + iphoneDoomStartup(); + StartSinglePlayerGame( localStartmap ); + + [ gAppDelegate ShowGLView ]; + +} + + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView +{ + + if( pickerView == levelPicker && [ iwadLabel.text caseInsensitiveCompare:@"doom.wad"] == NSOrderedSame ) { + return 2; // episode, map + } + + return 1; +} + +// The number of rows of data +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component +{ + + if( pickerView == levelPicker ) { + if( [ iwadLabel.text caseInsensitiveCompare:@"doom.wad"] == NSOrderedSame ) { + if( component == 0 ) { + return (NSInteger) doomEpisodes.count; + } else if( component == 1 ) { + return (NSInteger) doomLevels.count; + } + } else { + return (NSInteger) doom2Levels.count; + } + } + + if( pickerView == skillPicker ) { + return (NSInteger) skillLevels.count; + } + + return 1; +} + +// The data to return for the row and component (column) that's being passed in +- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component +{ + if( pickerView == levelPicker ) { + if( [ iwadLabel.text caseInsensitiveCompare:@"doom.wad"] == NSOrderedSame ) { + if( component == 0 ) { + return doomEpisodes[ (NSUInteger) row]; + } else if( component == 1 ) { + return doomLevels[ (NSUInteger) row]; + } + } else { + return doom2Levels[ (NSUInteger) row]; + } + } + + if( pickerView == skillPicker ) { + return skillLevels[ (NSUInteger) row]; + } + + return nil; +} + + +- (void)dealloc { + [pwadLabel release]; + [iwadLabel release]; + [levelPicker release]; + [skillPicker release]; + [super dealloc]; +} +@end diff --git a/code/iphone/SettingsMenuView-tvos.xib b/code/iphone/SettingsMenuView-tvos.xib new file mode 100755 index 0000000..2975061 --- /dev/null +++ b/code/iphone/SettingsMenuView-tvos.xib @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/SettingsMenuView.h b/code/iphone/SettingsMenuView.h deleted file mode 100644 index eb0d44d..0000000 --- a/code/iphone/SettingsMenuView.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -#import -#import -#import "UICustomSwitch.h" - -@interface SettingsMenuView : UIImageView { - - IBOutlet UICustomSwitch * autoUseSwitch; - IBOutlet UICustomSwitch * statusbarSwitch; - IBOutlet UICustomSwitch * touchclickSwitch; - IBOutlet UICustomSwitch * textMessageSwitch; - IBOutlet UICustomSwitch * drawControlsSwitch; - IBOutlet UICustomSwitch * musicSwitch; - IBOutlet UICustomSwitch * centerSticksSwitch; - IBOutlet UICustomSwitch * rampTurnSwitch; - - - -} - -- (void) resetSwitches; - -- (IBAction) BackToMain; -- (IBAction) ResetToDefaults; -- (IBAction) AutoUseChanged; -- (IBAction) StatusBarChanged; -- (IBAction) TouchClickChanged; -- (IBAction) TextMessagesChanged; -- (IBAction) DrawControlsChanged; -- (IBAction) MusicChanged; -- (IBAction) CenterSticksChanged; -- (IBAction) RampTurnChanged; - -@end diff --git a/code/iphone/SettingsMenuView.m b/code/iphone/SettingsMenuView.m deleted file mode 100644 index 00ce922..0000000 --- a/code/iphone/SettingsMenuView.m +++ /dev/null @@ -1,122 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import "SettingsMenuView.h" -#import "doomAppDelegate.h" -#include "doomiphone.h" - -@implementation SettingsMenuView - -- (void) resetSwitches { - [ autoUseSwitch setOn: (BOOL)autoUse->value ]; - [ statusbarSwitch setOn: (BOOL)statusBar->value ]; - [ touchclickSwitch setOn: (BOOL)touchClick->value ]; - [ textMessageSwitch setOn: (BOOL)messages->value ]; - [ drawControlsSwitch setOn: (BOOL)drawControls->value ]; - [ musicSwitch setOn: (BOOL)music->value ]; - [ centerSticksSwitch setOn: (BOOL)centerSticks->value ]; - [ rampTurnSwitch setOn: (BOOL)rampTurn->value ]; -} - - - - - -- (void) initialize{ - - - -} - -- (void)awakeFromNib { - - [self initialize]; - -} - -- (id) initWithCoder:(NSCoder *)aCoder{ - - if(self = [super initWithCoder:aCoder] ) { - [self initialize]; - } - - return self; -} - -- (id) initWithFrame:(CGRect)rect{ - if(self = [super initWithFrame:rect] ) { - [self initialize]; - } - return self; -} - - -- (IBAction) BackToMain { - [gAppDelegate MainMenu]; - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); -} - -- (IBAction) ResetToDefaults { - - // reset all cvars except the reverse-landscape mode value - float value = revLand->value; - Cvar_Reset_f(); - Cvar_SetValue( revLand->name, value ); - HudSetForScheme(0); - iphoneStartMusic(); - - Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); - - [self resetSwitches]; -} - -- (IBAction) AutoUseChanged { - Cvar_SetValue( autoUse->name, !autoUse->value ); -} - -- (IBAction) StatusBarChanged { - Cvar_SetValue( statusBar->name, !statusBar->value ); -} - -- (IBAction) TouchClickChanged { - Cvar_SetValue( touchClick->name, !touchClick->value ); -} - -- (IBAction) TextMessagesChanged { - Cvar_SetValue( messages->name, !messages->value ); -} - -- (IBAction) DrawControlsChanged { - Cvar_SetValue( drawControls->name, !drawControls->value ); -} - -- (IBAction) MusicChanged { - if ( !SysIPhoneOtherAudioIsPlaying() ) { - Cvar_SetValue( music->name, !music->value ); - if ( music->value ) { - iphoneStartMusic(); - } else { - iphoneStopMusic(); - } - } - -} - -- (IBAction) CenterSticksChanged { - Cvar_SetValue( centerSticks->name, !centerSticks->value ); -} - -- (IBAction) RampTurnChanged { - Cvar_SetValue( rampTurn->name, !rampTurn->value ); -} - -@end diff --git a/code/iphone/SettingsMenuView.xib b/code/iphone/SettingsMenuView.xib new file mode 100755 index 0000000..fc0932a --- /dev/null +++ b/code/iphone/SettingsMenuView.xib @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/SettingsMenuViewController.h b/code/iphone/SettingsMenuViewController.h new file mode 100755 index 0000000..33079e8 --- /dev/null +++ b/code/iphone/SettingsMenuViewController.h @@ -0,0 +1,68 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import +#import "../ios/Switch.h" +#import "../ios/LabelButton.h" + +/* + ================================================================================================ + Doom_SettingsMenuViewController + + ================================================================================================ + */ +@interface Doom_SettingsMenuViewController : UIViewController { + + + IBOutlet idSwitch * autoUseSwitch; + IBOutlet idSwitch * statusbarSwitch; + IBOutlet idSwitch * touchclickSwitch; + IBOutlet idSwitch * textMessageSwitch; + IBOutlet idSwitch * drawControlsSwitch; + IBOutlet idSwitch * musicSwitch; + IBOutlet idSwitch * centerSticksSwitch; + IBOutlet idSwitch * rampTurnSwitch; + IBOutlet idLabelButton * resetButton; + + IBOutlet UIImageView * autoUseSelection; + IBOutlet UIImageView * statusbarSelection; + IBOutlet UIImageView * touchclickSelection; + IBOutlet UIImageView * textMessageSelection; + IBOutlet UIImageView * drawControlsSelection; + IBOutlet UIImageView * musicSelection; + IBOutlet UIImageView * centerSticksSelection; + IBOutlet UIImageView * rampTurnSelection; + IBOutlet UIImageView * resetSelection; + + +} + +- (IBAction) BackToMain; +- (IBAction) ResetToDefaults; +- (IBAction) AutoUseChanged; +- (IBAction) StatusBarChanged; +- (IBAction) TouchClickChanged; +- (IBAction) TextMessagesChanged; +- (IBAction) DrawControlsChanged; +- (IBAction) MusicChanged; +- (IBAction) CenterSticksChanged; +- (IBAction) RampTurnChanged; + +@end diff --git a/code/iphone/SettingsMenuViewController.mm b/code/iphone/SettingsMenuViewController.mm new file mode 100755 index 0000000..fc32135 --- /dev/null +++ b/code/iphone/SettingsMenuViewController.mm @@ -0,0 +1,289 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ +#import "SettingsMenuViewController.h" +#include "doomiphone.h" +#include "iphone_delegate.h" + +/* + ================================================================================================ + Doom_SettingsMenuViewController + + ================================================================================================ + */ +@implementation Doom_SettingsMenuViewController + +UIFocusGuide *focusGuide; + +/* + ======================== + Doom_SettingsMenuViewController::initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // Custom initialization + } + return self; +} + +/* + ======================== + Doom_SettingsMenuViewController::didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning +{ + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +#pragma mark - View lifecycle + +/* + ======================== + Doom_SettingsMenuViewController::viewDidLoad + ======================== + */ +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [self setValues]; + +#if TARGET_OS_TV + focusGuide = [[UIFocusGuide alloc] init]; + [self.view addLayoutGuide:focusGuide]; + + [focusGuide.widthAnchor constraintEqualToAnchor:textMessageSwitch.widthAnchor].active = YES; + [focusGuide.heightAnchor constraintEqualToAnchor:resetButton.heightAnchor].active = YES; + [focusGuide.topAnchor constraintEqualToAnchor:resetButton.topAnchor].active = YES; + focusGuide.preferredFocusEnvironments = @[resetButton]; + +#endif +} + +/* + ======================== + Doom_SettingsMenuViewController::BackToMain + ======================== + */ +- (IBAction) BackToMain { + [self.navigationController popViewControllerAnimated:NO]; + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); +} + +- (void)setValues { + [ autoUseSwitch setOn: (BOOL)autoUse->value ]; + [ statusbarSwitch setOn: (BOOL)statusBar->value ]; + [ touchclickSwitch setOn: (BOOL)touchClick->value ]; + [ textMessageSwitch setOn: (BOOL)messages->value ]; + [ drawControlsSwitch setOn: (BOOL)drawControls->value ]; + [ musicSwitch setOn: (BOOL)music->value ]; + [ centerSticksSwitch setOn: (BOOL)centerSticks->value ]; + [ rampTurnSwitch setOn: (BOOL)rampTurn->value ]; + +#if TARGET_OS_TV + // This may be a bad way to do it but it lets me leave them as idSwitches instead of changing the type + [ autoUseSwitch setImage:(BOOL)autoUse->value ? [UIImage imageNamed:@"SettingsButton_Highlighted"] : [UIImage imageNamed:@"SettingsButton"] forState:UIControlStateFocused]; + [ statusbarSwitch setImage:(BOOL)statusBar->value ? [UIImage imageNamed:@"SettingsButton_Highlighted"] : [UIImage imageNamed:@"SettingsButton"] forState:UIControlStateFocused]; + [ touchclickSwitch setImage:(BOOL)touchClick->value ? [UIImage imageNamed:@"SettingsButton_Highlighted"] : [UIImage imageNamed:@"SettingsButton"] forState:UIControlStateFocused]; + [ textMessageSwitch setImage:(BOOL)messages->value ? [UIImage imageNamed:@"SettingsButton_Highlighted"] : [UIImage imageNamed:@"SettingsButton"] forState:UIControlStateFocused]; + [ drawControlsSwitch setImage:(BOOL)drawControls->value ? [UIImage imageNamed:@"SettingsButton_Highlighted"] : [UIImage imageNamed:@"SettingsButton"] forState:UIControlStateFocused]; + [ musicSwitch setImage:(BOOL)music->value ? [UIImage imageNamed:@"SettingsButton_Highlighted"] : [UIImage imageNamed:@"SettingsButton"] forState:UIControlStateFocused]; + [ centerSticksSwitch setImage:(BOOL)centerSticks->value ? [UIImage imageNamed:@"SettingsButton_Highlighted"] : [UIImage imageNamed:@"SettingsButton"] forState:UIControlStateFocused]; + [ rampTurnSwitch setImage:(BOOL)rampTurn->value ? [UIImage imageNamed:@"SettingsButton_Highlighted"] : [UIImage imageNamed:@"SettingsButton"] forState:UIControlStateFocused]; + +#endif +} + +/* + ======================== + Doom_SettingsMenuViewController::ResetToDefaults + ======================== + */ +- (IBAction) ResetToDefaults { + + // reset all cvars + Cvar_Reset_f(); + HudSetForScheme(0); + iphoneStartMusic(); + + mus_on = true; + mus_pause_opt = 1; + S_ResumeSound(); + + Sound_StartLocalSound( "iphone/controller_down_01_SILENCE.wav" ); + + [self setValues]; +} + +/* + ======================== + Doom_SettingsMenuViewController::AutoUseChanged + ======================== + */ +- (IBAction) AutoUseChanged { + Cvar_SetValue( autoUse->name, !autoUse->value ); +// NSLog(@"DOOM: AutoUseChanged: %f", autoUse->value); + [self setValues]; +} + +/* + ======================== + Doom_SettingsMenuViewController::StatusBarChanged + ======================== + */ +- (IBAction) StatusBarChanged { + Cvar_SetValue( statusBar->name, !statusBar->value ); +// NSLog(@"DOOM: StatusBarChanged: %f", statusBar->value); + [self setValues]; +} + +/* + ======================== + Doom_SettingsMenuViewController::TouchClickChanged + ======================== + */ +- (IBAction) TouchClickChanged { + Cvar_SetValue( touchClick->name, !touchClick->value ); +// NSLog(@"DOOM: TouchClickChanged: %f", touchClick->value); + [self setValues]; +} + +/* + ======================== + Doom_SettingsMenuViewController::TextMessagesChanged + ======================== + */ +- (IBAction) TextMessagesChanged { + Cvar_SetValue( messages->name, !messages->value ); +// NSLog(@"DOOM: TextMessagesChanged: %f", messages->value); + [self setValues]; +} + +/* + ======================== + Doom_SettingsMenuViewController::DrawControlsChanged + ======================== + */ +- (IBAction) DrawControlsChanged { + Cvar_SetValue( drawControls->name, !drawControls->value ); +// NSLog(@"DOOM: DrawControlsChanged: %f", drawControls->value); + [self setValues]; +} +extern int mus_pause_opt; // From m_misc.c +extern bool mus_on; + +/* + ======================== + Doom_SettingsMenuViewController::MusicChanged + ======================== + */ +- (IBAction) MusicChanged { + if ( !SysIPhoneOtherAudioIsPlaying() ) { + Cvar_SetValue( music->name, !music->value ); +// NSLog(@"DOOM: MusicChanged: %f", music->value); + [self setValues]; + if ( music->value ) { + mus_on = true; + mus_pause_opt = 1; + S_ResumeSound(); + } else { + mus_on = false; + mus_pause_opt = 1; + S_PauseSound(); + } + } + +} + +/* + ======================== + Doom_SettingsMenuViewController::CenterSticksChanged + ======================== + */ +- (IBAction) CenterSticksChanged { + Cvar_SetValue( centerSticks->name, !centerSticks->value ); +// NSLog(@"DOOM: CenterSticksChanged: %f", centerSticks->value); + [self setValues]; +} + +/* + ======================== + Doom_SettingsMenuViewController::RampTurnChanged + ======================== + */ +- (IBAction) RampTurnChanged { + Cvar_SetValue( rampTurn->name, !rampTurn->value ); +// NSLog(@"DOOM: RampTurnChanged: %f", rampTurn->value); + [self setValues]; +} + +#if TARGET_OS_TV + +- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator { + NSLog(@"DOOM: %@", context.nextFocusedView); + NSLog(@"DOOM: %@", context.previouslyFocusedView); + + [super didUpdateFocusInContext:context withAnimationCoordinator:coordinator]; + + if ([context.nextFocusedView isKindOfClass:[idSwitch class]]) { + + if (context.nextFocusedView.tag > 0) { + + autoUseSelection.hidden = YES; + statusbarSelection.hidden = YES; + touchclickSelection.hidden = YES; + textMessageSelection.hidden = YES; + drawControlsSelection.hidden = YES; + musicSelection.hidden = YES; + centerSticksSelection.hidden = YES; + rampTurnSelection.hidden = YES; + + if (context.nextFocusedView.tag == 1) { + autoUseSelection.hidden = NO; + } else if (context.nextFocusedView.tag == 2) { + statusbarSelection.hidden = NO; + } else if (context.nextFocusedView.tag == 3) { + touchclickSelection.hidden = NO; + } else if (context.nextFocusedView.tag == 4) { + textMessageSelection.hidden = NO; + } else if (context.nextFocusedView.tag == 5) { + drawControlsSelection.hidden = NO; + } else if (context.nextFocusedView.tag == 6) { + musicSelection.hidden = NO; + } else if (context.nextFocusedView.tag == 7) { + centerSticksSelection.hidden = NO; + } else if (context.nextFocusedView.tag == 8) { + rampTurnSelection.hidden = NO; + } + } + + [self setValues]; + } +} + +#endif + +@end diff --git a/code/iphone/SettingsMenuView~ipad.xib b/code/iphone/SettingsMenuView~ipad.xib new file mode 100755 index 0000000..75c8f45 --- /dev/null +++ b/code/iphone/SettingsMenuView~ipad.xib @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/iphone/SoundEngine.cpp b/code/iphone/SoundEngine.cpp old mode 100644 new mode 100755 index ec2b8ea..0c7c95e --- a/code/iphone/SoundEngine.cpp +++ b/code/iphone/SoundEngine.cpp @@ -343,7 +343,7 @@ void CalculateBytesForTime (AudioStreamBasicDescription & inDesc, UInt32 inMaxPa if (inDesc.mFramesPerPacket) { Float64 numPacketsForTime = inDesc.mSampleRate / inDesc.mFramesPerPacket * inSeconds; - *outBufferSize = (long unsigned int)numPacketsForTime * inMaxPacketSize; + *outBufferSize = (UInt32)(numPacketsForTime * inMaxPacketSize); } else { // if frames per packet is zero, then the codec has no predictable packet == time // so we can't tailor this (we don't know how many Packets represent a time period @@ -638,15 +638,14 @@ void BackgroundTrackMgr::QueueCallback( void * inUserData, AudioQueueRef inAQ, A if ((CurFileInfo->mFileDataInQueue) && (THIS->mBGFileInfo.size() == 1) && (!THIS->mStopAtEnd)) { nPackets = THIS->GetNumPacketsToRead(CurFileInfo); } else { - UInt32 numBytes; + UInt32 numBytes = 0; while (nPackets == 0) { // if loadAtOnce, get all packets in the file, otherwise ~.5 seconds of data nPackets = THIS->GetNumPacketsToRead(CurFileInfo); - result = AudioFileReadPackets(CurFileInfo->mAFID, false, &numBytes, THIS->mPacketDescs, THIS->mCurrentPacket, &nPackets, - inCompleteAQBuffer->mAudioData); + //FIXME: JadingTsunami (fix) result = AudioFileReadPackets(CurFileInfo->mAFID, false, &numBytes, THIS->mPacketDescs, THIS->mCurrentPacket, &nPackets, inCompleteAQBuffer->mAudioData); AssertNoError("Error reading file data", end); - inCompleteAQBuffer->mAudioDataByteSize = numBytes; + inCompleteAQBuffer->mAudioDataByteSize = numBytes; if (nPackets == 0) { // no packets were read, this file has ended. if (CurFileInfo->mLoadAtOnce) { @@ -724,6 +723,8 @@ void BackgroundTrackMgr::QueueCallback( void * inUserData, AudioQueueRef inAQ, A OSStatus BackgroundTrackMgr::SetupQueue(BG_FileInfo *inFileInfo) { UInt32 size = 0; OSStatus result = AudioQueueNewOutput(&inFileInfo->mFileFormat, QueueCallback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &mQueue); + OSStatus err = noErr; + AssertNoError("Error creating queue", end); // (2) If the file has a cookie, we should get it and set it on the AQ @@ -740,7 +741,7 @@ OSStatus BackgroundTrackMgr::SetupQueue(BG_FileInfo *inFileInfo) { } // channel layout - OSStatus err = AudioFileGetPropertyInfo(inFileInfo->mAFID, kAudioFilePropertyChannelLayout, &size, NULL); + err = AudioFileGetPropertyInfo(inFileInfo->mAFID, kAudioFilePropertyChannelLayout, &size, NULL); if (err == noErr && size > 0) { AudioChannelLayout *acl = (AudioChannelLayout *)malloc(size); result = AudioFileGetProperty(inFileInfo->mAFID, kAudioFilePropertyChannelLayout, &size, acl); @@ -768,6 +769,8 @@ OSStatus BackgroundTrackMgr::SetupBuffers(BG_FileInfo *inFileInfo) { int numBuffersToQueue = kNumberBuffers; UInt32 maxPacketSize; UInt32 size = sizeof(maxPacketSize); + bool isFormatVBR = false; + // we need to calculate how many packets we read at a time, and how big a buffer we need // we base this on the size of the packets in the file and an approximate duration for each buffer @@ -775,7 +778,7 @@ OSStatus BackgroundTrackMgr::SetupBuffers(BG_FileInfo *inFileInfo) { // than our allocation default size, that needs to become larger OSStatus result = AudioFileGetProperty(inFileInfo->mAFID, kAudioFilePropertyPacketSizeUpperBound, &size, &maxPacketSize); AssertNoError("Error getting packet upper bound size", end); - bool isFormatVBR = (inFileInfo->mFileFormat.mBytesPerPacket == 0 || inFileInfo->mFileFormat.mFramesPerPacket == 0); + isFormatVBR = (inFileInfo->mFileFormat.mBytesPerPacket == 0 || inFileInfo->mFileFormat.mFramesPerPacket == 0); CalculateBytesForTime(inFileInfo->mFileFormat, maxPacketSize, 0.5/*seconds*/, &mBufferByteSize, &mNumPacketsToRead); @@ -1240,7 +1243,7 @@ class SoundEngineEffectMap iterator GetIterator() { return begin(); } - UInt32 Size () const { return size(); } + UInt32 Size () const { return (UInt32)(size()); } bool Empty () const { return empty(); } }; @@ -1459,8 +1462,12 @@ class OpenALObject extern "C" -static void interruptionCallback(void* arg, UInt32 interruptionState) +void interruptionCallback(void* arg, UInt32 interruptionState) { +#if !TARGET_OS_TV + + (void)arg; + printf("Excuse this interruption...\n"); switch(interruptionState) { @@ -1476,6 +1483,7 @@ static void interruptionCallback(void* arg, UInt32 interruptionState) // gInterrupted = false; // break; } +#endif } @@ -1500,14 +1508,18 @@ OSStatus SoundEngine_Initialize(Float32 inMixerOutputRate) if(gInterrupted) return noErr; - if( !isInitialized ) +#if !TARGET_OS_TV + if( !isInitialized ) { - AudioSessionInitialize( NULL, NULL, interruptionCallback, NULL ); + printf("WARNING! Sound engine was not initialized!\n"); + //FIXME: JadingTsunami (fix) AudioSessionInitialize( NULL, NULL, interruptionCallback, NULL ); // UInt32 sessionCategory = kAudioSessionCategory_AmbientSound; // AudioSessionSetProperty( kAudioSessionProperty_AudioCategory, sizeof( sessionCategory ), &sessionCategory ); isInitialized = true; } - +#else + (void)isInitialized; +#endif if (sOpenALObject) delete sOpenALObject; diff --git a/code/iphone/UICustomSlider.h b/code/iphone/UICustomSlider.h deleted file mode 100644 index 82fbd36..0000000 --- a/code/iphone/UICustomSlider.h +++ /dev/null @@ -1,18 +0,0 @@ -/* -======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - -======================================================================================= - */ - -#import - - -@interface UICustomSlider : UISlider { - -} - -@end diff --git a/code/iphone/UICustomSlider.m b/code/iphone/UICustomSlider.m deleted file mode 100644 index 530443d..0000000 --- a/code/iphone/UICustomSlider.m +++ /dev/null @@ -1,25 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - -#import "UICustomSlider.h" - - -@implementation UICustomSlider - -- (CGRect)trackRectForBounds:(CGRect)bounds { - - UIImage* trackImage = [self minimumTrackImageForState:UIControlStateNormal]; - - CGFloat trackImageHeight = trackImage.size.height; - - return CGRectMake(bounds.origin.x, bounds.origin.y, self.bounds.size.width, trackImageHeight); -} - -@end diff --git a/code/iphone/UICustomSwitch.h b/code/iphone/UICustomSwitch.h deleted file mode 100644 index bca6878..0000000 --- a/code/iphone/UICustomSwitch.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -#import - - -@interface UICustomSwitch : UIButton { - BOOL on; -} - -@property(nonatomic,getter=isOn) BOOL on; - -@end diff --git a/code/iphone/UICustomSwitch.m b/code/iphone/UICustomSwitch.m deleted file mode 100644 index 2b4577a..0000000 --- a/code/iphone/UICustomSwitch.m +++ /dev/null @@ -1,56 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import "UICustomSwitch.h" - - -@implementation UICustomSwitch - -@synthesize on; - -- (void)setOn:(BOOL)turnOn; -{ - on = turnOn; - - if (on) - { - [ self setHighlighted: YES ]; - } - else - { - [ self setHighlighted: NO ]; - } -} - - -- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event -{ - [super touchesBegan:touches withEvent:event]; - [self setOn: !on ]; - -} - -- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event -{ - [super touchesEnded:touches withEvent:event]; - - if (on) - { - [ self setHighlighted: YES ]; - } - else - { - [ self setHighlighted: NO ]; - } -} - - -@end diff --git a/code/iphone/UIFontButton.h b/code/iphone/UIFontButton.h deleted file mode 100644 index 58b260b..0000000 --- a/code/iphone/UIFontButton.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import -#import -#import "UIFontLabel.h" - -@interface UIFontButton : UIButton { -@public - - IBOutlet UIFontLabel * label; - IBOutlet UIFontLabel * label2; - - UIColor * labelColor; - UIColor * label2Color; -} - -@property (nonatomic, retain) IBOutlet UIFontLabel *label; -@property (nonatomic, retain) IBOutlet UIFontLabel *label2; - -- (void) Hide; -- (void) Show; -- (void) Enable; -- (void) Disable; -@end diff --git a/code/iphone/UIFontButton.m b/code/iphone/UIFontButton.m deleted file mode 100644 index dd8e912..0000000 --- a/code/iphone/UIFontButton.m +++ /dev/null @@ -1,118 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import "UIFontButton.h" - - -@implementation UIFontButton - -@synthesize label; -@synthesize label2; - -- (void)awakeFromNib { - CGFloat points = self.titleLabel.font.pointSize; - - self.titleLabel.font = [UIFont fontWithName:@"idGinza Narrow" size:points]; - - if( self.label2 ) - label2Color = self.label2.textColor; - if( self.label ) - labelColor = self.label.textColor; -} - -- (void)setHighlighted:(BOOL)highlight { - if( highlight ) { - if( self.label ) - self.label.textColor = self.label.highlightedTextColor; - if( self.label2 ) - self.label2.textColor = self.label2.highlightedTextColor; - } else if( self.enabled ) { - if( self.label ) - self.label.textColor = labelColor; - if( self.label2 ) - self.label2.textColor = label2Color; - } - - [super setHighlighted:highlight]; -} - -- (void)setEnabled:(BOOL)enabled { - if( !enabled ) { - if( self.label ) - self.label.textColor = self.label.highlightedTextColor; - if( self.label2 ) - self.label2.textColor = self.label2.highlightedTextColor; - } else { - if( self.label ) - self.label.textColor = labelColor; - if( self.label2 ) - self.label2.textColor = label2Color; - } - - [super setEnabled:enabled]; -} - -- (void) Enable { - - self.enabled = YES; - if( self.label ) - label.enabled = YES; - if( self.label2 ) - label2.enabled = YES; -} - -- (void) Disable { - self.enabled = NO; - if( self.label ) - label.enabled = NO; - if( self.label2 ) - label2.enabled = NO; -} - -- (void) Hide { - - [UIView beginAnimations:@"Hide" context:nil]; - [UIView setAnimationDuration:1.0f]; - [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; - [UIView setAnimationBeginsFromCurrentState:YES]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(Disable)]; - - self.alpha = 0.0f; - if( self.label ) - label.alpha = 0.0f; - if( self.label2 ) - label2.alpha = 0.0f; - - [UIView commitAnimations]; - - -} - -- (void) Show { - - [UIView beginAnimations:@"Show" context:nil]; - [UIView setAnimationDuration:1.0f]; - [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut]; - [UIView setAnimationBeginsFromCurrentState:YES]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(Enable)]; - - self.alpha = 1.0f; - if( self.label ) - label.alpha = 1.0f; - if( self.label2 ) - label2.alpha = 1.0f; - - [UIView commitAnimations]; -} - -@end diff --git a/code/iphone/UIFontLabel.h b/code/iphone/UIFontLabel.h deleted file mode 100644 index f6c14fd..0000000 --- a/code/iphone/UIFontLabel.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - -#import - - -@interface UIFontLabel : UILabel { - -} - -@end diff --git a/code/iphone/UIFontLabel.m b/code/iphone/UIFontLabel.m deleted file mode 100644 index ee2bf77..0000000 --- a/code/iphone/UIFontLabel.m +++ /dev/null @@ -1,27 +0,0 @@ -/* - ======================================================================================= - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. All Right Reserved. - - This file is part of the DOOM Classic iOS v2.1 GPL Source Code. - - ======================================================================================= - */ - - - -#import "UIFontLabel.h" - - -@implementation UIFontLabel - -- (void)awakeFromNib { - CGFloat points = self.font.pointSize; - - self.font = [UIFont fontWithName:@"idGinza Narrow" size:points]; -} - -@end - - - diff --git a/code/iphone/arialGlyphRects.h b/code/iphone/arialGlyphRects.h old mode 100644 new mode 100755 diff --git a/code/iphone/cmd.c b/code/iphone/cmd.c old mode 100644 new mode 100755 index feafc92..0f82b38 --- a/code/iphone/cmd.c +++ b/code/iphone/cmd.c @@ -1,7 +1,12 @@ /* - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. - + * cmd.c + * doom + * + * Created by John Carmack on 4/14/09. + * Copyright 2009 id Software. All rights reserved. + * + */ +/* 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 @@ -19,7 +24,7 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" typedef struct cmd_function_s { struct cmd_function_s *next; @@ -113,7 +118,7 @@ void Cmd_AddCommand( const char *cmd_name, xcommand_t function ) { } void Cmd_ExecuteString( const char *str ) { - int l = strlen( str ); + int l = (int) strlen( str ); if ( str[l-1] == '\n' ) { char *stripped = alloca( l+1 ); strcpy( stripped, str ); diff --git a/code/iphone/cvar.c b/code/iphone/cvar.c old mode 100644 new mode 100755 index 5054cf2..3b0f1c6 --- a/code/iphone/cvar.c +++ b/code/iphone/cvar.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2004 Michael Liebscher Copyright (C) 1997-2001 Id Software, Inc. @@ -19,7 +19,7 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" cvar_t *cvar_vars; diff --git a/code/iphone/cvar.h b/code/iphone/cvar.h old mode 100644 new mode 100755 index 220224b..94d784e --- a/code/iphone/cvar.h +++ b/code/iphone/cvar.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2004 Michael Liebscher Copyright (C) 1997-2001 Id Software, Inc. @@ -56,6 +56,10 @@ #ifndef __CVAR_H__ #define __CVAR_H__ +#ifdef __cplusplus +extern "C" { +#endif + typedef enum _CVARFlags { CVAR_INIT = 0x0, // Just create it with no flag value. @@ -84,8 +88,8 @@ typedef struct cvar_s { extern cvar_t *cvar_vars; -void Cvar_List_f(); -void Cvar_Reset_f(); + void Cvar_List_f(void); + void Cvar_Reset_f(void); extern cvar_t *Cvar_Get( const char *var_name, const char *value, CVARFlags flags ); // creates the variable if it doesn't exist, or returns the existing one @@ -126,5 +130,10 @@ extern char *Cvar_Userinfo( void ); extern char *Cvar_Serverinfo( void ); // returns an info string containing all the CVAR_SERVERINFO cvars +#ifdef __cplusplus +} +#endif + + #endif /* __CVAR_H__ */ diff --git a/code/iphone/doomAppDelegate.h b/code/iphone/doomAppDelegate.h deleted file mode 100644 index 4a21d5a..0000000 --- a/code/iphone/doomAppDelegate.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. - Copyright (C) 2009 Id Software, Inc. - - 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. - - */ - -#import -#import -#import "MenuViewController.h" - -@class EAGLView; - -@interface gameAppDelegate : NSObject { - UIWindow *window; - EAGLView *glView; - CADisplayLink * displayLink; - - int lastAccelUpdateMsec; - - - IBOutlet MenuViewController * mainMenuViewController; - IBOutlet MenuViewController * mapMenuViewController; - IBOutlet MenuViewController * creditsMenuViewController; - IBOutlet MenuViewController * legalMenuViewController; - IBOutlet MenuViewController * settingsMenuViewController; - IBOutlet MenuViewController * controlsMenuViewController; - IBOutlet MenuViewController * episodeMenuViewController; - - BOOL IBMenuVisible; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet EAGLView *glView; -@property (nonatomic, retain) IBOutlet CADisplayLink *displayLink; - -- (void)restartAccelerometerIfNeeded; - -- (void) SelectEpisode: (int) episode; -- (void) PrepareForViewSwap; -- (void) ResumeGame; -- (void) NewGame; -- (void) DemoGame; -- (void) MainMenu; -- (void) CreditsMenu; -- (void) LegalMenu; -- (void) playMap: (int) dataset: (int) episode: (int) map: (int) skill; -- (void) GotoSupport; -- (void) idSoftwareApps; -- (void) SettingsMenu; -- (void) ControlsMenu; -- (void) HUDLayout; -- (void) HideIB; - -extern gameAppDelegate * gAppDelegate; - -@end - diff --git a/code/iphone/doomAppDelegate.m b/code/iphone/doomAppDelegate.m deleted file mode 100644 index fa52e1d..0000000 --- a/code/iphone/doomAppDelegate.m +++ /dev/null @@ -1,429 +0,0 @@ -/* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. - Copyright (C) 2009 Id Software, Inc. - - 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. - - */ - -#import "doomAppDelegate.h" -#import "EAGLView.h" -#import -#include "../doomiphone.h" -#import -#import "SettingsMenuView.h" -#import "ControlsMenuView.h" -#include "IBGlue.h" -#import "MapMenuView.h" - -@interface UIApplication (Private) - -- (void)setSystemVolumeHUDEnabled:(BOOL)enabled forAudioCategory:(NSString *)category; -- (void)setSystemVolumeHUDEnabled:(BOOL)enabled; - -- (void)runFrame; -- (void)asyncTic; - -@end - - -char iphoneDocDirectory[1024]; -char iphoneAppDirectory[1024]; - - -@implementation gameAppDelegate - -@synthesize window; -@synthesize glView; -@synthesize displayLink; - -extern EAGLContext *context; - -gameAppDelegate * gAppDelegate = NULL; - -NSTimer *animationTimer; -bool inBackgroundProcess = false; - -touch_t sysTouches[MAX_TOUCHES]; -touch_t gameTouches[MAX_TOUCHES]; -pthread_mutex_t eventMutex; // used to sync between game and event threads -bool firstRun = true; - -pthread_t gameThreadHandle; -volatile boolean startupCompleted; -void *GameThread( void *args ) { - if ( ![EAGLContext setCurrentContext:context]) { - printf( "Couldn't setCurrentContext for game thread\n" ); - exit( 1 ); - } - - while( inBackgroundProcess ) { - usleep( 1000 ); - } - - printf( "original game thread priority: %f\n", (float)[NSThread threadPriority] ); - [NSThread setThreadPriority: 0.5]; - printf( "new game thread priority: %f\n", (float)[NSThread threadPriority] ); - - iphoneStartup(); - - // make sure one frame has been run before setting - // startupCompleted, so we don't get one grey frame - iphoneFrame(); - - startupCompleted = TRUE; // OK to start touch / accel callbacks - while( 1 ) { - - // we are in the background.. dont do anything. - if( inBackgroundProcess ) { - usleep( 1000 ); - } - iphoneFrame(); - } -} - -- (void)asyncTic { - iphoneAsyncTic(); - [ self restartAccelerometerIfNeeded]; -} - -- (void)runFrame { - iphoneAsyncTic(); - iphoneFrame(); -} - -- (void)applicationDidFinishLaunching:(UIApplication *)application { - inBackgroundProcess = false; - application.statusBarHidden = YES; - application.statusBarOrientation = UIInterfaceOrientationLandscapeLeft; - gAppDelegate = self; - - // get the documents directory, where we will write configs and save games - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - [documentsDirectory getCString: iphoneDocDirectory - maxLength: sizeof( iphoneDocDirectory ) - 1 - encoding: NSASCIIStringEncoding ]; - - // get the app directory, where our data files live - // this gives something like: - // /var/mobile/Applications/71355F9F-6400-4267-B07D-E7980764F5A8/Applications - // when what we want is: - // /var/mobile/Applications/71355F9F-6400-4267-B07D-E7980764F5A8/doom.app - // so we get that in main() from argv[0] -#if 0 - paths = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES); - NSString *appDirectory = [paths objectAtIndex:0]; - - static char iphoneAppDirectoryFromAPI[1024]; - [appDirectory getCString: iphoneAppDirectoryFromAPI - maxLength: sizeof( iphoneAppDirectoryFromAPI ) - 1 - encoding: NSASCIIStringEncoding ]; -#endif - - // disable screen dimming - [UIApplication sharedApplication].idleTimerDisabled = YES; - - // Add the Main Menu as the SubView - [self MainMenu]; - - // start the flow of accelerometer events - UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer]; - accelerometer.delegate = self; - accelerometer.updateInterval = 1.0f / 30.0f; - - // use this mutex for coordinating touch handling between - // the run loop thread and the game thread - if ( pthread_mutex_init( &eventMutex, NULL ) == -1 ) { - perror( "pthread_mutex_init" ); - } - - // use this semaphore for signaling from the async cmd generation thread that - // the game / draw thread can wake up - - // sem_init is unimplemented on iPhone - //if ( sem_init( &ticSemaphore, 0, 0 ) == -1 ) { - // perror( "sem_init" ); - //} - ticSemaphore = sem_open( "ticSemaphore", O_CREAT, S_IRWXU, 0 ); - if ( ticSemaphore == SEM_FAILED ) { - perror( "sem_open" ); - } - - // we want the main (event/async) thread to be as high a priority as possible - // so the game/render thread will be interrupted immediately. - // It looks like the default scheduling on iPhone is already what we want -- - // the main thread is at 1.0, and new threads are at 0.5. - printf( "original event thread priority: %f\n", (float)[NSThread threadPriority] ); - [NSThread setThreadPriority: 1.0]; - printf( "new event thread priority: %f\n", (float)[NSThread threadPriority] ); - - // do all the game startup work - iphoneStartup(); - - int animationFrameInterval = 2; - CADisplayLink *aDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(runFrame)]; - [aDisplayLink setFrameInterval:animationFrameInterval]; - [aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - self.displayLink = aDisplayLink; - aDisplayLink.paused = YES; - - - startupCompleted = TRUE; // OK to start touch / accel callbacks -} - - -- (void)applicationWillResignActive:(UIApplication *)application { - displayLink.paused = YES; - inBackgroundProcess = YES; - iphonePauseMusic(); - iphoneShutdown(); -} - - -- (void)applicationDidBecomeActive:(UIApplication *)application { - displayLink.paused = NO; - inBackgroundProcess = NO; - - if( IBMenuVisible && !firstRun ) { - iphonePlayMusic( "intro" ); - } - - firstRun = false; -} - -- (void)applicationWillTerminate:(UIApplication *)application { - iphoneStopMusic(); - iphoneShutdown(); -} - -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - Com_Printf( "applicationDidReceiveMemoryWarning\n" ); -} - - - -- (void)dealloc { - [window release]; - [glView release]; - [super dealloc]; -} - -- (void)restartAccelerometerIfNeeded { - - // I have no idea why this seems to happen sometimes... - if ( SysIphoneMilliseconds() - lastAccelUpdateMsec > 1000 ) { - static int count; - if ( ++count < 100 ) { - printf( "Restarting accelerometer updates.\n" ); - } - UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer]; - accelerometer.delegate = self; - accelerometer.updateInterval = 0.01; - } -} - -- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration -{ - float acc[4]; - acc[0] = acceleration.x; - acc[1] = acceleration.y; - acc[2] = acceleration.z; - acc[3] = acceleration.timestamp; - iphoneTiltEvent( acc ); - lastAccelUpdateMsec = SysIphoneMilliseconds(); -} - -- (void) PrepareForViewSwap { - - [ mainMenuViewController.view removeFromSuperview ]; - [ mapMenuViewController.view removeFromSuperview ]; - [ creditsMenuViewController.view removeFromSuperview ]; - [ legalMenuViewController.view removeFromSuperview ]; - [ settingsMenuViewController.view removeFromSuperview ]; - [ controlsMenuViewController.view removeFromSuperview ]; - [ episodeMenuViewController.view removeFromSuperview ]; -} - -- (void) ResumeGame { - - ResumeGame(); - - // Switch to the Game View. - [window addSubview:glView]; - [window makeKeyAndVisible]; - - displayLink.paused = NO; - IBMenuVisible = NO; -} - -- (void) MainMenu { - - [self PrepareForViewSwap]; - - // Switch to the Game View. - [window addSubview: mainMenuViewController.view]; - [window makeKeyAndVisible]; - iphonePauseMusic(); - - displayLink.paused = YES; - IBMenuVisible = YES; -} - -- (void) DemoGame { - - StartDemoGame( false ); - - // Switch to the Game View. - [window addSubview:glView]; - [window makeKeyAndVisible]; - - displayLink.paused = NO; - IBMenuVisible = NO; -} - -- (void) NewGame { - - [self PrepareForViewSwap]; - - // Switch to the Game View. - [window addSubview: episodeMenuViewController.view]; - [window makeKeyAndVisible]; - - displayLink.paused = YES; - IBMenuVisible = YES; - -} - -- (void) playMap: (int) dataset: (int) episode: (int) map: (int) skill { - mapStart_t startmap; - - startmap.map = map; - startmap.episode = episode; - startmap.dataset = dataset; - startmap.skill = skill; - - StartSinglePlayerGame( startmap ); - - [self HideIB]; -} - -- (void) CreditsMenu { - - [self PrepareForViewSwap]; - - // Switch to the Game View. - [window addSubview: creditsMenuViewController.view]; - [window makeKeyAndVisible]; - - displayLink.paused = YES; - IBMenuVisible = YES; - -} - -- (void) LegalMenu { - - [self PrepareForViewSwap]; - - // Switch to the Game View. - [window addSubview: legalMenuViewController.view]; - [window makeKeyAndVisible]; - - displayLink.paused = YES; - IBMenuVisible = YES; - -} - -- (void) GotoSupport { - - SysIPhoneOpenURL("http://www.idsoftware.com/doom-classic/index.html"); - -} - -- (void) idSoftwareApps { - - SysIPhoneOpenURL("http://itunes.com/apps/idsoftware"); -} - -- (void) ControlsMenu { - - [self PrepareForViewSwap]; - - ControlsMenuView * menu = controlsMenuViewController.view; - [ menu SetOptions]; - - // Switch to the Game View. - [window addSubview: controlsMenuViewController.view]; - [window makeKeyAndVisible]; - - displayLink.paused = YES; - IBMenuVisible = YES; - -} - -- (void) SettingsMenu { - - [self PrepareForViewSwap]; - - SettingsMenuView * menu = settingsMenuViewController.view; - [ menu resetSwitches]; - - // Switch to the Game View. - [window addSubview: settingsMenuViewController.view]; - [window makeKeyAndVisible]; - - displayLink.paused = YES; - IBMenuVisible = YES; - -} - -- (void) HUDLayout { - - menuState = IPM_HUDEDIT; - - [self HideIB]; -} - -- (void) HideIB { - - [self PrepareForViewSwap]; - - // Switch to the Game View. - [window addSubview:glView]; - [window makeKeyAndVisible]; - - displayLink.paused = NO; - IBMenuVisible = NO; -} - -- (void) SelectEpisode: (int) episode { - - [self PrepareForViewSwap]; - - [ (MapMenuView*)mapMenuViewController.view setEpisode: episode ]; - - // Switch to the Game View. - [window addSubview: mapMenuViewController.view]; - [window makeKeyAndVisible]; - - displayLink.paused = YES; - IBMenuVisible = YES; - -} - -@end - - - diff --git a/code/iphone/gles_glue.c b/code/iphone/gles_glue.c old mode 100644 new mode 100755 index 603f07a..cf5d26d --- a/code/iphone/gles_glue.c +++ b/code/iphone/gles_glue.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -25,6 +25,40 @@ //#include "iphone_gl.h" +void R_Draw_Blend( int x, int y, int w, int h, color4_t c ) { + + x *= ((float)displaywidth) / 480.0f; + y *= ((float)displayheight) / 320.0f; + w *= ((float)displaywidth) / 480.0f; + h *= ((float)displayheight) / 320.0f; + + glDisable( GL_TEXTURE_2D ); + glColor4ubv( c ); + + glBegin( GL_QUADS ); + + glVertex2i( x, y ); + glVertex2i( x+w, y ); + glVertex2i( x+w, y+h ); + glVertex2i( x, y+h ); + + glEnd(); + + glColor3f( 1, 1, 1 ); + glEnable( GL_TEXTURE_2D ); +} + + +void R_Draw_Fill( int x, int y, int w, int h, color3_t c ) { + // as of 2.2 OS, doing a clear with a small scissor rect is MUCH slower + // than drawing geometry + color4_t c4; + c4[0] = c[0]; + c4[1] = c[1]; + c4[2] = c[2]; + c4[3] = 255; + R_Draw_Blend( x, y, w, h, c4 ); +} void GLCheckError(const char *message) { GLint err = glGetError(); @@ -52,7 +86,7 @@ short quad_indexes[MAX_VERTS * 3 / 2 ]; int curr_vertex; GLenum curr_prim; -void SetImmediateModeGLVertexArrays() { +void SetImmediateModeGLVertexArrays( void ) { glVertexPointer( 3, GL_FLOAT, sizeof( Vertex ), immediate[ 0 ].xyz ); glEnableClientState( GL_VERTEX_ARRAY ); glTexCoordPointer( 2, GL_FLOAT, sizeof( Vertex ), immediate[ 0 ].st ); @@ -63,7 +97,7 @@ void SetImmediateModeGLVertexArrays() { #endif } -void InitImmediateModeGL() { +void InitImmediateModeGL( void ) { for ( int i = 0; i < MAX_VERTS * 3 / 2; i+=6 ) { int q = i / 6 * 4; quad_indexes[ i + 0 ] = q + 0; @@ -162,7 +196,7 @@ void glTexCoord2fv( GLfloat *st ) { vab.st[ 1 ] = st[1]; } -void glEnd() { +void glEnd( void ) { #if 0 glVertexPointer( 3, GL_FLOAT, sizeof( Vertex ), immediate[ 0 ].xyz ); glTexCoordPointer( 2, GL_FLOAT, sizeof( Vertex ), immediate[ 0 ].st ); @@ -173,8 +207,10 @@ void glEnd() { #endif if ( curr_prim == GL_QUADS ) { glDrawElements( GL_TRIANGLES, curr_vertex / 4 * 6, GL_UNSIGNED_SHORT, quad_indexes ); + GLCheckError("DrawElements"); } else { glDrawArrays( curr_prim, 0, curr_vertex ); + GLCheckError("DrawArrays"); } curr_vertex = 0; curr_prim = 0; @@ -182,19 +218,15 @@ void glEnd() { void landscapeViewport( GLint x, GLint y, GLsizei width, GLsizei height ) { y = 0; // !@# - if ( revLand->value ) { - glViewport( displayheight - (y+height), x, height, width ); - } else { - glViewport( y, x, height, width ); + if (displaywidth > width) { + y = (displaywidth - width) / 2; } + /* JDS proper fix for landscape orientation */ + glViewport( y, x, width, height ); } void landscapeScissor( GLint x, GLint y, GLsizei width, GLsizei height ) { y = 0; // !@# - if ( revLand->value ) { - glScissor( displayheight - (y+height), x, height, width ); - } else { - glScissor( y, x, height, width ); - } + glScissor( y, x, height, width ); } diff --git a/code/iphone/gles_glue.h b/code/iphone/gles_glue.h old mode 100644 new mode 100755 index 20e41d1..6c1a62b --- a/code/iphone/gles_glue.h +++ b/code/iphone/gles_glue.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -22,12 +22,20 @@ #ifndef __GLES_GLUE_H__ #define __GLES_GLUE_H__ +#include + #define GL_QUADS 888 +#ifdef __cplusplus +extern "C" { +#endif + void GLCheckError( const char *message ); void glBegin( GLenum prim ); +void glVertex2f( GLfloat x, GLfloat y ); void glVertex3f( float x, float y, float z ); +void glVertex3fv( GLfloat *xyz ); void glVertex2i( GLint x, GLint y ); void glColor4ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a ); void glColor4ubv( GLubyte *rgba ); @@ -36,6 +44,12 @@ void glColor4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a ); void glColor4fv( GLfloat *rgba ); void glTexCoord2i( GLint s, GLint t ); void glTexCoord2f( GLfloat s, GLfloat t ); -void glEnd(); +void glEnd( void ); + +void SetImmediateModeGLVertexArrays( void ); + +#ifdef __cplusplus +} +#endif -#endif \ No newline at end of file +#endif diff --git a/code/iphone/hud.c b/code/iphone/hud.c old mode 100644 new mode 100755 index dc2f77a..991e106 --- a/code/iphone/hud.c +++ b/code/iphone/hud.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -18,16 +18,17 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" +#include "TargetConditionals.h" #include hud_t huds; -void HudDraw(); +void HudDraw(void); -void HudWrite(); +void HudWrite(void); -void HudRead(); +void HudRead(void); ibutton_t *dragHud; int dragX, dragY; @@ -43,13 +44,16 @@ void SetHudPic( ibutton_t *hp, const char *image ) { void SetHudSpot( ibutton_t *hp, int x, int y, int dw, int dh ) { hp->touch = NULL; // in case one was down when it was saved + // JDS Debug + printf("Registering button at Doom coordinates: %d %d %d %d\n",x,y,dw,dh); + float xRatio = ((float)displaywidth) / 480.0f; float yRatio = ((float)displayheight) / 320.0f; - float themin = MIN( xRatio, yRatio ); + x *= xRatio; + y *= yRatio; - x *= ((float)displaywidth) / 480.0f; - y *= ((float)displayheight) / 320.0f; + float themin = MIN( xRatio, yRatio ); dw *= themin; dh *= themin; @@ -60,9 +64,11 @@ void SetHudSpot( ibutton_t *hp, int x, int y, int dw, int dh ) { hp->drawHeight = dh; hp->buttonFlags = 0; hp->scale = 1.0f; + } void HudSetTexnums() { + SetHudPic( &huds.forwardStick, "iphone/up_down.tga" ); SetHudPic( &huds.sideStick, "iphone/side_2_side.tga" ); SetHudPic( &huds.turnStick, "iphone/directional_2.tga" ); @@ -71,23 +77,19 @@ void HudSetTexnums() { SetHudPic( &huds.menu, "iphone/menu_button.tga" ); SetHudPic( &huds.map, "iphone/map_button.tga" ); - SetHudSpot( &huds.weaponSelect, 240, 280, 40, 90 ); + SetHudSpot( &huds.weaponSelect, 240, 280, 40, 40 ); } void HudSetForScheme( int schemeNum ) { + for ( ibutton_t *hud = (ibutton_t *)&huds ; hud != (ibutton_t *)(&huds+1) ; hud++ ) { hud->buttonFlags = BF_IGNORE; } int STICK_SIZE = 128; int HALF_STICK = 128/2; - if( displaywidth >= 1024 ) { - STICK_SIZE = 64; - HALF_STICK = 64/2; - } - static const int BOTTOM = 320 - 44; // above the status bar - SetHudSpot( &huds.weaponSelect, 240, 280, 40, 90 ); // the touch area is doubled + SetHudSpot( &huds.weaponSelect, 240, 280, 40, 40 ); // the touch area is doubled // make the forward / back sticks touch taller than they draw switch ( schemeNum ) { @@ -217,6 +219,7 @@ void HudEditFrame() { if ( hud->buttonFlags & BF_IGNORE ) { continue; } + PK_StretchTexture( hud->texture, hud->x, hud->y, hud->drawWidth, hud->drawHeight ); } @@ -228,6 +231,7 @@ void HudEditFrame() { } if ( HandleButton( &btnDone ) ) { menuState = IPM_MAIN; + iphonePopGL(); } } diff --git a/code/iphone/ipak.c b/code/iphone/ipak.c old mode 100644 new mode 100755 index 2d070b5..d44d335 --- a/code/iphone/ipak.c +++ b/code/iphone/ipak.c @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * ipak.c + * doom + * + * Created by John Carmack on 4/9/09. + * Copyright 2009 Id Software. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -19,10 +27,10 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" pkHeader_t *pkHeader; -int pkSize; +off_t pkSize; // images and wavs have writable state, so they need separate // structs that also point to the source in the pak file @@ -50,7 +58,7 @@ void PK_Init( const char *pakFileName ) { fstat( fd, &s ); pkSize = s.st_size; - pkHeader = mmap( NULL, pkSize, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0 ); + pkHeader = mmap( NULL, (size_t)pkSize, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0 ); // mmap keeps the file internally, we can close our descriptor close( fd ); @@ -103,7 +111,7 @@ void PK_Init( const char *pakFileName ) { int endLoadingWavs = SysIphoneMicroseconds(); printf( "%i usec to load wavs\n", endLoadingWavs - startLoadingWavs ); - printf( "Mapped %i bytes of %s at 0x%p\n", pkSize, pakFileName, pkHeader ); + printf( "Mapped %lld bytes of %s at 0x%p\n", pkSize, pakFileName, (void*)pkHeader ); printf( "%4i textures\n", pkHeader->textures.count ); printf( "%4i wavs\n", pkHeader->wavs.count ); printf( "%4i raws\n", pkHeader->raws.count ); @@ -112,7 +120,7 @@ void PK_Init( const char *pakFileName ) { for ( int j = 0 ; j < 4 ; j++ ) { int startTime = Sys_Microseconds(); int sum = 0; - for ( int i = 0 ; i < pkSize ; i+=16 ) { + for ( off_t i = 0 ; i < pkSize ; i+=16 ) { sum += ((byte *)pkHeader)[i]; } int endTime = Sys_Microseconds(); @@ -236,12 +244,12 @@ void PK_LoadTexture( pkTexture_t *tex ) { ================== */ pkTexture_t *PK_FindTexture( const char *imageName ) { - int index; - pkTexture_t *texData = (pkTexture_t *)PK_FindType( imageName, &pkHeader->textures, &index ); + int texIndex; + pkTexture_t *texData = (pkTexture_t *)PK_FindType( imageName, &pkHeader->textures, &texIndex ); if ( !texData ) { return NULL; } - pkTexture_t *tex = pkTextures + index; + pkTexture_t *tex = pkTextures + texIndex; if ( tex->glTexNum == 0 ) { PK_LoadTexture( tex ); } @@ -255,12 +263,12 @@ pkTexture_t *PK_FindTexture( const char *imageName ) { ================== */ pkWav_t *PK_FindWav( const char *soundName ) { - int index; - pkWavData_t *wavData = (pkWavData_t *)PK_FindType( soundName, &pkHeader->wavs, &index ); + int wavIndex; + pkWavData_t *wavData = (pkWavData_t *)PK_FindType( soundName, &pkHeader->wavs, &wavIndex ); if ( !wavData ) { return NULL; } - pkWav_t *wav = pkWavs + index; + pkWav_t *wav = pkWavs + wavIndex; // create the OpenAL buffer @@ -330,18 +338,18 @@ const pkName_t *PK_FindType( const char *rawName, const pkType_t *type, int *ind int hashChain = hash & (PK_HASH_CHAINS-1); - int index = type->hashChains[hashChain]; - while ( index != -1 ) { - assert( index >= 0 && index < type->count ); - const pkName_t *name = (pkName_t *)((byte *)pkHeader + type->tableOfs + index * type->structSize ); + int typeIndex = type->hashChains[hashChain]; + while ( typeIndex != -1 ) { + assert( typeIndex >= 0 && typeIndex < type->count ); + const pkName_t *name = (pkName_t *)((byte *)pkHeader + type->tableOfs + typeIndex * type->structSize ); if ( name->nameHash == hash && !strcmp( canonicalName, name->name ) ) { // this is it if ( indexOutput ) { - *indexOutput = index; + *indexOutput = typeIndex; } return name; } - index = name->nextOnHashChain; + typeIndex = name->nextOnHashChain; } // not found diff --git a/code/iphone/ipak.h b/code/iphone/ipak.h old mode 100644 new mode 100755 index 25c1382..3e8a536 --- a/code/iphone/ipak.h +++ b/code/iphone/ipak.h @@ -1,5 +1,15 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * ipak.h + * General purpose data file management intended to be used + * as a read-only memory mapped file to play nice with iPhone OS's + * non-swapping and variable memory management. + * + * Created by John Carmack on 4/9/09. + * Copyright 2009 id Software. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -18,6 +28,8 @@ */ +#ifndef IPAK_H +#define IPAK_H //============================================================ // @@ -161,10 +173,11 @@ void PK_DrawTexture( pkTexture_t *tex, int x, int y ); void PK_StretchTexture( pkTexture_t *tex, float x, float y, float w, float h ); extern pkHeader_t * pkHeader; -extern int pkSize; +extern off_t pkSize; // images and wavs have writable state, so they need separate // structs that also point to the source in the pak file extern pkTexture_t *pkTextures; extern pkWav_t * pkWavs; +#endif diff --git a/code/iphone/iphone_async.c b/code/iphone/iphone_async.cpp old mode 100644 new mode 100755 similarity index 91% rename from code/iphone/iphone_async.c rename to code/iphone/iphone_async.cpp index 4c3fac9..43619c8 --- a/code/iphone/iphone_async.c +++ b/code/iphone/iphone_async.cpp @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * iphone_async.c + * doom + * + * Created by John Carmack on 7/2/09. + * Copyright 2009 id Software. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -19,7 +27,13 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" +//#include "DoomGameCenterMatch.h" +#include "TargetConditionals.h" + +//#include "ios/GameCenter.h" + +#include "GameController.h" typedef struct { int msecFromLast; @@ -65,6 +79,7 @@ void ShowMiniNet() { if ( !miniNet->value ) { return; } + color4_t red = { 255, 0, 0, 255 }; color4_t green = { 0, 255, 0, 255 }; color4_t blue = { 0, 0, 255, 255 }; @@ -91,7 +106,7 @@ void ShowMiniNet() { ================== */ void UpdatePeerTiming( netPeer_t *peer, int remoteMilliseconds ) { - peer->lastPacketAsyncTic == asyncTicNum; + peer->lastPacketAsyncTic = asyncTicNum; peer->lastPacketTime = SysIphoneMilliseconds(); peer->lastTimeDelta = abs( remoteMilliseconds - peer->lastPacketTime ); if ( peer->lowestTimeDelta == 0 || peer->lastTimeDelta < peer->lowestTimeDelta ) { @@ -299,6 +314,11 @@ void iphoneProcessPacket( const struct sockaddr *from, const void *data, int len // copy this after the cmds have been updated maketic = ps->maketic; + // See if anyone has disconnected. + for ( int i = 0; i < MAXPLAYERS; ++i ) { + playeringame[i] = ps->playersInGame[i]; + } + // check consistancy for all in-game players on the most // recent gametic that the server knew this client had run int checkTic = ps->consistancyTic; @@ -343,7 +363,7 @@ void SendSetupPacketIfNecessary() { if ( setupPacket.playerID[i] == 0 ) { continue; } - int r = sendto( gameSocket, &setupPacket, sizeof( setupPacket ), 0, + long int r = sendto( gameSocket, &setupPacket, sizeof( setupPacket ), 0, &netPlayers[i].peer.address, sizeof( netPlayers[i].peer.address ) ); if ( r == -1 ) { Com_Printf( "UDP sendTo failed: %s\n", strerror( errno ) ); @@ -493,7 +513,7 @@ float RotorControl( ibutton_t *hud ) { return deltaAngle / (2*M_PI); } -#define TURBOTHRESHOLD 0x32 +//#define TURBOTHRESHOLD 0x32 static int ClampMove( int v ) { if ( v > TURBOTHRESHOLD ) { return TURBOTHRESHOLD; @@ -533,6 +553,7 @@ static void iphoneBuildTiccmd(ticcmd_t* cmd) { if ( numTouches == numPrevTouches + 1 ) { cmd->buttons |= BT_ATTACK; } + iphoneControllerInput(cmd); return; } @@ -543,7 +564,21 @@ static void iphoneBuildTiccmd(ticcmd_t* cmd) { // don't built a tic when dead, other than the respawn use if ( players[consoleplayer].playerstate == PST_DEAD ) { - return; +#if TARGET_OS_TV + // unless we're on apple tv + iphoneControllerInput(cmd); + + // just to keep things simple all we can do is respawn + // load saved game and respawn with gear are not possible + // may re-evaluate this later but for now this is a tv change + if (cmd->buttons & BT_USE) { + players[consoleplayer].playerstate = PST_REBORN; + } + + return; +#else + return; +#endif } //------------------------ @@ -558,8 +593,17 @@ static void iphoneBuildTiccmd(ticcmd_t* cmd) { UpdateHudTouch( hud ); } } - - return; + + // Re-tapping in the weapon select area will cycle to the next weapon. + // The action happens on initial touch. + touch_t *t = huds.weaponSelect.touch; + if ( t && t->down && t->stateCount == 1 ) { + drawWeaponSelect = false; + t->stateCount++; // ensure it won't bring it back up + weaponCycle = true; + } else { + return; + } } //------------------------ @@ -619,7 +663,7 @@ static void iphoneBuildTiccmd(ticcmd_t* cmd) { sidemove = TURBOTHRESHOLD * AxisHit( &huds.sideStick ); huds.turnStick.scale = stickTurn->value / 128.0f; - cmd->angleturn = -1500.0f * AxisHit( &huds.turnStick ); + cmd->angleturn = -ROTATETHRESHOLD * AxisHit( &huds.turnStick ); // rotary wheel cmd->angleturn -= rotorTurn->value * RotorControl( &huds.turnRotor ); @@ -671,6 +715,9 @@ static void iphoneBuildTiccmd(ticcmd_t* cmd) { cmd->buttons |= newweapon<msecToExecute = 0; prev = now; - - // listen for changes to available servers - //ProcessDNSMessages(); - - // send out the setup packets if we are just starting the game - SendSetupPacketIfNecessary(); // don't generate any commands while loading levels if ( iphoneFrameNum == levelLoadFrameNum ) { return; } - // don't let the game thread mess with touches during the async tic execution - pthread_mutex_lock( &eventMutex ); - int afterLock = SysIphoneMilliseconds(); // latch the current touches for processing @@ -793,32 +831,8 @@ void iphoneAsyncTic() { } else { t->stateCount++; } - } + } - //--------------------------------- - // read network packets - // - // we may receive multiple packets in one frame due to timer skew - // even with only one other player - //--------------------------------- - if ( !netGameFailure ) { - byte packet[1500]; - - while( gameSocket > 0 ) { - struct sockaddr from; - unsigned senderLen = sizeof( from ); - int r = recvfrom( gameSocket, &packet, sizeof( packet ), 0, &from, &senderLen ); - if ( r == -1 ) { - if ( errno != EAGAIN ) { - perror( "recvfrom" ); - } - break; - } - stats->received++; - iphoneProcessPacket( &from, packet, r ); - } - } - //--------------------------------- // Create local user command // @@ -845,13 +859,8 @@ void iphoneAsyncTic() { cp.consoleplayer = consoleplayer; cp.gametic = gametic; cp.cmd = cmd; - int r = sendto( gameSocket, &cp, sizeof( cp ), 0, &netServer.address, sizeof( netServer.address ) ); - stats->sent++; - if ( r == -1 ) { - printf( "UDP sendTo failed: %s\n", strerror( errno ) ); - close( gameSocket ); - gameSocket = -1; - } + + //idGameCenter::SendPacketToPlayerUnreliable( serverGameCenterID, &cp, sizeof ( cp ) ); } } } else { @@ -906,6 +915,9 @@ void iphoneAsyncTic() { gp.gameID = gameID; gp.packetSequence = packetSequence++; gp.maketic = maketic; + for ( int i = 0; i < MAXPLAYERS; ++i ) { + gp.playersInGame[i] = playeringame[i]; + } memcpy( gp.netcmds, netcmds, sizeof( gp.netcmds ) ); //--------------------------------- @@ -915,22 +927,21 @@ void iphoneAsyncTic() { if ( !playeringame[i] ) { continue; } - if ( gameSocket <= 0 ) { - continue; - } + netPlayer_t *np = &netPlayers[i]; // only send over the ticcmd that this client needs gp.starttic = np->pc.gametic; ticcmd_t *cmd_p = gp.netcmds; - for ( int i = gp.starttic ; i < gp.maketic ; i++ ) { - for ( int j = 0 ; j < MAXPLAYERS ; j++ ) { - if ( playeringame[j] ) { - *cmd_p++ = netcmds[j][i&BACKUPTICMASK]; + for ( int j = gp.starttic ; j < gp.maketic ; j++ ) { + for ( int k = 0 ; k < MAXPLAYERS ; k++ ) { + if ( playeringame[k] ) { + *cmd_p++ = netcmds[k][j&BACKUPTICMASK]; } } } - int packetSize = (byte *)cmd_p - (byte *)&gp; + long int packetSize = (byte *)cmd_p - (byte *)&gp; + (void)packetSize; // use the most recent tic that both the client and // server have run @@ -944,14 +955,9 @@ void iphoneAsyncTic() { gp.packetAcknowledge = np->pc.packetSequence; gp.milliseconds = SysIphoneMilliseconds(); - // transmit the packet - stats->sent++; - int r = sendto( gameSocket, &gp, packetSize, 0, &np->peer.address, sizeof( np->peer.address ) ); - if ( r == -1 ) { - printf( "UDP sendTo failed: %s\n", strerror( errno ) ); - close( gameSocket ); - gameSocket = -1; - } + // transmit the packet + //const std::string theClient = playerIndexToIDMap[i]; + //idGameCenter::SendPacketToPlayerUnreliable( theClient, &gp, packetSize ); } } } @@ -962,15 +968,6 @@ void iphoneAsyncTic() { printf( "long asyncTic %i: %i msec (%i in lock), %i packets\n", asyncTicNum - 1, stats->msecToExecute, afterLock - now, stats->received ); } - - // the game thread can now swap touches - pthread_mutex_unlock( &eventMutex ); - - // signal the main thread that is probably blocked on this semaphore - if ( sem_post( ticSemaphore ) == -1 ) { - perror( "sem_post"); - } - } diff --git a/code/iphone/iphone_common.h b/code/iphone/iphone_common.h new file mode 100755 index 0000000..27c0e52 --- /dev/null +++ b/code/iphone/iphone_common.h @@ -0,0 +1,35 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#ifndef doomengine_iphone_common_h +#define doomengine_iphone_common_h + + +@class UIViewController; + +void CommonSystemSetup( UIViewController * gameController ); + + + +extern char iphoneDocDirectory[PATH_MAX]; +extern char iphoneAppDirectory[PATH_MAX]; +extern char iphoneTempDirectory[PATH_MAX]; + +#endif diff --git a/code/iphone/iphone_common.mm b/code/iphone/iphone_common.mm new file mode 100755 index 0000000..dc27e21 --- /dev/null +++ b/code/iphone/iphone_common.mm @@ -0,0 +1,113 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import + +#include "iphone_common.h" +#include "doomiphone.h" +// disabling it, not sure if used -tkidd +//#include "ios/GameCenter.h" +#include "../ios/Localization.h" +#import "../ios/LocalizationObjectiveC.h" +#include "iphone_delegate.h" +//#include "DoomGameCenterMatch.h" +//#import "ios/objectivec_utilities.h" + +@class UIViewController; + +/* +======================= +CommonSystemSetup + +Called in each game's didFinishLaunching method. +======================= +*/ +void CommonSystemSetup( UIViewController * gameViewController ) { + + // Authenticate the Game Center player. + //idGameCenter::Initialize(); + //idGameCenter::AuthenticateLocalPlayer( gameViewController, &gDoomGameCenterMatch ); + + // get the documents directory, where we will write configs and save games + #if TARGET_OS_TV + NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; + #else + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + #endif + [documentsDirectory getCString: iphoneDocDirectory + maxLength: sizeof( iphoneDocDirectory ) - 1 + encoding: NSASCIIStringEncoding ]; + + // get the app directory, where our data files live + // this gives something like: + // /var/mobile/Applications/71355F9F-6400-4267-B07D-E7980764F5A8/Applications + // when what we want is: + // /var/mobile/Applications/71355F9F-6400-4267-B07D-E7980764F5A8/doom.app + // so we get that in main() from argv[0] +#if 0 + paths = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES); + NSString *appDirectory = [paths objectAtIndex:0]; + + static char iphoneAppDirectoryFromAPI[1024]; + [appDirectory getCString: iphoneAppDirectoryFromAPI + maxLength: sizeof( iphoneAppDirectoryFromAPI ) - 1 + encoding: NSASCIIStringEncoding ]; +#endif + + + // Get the temporary directory. + NSString * tempDirectory = NSTemporaryDirectory(); + [tempDirectory getCString:iphoneTempDirectory maxLength:PATH_MAX encoding:NSUTF8StringEncoding]; + + // Initialize the localization system. + idLocalization_Initialize(); +} + +/* + ======================= + MainMenu + + Hides the OpenGL View and reverts back to Interface builder. + ======================= + */ +void iphoneMainMenu() { + + [ gAppDelegate HideGLView]; + menuState = IPM_MAIN; +} + +/* + ======================= + iphonePopGL + + Hides the OpenGL View and reverts back to Interface builder. + ======================= + */ +void iphonePopGL() { + + [ gAppDelegate PopGLView]; + menuState = IPM_MAIN; +} + +void iphoneNSLog(const char* message) { + NSLog( @"%@", [NSString stringWithUTF8String:message] ); +} + diff --git a/code/iphone/iphone_delegate.h b/code/iphone/iphone_delegate.h new file mode 100755 index 0000000..8ffa8c8 --- /dev/null +++ b/code/iphone/iphone_delegate.h @@ -0,0 +1,58 @@ +/* + + Copyright (C) 2009 Id Software, Inc. + + 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. + + */ + +#import +#import +#import "iphone_glViewController.h" + +@class EAGLView; + +#if TARGET_OS_TV + @interface iphoneApp : NSObject { +#else + @interface iphoneApp : NSObject { +#endif + + UIWindow * window; // Main Application Window. + UINavigationController * navigationController; // Our View Stack + iphone_glViewController * openGLViewController; // our OpenGL (Game) View + BOOL hasPushedGLView; // Keep track of whether the GL view + // is on top of the stack, for the + // hacked delay used to hide the first + // frame of garbage. +} + +@property (nonatomic, retain) IBOutlet UIWindow *window; + +extern iphoneApp * gAppDelegate; + +- (void) InitializeInterfaceBuilder; + +- (void) HACK_PushController; +- (void) ShowGLView; +- (void) HideGLView; +- (void) PopGLView; + +- (NSString*) GetNibNameForDevice:(NSString*) nibName; + +- (NSString*) GetFontName; + +@end + diff --git a/code/iphone/iphone_delegate.mm b/code/iphone/iphone_delegate.mm new file mode 100755 index 0000000..d836a4e --- /dev/null +++ b/code/iphone/iphone_delegate.mm @@ -0,0 +1,257 @@ +/* + + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "iphone_delegate.h" + +#import +#include "doomiphone.h" +#include "iphone_common.h" +// disabling all app store and game center stuff, not sure if used +//#include "ios/InAppStore.h" +//#include "ios/GameCenter.h" + + + +@implementation iphoneApp + +@synthesize window; + +iphoneApp * gAppDelegate = NULL; +bool inBackgroundProcess = false; + +touch_t sysTouches[MAX_TOUCHES]; +touch_t gameTouches[MAX_TOUCHES]; + +#define FRAME_HERTZ 30.0f +#if !TARGET_OS_TV +//const static float ACCELEROMETER_UPDATE_INTERVAL = 1.0f / FRAME_HERTZ; +#endif +//FIXME: JadingTsunami (fix) const static float ACCELEROMETER_UPDATE_INTERVAL = 1.0f / FRAME_HERTZ; + +/* + ======================== + applicationDidFinishLaunching + ======================== + */ +- (void)applicationDidFinishLaunching:(UIApplication *)application { + + gAppDelegate = self; + inBackgroundProcess = false; + hasPushedGLView = NO; + + // Create the window programmatically instead of loading from a nib file. + self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; + + // Disable Screen Dimming. + [[ UIApplication sharedApplication] setIdleTimerDisabled: YES ]; + +#if !TARGET_OS_TV + + // Initial Application Style config. + [UIApplication sharedApplication].statusBarHidden = YES; + + // start the flow of accelerometer events + /* //FIXME: JadingTsunami (fix) + UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer]; + [ accelerometer setDelegate: self ]; + [ accelerometer setUpdateInterval: ACCELEROMETER_UPDATE_INTERVAL ]; + */ + +#endif + + [self InitializeInterfaceBuilder ]; + + CommonSystemSetup( [navigationController topViewController] ); + + // do all the game startup work + iphoneStartup(); + + UIView * view = navigationController.view; + + [window addSubview: view]; + [window setRootViewController:navigationController]; + [window setBackgroundColor: [UIColor blackColor] ]; + [window makeKeyAndVisible]; +} + +/* + ======================== + applicationWillResignActive + ======================== + */ +- (void)applicationWillResignActive:(UIApplication *)application { + inBackgroundProcess = YES; + + //idGameCenter::HandleMoveToBackground(); + + // If we're in a multiplater game, and showing the OpenGL view, + // go back to the main menu since the multiplayer game is hosed. + if ( netgame && navigationController.topViewController == gAppDelegate->openGLViewController ) { + iphoneMainMenu(); + } + + iphonePauseMusic(); + iphoneShutdown(); +} + +/* + ======================== + applicationDidBecomeActive + ======================== + */ +- (void)applicationDidBecomeActive:(UIApplication *)application { + inBackgroundProcess = NO; +} + + +/* + ======================== + applicationWillTerminate + ======================== + */ +- (void)applicationWillTerminate:(UIApplication *)application { + iphoneStopMusic(); + iphoneShutdown(); +} + + +/* + ======================== + applicationDidReceiveMemoryWarning + ======================== + */ +- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { + Com_Printf( "applicationDidReceiveMemoryWarning\n" ); +} + + +/* + ======================== + dealloc + ======================== + */ +- (void)dealloc { + [window release]; + [super dealloc]; +} + +#if !TARGET_OS_TV + +/* + ======================== + accelerometer + ======================== +- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration +{ + float acc[4]; + acc[0] = acceleration.x; + acc[1] = acceleration.y; + acc[2] = acceleration.z; + acc[3] = acceleration.timestamp; + + + iphoneTiltEvent( acc ); +} +*/ + +#endif + +/* + ======================== + HACK_PushController - Removes Flicker from Loading Wads. + God forgive me. + + ======================== + */ +- (void) HACK_PushController { + [navigationController pushViewController:openGLViewController animated:NO]; +} + +/* + ======================== + ShowGLView + ======================== + */ +- (void)ShowGLView { + + if( hasPushedGLView == NO ) { + hasPushedGLView = YES; + // Hack city. + [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(HACK_PushController) userInfo:nil repeats:NO]; + + [ openGLViewController StartDisplay ]; + } +} + +/* + ======================== + HideGLView + ======================== + */ +- (void) HideGLView { + + [ navigationController popToRootViewControllerAnimated:NO ]; + hasPushedGLView = NO; +} + +/* + ======================== + PopGLView + ======================== + */ +- (void) PopGLView { + [ navigationController popViewControllerAnimated:NO]; + hasPushedGLView = NO; +} + + +/* + ======================== + InitializeInterfaceBuilder + ======================== + */ +- (void) InitializeInterfaceBuilder { + +} + +- (NSString*) GetNibNameForDevice:(NSString*) nibName +{ + NSString *extension = @""; + +#if TARGET_OS_TV + extension = @"-tvos"; +#endif + + return [NSString stringWithFormat:@"%@%@", nibName, extension]; +} + +- (NSString*) GetFontName +{ + // To restore usage of the original font, un-comment out this line and comment out the next line + //return @"idGinza Narrow"; + return @"Chicago"; +} + +@end + +void ShowGLView( void ) { + [ gAppDelegate ShowGLView ]; +} + diff --git a/code/iphone/iphone_doom.h b/code/iphone/iphone_doom.h old mode 100644 new mode 100755 index 1cfaaaf..42d3492 --- a/code/iphone/iphone_doom.h +++ b/code/iphone/iphone_doom.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -17,6 +17,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef IPHONE_DOOM_H +#define IPHONE_DOOM_H + +#include "../prboom/doomtype.h" +#include "../prboom/doomdef.h" +#include "../prboom/doomstat.h" +#include "../prboom/d_ticcmd.h" + +#include "ipak.h" +#include "cvar.h" + +#include // this is the version number displayed on the menu screen #define DOOM_IPHONE_VERSION 0.9 @@ -24,6 +37,10 @@ // if defined, the game runs in a separate thread from the app event loop #define USE_GAME_THREAD +#ifdef __cplusplus +extern "C" { +#endif + typedef enum menuState { IPM_GAME, IPM_MAIN, @@ -38,7 +55,7 @@ typedef enum menuState { extern menuState_t menuState; extern menuState_t lastState; -void iphoneDrawMenus(); + void iphoneDrawMenus(void); #define VID_WIDTH 480 #define VID_HEIGHT 320 @@ -100,6 +117,7 @@ extern int consoleActive; extern boolean iphoneTimeDemo; extern int timeDemoStart; extern char timeDemoResultString[80]; +extern float screenResolutionScale; extern cvar_t *skill; extern cvar_t *episode; @@ -119,7 +137,6 @@ extern cvar_t *showTime; extern cvar_t *showNet; extern cvar_t *showSound; extern cvar_t *cropSprites; -extern cvar_t *revLand; extern cvar_t *mapScale; extern cvar_t *drawControls; extern cvar_t *autoUse; @@ -133,12 +150,16 @@ extern cvar_t *mpDataset; extern cvar_t *mpSkill; extern cvar_t *mpEpisode; extern cvar_t *mpMap; +extern cvar_t *mpExpansion; extern cvar_t *glfinish; extern cvar_t *mapSelectY; extern cvar_t *throttle; extern cvar_t *centerSticks; extern cvar_t *rampTurn; extern cvar_t *netBuffer; +extern cvar_t *iwadSelection; +extern cvar_t *pwadSelection; + extern int numTouches; extern int touches[5][2]; // [0] = x, [1] = y in landscape mode, raster order with y = 0 at top @@ -155,8 +176,11 @@ extern int weaponSelected; // -1 for no change typedef unsigned char color4_t[4]; typedef unsigned char color3_t[3]; +extern char* doom_iwad; +extern char* doom_pwads; + // networking -enum { +typedef enum { PACKET_VERSION_BASE = 0x24350010, PACKET_VERSION_SETUP, PACKET_VERSION_JOIN, @@ -257,6 +281,10 @@ typedef struct { // netcmds[][(maketic-1)&BACKUPTICMASK] is the most recent int maketic; + // notifies the server of which players are connected. This way we can handle players + // that disconnect in the middle of a game. + int playersInGame[MAXPLAYERS]; + // only the [playersInGame*(maketic-starttic)] will be transmitted ticcmd_t netcmds[MAXPLAYERS*BACKUPTICS]; } packetServer_t; @@ -284,7 +312,8 @@ extern boolean respawnActive; typedef enum { NF_NONE, NF_CONSISTANCY, - NF_INTERRUPTED + NF_INTERRUPTED, + NF_LOST_SERVER } netFail_t; extern netFail_t netGameFailure; // set by asyncThread @@ -312,7 +341,6 @@ void iphoneProcessPacket( const struct sockaddr *from, const void *data, int len extern netPeer_t netServer; extern netPlayer_t netPlayers[MAXPLAYERS]; -extern sem_t * ticSemaphore; typedef struct { int numGameTics; @@ -336,20 +364,18 @@ int TouchPressed( int x, int y, int w, int h ); float iphoneDrawText( float x, float y, float scale, const char *str ); float iphoneCenterText( float x, float y, float scale, const char *str ); -void StartGame(); -void iphoneOpenAutomap(); -void iphoneDrawNotifyText(); +void StartGame(void); +void iphoneOpenAutomap(void); +void iphoneDrawNotifyText(void); void iphoneSet2D( void ); void R_Draw_Fill( int x, int y, int w, int h, color3_t c ); void R_Draw_Blend( int x, int y, int w, int h, color4_t c ); -void InitImmediateModeGL(); -int iphoneRotateForLandscape(); -void iphoneCheckForLandscapeReverse(); +void InitImmediateModeGL(void); -void iphonePacifierUpdate(); -void iphoneDrawScreen(); +void iphonePacifierUpdate(void); +void iphoneDrawScreen(void); extern int damageflash; extern int bonusFrameNum; @@ -399,13 +425,13 @@ typedef struct { extern hud_t huds; void HudSetForScheme( int schemeNum ); -void HudSetTexnums(); -void HudEditFrame(); +void HudSetTexnums(void); +void HudEditFrame(void); -boolean StartNetGame(); +boolean StartNetGame(void); -int BackButton(); -void ResumeGame(); +int BackButton(void); +void ResumeGame(void); //--------------------------------------- // Touch and button @@ -422,7 +448,6 @@ typedef struct touch_s { #define MAX_TOUCHES 5 extern touch_t sysTouches[MAX_TOUCHES]; extern touch_t gameTouches[MAX_TOUCHES]; -extern pthread_mutex_t eventMutex; // used to sync between game and event threads touch_t *TouchInBounds( int x, int y, int w, int h ); touch_t *AnyTouchInBounds( int x, int y, int w, int h ); @@ -451,28 +476,28 @@ void Sound_Init( void ); void Sound_StartLocalSound( const char *sound ); void Sound_StartLocalSoundAtVolume( const char *sound, float volume ); -void ShowSound(); +void ShowSound(void); //--------------------------------------- // iphone_net.c //--------------------------------------- // dump all the interfaces and ip addresses for debugging -void ReportNetworkInterfaces(); +void ReportNetworkInterfaces(void); // open a UDP socket, pass "en0" for wifi int UDPSocket( const char *interfaceName, int portnum ); // return false if the multiplayer button should be disabled -boolean NetworkAvailable(); +boolean NetworkAvailable(void); // this can be called every frame in the menu to highlight // the multiplayer icon when a server is already up -boolean NetworkServerAvailable(); +boolean NetworkServerAvailable(void); // returns "WiFi", "BlueTooth", or "" for display on the // main menu multiplayer icon -const char *NetworkServerTransport(); +const char *NetworkServerTransport(void); // this queries DNS for the actual address boolean ResolveNetworkServer( struct sockaddr *addr ); @@ -481,25 +506,20 @@ boolean ResolveNetworkServer( struct sockaddr *addr ); // us available as a bonjour service until we start the game // or back out of the multiplayer menu. Returns false if // someone else grabbed it just before we could. -boolean RegisterGameService(); -void TerminateGameService(); +boolean RegisterGameService(void); +void TerminateGameService(void); // called by AsyncTic() to check for server state changes, // registers for service browsing on first call. -void ProcessDNSMessages(); +void ProcessDNSMessages(void); // draw a graph of packets sent and received -void ShowNet(); -void ShowMiniNet(); +void ShowNet(void); +void ShowMiniNet(void); //--------------------------------------- // iphone_mapSelect.c //--------------------------------------- - -// returns false if nothing was selected -// if map->map is -1, the back button was hit instead of choosing a level -boolean iphoneMapSelectMenu( mapStart_t *map ); - mapStats_t *FindMapStats( int dataset, int episode, int map, boolean create ); const char *FindMapName( int dataset, int episode, int map ); @@ -508,9 +528,9 @@ const char *FindMapName( int dataset, int episode, int map ); // // game harness routines //--------------------------------------- -void ResumeGame(); -boolean StartNetGame(); -void StartSaveGame(); +void ResumeGame(void); +boolean StartNetGame(void); +void StartSaveGame(void); void StartSinglePlayerGame( mapStart_t map ); void StartDemoGame( boolean timeDemoMode ); @@ -519,12 +539,20 @@ void StartDemoGame( boolean timeDemoMode ); //--------------------------------------- void iphoneSetNotifyText( const char *str, ... ); void iphoneIntermission( wbstartstruct_t* wbstartstruct ); -void iphoneStartLevel(); -void iphoneStartMusic(); -void iphoneStopMusic(); +void iphoneStartLevel(void); +void iphoneStartMusic(void); +void iphoneStopMusic(void); void iphonePlayMusic( const char *name ); -void iphonePauseMusic(); -void iphoneResumeMusic(); +void iphoneStartMP3(const char *filename); +void iphonePauseMusic(void); +void iphoneResumeMusic(void); +void iphoneDoomStartup(void); +void iphoneIWADSelect( const char* iwad ); +void iphonePWADAdd( const char* pwad ); +void iphonePWADRemove( const char* pwad ); +void iphoneClearPWADs(void); +void iphoneLoadMissionPack(void); +void iphoneAddPWADFiles(void); //--------------------------------------- // interfaces to Objective-C land @@ -535,25 +563,41 @@ void iphoneResumeMusic(); // execute it, and clear it under mutex. extern char consoleCommand[1024]; -void SysIPhoneSwapBuffers(); -void SysIPhoneVibrate(); +void SysIPhoneSwapBuffers(void); +void SysIPhoneVibrate(void); void SysIPhoneOpenURL( const char *url ); +int SysIPhoneIsDeviceLandscapeRight( void ); void SysIPhoneSetUIKitOrientation( int isLandscapeRight ); -const char * SysIPhoneGetConsoleTextField(); +const char * SysIPhoneGetConsoleTextField(void); void SysIPhoneSetConsoleTextField(const char *); -void SysIPhoneInitAudioSession(); -int SysIPhoneOtherAudioIsPlaying(); -int SysIphoneMilliseconds(); -int SysIphoneMicroseconds(); -const char * SysIphoneGetAppDir(); -const char * SysIphoneGetDocDir(); +void SysIPhoneInitAudioSession(void); +int SysIPhoneOtherAudioIsPlaying(void); +int SysIphoneMilliseconds(void); +int SysIphoneMicroseconds(void); +const char * SysIphoneGetAppDir(void); +const char * SysIphoneGetDocDir(void); +const char * SysIphoneGetTempDir(void); + +void ShowGLView( void ); //--------------------------------------- // interfaces from Objective-C land //--------------------------------------- -void iphoneStartup(); -void iphoneShutdown(); -void iphoneFrame(); -void iphoneAsyncTic(); +void iphoneStartup(void); +void iphoneShutdown(void); +void iphoneFrame(void); +void iphoneAsyncTic(void); void iphoneTiltEvent( float *tilts ); +void iphoneMainMenu(void); +void iphonePopGL(void); +void iphoneNSLog(const char* message); + +extern boolean sigilShredsLoaded; // Buckethead! + +#ifdef __cplusplus +} +#endif + +#define DEFAULTS_MISSIONPACK_KEY "missionPack" +#endif diff --git a/code/iphone/iphone_email.h b/code/iphone/iphone_email.h old mode 100644 new mode 100755 index 953503b..5e0d57b --- a/code/iphone/iphone_email.h +++ b/code/iphone/iphone_email.h @@ -1,6 +1,13 @@ +/* + * iphone_email.h + * Doom + * + * Created by Greg Hodges on 10/20/09. + * Copyright 2009 id Software. All rights reserved. + * + */ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -25,4 +32,4 @@ void AppendConsoleBuffer(const char *buf); //Emails the console buffer to id software -void EmailConsole(); \ No newline at end of file +void EmailConsole(void); diff --git a/code/iphone/iphone_email.m b/code/iphone/iphone_email.m old mode 100644 new mode 100755 index 556b2bb..273c53c --- a/code/iphone/iphone_email.m +++ b/code/iphone/iphone_email.m @@ -1,6 +1,13 @@ +/* + * iphone_email.c + * Doom + * + * Created by Greg Hodges on 10/20/09. + * Copyright 2009 id Software. All rights reserved. + * + */ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -23,9 +30,12 @@ #include "iphone_email.h" #include +#import +#import + char *consoleBuffer = NULL; //buffer for the console output -int size = 0; +long int size = 0; /* * ReplaceAt() @@ -33,8 +43,8 @@ */ void ReplaceAt( char *oldString, const char *insertString, int location) { - int length = strlen(oldString); - int chunkLength = strlen(insertString); + unsigned long length = strlen(oldString); + unsigned long chunkLength = strlen(insertString); char *newString = malloc(length + chunkLength + 1);//the 1 includes space for the null terminating character @@ -80,7 +90,7 @@ void ReplaceAt( char *oldString, const char *insertString, int location) */ void AppendBuffer(const char *buf) { - int length = strlen(buf) + 1; //strlen doesn't include the null terminating character + unsigned long int length = strlen(buf) + 1; //strlen doesn't include the null terminating character char *temp = malloc(length); strcpy(temp, buf); @@ -128,11 +138,11 @@ void AppendBuffer(const char *buf) */ void AppendChunk(const char *buf, int start, int i) { - int size = i+1 - start; - char chunk[size]; + int chunkSize = i+1 - start; + char chunk[chunkSize]; chunk[0] = '\0'; - strncpy(chunk, &buf[start], size-1); - chunk[size-1] = '\0'; + strncpy(chunk, &buf[start], chunkSize-1); + chunk[chunkSize-1] = '\0'; AppendBuffer(chunk); } @@ -142,47 +152,7 @@ void AppendChunk(const char *buf, int start, int i) */ void AppendConsoleBuffer(const char *buf) { - int length = strlen(buf) + 1; //strlen doesn't include the null terminating character - char *temp = malloc(length); - strcpy(temp, buf); - - - int start = 0; - int i = 0; - for (i = 0; i < length; ++i) - { - //replace space and = with _ - //spaces and = tend to mess up the URL scheme - if (temp[i] == ' ' ) - { - temp[i] = '_'; - AppendChunk(temp, start, i); ++i; start = i; - AppendBuffer("\%20"); //line space - } - - if (temp[i] == '=' ) - { - temp[i] = '_'; - AppendChunk(temp, start, i); ++i; start = i; - AppendBuffer("\%3D"); //= - } - - if (temp[i] == '\n') - { - temp[i] = '_'; - AppendChunk(temp, start, i); ++i; start = i; - AppendBuffer("\%0A"); //line return - } - } - - //append the last of the chunk - i = length - 1; - if (start < i) - { - AppendChunk(temp, start, i); - } - - // AppendString("\%0A"); //line return + } @@ -193,6 +163,10 @@ void AppendConsoleBuffer(const char *buf) */ void EmailConsole() { + + return; // do not email me anymore. + +#if 0 if (!consoleBuffer) return; @@ -219,10 +193,11 @@ void EmailConsole() #endif //call the mail app - NSURL *url = [[NSURL alloc] initWithString:[[NSString alloc] initWithCString:buffer]]; + NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithCString:buffer encoding:NSUTF8StringEncoding]]; [[UIApplication sharedApplication] openURL:url]; free(buffer); +#endif } diff --git a/code/iphone/iphone_sys.c b/code/iphone/iphone_glViewController.h old mode 100644 new mode 100755 similarity index 53% rename from code/iphone/iphone_sys.c rename to code/iphone/iphone_glViewController.h index 64b80b3..ca5a126 --- a/code/iphone/iphone_sys.c +++ b/code/iphone/iphone_glViewController.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -18,45 +18,26 @@ */ +#import -#include "../doomiphone.h" -#import -int SysIphoneMicroseconds() { - struct timeval tp; - struct timezone tzp; - static int secbase; - - gettimeofday( &tp, &tzp ); - - if( ! secbase ) { - secbase = tp.tv_sec; - return tp.tv_usec; - } - - int curtime = (tp.tv_sec - secbase) * 1000000 + tp.tv_usec; - - return curtime; +@interface iphone_glViewController : UIViewController { + + CADisplayLink *displayLink; + } -int SysIphoneMilliseconds() { - return SysIphoneMicroseconds()/1000; -} - - -extern char iphoneDocDirectory[1024]; -extern char iphoneAppDirectory[1024]; - -const char *SysIphoneGetAppDir() { - return iphoneAppDirectory; -} - -const char *SysIphoneGetDocDir() { - return iphoneDocDirectory; -} +@property (nonatomic, retain) IBOutlet CADisplayLink *displayLink; -void SysIPhoneVibrate() { - AudioServicesPlaySystemSound( kSystemSoundID_Vibrate ); -} +- (void) StartDisplay; +- (void) StopDisplay; +- (bool) IsDisplaying; +// JDS revised orientation code +#if !TARGET_OS_TV +-(BOOL)shouldAutorotate; +- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation; +- (UIInterfaceOrientationMask)supportedInterfaceOrientations; +#endif +@end diff --git a/code/iphone/iphone_glViewController.mm b/code/iphone/iphone_glViewController.mm new file mode 100755 index 0000000..284791a --- /dev/null +++ b/code/iphone/iphone_glViewController.mm @@ -0,0 +1,203 @@ +/* + Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + + 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. + + */ + +#import "iphone_glViewController.h" +#import "EAGLView.h" +#import +#include "doomiphone.h" +#include "iphone_delegate.h" + +#if TARGET_OS_TV +const static int DISPLAY_LINK_FRAME_INTERVAL = 30; +#else +const static int DISPLAY_LINK_FRAME_INTERVAL = 2; +#endif + +// Need one buffer frame when transitioning from IB menus to the OpenGL game view. +// Otherwise, occasionally the IB view stays onscreen during the Doom loading frame. +// This seems to make precaching take way to long (about a whole minute). +// This flag will be set to true in StartDisplay, and reset to false after one display link +// frame has fired. +static bool inTransition = false; + +@implementation iphone_glViewController + +@synthesize displayLink; + +/* + ======================== + runFrame + ======================== + */ +- (void)runFrame { + + // Skip the frist frame after coming from IB menus, to give the view a chance to switch to + // OpenGL. For some reason, not doing this causes precaching to take way too long. + if ( inTransition ) { + inTransition = false; + return; + } + + // Update the Game + iphoneAsyncTic(); + + // Render the Game. + iphoneFrame(); +} + +/* + ======================== + initWithNibName + ======================== + */ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + + // Create the OpenGL View. +#if TARGET_OS_TV + EAGLView *glView = [[EAGLView alloc] initWithFrame:[UIScreen mainScreen].bounds]; +#else + EAGLView *glView = [[EAGLView alloc] initWithFrame:[UIScreen mainScreen].bounds]; +#endif + self.view = glView; + [glView release]; + + + // Setup the Display Link + CADisplayLink *aDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(runFrame)]; +#if TARGET_OS_TV + aDisplayLink.preferredFramesPerSecond= DISPLAY_LINK_FRAME_INTERVAL; +#else + [ aDisplayLink setFrameInterval: DISPLAY_LINK_FRAME_INTERVAL]; +#endif + [ aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [ self setDisplayLink: aDisplayLink ]; + + } + return self; +} + +/* +======================== +shouldAutorotateToInterfaceOrientation +======================== + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + // Return YES for supported orientations. + return UIInterfaceOrientationIsLandscape(interfaceOrientation); +} +*/ + +#if !TARGET_OS_TV +- (BOOL)shouldAutorotate { + return NO; +} + +- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { + return UIInterfaceOrientationLandscapeRight; +} + +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + return UIInterfaceOrientationMaskLandscape; +} +#endif + + +/* + ======================== + viewDidLoad + ======================== + */ +- (void)viewDidLoad { + [super viewDidLoad]; + + // Stop the Display link. + [self.displayLink invalidate]; + self.displayLink = nil; +} + + +/* + ======================== + didReceiveMemoryWarning + ======================== + */ +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; +} + +/* + ======================== + viewDidUnload + ======================== + */ +/* +- (void)viewDidUnload { + [super viewDidUnload]; +} +*/ + +/* + ======================== + dealloc + ======================== + */ +- (void)dealloc { + [super dealloc]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + +#if TARGET_OS_TV + [ gAppDelegate HideGLView ]; +#endif +} + +/* + ======================== + StartDisplay + ======================== + */ +- (void) StartDisplay { + inTransition = true; + displayLink.paused = NO; +} + +/* + ======================== + StopDisplay + ======================== + */ +- (void) StopDisplay { + displayLink.paused = YES; +} + +/* + ======================== + IsDisplaying + ======================== + */ +- (bool) IsDisplaying { + return displayLink.paused; +} + +@end diff --git a/code/iphone/iphone_loop.c b/code/iphone/iphone_loop.c old mode 100644 new mode 100755 index 2903f9c..38bae0a --- a/code/iphone/iphone_loop.c +++ b/code/iphone/iphone_loop.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -18,7 +18,8 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" +#include "TargetConditionals.h" playState_t playState; @@ -69,7 +70,6 @@ int packetSequence; // for logging dropped packets and estimating latency netFail_t netGameFailure; // set by asyncThread netPlayer_t netPlayers[MAXPLAYERS]; netPeer_t netServer; -sem_t * ticSemaphore; // set after each game tic if a usable line is in front of the player boolean autoUseActive; @@ -126,8 +126,14 @@ touch_t *TouchInBounds( int x, int y, int w, int h ) { } if ( t->x >= x && t->x < x + w && t->y >= y && t->y < y + h ) { + // JDS Debug + //printf("Touch HIT! %d vs. %d / %d vs. %d (%d %d)\n",x,t->x,y,t->y,w,h); return t; } + // JDS Debug + else { + //printf("Touch missed %d vs. %d / %d vs. %d (%d %d)\n",x,t->x,y,t->y,w,h); + } } return NULL; } @@ -154,7 +160,7 @@ touch_t *UpdateHudTouch( ibutton_t *hud ) { // hud element isn't active return NULL; } - + if ( !hud->touch ) { // see if a free touch was just made in, or dragged into the bounds // make the active boxes twice as large as the drawing bounds @@ -164,11 +170,12 @@ touch_t *UpdateHudTouch( ibutton_t *hud ) { int h = hud->drawHeight << 1; hud->touch = TouchInBounds( x, y, w, h ); + //printf("TIB: %d %d %d %d -> %s\n",x,y,w,h,(hud->touch == NULL) ? "none" : "found" ); if ( hud->touch ) { // claim this touch so it won't activate anything else hud->touch->controlOwner = hud; if ( touchClick->value ) { - Sound_StartLocalSoundAtVolume( "iphone/controller_down_01_SILENCE.wav", touchClick->value ); + Sound_StartLocalSoundAtVolume( "iphone/controller_down_01_SILENCE.wav", touchClick->value ? 0.15f : 0.0f ); } // save the initial touch position for auto-centering stcks hud->downX = hud->touch->x; @@ -179,19 +186,19 @@ touch_t *UpdateHudTouch( ibutton_t *hud ) { // but will instead cause immediate movement. This prevents the main // drawback of the centering controls -- if you pressed down too close // to the side, you wouldn't have full mobility that direction. - int w = hud->drawWidth / 2; - int h = hud->drawHeight / 2; - if ( hud->downX < w ) { - hud->downX = w; + int width = hud->drawWidth / 2; + int height = hud->drawHeight / 2; + if ( hud->downX < width ) { + hud->downX = width; } - if ( hud->downX + w > displaywidth ) { - hud->downX = displaywidth - w; + if ( hud->downX + width > displaywidth ) { + hud->downX = displaywidth - width; } - if ( hud->downY < h ) { - hud->downY = h; + if ( hud->downY < height ) { + hud->downY = height; } - if ( hud->downY > displayheight - h ) { - hud->downY = displayheight - h; + if ( hud->downY > displayheight - height ) { + hud->downY = displayheight - height; } } } @@ -200,7 +207,7 @@ touch_t *UpdateHudTouch( ibutton_t *hud ) { // see if the touch was released if ( !hud->touch->down ) { if ( touchClick->value ) { - Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value ); + Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value ? 0.15f : 0.0f ); } hud->touch = NULL; } @@ -213,11 +220,12 @@ void SetButtonPics( ibutton_t *button, const char *picBase, const char *title, i button->texture = PK_FindTexture( picBase ); button->scale = 1.0f; button->title = title; - button->x = x * ((float)displaywidth) / 480.0f; - button->y = y * ((float)displayheight) / 320.0f; - float xRatio = ((float)displaywidth) / 480.0f; - float yRatio = ((float)displayheight) / 320.0f; + button->x = x * ((float)SCREENWIDTH) / 480.0f; + button->y = y * ((float)SCREENHEIGHT) / 320.0f; + + float xRatio = ((float)SCREENWIDTH) / 480.0f; + float yRatio = ((float)SCREENHEIGHT) / 320.0f; float themin = MIN( xRatio, yRatio ); @@ -228,9 +236,8 @@ void SetButtonPics( ibutton_t *button, const char *picBase, const char *title, i void SetButtonPicsAndSizes( ibutton_t *button, const char *picBase, const char *title, int x, int y, int w, int h ) { SetButtonPics( button, picBase, title, x, y ); - - float xRatio = ((float)displaywidth) / 480.0f; - float yRatio = ((float)displayheight) / 320.0f; + float xRatio = ((float)SCREENWIDTH) / 480.0f; + float yRatio = ((float)SCREENHEIGHT) / 320.0f; float themin = MIN( xRatio, yRatio ); @@ -290,7 +297,7 @@ boolean HandleButton( ibutton_t *button ) { || button->touch->y < button->y || button->touch->y >= button->y + button->drawHeight ) { // dragged outside, don't trigger on release now if ( button->buttonFlags & BF_SMALL_CLICK ) { - Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value ); + Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value ? 0.15f : 0.0f ); } else { Sound_StartLocalSound( "iphone/baborted_01.wav" ); } @@ -303,7 +310,7 @@ boolean HandleButton( ibutton_t *button ) { if ( button->pressed ) { // released inside the button, so do the action if ( button->buttonFlags & BF_SMALL_CLICK ) { - Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value ); + Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value ? 0.15f : 0.0f ); } else { Sound_StartLocalSound( "iphone/baction_01.wav" ); } @@ -327,7 +334,7 @@ boolean HandleButton( ibutton_t *button ) { if ( t->x >= button->x && t->x < button->x + button->drawWidth && t->y >= button->y && t->y < button->y + button->drawHeight ) { if ( button->buttonFlags & BF_SMALL_CLICK ) { - Sound_StartLocalSoundAtVolume( "iphone/controller_down_01_SILENCE.wav", touchClick->value ); + Sound_StartLocalSoundAtVolume( "iphone/controller_down_01_SILENCE.wav", touchClick->value ? 0.15f : 0.0f ); } else { Sound_StartLocalSound( "iphone/bdown_01.wav" ); } @@ -387,34 +394,40 @@ boolean HandleButton( ibutton_t *button ) { glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE ); glTexEnvf( GL_TEXTURE_ENV, GL_RGB_SCALE, 2.0 ); } + PK_StretchTexture( button->texture, button->x+button->drawWidth/2 - button->drawWidth/2 * button->scale, button->y + button->drawHeight/2 - button->drawHeight/2 * button->scale, button->drawWidth * button->scale, button->drawHeight * button->scale ); + if ( button->buttonFlags & BF_GLOW ) { glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glColor4f( 1, 1, 1, 1 ); } - if ( button->title ) { - float length = StringFontWidth( button->title ) * 0.75; - float x = button->x + button->drawWidth/2 - length/2; - // don't push the text off the edge of the screen - if ( x < 0 ) { - x = 0; - } else if ( x + length > displaywidth ) { - x = displaywidth - length; - } - float y; - float textScale = 0.75; - if ( button->buttonFlags & BF_CENTERTEXT ) { - glColor4f( 1, 1, 1, 1 ); // !@# remove when we get a button background that doesn't need dimming - y = button->y + button->drawHeight / 2 + 8; - textScale *= button->scale; // animate text scale when centered - } else { - y = button->y + button->drawHeight + 16; - } - iphoneDrawText( x, y, textScale, button->title ); - } + if ( button->title ) { + float length = StringFontWidth( button->title ) * 0.75; + float x = button->x + button->drawWidth/2 - length*2; + // don't push the text off the edge of the screen + if ( x < 0 ) { + x = 0; + } else if ( x + length > displaywidth ) { + x = displaywidth - length; + } + float y; + float textScale = 0.75; + if ( button->buttonFlags & BF_CENTERTEXT ) { + glColor4f( 1, 1, 1, 1 ); // !@# remove when we get a button background that doesn't need dimming + y = button->y + button->drawHeight / 2 + 8; + textScale *= button->scale; // animate text scale when centered + } else { + y = button->y + button->drawHeight + 16; + } + + textScale *= screenResolutionScale * 2; + + iphoneDrawText( x, y, textScale, button->title ); + } + glColor4f( 1, 1, 1, 1 ); @@ -451,54 +464,58 @@ float StringFontWidth( const char *str ) { ================== */ float iphoneDrawText( float x, float y, float scale, const char *str ) { - - float fx = x; - float fy = y; - PK_BindTexture( arialFontTexture ); - glBegin( GL_QUADS ); - - while ( *str ) { - int i = *str; - if ( i >= ' ' && i < 128 ) { - GlyphRect *glyph = &glyphRects[i-32]; - - // the glyphRects don't include the shadow outline - float x0 = ( glyph->x0 - 1 ) / 256.0; - float y0 = ( glyph->y0 - 1 ) / 256.0; - float x1 = ( glyph->x1 + 2 ) / 256.0; - float y1 = ( glyph->y1 + 2 ) / 256.0; - - float width = ( x1 - x0 ) * 256 * scale; - float height = ( y1 - y0 ) * 256 * scale; - - float xoff = ( glyph->xoff - 1 ) * scale; - float yoff = ( glyph->yoff - 1 ) * scale; - - glTexCoord2f( x0, y0 ); - glVertex2f( fx + xoff, fy + yoff ); - - glTexCoord2f( x1, y0 ); - glVertex2f( fx + xoff + width, fy + yoff ); - - glTexCoord2f( x1, y1 ); - glVertex2f( fx + xoff + width, fy + yoff + height ); - - glTexCoord2f( x0, y1 ); - glVertex2f( fx + xoff, fy + yoff + height ); +float fx = x; +float fy = y; - // with our default texture, the difference is negligable - fx += glyph->xadvance * scale; -// fx += ceil(glyph->xadvance); // with the outline, ceil is probably the right thing - } - str++; - } - - glEnd(); - - return fx - x; +PK_BindTexture( arialFontTexture ); +glBegin( GL_QUADS ); + +while ( *str ) { + int i = *str; + if ( i >= ' ' && i < 128 ) { + GlyphRect *glyph = &glyphRects[i-32]; + + // the glyphRects don't include the shadow outline + float x0 = ( glyph->x0 - 1 ) / 256.0; + float y0 = ( glyph->y0 - 1 ) / 256.0; + float x1 = ( glyph->x1 + 2 ) / 256.0; + float y1 = ( glyph->y1 + 2 ) / 256.0; + + float width = ( x1 - x0 ) * 256 * scale; + float height = ( y1 - y0 ) * 256 * scale; + + float xoff = ( glyph->xoff - 1 ) * scale; + float yoff = ( glyph->yoff - 1 ) * scale; + + // red would be awesome here but it's kinda hard to read +// glColor4f( 1, 0, 0, 1 ); + + glTexCoord2f( x0, y0 ); + glVertex2f( fx + xoff, fy + yoff ); + + glTexCoord2f( x1, y0 ); + glVertex2f( fx + xoff + width, fy + yoff ); + + glTexCoord2f( x1, y1 ); + glVertex2f( fx + xoff + width, fy + yoff + height ); + + glTexCoord2f( x0, y1 ); + glVertex2f( fx + xoff, fy + yoff + height ); + + // with our default texture, the difference is negligable + fx += glyph->xadvance * scale; + // fx += ceil(glyph->xadvance); // with the outline, ceil is probably the right thing + } + str++; +} + +glEnd(); + +return fx - x; } + /* ================== iphoneCenterText @@ -514,7 +531,7 @@ float iphoneCenterText( float x, float y, float scale, const char *str ) { x -= l * scale * 0.5; - return iphoneDrawText( x, y, scale, str ); + return iphoneDrawText( x, y, scale * screenResolutionScale, str ); } @@ -652,23 +669,6 @@ int TouchReleased( int x, int y, int w, int h ) { #endif } -/* - ================== - iphoneRotateForLandscape - - ================== - */ -int iphoneRotateForLandscape() { - if ( revLand->value ) { - // reverse landscape mode - glRotatef( -90, 0, 0, 1 ); - return true; - } else { - glRotatef( 90, 0, 0, 1 ); - } - return false; -} - /* ================== iphoneSet2D @@ -679,7 +679,12 @@ void iphoneSet2D( void ) { // note that GL thinks the iphone is always // in portrait mode as far as the framebuffer // is concerned. - glViewport( 0,0, displayheight, displaywidth ); + int x = 0; + if (displaywidth > SCREENWIDTH) { + x = (displaywidth - SCREENWIDTH) / 2; + } + /* JDS proper fix for landscape orientation */ + glViewport( x,0, displaywidth, displayheight ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glEnable( GL_TEXTURE_2D ); @@ -693,26 +698,9 @@ void iphoneSet2D( void ) { glColor4f( 1,1,1,1 ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); - // now get into the landscape we want - iphoneRotateForLandscape(); glOrthof( 0, displaywidth, displayheight, 0, -99999, 99999 ); } - -void iphoneCheckForLandscapeReverse() { - static int reverseCount; - - // if we stay significantly negative for half a second, flip orientation - if ( tiltPitch < -0.35 ) { - if ( ++reverseCount > 10 ) { - Cvar_SetValue( revLand->name, !revLand->value ); - SysIPhoneSetUIKitOrientation( revLand->value ); - } - } else { - reverseCount = 0; - } -} - void iphoneTiltEvent( float *tilts ) { int i; int j; @@ -721,11 +709,12 @@ void iphoneTiltEvent( float *tilts ) { static float prevTime; // we probably should mutex this, but I doubt it causes any problems - + /* if ( revLand->value ) { tilts[1] = -tilts[1]; tilts[0] = -tilts[0]; } + */ c = tiltAverages->value; if ( c < 1 ) { @@ -818,6 +807,7 @@ void iphoneHighlightPicWhenTouched( pkTexture_t *texture, int x, int y, int w, i } else { glColor4f(1,1,1,0.5); } + PK_StretchTexture( texture, x, y, w, h ); glColor4f(1,1,1,1); } @@ -880,12 +870,12 @@ void iphoneDrawRotorControl( ibutton_t *hud ) { } pkTexture_t *tex = hud->texture; PK_BindTexture( tex ); - - float cx = hud->x + hud->drawWidth / 2; - float cy = hud->y + hud->drawHeight / 2; + + float cx = (hud->x + hud->drawWidth / 2); + float cy = (hud->y + hud->drawHeight / 2); float as = sin( hud->drawState ); float ac = cos( hud->drawState ); - float sz = hud->drawWidth / 2; + float sz = (hud->drawWidth / 2); float xv[2] = { sz*ac, sz*as }; float yv[2] = { -sz*as, sz*ac }; @@ -894,11 +884,18 @@ void iphoneDrawRotorControl( ibutton_t *hud ) { glBegin( GL_TRIANGLE_STRIP ); - glTexCoord2f( 0.0f, 0.0f ); glVertex2f( cx - xv[0] - yv[0], cy - xv[1] - yv[1] ); - glTexCoord2f( tex->textureData->maxS, 0.0f ); glVertex2f( cx + xv[0] - yv[0], cy + xv[1] - yv[1] ); - glTexCoord2f( 0.0f, tex->textureData->maxT ); glVertex2f( cx - xv[0] + yv[0], cy - xv[1] + yv[1] ); - glTexCoord2f( tex->textureData->maxS, tex->textureData->maxT ); glVertex2f( cx + xv[0] + yv[0], cy + xv[1] + yv[1] ); - + glTexCoord2f( 0.0f, 0.0f ); glVertex2f( (cx - xv[0] - yv[0]), (cy - xv[1] - yv[1]) ); + glTexCoord2f( tex->textureData->maxS, 0.0f ); glVertex2f( (cx + xv[0] - yv[0]), (cy + xv[1] - yv[1]) ); + glTexCoord2f( 0.0f, tex->textureData->maxT ); glVertex2f( (cx - xv[0] + yv[0]), (cy - xv[1] + yv[1]) ); + glTexCoord2f( tex->textureData->maxS, tex->textureData->maxT ); glVertex2f( (cx + xv[0] + yv[0]), (cy + xv[1] + yv[1]) ); + + /* + glTexCoord2f( 0.0f, 0.0f ); glVertex2f( cx - xv[0] - yv[0], cy - xv[1] - yv[1] ); + glTexCoord2f( tex->textureData->maxS, 0.0f ); glVertex2f( cx + xv[0] - yv[0], cy + xv[1] - yv[1] ); + glTexCoord2f( 0.0f, tex->textureData->maxT ); glVertex2f( cx - xv[0] + yv[0], cy - xv[1] + yv[1] ); + glTexCoord2f( tex->textureData->maxS, tex->textureData->maxT ); glVertex2f( cx + xv[0] + yv[0], cy + xv[1] + yv[1] ); + */ + glEnd(); } @@ -908,6 +905,11 @@ void iphoneDrawRotorControl( ibutton_t *hud ) { void iphoneDrawHudControl( ibutton_t *hud ) { + + if (TARGET_OS_TV) { + return; + } + if ( hud->buttonFlags & BF_IGNORE ) { return; } @@ -936,6 +938,8 @@ void iphoneDrawHudControl( ibutton_t *hud ) { x = hud->touch->x - w*0.5f; y = hud->touch->y - h*0.5f; } + + PK_StretchTexture( hud->texture, x, y, w, h ); glColor4f(1,1,1,1); } @@ -1105,7 +1109,7 @@ void AutomapControls() { prevY = t->y; } m_x -= ( t->x - prevX ) * (float)m_w / displaywidth; - m_y += ( t->y - prevY ) * (float)m_w / displaywidth; + m_y += ( t->y - prevY ) * (float)m_w / displaywidth; m_x2 = m_x + m_w; m_y2 = m_y + m_h; @@ -1158,13 +1162,11 @@ void SwapBuffersAndTouches() { ShowNet(); ShowSound(); - pthread_mutex_lock( &eventMutex ); for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) { if ( sysTouches[i].down && gameTouches[i].down ) { sysTouches[i].controlOwner = gameTouches[i].controlOwner; } } - pthread_mutex_unlock( &eventMutex ); loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].beforeSwap = SysIphoneMicroseconds(); SysIPhoneSwapBuffers(); @@ -1178,12 +1180,6 @@ void DrawWeapon(int weaponlump, int x, int y, int w, int h, int lightlevel) GLTexture *gltexture; float fU1,fU2,fV1,fV2; int x1,y1,x2,y2; - - if( displaywidth >= 960 ) { - weaponSelectDrawScale = 1.25f; - } else { - weaponSelectDrawScale = 0.75f; - } x *= ((float)displaywidth) / 480.0f; y *= ((float)displayheight) / 320.0f; @@ -1198,7 +1194,7 @@ void DrawWeapon(int weaponlump, int x, int y, int w, int h, int lightlevel) return; float scaledWidth = gltexture->width * weaponSelectDrawScale; - float scaledHeight = gltexture->height * weaponSelectDrawScale; + float scaledHeight = gltexture->height * weaponSelectDrawScale; // JDS Hack // pin the middle bottom of the patch to the middle bottom of // the draw rectangle, then let everything else scale as needed @@ -1270,9 +1266,17 @@ void DrawWeaponSelect() { case wp_shotgun: ammo = player->ammo[am_shell]; break; case wp_chaingun: ammo = player->ammo[am_clip]; break; case wp_missile: ammo = player->ammo[am_misl]; break; + case wp_plasma: ammo = player->ammo[am_cell]; break; + case wp_bfg: ammo = player->ammo[am_cell]; if ( ammo < 40 ) ammo = 0; break; + case wp_supershotgun: ammo = player->ammo[am_shell]; if ( ammo < 2 ) ammo = 0; break; + + + // These cases were here originally - but they feel buggy. + /* case wp_plasma: ammo = player->ammo[wp_plasma]; break; case wp_bfg: ammo = player->ammo[wp_plasma]; if ( ammo < 40 ) ammo = 0; break; case wp_supershotgun: ammo = player->ammo[wp_plasma]; if ( ammo < 2 ) ammo = 0; break; + */ } if ( !player->weaponowned[i] ) { // don't have the weapon @@ -1300,6 +1304,7 @@ void DrawWeaponSelect() { float nw = w * ((float)displaywidth) / 480.0f; float nh = h * ((float)displayheight) / 320.0f; + if ( selectable && TouchDown( nx, ny, nw, nh ) ) { color[0] = 128; color[1] = color[2] = 128; @@ -1346,11 +1351,10 @@ void iphoneFrame() { loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].numGameTics = 0; loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].afterSleep = loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].enterFrame = SysIphoneMicroseconds(); - + //------------------------------------------------- // grabs the console command under mutex. //------------------------------------------------- - pthread_mutex_lock( &eventMutex ); // execute a console command if one was typed if ( consoleCommand[0] ) { @@ -1365,8 +1369,6 @@ void iphoneFrame() { Cmd_ExecuteString( consoleCommand ); consoleCommand[0] = 0; } - - pthread_mutex_unlock( &eventMutex ); // move touches to prevTouches (old style use, remove...) numPrevTouches = numTouches; @@ -1382,9 +1384,6 @@ void iphoneFrame() { numTouches++; } } - - // check for flipping the phone orientation - iphoneCheckForLandscapeReverse(); // go to the next demo if needed if ( advancedemo ) { @@ -1392,6 +1391,7 @@ void iphoneFrame() { // go back to the menu after a timedemo menuState = IPM_MAIN; timeDemoStart = 0; + iphoneMainMenu(); return; } static int demoState; @@ -1399,9 +1399,9 @@ void iphoneFrame() { advancedemo = usergame = paused = false; gameaction = ga_nothing; gamestate = GS_DEMOSCREEN; - static const char *demoNames[4] = { "demo1", "demo2", "demo3", "demo4" }; + static const char *demoNames[3] = { "demo1", "demo2", "demo3" }; G_DeferedPlayDemo( demoNames[demoState] ); - if ( ++demoState == 4 ) { + if ( ++demoState == 3 ) { demoState = 0; } } @@ -1476,17 +1476,29 @@ void iphoneFrame() { stopTic = maketic; if ( consoleplayer != 0 ) { // we are a client, so try to leave a buffer frame - stopTic = maketic - 1; - if ( gametic == stopTic ) { - stopTic++; + static const int COMMAND_BUFFER_SIZE = 1; + + stopTic = maketic - COMMAND_BUFFER_SIZE; + + if ( gametic >= stopTic ) { + // Ideally, clients should run 1 gametic per frame. But if the client is + // waiting on the server to deliver more tics, the client has to stall + // if it runs out of buffered tics. + const int idealTic = gametic + 1; + + if ( idealTic < maketic ) { + stopTic = idealTic; + } else { + stopTic = maketic; + } } - } + } } //--------------------------------- // run game tics //--------------------------------- - while( gametic < stopTic ) { + while( gametic < stopTic ) { // run the gametic with all the player and monster logic // this will extract netcmds[player][gametic%BACKUPTICS] for each player // Com_Printf( "gametic %i\n", gametic ); @@ -1517,11 +1529,13 @@ void iphoneFrame() { // this probably doesn't need to be tic-synced, but it doesn't hurt if (players[displayplayer].mo) { // move positional sounds and free up channels that have completed - S_UpdateSounds(players[displayplayer].mo); - } + //GUS temporarily removed + //S_UpdateSounds(players[displayplayer].mo); + } } } + if ( consoleActive ) { iphoneSet2D(); // FIXME: actually draw a console... @@ -1532,7 +1546,11 @@ void iphoneFrame() { if ( menuState != IPM_GAME ) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); iphoneSet2D(); - iphoneDrawMenus(); + + if ( menuState == IPM_HUDEDIT ) { + HudEditFrame(); + } + SwapBuffersAndTouches(); return; @@ -1544,6 +1562,7 @@ void iphoneFrame() { if ( !usergame && !iphoneTimeDemo ) { if ( numTouches == 0 && numPrevTouches == 1 ) { menuState = IPM_MAIN; + iphoneMainMenu(); } } @@ -1558,14 +1577,14 @@ void iphoneFrame() { // If we just loaded a level, do the texture precaching after we // have drawn and displayed the first frame, so the user has // something to look at while it is loading. - if ( iphoneFrameNum == levelLoadFrameNum + 1 ) { - int start = SysIphoneMilliseconds(); - gld_Precache(); - int end = SysIphoneMilliseconds(); - Com_Printf( "%3.1f seconds to gld_Precache()\n", (end-start)*0.001f ); - timeDemoStart = end; - timeDemoFrames = 0; - } +// if ( false ) { // iphoneFrameNum == levelLoadFrameNum + 1 ) { +// int start = SysIphoneMilliseconds(); +// gld_Precache(); +// int end = SysIphoneMilliseconds(); +// Com_Printf( "%3.1f seconds to gld_Precache()\n", (end-start)*0.001f ); +// timeDemoStart = end; +// timeDemoFrames = 0; +// } } int pacifierCycle; @@ -1580,6 +1599,8 @@ void iphonePacifierUpdate() { } pacifierTime = now; pacifierCycle = ( pacifierCycle + 1 ) & 7; + + // Is this causing a massive slowdown while precaching? iphoneDrawScreen(); } @@ -1595,11 +1616,17 @@ void iphoneDrawScreen() { if ( statusBar->modified ) { statusBar->modified = false; - if ( statusBar->value ) { - R_SetViewSize( 10 ); - } else { - R_SetViewSize( 11 ); - } + if ( statusBar->value ) { + R_SetViewSize( 10 ); + hud_displayed = 0; + hud_active = 0; + hud_distributed = 0; + } else { + R_SetViewSize( 11 ); + hud_displayed = 1; + hud_active = 2; + hud_distributed = 1; + } } //------------------------------------------------ @@ -1632,11 +1659,14 @@ void iphoneDrawScreen() { AutomapControls(); } else if ( iphoneFrameNum == levelLoadFrameNum + 1 ) { // don't draw hud elements during the precache - + color4_t black = { 0, 0, 0, 255 }; + R_Draw_Fill( 0, 0, 480, 320, black ); + + // draw rotating pacifier icon PK_BindTexture( PK_FindTexture( "iphone/loading.tga" ) ); glColor4f( 1, 1, 1, 1 ); - + float cx = 240 * ((float)displaywidth) / 480.0f; float cy = 160 * ((float)displayheight) / 320.0f; float as = sin( pacifierCycle * M_PI / 4 ); @@ -1662,16 +1692,31 @@ void iphoneDrawScreen() { if ( HandleButton( &huds.menu ) ) { iphonePauseMusic(); menuState = IPM_MAIN; + iphoneMainMenu(); } } else if ( !menuactive && !demoplayback && usergame && gamestate == GS_LEVEL ) { if ( players[consoleplayer].playerstate == PST_DEAD ) { // when dead, only show the main menu con and the // respawn / load game icons +#if !TARGET_OS_TV if ( HandleButton( &huds.menu ) ) { iphonePauseMusic(); menuState = IPM_MAIN; + iphoneMainMenu(); } +#endif if ( !deathmatch && !netgame ) { + + // for now we're going to not draw these on the screen for the TV version + // all you can do is respawn with the USE button (A) + +#if TARGET_OS_TV + static ibutton_t btnRespawn; + SetButtonPicsAndSizes( &btnRespawn, "iphone/respawn.tga", "Press A to restart", 240 - 48, 80, 96, 96 ); + if ( HandleButton( &btnRespawn ) ) { +// players[consoleplayer].playerstate = PST_REBORN; + } +#else static ibutton_t btnSaved; static ibutton_t btnRespawn; static ibutton_t btnGear; @@ -1693,6 +1738,7 @@ void iphoneDrawScreen() { players[consoleplayer].playerstate = PST_REBORN; addGear = true; } +#endif } else { static ibutton_t btnNetRespawn; if ( !btnNetRespawn.texture ) { @@ -1715,16 +1761,20 @@ void iphoneDrawScreen() { iphoneDrawRotorControl( &huds.turnRotor ); // iphoneDrawHudControl( &huds.fire ); } - - if ( HandleButton( &huds.menu ) ) { - iphonePauseMusic(); - menuState = IPM_MAIN; - } - if ( HandleButton( &huds.map ) ) { - AM_Start(); - } - if ( HandleButton( &huds.fire ) ) { - } + + if (!TARGET_OS_TV) { + + if ( HandleButton( &huds.menu ) ) { + iphonePauseMusic(); + menuState = IPM_MAIN; + iphoneMainMenu(); + } + if ( HandleButton( &huds.map ) ) { + AM_Start(); + } + if ( HandleButton( &huds.fire ) ) { + } + } if ( netgame ) { #if 0 @@ -1761,14 +1811,17 @@ void iphoneDrawScreen() { iphoneDrawNotifyText(); // not getting network tics - if ( SysIphoneMilliseconds() - lastGameProcessedTime > 500 ) { + const int timeSinceLastProcessed = SysIphoneMilliseconds() - lastGameProcessedTime; + if ( timeSinceLastProcessed > 800 ) { // Origianlly was 500, let's be a little more lenient for internet play. PK_StretchTexture( PK_FindTexture("iphone/multiplay.tga"), 240 - 96/2, 90, 96, 96 ); } // draw the little graph in the upper right corner +#ifndef NDEBUG if ( netgame ) { ShowMiniNet(); } +#endif } } diff --git a/code/iphone/iphone_main.c b/code/iphone/iphone_main.c old mode 100644 new mode 100755 index 8fc2947..6f89b99 --- a/code/iphone/iphone_main.c +++ b/code/iphone/iphone_main.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2004-2005 Michael Liebscher Copyright (C) 1997-2001 Id Software, Inc. @@ -190,9 +190,9 @@ static JDC removed short consistancy[MAXPLAYERS][BACKUPTICS]; */ -#include "../doomiphone.h" - +#include "doomiphone.h" +cvar_t *freeLevelOfWeek; cvar_t *skill; cvar_t *episode; cvar_t *controlScheme; @@ -211,7 +211,6 @@ cvar_t *showTime; cvar_t *showNet; cvar_t *showSound; cvar_t *cropSprites; -cvar_t *revLand; cvar_t *mapScale; cvar_t *drawControls; cvar_t *autoUse; @@ -225,6 +224,7 @@ cvar_t *mpSkill; cvar_t *mpDataset; cvar_t *mpEpisode; cvar_t *mpMap; +cvar_t *mpExpansion; cvar_t *noBlend; cvar_t *glfinish; cvar_t *mapSelectY; @@ -232,6 +232,11 @@ cvar_t *throttle; cvar_t *centerSticks; cvar_t *rampTurn; cvar_t *netBuffer; +cvar_t *iwadSelection; +cvar_t *pwadSelection; + +char* doom_iwad; +char* doom_pwads = ""; #define VERSION_BCONFIG ( 0x89490000 + sizeof( huds ) + sizeof( playState ) ) @@ -303,12 +308,9 @@ void ResetMaps_f() { */ struct addrinfo *addrinfoHead; -void D_DoomMainSetup(); +void D_DoomMainSetup( const char * iwad, const char * pwad ); void iphoneStartup() { int start = SysIphoneMilliseconds(); - - // print networking information - ReportNetworkInterfaces(); // microseconds will be plenty random for playerID and localGameID playerID = localGameID = SysIphoneMicroseconds(); @@ -319,10 +321,10 @@ void iphoneStartup() { // make all the al static buffers Sound_Init(); + char buffer[1028]; + sprintf( buffer, "%s/base.iPack", SysIphoneGetAppDir() ); // get our new-style pak file - char pakFile[1024]; - sprintf( pakFile, "%s/base/base.iPack", SysIphoneGetAppDir() ); - PK_Init( pakFile ); + PK_Init( buffer ); // register console commands Cmd_AddCommand( "listcvars", Cvar_List_f ); @@ -335,7 +337,8 @@ void iphoneStartup() { // register console variables Cvar_Get( "version", va( "%3.1f %s %s", DOOM_IPHONE_VERSION, __DATE__, __TIME__ ), 0 ); - + + freeLevelOfWeek = Cvar_Get("freeLevelOfWeek", "0", 0 ); skill = Cvar_Get( "skill", "1", CVAR_ARCHIVE ); episode = Cvar_Get( "episode", "0", CVAR_ARCHIVE ); @@ -353,12 +356,11 @@ void iphoneStartup() { music = Cvar_Get( "music", "1", CVAR_ARCHIVE ); cropSprites = Cvar_Get( "cropSprites", "1", 0 ); - revLand = Cvar_Get( "revLand", "0", CVAR_ARCHIVE ); mapScale = Cvar_Get( "mapScale", "10", CVAR_ARCHIVE ); drawControls = Cvar_Get( "drawControls", "1", CVAR_ARCHIVE ); autoUse = Cvar_Get( "autoUse", "1", CVAR_ARCHIVE ); statusBar = Cvar_Get( "statusBar", "1", CVAR_ARCHIVE ); - touchClick = Cvar_Get( "touchClick", "0.15", CVAR_ARCHIVE ); + touchClick = Cvar_Get( "touchClick", "1", CVAR_ARCHIVE ); messages = Cvar_Get( "messages", "1", CVAR_ARCHIVE ); mapSelectY = Cvar_Get( "mapSelectY", "0", CVAR_ARCHIVE ); miniNet = Cvar_Get( "miniNet", "1", CVAR_ARCHIVE ); @@ -371,7 +373,12 @@ void iphoneStartup() { mpEpisode = Cvar_Get( "mpEpisode", "1", CVAR_ARCHIVE ); mpSkill = Cvar_Get( "mpSkill", "1", CVAR_ARCHIVE ); mpMap = Cvar_Get( "mpMap", "1", CVAR_ARCHIVE ); + mpExpansion = Cvar_Get( "mpExpansion", "0", CVAR_ARCHIVE | CVAR_NOSET ); + // WADs to load + iwadSelection = Cvar_Get( "iwadSelection", "doom.wad", CVAR_ARCHIVE ); + pwadSelection = Cvar_Get( "pwadSelection", "", CVAR_ARCHIVE ); + // debug tools showTilt = Cvar_Get( "showTilt", "-1", 0 ); showTime = Cvar_Get( "showTime", "0", 0 ); @@ -379,15 +386,36 @@ void iphoneStartup() { showSound = Cvar_Get( "showSound", "0", 0 ); noBlend = Cvar_Get( "noBlend", "0", 0 ); // disable the damae blends for screenshots glfinish = Cvar_Get( "glfinish", "0", 0 ); - throttle = Cvar_Get( "throttle", "1", 0 ); // network packet throttle enable - netBuffer = Cvar_Get( "netBuffer", "4", 0 ); // max tics to buffer ahead + throttle = Cvar_Get( "throttle", "0", 0 ); // network packet throttle enable + + // Was origiinally 4. Trying different values to help internet play. + netBuffer = Cvar_Get( "netBuffer", "12", 0 ); // max tics to buffer ahead // load the archived cvars Cmd_ExecuteFile( va( "%s/config.cfg", SysIphoneGetDocDir() ) ); - // make sure volume changes and incoming calls draw the right orientation - SysIPhoneSetUIKitOrientation( revLand->value ); - + // Check if our WADs were bad last time. + { + FILE *fp; + char path[1024]; + snprintf( path, sizeof( path ), "%s/abandon.ship", SysIphoneGetDocDir() ); + fp = fopen( path, "r" ); + if( fp ) { + Com_Printf("Last exit was fatal (ship abandoned). Recovering...\n"); + + Cvar_Set( "iwadSelection", "doom.wad" ); + Cvar_Set( "pwadSelection", "" ); + + iwadSelection = Cvar_Get( "iwadSelection", "doom.wad", CVAR_ARCHIVE ); + pwadSelection = Cvar_Get( "pwadSelection", "", CVAR_ARCHIVE ); + + // remove canary + if( remove(path) != 0 ) { + Com_Printf("Could not remove canary. This is bad!\n"); + } + } + } + // start the intro music if it wasn't disabled with the music cvar iphonePlayMusic( "intro" ); // iphonePlayMusic( "e1m1" ); @@ -402,7 +430,7 @@ void iphoneStartup() { // load the binary config file FILE *f = fopen( va( "%s/binaryConfig.bin", SysIphoneGetDocDir() ), "rb" ); if ( f ) { - int version; + long int version; version = 0; fread( &version, 1, sizeof( version ), f ); @@ -410,7 +438,11 @@ void iphoneStartup() { Com_Printf( "Binary config file bad version.\n" ); } else { fread( &playState, 1, sizeof( playState ), f ); - fread( &huds, 1, sizeof( huds ), f ); + + fread( &huds, 1, sizeof( huds ), f ); + + //hud_t fakehuds; + //fread( &fakehuds, 1, sizeof(fakehuds), f ); version = 0; fread( &version, 1, sizeof( version ), f ); @@ -420,7 +452,6 @@ void iphoneStartup() { } fclose( f ); } - Com_Printf( "startup time: %i msec\n", SysIphoneMilliseconds() - start ); @@ -433,12 +464,6 @@ void iphoneStartup() { Com_Printf( "preloadBeforePlay(): %i msec\n", SysIphoneMilliseconds() - start ); - Com_Printf( "---------- D_DoomMain ----------\n" ); - D_DoomMainSetup(); - - // put savegames here - strcpy( basesavegame, SysIphoneGetDocDir() ); - // prBoom seems to draw the static pic screens without setting up 2D, causing // a bad first frame iphoneSet2D(); @@ -452,6 +477,222 @@ void iphoneStartup() { #endif } +/* + ================== + iphoneWadSelect + + Apply WAD file selection + ================== +*/ +void iphoneIWADSelect( const char* iwad ) { + char full_iwad[1024]; + + I_FindFile( iwad, ".wad", full_iwad ); + + if( full_iwad[0] == '\0' ) { + // fall back to vanilla Doom IWAD. + + I_FindFile( "doom.wad", ".wad", full_iwad ); + iwad = "doom.wad"; + } + + if( doom_iwad ) free(doom_iwad); + + // IWAD is part of bundle, do NOT store + doom_iwad = strdup( iwad ); +} + +/* + ================== + iphonePWADAdd + + Add a PWAD file selection + ================== + */ +void iphonePWADAdd( const char* pwad ) { + + char full_pwad[1024]; + + I_FindFile( pwad, ".wad", full_pwad ); + + if( full_pwad[0] != '\0' && strcmp( pwad, "" ) != 0 ) { + // +2, 1 for separator and 1 for null terminator + char* pwadlist = (char*)malloc( sizeof(char)*(strlen(doom_pwads)+strlen(full_pwad)+2) ); + strcpy( pwadlist, doom_pwads); + strcat( pwadlist, full_pwad); + unsigned long len = strlen(pwadlist); + pwadlist[len] = PWAD_LIST_SEPARATOR; + pwadlist[len+1] = '\0'; + //if( doom_pwads ) free(doom_pwads); + doom_pwads = pwadlist; + Com_Printf("Added PWAD: %s (%s)\n", pwad, doom_pwads); + } else { + Com_Printf("Failed to add PWAD: %s (%s)\n", pwad, doom_pwads); + } + +} + +/* + ================== + iphonePWADRemove + + Remove a PWAD from the current selection + ================== + */ +void iphonePWADRemove( const char* pwad ) { + char full_pwad[1024]; + + I_FindFile( pwad, ".wad", full_pwad ); + + char* pwadloc_start = strstr( doom_pwads, full_pwad ); + char* pwadloc_end = strchr( pwadloc_start, PWAD_LIST_SEPARATOR ); + + // if this is the only PWAD... + if( pwadloc_start == doom_pwads && pwadloc_end == (doom_pwads + (strlen(doom_pwads) - 1)) ) { + if( doom_pwads ) free(doom_pwads); + doom_pwads = strdup(""); + Com_Printf("Removed only PWAD: %s (%s)\n", pwad, doom_pwads); + } else if( pwadloc_start && pwadloc_end && full_pwad[0] != '\0' && strcmp( pwad, "" ) != 0 ) { + + // remove pwad and its separator, hence +1 + unsigned long i = 0; + unsigned long pwadlist_len = (strlen(doom_pwads)-(strlen(full_pwad)+1) ); + char* pwadlist = (char*)malloc( sizeof(char)*pwadlist_len ); + + char* pwadlocal = doom_pwads; + + + while( pwadlocal != pwadloc_start && i < pwadlist_len ) { + pwadlist[i++] = *pwadlocal++; + } + + pwadlocal = pwadloc_end+1; // advance past the separator + while( *pwadlocal && i < pwadlist_len ) { + pwadlist[i++] = *pwadlocal++; + } + + pwadlist[i] = '\0'; + + if( doom_pwads ) free(doom_pwads); + doom_pwads = pwadlist; + Com_Printf("Removed PWAD: %s (%s)\n", pwad, doom_pwads); + } else { + Com_Printf("Failed to remove PWAD: %s (%X,%X %s)\n", pwad,pwadloc_start,pwadloc_end,doom_pwads); + } +} + +/* + ================== + iphoneClearPWADs + + Remove all PWADs from the current selection + ================== + */ +void iphoneClearPWADs() { + //if( doom_pwads ) free(doom_pwads); + doom_pwads = strdup(""); +} + +/* + ================== + iphoneSanitizePWADs + + Ensure all PWADs from the current selection actually exist. + Useful when resuming from shutdown and checking for changed paths. + ================== + */ +void iphoneSanitizePWADs() { + if( strlen(doom_pwads) == 0 ) return; + char* pwad_local = strdup(doom_pwads); + if(!pwad_local) return; + + char* pwad_final = (char*)malloc( sizeof(char)*(1+strlen(doom_pwads))); + if(!pwad_final) { + free(pwad_local); + return; + } + + pwad_final[0] = '\0'; // start with blank string + char delim[2] = { PWAD_LIST_SEPARATOR, '\0' }; + char* pwad = strtok(pwad_local, delim ); + + while( pwad != NULL ) { + char pwad_path[1024] = { 0 }; + char pwad_doc_path[1024]; + char* pwad_file = strrchr(pwad,'/'); + + if( pwad_file && *pwad_file ) { + pwad_file++; + strcpy( pwad_doc_path, SysIphoneGetDocDir() ); + strcat( pwad_doc_path, "/" ); + strcat( pwad_doc_path, pwad_file ); + I_FindFile(pwad_doc_path,".wad",pwad_path); + + // try the app dir + if( !*pwad_path ) { + strcpy( pwad_doc_path, SysIphoneGetAppDir() ); + strcat( pwad_doc_path, "/" ); + strcat( pwad_doc_path, pwad_file ); + I_FindFile(pwad_doc_path,".wad",pwad_path); + } + } + + if( *pwad_path ) { + // keep this pwad + strcat(pwad_final, pwad_path); + strcat(pwad_final, delim); + Com_Printf("PWAD Retained: %s\n", pwad); + } else { + Com_Printf("PWAD Lost: %s\n", pwad); + } + + pwad = strtok( NULL, delim ); + } + + if( doom_pwads ) free(doom_pwads); + doom_pwads = pwad_final; + free(pwad_local); +} + +/* + ================== + iphoneDoomSetup + + Run the Doom game setup functions. This was made seperate from iphoneStartup so that the user + could select a mission pack first. + ================== + */ +void iphoneDoomStartup() { + Com_Printf( "---------- D_DoomMain ----------\n" ); + + char full_iwad[1024]; + + I_FindFile( doom_iwad, ".wad", full_iwad ); + + if( full_iwad[0] == '\0' ) { + // fall back to vanilla Doom IWAD. + + I_FindFile( "doom.wad", ".wad", full_iwad ); + } + + iphoneSanitizePWADs(); + + D_DoomMainSetup( full_iwad, doom_pwads ); + + // upon successful setup, save CVARs for future use + // ensure we never save a NULL string (this should never happen) + if( doom_pwads == NULL ) { + doom_pwads = strdup(""); + } + + Cvar_Set( "iwadSelection", doom_iwad ); + Cvar_Set( "pwadSelection", doom_pwads ); + + // put savegames here + strcpy( basesavegame, SysIphoneGetDocDir() ); + +} + /* ================== iphoneShutdown @@ -465,7 +706,7 @@ void iphoneShutdown() { cvar_t *var; char buffer[1024]; - if( lastState == IPM_GAME ) { + if( lastState == IPM_GAME && gamestate != GS_INTERMISSION && !demoplayback ) { G_DoSaveGame( false ); } @@ -496,7 +737,7 @@ void iphoneShutdown() { return; } - int version = VERSION_BCONFIG; + long int version = VERSION_BCONFIG; fwrite( &version, 1, sizeof( version ), f ); diff --git a/code/iphone/iphone_mapSelect.c b/code/iphone/iphone_mapSelect.c old mode 100644 new mode 100755 index a574fad..9d7ff90 --- a/code/iphone/iphone_mapSelect.c +++ b/code/iphone/iphone_mapSelect.c @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * iphone_mapSelect.c + * doom + * + * Created by John Carmack on 4/19/09. + * Copyright 2009 id Software. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -19,7 +27,7 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" typedef struct { int dataset; @@ -186,10 +194,10 @@ mapData_t mapData[] = { happen when people have an absurd number of downloaded levels. =================== */ -mapStats_t *FindMapStats( int dataset, int episode, int map, boolean create ) { +mapStats_t *FindMapStats( int dataset, int theEpisode, int map, boolean create ) { for ( int i = 0 ; i < playState.numMapStats ; i++ ) { mapStats_t *ms = &playState.mapStats[i]; - if ( ms->dataset == dataset && ms->episode == episode && ms->map == map ) { + if ( ms->dataset == dataset && ms->episode == theEpisode && ms->map == map ) { return ms; } } @@ -203,7 +211,7 @@ mapStats_t *FindMapStats( int dataset, int episode, int map, boolean create ) { } mapStats_t *cms = &playState.mapStats[playState.numMapStats]; cms->dataset = dataset; - cms->episode = episode; + cms->episode = theEpisode; cms->map = map; playState.numMapStats++; @@ -217,219 +225,12 @@ mapStats_t *FindMapStats( int dataset, int episode, int map, boolean create ) { episodes and maps are one base ================== */ -const char *FindMapName( int dataset, int episode, int map ) { +const char *FindMapName( int dataset, int theEpisode, int map ) { for ( mapData_t *md = mapData ; md->name ; md++ ) { - if ( md->dataset == dataset && md->episode == episode && md->map == map ) { + if ( md->dataset == dataset && md->episode == theEpisode && md->map == map ) { return md->name; } } return "UNKNOWN MAP NAME"; } - -/* - ================== - iphoneMapSelectMenu - - Skills are zero based: - sk_baby=0, - sk_easy, - sk_medium, - sk_hard, - sk_nightmare=4 - - episodes are one base - - ================== - */ -static const int MAP_ROW_HEIGHT = 52; -ibutton_t btnSkills[4]; -int dragVelocity; -ibutton_t dragScroll; -mapData_t *selectedMap; -int totalDrag; // for determining if a release will activate the level -boolean iphoneMapSelectMenu( mapStart_t *map ) { - static int prevDragY; - - if ( !dragScroll.x ) { - // first initialization - dragScroll.drawWidth = 480 - 80 - 64; - dragScroll.drawHeight = 320; - dragScroll.x = 64 + dragScroll.drawWidth / 2; - dragScroll.y = 160; - - static char * skillNames[4] = { - "iphone/skill_easy.tga", - "iphone/skill_normal.tga", - "iphone/skill_hard.tga", - "iphone/skill_nightmare.tga" }; // not really "nightmare" skill since easy is "baby" - for ( int i = 0 ; i < 4 ; i++ ) { - SetButtonPics( &btnSkills[i], skillNames[i], "", 400, i*80 ); - } - } - - // check for drag-scrolling - if ( dragScroll.touch ) { - if ( dragScroll.touch->y != prevDragY ) { - dragVelocity = dragScroll.touch->y - prevDragY; - prevDragY = dragScroll.touch->y; - totalDrag += abs( dragVelocity ); - } - } - Cvar_SetValue( mapSelectY->name, mapSelectY->value - dragVelocity ); - - // decay the dragVelocity - for ( int i = 0 ; i < 2 ; i++ ) { - if ( dragVelocity < 0 ) { - dragVelocity++; - } else if ( dragVelocity > 0 ) { - dragVelocity--; - } - } - - int iskill = (int)skill->value; - if ( iskill < 0 ) { - iskill = 0; - Cvar_SetValue( skill->name, iskill ); - } else if ( iskill >= MAX_SKILLS ) { - iskill = MAX_SKILLS-1; - Cvar_SetValue( skill->name, iskill ); - } - - // snap back to bounds if dragging past end - if ( mapSelectY->value < 0 ) { - Cvar_SetValue( mapSelectY->name, 0 ); - } - int numMaps = 0; - for ( mapData_t *map = mapData ; map->name != NULL ; map++ ) { - numMaps++; - } - if ( mapSelectY->value > numMaps * MAP_ROW_HEIGHT - 320 ) { - Cvar_SetValue( mapSelectY->name, numMaps * MAP_ROW_HEIGHT - 320 ); - } - - // scrolling display of levels - int y = -mapSelectY->value; - mapData_t *startMap = NULL; - for ( mapData_t *map = mapData ; map->name != NULL ; map++ ) { - if ( y > -64 && y < 320 ) { - // find the mapStat_t for this map, if it has ever been started - int completionFlags = 0; - mapStats_t *ms = FindMapStats( map->dataset, map->episode, map->map, false ); - if ( ms ) { - completionFlags = ms->completionFlags[iskill]; - } - - // if we aren't already dragging, check for a touch on a map button - if ( !dragScroll.touch ) { - touch_t *touch = TouchInBounds( 120, y, 400-128, 48 ); - if ( touch ) { - Sound_StartLocalSound( "iphone/bdown_01.wav" ); - dragScroll.touch = touch; - prevDragY = touch->y; - touch->controlOwner = &dragScroll; - selectedMap = map; - } - } - - // color background based on selected / entered / completed state - if ( selectedMap == map ) { - glColor4f( 1,1,1,1 ); // launch if released - } else if ( completionFlags & MF_COMPLETED ) { - glColor4f( 0.2, 0.5, 0.2, 1 ); - } else if ( completionFlags & MF_TRIED ) { - glColor4f( 0.5, 0.2, 0.2, 1 ); - } else { - glColor4f( 0.4, 0.4, 0.4, 1 ); - } - - // use -1 x to avoid a texture wrap seam - PK_StretchTexture( PK_FindTexture( "iphone/long_string_box.tga" ), 110, y, 400-114, 48 ); - glColor4f( 1,1,1,1 ); - - // draw the text - float w = StringFontWidth( map->name ); - float fontScale = 0.75; - if ( w > 360 ) { - fontScale *= ( 360 / w ); - } - iphoneDrawText( 120, y+32, fontScale, map->name ); - - // add the awards - if ( completionFlags & MF_KILLS ) { - PK_DrawTexture( PK_FindTexture( "iphone/kills.tga" ), 80, y+4 ); - } - if ( completionFlags & MF_TIME ) { - PK_DrawTexture( PK_FindTexture( "iphone/par.tga" ), 40, y+4 ); - } - if ( completionFlags & MF_SECRETS ) { - PK_DrawTexture( PK_FindTexture( "iphone/secrets.tga" ), 0, y+4 ); - } - - } - y += MAP_ROW_HEIGHT; - } - - if ( numTouches == 0 ) { - totalDrag = 0; - } - - // draw the skill level - for ( int i = 0 ; i < 4 ; i++ ) { - if ( i == iskill ) { - btnSkills[i].buttonFlags = 0; - } else { - btnSkills[i].buttonFlags = BF_DIMMED; - } - if ( HandleButton( &btnSkills[i] ) ) { - Cvar_SetValue( skill->name, i ); - } - } - glColor4f( 1, 1, 1, 1 ); - - // handle back button before checking for touches in the awards area - if ( BackButton() ) { - map->map = -1; - return true; - } - - // if we aren't already dragging, check for a touch anywhere outside the skill buttons - if ( !dragScroll.touch ) { - touch_t *touch = TouchInBounds( 0, 0, 400-128, 320 ); - if ( touch ) { - dragScroll.touch = touch; - prevDragY = touch->y; - touch->controlOwner = &dragScroll; - selectedMap = NULL; - Sound_StartLocalSoundAtVolume( "iphone/controller_down_01_SILENCE.wav", touchClick->value ); - } - } else { - // if we dragged more than a few pixels, don't launch the level - if ( totalDrag > 8 ) { - selectedMap = NULL; - } - if ( !dragScroll.touch->down ) { - // lifted finger - dragScroll.touch = NULL; - if ( selectedMap ) { - Sound_StartLocalSound( "iphone/baction_01.wav" ); - startMap = selectedMap; - selectedMap = NULL; - } else { - Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value ); - } - } - } - - - if ( !startMap ) { - return false; - } - - map->skill = iskill; - map->episode = startMap->episode; - map->map = startMap->map; - map->dataset = startMap->dataset; - - return true; -} diff --git a/code/iphone/iphone_menus.c b/code/iphone/iphone_menus.c deleted file mode 100644 index a226c42..0000000 --- a/code/iphone/iphone_menus.c +++ /dev/null @@ -1,912 +0,0 @@ -/* - - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. - Copyright (C) 2009 Id Software, Inc. - - 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 "IBGlue.h" -#include "../doomiphone.h" - - -// Only one game can be set up at a time on a given wireless segment, although -// several independent games can be played. -// If a valid setupPacket has arrived in the last second, that will be the -// displayed game, otherwise the local system starts sending out setupPackets. -packetSetup_t setupPacket; -int setupPacketFrameNum; -int localGameID; // change every time we take over as the sender of setupPackets - -boolean levelHasBeenLoaded; // determines if "resume game" does a loadGame and exiting does a saveGame - -menuState_t menuState; -menuState_t lastState = 0; -color4_t highlightColor = { 128, 128, 128, 255 }; -color4_t colorPressed = { 128, 128, 0, 255 }; - -void SetupEmptyNetGame(); - -void R_Draw_Blend( int x, int y, int w, int h, color4_t c ) { - - x *= ((float)displaywidth) / 480.0f; - y *= ((float)displayheight) / 320.0f; - w *= ((float)displaywidth) / 480.0f; - h *= ((float)displayheight) / 320.0f; - - glDisable( GL_TEXTURE_2D ); - glColor4ubv( c ); - - glBegin( GL_QUADS ); - - glVertex2i( x, y ); - glVertex2i( x+w, y ); - glVertex2i( x+w, y+h ); - glVertex2i( x, y+h ); - - glEnd(); - - glColor3f( 1, 1, 1 ); - glEnable( GL_TEXTURE_2D ); -} - - -void R_Draw_Fill( int x, int y, int w, int h, color3_t c ) { - // as of 2.2 OS, doing a clear with a small scissor rect is MUCH slower - // than drawing geometry - color4_t c4; - c4[0] = c[0]; - c4[1] = c[1]; - c4[2] = c[2]; - c4[3] = 255; - R_Draw_Blend( x, y, w, h, c4 ); -} - -/* - ================== - iphoneSlider - - Returns true if modified - ================== - */ -#define SF_DISABLED 1 // grey out, don't respond to touches -#define SF_INTEGER 2 // don't add percent -boolean iphoneSlider( int x, int y, int w, int h, const char *title, cvar_t *cvar, - float min, float max, int sliderFlags ) { - - float textX = x; - float textY = y; - float textW = w; - float textH = h; - - x *= ((float)displaywidth) / 480.0f; - y *= ((float)displayheight) / 320.0f; - w *= ((float)displaywidth) / 480.0f; - h *= ((float)displayheight) / 320.0f; - - float value = cvar->value; - char str[80]; - float f = ( value - min ) / ( max - min ); - - if ( f < 0 ) { - f = 0; - } - if ( f > 1 ) { - f = 1; - } - - // draw the background - PK_StretchTexture( PK_FindTexture( "iphone/slider_shadow.tga" ), x, y, w, h ); - - // draw the current range - PK_BindTexture( PK_FindTexture( "iphone/slider_bar.tga" ) ); -#if 0 - // proportional - glBegin( GL_QUADS ); - - glTexCoord2f( 0.0f, 0.0f ); glVertex2i( x, y ); - glTexCoord2f( f, 0.0f ); glVertex2i( x+w*f, y ); - glTexCoord2f( f, 1.0f ); glVertex2i( x+w*f, y+h ); - glTexCoord2f( 0.0f, 1.0f ); glVertex2i( x, y+h ); - - glEnd(); -#else - // dragging thumb - glBegin( GL_QUADS ); - - glTexCoord2f( 0.0f, 0.0f ); glVertex2i( x+w*f-8, y ); - glTexCoord2f( 1.0f, 0.0f ); glVertex2i( x+w*f+8, y ); - glTexCoord2f( 1.0f, 1.0f ); glVertex2i( x+w*f+8, y+h ); - glTexCoord2f( 0.0f, 1.0f ); glVertex2i( x+w*f-8, y+h ); - - glEnd(); -#endif - - // draw the title and fraction - if ( sliderFlags & SF_INTEGER ) { - sprintf( str, "%s : %i", title, (int)value ); - } else { - sprintf( str, "%s : %i%%", title, (int)(f*100+0.5) ); - } - iphoneCenterText( textX+ textW/2, textY+textH-10, 0.75, str ); - - // check for touches - if ( numTouches > 0 && touches[0][0] >= x && touches[0][0] < x + w - && touches[0][1] >= y && touches[0][1] < y+ h ) { - float newValue; - float delta; - - f = (float)( touches[0][0] - x ) / w; - - if ( sliderFlags & SF_INTEGER ) { - newValue = rint( min + f * ( max - min ) ); - } else { - // round to tenths - f = (int)( ( f + 0.05 ) * 10 ) * 0.1f; - if ( f < 0 ) { - f = 0; - } - if ( f > 1.0 ) { - f = 1.0; - } - newValue = min + f * ( max - min ); - } - - delta = fabs( newValue - cvar->value ); - if ( f == 0 && cvar->value == 0 ) { - // special case of disable-at-0 - } else if ( delta > 0.01 ) { - Cvar_SetValue( cvar->name, newValue ); - Sound_StartLocalSound( "iphone/slide_01.wav" ); - return true; - } - return false; - } - - return false; -} - -/* - ================== - BackButton - - ================== - */ -ibutton_t btnBack; -int BackButton() { - if ( !btnBack.texture ) { - SetButtonPicsAndSizes( &btnBack, "iphone/back_button.tga", "", 0, 0, 48, 48 ); - } - return HandleButton( &btnBack ); -} - -void GetMoreLevels( int x, int y ) { - // directly to the app store for more levels - SysIPhoneOpenURL( "http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=304694876" ); -} - - -/* - ================== - iphoneMainMenu - - ================== - */ -ibutton_t btnResumeGame; -ibutton_t btnNewGame; -ibutton_t btnControls; -ibutton_t btnMultiplayer; -ibutton_t btnWWW; -ibutton_t btnDemo; - -void iphoneMainMenu() { - - // MAIN MENU IS Driven Through Interface Builder. ( Makes for Rapid ProtoTyping ) -} - - -/* - ================== - iphoneControlMenu - - ================== - */ -ibutton_t btnSchemes[4]; -ibutton_t btnSettings; -ibutton_t btnMove; - -void iphoneControlMenu() { - int i; - -// iphoneCenterText( 240, 16, 0.75, __DATE__" "__TIME__ ); - - // 112 units between - - if ( BackButton() ) { - menuState = IPM_MAIN; - } - if ( NewTextButton( &btnSettings, "Settings", 480-128, 0, 128, 48 ) ) { - menuState = IPM_OPTIONS; - } - if ( NewTextButton( &btnMove, "Move Controls", 48 + (480-(128+160+48))/2, 0, 160, 48 ) ) { - menuState = IPM_HUDEDIT; - lastState = IPM_MAIN; - } - - if ( !btnSchemes[0].texture ) { - for ( int i = 0 ; i < 3 ; i++ ) { - SetButtonPicsAndSizes( &btnSchemes[i], va("iphone/config_%i.tga",i+1), "", - 32 + (96+64) * i, 48 + ( 112 - 64 )*0.5, 96, 64 ); - } - } - - for ( i = 0 ; i < 3 ; i++ ) { - char str[128]; - sprintf( str, "iphone/config_%i.tga", i+1 ); - if ( i != controlScheme->value ) { - btnSchemes[i].buttonFlags = BF_DIMMED; - } else { - btnSchemes[i].buttonFlags = 0; - } - if ( HandleButton( &btnSchemes[i] ) ) { - Cvar_SetValue( controlScheme->name, i ); - HudSetForScheme( i ); - } - } - - iphoneSlider( 20, 160, 440, 40, "Move stick size", stickMove, 64, 128, 0 ); - iphoneSlider( 20, 210, 440, 40, "Turn stick size", stickTurn, 64, 128, 0 ); - - iphoneSlider( 20, 260, 440, 40, "Tilt move speed", tiltMove, 100, 300, 0 ); - if ( tiltMove->value == 100 ) { - Cvar_SetValue( tiltMove->name, 0 ); - } - if ( tiltMove->value ) { - Cvar_SetValue( tiltTurn->name, 0 ); - } -#if 0 - iphoneSlider( 20, 280, 440, 40, "Tilt turn speed", tiltTurn, 1500, 3500, 0 ); - if ( tiltTurn->value == 1500 ) { - Cvar_SetValue( tiltTurn->name, 0 ); - } - if ( tiltTurn->value ) { - Cvar_SetValue( tiltMove->name, 0 ); - } -#endif -} - - -void SetupEmptyNetGame() { - Com_Printf( "SetupEmptyNetGame()\n" ); - // no current setup packet, so initialize with this phone's default values - localGameID = SysIphoneMicroseconds(); - memset( &setupPacket, 0, sizeof( setupPacket ) ); - setupPacket.gameID = localGameID; - setupPacket.packetType = PACKET_VERSION_SETUP; - setupPacket.map.dataset = mpDataset->value; - setupPacket.map.episode = mpEpisode->value; - setupPacket.map.map = mpMap->value; - setupPacket.map.skill = mpSkill->value; - setupPacket.deathmatch = mpDeathmatch->value; - setupPacket.timelimit = timeLimit->value; - setupPacket.fraglimit = fragLimit->value; - setupPacket.playerID[0] = playerID; -} - -/* - ================== - SendJoinPacket - - These will be sent to the server ever frame we are in the multiplayer menu. - ================== - */ -void SendJoinPacket() { - packetJoin_t pj; - - pj.packetType = PACKET_VERSION_JOIN; - pj.gameID = setupPacket.gameID; - pj.playerID = playerID; - - int r = sendto( gameSocket, &pj, sizeof( pj ), 0, - &netServer.address, sizeof( netServer.address ) ); - if ( r == -1 ) { - struct sockaddr_in *addr = (struct sockaddr_in *)&netServer.address; - byte *ip = (byte *)&addr->sin_addr; - Com_Printf( "UDP sendTo %i.%i.%i.%i failed: %s\n", - ip[0], ip[1], ip[2], ip[3], strerror( errno ) ); - close( gameSocket ); - gameSocket = -1; - } -} - -/* - ================== - iphoneMultiplayerMenu - - ================== - */ -ibutton_t btnCoop; -ibutton_t btnDeathmatch; -ibutton_t btnMap; -ibutton_t btnNetSettings; -typedef enum { - NM_MAIN, - NM_MAP_SELECT, - NM_OPTIONS -} netMenu_t; -netMenu_t netMenu; - -void iphoneMultiplayerMenu() { - if ( gameSocket <= 0 ) { - // no socket, so no multiplayer - TerminateGameService(); // don't advertise for any more new players - setupPacket.gameID = 0; // stop sending packets - menuState = IPM_MAIN; - return; - } - - boolean server = ( setupPacket.gameID == localGameID ); - - // different screen when selecting a map to play - if ( netMenu == NM_MAP_SELECT ) { - mapStart_t map; - if ( !iphoneMapSelectMenu( &map ) ) { - // haven't selected anything yet - return; - } - netMenu = NM_MAIN; - if ( map.map != -1 ) { - // selected something new, didn't hit the back arrow - setupPacket.map = map; - } - } else if ( netMenu == NM_OPTIONS ) { - Cvar_SetValue( fragLimit->name, setupPacket.fraglimit ); - if ( iphoneSlider( 104, 64, 272, 40, "frag limit", fragLimit, 0, 20, SF_INTEGER ) ) { - if ( server ) { - setupPacket.fraglimit = fragLimit->value; - } - } - - Cvar_SetValue( timeLimit->name, setupPacket.timelimit ); - if ( iphoneSlider( 104, 64+56, 272, 40, "time limit", timeLimit, 0, 20, SF_INTEGER ) ) { - if ( server ) { - setupPacket.timelimit = timeLimit->value; - } - } - if ( BackButton() ) { - netMenu = NM_MAIN; - } - return; - } - - if ( !btnDeathmatch.texture ) { - // initial setup - SetButtonPicsAndSizes( &btnDeathmatch, "iphone/deathmatch.tga", "Deathmatch", 4+48, 64, 96, 96 ); - SetButtonPicsAndSizes( &btnCoop, "iphone/co-op.tga", "Cooperative", 480-148, 64, 96, 96 ); - } - - if ( BackButton() ) { - if ( server ) { - TerminateGameService(); // don't advertise for any more new players - setupPacket.gameID = 0; // stop sending packets - } - menuState = IPM_MAIN; - } - - if ( !server ) { - // we aren't the server - // send our join packet every frame - SendJoinPacket(); - - if ( setupPacketFrameNum < iphoneFrameNum - 30 ) { - // haven't received a current server packet - char str[1024]; - struct sockaddr_in *sin = (struct sockaddr_in *)&netServer.address; - byte *ip = (byte *)&sin->sin_addr; - sprintf( str, "Joining server at %i.%i.%i.%i:%i\n", ip[0], ip[1], ip[2], ip[3], - ntohs( sin->sin_port ) ); - iphoneCenterText( 240, 160, 0.75, str ); - return; - } - } else { - // cull out any players that haven't given us a packet in a couple seconds - int now = SysIphoneMilliseconds(); - for ( int i = 1 ; i < MAXPLAYERS ; i++ ) { - if ( setupPacket.playerID[i] && now - netPlayers[i].peer.lastPacketTime > 1000 ) { - printf( "Dropping player %i: last:%i now:%i\n", i, netPlayers[i].peer.lastPacketTime, now ); - setupPacket.playerID[i] = 0; - } - } - } - - // draw the level and allow clicking to change - Cvar_SetValue( mpDataset->name, setupPacket.map.dataset ); - Cvar_SetValue( mpEpisode->name, setupPacket.map.episode ); - Cvar_SetValue( mpMap->name, setupPacket.map.map ); - Cvar_SetValue( mpSkill->name, setupPacket.map.skill ); - - // map select button / display - if ( NewTextButton( &btnMap, FindMapName( mpDataset->value, mpEpisode->value, mpMap->value ), 64, 0, 480-128, 48 ) ) { - if ( server ) { - // clients can't go into this menu - netMenu = NM_MAP_SELECT; - } - } - - if ( setupPacket.deathmatch ) { - btnDeathmatch.buttonFlags = 0; - btnCoop.buttonFlags = BF_DIMMED; - } else { - btnDeathmatch.buttonFlags = BF_DIMMED; - btnCoop.buttonFlags = 0; - } - - if ( HandleButton( &btnDeathmatch ) ) { - if ( server ) { - Cvar_SetValue( mpDeathmatch->name, 3 ); // weapons stay, items respawn rules - setupPacket.deathmatch = mpDeathmatch->value; - } - } - if ( HandleButton( &btnCoop ) ) { - if ( server ) { - Cvar_SetValue( mpDeathmatch->name, 0 ); - setupPacket.deathmatch = mpDeathmatch->value; - } - } - - if ( NewTextButton( &btnNetSettings, "Settings", 240-64, 64+24, 128, 48 ) ) { - netMenu = NM_OPTIONS; - } - - for ( int i = 0 ; i < 4 ; i ++ ) { - int x = 45 + ( 64+45) * i; - int y = 64+128; - - x *= ((float)displaywidth) / 480.0f; - y *= ((float)displayheight) / 320.0f; - - // FIXME: show proper player colors - byte color[4][4] = { { 0, 255, 0, 255 }, { 128, 128, 128, 255 }, { 128,64,0, 255 }, {255,0,0, 255 } }; - glColor4ubv( color[i] ); - PK_DrawTexture( PK_FindTexture( "iphone/multi_backdrop.tga" ), x, y ); - glColor4f( 1, 1, 1, 1 ); - if ( setupPacket.playerID[i] == playerID ) { - // bigger outline for your player slot - PK_StretchTexture( PK_FindTexture( "iphone/multi_frame.tga" ), x, y, 64, 64 ); - } - - - // draw doom guy face - if ( setupPacket.playerID[i] != 0 ) { - PK_DrawTexture( PK_FindTexture( "iphone/multi_face.tga" ), x, y ); -#if 0 - // temp display IP address - byte *ip = (byte *)&setupPacket.address[i].sin_addr; - iphoneDrawText( x-16, (i&1) ? y+16 : y+48, 0.75, va("%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3] ) ); -#endif - } - - } - - if ( server ) { - // flash a tiny pic when transmitting - if ( iphoneFrameNum & 1 ) { - glColor4f( 1,1,1,1 ); - } else { - glColor4f( 0.5,0.5,0.5,1 ); - } - iphoneCenterText( 470, 310, 0.75, "*" ); - glColor4f( 1,1,1,1 ); - } - if ( setupPacketFrameNum == iphoneFrameNum ) { - iphoneCenterText( 450, 310, 0.75, "*" ); - } -// iphoneDrawText( 0, 310, 0.75, va("%i:%i", localGameID, setupPacket.gameID ) ); - - // only draw the start button if we have at least two players in game - int numPlayers = 0; - for ( int i = 0 ; i < MAXPLAYERS ; i++ ) { - if ( setupPacket.playerID[i] != 0 ) { - numPlayers++; - } - } - - if ( numPlayers > 1 ) { - if ( server ) { - static ibutton_t btnStart; - if ( NewTextButton( &btnStart, "Start game", 240-80, 320-48, 160, 48 ) ) { - setupPacket.startGame = 1; - StartNetGame(); - TerminateGameService(); // don't advertise for any more new players - return; - } - } else { - iphoneCenterText( 240, 320-10, 0.75, "Waiting for server to start the game" ); - } - } else { - byte *ip = (byte *)&gameSocketAddress.sin_addr; - iphoneCenterText( 240, 320-10, 0.75, va("Waiting for players on %i.%i.%i.%i", - ip[0], ip[1], ip[2], ip[3] ) ); - } -} - - -static ibutton_t optionButtons[2][6]; -static ibutton_t defaultsButton; -boolean OptionButton( int col, int row, const char *title ) { - assert( col >= 0 && col < 2 && row >= 0 && row < 6 ); - return NewTextButton( &optionButtons[col][row], title, 10 + 235 * col, 64 + 50 * row, 225, 48 ); -} - -/* - ================== - iphoneOptionsMenu - - ================== - */ -void iphoneOptionsMenu() { - if ( BackButton() ) { - menuState = IPM_CONTROLS; - } - - boolean musicState = music->value; - if ( SysIPhoneOtherAudioIsPlaying() ) { - // music always off when ipod music is playing - musicState = false; - } - - if ( NewTextButton( &defaultsButton, "Defaults", 240-225/2, 2, 225, 48 ) ) { - // reset all cvars except the reverse-landscape mode value - float value = revLand->value; - Cvar_Reset_f(); - Cvar_SetValue( revLand->name, value ); - HudSetForScheme(0); - iphoneStartMusic(); - } - - if ( OptionButton( 0, 0, autoUse->value ? "Auto use: ON" : "Auto use: OFF" ) ) { - Cvar_SetValue( autoUse->name, !autoUse->value ); - } - if ( OptionButton( 0, 1, statusBar->value ? "Status bar: ON" : "Status bar: OFF" ) ) { - Cvar_SetValue( statusBar->name, !statusBar->value ); - } - if ( OptionButton( 0, 2, touchClick->value ? "Touch click: ON" : "Touch click: OFF" ) ) { - Cvar_SetValue( touchClick->name, !touchClick->value ); - } - if ( OptionButton( 0, 3, messages->value ? "Text messages: ON" : "Text messages: OFF" ) ) { - Cvar_SetValue( messages->name, !messages->value ); - } - if ( OptionButton( 1, 0, drawControls->value ? "Draw controls: ON" : "Draw controls: OFF" ) ) { - Cvar_SetValue( drawControls->name, !drawControls->value ); - } - if ( OptionButton( 1, 1, musicState ? "Music: ON" : "Music: OFF" ) ) { - if ( !SysIPhoneOtherAudioIsPlaying() ) { - Cvar_SetValue( music->name, !music->value ); - if ( music->value ) { - iphoneStartMusic(); - } else { - iphoneStopMusic(); - } - } - } - if ( OptionButton( 1, 2, centerSticks->value ? "Center sticks: ON" : "Center sticks: OFF" ) ) { - Cvar_SetValue( centerSticks->name, !centerSticks->value ); - } - if ( OptionButton( 1, 3, rampTurn->value ? "Ramp turn: ON" : "Ramp turn: OFF" ) ) { - Cvar_SetValue( rampTurn->name, !rampTurn->value ); - } -} - -/* - =================== - iphoneIntermission - - The end-of-level switch was just hit, note the state and awards - for the map select menu - =================== - */ -void iphoneIntermission( wbstartstruct_t* wb ) { - if ( deathmatch || netgame ) { - // no achievements in deathmatch mode - return; - } - - // find the current episode / map combination - - // if a mapStat_t doesn't exist for this yet, create one - - // mark this level / skill combination as tried - mapStats_t *cms = FindMapStats( playState.map.dataset, playState.map.episode, playState.map.map, true ); - if ( !cms ) { - return; - } - - int skill = playState.map.skill; - cms->completionFlags[skill] |= MF_COMPLETED; - - // add the awards - if ( wb->plyr[0].stime < wb->partime ) { - cms->completionFlags[skill] |= MF_TIME; - } - - int numkills = 0; - int numsecrets = 0; - int numitems = 0; - for ( int i = 0 ; i < MAXPLAYERS ; i++ ) { - if ( wb->plyr[i].in ) { - numkills += wb->plyr[i].skills; - numitems += wb->plyr[i].sitems; - numsecrets += wb->plyr[i].ssecret; - } - } - if ( numkills >= wb->maxkills ) { - cms->completionFlags[skill] |= MF_KILLS; - } - if ( numitems >= wb->maxitems ) { - cms->completionFlags[skill] |= MF_TREASURE; - } - if ( numsecrets >= wb->maxsecret ) { - cms->completionFlags[skill] |= MF_SECRETS; - } -} - -/* - =================== - iphoneStartLevel - - Do a savegame with the current state - =================== - */ -void iphoneStartLevel() { - if ( deathmatch || netgame ) { - // no achievements in deathmatch mode - - // reset the levelTimer - if ( levelTimer && setupPacket.timelimit > 0 ) { - // 30 hz, minutes - levelTimeCount = setupPacket.timelimit * 30 * 60; - } - - return; - } - playState.map.map = gamemap; - - // automatic save game - G_SaveGame( 0, "entersave" ); - G_DoSaveGame(true); - - // mark this level as tried - mapStats_t *cms = FindMapStats( playState.map.dataset, playState.map.episode, playState.map.map, true ); - if ( cms ) { - cms->completionFlags[playState.map.skill] |= MF_TRIED; - } -} - - -/* - =================== - DrawLiveBackground - - Draw a randomish moving cloudy background - =================== - */ -void DrawLiveBackground() { - static float bgVectors[2][2] = { { 0.01, 0.015 }, { -0.01, -0.02 } }; - float fade[2]; - - // slide and fade a couple textures around - static float tc[2][4][2]; - for ( int i = 0 ; i < 2 ; i++ ) { - int ofs = iphoneFrameNum + i * 32; - float dist = ( ofs & 63 ); - for ( int j = 0 ; j < 2 ; j ++ ) { - for ( int k = 0 ; k < 2 ; k++ ) { - if ( rand()&1 ) { - if ( bgVectors[j][k] < 0.03 ) { - bgVectors[j][k] += 0.0001; - } - } else { - if ( bgVectors[j][k] > -0.03 ) { - bgVectors[j][k] -= 0.0001; - } - } - } - } - fade[i] = sin( ( dist - 16 ) / 32.0 * M_PI ) * 0.5 + 0.5; - fade[i] *= 0.7; - - for ( int j = 0 ; j < 2 ; j++ ) { - tc[i][0][j] += bgVectors[i][j]; - tc[i][0][j] -= floor( tc[i][0][j] ); - } - tc[i][1][0] = tc[i][0][0]+1; - tc[i][1][1] = tc[i][0][1]+0; - - tc[i][2][0] = tc[i][0][0]+0; - tc[i][2][1] = tc[i][0][1]+1; - - tc[i][3][0] = tc[i][0][0]+1; - tc[i][3][1] = tc[i][0][1]+1; - } - - - - // Fill rate performance is an issue just for two scrolling layers under - // modest GUI objects. Using a PVR2 texture and a single multitexture - // pass helps. If all the GUI objects were drawn with depth buffering, - // the surface rejection would help out, but bumping depth after every - // draw would be a bit of a chore. - -#if 0 - glClear( GL_DEPTH_BUFFER_BIT ); - glDepthMask( 1 ); // write the depth buffer - glEnable( GL_DEPTH_TEST ); // depth test this background -#endif - - PK_BindTexture( PK_FindTexture( "iphone/livetile_1.tga" ) ); - - glDisable( GL_BLEND ); - glDisable( GL_DEPTH_TEST ); - - // multitexture setup - glActiveTexture( GL_TEXTURE1 ); - glClientActiveTexture( GL_TEXTURE1 ); - glEnable( GL_TEXTURE_2D ); - PK_BindTexture( PK_FindTexture( "iphone/livetile_1.tga" ) ); - glTexCoordPointer( 2, GL_FLOAT, 8, tc[1][0] ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); - - glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); -// glColor4f( fade[0], fade[0], fade[0], fade[1] ); - glBegin( GL_TRIANGLE_STRIP ); - - glTexCoord2f( tc[0][0][0], tc[0][0][1] ); glVertex3f( 0, 0, 0.5 ); - glTexCoord2f( tc[0][1][0], tc[0][1][1] ); glVertex3f( displaywidth, 0, 0.5 ); - glTexCoord2f( tc[0][2][0], tc[0][2][1]+1 ); glVertex3f( 0, displayheight, 0.5 ); - glTexCoord2f( tc[0][3][0], tc[0][3][1]+1 ); glVertex3f( displaywidth, displayheight, 0.5 ); - - glEnd(); - - // unbind the second texture - glBindTexture( GL_TEXTURE_2D, 0 ); - glDisable( GL_TEXTURE_2D ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - glActiveTexture( GL_TEXTURE0 ); - glClientActiveTexture( GL_TEXTURE0 ); - - glColor4f( 1, 1, 1, 1 ); - glEnable( GL_BLEND ); -#if 0 - // Enable depth test, but not depth writes, so the tile dorting - // minimizes the amount of time drawing the background when it - // is mostly covered. - glEnable( GL_DEPTH_TEST ); - glDepthMask( 0 ); -#endif -} - -#define MAX_PACKET_LOG 64 -int currentPacketLog; -int packetLogMsec[MAX_PACKET_LOG]; - -void iphonePacketTester() { - glClear( GL_COLOR_BUFFER_BIT ); - - if ( BackButton() ) { - menuState = IPM_MAIN; - return; - } - - struct sockaddr_in sender; - unsigned senderLen = sizeof( sender ); - byte buffer[1024]; - while( 1 ) { - int r = recvfrom( gameSocket, buffer, sizeof( buffer ), 0, (struct sockaddr *)&sender, &senderLen ); - if ( r == -1 ) { - break; - } - packetSetup_t *sp = (packetSetup_t *)buffer; - if ( sp->sendCount == setupPacket.sendCount ) { - Com_Printf( "Duplicated receive: %i\n", sp->sendCount ); - } else if ( sp->sendCount < setupPacket.sendCount ) { - Com_Printf( "Out of order receive: %i < %i\n", sp->sendCount, setupPacket.sendCount ); - } else if ( sp->sendCount > setupPacket.sendCount + 1 ) { - Com_Printf( "Dropped %i packets before %i\n", sp->sendCount - 1 - setupPacket.sendCount, sp->sendCount ); - } - setupPacket = *sp; - packetLogMsec[currentPacketLog&(MAX_PACKET_LOG-1)] = SysIphoneMilliseconds(); - currentPacketLog++; - } - - color4_t activeColor = { 0, 255, 0, 255 }; - for ( int i = 1 ; i < MAX_PACKET_LOG ; i++ ) { - int t1 = packetLogMsec[(currentPacketLog - i)&(MAX_PACKET_LOG-1)]; - int t2 = packetLogMsec[(currentPacketLog - i - 1)&(MAX_PACKET_LOG-1)]; - int msec = t1 - t2; - R_Draw_Fill( 0, i * 4, msec, 2, activeColor ); - } -} - - -/* - =================== - iphoneStartMenu - - =================== - */ -void iphoneStartMenu() { - mapStart_t map; - if ( !iphoneMapSelectMenu( &map ) ) { - return; - } - if ( map.map == -1 ) { - // hit the back button - menuState = IPM_MAIN; - return; - } - - StartSinglePlayerGame( map ); -} - -/* - =================== - iphoneDrawMenus - - =================== - */ -void iphoneDrawMenus() { - - // Because mState is global, i have no clue when it changes. - if( lastState != menuState ) { - // Menu State has Changed... - switch ( menuState ) { - case IPM_MAIN: IB_GotoMainMenu(); break; - case IPM_MULTIPLAYER: iphoneMultiplayerMenu(); break; - case IPM_MAPS: iphoneStartMenu(); break; - case IPM_CONTROLS: iphoneControlMenu(); break; - case IPM_OPTIONS: iphoneOptionsMenu(); break; - case IPM_HUDEDIT: HudEditFrame(); break; - } - - lastState = menuState; - } else { - - if ( menuState == IPM_PACKET_TEST ) { - // do this before the slow drawing background to get 60hz update rate - iphonePacketTester(); - return; - } - - // check for game start in a received setup packet - if ( !netgame && setupPacket.startGame ) { - if ( StartNetGame() ) { - setupPacket.startGame = false; - // we aren't in this game - return; - } - } - - // interactive menus - switch ( menuState ) { - case IPM_MULTIPLAYER: iphoneMultiplayerMenu(); break; - case IPM_MAPS: iphoneStartMenu(); break; - case IPM_CONTROLS: iphoneControlMenu(); break; - case IPM_OPTIONS: iphoneOptionsMenu(); break; - case IPM_HUDEDIT: HudEditFrame(); break; - } - } -} - - diff --git a/code/iphone/iphone_net.c b/code/iphone/iphone_net.c old mode 100644 new mode 100755 index 098d5d0..ad9b967 --- a/code/iphone/iphone_net.c +++ b/code/iphone/iphone_net.c @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * iphone_net.c + * doom + * + * Created by John Carmack on 7/8/09. + * Copyright 2009 id Software. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -25,7 +33,7 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" #include #include // for gethostbyname @@ -64,6 +72,13 @@ void DNSServiceRegisterReplyCallback ( const char *regtype, const char *domain, void *context ) { + (void)sdRef; + (void)flags; + (void)name; + (void)regtype; + (void)domain; + (void)context; + if ( errorCode == kDNSServiceErr_NoError ) { localServer = true; } else { @@ -119,6 +134,14 @@ void DNSServiceQueryRecordReplyCallback ( const void *rdata, uint32_t ttl, void *context ) { + (void)DNSServiceRef; + (void)flags; + (void)errorCode; + (void)rrtype; + (void)rrclass; + (void)ttl; + (void)context; + assert( rdlen == 4 ); const byte *ip = (const byte *)rdata; char interfaceName[IF_NAMESIZE]; @@ -152,6 +175,13 @@ void DNSServiceResolveReplyCallback ( uint16_t txtLen, const unsigned char *txtRecord, void *context ) { + (void)sdRef; + (void)errorCode; + (void)port; + (void)txtLen; + (void)txtRecord; + (void)context; + char interfaceName[IF_NAMESIZE]; if_indextoname( interfaceIndex, interfaceName ); printf( "Resolve: interfaceIndex [%i]=%s : %s @ %s\n", interfaceIndex, interfaceName, fullname, hosttarget ); @@ -336,13 +366,17 @@ void DNSServiceBrowseReplyCallback( DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, - const char *serviceName, + const char *theServiceName, const char *regtype, const char *replyDomain, void *context ) { + (void)sdRef; + (void)errorCode; + (void)context; + printf( "DNSServiceBrowseReplyCallback %s: interface:%i name:%s regtype:%s domain:%s\n", (flags & kDNSServiceFlagsAdd) ? "ADD" : "REMOVE", - interfaceIndex, serviceName, regtype, replyDomain ); + interfaceIndex, theServiceName, regtype, replyDomain ); if ( flags & kDNSServiceFlagsAdd ) { // add it to the list if ( interfaceIndex == 1 ) { @@ -351,7 +385,7 @@ void DNSServiceBrowseReplyCallback( for ( int i = 0 ; i < MAX_SERVICE_INTEFACES ; i++ ) { service_t *service = &serviceInterfaces[i]; if ( service->interfaceIndex == 0 ) { - strncpy( service->browseName, serviceName, sizeof( service->browseName ) -1 ); + strncpy( service->browseName, theServiceName, sizeof( service->browseName ) -1 ); strncpy( service->browseRegtype, regtype, sizeof( service->browseRegtype ) -1 ); strncpy( service->browseDomain, replyDomain, sizeof( service->browseDomain ) -1 ); service->interfaceIndex = interfaceIndex; @@ -467,6 +501,7 @@ boolean NetworkAvailable() { } int InterfaceIndexForAddress( struct sockaddr_in *adr ) { + (void)adr; // FIXME: compare against getifaddrs return 0; } diff --git a/code/iphone/iphone_render.c b/code/iphone/iphone_render.c old mode 100644 new mode 100755 index a586c59..20e687d --- a/code/iphone/iphone_render.c +++ b/code/iphone/iphone_render.c @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * iphoneRender.c + * doom + * + * Created by John Carmack on 4/29/09. + * Copyright 2009 id Software. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -120,13 +128,13 @@ int c_subsectors; // test options int testClear = 0; -int testNewRenderer = 1; +int testNewRenderer = 0; int showRenderTime; int blendAll; -void BuildIndexedTriangles(); -void BuildSideSegs(); +void BuildIndexedTriangles(void); +void BuildSideSegs(void); void IR_MergeSectors( int fromSector, int intoSector ) { // E3M8 (and possibly others somewhere) has a bad sector @@ -366,10 +374,10 @@ static void IR_ProjectSprite (mobj_t* thing, int lightlevel) // JDC: clip to the occlusio buffer int testLow = x1 < 0 ? 0 : x1; int testHigh = x2 >= viewwidth ? viewwidth - 1 : x2; - if ( reversedLandscape ) { - testLow = viewwidth-1-testLow; - testHigh = viewwidth-1-testHigh; - } + //if ( reversedLandscape ) { + // testLow = viewwidth-1-testLow; + // testHigh = viewwidth-1-testHigh; + //} if ( !memchr( occlusion+testLow, 0, testHigh - testLow ) ) { c_occludedSprites++; return; @@ -554,23 +562,28 @@ gld_drawinfo.walls[gld_drawinfo.num_walls++]=*wall;\ extern GLSeg *gl_segs; extern byte rendermarker; extern byte *segrendered; +extern int tran_filter_pct; void IR_AddWall(seg_t *seg) { GLWall wall; GLTexture *temptex; - sector_t *frontsector; - sector_t *backsector; + sector_t *thefrontsector; + sector_t *thebacksector; + sector_t ftempsec; // needed for R_FakeFlat + sector_t btempsec; // needed for R_FakeFlat float lineheight; int rellight = 0; wall.glseg=NULL; wall.side = seg->sidedef; - frontsector = seg->frontsector; + thefrontsector=R_FakeFlat(seg->frontsector, &ftempsec, NULL, NULL, false); // for boom effects + if (!thefrontsector) + return; // JDC: improve this lighting tweak rellight = seg->linedef->dx==0? +8 : seg->linedef->dy==0 ? -8 : 0; - int light = frontsector->lightlevel+rellight+(extralight<<5); + int light = thefrontsector->lightlevel+rellight+(extralight<<5); wall.light = MAX(MIN((light),255),0); wall.alpha=1.0f; wall.gltexture=NULL; @@ -578,18 +591,18 @@ void IR_AddWall(seg_t *seg) if (!seg->backsector) /* onesided */ { #ifdef SKYWALLS - if (frontsector->ceilingpic==skyflatnum) + if (thefrontsector->ceilingpic==skyflatnum) { wall.ytop=255.0f; - wall.ybottom=(float)frontsector->ceilingheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,frontsector->sky); + wall.ybottom=(float)thefrontsector->ceilingheight/MAP_SCALE; + SKYTEXTURE(thefrontsector->sky,thefrontsector->sky); ADDWALL(&wall); } - if (frontsector->floorpic==skyflatnum) + if (thefrontsector->floorpic==skyflatnum) { - wall.ytop=(float)frontsector->floorheight/MAP_SCALE; + wall.ytop=(float)thefrontsector->floorheight/MAP_SCALE; wall.ybottom=-255.0f; - SKYTEXTURE(frontsector->sky,frontsector->sky); + SKYTEXTURE(thefrontsector->sky,thefrontsector->sky); ADDWALL(&wall); } #endif @@ -597,7 +610,7 @@ void IR_AddWall(seg_t *seg) if (temptex) { wall.gltexture=temptex; - CALC_Y_VALUES(wall, lineheight, frontsector->floorheight, frontsector->ceilingheight); + CALC_Y_VALUES(wall, lineheight, thefrontsector->floorheight, thefrontsector->ceilingheight); CALC_TEX_VALUES_MIDDLE1S( wall, seg, (LINE->flags & ML_DONTPEGBOTTOM)>0, seg->length, lineheight @@ -609,24 +622,26 @@ void IR_AddWall(seg_t *seg) { int floor_height,ceiling_height; - backsector=seg->backsector; + thebacksector=R_FakeFlat(seg->backsector, &btempsec, NULL, NULL, true); // for boom effects + if(!thebacksector) + return; /* toptexture */ - ceiling_height=frontsector->ceilingheight; - floor_height=backsector->ceilingheight; + ceiling_height=thefrontsector->ceilingheight; + floor_height=thebacksector->ceilingheight; #ifdef SKYWALLS - if (frontsector->ceilingpic==skyflatnum) + if (thefrontsector->ceilingpic==skyflatnum) { wall.ytop=255.0f; if ( // e6y // Fix for HOM in the starting area on Memento Mori map29 and on map30. - // old code: (backsector->ceilingheight==backsector->floorheight) && - (backsector->ceilingheight==backsector->floorheight||(backsector->ceilingheight<=frontsector->floorheight)) && - (backsector->ceilingpic==skyflatnum) + // old code: (thebacksector->ceilingheight==thebacksector->floorheight) && + (thebacksector->ceilingheight==thebacksector->floorheight||(thebacksector->ceilingheight<=thefrontsector->floorheight)) && + (thebacksector->ceilingpic==skyflatnum) ) { - wall.ybottom=(float)backsector->floorheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ybottom=(float)thebacksector->floorheight/MAP_SCALE; + SKYTEXTURE(thefrontsector->sky,thebacksector->sky); ADDWALL(&wall); } else @@ -635,18 +650,18 @@ void IR_AddWall(seg_t *seg) { // e6y // It corrects some problem with sky, but I do not remember which one - // old code: wall.ybottom=(float)frontsector->ceilingheight/MAP_SCALE; - wall.ybottom=(float)MAX(frontsector->ceilingheight,backsector->ceilingheight)/MAP_SCALE; + // old code: wall.ybottom=(float)thefrontsector->ceilingheight/MAP_SCALE; + wall.ybottom=(float)MAX(thefrontsector->ceilingheight,thebacksector->ceilingheight)/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + SKYTEXTURE(thefrontsector->sky,thebacksector->sky); ADDWALL(&wall); } else - if ( (backsector->ceilingheight <= frontsector->floorheight) || - (backsector->ceilingpic != skyflatnum) ) + if ( (thebacksector->ceilingheight <= thefrontsector->floorheight) || + (thebacksector->ceilingpic != skyflatnum) ) { - wall.ybottom=(float)backsector->ceilingheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ybottom=(float)thebacksector->ceilingheight/MAP_SCALE; + SKYTEXTURE(thefrontsector->sky,thebacksector->sky); ADDWALL(&wall); } } @@ -654,7 +669,7 @@ void IR_AddWall(seg_t *seg) #endif if (floor_heightceilingpic==skyflatnum) && (backsector->ceilingpic==skyflatnum))) + if (!((thefrontsector->ceilingpic==skyflatnum) && (thebacksector->ceilingpic==skyflatnum))) { temptex=gld_RegisterTexture(texturetranslation[seg->sidedef->toptexture], true, false); if ( !temptex ) { @@ -735,40 +750,42 @@ void IR_AddWall(seg_t *seg) wall.vt=mip*((float)(ceiling_height - ceilingmin))/linelen; } + if (seg->linedef->tranlump >= 0 && general_translucency) + wall.alpha=(float)tran_filter_pct/100.0f; wall.alpha=1.0f; ADDWALL(&wall); } bottomtexture: /* bottomtexture */ - ceiling_height=backsector->floorheight; - floor_height=frontsector->floorheight; + ceiling_height=thebacksector->floorheight; + floor_height=thefrontsector->floorheight; #ifdef SKYWALLS - if (frontsector->floorpic==skyflatnum) + if (thefrontsector->floorpic==skyflatnum) { wall.ybottom=-255.0f; if ( - (backsector->ceilingheight==backsector->floorheight) && - (backsector->floorpic==skyflatnum) + (thebacksector->ceilingheight==thebacksector->floorheight) && + (thebacksector->floorpic==skyflatnum) ) { - wall.ytop=(float)backsector->floorheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ytop=(float)thebacksector->floorheight/MAP_SCALE; + SKYTEXTURE(thefrontsector->sky,thebacksector->sky); ADDWALL(&wall); } else { if ( (texturetranslation[seg->sidedef->bottomtexture]!=NO_TEXTURE) ) { - wall.ytop=(float)frontsector->floorheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ytop=(float)thefrontsector->floorheight/MAP_SCALE; + SKYTEXTURE(thefrontsector->sky,thebacksector->sky); ADDWALL(&wall); } else - if ( (backsector->floorheight >= frontsector->ceilingheight) || - (backsector->floorpic != skyflatnum) ) + if ( (thebacksector->floorheight >= thefrontsector->ceilingheight) || + (thebacksector->floorpic != skyflatnum) ) { - wall.ytop=(float)backsector->floorheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ytop=(float)thebacksector->floorheight/MAP_SCALE; + SKYTEXTURE(thefrontsector->sky,thebacksector->sky); ADDWALL(&wall); } } @@ -785,7 +802,7 @@ void IR_AddWall(seg_t *seg) CALC_TEX_VALUES_BOTTOM( wall, seg, (LINE->flags & ML_DONTPEGBOTTOM)>0, seg->length, lineheight, - floor_height-frontsector->ceilingheight + floor_height-thefrontsector->ceilingheight ); ADDWALL(&wall); } @@ -821,13 +838,13 @@ boolean TransformAndClipSegment( float v[2][2], float ends[2] ) { // if we are in iphone reverse-landscape mode, we need // to flip the coordinates around float *v0, *v1; - if ( reversedLandscape ) { - v0 = v[1]; - v1 = v[0]; - } else { + //if ( reversedLandscape ) { + // v0 = v[1]; + // v1 = v[0]; + //} else { v0 = v[0]; v1 = v[1]; - } + //} // transform from model to clip space // because the iPhone screen hardware is portrait mode, @@ -870,7 +887,7 @@ boolean TransformAndClipSegment( float v[2][2], float ends[2] ) { // project for ( int i = 0 ; i < 2 ; i++ ) { - float x = viewwidth * ( ( clip[i][1] / clip[i][3] ) * 0.5 + 0.5 ); + float x = viewwidth * ( ( clip[i][1] / clip[i][3] ) * 0.5f + 0.5f ); if ( x < 0 ) { x = 0; } else if ( x > viewwidth ) { @@ -902,49 +919,49 @@ void IR_Subsector(int num) // if the sector that this subsector is a part of has not already had its // planes and sprites added, add them now. - sector_t *frontsector = sub->sector; - int lightlevel = frontsector->lightlevel+(extralight<<5); + sector_t *thefrontsector = sub->sector; + int lightlevel = thefrontsector->lightlevel+(extralight<<5); // There can be several subsectors in each sector due to non-convex // sectors or BSP splits, but we draw the floors, ceilings and lines // with a single draw call for the entire thing, so ensure that they // are only added once per frame. - if ( frontsector->validcount != validcount ) { - frontsector->validcount = validcount; + if ( thefrontsector->validcount != validcount ) { + thefrontsector->validcount = validcount; c_sectors++; GLFlat flat; - flat.sectornum = frontsector->iSectorID; + flat.sectornum = thefrontsector->iSectorID; flat.light = lightlevel; flat.uoffs= 0; // no support in standard doom flat.voffs= 0; - if ( frontsector->floorheight < viewz ) { - if (frontsector->floorpic == skyflatnum) { + if ( thefrontsector->floorheight < viewz ) { + if (thefrontsector->floorpic == skyflatnum) { skyIsVisible = true; } else { // get the texture. flattranslation is maintained by doom and // contains the number of the current animation frame - GLTexture *tex = gld_RegisterFlat(flattranslation[frontsector->floorpic], true); + GLTexture *tex = gld_RegisterFlat(flattranslation[thefrontsector->floorpic], true); if ( tex ) { sectorPlanes[numSectorPlanes].texture = tex; sectorPlanes[numSectorPlanes].ceiling = false; - sectorPlanes[numSectorPlanes].sector = frontsector; + sectorPlanes[numSectorPlanes].sector = thefrontsector; numSectorPlanes++; } } } - if ( frontsector->ceilingheight > viewz ) { - if (frontsector->ceilingpic == skyflatnum) { + if ( thefrontsector->ceilingheight > viewz ) { + if (thefrontsector->ceilingpic == skyflatnum) { skyIsVisible = true; } else { // get the texture. flattranslation is maintained by doom and // contains the number of the current animation frame - GLTexture *tex = gld_RegisterFlat(flattranslation[frontsector->ceilingpic], true); + GLTexture *tex = gld_RegisterFlat(flattranslation[thefrontsector->ceilingpic], true); if ( tex ) { sectorPlanes[numSectorPlanes].texture = tex; sectorPlanes[numSectorPlanes].ceiling = true; - sectorPlanes[numSectorPlanes].sector = frontsector; + sectorPlanes[numSectorPlanes].sector = thefrontsector; numSectorPlanes++; } } @@ -955,7 +972,7 @@ void IR_Subsector(int num) // we could do more accurate occlusion culling. With non-convex sectors, // occasionally a sprite will be added in a rear portion of the sector that // would have been occluded away if everything was done in BSP subsector order. - for ( mobj_t *thing = frontsector->thinglist; thing; thing = thing->snext) { + for ( mobj_t *thing = thefrontsector->thinglist; thing; thing = thing->snext) { IR_ProjectSprite( thing, lightlevel ); } } @@ -1197,8 +1214,8 @@ static int TexSort( const void *a, const void *b ) { return 1; } -int SysIphoneMicroseconds(); -void SetImmediateModeGLVertexArrays(); +int SysIphoneMicroseconds(void); +void SetImmediateModeGLVertexArrays(void); extern float yaw; extern GLTexture **gld_GLTextures; extern GLTexture **gld_GLPatchTextures; @@ -1273,7 +1290,6 @@ void NewDrawScene(player_t *player) // JDC: new version glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); - iphoneRotateForLandscape(); gld_BindTexture( gld_RegisterTexture( skytexture, true, true ) ); glColor4f( 0.5, 0.5, 0.5, 1.0 ); // native texture color, not double bright @@ -1687,7 +1703,7 @@ void IR_RenderPlayerView (player_t* player) { #ifdef _DEBUG glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #else - glClear(GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #endif // To make it easier to accurately mimic the GL model to screen transformation, @@ -1701,10 +1717,6 @@ void IR_RenderPlayerView (player_t* player) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - // make the 320x480 hardware seem like 480x320 in two different orientations - // and note if the occlusion segmenrs need to be reversed - reversedLandscape = iphoneRotateForLandscape(); - infinitePerspective(64.0f, 320.0f/200.0f, 5.0f/100.0f); glRotatef(roll, 0.0f, 0.0f, 1.0f); @@ -1749,3 +1761,5 @@ void IR_RenderPlayerView (player_t* player) { printf( "%i usec\n", end - start ); } } + + diff --git a/code/iphone/iphone_sound.c b/code/iphone/iphone_sound.c deleted file mode 100644 index ca4ea84..0000000 --- a/code/iphone/iphone_sound.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. - Copyright (C) 2009 Id Software, Inc. - - 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 "../doomiphone.h" -#import - - -typedef struct { - unsigned sourceName; // OpenAL sourceName - pkWav_t *sfx; // NULL if unused - float volume; // stored for showSound display -} channel_t; - -static ALCcontext *Context; -static ALCdevice *Device; - -#define MAX_CHANNELS 16 -static channel_t s_channels[ MAX_CHANNELS ]; - -cvar_t *s_sfxVolume; - -void Sound_StartLocalSound( const char *filename ) { - Sound_StartLocalSoundAtVolume( filename, 1.0f ); -} - -void Sound_StartLocalSoundAtVolume( const char *filename, float volume ) { - pkWav_t *sfx; - - sfx = PK_FindWav( filename ); - if( ! sfx ) { - Com_Printf( "Sound_StartLocalSound: could not cache (%s)\n", filename ); - return; - } -// printf( "sound:%s\n", filename ); - // channel 0 is reserved for UI sounds, the other channels - // are for DOOM sounds - channel_t *ch = &s_channels[ 0 ]; - - ch->sfx = sfx; - ch->volume = s_sfxVolume->value * volume; - - alSourceStop( ch->sourceName ); - alSourcef( ch->sourceName, AL_GAIN, ch->volume ); - alSourcei( ch->sourceName, AL_BUFFER, sfx->alBufferNum ); - alSourcef( ch->sourceName, AL_PITCH, 1.0f ); - alSourcePlay( ch->sourceName ); -} - - -static void Sound_Play_f( void ) { - if( Cmd_Argc() == 1 ) { - Com_Printf( "Usage: play \n" ); - return; - } - Sound_StartLocalSound( Cmd_Argv( 1 ) ); -} - -// we won't allow music to be toggled on or off in the menu when this is true -int otherAudioIsPlaying; - -int SysIPhoneOtherAudioIsPlaying() { - return otherAudioIsPlaying; -} - -void interruptionListener( void *inUserData, UInt32 inInterruption) -{ - printf("Session interrupted! --- %s ---\n", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption"); - - if ( inInterruption == kAudioSessionBeginInterruption ) { - printf("Audio interrupted.\n" ); - iphonePauseMusic(); - alcMakeContextCurrent( NULL ); - AudioSessionSetActive( false ); - } else if ( inInterruption == kAudioSessionEndInterruption ) { - printf("Audio restored.\n" ); - - OSStatus r = AudioSessionSetActive( true ); - if ( r != kAudioSessionNoError ) { - printf( "AudioSessionSetActive( true ) failed: 0x%x\n", r ); - } else { - printf( "AudioSessionSetActive( true ) succeeded.\n" ); - } - alcMakeContextCurrent( Context ); - if( alcGetError( Device ) != ALC_NO_ERROR ) { - Com_Error( "Failed to alcMakeContextCurrent\n" ); - } - iphoneResumeMusic(); - } -} - -void Sound_Init( void ) { - - Com_Printf( "\n------- Sound Initialization -------\n" ); - - s_sfxVolume = Cvar_Get( "s_sfxVolume", "1.0", 0 ); - - Cmd_AddCommand( "play", Sound_Play_f ); - - // make sure background ipod music mixes with our sound effects - Com_Printf( "...Initializing AudioSession\n" ); - OSStatus status = 0; - status = AudioSessionInitialize(NULL, NULL, interruptionListener, NULL); // else "couldn't initialize audio session" - - // if there is iPod music playing in the background, we want to use - // the AmbientSound catagory, otherwise we will leave it at the default. - // If we always set it to AmbientSound, then the mp3 background music - // playback goes to software on 3.0 for a huge slowdown. - UInt32 propOtherAudioIsPlaying = 'othr'; // kAudioSessionProperty_OtherAudioIsPlaying - UInt32 size = sizeof( otherAudioIsPlaying ); - AudioSessionGetProperty( propOtherAudioIsPlaying, &size, &otherAudioIsPlaying ); - Com_Printf("OtherAudioIsPlaying = %d\n", otherAudioIsPlaying ); - - if ( otherAudioIsPlaying ) { - UInt32 audioCategory = kAudioSessionCategory_AmbientSound; - status = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); - } - - status = AudioSessionSetActive(true); // else "couldn't set audio session active\n" - - Com_Printf( "...Initializing OpenAL subsystem\n" ); - - // get the OpenAL device - Device = alcOpenDevice( NULL ); - if( Device == NULL ) { - Com_Printf( "Failed to alcOpenDevice\n" ); - } - - // Create context(s) - Context = alcCreateContext( Device, NULL ); - if( Context == NULL ) { - Com_Error( "Failed to alcCreateContext\n" ); - } - - // Set active context - alcGetError( Device ); - alcMakeContextCurrent( Context ); - if( alcGetError( Device ) != ALC_NO_ERROR ) { - Com_Error( "Failed to alcMakeContextCurrent\n" ); - } - - // allocate all the channels we are going to use - channel_t *ch; - int i; - for( i = 0, ch = s_channels ; i < MAX_CHANNELS ; ++i, ++ch ) { - alGenSources( 1, &ch->sourceName ); - - if( alGetError() != AL_NO_ERROR ) { - Com_Error( "Allocating AL sound sources" ); - } - alSourcei( ch->sourceName, AL_SOURCE_RELATIVE, AL_FALSE ); - } - - Com_Printf( "------------------------------------\n" ); -} - -/* - ================== - ShowSound - - Display active sound channels - ================== - */ -void ShowSound() { - - if ( !showSound->value ) { - return; - } - channel_t *ch; - int i; - for( i = 0, ch = s_channels ; i < MAX_CHANNELS ; ++i, ++ch ) { - int state; - alGetSourcei( ch->sourceName, AL_SOURCE_STATE, &state ); - if ( state != AL_PLAYING ) { - continue; - } - - int v = ch->volume * 255; - if ( v > 255 ) { - v = 255; - } - color4_t color = { v, v, v, 255 }; - R_Draw_Fill( i*16, 0, 12, 12, color ); - } -} - - -/* - ================================================================== - - PrBoom interface - - ================================================================== -*/ - -// Init at program start... -void I_InitSound(void) {} - -// ... shut down and relase at program termination. -void I_ShutdownSound(void) {} - -// Initialize channels? -void I_SetChannels(void) {} - -// Get raw data lump index for sound descriptor. -int I_GetSfxLumpNum (sfxinfo_t *sfx) { - // find the pkWav_t for this sfxinfo - char upper[16], *d = upper; - for ( const char *c = sfx->name ; *c ; c++ ) { - *d++ = toupper( *c ); - } - *d = 0; - pkWav_t *pkwav = PK_FindWav( va( "newsfx/DS%s.wav", upper ) ); - - return pkwav - pkWavs; -} - -// Starts a sound in a particular sound channel. -// volume ranges 0 - 64 -// seperation tanges is 128 straight ahead, 0 = all left ear, 255 = all right ear -// pitch centers around 128 -int I_StartSound(int sfx_id, int channel, int vol, int sep, int pitch, int priority) { - - sfxinfo_t *dsfx = &S_sfx[sfx_id]; - - assert( dsfx->lumpnum >= 0 && dsfx->lumpnum < pkHeader->wavs.count ); - - pkWav_t *sfx = &pkWavs[dsfx->lumpnum]; -// printf( "sound: %s chan:%i vol:%i sep:%i pitch:%i priority:%i\n", sfx->wavData->name.name, channel, vol, sep, pitch, priority ); - - assert( channel >= 0 && channel < MAX_CHANNELS - 1 ); - channel_t *ch = &s_channels[ 1+channel ]; - - alSourceStop( ch->sourceName ); - if ( ch->sfx == sfx ) { - // restarting the same sound - alSourceRewind( ch->sourceName ); - } else { - alSourcei( ch->sourceName, AL_BUFFER, sfx->alBufferNum ); - } - - ch->sfx = sfx; - ch->volume = s_sfxVolume->value * vol / 64.0; - alSourcef( ch->sourceName, AL_GAIN, ch->volume ); - alSourcef( ch->sourceName, AL_PITCH, pitch / 128.0f ); - alSourcePlay( ch->sourceName ); - - return (int)ch; -} - -// Stops a sound channel. -void I_StopSound(int handle) {} - -// Called by S_*() functions -// to see if a channel is still playing. -// Returns 0 if no longer playing, 1 if playing. -boolean I_SoundIsPlaying(int handle) { - - channel_t *ch = (channel_t *)handle; - if ( !ch ) { - return false; - } - int state; - alGetSourcei( ch->sourceName, AL_SOURCE_STATE, &state ); - - return state == AL_PLAYING; -} - -// Called by m_menu.c to let the quit sound play and quit right after it stops -boolean I_AnySoundStillPlaying(void) { return false; } - -// Updates the volume, separation, -// and pitch of a sound channel. -void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) {} diff --git a/code/iphone/iphone_sound.mm b/code/iphone/iphone_sound.mm new file mode 100755 index 0000000..7bd8431 --- /dev/null +++ b/code/iphone/iphone_sound.mm @@ -0,0 +1,449 @@ +/* + * iphone_sound.c + * doom + * + * Created by John Carmack on 4/16/09. + * Copyright 2009 Id Software. All rights reserved. + * + */ +/* + + Copyright (C) 2009 Id Software, Inc. + + 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 "doomiphone.h" +#include "w_wad.h" +#include +#import +#import + +typedef struct { + unsigned sourceName; // OpenAL sourceName + pkWav_t *sfx; // NULL if unused + float volume; // stored for showSound display +} channel_t; + +static ALCcontext *Context; +static ALCdevice *Device; + +@interface AudioInterruptionListener : NSObject { +} +- (void)handleAudioSessionInterruption:(NSNotification *)notification; +- (void)registerInterruptionListener; +@end + +@implementation AudioInterruptionListener { +} +- (void)registerInterruptionListener { + +#if !TARGET_OS_TV +[[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleAudioSessionInterruption:) + name:AVAudioSessionInterruptionNotification + object:[AVAudioSession sharedInstance]]; +#endif + +} + +- (void)handleAudioSessionInterruption:(NSNotification *)notification { + +#if !TARGET_OS_TV + + + NSDictionary *interruptionDict = notification.userInfo; + NSInteger interruptionType = [[interruptionDict valueForKey:AVAudioSessionInterruptionTypeKey] integerValue]; + printf("Session interrupted! --- %s ---\n", interruptionType == AVAudioSessionInterruptionTypeBegan ? "Begin Interruption" : "End Interruption"); + + /* JDS Log interruption for now but don't do anything with it yet + NSError* error = nil; + switch (interruptionType) { + case AVAudioSessionInterruptionTypeBegan: + printf("Audio interrupted.\n" ); + iphonePauseMusic(); + alcMakeContextCurrent( NULL ); + + [[AVAudioSession sharedInstance] setActive:NO error:&error]; + + UInt32 otherAudioIsPlaying = [[AVAudioSession sharedInstance] isOtherAudioPlaying]; + Com_Printf("OtherAudioIsPlaying = %d\n", otherAudioIsPlaying ); + + // If other audio is playing now, switch to the Ambient category so it + // can continue in the background. If not, use the default category. + if ( otherAudioIsPlaying ) { + + NSError *error = nil; + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error]; + + if( error != nil ) { + NSLog(@"%@", error); + } + + } else { + NSError *error = nil; + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:&error]; + + if( error != nil ) { + NSLog(@"%@", error); + } + } + + break; + + case AVAudioSessionInterruptionTypeEnded: + printf("Audio restored.\n" ); + + UInt32 otherAudioIsPlaying = [[AVAudioSession sharedInstance] isOtherAudioPlaying]; + Com_Printf("OtherAudioIsPlaying = %d\n", otherAudioIsPlaying ); + + // If other audio is playing now, switch to the Ambient category so it + // can continue in the background. If not, use the default category. + if ( otherAudioIsPlaying ) { + + NSError *error = nil; + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error]; + + if( error != nil ) { + NSLog(@"%@", error); + } + + } else { + NSError *error = nil; + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:&error]; + + if( error != nil ) { + NSLog(@"%@", error); + } + } + + [[AVAudioSession sharedInstance] setActive:YES error:&error]; + if( error != nil ) { + NSLog(@"%@", error); + } + alcMakeContextCurrent( Context ); + if( alcGetError( Device ) != ALC_NO_ERROR ) { + Com_Error( "Failed to alcMakeContextCurrent\n" ); + } + iphoneResumeMusic(); + } + */ + +#endif +} +@end + +#define MAX_CHANNELS 16 +static channel_t s_channels[ MAX_CHANNELS ]; + +cvar_t *s_sfxVolume; + +void Sound_StartLocalSound( const char *filename ) { + Sound_StartLocalSoundAtVolume( filename, 1.0f ); +} + +void Sound_StartLocalSoundAtVolume( const char *filename, float volume ) { + pkWav_t *sfx; + + sfx = PK_FindWav( filename ); + if( ! sfx ) { + Com_Printf( "Sound_StartLocalSound: could not cache (%s)\n", filename ); + return; + } +// printf( "sound:%s\n", filename ); + // channel 0 is reserved for UI sounds, the other channels + // are for DOOM sounds + channel_t *ch = &s_channels[ 0 ]; + + ch->sfx = sfx; + ch->volume = s_sfxVolume->value * volume; + + alSourceStop( ch->sourceName ); + alSourcef( ch->sourceName, AL_GAIN, ch->volume ); + alSourcei( ch->sourceName, AL_BUFFER, sfx->alBufferNum ); + alSourcef( ch->sourceName, AL_PITCH, 1.0f ); + alSourcePlay( ch->sourceName ); +} + + +static void Sound_Play_f( void ) { + if( Cmd_Argc() == 1 ) { + Com_Printf( "Usage: play \n" ); + return; + } + Sound_StartLocalSound( Cmd_Argv( 1 ) ); +} + +// we won't allow music to be toggled on or off in the menu when this is true +int otherAudioIsPlaying; + +int SysIPhoneOtherAudioIsPlaying() { + return otherAudioIsPlaying; +} + +void Sound_Init(void) { + + Com_Printf( "\n------- Sound Initialization -------\n" ); + + s_sfxVolume = Cvar_Get( "s_sfxVolume", "1.0", static_cast(0) ); + + Cmd_AddCommand( "play", Sound_Play_f ); + +#if !TARGET_OS_TV + // make sure background ipod music mixes with our sound effects + Com_Printf( "...Initializing AudioSession\n" ); + + //OSStatus status = 0; + + /* JDS FIXME [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interruptionListener:) + name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; + */ + AudioInterruptionListener *listener = [[AudioInterruptionListener alloc] init]; + [listener registerInterruptionListener]; + + // JDS deprecated status = AudioSessionInitialize(NULL, NULL, interruptionListener, NULL); // else "couldn't initialize audio session" + + // if there is iPod music playing in the background, we want to use + // the AmbientSound catagory, otherwise we will leave it at the default. + // If we always set it to AmbientSound, then the mp3 background music + // playback goes to software on 3.0 for a huge slowdown. + UInt32 otherAudioIsPlaying = [[AVAudioSession sharedInstance] isOtherAudioPlaying]; + //JDS deprecated UInt32 propOtherAudioIsPlaying = kAudioSessionProperty_OtherAudioIsPlaying; + //JDS deprecated UInt32 size = sizeof( otherAudioIsPlaying ); + //AudioServicesGetProperty( propOtherAudioIsPlaying, &size, &otherAudioIsPlaying ); + + Com_Printf("OtherAudioIsPlaying = %d\n", otherAudioIsPlaying ); + + // JDS FIXME + if ( 1 ) { + //UInt32 audioCategory = kAudioSessionCategory_AmbientSound; + + // Allow sound to play in the background + NSError *error = nil; + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error]; + + if( error != nil ) { + NSLog(@"%@", error); + } + + //status = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); + } + + NSError* error = nil; + [[AVAudioSession sharedInstance] setActive:YES error:&error]; + if( error != nil ) { + NSLog(@"%@", error); + } + //JDS deprecated status = AudioSessionSetActive(true); // else "couldn't set audio session active\n" +#endif + + Com_Printf( "...Initializing OpenAL subsystem\n" ); + + // get the OpenAL device + Device = alcOpenDevice( NULL ); + if( Device == NULL ) { + Com_Printf( "Failed to alcOpenDevice\n" ); + } + + // Create context(s) + Context = alcCreateContext( Device, NULL ); + if( Context == NULL ) { + Com_Error( "Failed to alcCreateContext\n" ); + } + + // Set active context + alcGetError( Device ); + alcMakeContextCurrent( Context ); + if( alcGetError( Device ) != ALC_NO_ERROR ) { + Com_Error( "Failed to alcMakeContextCurrent\n" ); + } + + // allocate all the channels we are going to use + channel_t *ch; + int i; + for( i = 0, ch = s_channels ; i < MAX_CHANNELS ; ++i, ++ch ) { + alGenSources( 1, &ch->sourceName ); + + if( alGetError() != AL_NO_ERROR ) { + Com_Error( "Allocating AL sound sources" ); + } + alSourcei( ch->sourceName, AL_SOURCE_RELATIVE, AL_FALSE ); + } + + Com_Printf( "------------------------------------\n" ); +} + +/* + ================== + ShowSound + + Display active sound channels + ================== + */ +void ShowSound() { + + if ( !showSound->value ) { + return; + } + channel_t *ch; + int i; + for( i = 0, ch = s_channels ; i < MAX_CHANNELS ; ++i, ++ch ) { + int state; + alGetSourcei( ch->sourceName, AL_SOURCE_STATE, &state ); + if ( state != AL_PLAYING ) { + continue; + } + + int v = ch->volume * 255; + if ( v > 255 ) { + v = 255; + } + color4_t color = { static_cast(v), static_cast(v), static_cast(v), 255 }; + R_Draw_Fill( i*16, 0, 12, 12, color ); + } +} + + + +/* + ================================================================== + + PrBoom interface + + ================================================================== +*/ + +// Initialize channels? +void I_SetChannels(void) {} + +// Get raw data lump index for sound descriptor. +int I_GetSfxLumpNum (sfxinfo_t *sfx) { + // find the pkWav_t for this sfxinfo + char upper[16], *d = upper; + for ( const char *c = sfx->name ; *c ; c++ ) { + *d++ = toupper( *c ); + } + *d = 0; + pkWav_t *pkwav = PK_FindWav( va( "newsfx/DS%s.wav", upper ) ); + + return (int) (pkwav - pkWavs); +} + +// Starts a sound in a particular sound channel. +// volume ranges 0 - 64 +// seperation tanges is 128 straight ahead, 0 = all left ear, 255 = all right ear +// pitch centers around 128 +long int I_StartSound(int sfx_id, int channel, int vol, int sep, int pitch, int priority) { + + sfxinfo_t *dsfx = &S_sfx[sfx_id]; + + assert( dsfx->lumpnum >= 0 && dsfx->lumpnum < pkHeader->wavs.count ); + + pkWav_t *sfx = &pkWavs[dsfx->lumpnum]; +// printf( "sound: %s chan:%i vol:%i sep:%i pitch:%i priority:%i\n", sfx->wavData->name.name, channel, vol, sep, pitch, priority ); + + assert( channel >= 0 && channel < MAX_CHANNELS ); + channel_t *ch = &s_channels[ 1+channel ]; + + alSourceStop( ch->sourceName ); + if ( ch->sfx == sfx ) { + // restarting the same sound + alSourceRewind( ch->sourceName ); + } else { + alSourcei( ch->sourceName, AL_BUFFER, sfx->alBufferNum ); + } + + ch->sfx = sfx; + ch->volume = s_sfxVolume->value * vol / 64.0; + alSourcef( ch->sourceName, AL_GAIN, ch->volume ); + alSourcef( ch->sourceName, AL_PITCH, pitch / 128.0f ); + alSourcePlay( ch->sourceName ); + + return (long int)ch; +} + +// Stops a sound channel. +void I_StopSound(long int handle) {} + +// Called by S_*() functions +// to see if a channel is still playing. +// Returns 0 if no longer playing, 1 if playing. +boolean I_SoundIsPlaying(long int handle) { + + channel_t *ch = (channel_t *)handle; + if ( !ch ) { + return false; + } + int state; + + alGetSourcei( ch->sourceName, AL_SOURCE_STATE, &state ); + + return state == AL_PLAYING; +} + +// Called by m_menu.c to let the quit sound play and quit right after it stops +boolean I_AnySoundStillPlaying(void) { return false; } + +// Updates the volume, separation, +// and pitch of a sound channel. +void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) {} + +// This function overwrites the audio data loaded from the iPack file +// with the lumps from the loaded WAD files. +void I_OverwriteSoundBuffersWithLumps() { + for ( int i = 0 ; i < pkHeader->wavs.count ; i++ ) { + pkWav_t *sfx = &pkWavs[i]; + sfx->wavData = (pkWavData_t *)( (byte *)pkHeader + pkHeader->wavs.tableOfs + i * pkHeader->wavs.structSize ); + + // get the lump instead of the normal sound effect + const char* sfxname = sfx->wavData->name.name; + + // strip off the path name + // JDS FIXME: clean this up + while(*sfxname && *sfxname != '/') sfxname++; + if( sfxname ) sfxname++; + + // If this is a Doom sound... + // JDS FIXME: clean this up + if( sfxname && tolower(sfxname[0]) == 'd' && tolower(sfxname[1]) == 's' ) { + char* sfxname_noext = strdup(sfxname); + char* sfxname_noext_s = sfxname_noext; + // strip off extension, convert to uppercase + // JDS FIXME: clean this up + while( *sfxname_noext && *sfxname_noext != '.' ) { + *sfxname_noext = toupper(*sfxname_noext); + sfxname_noext++; + } + *sfxname_noext = '\0'; + sfxname_noext = sfxname_noext_s; + // extract the lump + // BUG! Need to parse the Doom sound header format vs. + // hardcoding all this + int lumpNum = (W_CheckNumForName)( sfxname_noext,0 ); + free(sfxname_noext); + if( lumpNum != -1 ) { + int lumpSize = W_LumpLength( lumpNum ); + byte* replacementSound = (byte*)malloc( lumpSize ); + replacementSound = (byte*)W_CacheLumpNum( lumpNum ); + uint16_t sampleRate = *((uint16_t*)(replacementSound + 2)); + uint32_t numSamples = (*((uint32_t*)(replacementSound + 4)) - 32); // remove 32 bytes of padding + alBufferData( sfx->alBufferNum, AL_FORMAT_MONO8, replacementSound + 0x18 + , numSamples + , sampleRate ); + } + } + } +} diff --git a/code/iphone/iphone_start.c b/code/iphone/iphone_start.cpp old mode 100644 new mode 100755 similarity index 73% rename from code/iphone/iphone_start.c rename to code/iphone/iphone_start.cpp index f571181..26ec535 --- a/code/iphone/iphone_start.c +++ b/code/iphone/iphone_start.cpp @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * iphone_start.c + * doom + * + * Created by John Carmack on 7/7/09. + * Copyright 2009 id Software. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -19,8 +27,23 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" +//#include "ios/GameCenter.h" + +// Only one game can be set up at a time on a given wireless segment, although +// several independent games can be played. +// If a valid setupPacket has arrived in the last second, that will be the +// displayed game, otherwise the local system starts sending out setupPackets. +packetSetup_t setupPacket; +int setupPacketFrameNum; +int localGameID; // change every time we take over as the sender of setupPackets +boolean levelHasBeenLoaded; // determines if "resume game" does a loadGame and exiting does a saveGame + +menuState_t menuState; +menuState_t lastState = IPM_GAME; +color4_t highlightColor = { 128, 128, 128, 255 }; +color4_t colorPressed = { 128, 128, 0, 255 }; /* ================== @@ -34,10 +57,23 @@ void ResumeGame() { iphoneResumeMusic(); drawWeaponSelect = false; weaponSelected = -1; - automapmode = 0; + automapmode = am_none; advancedemo = false; menuState = IPM_GAME; lastState = IPM_GAME; + + if ( statusBar->value ) { + R_SetViewSize( 10 ); + hud_displayed = 0; + hud_active = 0; + hud_distributed = 0; + } else { + R_SetViewSize( 11 ); + hud_displayed = 1; + hud_active = 2; + hud_distributed = 1; + } + return; } @@ -63,6 +99,8 @@ void ResumeGame() { ================== */ void GameSetup() { + netGameFailure = NF_NONE; + // resume game just goes back to playing, it doesn't load anything levelHasBeenLoaded = true; @@ -76,7 +114,7 @@ void GameSetup() { // display the game next time through the main loop drawWeaponSelect = false; weaponSelected = -1; - automapmode = 0; + automapmode = am_none; menuState = IPM_GAME; demoplayback = false; @@ -92,7 +130,18 @@ void GameSetup() { consoleplayer = 0; displayplayer = 0; playeringame[consoleplayer] = 1; -} + + if ( statusBar->value ) { + R_SetViewSize( 10 ); + hud_displayed = 0; + hud_active = 0; + hud_distributed = 0; + } else { + R_SetViewSize( 11 ); + hud_displayed = 1; + hud_active = 2; + hud_distributed = 1; + }} /* ======================= @@ -115,6 +164,9 @@ void StartSaveGame() { ======================= */ void StartSinglePlayerGame( mapStart_t map ) { + // Disconnect from a multiplayer game + //idGameCenter::DisconnectFromMatch(); + playState.map = map; playState.saveGameIsValid = true; // assume we will save the game on exit lastState = IPM_GAME; @@ -130,7 +182,7 @@ void StartSinglePlayerGame( mapStart_t map ) { GameSetup(); // start the map - G_InitNew( playState.map.skill, playState.map.episode, playState.map.map ); + G_InitNew( static_cast( playState.map.skill ), playState.map.episode, playState.map.map ); } @@ -152,6 +204,9 @@ boolean StartNetGame() { if ( slot == -1 ) { return false; } + + + GameSetup(); consoleplayer = displayplayer = slot; @@ -196,7 +251,7 @@ boolean StartNetGame() { gameID = setupPacket.gameID; // start the map - G_InitNew( setupPacket.map.skill, setupPacket.map.episode, setupPacket.map.map ); + G_InitNew( static_cast( setupPacket.map.skill ), setupPacket.map.episode, setupPacket.map.map ); return true; } @@ -226,3 +281,5 @@ void StartDemoGame( boolean timeDemoMode ) { advancedemo = true; } + + diff --git a/code/iphone/iphone_sys.mm b/code/iphone/iphone_sys.mm new file mode 100755 index 0000000..1c8c4f6 --- /dev/null +++ b/code/iphone/iphone_sys.mm @@ -0,0 +1,99 @@ +/* + + Copyright (C) 2009 Id Software, Inc. + + 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 "doomiphone.h" +#import +#import +#import "../ios/View.h" + +char consoleCommand[1024]; + +int SysIphoneMicroseconds() { + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday( &tp, &tzp ); + + if( ! secbase ) { + secbase = (int) tp.tv_sec; + return tp.tv_usec; + } + + int curtime = (int)((tp.tv_sec - secbase) * 1000000 + tp.tv_usec); + + return curtime; +} + +int SysIphoneMilliseconds() { + return SysIphoneMicroseconds()/1000; +} + + +char iphoneDocDirectory[PATH_MAX]; +char iphoneAppDirectory[PATH_MAX]; +char iphoneTempDirectory[PATH_MAX]; + +const char *SysIphoneGetAppDir() { + return iphoneAppDirectory; +} + +const char *SysIphoneGetDocDir() { + return iphoneDocDirectory; +} + +const char *SysIphoneGetTempDir() { + return iphoneTempDirectory; +} + +void SysIPhoneVibrate() { + AudioServicesPlaySystemSound( kSystemSoundID_Vibrate ); +} + + +void SysIPhoneOpenURL( const char *url ) { +#if !TARGET_OS_TV + Com_Printf( "OpenURL char *: %s\n", url ); + + NSString *nss = [NSString stringWithCString: url encoding: NSASCIIStringEncoding]; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString: nss]]; +#endif +} + +int SysIPhoneIsDeviceLandscapeRight( void ) { +#if TARGET_OS_TV + return 0; +#else + return [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight; +#endif +} + +void SysIPhoneSetUIKitOrientation( int isLandscapeRight ) { + // Using OS autorotation for now. If we ever want to support 60FPS on MBX devices, + // we'll probably have to go back to manual rotation for the GL view. + /* + if ( isLandscapeRight ) { + [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight; + } else { + [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeLeft; + } + */ +} diff --git a/code/iphone/main.m b/code/iphone/main.m old mode 100644 new mode 100755 index fbee33b..6c02e52 --- a/code/iphone/main.m +++ b/code/iphone/main.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -19,6 +19,7 @@ */ #import +#import "Doom_App.h" #include #include @@ -33,17 +34,17 @@ int main(int argc, char *argv[]) { // get the app directory based on argv[0] strcpy( iphoneAppDirectory, argv[0] ); - int len = strlen( iphoneAppDirectory ); - for( int i = len-1; i >= 0; i-- ) { - if ( iphoneAppDirectory[i] == '/' ) { - iphoneAppDirectory[i] = 0; - break; - } - iphoneAppDirectory[i] = 0; + + char * slashPosition = strrchr( iphoneAppDirectory, '/' ); + if ( slashPosition != NULL ) { + *slashPosition = 0; + } else { + iphoneAppDirectory[0] = 0; } NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); + NSString * classString = NSStringFromClass([DoomApp class]); + int retVal = UIApplicationMain(argc, argv, nil, classString ); [pool release]; return retVal; } diff --git a/code/iphone/misc.c b/code/iphone/misc.c old mode 100644 new mode 100755 index 05482cc..98edf53 --- a/code/iphone/misc.c +++ b/code/iphone/misc.c @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * misc.c + * doom + * + * Created by John Carmack on 4/13/09. + * Copyright 2009 idSoftware. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -19,7 +27,7 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" void Com_Printf( const char *fmt, ... ) { va_list argptr; @@ -31,7 +39,7 @@ void Com_Printf( const char *fmt, ... ) { vsnprintf( buffer, sizeof( buffer ), fmt, argptr ); AppendConsoleBuffer(buffer); - vprintf( fmt, argptr ); + printf( "%s\n", buffer ); va_end( argptr ); } @@ -53,7 +61,7 @@ void Com_Error( const char *fmt, ... ) { // drop into the editor abort(); - exit( 1 ); +// exit( 1 ); } char *va( const char *format, ... ) { diff --git a/code/iphone/misc.h b/code/iphone/misc.h old mode 100644 new mode 100755 index 8bfab77..4986292 --- a/code/iphone/misc.h +++ b/code/iphone/misc.h @@ -1,5 +1,13 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * misc.h + * doom + * + * Created by John Carmack on 4/13/09. + * Copyright 2009 idSoftware. All rights reserved. + * + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -41,7 +49,7 @@ typedef void (*xcommand_t) (void); void Cmd_AddCommand( const char *cmd_name, xcommand_t function ); // print all the added commands -void Cmd_ListCommands_f(); +void Cmd_ListCommands_f(void); // attempts to match a partial command for automatic command line completion // returns NULL if nothing fits diff --git a/code/iphone/prboomInterface.c b/code/iphone/prboomInterface.c old mode 100644 new mode 100755 index 461df40..d3e0f98 --- a/code/iphone/prboomInterface.c +++ b/code/iphone/prboomInterface.c @@ -1,5 +1,14 @@ /* - Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company. + * prboomInterface.c + * doom + * + * Created by John Carmack on 4/14/09. + * Copyright 2009 Id Software. All rights reserved. + * + * Stuff to get prboom to compile without SDL + */ +/* + Copyright (C) 2009 Id Software, Inc. This program is free software; you can redistribute it and/or @@ -19,7 +28,7 @@ */ -#include "../doomiphone.h" +#include "doomiphone.h" int desired_fullscreen; int usejoystick; @@ -54,7 +63,7 @@ void I_SafeExit(int rc) { } void I_uSleep( unsigned long usec ) { - usleep( usec ); + usleep( (unsigned int) usec ); } /* @@ -68,19 +77,33 @@ boolean HasTrailingSlash(const char* dn) return ( (dn[strlen(dn)-1] == '/') ); } -char* I_FindFile(const char* wfname, const char* ext) +void I_FindFile(const char* wfname, const char* ext, char * returnFileName ) { - char *p = malloc( 1024 ); - - sprintf( p, "%s/base/%s", SysIphoneGetAppDir(), wfname ); - if (access(p,F_OK)) - strcat(p, ext); // try adding the extension - if (!access(p,F_OK)) { - lprintf(LO_INFO, " found %s\n", p); - return p; + sprintf( returnFileName, "%s/%s", SysIphoneGetAppDir(), wfname ); + if (access(returnFileName,F_OK)) + strcat(returnFileName, ext); // try adding the extension + if (!access(returnFileName,F_OK)) { + lprintf(LO_INFO, " found %s\n", returnFileName); + + // Found the file. + return; } - free( p ); - return NULL; + + // JDS: try assuming it's a full path instead + sprintf( returnFileName, "%s", wfname ); + if (access(returnFileName,F_OK)) + strcat(returnFileName, ext); // try adding the extension + if (!access(returnFileName,F_OK)) { + lprintf(LO_INFO, " found %s\n", returnFileName); + + // Found the file. + return; + } + + // did not find the file. + returnFileName[0] = '\0'; + lprintf(LO_INFO, " NOT found %s\n", wfname ); + #if 0 // lookup table of directories to search static const struct { @@ -170,7 +193,7 @@ void I_Read(int fd, void* vbuf, size_t sz) unsigned char* buf = vbuf; while (sz) { - int rc = read(fd,buf,sz); + int rc = (int) read(fd,buf,sz); if (rc <= 0) { I_Error("I_Read: read failed: %s", rc ? strerror(errno) : "EOF"); } @@ -189,51 +212,7 @@ int I_Filelength(int handle) struct stat fileinfo; if (fstat(handle,&fileinfo) == -1) I_Error("I_Filelength: %s",strerror(errno)); - return fileinfo.st_size; -} - - - - - -// -// MUSIC I/O -// -void I_InitMusic(void) {} -void I_ShutdownMusic(void) {} - -void I_UpdateMusic(void) {} - -// Volume. -void I_SetMusicVolume(int volume) {} - -// PAUSE game handling. -void I_PauseSong(int handle) {} -void I_ResumeSong(int handle) {} - -// Registers a song handle to song data. -int I_RegisterSong(const void *data, size_t len) { - return 0; -} - -// cournia - tries to load a music file -int I_RegisterMusic( const char* filename, musicinfo_t *music ) { - return 0; -} - -// Called by anything that wishes to start music. -// plays a song, and when the song is done, -// starts playing it again in an endless loop. -// Horrible thing to do, considering. -void I_PlaySong(int handle, int looping) { -} - -// Stops a song over 3 seconds. -void I_StopSong(int handle) { -} - -// See above (register), then think backwards -void I_UnRegisterSong(int handle) { + return (int)fileinfo.st_size; } @@ -241,12 +220,12 @@ void I_UnRegisterSong(int handle) { void I_PreInitGraphics(void){} -void I_CalculateRes(unsigned int width, unsigned int height){} +void I_CalculateRes(unsigned int width, unsigned int height){ (void)width; (void)height; } void I_ShutdownGraphics(void){} -void I_SetPalette(int pal){} +void I_SetPalette(int pal){ (void)pal; } void I_UpdateNoBlit (void){} void I_FinishUpdate (void){} -int I_ScreenShot (const char *fname){return 0;} +int I_ScreenShot (const char *fname){ (void)fname; return 0;} // CPhipps - @@ -302,7 +281,7 @@ void I_InitGraphics(void) char titlebuffer[2048]; static int firsttime=1; - SCREENWIDTH = displaywidth; + SCREENWIDTH = displaywidth > MAX_SCREENWIDTH ? MAX_SCREENWIDTH : displaywidth; SCREENHEIGHT = displayheight; if (firsttime) @@ -347,9 +326,11 @@ void I_StartTic (void){} void I_StartFrame (void){} -void I_Init(){} +void I_Init() { + I_InitSound(); +} -unsigned int SDL_GetTicks() { return 0; }; +unsigned int SDL_GetTicks() { return 0; } int (*I_GetTime)(void) = I_GetTime_RealTime; diff --git a/code/libtess/geom.h b/code/libtess/geom.h old mode 100644 new mode 100755 index 5cb76c7..c87b4f0 --- a/code/libtess/geom.h +++ b/code/libtess/geom.h @@ -72,10 +72,10 @@ #define VertCCW(u,v,w) __gl_vertCCW(u,v,w) int __gl_vertLeq( GLUvertex *u, GLUvertex *v ); -GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ); -GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ); -GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ); -GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +double __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +double __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +double __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w ); +double __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w ); int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w ); void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1, GLUvertex *o2, GLUvertex *d2, diff --git a/code/libtess/mesh.h b/code/libtess/mesh.h old mode 100644 new mode 100755 index f2c30af..a24e76a --- a/code/libtess/mesh.h +++ b/code/libtess/mesh.h @@ -35,7 +35,7 @@ #ifndef __mesh_h_ #define __mesh_h_ -// JDC #include +#include typedef struct GLUmesh GLUmesh; @@ -118,8 +118,8 @@ struct GLUvertex { void *data; /* client's data */ /* Internal data (keep hidden) */ - GLdouble coords[3]; /* vertex location in 3D */ - GLdouble s, t; /* projection onto the sweep plane */ + double coords[3]; /* vertex location in 3D */ + double s, t; /* projection onto the sweep plane */ long pqHandle; /* to allow deletion from priority queue */ }; diff --git a/code/libtess/priorityq-heap.c b/code/libtess/priorityq-heap.c old mode 100644 new mode 100755 index e3a6c60..2d7d164 --- a/code/libtess/priorityq-heap.c +++ b/code/libtess/priorityq-heap.c @@ -34,6 +34,7 @@ #include #include +#include #include "priorityq-heap.h" #include "memalloc.h" diff --git a/code/libtess/tess.c b/code/libtess/tess.c old mode 100644 new mode 100755 index 627f1a7..af1735f --- a/code/libtess/tess.c +++ b/code/libtess/tess.c @@ -232,6 +232,9 @@ gluTessProperty( GLUtesselator *tess, GLenum which, GLdouble value ) CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_VALUE ); } +void GLAPIENTRY +gluGetTessProperty( GLUtesselator *tess, GLenum which, GLdouble *value ); + /* Returns tessellator property */ void GLAPIENTRY gluGetTessProperty( GLUtesselator *tess, GLenum which, GLdouble *value ) @@ -603,16 +606,16 @@ gluDeleteMesh( GLUmesh *mesh ) /*******************************************************/ /* Obsolete calls -- for backward compatibility */ - +/* void GLAPIENTRY gluBeginPolygon( GLUtesselator *tess ) { gluTessBeginPolygon( tess, NULL ); gluTessBeginContour( tess ); } +*/ - -/*ARGSUSED*/ +/*ARGSUSED*//* void GLAPIENTRY gluNextContour( GLUtesselator *tess, GLenum type ) { @@ -626,4 +629,4 @@ gluEndPolygon( GLUtesselator *tess ) { gluTessEndContour( tess ); gluTessEndPolygon( tess ); -} +}*/ diff --git a/code/prboom/SDL/i_sound.c b/code/prboom/SDL/i_sound.c new file mode 100755 index 0000000..c764ae0 --- /dev/null +++ b/code/prboom/SDL/i_sound.c @@ -0,0 +1,830 @@ +/* Emacs style mode select -*- C++ -*- + *----------------------------------------------------------------------------- + * + * + * PrBoom: a Doom port merged with LxDoom and LSDLDoom + * based on BOOM, a modified and improved DOOM engine + * Copyright (C) 1999 by + * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman + * Copyright (C) 1999-2000 by + * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze + * Copyright 2005, 2006 by + * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko + * + * 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. + * + * DESCRIPTION: + * System interface for sound. + * + *----------------------------------------------------------------------------- + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef HAVE_LIBSDL_MIXER +#define HAVE_MIXER +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif + + +// I'm hacking back in the MIDI music support. At this time, I only want +// music-related functions, so I'm adding this macro to remove sfx-related +// functions. +#define ID_DISABLE_SDL_SOUND 1 + +#ifndef ID_DISABLE_SDL_SOUND + +#include "SDL.h" +#include "SDL_audio.h" +#include "SDL_mutex.h" +#include "SDL_byteorder.h" +#include "SDL_version.h" + +#endif // ID_DISABLE_SDL_SOUND + +#ifdef HAVE_MIXER +#include "SDL_mixer.h" +#endif + +#include "z_zone.h" + +#include "m_swap.h" +#include "i_sound.h" +#include "m_argv.h" +#include "m_misc.h" +#include "w_wad.h" +#include "lprintf.h" +#include "s_sound.h" + +#include "doomdef.h" +#include "doomstat.h" +#include "doomtype.h" + +#include "d_main.h" + +// The number of internal mixing channels, +// the samples calculated for each mixing step, +// the size of the 16bit, 2 hardware channel (stereo) +// mixing buffer, and the samplerate of the raw data. + +// Variables used by Boom from Allegro +// created here to avoid changes to core Boom files +int snd_card = 1; +int mus_card = 1; +int detect_voices = 0; // God knows + +static boolean sound_inited = false; +static boolean first_sound_init = true; + +// Needed for calling the actual sound output. +static int SAMPLECOUNT= 512; +#define MAX_CHANNELS 32 + +// MWM 2000-01-08: Sample rate in samples/second +int snd_samplerate=11025; + +// The actual output device. +int audio_fd; + +typedef struct { + // SFX id of the playing sound effect. + // Used to catch duplicates (like chainsaw). + int id; +// The channel step amount... + unsigned int step; +// ... and a 0.16 bit remainder of last step. + unsigned int stepremainder; + unsigned int samplerate; +// The channel data pointers, start and end. + const unsigned char* data; + const unsigned char* enddata; +// Time/gametic that the channel started playing, +// used to determine oldest, which automatically +// has lowest priority. +// In case number of active sounds exceeds +// available channels. + int starttime; + // Hardware left and right channel volume lookup. + int *leftvol_lookup; + int *rightvol_lookup; +} channel_info_t; + +channel_info_t channelinfo[MAX_CHANNELS]; + +// Pitch to stepping lookup, unused. +int steptable[256]; + +// Volume lookups. +int vol_lookup[128*256]; + + + + +#ifndef ID_DISABLE_SDL_SOUND + + + + +/* cph + * stopchan + * Stops a sound, unlocks the data + */ + +static void stopchan(int i) +{ + if (channelinfo[i].data) /* cph - prevent excess unlocks */ + { + channelinfo[i].data=NULL; + W_UnlockLumpNum(S_sfx[channelinfo[i].id].lumpnum); + } +} + +// +// This function adds a sound to the +// list of currently active sounds, +// which is maintained as a given number +// (eight, usually) of internal channels. +// Returns a handle. +// +static int addsfx(int sfxid, int channel, const unsigned char* data, size_t len) +{ + stopchan(channel); + + channelinfo[channel].data = data; + /* Set pointer to end of raw data. */ + channelinfo[channel].enddata = channelinfo[channel].data + len - 1; + channelinfo[channel].samplerate = (channelinfo[channel].data[3]<<8)+channelinfo[channel].data[2]; + channelinfo[channel].data += 8; /* Skip header */ + + channelinfo[channel].stepremainder = 0; + // Should be gametic, I presume. + channelinfo[channel].starttime = gametic; + + // Preserve sound SFX id, + // e.g. for avoiding duplicates of chainsaw. + channelinfo[channel].id = sfxid; + + return channel; +} + +static void updateSoundParams(int handle, int volume, int seperation, int pitch) +{ + int slot = handle; + int rightvol; + int leftvol; + int step = steptable[pitch]; + +#ifdef RANGECHECK + if ((handle < 0) || (handle >= MAX_CHANNELS)) + I_Error("I_UpdateSoundParams: handle out of range"); +#endif + // Set stepping + // MWM 2000-12-24: Calculates proportion of channel samplerate + // to global samplerate for mixing purposes. + // Patched to shift left *then* divide, to minimize roundoff errors + // as well as to use SAMPLERATE as defined above, not to assume 11025 Hz + if (pitched_sounds) + channelinfo[slot].step = step + (((channelinfo[slot].samplerate<<16)/snd_samplerate)-65536); + else + channelinfo[slot].step = ((channelinfo[slot].samplerate<<16)/snd_samplerate); + + // Separation, that is, orientation/stereo. + // range is: 1 - 256 + seperation += 1; + + // Per left/right channel. + // x^2 seperation, + // adjust volume properly. + leftvol = volume - ((volume*seperation*seperation) >> 16); + seperation = seperation - 257; + rightvol= volume - ((volume*seperation*seperation) >> 16); + + // Sanity check, clamp volume. + if (rightvol < 0 || rightvol > 127) + I_Error("rightvol out of bounds"); + + if (leftvol < 0 || leftvol > 127) + I_Error("leftvol out of bounds"); + + // Get the proper lookup table piece + // for this volume level??? + channelinfo[slot].leftvol_lookup = &vol_lookup[leftvol*256]; + channelinfo[slot].rightvol_lookup = &vol_lookup[rightvol*256]; +} + +void I_UpdateSoundParams(int handle, int volume, int seperation, int pitch) +{ + SDL_LockAudio(); + updateSoundParams(handle, volume, seperation, pitch); + SDL_UnlockAudio(); +} + +// +// SFX API +// Note: this was called by S_Init. +// However, whatever they did in the +// old DPMS based DOS version, this +// were simply dummies in the Linux +// version. +// See soundserver initdata(). +// +void I_SetChannels(void) +{ + // Init internal lookups (raw data, mixing buffer, channels). + // This function sets up internal lookups used during + // the mixing process. + int i; + int j; + + int* steptablemid = steptable + 128; + + // Okay, reset internal mixing channels to zero. + for (i=0; iname); + return W_GetNumForName(namebuf); +} + +// +// Starting a sound means adding it +// to the current list of active sounds +// in the internal channels. +// As the SFX info struct contains +// e.g. a pointer to the raw data, +// it is ignored. +// As our sound handling does not handle +// priority, it is ignored. +// Pitching (that is, increased speed of playback) +// is set, but currently not used by mixing. +// +long int I_StartSound(int id, int channel, int vol, int sep, int pitch, int priority) +{ + const unsigned char* data; + int lump; + size_t len; + + if ((channel < 0) || (channel >= MAX_CHANNELS)) +#ifdef RANGECHECK + I_Error("I_StartSound: handle out of range"); +#else + return -1; +#endif + + lump = S_sfx[id].lumpnum; + + // We will handle the new SFX. + // Set pointer to raw data. + len = W_LumpLength(lump); + + // e6y: Crash with zero-length sounds. + // Example wad: dakills (http://www.doomworld.com/idgames/index.php?id=2803) + // The entries DSBSPWLK, DSBSPACT, DSSWTCHN and DSSWTCHX are all zero-length sounds + if (len<=8) return -1; + + /* Find padded length */ + len -= 8; + // do the lump caching outside the SDL_LockAudio/SDL_UnlockAudio pair + // use locking which makes sure the sound data is in a malloced area and + // not in a memory mapped one + data = W_LockLumpNum(lump); + + SDL_LockAudio(); + + // Returns a handle (not used). + addsfx(id, channel, data, len); + updateSoundParams(channel, vol, sep, pitch); + + SDL_UnlockAudio(); + + + return channel; +} + + + +void I_StopSound (int handle) +{ +#ifdef RANGECHECK + if ((handle < 0) || (handle >= MAX_CHANNELS)) + I_Error("I_StopSound: handle out of range"); +#endif + SDL_LockAudio(); + stopchan(handle); + SDL_UnlockAudio(); +} + + +boolean I_SoundIsPlaying(long int handle) +{ +#ifdef RANGECHECK + if ((handle < 0) || (handle >= MAX_CHANNELS)) + I_Error("I_SoundIsPlaying: handle out of range"); +#endif + return channelinfo[handle].data != NULL; +} + + +boolean I_AnySoundStillPlaying(void) +{ + boolean result = false; + int i; + + for (i=0; i> 16; + + // Add left and right part + // for this channel (sound) + // to the current data. + // Adjust volume accordingly. + dl += channelinfo[chan].leftvol_lookup[sample]; + dr += channelinfo[chan].rightvol_lookup[sample]; + // Increment index ??? + channelinfo[chan].stepremainder += channelinfo[chan].step; + // MSB is next sample??? + channelinfo[chan].data += channelinfo[chan].stepremainder >> 16; + // Limit to LSB??? + channelinfo[chan].stepremainder &= 0xffff; + + // Check whether we are done. + if (channelinfo[chan].data >= channelinfo[chan].enddata) + stopchan(chan); + } + } + + // Clamp to range. Left hardware channel. + // Has been char instead of short. + // if (dl > 127) *leftout = 127; + // else if (dl < -128) *leftout = -128; + // else *leftout = dl; + + if (dl > SHRT_MAX) + *leftout = SHRT_MAX; + else if (dl < SHRT_MIN) + *leftout = SHRT_MIN; + else + *leftout = (signed short)dl; + + // Same for right hardware channel. + if (dr > SHRT_MAX) + *rightout = SHRT_MAX; + else if (dr < SHRT_MIN) + *rightout = SHRT_MIN; + else + *rightout = (signed short)dr; + + // Increment current pointers in stream + leftout += step; + rightout += step; + } +#endif +} + +void I_ShutdownSound(void) +{ + if (sound_inited) { + lprintf(LO_INFO, "I_ShutdownSound: "); +#ifdef HAVE_MIXER + Mix_CloseAudio(); +#else + SDL_CloseAudio(); +#endif + lprintf(LO_INFO, "\n"); + sound_inited = false; + } +} + +//static SDL_AudioSpec audio; + +// Hack! Fix this if real SDL sound is reintroduced. +#define AUDIO_S16MSB 0 +#define AUDIO_S16LSB 0 + + +void I_InitSound(void) +{ +#ifdef HAVE_MIXER + int audio_rate; + uint16_t audio_format; + int audio_channels; + int audio_buffers; + + if (sound_inited) + I_ShutdownSound(); + + // Secure and configure sound device first. + lprintf(LO_INFO,"I_InitSound: "); + + /* Initialize variables */ + audio_rate = snd_samplerate; +#if ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) + audio_format = AUDIO_S16MSB; +#else + audio_format = AUDIO_S16LSB; +#endif + audio_channels = 2; + SAMPLECOUNT = 512; + audio_buffers = SAMPLECOUNT*snd_samplerate/11025; + + if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) { + lprintf(LO_INFO,"couldn't open audio with desired format\n"); + return; + } + sound_inited = true; + SAMPLECOUNT = audio_buffers; + Mix_SetPostMix(I_UpdateSound, NULL); + lprintf(LO_INFO," configured audio device with %d samples/slice\n", SAMPLECOUNT); +#else + SDL_AudioSpec audio; + + // Secure and configure sound device first. + lprintf(LO_INFO,"I_InitSound: "); + + // Open the audio device + audio.freq = snd_samplerate; +#if ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) + audio.format = AUDIO_S16MSB; +#else + audio.format = AUDIO_S16LSB; +#endif + audio.channels = 2; + audio.samples = SAMPLECOUNT*snd_samplerate/11025; + audio.callback = I_UpdateSound; + if ( SDL_OpenAudio(&audio, NULL) < 0 ) { + lprintf(LO_INFO,"couldn't open audio with desired format\n"); + return; + } + SAMPLECOUNT = audio.samples; + lprintf(LO_INFO," configured audio device with %d samples/slice\n", SAMPLECOUNT); +#endif + + if (first_sound_init) { + atexit(I_ShutdownSound); + first_sound_init = false; + } + + if (!nomusicparm) + I_InitMusic(); + + // Finished initialization. + lprintf(LO_INFO,"I_InitSound: sound module ready\n"); +#ifndef HAVE_MIXER + SDL_PauseAudio(0); +#endif +} + + + +// +// MUSIC API. +// + +#ifndef HAVE_OWN_MUSIC + +#ifdef HAVE_MIXER +#include "SDL_mixer.h" +#include "mmus2mid.h" + +static Mix_Music *music[2] = { NULL, NULL }; + +char* music_tmp = NULL; /* cph - name of music temporary file */ + +#endif + +void I_ShutdownMusic(void) +{ +#ifdef HAVE_MIXER + if (music_tmp) { + //unlink(music_tmp); + //lprintf(LO_DEBUG, "I_ShutdownMusic: removing %s\n", music_tmp); + free(music_tmp); + music_tmp = NULL; + } +#endif +} + +#ifdef IPHONE + +const char * SysIphoneGetTempDir(void); +static char iphoneMusicPath[PATH_MAX]; + +#endif + +void I_InitMusic(void) +{ + // Since we can load different IWADs in the same run of the iOS game, we need to clear + // the cached lumpnums for all the music, since they differ in different IWADs. + for ( int i = 0; i < NUMMUSIC; ++i ) { + S_music[i].lumpnum = 0; + } + +#ifdef HAVE_MIXER + if (!music_tmp) { +#ifndef _WIN32 + #ifdef IPHONE + + iphoneMusicPath[0] = '\0'; + strcat( iphoneMusicPath, SysIphoneGetTempDir() ); + strcat( iphoneMusicPath, "prboom-music-XXXXXX" ); + + music_tmp = strdup(iphoneMusicPath); + #else + music_tmp = strdup("/tmp/prboom-music-XXXXXX"); + #endif + { + int fd = mkstemp(music_tmp); + if (fd<0) { + lprintf(LO_ERROR, "I_InitMusic: failed to create music temp file %s", music_tmp); + free(music_tmp); return; + } else + close(fd); + } +#else /* !_WIN32 */ + music_tmp = strdup("doom.tmp"); +#endif + atexit(I_ShutdownMusic); + } +#endif +} + +extern int mus_pause_opt; // From m_misc.c +extern bool mus_on; + +void I_PlaySong(int handle, int looping) +{ +#ifdef HAVE_MIXER + if ( music[handle] && mus_on ) { + Mix_FadeInMusic(music[handle], looping ? -1 : 0, 500); + } + +#endif +} + +void I_PauseSong (int handle) +{ +#ifdef HAVE_MIXER + switch(mus_pause_opt) { + case 0: + I_StopSong(handle); + break; + case 1: + Mix_PauseMusic(); + break; + } +#endif + // Default - let music continue +} + +void I_ResumeSong (int handle) +{ +#ifdef HAVE_MIXER + switch(mus_pause_opt) { + case 0: + I_PlaySong(handle,1); + break; + case 1: + Mix_ResumeMusic(); + break; + } +#endif + /* Otherwise, music wasn't stopped */ +} + +void I_StopSong(int handle) +{ +#ifdef HAVE_MIXER + Mix_FadeOutMusic(500); +#endif +} + +void I_UnRegisterSong(int handle) +{ +#ifdef HAVE_MIXER + if ( music[handle] ) { + Mix_FreeMusic(music[handle]); + music[handle] = NULL; + } +#endif +} + +int I_RegisterSong(const void *data, size_t len) +{ +#ifdef HAVE_MIXER + MIDI *mididata; + FILE *midfile; + + if ( len < 32 ) + return 0; // the data should at least as big as the MUS header + if ( music_tmp == NULL ) + return 0; + midfile = fopen(music_tmp, "wb"); + if ( midfile == NULL ) { + lprintf(LO_ERROR,"Couldn't write MIDI to %s\n", music_tmp); + return 0; + } + /* Convert MUS chunk to MIDI? */ + if ( memcmp(data, "MUS", 3) == 0 ) + { + UBYTE *mid; + int midlen; + + mididata = malloc(sizeof(MIDI)); + int musResult = mmus2mid(data, mididata, 89, 0); + if ( musResult != 0 ) { + printf( "Failed to conver MUS to MIDI: %s\n", music_tmp ); + } + MIDIToMidi(mididata,&mid,&midlen); + M_WriteFile(music_tmp,mid,midlen); + free(mid); + free_mididata(mididata); + free(mididata); + } else { + fwrite(data, len, 1, midfile); + } + fclose(midfile); + + music[0] = Mix_LoadMUS(music_tmp); + if ( music[0] == NULL ) { + lprintf(LO_ERROR,"Couldn't load MIDI from %s: %s\n", music_tmp, Mix_GetError()); + } +#endif + return (0); +} + +char* I_RegisterMusic_MP3( musicinfo_t *song, const void *data, size_t len ) +{ + FILE *mp3file; + + //music->data, W_LumpLength(music->lumpnum) +// if (!song) return null; + + if ( len < 32 ) + return 0; // the data should at least as big as the MUS header + if ( music_tmp == NULL ) + return 0; + mp3file = fopen(music_tmp, "wb"); + if ( mp3file == NULL ) { + lprintf(LO_ERROR,"Couldn't write MP3 to %s\n", music_tmp); + return 0; + } + fwrite(data, len, 1, mp3file); + fclose(mp3file); + + return music_tmp; +} + +// cournia - try to load a music file into SDL_Mixer +// returns true if could not load the file +int I_RegisterMusic( const char* filename, musicinfo_t *song ) +{ +#ifdef HAVE_MIXER + if (!filename) return 1; + if (!song) return 1; + music[0] = Mix_LoadMUS(filename); + if (music[0] == NULL) + { + lprintf(LO_WARN,"Couldn't load music from %s: %s\nAttempting to load default MIDI music.\n", filename, Mix_GetError()); + return 1; + } + else + { + song->data = 0; + song->handle = 0; + song->lumpnum = 0; + return 0; + } +#else + return 1; +#endif +} + +void I_SetMusicVolume(int volume) +{ +#ifdef HAVE_MIXER + Mix_VolumeMusic(volume*8); +#endif +} + +#endif /* HAVE_OWN_MUSIC */ + diff --git a/code/prboom/SDL_opengl.h b/code/prboom/SDL_opengl.h old mode 100644 new mode 100755 index 8a73ee2..38b78fb --- a/code/prboom/SDL_opengl.h +++ b/code/prboom/SDL_opengl.h @@ -14,17 +14,18 @@ #include #include -#define GLAPIENTRY +#ifdef __cplusplus +extern "C" { +#endif -// this needs to be added before each projection matrix -int iphoneRotateForLandscape(); +#define GLAPIENTRY // no colorTable in ES typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); -static GLubyte *gluErrorString( int err ) { return (GLubyte *)"GLU error"; } -static void *SDL_GL_GetProcAddress( const char *proc ) { return 0; } -static void SDL_GL_SwapBuffers() {} +static inline GLubyte *gluErrorString( int err ) { (void)err; return (GLubyte *)"GLU error"; } +static inline void *SDL_GL_GetProcAddress( const char * proc ) { (void)proc; return 0; } +static inline void SDL_GL_SwapBuffers() {} // we need to emulate immediate mode gl for ES void glBegin( GLenum prim ); @@ -38,7 +39,7 @@ void glTexCoord2i( GLint s, GLint t ); void glTexCoord2f( GLfloat s, GLfloat t ); void glTexCoord2fv( GLfloat *st ); -void glEnd(); +void glEnd(void); // Doom just uses state color for all draw calls, setting it once // before a glBegin, rather than setting it each vertex, so we @@ -79,14 +80,12 @@ typedef double GLdouble; // this is the internal format used by the prBoom gl code // ES doesn't allow format conversions between external and internal, // so we need to manually convert to 5551 before doing glTexSubImage -#define GL_RGB5_A1 GL_RGBA #define GL_RGBA8 GL_RGBA -#define GL_RGBA4 GL_RGBA #define GL_RGBA2 GL_RGBA // not available in ES, so prBoom's skies must be implemeted differently -static void glTexGenfv( int a, int b, void *c ) { }; -static void glTexGenf( int a, int b, int c ) { }; +static inline void glTexGenfv( int a, int b, void * c ) { (void)a; (void)b; (void)c; } +static inline void glTexGenf( int a, int b, int c ) { (void)a; (void)b; (void)c; } // texGen enums not present in ES #define GL_S 0x2000 @@ -192,7 +191,7 @@ typedef GLUtesselator GLUtriangulatorObj; #define GLU_TESS_MAX_COORD 1.0e150 /* Internal convenience typedefs */ -typedef void (GLAPIENTRYP _GLUfuncptr)(); + typedef void (GLAPIENTRYP _GLUfuncptr)(void); GLAPI void GLAPIENTRY gluTessBeginContour (GLUtesselator* tess); GLAPI void GLAPIENTRY gluTessBeginPolygon (GLUtesselator* tess, GLvoid* data); @@ -206,6 +205,11 @@ GLAPI void GLAPIENTRY gluTessVertex (GLUtesselator* tess, GLdouble *location, GL GLUtesselator * GLAPIENTRY gluNewTess( void ); void GLAPIENTRY gluDeleteTess( GLUtesselator *tess ); +#ifdef __cplusplus +} +#endif + + #endif diff --git a/code/prboom/am_map.c b/code/prboom/am_map.c old mode 100644 new mode 100755 index c194670..d382e4e --- a/code/prboom/am_map.c +++ b/code/prboom/am_map.c @@ -50,6 +50,12 @@ #include "lprintf.h" // jff 08/03/98 - declaration of lprintf #include "g_game.h" +// IPHONE +#include "gles_glue.h" + +void iphoneSet2D( void ); + + //jff 1/7/98 default automap colors added int mapcolor_back; // map background int mapcolor_grid; // grid lines color @@ -1542,22 +1548,22 @@ static void AM_drawMarks(void) // // CPhipps - made static inline, and use the general pixel plotter function -inline static void AM_drawCrosshair(int color) -{ - fline_t line; - - line.a.x = (f_w/2)-1; - line.a.y = (f_h/2); - line.b.x = (f_w/2)+1; - line.b.y = (f_h/2); - V_DrawLine(&line, color); - - line.a.x = (f_w/2); - line.a.y = (f_h/2)-1; - line.b.x = (f_w/2); - line.b.y = (f_h/2)+1; - V_DrawLine(&line, color); -} +//inline static void AM_drawCrosshair(int color) +//{ +// fline_t line; +// +// line.a.x = (f_w/2)-1; +// line.a.y = (f_h/2); +// line.b.x = (f_w/2)+1; +// line.b.y = (f_h/2); +// V_DrawLine(&line, color); +// +// line.a.x = (f_w/2); +// line.a.y = (f_h/2)-1; +// line.b.x = (f_w/2); +// line.b.y = (f_h/2)+1; +// V_DrawLine(&line, color); +//} // // AM_Drawer() diff --git a/code/prboom/config.h b/code/prboom/config.h old mode 100644 new mode 100755 index 4cfdd5a..afcb64e --- a/code/prboom/config.h +++ b/code/prboom/config.h @@ -45,7 +45,7 @@ /**/ #define USE_SDL 1 -/*#define HAVE_MIXER 1*/ +#define HAVE_LIBSDL_MIXER 1 #define HAVE_NET 1 #define USE_SDL_NET 1 @@ -75,7 +75,7 @@ #define HAVE_IPv6 1 -#define HAVE_UNISTD_H +#define HAVE_UNISTD_H 1 #define HAVE_SYS_WAIT_H #define HAVE_GETOPT /* causes a duplicate define warning @@ -96,10 +96,6 @@ #define MACOSX #define HAVE_LIBKERN_OSBYTEORDER_H -#define HAVE_OWN_MUSIC -#define UPDATE_MUSIC -#define SCREENSHOT_DIR I_DoomExeDir() -#define HEAPDUMP_DIR I_DoomExeDir() //------ JDC config changes for iPhone ------------ @@ -110,3 +106,4 @@ #undef DOGS // not sure why this needs to be removed, info.c complains #undef USE_GLU_IMAGESCALE #undef USE_GLU_MIPMAP + diff --git a/code/prboom/d_client.c b/code/prboom/d_client.c old mode 100644 new mode 100755 index 9eed60a..a340bc2 --- a/code/prboom/d_client.c +++ b/code/prboom/d_client.c @@ -72,19 +72,21 @@ static boolean server; static int remotetic; // Tic expected from the remote -static int remotesend; // Tic expected by the remote +//static int remotesend; // Tic expected by the remote ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS]; static ticcmd_t* localcmds; -static unsigned numqueuedpackets; -static packet_header_t** queuedpacket; +//static unsigned numqueuedpackets; +//static packet_header_t** queuedpacket; int maketic; int ticdup = 1; -static int xtratics = 0; +//static int xtratics = 0; int wanted_player_number; static boolean isExtraDDisplay = false; +#ifdef HAVE_NET static void D_QuitNetGame (void); +#endif #ifndef HAVE_NET doomcom_t* doomcom; diff --git a/code/prboom/d_deh.c b/code/prboom/d_deh.c old mode 100644 new mode 100755 index d122668..9c10410 --- a/code/prboom/d_deh.c +++ b/code/prboom/d_deh.c @@ -83,16 +83,18 @@ typedef struct { static char *dehfgets(char *buf, size_t n, DEHFILE *fp) { if (!fp->lump) // If this is a real file, - return (fgets)(buf, n, fp->f); // return regular fgets + return (fgets)(buf, (int)n, fp->f); // return regular fgets if (!n || !*fp->inp || fp->size<=0) // If no more characters return NULL; - if (n==1) - fp->size--, *buf = *fp->inp++; + if (n==1) { + fp->size--; + *buf = *fp->inp++; + } else { // copy buffer char *p = buf; while (n>1 && *fp->inp && fp->size && - (n--, fp->size--, *p++ = *fp->inp++) != '\n') + ((void)(n--), (void)(fp->size--), *p++ = *fp->inp++) != '\n') ; *p = 0; } @@ -107,7 +109,7 @@ static int dehfeof(DEHFILE *fp) static int dehfgetc(DEHFILE *fp) { return !fp->lump ? fgetc(fp->f) : fp->size > 0 ? - fp->size--, *fp->inp++ : EOF; + (void)(fp->size--), *fp->inp++ : EOF; } // haleyjd 9/22/99 @@ -169,6 +171,7 @@ const char *s_GOTREDCARD = GOTREDCARD; const char *s_GOTBLUESKUL = GOTBLUESKUL; const char *s_GOTYELWSKUL = GOTYELWSKUL; const char *s_GOTREDSKULL = GOTREDSKULL; +const char *s_GOTSECRET = GOTSECRET; const char *s_GOTINVUL = GOTINVUL; const char *s_GOTBERSERK = GOTBERSERK; const char *s_GOTINVIS = GOTINVIS; @@ -508,6 +511,7 @@ static const deh_strs deh_strlookup[] = { {&s_GOTBLUESKUL,"GOTBLUESKUL"}, {&s_GOTYELWSKUL,"GOTYELWSKUL"}, {&s_GOTREDSKULL,"GOTREDSKULL"}, + {&s_GOTSECRET,"GOTSECRET"}, {&s_GOTINVUL,"GOTINVUL"}, {&s_GOTBERSERK,"GOTBERSERK"}, {&s_GOTINVIS,"GOTINVIS"}, @@ -1476,7 +1480,10 @@ void ProcessDehFile(const char *filename, const char *outfilename, int lumpnum) // file but using the BEX format to handle strings if (!strnicmp(nextfile = ptr_lstrip(inbuffer+7),"NOTEXT",6)) - includenotext = true, nextfile = ptr_lstrip(nextfile+6); + { + includenotext = true; + nextfile = ptr_lstrip(nextfile+6); + } if (fileout) fprintf(fileout,"Branching to include file %s...\n", nextfile); @@ -1932,7 +1939,7 @@ static void deh_procPointer(DEHFILE *fpin, FILE* fpout, char *line) // done continue; } - if (value < 0 || value >= NUMSTATES) + if (value >= NUMSTATES) { if (fpout) fprintf(fpout,"Bad pointer number %lld of %d\n",value, NUMSTATES); @@ -1975,6 +1982,9 @@ static void deh_procPointer(DEHFILE *fpin, FILE* fpout, char *line) // done // static void deh_procSounds(DEHFILE *fpin, FILE* fpout, char *line) { + assert( false || "Does the iOS version ever call this function? I hope not." ); + (void)deh_sfxinfo; +#if 0 char key[DEH_MAXKEYLEN]; char inbuffer[DEH_BUFFERMAX]; uint_64_t value; // All deh values are ints or longs @@ -2031,6 +2041,7 @@ static void deh_procSounds(DEHFILE *fpin, FILE* fpout, char *line) "Invalid sound string index for '%s'\n",key); } return; +#endif } // ==================================================================== @@ -2702,7 +2713,7 @@ boolean deh_procStringSub(char *key, char *lookfor, char *newstring, FILE *fpout for (s=*deh_strlookup[i].ppstr; *s; ++s, ++t) { if (*s == '\\' && (s[1] == 'n' || s[1] == 'N')) //found one - ++s, *t = '\n'; // skip one extra for second character + (void)(++s), *t = '\n'; // skip one extra for second character else *t = *s; } @@ -2871,7 +2882,7 @@ static void deh_procBexSounds(DEHFILE *fpin, FILE *fpout, char *line) // do it memset(candidate, 0, 7); strncpy(candidate, ptr_lstrip(strval), 6); - len = strlen(candidate); + len = (int)strlen(candidate); if(len < 1 || len > 6) { if(fpout) @@ -2930,7 +2941,7 @@ static void deh_procBexMusic(DEHFILE *fpin, FILE *fpout, char *line) // do it memset(candidate, 0, 7); strncpy(candidate, ptr_lstrip(strval), 6); - len = strlen(candidate); + len = (int)strlen(candidate); if(len < 1 || len > 6) { if(fpout) @@ -2980,7 +2991,7 @@ char *dehReformatStr(char *string) while (*s) { if (*s == '\n') - ++s, *t++ = '\\', *t++ = 'n', *t++ = '\\', *t++='\n'; + (void)(++s), (void)(*t++ = '\\'), (void)(*t++ = 'n'), (void)(*t++ = '\\'), *t++='\n'; else *t++ = *s++; } diff --git a/code/prboom/d_deh.h b/code/prboom/d_deh.h old mode 100644 new mode 100755 index 02cdffa..9fb51f7 --- a/code/prboom/d_deh.h +++ b/code/prboom/d_deh.h @@ -171,6 +171,9 @@ extern const char *s_GOTYELWSKUL; // = GOTYELWSKUL; //#define GOTREDSKULL "Picked up a red skull key." extern const char *s_GOTREDSKULL; // = GOTREDSKULL; +//#define GOTSECRET "Secret found." +extern const char *s_GOTSECRET; // = GOTSECRET; + //#define GOTINVUL "Invulnerability!" extern const char *s_GOTINVUL; // = GOTINVUL; //#define GOTBERSERK "Berserk!" diff --git a/code/prboom/d_englsh.h b/code/prboom/d_englsh.h old mode 100644 new mode 100755 index bf8dfef..6c2fb73 --- a/code/prboom/d_englsh.h +++ b/code/prboom/d_englsh.h @@ -44,30 +44,30 @@ #define PRESSKEY "press a key." #define PRESSYN "press y or n." #define QUITMSG "are you sure you want to\nquit this great game?" -#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY -#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY -#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY -#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY -#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN -#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n"PRESSYN +#define LOADNET "you can't do load while in a net game!\n\n" PRESSKEY +#define QLOADNET "you can't quickload during a netgame!\n\n" PRESSKEY +#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n" PRESSKEY +#define SAVEDEAD "you can't save if you aren't playing!\n\n" PRESSKEY +#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n" PRESSYN +#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n" PRESSYN #define NEWGAME \ "you can't start a new game\n"\ - "while in a network game.\n\n"PRESSKEY + "while in a network game.\n\n" PRESSKEY #define NIGHTMARE \ "are you sure? this skill level\n"\ - "isn't even remotely fair.\n\n"PRESSYN + "isn't even remotely fair.\n\n" PRESSYN #define SWSTRING \ "this is the shareware version of doom.\n\n"\ - "you need to order the entire trilogy.\n\n"PRESSKEY + "you need to order the entire trilogy.\n\n" PRESSKEY #define MSGOFF "Messages OFF" #define MSGON "Messages ON" -#define NETEND "you can't end a netgame!\n\n"PRESSKEY -#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN -#define RESTARTLEVEL "restart the level?\n\n"PRESSYN +#define NETEND "you can't end a netgame!\n\n" PRESSKEY +#define ENDGAME "are you sure you want to end the game?\n\n" PRESSYN +#define RESTARTLEVEL "restart the level?\n\n" PRESSYN #define DOSY "(press y to quit)" @@ -97,6 +97,8 @@ #define GOTYELWSKUL "Picked up a yellow skull key." #define GOTREDSKULL "Picked up a red skull key." +#define GOTSECRET "Secret found." + #define GOTINVUL "Invulnerability!" #define GOTBERSERK "Berserk!" #define GOTINVIS "Partial Invisibility" diff --git a/code/prboom/d_items.h b/code/prboom/d_items.h old mode 100644 new mode 100755 index 8da4df2..766f9f4 --- a/code/prboom/d_items.h +++ b/code/prboom/d_items.h @@ -37,9 +37,6 @@ #include "doomdef.h" -#ifdef __GNUG__ -#pragma interface -#endif /* Weapon info: sprite frames, ammunition use. */ diff --git a/code/prboom/d_main.c b/code/prboom/d_main.c old mode 100644 new mode 100755 index 9fb21ce..59ca588 --- a/code/prboom/d_main.c +++ b/code/prboom/d_main.c @@ -82,6 +82,7 @@ #include "d_deh.h" // Ty 04/08/98 - Externalizations #include "lprintf.h" // jff 08/03/98 - declaration of lprintf #include "am_map.h" +#include "doomiphone.h" void GetFirstMap(int *ep, int *map); // Ty 08/29/98 - add "-warp x" functionality static void D_PageDrawer(void); @@ -127,7 +128,7 @@ char basesavegame[PATH_MAX+1]; // killough 2/16/98: savegame directory const char *const standard_iwads[]= { "doom2f.wad", - "HERETIC.WAD", + "doom2.wad", "plutonia.wad", "tnt.wad", "doom.wad", @@ -135,7 +136,7 @@ const char *const standard_iwads[]= "doomu.wad", /* CPhipps - alow doomu.wad */ "freedoom.wad", /* wart@kobold.org: added freedoom for Fedora Extras */ }; -static const int nstandard_iwads = sizeof standard_iwads/sizeof*standard_iwads; +//static const int nstandard_iwads = sizeof standard_iwads/sizeof*standard_iwads; /* * D_PostEvent - Event handling @@ -222,7 +223,7 @@ void D_Display (void) wipe_StartScreen(); if (gamestate != GS_LEVEL) { // Not a level - switch (oldgamestate) { + switch ((int)oldgamestate) { case -1: case GS_LEVEL: V_SetPalette(0); // cph - use default (basic) palette @@ -341,6 +342,8 @@ static const char *auto_shot_fname; // calls I_GetTime, I_StartFrame, and I_StartTic // +// This function is unused on iOS. +#ifndef IPHONE static void D_DoomLoop(void) { for (;;) @@ -387,6 +390,7 @@ static void D_DoomLoop(void) } } } +#endif // // DEMO LOOP @@ -504,24 +508,24 @@ static struct }, { - {NULL}, - {NULL}, - {NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, {D_SetPageName, "CREDIT"}, }, { - {NULL}, - {NULL}, - {NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, {G_DeferedPlayDemo, "demo4"}, }, { - {NULL}, - {NULL}, - {NULL}, - {NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, } }; @@ -634,8 +638,8 @@ static void CheckIWAD(const char *iwadname,GameMode_t *gmode,boolean *hassec) filelump_t *fileinfo; // read IWAD directory - header.numlumps = LONG(header.numlumps); - header.infotableofs = LONG(header.infotableofs); + header.numlumps = (int)LONG(header.numlumps); + header.infotableofs = (int)LONG(header.infotableofs); length = header.numlumps; fileinfo = malloc(length*sizeof(filelump_t)); if (fseek (fp, header.infotableofs, SEEK_SET) || @@ -716,7 +720,7 @@ static void NormalizeSlashes(char *str) // killough 1/18/98: Neater / \ handling. // Remove trailing / or \ to prevent // /\ \/ \\, and change \ to / - if (!str || !(l = strlen(str))) + if (!str || !(l = (int)strlen(str))) return; if (str[--l]=='/' || str[l]=='\\') // killough 1/18/98 str[l]=0; @@ -732,6 +736,9 @@ static void NormalizeSlashes(char *str) * CPhipps - static, proper prototype * - 12/1999 - rewritten to use I_FindFile */ +// TODO: We may restore this function later, if we send in iwad selection as a "parameter" +// in order to remain closer to vanilla prboom. +#ifndef IPHONE static char *FindIWADFile(void) { int i; @@ -746,6 +753,7 @@ static char *FindIWADFile(void) } return iwad; } +#endif // // IdentifyVersion @@ -767,12 +775,15 @@ static char *FindIWADFile(void) // d) or $HOME // // jff 4/19/98 rewritten to use a more advanced search algorithm +// +// Added an iwad parameter to IdentifyVersion - this makes it easier to use this +// code in a library shared between multiple games. -static void IdentifyVersion (void) +static void IdentifyVersion ( const char * iwad ) { int i; //jff 3/24/98 index of args on commandline struct stat sbuf; //jff 3/24/98 used to test save path for existence - char *iwad; + //const char *iwad; // set save path to -save parm or current dir @@ -800,7 +811,8 @@ static void IdentifyVersion (void) // locate the IWAD and determine game mode from it - iwad = FindIWADFile(); + //iwad = FindIWADFile(); + //iwad = iphoneFindIWADFile(); #if (defined(GL_DOOM) && defined(_DEBUG)) // proff 11/99: used for debugging @@ -832,7 +844,7 @@ static void IdentifyVersion (void) gamemission = doom; break; case commercial: - i = strlen(iwad); + i = (int)strlen(iwad); gamemission = doom2; if (i>=10 && !strnicmp(iwad+i-10,"doom2f.wad",10)) language=french; @@ -849,7 +861,8 @@ static void IdentifyVersion (void) //jff 9/3/98 use logical output routine lprintf(LO_WARN,"Unknown Game Version, may not work\n"); D_AddFile(iwad,source_iwad); - free(iwad); + + //free(iwad); } else I_Error("IdentifyVersion: IWAD not found\n"); @@ -1017,7 +1030,7 @@ static void DoLooseFiles(void) if (*myargv[i] == '-') break; // quit at first switch // so now we must have a loose file. Find out what kind and store it. - j = strlen(myargv[i]); + j = (int)strlen(myargv[i]); if (!stricmp(&myargv[i][j-4],".wad")) wads[wadcount++] = strdup(myargv[i]); if (!stricmp(&myargv[i][j-4],".lmp")) @@ -1109,7 +1122,7 @@ static void DoLooseFiles(void) const char *wad_files[MAXLOADFILES], *deh_files[MAXLOADFILES]; // CPhipps - misc screen stuff -unsigned int desired_screenwidth, desired_screenheight; +int desired_screenwidth, desired_screenheight; static void L_SetupConsoleMasks(void) { int p; @@ -1146,11 +1159,20 @@ static void L_SetupConsoleMasks(void) { // // CPhipps - the old contents of D_DoomMain, but moved out of the main // line of execution so its stack space can be freed +// +// Added iwad and pwad parameters to facilitate using this code in a library shared between +// multiple games. +void iphoneAddPWADFiles(void); -/* JDC static */ void D_DoomMainSetup(void) +/* JDC static */ void D_DoomMainSetup( const char * iwad, const char * pwad ) { int p,slot; - + + numwadfiles = 0; + R_FlushAllPatches(); + gld_CleanMemory(); + + L_SetupConsoleMasks(); setbuf(stdout,NULL); @@ -1183,17 +1205,14 @@ static void L_SetupConsoleMasks(void) { D_BuildBEXTables(); // haleyjd DoLooseFiles(); // Ty 08/29/98 - handle "loose" files on command line - IdentifyVersion(); + IdentifyVersion( iwad ); // Load prboom.wad after IWAD but before everything else { - char *data_wad_path = I_FindFile(PACKAGE ".wad", ".wad"); - - if (!data_wad_path) - I_Error(PACKAGE ".wad not found - cannot continue"); + char data_wad_path[ 1024 ]; + I_FindFile(PACKAGE ".wad", ".wad", data_wad_path ); D_AddFile(data_wad_path, source_pre); - free(data_wad_path); } // e6y: DEH files preloaded in wrong order @@ -1425,22 +1444,19 @@ static void L_SetupConsoleMasks(void) { for (i=0; i= MAXLOADFILES) ProcessDehFile(fpath, D_dehout(), 0); else { D_AddFile(fpath,source_auto_load); } modifiedgame = true; - free(fpath); - } + } } @@ -1491,6 +1507,24 @@ static void L_SetupConsoleMasks(void) { D_AddFile(myargv[p],source_pwad); } + // Add any iphone pwads (for example, No Rest for the Living is a pwad). + while(pwad && *pwad) { + char pwad_to_add[1024]; + char* pwadloc_end = strchr(pwad,PWAD_LIST_SEPARATOR); + unsigned long i = 0; + if( pwadloc_end ) { + while( pwad != pwadloc_end ) { + pwad_to_add[i++] = *pwad++; + } + pwad_to_add[i] = '\0'; + pwad++; // advance past separator + D_AddFile( pwad_to_add, source_pwad ); + } else { + Com_Printf("Error processing PWADs: %s (%X)", pwad,pwadloc_end); + break; + } + } + if (!(p = M_CheckParm("-playdemo")) || p >= myargc-1) { /* killough */ if ((p = M_CheckParm ("-fastdemo")) && p < myargc-1) /* killough */ fastdemo = true; // run at fastest speed possible @@ -1536,6 +1570,9 @@ static void L_SetupConsoleMasks(void) { V_InitColorTranslation(); //jff 4/24/98 load color translation lumps + // JDS: replace sounds with lumps + I_OverwriteSoundBuffersWithLumps(); + // killough 2/22/98: copyright / "modified game" / SPA banners removed // Ty 04/08/98 - Add 5 lines of misc. data, only if nonblank @@ -1550,7 +1587,7 @@ static void L_SetupConsoleMasks(void) { //jff 9/3/98 use logical output routine lprintf(LO_INFO,"M_Init: Init miscellaneous info.\n"); - M_Init(); + //M_Init(); #ifdef HAVE_NET // CPhipps - now wait for netgame start @@ -1656,13 +1693,15 @@ static void L_SetupConsoleMasks(void) { // // D_DoomMain // - +// Not called in iphone version. +/* void D_DoomMain(void) { D_DoomMainSetup(); // CPhipps - setup out of main execution stack D_DoomLoop (); // never returns } +*/ // // GetFirstMap diff --git a/code/prboom/d_main.h b/code/prboom/d_main.h old mode 100644 new mode 100755 index d6b9b6e..146b724 --- a/code/prboom/d_main.h +++ b/code/prboom/d_main.h @@ -37,9 +37,6 @@ #include "d_event.h" #include "w_wad.h" -#ifdef __GNUG__ -#pragma interface -#endif /* CPhipps - removed wadfiles[] stuff to w_wad.h */ @@ -70,6 +67,7 @@ void D_DoAdvanceDemo (void); void D_Display(void); void D_PageTicker(void); void D_StartTitle(void); +void D_DoomMainSetup( const char * iwad, const char * pwad ); void D_DoomMain(void); void D_AddFile (const char *file, wad_source_t source); diff --git a/code/prboom/d_net.h b/code/prboom/d_net.h old mode 100644 new mode 100755 index fcdeb6c..e5fd377 --- a/code/prboom/d_net.h +++ b/code/prboom/d_net.h @@ -38,9 +38,6 @@ #include "d_player.h" -#ifdef __GNUG__ -#pragma interface -#endif // diff --git a/code/prboom/d_player.h b/code/prboom/d_player.h old mode 100644 new mode 100755 index a45abe8..363d43f --- a/code/prboom/d_player.h +++ b/code/prboom/d_player.h @@ -52,9 +52,6 @@ // as commands per game tick. #include "d_ticcmd.h" -#ifdef __GNUG__ -#pragma interface -#endif // diff --git a/code/prboom/d_server.c b/code/prboom/d_server.c deleted file mode 100644 index dd16483..0000000 --- a/code/prboom/d_server.c +++ /dev/null @@ -1,754 +0,0 @@ -/* Emacs style mode select -*- C++ -*- - *----------------------------------------------------------------------------- - * - * - * PrBoom: a Doom port merged with LxDoom and LSDLDoom - * based on BOOM, a modified and improved DOOM engine - * Copyright (C) 1999 by - * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman - * Copyright (C) 1999-2004 by - * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze - * Copyright 2005, 2006 by - * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko - * - * 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. - * - * DESCRIPTION: - * Network game server code - * New for LxDoom, but drawing ideas and code fragments from the - * earlier net code - *----------------------------------------------------------------------------- - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include - -#ifdef USE_SDL_NET - #include "SDL.h" -#endif - -#include "doomtype.h" -#include "protocol.h" -#include "i_network.h" -#ifndef PRBOOM_SERVER -#include "m_fixed.h" -#endif -#include "i_system.h" -#include "m_swap.h" - -#ifndef HAVE_NET - -int main(void) -{ - fprintf(stderr, - PACKAGE "-server: You must compile with networking enabled!\n"); - exit(1); - return 1; -} - -#else - -#ifndef HAVE_GETOPT -/* The following code for getopt is from the libc-source of FreeBSD, - * it might be changed a little bit. - * Florian Schulze (florian.schulze@gmx.net) - */ - -/* - * Copyright (c) 1987, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; -#endif -static const char rcsid[] = "$FreeBSD$"; -#endif /* LIBC_SCCS and not lint */ - -int opterr = 1, /* if error message should be printed */ - optind = 1, /* index into parent argv vector */ - optopt, /* character checked for validity */ - optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ - -#define BADCH (int)'?' -#define BADARG (int)':' -#define EMSG "" - -char *__progname="prboom_server"; - -/* - * getopt -- - * Parse argc/argv argument vector. - */ -int -getopt(nargc, nargv, ostr) - int nargc; - char * const *nargv; - const char *ostr; -{ - extern char *__progname; - static char *place = EMSG; /* option letter processing */ - char *oli; /* option letter list index */ - int ret; - - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc || *(place = nargv[optind]) != '-') { - place = EMSG; - return (-1); - } - if (place[1] && *++place == '-') { /* found "--" */ - ++optind; - place = EMSG; - return (-1); - } - } /* option letter okay? */ - if ((optopt = (int)*place++) == (int)':' || - !(oli = strchr(ostr, optopt))) { - /* - * if the user didn't specify '-' as an option, - * assume it means -1. - */ - if (optopt == (int)'-') - return (-1); - if (!*place) - ++optind; - if (opterr && *ostr != ':') - (void)fprintf(stderr, - "%s: illegal option -- %c\n", __progname, optopt); - return (BADCH); - } - if (*++oli != ':') { /* don't need argument */ - optarg = NULL; - if (!*place) - ++optind; - } - else { /* need an argument */ - if (*place) /* no white space */ - optarg = place; - else if (nargc <= ++optind) { /* no arg */ - place = EMSG; - if (*ostr == ':') - ret = BADARG; - else - ret = BADCH; - if (opterr) - (void)fprintf(stderr, - "%s: option requires an argument -- %c\n", - __progname, optopt); - return (ret); - } - else /* white space */ - optarg = nargv[optind]; - place = EMSG; - ++optind; - } - return (optopt); /* dump back option letter */ -} -#else -#include -#endif - -#define MAXPLAYERS 4 -#define BACKUPTICS 12 - -// Dummies to forfill l_udp.c unused client stuff -int M_CheckParm(const char* p) { p = NULL; return 1; } -int myargc; -char** myargv; - -void NORETURN I_Error(const char *error, ...) // killough 3/20/98: add const -{ - va_list argptr; - va_start(argptr,error); - vfprintf(stderr,error,argptr); - va_end(argptr); - exit(-1); -} - -int playerjoingame[MAXPLAYERS], playerleftgame[MAXPLAYERS]; -UDP_CHANNEL remoteaddr[MAXPLAYERS]; -enum { pc_unused, pc_connected, pc_ready, pc_confirmedready, pc_playing, pc_quit } playerstate[MAXPLAYERS]; -int displaycounter; - -boolean n_players_in_state(int n, int ps) { - int i,j; - for (i=j=0;itic); -} - - - -void read_config_file(FILE* fp, struct setup_packet_s* sp) -{ - byte* gameopt = sp->game_options; - - while (!feof(fp)) { - char def[80]; - char strparm[100]; - if (fscanf (fp, "%79s %99[^\n]\n", def, strparm) == 2) { - int v = atoi(strparm); - if (!strcmp(def,"default_skill")) { - if (verbose) printf("config file sets default_skill to %d\n",v); - sp->skill = v-1; - } else if (!strcmp(def,"default_compatibility_level")) { - if (verbose) printf("config file sets compatibility_level to %d\n",v); - if (v == -1) v = MAX_COMPATIBILITY_LEVEL-1; //e6y: -1 => maxcompat - sp->complevel = v; - } else { - int i; - for (i=0; i= MAXPLAYERS); } - -int main(int argc, char** argv) -{ -#ifndef USE_SDL_NET - int localport = 5030; -#else - Uint16 localport = 5030; -#endif - int numplayers = 2, xtratics = 0, ticdup = 1; - int exectics = 0; // gametics completed - struct setup_packet_s setupinfo = { 2, 0, 1, 1, 1, 0, best_compatibility, 0, 0}; - char**wadname = NULL; - char**wadget = NULL; - int numwads = 0; - { - int opt; - byte *gameopt = setupinfo.game_options; - - memcpy(gameopt, &def_game_options, sizeof (setupinfo.game_options)); - while ((opt = getopt(argc, argv, "c:t:x:p:e:l:adrfns:N:vw:")) != EOF) - switch (opt) { - case 'c': - { - FILE *cf = fopen(optarg,"r"); - if (!cf) { perror("fopen"); return -1; } - read_config_file(cf,&setupinfo); - fclose(cf); - } - break; - case 't': - if (optarg) ticdup = atoi(optarg); - break; - case 'x': - if (optarg) xtratics = atoi(optarg); - break; - case 'p': - if (optarg) localport = atoi(optarg); - break; - case 'e': - if (optarg) setupinfo.episode = atoi(optarg); - break; - case 'l': - if (optarg) setupinfo.level = atoi(optarg); - break; - case 'a': - setupinfo.deathmatch = 2; - break; - case 'd': - setupinfo.deathmatch = 1; - break; - case 'r': - setupinfo.game_options[6] = 1; - break; - case 'f': - setupinfo.game_options[7] = 1; - break; - case 'n': - setupinfo.game_options[8] = 1; - break; - case 's': - if (optarg) setupinfo.skill = atoi(optarg)-1; - break; - case 'N': - if (optarg) setupinfo.players = numplayers = atoi(optarg); - break; - case 'v': - verbose++; - break; - case 'w': - if (optarg) { - char *p; - wadname = realloc(wadname, ++numwads * sizeof *wadname); - wadget = realloc(wadget , numwads * sizeof *wadget ); - wadname[numwads-1] = strdup(optarg); - if ((p = strchr(wadname[numwads-1], ','))) { - *p++ = 0; wadget[numwads-1] = p; - } else wadget[numwads-1] = NULL; - } - break; - } - } - - setupinfo.ticdup = ticdup; setupinfo.extratic = xtratics; - { /* Random number seed - * Mirrors the corresponding code in G_ReadOptions */ - int rngseed = (int)time(NULL); - setupinfo.game_options[13] = rngseed & 0xff; - rngseed >>= 8; - setupinfo.game_options[12] = rngseed & 0xff; - rngseed >>= 8; - setupinfo.game_options[11] = rngseed & 0xff; - rngseed >>= 8; - setupinfo.game_options[10] = rngseed & 0xff; - } - I_InitSockets(localport); - - printf("Listening on port %d, waiting for %d players\n", localport, numplayers); - - { // no players initially - int i; - for (i=0; i2) printf("Received packet:"); - switch (packet->type) { - case PKT_INIT: - if (!ingame) { - { - int n; - struct setup_packet_s *sinfo = (void*)(packet+1); - - /* Find player number and add to the game */ - n = *(short*)(packet+1); - - if (badplayer(n) || playerstate[n] != pc_unused) - for (n=0; nyourplayer = n; - sinfo->numwads = numwads; - for (i=0; iwadnames + extrabytes, wadname[i]); - extrabytes += strlen(wadname[i]) + 1; - } - I_SendPacketTo(packet, sizeof *packet + sizeof setupinfo + extrabytes, - remoteaddr+n); - I_uSleep(10000); - I_SendPacketTo(packet, sizeof *packet + sizeof setupinfo + extrabytes, - remoteaddr+n); - } - } - } - break; - case PKT_GO: - if (!ingame) { - int from = *(byte*)(packet+1); - - if (badplayer(from) || playerstate[from] == pc_unused) break; - if (confirming) { - if (playerstate[from] != pc_confirmedready) curplayers++; - playerstate[from] = pc_confirmedready; - } else - playerstate[from] = pc_ready; - } - break; - case PKT_TICC: - { - byte tics = *(byte*)(packet+1); - int from = *(((byte*)(packet+1))+1); - - if (badplayer(from)) break; - - if (verbose>2) - printf("tics %ld - %ld from %d\n", ptic(packet), ptic(packet) + tics - 1, from); - if (ptic(packet) > remoteticfrom[from]) { - // Missed tics, so request a resend - packet_set(packet, PKT_RETRANS, remoteticfrom[from]); - I_SendPacketTo(packet, sizeof *packet, remoteaddr+from); - } else { - ticcmd_t *newtic = (void*)(((byte*)(packet+1))+2); - if (ptic(packet) + tics < remoteticfrom[from]) break; // Won't help - remoteticfrom[from] = ptic(packet); - while (tics--) - netcmds[from][remoteticfrom[from]++%BACKUPTICS] = *newtic++; - } - } - break; - case PKT_RETRANS: - { - int from = *(byte*)(packet+1); - if (badplayer(from)) break; - - if (verbose>2) printf("%d requests resend from %d\n", from, ptic(packet)); - remoteticto[from] = ptic(packet); - } - break; - case PKT_QUIT: - { - int from = *(byte*)(packet+1); - if (badplayer(from)) break; - - if (!ingame && playerstate[from] != pc_unused) { - // If we already got a PKT_GO, we have to remove this player frmo the count of ready players. And we then flag this player slot as vacant. - printf("player %d pulls out\n", from); - if (playerstate[from] == pc_confirmedready) curplayers--; - playerstate[from] = pc_unused; - } else - if (playerleftgame[from] == INT_MAX) { // In the game - playerleftgame[from] = ptic(packet); - --curplayers; - if (verbose) printf("%d quits at %d (%d left)\n", from, ptic(packet),curplayers); - if (ingame && !curplayers) exit(0); // All players have exited - } - } - // Fall through and broadcast it - case PKT_EXTRA: - BroadcastPacket(packet, len); - if (packet->type == PKT_EXTRA) { - if (verbose>2) printf("misc from %d\n", *(((byte*)(packet+1))+1)); - } - break; - case PKT_WAD: - { - int i; - int from = *(byte*)(packet+1); - char *name = 1 + (char*)(packet+1); - size_t size = sizeof(packet_header_t); - packet_header_t *reply; - - if (badplayer(from) || playerstate[from] != pc_unused) break; - - if (verbose) printf("Request for %s ", name); - for (i=0; itype); - break; - } - } - free(packet); - if (!ingame && n_players_in_state(numplayers,pc_confirmedready)) { - int i; - packet_header_t gopacket; - packet = &gopacket; - ingame=true; - printf("All players joined, beginning game.\n"); - for (i=0; i1) printf("%d new tics can be run\n", lowtic - exectics); - - if (lowtic > exectics) - exectics = lowtic; // count exec'ed tics - // Now send all tics up to lowtic - for (i=0; i1) printf("sending %d tics to %d\n", tics, i); - while (tics--) { - int j, playersthistic = 0; - byte *q = p++; - for (j=0; j remoteticto[i])) { - *p++ = j; - memcpy(p, &netcmds[j][remoteticto[i]%BACKUPTICS], sizeof(ticcmd_t)); - p += sizeof(ticcmd_t); - playersthistic++; - } - *q = playersthistic; - remoteticto[i]++; - } - I_SendPacketTo(packet, p - ((byte*)packet), remoteaddr+i); - free(packet); - } - { - if (remoteticfrom[i] == remoteticto[i]) { - backoffcounter[i] = 0; - } else if (remoteticfrom[i] > remoteticto[i]+1) { - if ((backoffcounter[i] += remoteticfrom[i] - remoteticto[i] - 1) > 35) { - packet_header_t *packet = malloc(sizeof(packet_header_t)); - packet_set(packet, PKT_BACKOFF, remoteticto[i]); - I_SendPacketTo(packet,sizeof *packet,remoteaddr+i); - backoffcounter[i] = 0; - if (verbose) printf("telling client %d to back off\n",i); - free(packet); - } - } - } - } - } - if (!((ingame ? 0xff : 0xf) & displaycounter++)) { - int i; - fprintf(stderr,"Player states: ["); - for (i=0;i + +typedef int boolean; + typedef unsigned char byte; + #endif //e6y diff --git a/code/prboom/f_finale.c b/code/prboom/f_finale.c old mode 100644 new mode 100755 index 1a96c33..43ba371 --- a/code/prboom/f_finale.c +++ b/code/prboom/f_finale.c @@ -192,7 +192,7 @@ boolean F_Responder (event_t *event) static float Get_TextSpeed(void) { return midstage ? NEWTEXTSPEED : (midstage=acceleratestage) ? - acceleratestage=0, NEWTEXTSPEED : TEXTSPEED; + (void)(acceleratestage=0), NEWTEXTSPEED : TEXTSPEED; } @@ -361,7 +361,7 @@ void F_StartCast (void) wipegamestate = -1; // force a screen wipe castnum = 0; caststate = &states[mobjinfo[castorder[castnum].type].seestate]; - casttics = caststate->tics; + casttics = (int)caststate->tics; castdeath = false; finalestage = 2; castframes = 0; @@ -471,7 +471,7 @@ void F_CastTicker (void) } } - casttics = caststate->tics; + casttics = (int)caststate->tics; if (casttics == -1) casttics = 15; } @@ -492,7 +492,7 @@ boolean F_CastResponder (event_t* ev) // go into death frame castdeath = true; caststate = &states[mobjinfo[castorder[castnum].type].deathstate]; - casttics = caststate->tics; + casttics = (int)caststate->tics; castframes = 0; castattacking = false; if (mobjinfo[castorder[castnum].type].deathsound) @@ -663,6 +663,10 @@ void F_Drawer (void) case 4: V_DrawNamePatch(0, 0, 0, "ENDPIC", CR_DEFAULT, VPT_STRETCH); break; + case 5: + // SIGIL + V_DrawNamePatch(0, 0, 0, "SIGILEND", CR_DEFAULT, VPT_STRETCH); + break; } } } diff --git a/code/prboom/g_game.c b/code/prboom/g_game.c old mode 100644 new mode 100755 index c3eb032..67bcaeb --- a/code/prboom/g_game.c +++ b/code/prboom/g_game.c @@ -87,6 +87,10 @@ #include "r_demo.h" #include "r_fps.h" +void iphoneStartLevel(void); +void iphoneIntermission(void); +void iphoneMainMenu(void); + #define SAVEGAMESIZE 0x20000 #define SAVESTRINGSIZE 24 @@ -130,7 +134,7 @@ int demover; boolean singledemo; // quit after playing a demo from cmdline wbstartstruct_t wminfo; // parms for world map / intermission boolean haswolflevels = false;// jff 4/18/98 wolf levels present -static byte *savebuffer; // CPhipps - static +static byte *savebuffer; // CPhipps - static int autorun = false; // always running? // phares int totalleveltimes; // CPhipps - total time for all completed levels int longtics; @@ -625,8 +629,8 @@ static void G_DoLoadLevel (void) joyxmove = joyymove = 0; mousex = mousey = 0; special_event = 0; paused = false; - memset (mousebuttons, 0, sizeof(mousebuttons)); - memset (joybuttons, 0, sizeof(joybuttons)); + memset (mousearray, 0, sizeof(mousearray)); + memset (joyarray, 0, sizeof(joyarray)); // killough 5/13/98: in case netdemo has consoleplayer other than green ST_Start(); @@ -697,7 +701,7 @@ boolean G_Responder (event_t* ev) ((ev->type == ev_keydown) || (ev->type == ev_mouse && ev->data1) || (ev->type == ev_joystick && ev->data1)) ? - M_StartControlPanel(), true : false; + (void)(M_StartControlPanel()), true : false; } if (gamestate == GS_FINALE && F_Responder(ev)) @@ -763,10 +767,11 @@ void G_Ticker (void) // CPhipps - player colour changing if (!demoplayback && mapcolor_plyr[consoleplayer] != mapcolor_me) { // Changed my multiplayer colour - Inform the whole game - int net_cl = LONG(mapcolor_me); + int net_cl = (int)LONG(mapcolor_me); #ifdef HAVE_NET D_NetSendMisc(nm_plcolour, sizeof(net_cl), &net_cl); #endif + (void)net_cl; G_ChangedPlayerColour(consoleplayer, mapcolor_me); } P_MapStart(); @@ -1161,7 +1166,7 @@ static boolean G_CheckSpot(int playernum, mapthing_t *mthing) // void G_DeathMatchSpawnPlayer (int playernum) { - int j, selections = deathmatch_p - deathmatchstarts; + int j, selections = (int)(deathmatch_p - deathmatchstarts); if (selections < MAXPLAYERS) I_Error("G_DeathMatchSpawnPlayer: Only %i deathmatch spots, %d required", @@ -1383,10 +1388,6 @@ void G_DoCompleted (void) } WI_Start (&wminfo); - -#ifdef IPHONE - iphoneIntermission( &wminfo ); -#endif } // @@ -1420,16 +1421,28 @@ void G_WorldDone (void) gameaction = ga_victory; // cph - after ExM8 summary screen, show victory stuff } +extern float *freeLevelOfWeek; // actually cvar, but value is first element +extern boolean levelHasBeenLoaded; void G_DoWorldDone (void) -{ +{ + // JAF Added Free level of Week Check. + if( *freeLevelOfWeek == 1 ) { + gameaction = ga_nothing; + levelHasBeenLoaded = false; + iphoneMainMenu(); + return; + } + idmusnum = -1; //jff 3/17/98 allow new level's music to be loaded gamestate = GS_LEVEL; gamemap = wminfo.next+1; G_DoLoadLevel(); gameaction = ga_nothing; AM_clearMarks(); //jff 4/12/98 clear any marks on the automap - - iphoneStartLevel(); // JDC: update playState and set the "tried level" flag + + // automatic save game + G_SaveGame( 0, "entersave" ); + G_DoSaveGame(true); } // killough 2/28/98: A ridiculously large number @@ -1458,7 +1471,7 @@ static uint_64_t G_UpdateSignature(uint_64_t s, const char *name) int size = W_LumpLength(i); const byte *p = W_CacheLumpNum(i); while (size--) - s <<= 1, s += *p++; + (void)(s <<= 1), s += *p++; W_UnlockLumpNum(i); } while (--i > lump); @@ -1476,12 +1489,15 @@ static uint_64_t G_Signature(void) computed = true; if (gamemode == commercial) for (map = haswolflevels ? 32 : 30; map; map--) - sprintf(name, "map%02d", map), s = G_UpdateSignature(s, name); + { + sprintf(name, "map%02d", map); + s = G_UpdateSignature(s, name); + } else for (episode = gamemode==retail ? 4 : gamemode==shareware ? 1 : 3; episode; episode--) for (map = 9; map; map--) - sprintf(name, "E%dM%d", episode, map), s = G_UpdateSignature(s, name); + (void)(sprintf(name, "E%dM%d", episode, map)), s = G_UpdateSignature(s, name); } return s; } @@ -1512,6 +1528,9 @@ void G_LoadGame(int slot, boolean command) } else { // Do the old thing, immediate load gameaction = ga_loadgame; +//#warning FIXME checksum: was false, but issues when loading savegames (checksum seems to be different) +// forced_loadgame = true; + // MAY NEED TVOS FIXES? -tkidd forced_loadgame = false; savegameslot = slot; demoplayback = false; @@ -1568,10 +1587,10 @@ static const size_t num_version_headers = sizeof(version_headers) / sizeof(versi boolean G_SaveGameValid() { - int length, i; + int length; // CPhipps - do savegame filename stuff here char name[PATH_MAX+1]; // killough 3/22/98 - int savegame_compatibility = -1; + //int savegame_compatibility = -1; G_SaveGameName(name,sizeof(name),savegameslot, demoplayback); @@ -1598,8 +1617,11 @@ void G_DoLoadGame(void) gameaction = ga_nothing; length = M_ReadFile(name, &savebuffer); - if (length<=0) - I_Error("Couldn't read file %s: %s", name, "(Unknown Error)"); + if (length<=0) { + //I_Error("Couldn't read file %s: %s", name, "(Unknown Error)"); + doom_printf("No save game found."); + return; + } save_p = savebuffer + SAVESTRINGSIZE; // CPhipps - read the description field, compare with supported ones @@ -1608,7 +1630,7 @@ void G_DoLoadGame(void) // killough 2/22/98: "proprietary" version string :-) sprintf (vcheck, version_headers[i].ver_printf, version_headers[i].version); - if (!strncmp(save_p, vcheck, VERSIONSIZE)) { + if (!strncmp( (char*)save_p, vcheck, VERSIONSIZE)) { savegame_compatibility = version_headers[i].comp_level; i = num_version_headers; } @@ -1633,10 +1655,10 @@ void G_DoLoadGame(void) if (memcmp(&checksum, save_p, sizeof checksum)) { if (!forced_loadgame) { - char *msg = malloc(strlen(save_p + sizeof checksum) + 128); + char *msg = malloc(strlen( (char*)save_p + sizeof checksum) + 128); strcpy(msg,"Incompatible Savegame!!!\n"); if (save_p[sizeof checksum]) - strcat(strcat(msg,"Wads expected:\n\n"), save_p + sizeof checksum); + strcat(strcat(msg,"Wads expected:\n\n"), (char*)save_p + sizeof checksum); strcat(msg, "\nAre you sure?"); G_LoadGameErr(msg); free(msg); @@ -1647,7 +1669,7 @@ void G_DoLoadGame(void) save_p += sizeof checksum; } - save_p += strlen(save_p)+1; + save_p += strlen( (char*)save_p)+1; compatibility_level = (savegame_compatibility >= prboom_4_compatibility) ? *save_p : savegame_compatibility; if (savegame_compatibility < prboom_6_compatibility) @@ -1668,7 +1690,7 @@ void G_DoLoadGame(void) /* killough 3/1/98: Read game options * killough 11/98: move down to here */ - save_p = (char*)G_ReadOptions(save_p); + save_p = (byte*)G_ReadOptions(save_p); // load a base level G_InitNew (gameskill, gameepisode, gamemap); @@ -1728,7 +1750,7 @@ void G_DoLoadGame(void) // Description is a 24 byte text string // -void G_SaveGame(int slot, char *description) +void G_SaveGame(int slot, const char *description) { strcpy(savedescription, description); if (demoplayback) { @@ -1758,7 +1780,7 @@ void (CheckSaveGame)(size_t size, const char* file, int line) static int prevl; if (pos > prev_check) - I_Error("CheckSaveGame at %s:%d called for insufficient buffer (%u < %u)", prevf, prevl, prev_check, pos); + I_Error("CheckSaveGame at %s:%d called for insufficient buffer (%lu < %lu)", prevf, prevl, prev_check, pos); prev_check = size + pos; prevf = file; prevl = line; @@ -1775,9 +1797,9 @@ void (CheckSaveGame)(size_t size, const char* file, int line) * cph - Avoid possible buffer overflow problems by passing * size to this function and using snprintf */ -void G_SaveGameName(char *name, size_t size, int slot, boolean demoplayback) +void G_SaveGameName(char *name, size_t size, int slot, boolean isDemoplayback) { - const char* sgn = demoplayback ? "demosav" : savegamename; + const char* sgn = savegamename; #ifdef HAVE_SNPRINTF snprintf (name, size, "%s/%s%d.dsg", basesavegame, sgn, slot); #else @@ -1826,13 +1848,13 @@ void G_SaveGameName(char *name, size_t size, int slot, boolean demoplayback) // killough 3/16/98: store pwad filenames in savegame { // CPhipps - changed for new wadfiles handling - size_t i; - for (i = 0; i= -1) compatibility_level = l; } } - if (compatibility_level == -1) - compatibility_level = best_compatibility; +// if (compatibility_level == -1) +// compatibility_level = best_compatibility; if (mbf_features) memcpy(comp, default_comp, sizeof comp); @@ -2176,8 +2198,13 @@ void G_InitNew(skill_t skill, int episode, int map) if (gamemode == retail) { - if (episode > 4) - episode = 4; +#if GAME_SIGIL + if (episode > 5) + episode = 5; +#else + if (episode > 4) + episode = 4; +#endif } else if (gamemode == shareware) @@ -2185,9 +2212,6 @@ void G_InitNew(skill_t skill, int episode, int map) if (episode > 1) episode = 1; // only start episode 1 on shareware } - else - if (episode > 3) - episode = 3; if (map < 1) map = 1; @@ -2281,7 +2305,7 @@ void G_WriteDemoTiccmd (ticcmd_t* cmd) I_Error("G_WriteDemoTiccmd: error writing demo"); /* cph - alias demo_p to it so we can read it back */ - demo_p = buf; + demo_p = (const byte*)buf; G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same } @@ -2304,7 +2328,7 @@ void G_RecordDemo (const char* name) demofp = fopen(demoname, "r+"); if (demofp) { int slot = -1; - int rc; + int rc = 0; int bytes_per_tic; const byte* pos; @@ -2323,7 +2347,7 @@ void G_RecordDemo (const char* name) do { byte buf[5]; - rc = fread(buf, 1, bytes_per_tic, demofp); + rc = (int)fread(buf, 1, bytes_per_tic, demofp); if (buf[0] == DEMOMARKER) break; if (buf[bytes_per_tic-1] & BT_SPECIAL) if ((buf[bytes_per_tic-1] & BT_SPECIALMASK) == BTS_SAVEGAME) @@ -2351,82 +2375,82 @@ void G_RecordDemo (const char* name) extern int forceOldBsp; -byte *G_WriteOptions(byte *demo_p) +byte *G_WriteOptions(byte *theDemo_p) { - byte *target = demo_p + GAME_OPTION_SIZE; + byte *target = theDemo_p + GAME_OPTION_SIZE; - *demo_p++ = monsters_remember; // part of monster AI + *theDemo_p++ = monsters_remember; // part of monster AI - *demo_p++ = variable_friction; // ice & mud + *theDemo_p++ = variable_friction; // ice & mud - *demo_p++ = weapon_recoil; // weapon recoil + *theDemo_p++ = weapon_recoil; // weapon recoil - *demo_p++ = allow_pushers; // MT_PUSH Things + *theDemo_p++ = allow_pushers; // MT_PUSH Things - *demo_p++ = 0; + *theDemo_p++ = 0; - *demo_p++ = player_bobbing; // whether player bobs or not + *theDemo_p++ = player_bobbing; // whether player bobs or not // killough 3/6/98: add parameters to savegame, move around some in demos - *demo_p++ = respawnparm; - *demo_p++ = fastparm; - *demo_p++ = nomonsters; + *theDemo_p++ = respawnparm; + *theDemo_p++ = fastparm; + *theDemo_p++ = nomonsters; - *demo_p++ = demo_insurance; // killough 3/31/98 + *theDemo_p++ = demo_insurance; // killough 3/31/98 // killough 3/26/98: Added rngseed. 3/31/98: moved here - *demo_p++ = (byte)((rngseed >> 24) & 0xff); - *demo_p++ = (byte)((rngseed >> 16) & 0xff); - *demo_p++ = (byte)((rngseed >> 8) & 0xff); - *demo_p++ = (byte)( rngseed & 0xff); + *theDemo_p++ = (byte)((rngseed >> 24) & 0xff); + *theDemo_p++ = (byte)((rngseed >> 16) & 0xff); + *theDemo_p++ = (byte)((rngseed >> 8) & 0xff); + *theDemo_p++ = (byte)( rngseed & 0xff); // Options new to v2.03 begin here - *demo_p++ = monster_infighting; // killough 7/19/98 + *theDemo_p++ = monster_infighting; // killough 7/19/98 #ifdef DOGS - *demo_p++ = dogs; // killough 7/19/98 + *theDemo_p++ = dogs; // killough 7/19/98 #else - *demo_p++ = 0; + *theDemo_p++ = 0; #endif - *demo_p++ = 0; - *demo_p++ = 0; + *theDemo_p++ = 0; + *theDemo_p++ = 0; - *demo_p++ = (distfriend >> 8) & 0xff; // killough 8/8/98 - *demo_p++ = distfriend & 0xff; // killough 8/8/98 + *theDemo_p++ = (distfriend >> 8) & 0xff; // killough 8/8/98 + *theDemo_p++ = distfriend & 0xff; // killough 8/8/98 - *demo_p++ = monster_backing; // killough 9/8/98 + *theDemo_p++ = monster_backing; // killough 9/8/98 - *demo_p++ = monster_avoid_hazards; // killough 9/9/98 + *theDemo_p++ = monster_avoid_hazards; // killough 9/9/98 - *demo_p++ = monster_friction; // killough 10/98 + *theDemo_p++ = monster_friction; // killough 10/98 - *demo_p++ = help_friends; // killough 9/9/98 + *theDemo_p++ = help_friends; // killough 9/9/98 #ifdef DOGS - *demo_p++ = dog_jumping; + *theDemo_p++ = dog_jumping; #else - *demo_p++ = 0; + *theDemo_p++ = 0; #endif - *demo_p++ = monkeys; + *theDemo_p++ = monkeys; { // killough 10/98: a compatibility vector now int i; for (i=0; i < COMP_TOTAL; i++) - *demo_p++ = comp[i] != 0; + *theDemo_p++ = comp[i] != 0; } - *demo_p++ = (compatibility_level >= prboom_2_compatibility) && forceOldBsp; // cph 2002/07/20 + *theDemo_p++ = (compatibility_level >= prboom_2_compatibility) && forceOldBsp; // cph 2002/07/20 //---------------- // Padding at end //---------------- - while (demo_p < target) - *demo_p++ = 0; + while (theDemo_p < target) + *theDemo_p++ = 0; - if (demo_p != target) + if (theDemo_p != target) I_Error("G_WriteOptions: GAME_OPTION_SIZE is too small"); return target; @@ -2436,82 +2460,82 @@ byte *G_WriteOptions(byte *demo_p) * cph - const byte*'s */ -const byte *G_ReadOptions(const byte *demo_p) +const byte *G_ReadOptions(const byte *theDemo_p) { - const byte *target = demo_p + GAME_OPTION_SIZE; + const byte *target = theDemo_p + GAME_OPTION_SIZE; - monsters_remember = *demo_p++; + monsters_remember = *theDemo_p++; - variable_friction = *demo_p; // ice & mud - demo_p++; + variable_friction = *theDemo_p; // ice & mud + theDemo_p++; - weapon_recoil = *demo_p; // weapon recoil - demo_p++; + weapon_recoil = *theDemo_p; // weapon recoil + theDemo_p++; - allow_pushers = *demo_p; // MT_PUSH Things - demo_p++; + allow_pushers = *theDemo_p; // MT_PUSH Things + theDemo_p++; - demo_p++; + theDemo_p++; - player_bobbing = *demo_p; // whether player bobs or not - demo_p++; + player_bobbing = *theDemo_p; // whether player bobs or not + theDemo_p++; // killough 3/6/98: add parameters to savegame, move from demo - respawnparm = *demo_p++; - fastparm = *demo_p++; - nomonsters = *demo_p++; + respawnparm = *theDemo_p++; + fastparm = *theDemo_p++; + nomonsters = *theDemo_p++; - demo_insurance = *demo_p++; // killough 3/31/98 + demo_insurance = *theDemo_p++; // killough 3/31/98 // killough 3/26/98: Added rngseed to demos; 3/31/98: moved here - rngseed = *demo_p++ & 0xff; + rngseed = *theDemo_p++ & 0xff; rngseed <<= 8; - rngseed += *demo_p++ & 0xff; + rngseed += *theDemo_p++ & 0xff; rngseed <<= 8; - rngseed += *demo_p++ & 0xff; + rngseed += *theDemo_p++ & 0xff; rngseed <<= 8; - rngseed += *demo_p++ & 0xff; + rngseed += *theDemo_p++ & 0xff; // Options new to v2.03 if (mbf_features) { - monster_infighting = *demo_p++; // killough 7/19/98 + monster_infighting = *theDemo_p++; // killough 7/19/98 #ifdef DOGS - dogs = *demo_p++; // killough 7/19/98 + dogs = *theDemo_p++; // killough 7/19/98 #else - demo_p++; + theDemo_p++; #endif - demo_p += 2; + theDemo_p += 2; - distfriend = *demo_p++ << 8; // killough 8/8/98 - distfriend+= *demo_p++; + distfriend = *theDemo_p++ << 8; // killough 8/8/98 + distfriend+= *theDemo_p++; - monster_backing = *demo_p++; // killough 9/8/98 + monster_backing = *theDemo_p++; // killough 9/8/98 - monster_avoid_hazards = *demo_p++; // killough 9/9/98 + monster_avoid_hazards = *theDemo_p++; // killough 9/9/98 - monster_friction = *demo_p++; // killough 10/98 + monster_friction = *theDemo_p++; // killough 10/98 - help_friends = *demo_p++; // killough 9/9/98 + help_friends = *theDemo_p++; // killough 9/9/98 #ifdef DOGS - dog_jumping = *demo_p++; // killough 10/98 + dog_jumping = *theDemo_p++; // killough 10/98 #else - demo_p++; + theDemo_p++; #endif - monkeys = *demo_p++; + monkeys = *theDemo_p++; { // killough 10/98: a compatibility vector now int i; for (i=0; i < COMP_TOTAL; i++) - comp[i] = *demo_p++; + comp[i] = *theDemo_p++; } - forceOldBsp = *demo_p++; // cph 2002/07/20 + forceOldBsp = *theDemo_p++; // cph 2002/07/20 } else /* defaults for versions <= 2.02 */ { @@ -2525,14 +2549,14 @@ const byte *G_ReadOptions(const byte *demo_p) void G_BeginRecording (void) { int i; - byte *demostart, *demo_p; - demostart = demo_p = malloc(1000); + byte *demostart, *theDemo_p; + demostart = theDemo_p = malloc(1000); longtics = 0; /* cph - 3 demo record formats supported: MBF+, BOOM, and Doom v1.9 */ if (mbf_features) { { /* Write version code into demo */ - unsigned char v; + unsigned char v = '\0'; switch(compatibility_level) { case mbf_compatibility: v = 203; break; // e6y: Bug in MBF compatibility mode fixed case prboom_2_compatibility: v = 210; break; @@ -2543,94 +2567,95 @@ void G_BeginRecording (void) v = 214; longtics = 1; break; + default: break; } - *demo_p++ = v; + *theDemo_p++ = v; } // signature - *demo_p++ = 0x1d; - *demo_p++ = 'M'; - *demo_p++ = 'B'; - *demo_p++ = 'F'; - *demo_p++ = 0xe6; - *demo_p++ = '\0'; + *theDemo_p++ = 0x1d; + *theDemo_p++ = 'M'; + *theDemo_p++ = 'B'; + *theDemo_p++ = 'F'; + *theDemo_p++ = 0xe6; + *theDemo_p++ = '\0'; /* killough 2/22/98: save compatibility flag in new demos * cph - FIXME? MBF demos will always be not in compat. mode */ - *demo_p++ = 0; + *theDemo_p++ = 0; - *demo_p++ = gameskill; - *demo_p++ = gameepisode; - *demo_p++ = gamemap; - *demo_p++ = deathmatch; - *demo_p++ = consoleplayer; + *theDemo_p++ = gameskill; + *theDemo_p++ = gameepisode; + *theDemo_p++ = gamemap; + *theDemo_p++ = deathmatch; + *theDemo_p++ = consoleplayer; - demo_p = G_WriteOptions(demo_p); // killough 3/1/98: Save game options + theDemo_p = G_WriteOptions(theDemo_p); // killough 3/1/98: Save game options for (i=0 ; i boom_compatibility_compatibility) { - byte v, c; /* Nominally, version and compatibility bits */ + byte v = '\0', c = '\0'; /* Nominally, version and compatibility bits */ switch (compatibility_level) { - case boom_compatibility_compatibility: v = 202, c = 1; break; + case boom_compatibility_compatibility: (void)(v = 202), c = 1; break; case boom_201_compatibility: v = 201; c = 0; break; - case boom_202_compatibility: v = 202, c = 0; break; + case boom_202_compatibility: (void)(v = 202), c = 0; break; default: I_Error("G_BeginRecording: Boom compatibility level unrecognised?"); } - *demo_p++ = v; + *theDemo_p++ = v; // signature - *demo_p++ = 0x1d; - *demo_p++ = 'B'; - *demo_p++ = 'o'; - *demo_p++ = 'o'; - *demo_p++ = 'm'; - *demo_p++ = 0xe6; + *theDemo_p++ = 0x1d; + *theDemo_p++ = 'B'; + *theDemo_p++ = 'o'; + *theDemo_p++ = 'o'; + *theDemo_p++ = 'm'; + *theDemo_p++ = 0xe6; /* CPhipps - save compatibility level in demos */ - *demo_p++ = c; + *theDemo_p++ = c; - *demo_p++ = gameskill; - *demo_p++ = gameepisode; - *demo_p++ = gamemap; - *demo_p++ = deathmatch; - *demo_p++ = consoleplayer; + *theDemo_p++ = gameskill; + *theDemo_p++ = gameepisode; + *theDemo_p++ = gamemap; + *theDemo_p++ = deathmatch; + *theDemo_p++ = consoleplayer; - demo_p = G_WriteOptions(demo_p); // killough 3/1/98: Save game options + theDemo_p = G_WriteOptions(theDemo_p); // killough 3/1/98: Save game options for (i=0 ; i= 100) // For demos from versions >= 1.4 - { +// if ((skill=demover) >= 100) // For demos from versions >= 1.4 +// { //e6y: check for overrun - if (CheckForOverrun(header_p, demo_p, size, 8, failonerror)) + if (CheckForOverrun(header_p, theDemo_p, size, 8, failonerror)) return NULL; compatibility_level = G_GetOriginalDoomCompatLevel(demover); - skill = *demo_p++; - episode = *demo_p++; - map = *demo_p++; - deathmatch = *demo_p++; - respawnparm = *demo_p++; - fastparm = *demo_p++; - nomonsters = *demo_p++; - consoleplayer = *demo_p++; - } - else - { - //e6y: check for overrun - if (CheckForOverrun(header_p, demo_p, size, 2, failonerror)) - return NULL; - - compatibility_level = doom_12_compatibility; - episode = *demo_p++; - map = *demo_p++; - deathmatch = respawnparm = fastparm = - nomonsters = consoleplayer = 0; - } + skill = *theDemo_p++; + episode = *theDemo_p++; + map = *theDemo_p++; + deathmatch = *theDemo_p++; + respawnparm = *theDemo_p++; + fastparm = *theDemo_p++; + nomonsters = *theDemo_p++; + consoleplayer = *theDemo_p++; +// } +// else +// { +// //e6y: check for overrun +// if (CheckForOverrun(header_p, theDemo_p, size, 2, failonerror)) +// return NULL; +// +// compatibility_level = doom_12_compatibility; +// episode = *theDemo_p++; +// map = *theDemo_p++; +// deathmatch = respawnparm = fastparm = +// nomonsters = consoleplayer = 0; +// } G_Compatibility(); } else // new versions of demos { - demo_p += 6; // skip signature; + theDemo_p += 6; // skip signature; switch (demover) { case 200: /* BOOM */ case 201: //e6y: check for overrun - if (CheckForOverrun(header_p, demo_p, size, 1, failonerror)) + if (CheckForOverrun(header_p, theDemo_p, size, 1, failonerror)) return NULL; - if (!*demo_p++) + if (!*theDemo_p++) compatibility_level = boom_201_compatibility; else compatibility_level = boom_compatibility_compatibility; break; case 202: //e6y: check for overrun - if (CheckForOverrun(header_p, demo_p, size, 1, failonerror)) + if (CheckForOverrun(header_p, theDemo_p, size, 1, failonerror)) return NULL; - if (!*demo_p++) + if (!*theDemo_p++) compatibility_level = boom_202_compatibility; else compatibility_level = boom_compatibility_compatibility; @@ -2813,54 +2838,54 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai break; case 'M': compatibility_level = mbf_compatibility; - demo_p++; + theDemo_p++; break; } break; case 210: compatibility_level = prboom_2_compatibility; - demo_p++; + theDemo_p++; break; case 211: compatibility_level = prboom_3_compatibility; - demo_p++; + theDemo_p++; break; case 212: compatibility_level = prboom_4_compatibility; - demo_p++; + theDemo_p++; break; case 213: compatibility_level = prboom_5_compatibility; - demo_p++; + theDemo_p++; break; case 214: compatibility_level = prboom_6_compatibility; longtics = 1; - demo_p++; + theDemo_p++; break; } //e6y: check for overrun - if (CheckForOverrun(header_p, demo_p, size, 5, failonerror)) + if (CheckForOverrun(header_p, theDemo_p, size, 5, failonerror)) return NULL; - skill = *demo_p++; - episode = *demo_p++; - map = *demo_p++; - deathmatch = *demo_p++; - consoleplayer = *demo_p++; + skill = *theDemo_p++; + episode = *theDemo_p++; + map = *theDemo_p++; + deathmatch = *theDemo_p++; + consoleplayer = *theDemo_p++; /* killough 11/98: save option pointer for below */ if (mbf_features) - option_p = demo_p; + option_p = theDemo_p; //e6y: check for overrun - if (CheckForOverrun(header_p, demo_p, size, GAME_OPTION_SIZE, failonerror)) + if (CheckForOverrun(header_p, theDemo_p, size, GAME_OPTION_SIZE, failonerror)) return NULL; - demo_p = G_ReadOptions(demo_p); // killough 3/1/98: Read game options + theDemo_p = G_ReadOptions(theDemo_p); // killough 3/1/98: Read game options if (demover == 200) // killough 6/3/98: partially fix v2.00 demos - demo_p += 256-GAME_OPTION_SIZE; + theDemo_p += 256-GAME_OPTION_SIZE; } if (sizeof(comp_lev_str)/sizeof(comp_lev_str[0]) != MAX_COMPATIBILITY_LEVEL) @@ -2871,23 +2896,23 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai if (demo_compatibility) // only 4 players can exist in old demos { //e6y: check for overrun - if (CheckForOverrun(header_p, demo_p, size, 4, failonerror)) + if (CheckForOverrun(header_p, theDemo_p, size, 4, failonerror)) return NULL; for (i=0; i<4; i++) // intentionally hard-coded 4 -- killough - playeringame[i] = *demo_p++; + playeringame[i] = *theDemo_p++; for (;i < MAXPLAYERS; i++) playeringame[i] = 0; } else { //e6y: check for overrun - if (CheckForOverrun(header_p, demo_p, size, MAXPLAYERS, failonerror)) + if (CheckForOverrun(header_p, theDemo_p, size, MAXPLAYERS, failonerror)) return NULL; for (i=0 ; i < MAXPLAYERS; i++) - playeringame[i] = *demo_p++; - demo_p += MIN_MAXPLAYERS - MAXPLAYERS; + playeringame[i] = *theDemo_p++; + theDemo_p += MIN_MAXPLAYERS - MAXPLAYERS; } if (playeringame[1]) @@ -2903,7 +2928,7 @@ static const byte* G_ReadDemoHeader(const byte *demo_p, size_t size, boolean fai for (i=0; iy = (fixed_t)((double)s->y + r*((double)e->y-(double)s->y)); } +#endif + #undef FIX2DBL +#ifndef IPHONE // Returns a pointer to the list of points. It must be used. // static vertex_t *gld_FlatEdgeClipper(int *numpoints, vertex_t *points, int numclippers, divline_t *clippers) @@ -1029,7 +1040,10 @@ static vertex_t *gld_FlatEdgeClipper(int *numpoints, vertex_t *points, int numcl *numpoints = num; return points; } +#endif +// Unused in iOS version. +#ifndef IPHONE static void gld_FlatConvexCarver(int ssidx, int num, divline_t *list) { subsector_t *ssec=&subsectors[ssidx]; @@ -1111,7 +1125,10 @@ static void gld_FlatConvexCarver(int ssidx, int num, divline_t *list) Z_Free(edgepoints); Z_Free(clippers); } +#endif +// Unused in iOS version +#ifndef IPHONE static void gld_CarveFlats(int bspnode, int numdivlines, divline_t *divlines, boolean *sectorclosed) { node_t *nod; @@ -1158,6 +1175,7 @@ static void gld_CarveFlats(int bspnode, int numdivlines, divline_t *divlines, bo // We are finishing with this node, free the allocated list. Z_Free(childlist); } +#endif #ifdef USE_GLU_TESS @@ -1296,7 +1314,7 @@ static void gld_PrecalculateSector(int num) angle_t lineangle; angle_t angle; angle_t bestangle; - sector_t *backsector; + sector_t *currentbacksector; GLUtesselator *tess; double *v=NULL; int maxvertexnum; @@ -1318,10 +1336,10 @@ static void gld_PrecalculateSector(int num) return; } // set callbacks - gluTessCallback(tess, GLU_TESS_BEGIN, ntessBegin); - gluTessCallback(tess, GLU_TESS_VERTEX, ntessVertex); - gluTessCallback(tess, GLU_TESS_ERROR, ntessError); - gluTessCallback(tess, GLU_TESS_COMBINE, ntessCombine); + gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr*)ntessBegin); + gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr*)ntessVertex); + gluTessCallback(tess, GLU_TESS_ERROR, (_GLUfuncptr*)ntessError); + gluTessCallback(tess, GLU_TESS_COMBINE, (_GLUfuncptr*)ntessCombine); gluTessCallback(tess, GLU_TESS_END, ntessEnd); if (levelinfo) fprintf(levelinfo, "sector %i, %i lines in sector\n", num, sectors[num].linecount); // remove any line which has both sides in the same sector (i.e. Doom2 Map01 Sector 1) @@ -1429,9 +1447,9 @@ static void gld_PrecalculateSector(int num) bestlinecount=0; // set backsector if there is one if (sectors[num].lines[currentline]->sidenum[1]!=NO_INDEX) - backsector=sides[sectors[num].lines[currentline]->sidenum[1]].sector; + currentbacksector=sides[sectors[num].lines[currentline]->sidenum[1]].sector; else - backsector=NULL; + currentbacksector=NULL; // search through all lines of the current sector for (i=0; isector->iSectorID; + int currentsectorid = ssector->sector->iSectorID; - sectorloops[currentsector].loopcount++; - sectorloops[currentsector].loops = Z_Realloc(sectorloops[currentsector].loops,sizeof(GLLoopDef)*sectorloops[currentsector].loopcount, PU_LEVEL, 0); - sectorloops[currentsector].loops[sectorloops[currentsector].loopcount-1].mode = GL_TRIANGLE_FAN; - sectorloops[currentsector].loops[sectorloops[currentsector].loopcount-1].vertexcount = numedgepoints; - sectorloops[currentsector].loops[sectorloops[currentsector].loopcount-1].vertexindex = gld_num_vertexes; + sectorloops[currentsectorid].loopcount++; + sectorloops[currentsectorid].loops = Z_Realloc(sectorloops[currentsectorid].loops,sizeof(GLLoopDef)*sectorloops[currentsectorid].loopcount, PU_LEVEL, 0); + sectorloops[currentsectorid].loops[sectorloops[currentsectorid].loopcount-1].mode = GL_TRIANGLE_FAN; + sectorloops[currentsectorid].loops[sectorloops[currentsectorid].loopcount-1].vertexcount = numedgepoints; + sectorloops[currentsectorid].loops[sectorloops[currentsector].loopcount-1].vertexindex = gld_num_vertexes; for(j = 0; j < numedgepoints; j++) { gld_texcoords[gld_num_vertexes].u =( (float)(segs[ssector->firstline + j].v1->x)/FRACUNIT)/64.0f; @@ -1610,7 +1628,7 @@ void BuildSideSegs() { // check that every sidedef had a sideSeg created for ( int i = 0 ; i < numsides ; i++ ) { - assert( sides[i].sideSeg.sidedef == &sides[i] ); + //assert( sides[i].sideSeg.sidedef == &sides[i] ); } } @@ -1656,19 +1674,19 @@ void BuildIndexedTriangles() { // Without this, there is texture jittering visible when the viewpoint // is near the floor and far away from the origin (dead on the ground in netplay). float minST[2] = { 99999, 99999 }; - for ( int j = 0 ; j < loop->vertexcount ; j++ ) { - for ( int k = 0 ; k < 2 ; k++ ) { - if ( drawVerts[numDrawVerts+j].st[k] < minST[k] ) { - minST[k] = drawVerts[numDrawVerts+j].st[k]; + for ( int k = 0 ; k < loop->vertexcount ; k++ ) { + for ( int l = 0 ; l < 2 ; l++ ) { + if ( drawVerts[numDrawVerts+k].st[l] < minST[l] ) { + minST[l] = drawVerts[numDrawVerts+k].st[l]; } } } for ( int k = 0 ; k < 2 ; k++ ) { minST[k] = floor( minST[k] ); } - for ( int j = 0 ; j < loop->vertexcount ; j++ ) { - for ( int k = 0 ; k < 2 ; k++ ) { - drawVerts[numDrawVerts+j].st[k] -= minST[k]; + for ( int k = 0 ; k < loop->vertexcount ; k++ ) { + for ( int l = 0 ; l < 2 ; l++ ) { + drawVerts[numDrawVerts+k].st[l] -= minST[l]; } } @@ -1947,8 +1965,8 @@ void gld_StartDrawScene(void) height = (screenblocks*SCREENHEIGHT/10) & ~7; glViewport(viewwindowx, SCREENHEIGHT-(height+viewwindowy-((height-viewheight)/2)), viewwidth, height); - glScissor(viewwindowx, SCREENHEIGHT-(viewheight+viewwindowy), viewwidth, viewheight); - glEnable(GL_SCISSOR_TEST); + //glScissor(viewwindowx, SCREENHEIGHT-(viewheight+viewwindowy), viewwidth, viewheight); + //glEnable(GL_SCISSOR_TEST); // Player coordinates xCamera=-(float)viewx/MAP_SCALE; yCamera=(float)viewy/MAP_SCALE; @@ -1967,8 +1985,7 @@ void gld_StartDrawScene(void) glMatrixMode(GL_PROJECTION); glLoadIdentity(); - iphoneRotateForLandscape(); //JDC, make the 320x480 hardware seem like 480x320 in two different orientations - + infinitePerspective(64.0f, 320.0f/200.0f, (float)gl_nearclip/100.0f); glMatrixMode(GL_MODELVIEW); @@ -1999,6 +2016,7 @@ void gld_EndDrawScene(void) glDisable(GL_FOG); gld_Set2DMode(); + // suppressing this warning in the compiler with a -w flag as I think it can't be helped -tkidd if (viewangleoffset <= 1024<=-1024<flag>=GLDWF_SKY) ) - wall->gltexture=NULL; + gld_BindTexture(wall->gltexture); - if (!wall->gltexture) - { -#ifdef _DEBUG - glColor4f(1.0f,0.0f,0.0f,1.0f); -#endif - } + if (wall->flag>=GLDWF_SKY) { - if ( wall->gltexture ) - { - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - if ((wall->flag&GLDWF_SKYFLIP)==GLDWF_SKYFLIP) - glScalef(-128.0f/(float)wall->gltexture->buffer_width,200.0f/320.0f*2.0f,1.0f); - else - glScalef(128.0f/(float)wall->gltexture->buffer_width,200.0f/320.0f*2.0f,1.0f); - glTranslatef(wall->skyyaw,wall->skyymid,0.0f); - } - glBegin(GL_TRIANGLE_STRIP); - glVertex3f(wall->glseg->x1,wall->ytop,wall->glseg->z1); - glVertex3f(wall->glseg->x1,wall->ybottom,wall->glseg->z1); - glVertex3f(wall->glseg->x2,wall->ytop,wall->glseg->z2); - glVertex3f(wall->glseg->x2,wall->ybottom,wall->glseg->z2); - glEnd(); - if ( wall->gltexture ) - { - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - } + // Dont Draw Sky Walls. } else { @@ -2249,8 +2241,8 @@ void gld_AddWall(seg_t *seg) { GLWall wall; GLTexture *temptex; - sector_t *frontsector; - sector_t *backsector; + sector_t *theFrontsector; + sector_t *theBacksector; sector_t ftempsec; // needed for R_FakeFlat sector_t btempsec; // needed for R_FakeFlat float lineheight; @@ -2263,37 +2255,37 @@ void gld_AddWall(seg_t *seg) segrendered[seg->iSegID]=rendermarker; if (!seg->frontsector) return; - frontsector=R_FakeFlat(seg->frontsector, &ftempsec, NULL, NULL, false); // for boom effects - if (!frontsector) + theFrontsector=R_FakeFlat(seg->frontsector, &ftempsec, NULL, NULL, false); // for boom effects + if (!theFrontsector) return; wall.glseg=&gl_segs[seg->iSegID]; rellight = seg->linedef->dx==0? +8 : seg->linedef->dy==0 ? -8 : 0; - wall.light=gld_CalcLightLevel(frontsector->lightlevel+rellight+(extralight<<5)); + wall.light=gld_CalcLightLevel(theFrontsector->lightlevel+rellight+(extralight<<5)); wall.alpha=1.0f; wall.gltexture=NULL; if (!seg->backsector) /* onesided */ { - if (frontsector->ceilingpic==skyflatnum) + if (theFrontsector->ceilingpic==skyflatnum) { wall.ytop=255.0f; - wall.ybottom=(float)frontsector->ceilingheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,frontsector->sky); + wall.ybottom=(float)theFrontsector->ceilingheight/MAP_SCALE; + SKYTEXTURE(theFrontsector->sky,theFrontsector->sky); ADDWALL(&wall); } - if (frontsector->floorpic==skyflatnum) + if (theFrontsector->floorpic==skyflatnum) { - wall.ytop=(float)frontsector->floorheight/MAP_SCALE; + wall.ytop=(float)theFrontsector->floorheight/MAP_SCALE; wall.ybottom=-255.0f; - SKYTEXTURE(frontsector->sky,frontsector->sky); + SKYTEXTURE(theFrontsector->sky,theFrontsector->sky); ADDWALL(&wall); } temptex=gld_RegisterTexture(texturetranslation[seg->sidedef->midtexture], true, false); if (temptex) { wall.gltexture=temptex; - CALC_Y_VALUES(wall, lineheight, frontsector->floorheight, frontsector->ceilingheight); + CALC_Y_VALUES(wall, lineheight, theFrontsector->floorheight, theFrontsector->ceilingheight); CALC_TEX_VALUES_MIDDLE1S( wall, seg, (LINE->flags & ML_DONTPEGBOTTOM)>0, segs[seg->iSegID].length, lineheight @@ -2305,25 +2297,25 @@ void gld_AddWall(seg_t *seg) { int floor_height,ceiling_height; - backsector=R_FakeFlat(seg->backsector, &btempsec, NULL, NULL, true); // for boom effects - if (!backsector) + theBacksector=R_FakeFlat(seg->backsector, &btempsec, NULL, NULL, true); // for boom effects + if (!theBacksector) return; /* toptexture */ - ceiling_height=frontsector->ceilingheight; - floor_height=backsector->ceilingheight; - if (frontsector->ceilingpic==skyflatnum) + ceiling_height=theFrontsector->ceilingheight; + floor_height=theBacksector->ceilingheight; + if (theFrontsector->ceilingpic==skyflatnum) { wall.ytop=255.0f; if ( // e6y // Fix for HOM in the starting area on Memento Mori map29 and on map30. - // old code: (backsector->ceilingheight==backsector->floorheight) && - (backsector->ceilingheight==backsector->floorheight||(backsector->ceilingheight<=frontsector->floorheight)) && - (backsector->ceilingpic==skyflatnum) + // old code: (theBacksector->ceilingheight==theBacksector->floorheight) && + (theBacksector->ceilingheight==theBacksector->floorheight||(theBacksector->ceilingheight<=theFrontsector->floorheight)) && + (theBacksector->ceilingpic==skyflatnum) ) { - wall.ybottom=(float)backsector->floorheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ybottom=(float)theBacksector->floorheight/MAP_SCALE; + SKYTEXTURE(theFrontsector->sky,theBacksector->sky); ADDWALL(&wall); } else @@ -2332,25 +2324,25 @@ void gld_AddWall(seg_t *seg) { // e6y // It corrects some problem with sky, but I do not remember which one - // old code: wall.ybottom=(float)frontsector->ceilingheight/MAP_SCALE; - wall.ybottom=(float)MAX(frontsector->ceilingheight,backsector->ceilingheight)/MAP_SCALE; + // old code: wall.ybottom=(float)theFrontsector->ceilingheight/MAP_SCALE; + wall.ybottom=(float)MAX(theFrontsector->ceilingheight,theBacksector->ceilingheight)/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + SKYTEXTURE(theFrontsector->sky,theBacksector->sky); ADDWALL(&wall); } else - if ( (backsector->ceilingheight <= frontsector->floorheight) || - (backsector->ceilingpic != skyflatnum) ) + if ( (theBacksector->ceilingheight <= theFrontsector->floorheight) || + (theBacksector->ceilingpic != skyflatnum) ) { - wall.ybottom=(float)backsector->ceilingheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ybottom=(float)theBacksector->ceilingheight/MAP_SCALE; + SKYTEXTURE(theFrontsector->sky,theBacksector->sky); ADDWALL(&wall); } } } if (floor_heightceilingpic==skyflatnum) && (backsector->ceilingpic==skyflatnum))) + if (!((theFrontsector->ceilingpic==skyflatnum) && (theBacksector->ceilingpic==skyflatnum))) { temptex=gld_RegisterTexture(texturetranslation[seg->sidedef->toptexture], true, false); if (temptex) @@ -2442,34 +2434,34 @@ void gld_AddWall(seg_t *seg) } bottomtexture: /* bottomtexture */ - ceiling_height=backsector->floorheight; - floor_height=frontsector->floorheight; - if (frontsector->floorpic==skyflatnum) + ceiling_height=theBacksector->floorheight; + floor_height=theFrontsector->floorheight; + if (theFrontsector->floorpic==skyflatnum) { wall.ybottom=-255.0f; if ( - (backsector->ceilingheight==backsector->floorheight) && - (backsector->floorpic==skyflatnum) + (theBacksector->ceilingheight==theBacksector->floorheight) && + (theBacksector->floorpic==skyflatnum) ) { - wall.ytop=(float)backsector->floorheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ytop=(float)theBacksector->floorheight/MAP_SCALE; + SKYTEXTURE(theFrontsector->sky,theBacksector->sky); ADDWALL(&wall); } else { if ( (texturetranslation[seg->sidedef->bottomtexture]!=NO_TEXTURE) ) { - wall.ytop=(float)frontsector->floorheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ytop=(float)theFrontsector->floorheight/MAP_SCALE; + SKYTEXTURE(theFrontsector->sky,theBacksector->sky); ADDWALL(&wall); } else - if ( (backsector->floorheight >= frontsector->ceilingheight) || - (backsector->floorpic != skyflatnum) ) + if ( (theBacksector->floorheight >= theFrontsector->ceilingheight) || + (theBacksector->floorpic != skyflatnum) ) { - wall.ytop=(float)backsector->floorheight/MAP_SCALE; - SKYTEXTURE(frontsector->sky,backsector->sky); + wall.ytop=(float)theBacksector->floorheight/MAP_SCALE; + SKYTEXTURE(theFrontsector->sky,theBacksector->sky); ADDWALL(&wall); } } @@ -2484,7 +2476,7 @@ void gld_AddWall(seg_t *seg) CALC_TEX_VALUES_BOTTOM( wall, seg, (LINE->flags & ML_DONTPEGBOTTOM)>0, segs[seg->iSegID].length, lineheight, - floor_height-frontsector->ceilingheight + floor_height-theFrontsector->ceilingheight ); ADDWALL(&wall); } @@ -2672,6 +2664,13 @@ void gld_AddPlane(int subsectornum, visplane_t *floor, visplane_t *ceiling) static void gld_DrawSprite(GLSprite *sprite) { + + // transparent sprites blend and don't write to the depth buffer + glEnable( GL_BLEND ); +// glDepthMask( 0 ); + + glEnable( GL_ALPHA_TEST ); + gld_BindPatch(sprite->gltexture,sprite->cm); glMatrixMode(GL_MODELVIEW); glPushMatrix(); @@ -2706,6 +2705,9 @@ static void gld_DrawSprite(GLSprite *sprite) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glAlphaFunc(GL_GEQUAL,0.5f); } + + glDisable( GL_ALPHA_TEST ); +// glDepthMask( 1 ); } void gld_AddSprite(vissprite_t *vspr) @@ -2785,9 +2787,51 @@ void gld_DrawScene(player_t *player) { int i,j,k,count; fixed_t max_scale; - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); + + glDisable(GL_CULL_FACE); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + + //----------------------------------------- + // draw the sky if needed + //----------------------------------------- + if ( true ) { + float s; + float y; + + // Note that these texcoords would have to be corrected + // for different screen aspect ratios or fields of view! + s = ((yaw+90.0f)/90.0f); + y = 1 - 2 * 128.0 / 200; + + // With identity matricies, the vertex coordinates + // can just be in the 0-1 range. + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + + gld_BindTexture( gld_RegisterTexture( skytexture, true, true ) ); + glColor4f( 0.5, 0.5, 0.5, 1.0 ); // native texture color, not double bright + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2f( s, 1 ); glVertex3f(-1,y,0.999); + glTexCoord2f( s, 0 ); glVertex3f(-1,1,0.999); + glTexCoord2f( s+1, 1 ); glVertex3f(1,y,0.999); + glTexCoord2f( s+1, 0 ); glVertex3f(1,1,0.999); + glEnd(); + + // back to the normal drawing matrix + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + } + + + rendered_visplanes = rendered_segs = rendered_vissprites = 0; for (i=gld_drawinfo.num_drawitems; i>=0; i--) { @@ -2815,7 +2859,9 @@ void gld_DrawScene(player_t *player) // disable backside removing glDisable(GL_CULL_FACE); break; - } + + default: break; + } } for (i=gld_drawinfo.num_drawitems; i>=0; i--) { @@ -2829,11 +2875,14 @@ void gld_DrawScene(player_t *player) continue; if ( (gl_drawskys) && (k>=GLDWF_SKY) ) { + // Texture gen is not supported in OpenGL ES + #ifndef IPHONE if (comp[comp_skymap] && gl_shared_texture_palette) glDisable(GL_SHARED_TEXTURE_PALETTE_EXT); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_Q); + #endif glColor4fv(gl_whitecolor); } for (j=(gld_drawinfo.drawitems[i].itemcount-1); j>=0; j--) @@ -2845,11 +2894,14 @@ void gld_DrawScene(player_t *player) } if (gl_drawskys) { + // Texture gen is not supported in OpenGL ES + #ifndef IPHONE glDisable(GL_TEXTURE_GEN_Q); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_S); if (comp[comp_skymap] && gl_shared_texture_palette) glEnable(GL_SHARED_TEXTURE_PALETTE_EXT); + #endif } } break; @@ -2880,6 +2932,7 @@ void gld_DrawScene(player_t *player) gld_DrawSprite(&gld_drawinfo.sprites[j+gld_drawinfo.drawitems[i].firstitemindex]); } break; + default: break; } } // JDC glDisableClientState(GL_TEXTURE_COORD_ARRAY); diff --git a/code/prboom/gl_struct.h b/code/prboom/gl_struct.h old mode 100644 new mode 100755 index 1bd0779..714cf33 --- a/code/prboom/gl_struct.h +++ b/code/prboom/gl_struct.h @@ -40,7 +40,7 @@ extern int nodesVersion; extern byte *staticPlaypal; // JDC: added to avoid the continuous lookup of PLAYPAL void gld_Init(int width, int height); -void gld_InitCommandLine(); +void gld_InitCommandLine(void); void gld_DrawNumPatch(int x, int y, int lump, int cm, enum patch_translation_e flags); void gld_DrawBackground(const char* name); @@ -54,7 +54,7 @@ unsigned char *gld_ReadScreen (void); void gld_CleanMemory(void); void gld_PreprocessLevel(void); -void gld_Set2DMode(); +void gld_Set2DMode(void); void gld_InitDrawScene(void); void gld_StartDrawScene(void); void gld_AddPlane(int subsectornum, visplane_t *floor, visplane_t *ceiling); @@ -62,6 +62,6 @@ void gld_AddWall(seg_t *seg); void gld_AddSprite(vissprite_t *vspr); void gld_DrawScene(player_t *player); void gld_EndDrawScene(void); -void gld_Finish(); +void gld_Finish(void); #endif // _GL_STRUCT_H diff --git a/code/prboom/gl_texture.c b/code/prboom/gl_texture.c old mode 100644 new mode 100755 index 24d9219..81a0e59 --- a/code/prboom/gl_texture.c +++ b/code/prboom/gl_texture.c @@ -71,9 +71,9 @@ boolean use_mipmapping=false; int gld_max_texturesize=0; -char *gl_tex_format_string; +const char *gl_tex_format_string; //int gl_tex_format=GL_RGBA8; -int gl_tex_format=GL_RGB5_A1; +int gl_tex_format=GL_RGBA; //int gl_tex_format=GL_RGBA4; //int gl_tex_format=GL_RGBA2; @@ -499,7 +499,6 @@ GLTexture *gld_RegisterTexture(int texture_num, boolean mipmap, boolean force) void gld_BindTexture(GLTexture *gltexture) { const rpatch_t *patch; - int i; unsigned char *buffer; if (gltexture==last_gltexture) @@ -532,14 +531,14 @@ void gld_BindTexture(GLTexture *gltexture) return; } buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0); - if (!(gltexture->mipmap & use_mipmapping) & gl_paletted_texture) + if ((!(gltexture->mipmap & use_mipmapping)) & gl_paletted_texture) memset(buffer,transparent_pal_index,gltexture->buffer_size); else memset(buffer,0,gltexture->buffer_size); patch=R_CacheTextureCompositePatchNum(gltexture->index); gld_AddPatchToTexture(gltexture, buffer, patch, 0, 0, - CR_DEFAULT, !(gltexture->mipmap & use_mipmapping) & gl_paletted_texture); + CR_DEFAULT, (!(gltexture->mipmap & use_mipmapping)) & gl_paletted_texture); R_UnlockTextureCompositePatchNum(gltexture->index); if (gltexture->glTexID[CR_DEFAULT]==0) glGenTextures(1,&gltexture->glTexID[CR_DEFAULT]); @@ -655,7 +654,6 @@ GLTexture *gld_RegisterPatch(int lump, int cm) void gld_BindPatch(GLTexture *gltexture, int cm) { const rpatch_t *patch; - int i; unsigned char *buffer; if ((gltexture==last_gltexture) && (cm==last_cm)) @@ -792,7 +790,6 @@ GLTexture *gld_RegisterFlat(int lump, boolean mipmap) void gld_BindFlat(GLTexture *gltexture) { const unsigned char *flat; - int i; unsigned char *buffer; if (gltexture==last_gltexture) @@ -822,11 +819,11 @@ void gld_BindFlat(GLTexture *gltexture) } flat=W_CacheLumpNum(gltexture->index); buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0); - if (!(gltexture->mipmap & use_mipmapping) & gl_paletted_texture) + if ((!(gltexture->mipmap & use_mipmapping)) & gl_paletted_texture) memset(buffer,transparent_pal_index,gltexture->buffer_size); else memset(buffer,0,gltexture->buffer_size); - gld_AddFlatToTexture(gltexture, buffer, flat, !(gltexture->mipmap & use_mipmapping) & gl_paletted_texture); + gld_AddFlatToTexture(gltexture, buffer, flat, (!(gltexture->mipmap & use_mipmapping)) & gl_paletted_texture); if (gltexture->glTexID[CR_DEFAULT]==0) glGenTextures(1,&gltexture->glTexID[CR_DEFAULT]); glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]); @@ -903,14 +900,27 @@ static void gld_CleanTextures(void) return; for (i=0; iglTexID[j])); - Z_Free(gld_GLTextures[i]); + GLTexture * texture = gld_GLTextures[i]; + + if (texture) + { + for (j=0; j<(CR_LIMIT+MAXPLAYERS); j++) { + + GLuint handle = texture->glTexID[j]; + + glDeleteTextures(1,&handle); + } + + Z_Free(texture); + + gld_GLTextures[i] = NULL; } } - memset(gld_GLTextures,0,numtextures*sizeof(GLTexture *)); + + Z_Free( gld_GLTextures ); + gld_GLTextures = NULL; + numtextures = 0; + } static void gld_CleanPatchTextures(void) @@ -926,9 +936,11 @@ static void gld_CleanPatchTextures(void) for (j=0; j<(CR_LIMIT+MAXPLAYERS); j++) glDeleteTextures(1,&(gld_GLPatchTextures[i]->glTexID[j])); Z_Free(gld_GLPatchTextures[i]); + gld_GLPatchTextures[i] = NULL; } } - memset(gld_GLPatchTextures,0,numlumps*sizeof(GLTexture *)); + Z_Free( gld_GLPatchTextures ); + gld_GLPatchTextures = NULL; } void DrawEmptyTriangleToForceTextureLoad() { // JDC @@ -958,7 +970,7 @@ void gld_Precache(void) // faster. // this updates the spinning wheel icon as we load textures - void iphonePacifierUpdate(); + void iphonePacifierUpdate(void); // JDC if (demoplayback) // JDC return; @@ -1037,7 +1049,7 @@ void gld_Precache(void) if ( gld_GLPatchTextures ) { for (i=numsprites; --i >= 0;) { if ( !spriteHitlist[i] ) { - for ( int j = 0 ; j < sprites[i].numframes ; j++ ) { + for (j = 0 ; j < sprites[i].numframes ; j++ ) { short *sflump = sprites[i].spriteframes[j].lump; for ( k = 0 ; k < 7 ; k++ ) { int patchNum = firstspritelump + sflump[k]; @@ -1077,11 +1089,11 @@ void gld_Precache(void) for (i=numsprites; --i >= 0;) if (spriteHitlist[i]) { - int j = sprites[i].numframes; + j = sprites[i].numframes; while (--j >= 0) { short *sflump = sprites[i].spriteframes[j].lump; - int k = 7; + k = 7; do { // JDC: changed from CR_DEFAULT to CR_LIMIT to match game behavior gld_BindPatch(gld_RegisterPatch(firstspritelump + sflump[k],CR_LIMIT),CR_LIMIT); @@ -1094,11 +1106,7 @@ void gld_Precache(void) void gld_CleanMemory(void) { -#if 0 // JDC: changed to only free things not used in the current level - // that will use somewhat more memory during the transition period, - // but it makes most level transitions faster, and respawns many - // times faster. gld_CleanTextures(); gld_CleanPatchTextures(); -#endif + } diff --git a/code/prboom/hu_lib.c b/code/prboom/hu_lib.c old mode 100644 new mode 100755 index 93c6a62..8fe9e97 --- a/code/prboom/hu_lib.c +++ b/code/prboom/hu_lib.c @@ -46,13 +46,6 @@ extern int key_backspace; // phares extern int key_enter; // phares -// -// not used currently -// code to initialize HUlib would go here if needed -// -static void HUlib_init(void) -{ -} //////////////////////////////////////////////////////// // @@ -170,8 +163,10 @@ void HUlib_drawTextLine { c = toupper(l->l[i]); //jff insure were not getting a cheap toupper conv. - if (c=='\n') // killough 1/18/98 -- support multiple lines - x=0,y+=8; + if (c=='\n') { // killough 1/18/98 -- support multiple lines + x=0; + y+=8; + } else if (c=='\t') // killough 1/23/98 -- support tab stops x=x-x%80+80; else if (c=='\x1b') //jff 2/17/98 escape code for color change @@ -671,11 +666,13 @@ static void HUlib_delCharFromIText(hu_itext_t* it) // Passed the hu_itext_t // Returns nothing // +#ifndef IPHONE static void HUlib_eraseLineFromIText(hu_itext_t* it) { while (it->lm != it->l.len) HUlib_delCharFromTextLine(&it->l); } +#endif // // HUlib_resetIText() diff --git a/code/prboom/hu_stuff.c b/code/prboom/hu_stuff.c old mode 100644 new mode 100755 index 4bb001c..d59e7fa --- a/code/prboom/hu_stuff.c +++ b/code/prboom/hu_stuff.c @@ -45,6 +45,10 @@ #include "g_game.h" #include "r_main.h" +#include "doomiphone.h" + +#include + // global heads up display controls int hud_active; //jff 2/17/98 controls heads-up display mode @@ -733,13 +737,13 @@ void HU_MoveHud(void) void HU_Drawer(void) { char *s; - player_t *plr; + player_t *player; char ammostr[80]; //jff 3/8/98 allow plenty room for dehacked mods char healthstr[80];//jff char armorstr[80]; //jff int i,doit; - plr = &players[displayplayer]; // killough 3/7/98 + player = &players[displayplayer]; // killough 3/7/98 // draw the automap widgets if automap is displayed if (automapmode & am_active) { @@ -750,7 +754,7 @@ void HU_Drawer(void) // x-coord if (map_point_coordinates) { - sprintf(hud_coordstrx,"X: %-5d", (plr->mo->x)>>FRACBITS); + sprintf(hud_coordstrx,"X: %-5d", (player->mo->x)>>FRACBITS); HUlib_clearTextLine(&w_coordx); s = hud_coordstrx; while (*s) @@ -759,7 +763,7 @@ void HU_Drawer(void) //jff 3/3/98 split coord display into x,y,z lines // y-coord - sprintf(hud_coordstry,"Y: %-5d", (plr->mo->y)>>FRACBITS); + sprintf(hud_coordstry,"Y: %-5d", (player->mo->y)>>FRACBITS); HUlib_clearTextLine(&w_coordy); s = hud_coordstry; while (*s) @@ -769,7 +773,7 @@ void HU_Drawer(void) //jff 3/3/98 split coord display into x,y,z lines //jff 2/22/98 added z // z-coord - sprintf(hud_coordstrz,"Z: %-5d", (plr->mo->z)>>FRACBITS); + sprintf(hud_coordstrz,"Z: %-5d", (player->mo->z)>>FRACBITS); HUlib_clearTextLine(&w_coordz); s = hud_coordstrz; while (*s) @@ -798,15 +802,15 @@ void HU_Drawer(void) // clear the widgets internal line HUlib_clearTextLine(&w_ammo); strcpy(hud_ammostr,"AMM "); - if (weaponinfo[plr->readyweapon].ammo == am_noammo) + if (weaponinfo[player->readyweapon].ammo == am_noammo) { // special case for weapon with no ammo selected - blank bargraph + N/A strcat(hud_ammostr,"\x7f\x7f\x7f\x7f\x7f\x7f\x7f N/A"); w_ammo.cm = CR_GRAY; } else { - int ammo = plr->ammo[weaponinfo[plr->readyweapon].ammo]; - int fullammo = plr->maxammo[weaponinfo[plr->readyweapon].ammo]; + int ammo = player->ammo[weaponinfo[player->readyweapon].ammo]; + int fullammo = player->maxammo[weaponinfo[player->readyweapon].ammo]; int ammopct = (100*ammo)/fullammo; int ammobars = ammopct/4; @@ -856,7 +860,7 @@ void HU_Drawer(void) // do the hud health display if (doit) { - int health = plr->health; + int health = player->health; int healthbars = health>100? 25 : health/4; // clear the widgets internal line @@ -910,7 +914,7 @@ void HU_Drawer(void) // do the hud armor display if (doit) { - int armor = plr->armorpoints; + int armor = player->armorpoints; int armorbars = armor>100? 25 : armor/4; // clear the widgets internal line @@ -992,12 +996,12 @@ void HU_Drawer(void) } if (!ok) continue; - ammo = plr->ammo[weaponinfo[w].ammo]; - fullammo = plr->maxammo[weaponinfo[w].ammo]; + ammo = player->ammo[weaponinfo[w].ammo]; + fullammo = player->maxammo[weaponinfo[w].ammo]; ammopct=0; // skip weapons not currently posessed - if (!plr->weaponowned[w]) + if (!player->weaponowned[w]) continue; ammopct = fullammo? (100*ammo)/fullammo : 100; @@ -1005,7 +1009,7 @@ void HU_Drawer(void) // display each weapon number in a color related to the ammo for it hud_weapstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths if (weaponinfo[w].ammo==am_noammo) //jff 3/14/98 show berserk on HUD - hud_weapstr[i++] = plr->powers[pw_strength]? '0'+CR_GREEN : '0'+CR_GRAY; + hud_weapstr[i++] = player->powers[pw_strength]? '0'+CR_GREEN : '0'+CR_GRAY; else if (ammopctcards[k]) + if (!player->cards[k]) continue; hud_gkeysstr[i++] = '!'+k; // key number plus '!' is char for key @@ -1151,7 +1155,7 @@ void HU_Drawer(void) for (k=0;k<6;k++) { // skip any not possessed by the displayed player's stats - if (!plr->cards[k]) + if (!player->cards[k]) continue; // use color escapes to make text in key's color @@ -1237,9 +1241,9 @@ void HU_Drawer(void) ( hud_monsecstr, "STS \x1b\x36K \x1b\x33%d \x1b\x36M \x1b\x33%d \x1b\x37I \x1b\x33%d/%d \x1b\x35S \x1b\x33%d/%d", - plr->killcount,totallive, - plr->itemcount,totalitems, - plr->secretcount,totalsecret + player->killcount,totallive, + player->itemcount,totalitems, + player->secretcount,totalsecret ); // transfer the init string to the widget s = hud_monsecstr; diff --git a/code/prboom/i_sound.h b/code/prboom/i_sound.h old mode 100644 new mode 100755 index e03ccbf..4640f51 --- a/code/prboom/i_sound.h +++ b/code/prboom/i_sound.h @@ -47,6 +47,8 @@ // Init at program start... void I_InitSound(void); +void I_OverwriteSoundBuffersWithLumps(void); + // ... shut down and relase at program termination. void I_ShutdownSound(void); @@ -61,15 +63,15 @@ void I_SetChannels(void); int I_GetSfxLumpNum (sfxinfo_t *sfxinfo); // Starts a sound in a particular sound channel. -int I_StartSound(int id, int channel, int vol, int sep, int pitch, int priority); +long int I_StartSound(int id, int channel, int vol, int sep, int pitch, int priority); // Stops a sound channel. -void I_StopSound(int handle); +void I_StopSound(long int handle); // Called by S_*() functions // to see if a channel is still playing. // Returns 0 if no longer playing, 1 if playing. -boolean I_SoundIsPlaying(int handle); +boolean I_SoundIsPlaying(long int handle); // Called by m_menu.c to let the quit sound play and quit right after it stops boolean I_AnySoundStillPlaying(void); @@ -99,6 +101,9 @@ int I_RegisterSong(const void *data, size_t len); // cournia - tries to load a music file int I_RegisterMusic( const char* filename, musicinfo_t *music ); +// tkidd - fun with mp3 +char* I_RegisterMusic_MP3( musicinfo_t *song, const void *data, size_t len ); + // Called by anything that wishes to start music. // plays a song, and when the song is done, // starts playing it again in an endless loop. diff --git a/code/prboom/i_system.h b/code/prboom/i_system.h old mode 100644 new mode 100755 index 727a5ea..c82ae7d --- a/code/prboom/i_system.h +++ b/code/prboom/i_system.h @@ -34,10 +34,11 @@ #ifndef __I_SYSTEM__ #define __I_SYSTEM__ -#ifdef __GNUG__ -#pragma interface +#ifdef __cplusplus +extern "C" { #endif + extern int ms_to_next_tick; boolean I_StartDisplay(void); void I_EndDisplay(void); @@ -64,7 +65,7 @@ const char* I_SigString(char* buf, size_t sz, int signum); const char *I_DoomExeDir(void); // killough 2/16/98: path to executable's dir boolean HasTrailingSlash(const char* dn); -char* I_FindFile(const char* wfname, const char* ext); +void I_FindFile(const char* wfname, const char* ext, char * returnWadName ); /* cph 2001/11/18 - wrapper for read(2) which deals with partial reads */ void I_Read(int fd, void* buf, size_t sz); @@ -74,4 +75,11 @@ int I_Filelength(int handle); void I_SetAffinityMask(void); +#define SCREENSHOT_DIR I_DoomExeDir() +#define HEAPDUMP_DIR I_DoomExeDir() + +#ifdef __cplusplus +} +#endif + #endif diff --git a/code/prboom/i_video.h b/code/prboom/i_video.h old mode 100644 new mode 100755 index 00d1a04..141e9ef --- a/code/prboom/i_video.h +++ b/code/prboom/i_video.h @@ -37,9 +37,6 @@ #include "doomtype.h" #include "v_video.h" -#ifdef __GNUG__ -#pragma interface -#endif void I_PreInitGraphics(void); /* CPhipps - do stuff immediately on start */ void I_CalculateRes(unsigned int width, unsigned int height); /* calculate resolution */ diff --git a/code/prboom/info.c b/code/prboom/info.c old mode 100644 new mode 100755 index 2e64614..50349cc --- a/code/prboom/info.c +++ b/code/prboom/info.c @@ -1074,12 +1074,12 @@ state_t states[NUMSTATES] = { {SPR_TNT1,0,-1,NULL,S_TNT1,0,0}, // S_TNT1 // phares 3/8/98 // killough 8/9/98: grenade - {SPR_MISL,32768,1000,A_Die,S_GRENADE}, // S_GRENADE + {SPR_MISL,32768,1000,A_Die,S_GRENADE,0,0}, // S_GRENADE // killough 8/10/98: variable damage explosion - {SPR_MISL,32769,4,A_Scream,S_DETONATE2}, // S_DETONATE - {SPR_MISL,32770,6,A_Detonate,S_DETONATE3}, // S_DETONATE2 - {SPR_MISL,32771,10,NULL,S_NULL}, // S_DETONATE3 + {SPR_MISL,32769,4,A_Scream,S_DETONATE2,0,0}, // S_DETONATE + {SPR_MISL,32770,6,A_Detonate,S_DETONATE3,0,0}, // S_DETONATE2 + {SPR_MISL,32771,10,NULL,S_NULL,0,0}, // S_DETONATE3 #ifdef DOGS // killough 7/19/98: Marine's best friend :) @@ -1112,120 +1112,120 @@ state_t states[NUMSTATES] = { {SPR_DOGS,8,5,NULL,S_DOGS_RUN1}, // S_DOGS_RAISE6 #else // if dogs are disabled, dummy states are required for dehacked compatibility - {0,0,-1,NULL,S_NULL}, // S_DOGS_STND - {0,0,-1,NULL,S_NULL}, // S_DOGS_STND2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN1 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN3 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN4 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN5 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN6 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN7 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RUN8 - {0,0,-1,NULL,S_NULL}, // S_DOGS_ATK1 - {0,0,-1,NULL,S_NULL}, // S_DOGS_ATK2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_ATK3 - {0,0,-1,NULL,S_NULL}, // S_DOGS_PAIN - {0,0,-1,NULL,S_NULL}, // S_DOGS_PAIN2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE1 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE3 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE4 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE5 - {0,0,-1,NULL,S_NULL}, // S_DOGS_DIE6 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE1 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE2 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE3 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE4 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE5 - {0,0,-1,NULL,S_NULL}, // S_DOGS_RAISE6 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_STND + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_STND2 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RUN1 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RUN2 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RUN3 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RUN4 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RUN5 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RUN6 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RUN7 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RUN8 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_ATK1 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_ATK2 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_ATK3 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_PAIN + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_PAIN2 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_DIE1 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_DIE2 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_DIE3 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_DIE4 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_DIE5 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_DIE6 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RAISE1 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RAISE2 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RAISE3 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RAISE4 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RAISE5 + {0,0,-1,NULL,S_NULL,0,0}, // S_DOGS_RAISE6 #endif // add dummy beta bfg / lost soul frames for dehacked compatibility // fixes bug #1576151 (part 2) - {0,0,-1,NULL,S_NULL}, // S_OLDBFG1 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG2 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG3 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG4 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG5 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG6 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG7 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG8 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG9 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG10 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG11 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG12 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG13 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG14 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG15 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG16 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG17 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG18 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG19 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG20 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG21 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG22 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG23 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG24 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG25 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG26 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG27 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG28 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG29 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG30 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG31 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG32 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG33 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG34 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG35 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG36 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG37 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG38 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG39 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG40 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG41 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG42 - {0,0,-1,NULL,S_NULL}, // S_OLDBFG43 - - {0,0,-1,NULL,S_NULL}, // S_PLS1BALL - {0,0,-1,NULL,S_NULL}, // S_PLS1BALL2 - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP2 - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP3 - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP4 - {0,0,-1,NULL,S_NULL}, // S_PLS1EXP5 - - {0,0,-1,NULL,S_NULL}, // S_PLS2BALL - {0,0,-1,NULL,S_NULL}, // S_PLS2BALL2 - {0,0,-1,NULL,S_NULL}, // S_PLS2BALLX1 - {0,0,-1,NULL,S_NULL}, // S_PLS2BALLX2 - {0,0,-1,NULL,S_NULL}, // S_PLS2BALLX3 - - {0,0,-1,NULL,S_NULL}, // S_BON3 - {0,0,-1,NULL,S_NULL}, // S_BON4 - - {0,0,-1,NULL,S_NULL}, // S_BSKUL_STND - {0,0,-1,NULL,S_NULL}, // S_BSKUL_RUN1 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_RUN2 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_RUN3 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_RUN4 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_ATK1 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_ATK2 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_ATK3 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_PAIN1 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_PAIN2 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_PAIN3 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE1 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE2 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE3 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE4 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE5 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE6 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE7 - {0,0,-1,NULL,S_NULL}, // S_BSKUL_DIE8 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG1 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG2 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG3 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG4 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG5 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG6 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG7 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG8 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG9 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG10 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG11 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG12 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG13 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG14 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG15 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG16 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG17 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG18 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG19 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG20 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG21 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG22 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG23 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG24 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG25 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG26 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG27 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG28 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG29 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG30 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG31 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG32 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG33 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG34 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG35 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG36 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG37 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG38 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG39 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG40 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG41 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG42 + {0,0,-1,NULL,S_NULL,0,0}, // S_OLDBFG43 + + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS1BALL + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS1BALL2 + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS1EXP + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS1EXP2 + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS1EXP3 + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS1EXP4 + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS1EXP5 + + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS2BALL + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS2BALL2 + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS2BALLX1 + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS2BALLX2 + {0,0,-1,NULL,S_NULL,0,0}, // S_PLS2BALLX3 + + {0,0,-1,NULL,S_NULL,0,0}, // S_BON3 + {0,0,-1,NULL,S_NULL,0,0}, // S_BON4 + + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_STND + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_RUN1 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_RUN2 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_RUN3 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_RUN4 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_ATK1 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_ATK2 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_ATK3 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_PAIN1 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_PAIN2 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_PAIN3 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_DIE1 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_DIE2 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_DIE3 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_DIE4 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_DIE5 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_DIE6 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_DIE7 + {0,0,-1,NULL,S_NULL,0,0}, // S_BSKUL_DIE8 // killough 10/98: mushroom effect - {SPR_MISL,32769,8,A_Mushroom,S_EXPLODE2}, // S_MUSHROOM + {SPR_MISL,32769,8,A_Mushroom,S_EXPLODE2,0,0}, // S_MUSHROOM }; // ******************************************************************** diff --git a/code/prboom/lprintf.c b/code/prboom/lprintf.c old mode 100644 new mode 100755 index 0951cf3..ebef586 --- a/code/prboom/lprintf.c +++ b/code/prboom/lprintf.c @@ -53,6 +53,8 @@ #include "lprintf.h" #include "i_main.h" #include "m_argv.h" +#include "doomiphone.h" +#include int cons_error_mask = -1-LO_INFO; /* all but LO_INFO when redir'd */ int cons_output_mask = -1; /* all output enabled */ @@ -372,11 +374,32 @@ void I_Error(const char *error, ...) #endif va_end(argptr); lprintf(LO_ERROR, "%s\n", errmsg); + iphoneNSLog(errmsg); + iphoneNSLog("ABANDON SHIP!"); #ifdef _MSC_VER if (!M_CheckParm ("-nodraw")) { //Init_ConsoleWin(); MessageBox(con_hWnd,errmsg,"PrBoom",MB_OK | MB_TASKMODAL | MB_TOPMOST); } #endif - I_SafeExit(-1); + + while( true ) { + printf( " SAFE EXIT \n" ); + // it's likely our WADs are bad. Wipe them out next time. + FILE *fp; + char path[1024]; + char buffer[1024]; + snprintf( path, sizeof( path ), "%s/abandon.ship", SysIphoneGetDocDir() ); + fp = fopen( path, "w" ); + if( ! fp ) { + printf( "Could not write canary. This is very bad!\n" ); + return; + } + snprintf( buffer, sizeof( buffer ), "ABANDON SHIP!\n" ); + fprintf( fp, "%s", buffer ); + fclose(fp); + assert( false ); + usleep(1000); + } + } diff --git a/code/prboom/m_cheat.c b/code/prboom/m_cheat.c old mode 100644 new mode 100755 index aebad97..1c2019f --- a/code/prboom/m_cheat.c +++ b/code/prboom/m_cheat.c @@ -55,37 +55,37 @@ // //----------------------------------------------------------------------------- -static void cheat_mus(); -static void cheat_choppers(); -static void cheat_god(); -static void cheat_fa(); -static void cheat_k(); -static void cheat_kfa(); -static void cheat_noclip(); -static void cheat_pw(); -static void cheat_behold(); -static void cheat_clev(); -static void cheat_mypos(); -static void cheat_rate(); -static void cheat_comp(); -static void cheat_friction(); -static void cheat_pushers(); -static void cheat_tnttran(); -static void cheat_massacre(); -static void cheat_ddt(); -static void cheat_hom(); -static void cheat_fast(); -static void cheat_tntkey(); -static void cheat_tntkeyx(); -static void cheat_tntkeyxx(); -static void cheat_tntweap(); -static void cheat_tntweapx(); -static void cheat_tntammo(); -static void cheat_tntammox(); -static void cheat_smart(); -static void cheat_pitch(); -static void cheat_megaarmour(); -static void cheat_health(); +static void cheat_mus(char buf[3]); +static void cheat_choppers(void); +static void cheat_god(void); +static void cheat_fa(void); +static void cheat_k(void); +static void cheat_kfa(void); +static void cheat_noclip(void); +static void cheat_pw(int pw); +static void cheat_behold(void); +static void cheat_clev(char buf[3]); +static void cheat_mypos(void); +static void cheat_rate(void); +static void cheat_comp(void); +static void cheat_friction(void); +static void cheat_pushers(void); +static void cheat_tnttran(void); +static void cheat_massacre(void); +static void cheat_ddt(void); +static void cheat_hom(void); +static void cheat_fast(void); +static void cheat_tntkey(void); +static void cheat_tntkeyx(void); +static void cheat_tntkeyxx(int key); +static void cheat_tntweap(void); +static void cheat_tntweapx(char buf[3]); +static void cheat_tntammo(void); +static void cheat_tntammox(char buf[1]); +static void cheat_smart(void); +static void cheat_pitch(void); +static void cheat_megaarmour(void); +static void cheat_health(void); //----------------------------------------------------------------------------- // @@ -110,13 +110,13 @@ static void cheat_health(); struct cheat_s cheat[] = { {"idmus", "Change music", always, - cheat_mus, -2}, + cheat_mus, -2, 0, 0 }, {"idchoppers", "Chainsaw", not_net | not_demo, - cheat_choppers }, + cheat_choppers, 0, 0, 0 }, {"iddqd", "God mode", not_net | not_demo, - cheat_god }, + cheat_god, 0, 0, 0 }, #if 0 {"idk", NULL, not_net | not_demo | not_deh, @@ -124,139 +124,139 @@ struct cheat_s cheat[] = { #endif {"idkfa", "Ammo & Keys", not_net | not_demo, - cheat_kfa }, + cheat_kfa, 0, 0, 0 }, {"idfa", "Ammo", not_net | not_demo, - cheat_fa }, + cheat_fa, 0, 0, 0 }, {"idspispopd", "No Clipping 1", not_net | not_demo, - cheat_noclip }, + cheat_noclip, 0, 0, 0 }, {"idclip", "No Clipping 2", not_net | not_demo, - cheat_noclip }, + cheat_noclip, 0, 0, 0 }, {"idbeholdh", "Invincibility", not_net | not_demo, - cheat_health }, + cheat_health, 0, 0, 0 }, {"idbeholdm", "Invincibility", not_net | not_demo, - cheat_megaarmour }, + cheat_megaarmour, 0, 0, 0 }, {"idbeholdv", "Invincibility", not_net | not_demo, - cheat_pw, pw_invulnerability }, + cheat_pw, pw_invulnerability, 0, 0 }, {"idbeholds", "Berserk", not_net | not_demo, - cheat_pw, pw_strength }, + cheat_pw, pw_strength, 0, 0 }, {"idbeholdi", "Invisibility", not_net | not_demo, - cheat_pw, pw_invisibility }, + cheat_pw, pw_invisibility, 0, 0 }, {"idbeholdr", "Radiation Suit", not_net | not_demo, - cheat_pw, pw_ironfeet }, + cheat_pw, pw_ironfeet, 0, 0 }, {"idbeholda", "Auto-map", not_dm, - cheat_pw, pw_allmap }, + cheat_pw, pw_allmap, 0, 0 }, {"idbeholdl", "Lite-Amp Goggles", not_dm, - cheat_pw, pw_infrared }, + cheat_pw, pw_infrared, 0, 0 }, {"idbehold", "BEHOLD menu", not_dm, - cheat_behold }, + cheat_behold, 0, 0, 0 }, {"idclev", "Level Warp", not_net | not_demo | not_menu, - cheat_clev, -2}, + cheat_clev, -2, 0, 0}, {"idmypos", "Player Position", not_dm, - cheat_mypos }, + cheat_mypos, 0, 0, 0 }, {"idrate", "Frame rate", 0, - cheat_rate }, + cheat_rate, 0, 0, 0 }, {"tntcomp", NULL, not_net | not_demo, - cheat_comp }, // phares + cheat_comp, 0, 0, 0 }, // phares {"tntem", NULL, not_net | not_demo, - cheat_massacre }, // jff 2/01/98 kill all monsters + cheat_massacre, 0, 0, 0 }, // jff 2/01/98 kill all monsters {"iddt", "Map cheat", not_dm, - cheat_ddt }, // killough 2/07/98: moved from am_map.c + cheat_ddt, 0, 0, 0 }, // killough 2/07/98: moved from am_map.c {"tnthom", NULL, always, - cheat_hom }, // killough 2/07/98: HOM autodetector + cheat_hom, 0, 0, 0 }, // killough 2/07/98: HOM autodetector {"tntkey", NULL, not_net | not_demo, - cheat_tntkey }, // killough 2/16/98: generalized key cheats + cheat_tntkey, 0, 0, 0 }, // killough 2/16/98: generalized key cheats {"tntkeyr", NULL, not_net | not_demo, - cheat_tntkeyx }, + cheat_tntkeyx, 0, 0, 0 }, {"tntkeyy", NULL, not_net | not_demo, - cheat_tntkeyx }, + cheat_tntkeyx, 0, 0, 0 }, {"tntkeyb", NULL, not_net | not_demo, - cheat_tntkeyx }, + cheat_tntkeyx, 0, 0, 0 }, {"tntkeyrc", NULL, not_net | not_demo, - cheat_tntkeyxx, it_redcard }, + cheat_tntkeyxx, it_redcard, 0, 0 }, {"tntkeyyc", NULL, not_net | not_demo, - cheat_tntkeyxx, it_yellowcard }, + cheat_tntkeyxx, it_yellowcard, 0, 0 }, {"tntkeybc", NULL, not_net | not_demo, - cheat_tntkeyxx, it_bluecard }, + cheat_tntkeyxx, it_bluecard, 0, 0 }, {"tntkeyrs", NULL, not_net | not_demo, - cheat_tntkeyxx, it_redskull }, + cheat_tntkeyxx, it_redskull, 0, 0 }, {"tntkeyys", NULL, not_net | not_demo, - cheat_tntkeyxx, it_yellowskull}, + cheat_tntkeyxx, it_yellowskull, 0, 0 }, {"tntkeybs", NULL, not_net | not_demo, - cheat_tntkeyxx, it_blueskull }, // killough 2/16/98: end generalized keys + cheat_tntkeyxx, it_blueskull, 0, 0 }, // killough 2/16/98: end generalized keys {"tntka", NULL, not_net | not_demo, - cheat_k }, // Ty 04/11/98 - Added TNTKA + cheat_k, 0, 0, 0 }, // Ty 04/11/98 - Added TNTKA {"tntweap", NULL, not_net | not_demo, - cheat_tntweap }, // killough 2/16/98: generalized weapon cheats + cheat_tntweap, 0, 0, 0 }, // killough 2/16/98: generalized weapon cheats {"tntweap", NULL, not_net | not_demo, - cheat_tntweapx, -1}, + cheat_tntweapx, -1, 0, 0}, {"tntammo", NULL, not_net | not_demo, - cheat_tntammo }, + cheat_tntammo, 0, 0, 0 }, {"tntammo", NULL, not_net | not_demo, - cheat_tntammox, -1}, // killough 2/16/98: end generalized weapons + cheat_tntammox, -1, 0, 0}, // killough 2/16/98: end generalized weapons {"tnttran", NULL, always, - cheat_tnttran }, // invoke translucency // phares + cheat_tnttran, 0, 0, 0 }, // invoke translucency // phares {"tntsmart", NULL, not_net | not_demo, - cheat_smart}, // killough 2/21/98: smart monster toggle + cheat_smart, 0, 0, 0}, // killough 2/21/98: smart monster toggle {"tntpitch", NULL, always, - cheat_pitch}, // killough 2/21/98: pitched sound toggle + cheat_pitch, 0, 0, 0}, // killough 2/21/98: pitched sound toggle // killough 2/21/98: reduce RSI injury by adding simpler alias sequences: {"tntran", NULL, always, - cheat_tnttran }, // killough 2/21/98: same as tnttran + cheat_tnttran, 0, 0, 0 }, // killough 2/21/98: same as tnttran {"tntamo", NULL, not_net | not_demo, - cheat_tntammo }, // killough 2/21/98: same as tntammo + cheat_tntammo, 0, 0, 0 }, // killough 2/21/98: same as tntammo {"tntamo", NULL, not_net | not_demo, - cheat_tntammox, -1}, // killough 2/21/98: same as tntammo + cheat_tntammox, -1, 0, 0}, // killough 2/21/98: same as tntammo {"tntfast", NULL, not_net | not_demo, - cheat_fast }, // killough 3/6/98: -fast toggle + cheat_fast, 0, 0, 0 }, // killough 3/6/98: -fast toggle {"tntice", NULL, not_net | not_demo, - cheat_friction }, // phares 3/10/98: toggle variable friction effects + cheat_friction, 0, 0, 0 }, // phares 3/10/98: toggle variable friction effects {"tntpush", NULL, not_net | not_demo, - cheat_pushers }, // phares 3/10/98: toggle pushers + cheat_pushers, 0, 0, 0 }, // phares 3/10/98: toggle pushers - {NULL} // end-of-list marker + {NULL, NULL, 0, NULL, 0, 0, 0} // end-of-list marker }; //----------------------------------------------------------------------------- @@ -542,7 +542,7 @@ static void cheat_massacre() // jff 2/01/98 kill all monsters P_SetMobjState ((mobj_t *) currentthinker, S_PAIN_DIE6); } } - while (!killcount && mask ? mask=0, 1 : 0); // killough 7/20/98 + while (!killcount && mask ? (void)(mask=0), 1 : 0); // killough 7/20/98 P_MapEnd(); // killough 3/22/98: make more intelligent about plural // Ty 03/27/98 - string(s) *not* externalized @@ -648,7 +648,7 @@ char buf[1]; { // killough 5/5/98: switch plasma and rockets for now -- KLUDGE a = a==am_cell ? am_misl : a==am_misl ? am_cell : a; // HACK plyr->message = (plyr->ammo[a] = !plyr->ammo[a]) ? - plyr->ammo[a] = plyr->maxammo[a], "Ammo Added" : "Ammo Removed"; + (void)(plyr->ammo[a] = plyr->maxammo[a]), "Ammo Added" : "Ammo Removed"; } } @@ -706,10 +706,10 @@ boolean M_FindCheats(int key) for (p=cheat[i].cheat; *p; p++) { - unsigned key = tolower(*p)-'a'; // convert to 0-31 - if (key >= 32) // ignore most non-alpha cheat letters + unsigned keynum = tolower(*p)-'a'; // convert to 0-31 + if (keynum >= 32) // ignore most non-alpha cheat letters continue; - c = (c<<5) + key; // shift key into code + c = (c<<5) + keynum; // shift key into code m = (m<<5) + 31; // shift 1's into mask } cheat[i].code = c; // code for this cheat key diff --git a/code/prboom/m_fixed.h b/code/prboom/m_fixed.h old mode 100644 new mode 100755 index 239251a..bb21368 --- a/code/prboom/m_fixed.h +++ b/code/prboom/m_fixed.h @@ -53,30 +53,26 @@ typedef int fixed_t; * killough 9/05/98: better code seems to be gotten from using inlined C */ -#ifdef _MSC_VER -# ifdef I386_ASM -#pragma warning( disable : 4035 ) -__inline static int D_abs(int x) -{ - __asm - { - mov eax,x - cdq - xor eax,edx - sub eax,edx - } -} -# else /* I386_ASM */ -inline static const int D_abs(x) -{ - fixed_t _t = (x),_s; - _s = _t >> (8*sizeof _t-1); - return (_t^_s)-_s; -} -# endif /* I386_ASM */ -#else /* _MSC_VER */ -#define D_abs(x) ({fixed_t _t = (x), _s = _t >> (8*sizeof _t-1); (_t^_s)-_s;}) -#endif /* _MSC_VER */ +#if defined( _MSC_VER ) && defined( I386_ASM ) + #pragma warning( disable : 4035 ) + __inline static int D_abs(int x) + { + __asm + { + mov eax,x + cdq + xor eax,edx + sub eax,edx + } + } +#else + inline static int D_abs( int x ) + { + fixed_t _t = (x),_s; + _s = _t >> (8*sizeof _t-1); + return (_t^_s)-_s; + } +# endif /* * Fixed Point Multiplication diff --git a/code/prboom/m_menu.c b/code/prboom/m_menu.c old mode 100644 new mode 100755 index 91da34b..1946069 --- a/code/prboom/m_menu.c +++ b/code/prboom/m_menu.c @@ -97,7 +97,8 @@ int messageLastMenuActive; boolean messageNeedsInput; // timed message = no input from user -void (*messageRoutine)(int response); +typedef void (*MessageRoutineFunction)(int response); +MessageRoutineFunction messageRoutine; #define SAVESTRINGSIZE 24 @@ -256,7 +257,7 @@ void M_DrawSelCell(menu_t *menu,int item); void M_WriteText(int x, int y, const char *string); int M_StringWidth(const char *string); int M_StringHeight(const char *string); -void M_StartMessage(const char *string,void *routine,boolean input); +void M_StartMessage(const char *string,MessageRoutineFunction routine,boolean input); void M_StopMessage(void); void M_ClearMenus (void); @@ -903,7 +904,7 @@ void M_SaveSelect(int choice) strcpy(saveOldString,savegamestrings[choice]); if (!strcmp(savegamestrings[choice],s_EMPTYSTRING)) // Ty 03/27/98 - externalized savegamestrings[choice][0] = 0; - saveCharIndex = strlen(savegamestrings[choice]); + saveCharIndex = (int)strlen(savegamestrings[choice]); } // @@ -959,7 +960,7 @@ menuitem_t OptionsMenu[]= {1,"M_MESSG", M_ChangeMessages,'m'}, /* {1,"M_DETAIL", M_ChangeDetail,'g'}, unused -- killough */ {2,"M_SCRNSZ", M_SizeDisplay,'s'}, - {-1,"",0}, + {-1,"",0,0}, {1,"M_MSENS", M_ChangeSensitivity,'m'}, /* {-1,"",0}, replaced with submenu -- killough */ {1,"M_SVOL", M_Sound,'s'} @@ -1091,9 +1092,9 @@ enum menuitem_t SoundMenu[]= { {2,"M_SFXVOL",M_SfxVol,'s'}, - {-1,"",0}, + {-1,"",0,0}, {2,"M_MUSVOL",M_MusicVol,'m'}, - {-1,"",0} + {-1,"",0,0} }; menu_t SoundDef = @@ -1181,9 +1182,9 @@ enum menuitem_t MouseMenu[]= { {2,"M_HORSEN",M_MouseHoriz,'h'}, - {-1,"",0}, + {-1,"",0,0}, {2,"M_VERSEN",M_MouseVert,'v'}, - {-1,"",0} + {-1,"",0,0} }; menu_t MouseDef = @@ -1905,7 +1906,7 @@ static void M_DrawSetting(const setup_menu_t* s) // while you're editing the string. while (M_GetPixelWidth(text) >= MAXCHATWIDTH) { - int len = strlen(text); + int len = (int)strlen(text); text[--len] = 0; if (chat_index > len) chat_index--; @@ -2162,41 +2163,41 @@ int mult_screens_index; // the index of the current screen in a set setup_menu_t keys_settings1[] = // Key Binding screen strings { - {"MOVEMENT" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y}, - {"FORWARD" ,S_KEY ,m_scrn,KB_X,KB_Y+1*8,{&key_up},&mousebforward}, - {"BACKWARD" ,S_KEY ,m_scrn,KB_X,KB_Y+2*8,{&key_down}}, - {"TURN LEFT" ,S_KEY ,m_scrn,KB_X,KB_Y+3*8,{&key_left}}, - {"TURN RIGHT" ,S_KEY ,m_scrn,KB_X,KB_Y+4*8,{&key_right}}, - {"RUN" ,S_KEY ,m_scrn,KB_X,KB_Y+5*8,{&key_speed},0,&joybspeed}, - {"STRAFE LEFT" ,S_KEY ,m_scrn,KB_X,KB_Y+6*8,{&key_strafeleft}}, - {"STRAFE RIGHT",S_KEY ,m_scrn,KB_X,KB_Y+7*8,{&key_straferight}}, - {"STRAFE" ,S_KEY ,m_scrn,KB_X,KB_Y+8*8,{&key_strafe},&mousebstrafe,&joybstrafe}, - {"AUTORUN" ,S_KEY ,m_scrn,KB_X,KB_Y+9*8,{&key_autorun}}, - {"180 TURN" ,S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_reverse}}, - {"USE" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_use},&mousebforward,&joybuse}, - - {"MENUS" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8}, - {"NEXT ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+13*8,{&key_menu_down}}, - {"PREV ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+14*8,{&key_menu_up}}, - {"LEFT" ,S_KEY ,m_menu,KB_X,KB_Y+15*8,{&key_menu_left}}, - {"RIGHT" ,S_KEY ,m_menu,KB_X,KB_Y+16*8,{&key_menu_right}}, - {"BACKSPACE" ,S_KEY ,m_menu,KB_X,KB_Y+17*8,{&key_menu_backspace}}, - {"SELECT ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+18*8,{&key_menu_enter}}, - {"EXIT" ,S_KEY ,m_menu,KB_X,KB_Y+19*8,{&key_menu_escape}}, + {"MOVEMENT" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y,{NULL},NULL,NULL,NULL,NULL}, + {"FORWARD" ,S_KEY ,m_scrn,KB_X,KB_Y+1*8,{&key_up},&mousebforward,NULL,NULL,NULL}, + {"BACKWARD" ,S_KEY ,m_scrn,KB_X,KB_Y+2*8,{&key_down},NULL,NULL,NULL,NULL}, + {"TURN LEFT" ,S_KEY ,m_scrn,KB_X,KB_Y+3*8,{&key_left},NULL,NULL,NULL,NULL}, + {"TURN RIGHT" ,S_KEY ,m_scrn,KB_X,KB_Y+4*8,{&key_right},NULL,NULL,NULL,NULL}, + {"RUN" ,S_KEY ,m_scrn,KB_X,KB_Y+5*8,{&key_speed},0,&joybspeed,NULL,NULL}, + {"STRAFE LEFT" ,S_KEY ,m_scrn,KB_X,KB_Y+6*8,{&key_strafeleft},NULL,NULL,NULL,NULL}, + {"STRAFE RIGHT",S_KEY ,m_scrn,KB_X,KB_Y+7*8,{&key_straferight},NULL,NULL,NULL,NULL}, + {"STRAFE" ,S_KEY ,m_scrn,KB_X,KB_Y+8*8,{&key_strafe},&mousebstrafe,&joybstrafe,NULL,NULL}, + {"AUTORUN" ,S_KEY ,m_scrn,KB_X,KB_Y+9*8,{&key_autorun},NULL,NULL,NULL,NULL}, + {"180 TURN" ,S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_reverse},NULL,NULL,NULL,NULL}, + {"USE" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_use},&mousebforward,&joybuse,NULL,NULL}, + + {"MENUS" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8,{NULL},NULL,NULL,NULL,NULL}, + {"NEXT ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+13*8,{&key_menu_down},NULL,NULL,NULL,NULL}, + {"PREV ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+14*8,{&key_menu_up},NULL,NULL,NULL,NULL}, + {"LEFT" ,S_KEY ,m_menu,KB_X,KB_Y+15*8,{&key_menu_left},NULL,NULL,NULL,NULL}, + {"RIGHT" ,S_KEY ,m_menu,KB_X,KB_Y+16*8,{&key_menu_right},NULL,NULL,NULL,NULL}, + {"BACKSPACE" ,S_KEY ,m_menu,KB_X,KB_Y+17*8,{&key_menu_backspace},NULL,NULL,NULL,NULL}, + {"SELECT ITEM" ,S_KEY ,m_menu,KB_X,KB_Y+18*8,{&key_menu_enter},NULL,NULL,NULL,NULL}, + {"EXIT" ,S_KEY ,m_menu,KB_X,KB_Y+19*8,{&key_menu_escape},NULL,NULL,NULL,NULL}, // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, - {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings2}}, + {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings2},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; setup_menu_t keys_settings2[] = // Key Binding screen strings { - {"SCREEN" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y}, + {"SCREEN" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y,{NULL},NULL,NULL,NULL,NULL}, // phares 4/13/98: // key_help and key_escape can no longer be rebound. This keeps the @@ -2208,88 +2209,88 @@ setup_menu_t keys_settings2[] = // Key Binding screen strings // functions. Introduce an S_KEEP flag to show that you cannot swap this // key with other keys in the same 'group'. (m_scrn, etc.) - {"HELP" ,S_SKIP|S_KEEP ,m_scrn,0 ,0 ,{&key_help}}, - {"MENU" ,S_SKIP|S_KEEP ,m_scrn,0 ,0 ,{&key_escape}}, + {"HELP" ,S_SKIP|S_KEEP ,m_scrn,0 ,0 ,{&key_help},NULL,NULL,NULL,NULL}, + {"MENU" ,S_SKIP|S_KEEP ,m_scrn,0 ,0 ,{&key_escape},NULL,NULL,NULL,NULL}, // killough 10/98: hotkey for entering setup menu: - {"SETUP" ,S_KEY ,m_scrn,KB_X,KB_Y+ 1*8,{&key_setup}}, - {"PAUSE" ,S_KEY ,m_scrn,KB_X,KB_Y+ 2*8,{&key_pause}}, - {"AUTOMAP" ,S_KEY ,m_scrn,KB_X,KB_Y+ 3*8,{&key_map}}, - {"VOLUME" ,S_KEY ,m_scrn,KB_X,KB_Y+ 4*8,{&key_soundvolume}}, - {"HUD" ,S_KEY ,m_scrn,KB_X,KB_Y+ 5*8,{&key_hud}}, - {"MESSAGES" ,S_KEY ,m_scrn,KB_X,KB_Y+ 6*8,{&key_messages}}, - {"GAMMA FIX" ,S_KEY ,m_scrn,KB_X,KB_Y+ 7*8,{&key_gamma}}, - {"SPY" ,S_KEY ,m_scrn,KB_X,KB_Y+ 8*8,{&key_spy}}, - {"LARGER VIEW" ,S_KEY ,m_scrn,KB_X,KB_Y+ 9*8,{&key_zoomin}}, - {"SMALLER VIEW",S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_zoomout}}, - {"SCREENSHOT" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_screenshot}}, - {"GAME" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8}, - {"SAVE" ,S_KEY ,m_scrn,KB_X,KB_Y+13*8,{&key_savegame}}, - {"LOAD" ,S_KEY ,m_scrn,KB_X,KB_Y+14*8,{&key_loadgame}}, - {"QUICKSAVE" ,S_KEY ,m_scrn,KB_X,KB_Y+15*8,{&key_quicksave}}, - {"QUICKLOAD" ,S_KEY ,m_scrn,KB_X,KB_Y+16*8,{&key_quickload}}, - {"END GAME" ,S_KEY ,m_scrn,KB_X,KB_Y+17*8,{&key_endgame}}, - {"QUIT" ,S_KEY ,m_scrn,KB_X,KB_Y+18*8,{&key_quit}}, - {"<- PREV", S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings1}}, - {"NEXT ->", S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings3}}, + {"SETUP" ,S_KEY ,m_scrn,KB_X,KB_Y+ 1*8,{&key_setup},NULL,NULL,NULL,NULL}, + {"PAUSE" ,S_KEY ,m_scrn,KB_X,KB_Y+ 2*8,{&key_pause},NULL,NULL,NULL,NULL}, + {"AUTOMAP" ,S_KEY ,m_scrn,KB_X,KB_Y+ 3*8,{&key_map},NULL,NULL,NULL,NULL}, + {"VOLUME" ,S_KEY ,m_scrn,KB_X,KB_Y+ 4*8,{&key_soundvolume},NULL,NULL,NULL,NULL}, + {"HUD" ,S_KEY ,m_scrn,KB_X,KB_Y+ 5*8,{&key_hud},NULL,NULL,NULL,NULL}, + {"MESSAGES" ,S_KEY ,m_scrn,KB_X,KB_Y+ 6*8,{&key_messages},NULL,NULL,NULL,NULL}, + {"GAMMA FIX" ,S_KEY ,m_scrn,KB_X,KB_Y+ 7*8,{&key_gamma},NULL,NULL,NULL,NULL}, + {"SPY" ,S_KEY ,m_scrn,KB_X,KB_Y+ 8*8,{&key_spy},NULL,NULL,NULL,NULL}, + {"LARGER VIEW" ,S_KEY ,m_scrn,KB_X,KB_Y+ 9*8,{&key_zoomin},NULL,NULL,NULL,NULL}, + {"SMALLER VIEW",S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_zoomout},NULL,NULL,NULL,NULL}, + {"SCREENSHOT" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_screenshot},NULL,NULL,NULL,NULL}, + {"GAME" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8,{NULL},NULL,NULL,NULL,NULL}, + {"SAVE" ,S_KEY ,m_scrn,KB_X,KB_Y+13*8,{&key_savegame},NULL,NULL,NULL,NULL}, + {"LOAD" ,S_KEY ,m_scrn,KB_X,KB_Y+14*8,{&key_loadgame},NULL,NULL,NULL,NULL}, + {"QUICKSAVE" ,S_KEY ,m_scrn,KB_X,KB_Y+15*8,{&key_quicksave},NULL,NULL,NULL,NULL}, + {"QUICKLOAD" ,S_KEY ,m_scrn,KB_X,KB_Y+16*8,{&key_quickload},NULL,NULL,NULL,NULL}, + {"END GAME" ,S_KEY ,m_scrn,KB_X,KB_Y+17*8,{&key_endgame},NULL,NULL,NULL,NULL}, + {"QUIT" ,S_KEY ,m_scrn,KB_X,KB_Y+18*8,{&key_quit},NULL,NULL,NULL,NULL}, + {"<- PREV", S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings1},NULL,NULL,NULL,NULL}, + {"NEXT ->", S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings3},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; setup_menu_t keys_settings3[] = // Key Binding screen strings { - {"WEAPONS" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y}, - {"FIST" ,S_KEY ,m_scrn,KB_X,KB_Y+ 1*8,{&key_weapon1}}, - {"PISTOL" ,S_KEY ,m_scrn,KB_X,KB_Y+ 2*8,{&key_weapon2}}, - {"SHOTGUN" ,S_KEY ,m_scrn,KB_X,KB_Y+ 3*8,{&key_weapon3}}, - {"CHAINGUN",S_KEY ,m_scrn,KB_X,KB_Y+ 4*8,{&key_weapon4}}, - {"ROCKET" ,S_KEY ,m_scrn,KB_X,KB_Y+ 5*8,{&key_weapon5}}, - {"PLASMA" ,S_KEY ,m_scrn,KB_X,KB_Y+ 6*8,{&key_weapon6}}, - {"BFG", S_KEY ,m_scrn,KB_X,KB_Y+ 7*8,{&key_weapon7}}, - {"CHAINSAW",S_KEY ,m_scrn,KB_X,KB_Y+ 8*8,{&key_weapon8}}, - {"SSG" ,S_KEY ,m_scrn,KB_X,KB_Y+ 9*8,{&key_weapon9}}, - {"BEST" ,S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_weapontoggle}}, - {"FIRE" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_fire},&mousebfire,&joybfire}, - - {"<- PREV",S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings2}}, - {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings4}}, + {"WEAPONS" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y,{NULL},NULL,NULL,NULL,NULL}, + {"FIST" ,S_KEY ,m_scrn,KB_X,KB_Y+ 1*8,{&key_weapon1},NULL,NULL,NULL,NULL}, + {"PISTOL" ,S_KEY ,m_scrn,KB_X,KB_Y+ 2*8,{&key_weapon2},NULL,NULL,NULL,NULL}, + {"SHOTGUN" ,S_KEY ,m_scrn,KB_X,KB_Y+ 3*8,{&key_weapon3},NULL,NULL,NULL,NULL}, + {"CHAINGUN",S_KEY ,m_scrn,KB_X,KB_Y+ 4*8,{&key_weapon4},NULL,NULL,NULL,NULL}, + {"ROCKET" ,S_KEY ,m_scrn,KB_X,KB_Y+ 5*8,{&key_weapon5},NULL,NULL,NULL,NULL}, + {"PLASMA" ,S_KEY ,m_scrn,KB_X,KB_Y+ 6*8,{&key_weapon6},NULL,NULL,NULL,NULL}, + {"BFG", S_KEY ,m_scrn,KB_X,KB_Y+ 7*8,{&key_weapon7},NULL,NULL,NULL,NULL}, + {"CHAINSAW",S_KEY ,m_scrn,KB_X,KB_Y+ 8*8,{&key_weapon8},NULL,NULL,NULL,NULL}, + {"SSG" ,S_KEY ,m_scrn,KB_X,KB_Y+ 9*8,{&key_weapon9},NULL,NULL,NULL,NULL}, + {"BEST" ,S_KEY ,m_scrn,KB_X,KB_Y+10*8,{&key_weapontoggle},NULL,NULL,NULL,NULL}, + {"FIRE" ,S_KEY ,m_scrn,KB_X,KB_Y+11*8,{&key_fire},&mousebfire,&joybfire,NULL,NULL}, + + {"<- PREV",S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings2},NULL,NULL,NULL,NULL}, + {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {keys_settings4},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; setup_menu_t keys_settings4[] = // Key Binding screen strings { - {"AUTOMAP" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y}, - {"FOLLOW" ,S_KEY ,m_map ,KB_X,KB_Y+ 1*8,{&key_map_follow}}, - {"ZOOM IN" ,S_KEY ,m_map ,KB_X,KB_Y+ 2*8,{&key_map_zoomin}}, - {"ZOOM OUT" ,S_KEY ,m_map ,KB_X,KB_Y+ 3*8,{&key_map_zoomout}}, - {"SHIFT UP" ,S_KEY ,m_map ,KB_X,KB_Y+ 4*8,{&key_map_up}}, - {"SHIFT DOWN" ,S_KEY ,m_map ,KB_X,KB_Y+ 5*8,{&key_map_down}}, - {"SHIFT LEFT" ,S_KEY ,m_map ,KB_X,KB_Y+ 6*8,{&key_map_left}}, - {"SHIFT RIGHT",S_KEY ,m_map ,KB_X,KB_Y+ 7*8,{&key_map_right}}, - {"MARK PLACE" ,S_KEY ,m_map ,KB_X,KB_Y+ 8*8,{&key_map_mark}}, - {"CLEAR MARKS",S_KEY ,m_map ,KB_X,KB_Y+ 9*8,{&key_map_clear}}, - {"FULL/ZOOM" ,S_KEY ,m_map ,KB_X,KB_Y+10*8,{&key_map_gobig}}, - {"GRID" ,S_KEY ,m_map ,KB_X,KB_Y+11*8,{&key_map_grid}}, - - {"CHATTING" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8}, - {"BEGIN CHAT" ,S_KEY ,m_scrn,KB_X,KB_Y+13*8,{&key_chat}}, - {"PLAYER 1" ,S_KEY ,m_scrn,KB_X,KB_Y+14*8,{&destination_keys[0]}}, - {"PLAYER 2" ,S_KEY ,m_scrn,KB_X,KB_Y+15*8,{&destination_keys[1]}}, - {"PLAYER 3" ,S_KEY ,m_scrn,KB_X,KB_Y+16*8,{&destination_keys[2]}}, - {"PLAYER 4" ,S_KEY ,m_scrn,KB_X,KB_Y+17*8,{&destination_keys[3]}}, - {"BACKSPACE" ,S_KEY ,m_scrn,KB_X,KB_Y+18*8,{&key_backspace}}, - {"ENTER" ,S_KEY ,m_scrn,KB_X,KB_Y+19*8,{&key_enter}}, - - {"<- PREV" ,S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings3}}, + {"AUTOMAP" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y,{NULL},NULL,NULL,NULL,NULL}, + {"FOLLOW" ,S_KEY ,m_map ,KB_X,KB_Y+ 1*8,{&key_map_follow},NULL,NULL,NULL,NULL}, + {"ZOOM IN" ,S_KEY ,m_map ,KB_X,KB_Y+ 2*8,{&key_map_zoomin},NULL,NULL,NULL,NULL}, + {"ZOOM OUT" ,S_KEY ,m_map ,KB_X,KB_Y+ 3*8,{&key_map_zoomout},NULL,NULL,NULL,NULL}, + {"SHIFT UP" ,S_KEY ,m_map ,KB_X,KB_Y+ 4*8,{&key_map_up},NULL,NULL,NULL,NULL}, + {"SHIFT DOWN" ,S_KEY ,m_map ,KB_X,KB_Y+ 5*8,{&key_map_down},NULL,NULL,NULL,NULL}, + {"SHIFT LEFT" ,S_KEY ,m_map ,KB_X,KB_Y+ 6*8,{&key_map_left},NULL,NULL,NULL,NULL}, + {"SHIFT RIGHT",S_KEY ,m_map ,KB_X,KB_Y+ 7*8,{&key_map_right},NULL,NULL,NULL,NULL}, + {"MARK PLACE" ,S_KEY ,m_map ,KB_X,KB_Y+ 8*8,{&key_map_mark},NULL,NULL,NULL,NULL}, + {"CLEAR MARKS",S_KEY ,m_map ,KB_X,KB_Y+ 9*8,{&key_map_clear},NULL,NULL,NULL,NULL}, + {"FULL/ZOOM" ,S_KEY ,m_map ,KB_X,KB_Y+10*8,{&key_map_gobig},NULL,NULL,NULL,NULL}, + {"GRID" ,S_KEY ,m_map ,KB_X,KB_Y+11*8,{&key_map_grid},NULL,NULL,NULL,NULL}, + + {"CHATTING" ,S_SKIP|S_TITLE,m_null,KB_X,KB_Y+12*8,{NULL},NULL,NULL,NULL,NULL}, + {"BEGIN CHAT" ,S_KEY ,m_scrn,KB_X,KB_Y+13*8,{&key_chat},NULL,NULL,NULL,NULL}, + {"PLAYER 1" ,S_KEY ,m_scrn,KB_X,KB_Y+14*8,{&destination_keys[0]},NULL,NULL,NULL,NULL}, + {"PLAYER 2" ,S_KEY ,m_scrn,KB_X,KB_Y+15*8,{&destination_keys[1]},NULL,NULL,NULL,NULL}, + {"PLAYER 3" ,S_KEY ,m_scrn,KB_X,KB_Y+16*8,{&destination_keys[2]},NULL,NULL,NULL,NULL}, + {"PLAYER 4" ,S_KEY ,m_scrn,KB_X,KB_Y+17*8,{&destination_keys[3]},NULL,NULL,NULL,NULL}, + {"BACKSPACE" ,S_KEY ,m_scrn,KB_X,KB_Y+18*8,{&key_backspace},NULL,NULL,NULL,NULL}, + {"ENTER" ,S_KEY ,m_scrn,KB_X,KB_Y+19*8,{&key_enter},NULL,NULL,NULL,NULL}, + + {"<- PREV" ,S_SKIP|S_PREV,m_null,KB_PREV,KB_Y+20*8, {keys_settings3},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; @@ -2380,27 +2381,27 @@ setup_menu_t* weap_settings[] = setup_menu_t weap_settings1[] = // Weapons Settings screen { - {"ENABLE RECOIL", S_YESNO,m_null,WP_X, WP_Y+ weap_recoil*8, {"weapon_recoil"}}, - {"ENABLE BOBBING",S_YESNO,m_null,WP_X, WP_Y+weap_bobbing*8, {"player_bobbing"}}, + {"ENABLE RECOIL", S_YESNO,m_null,WP_X, WP_Y+ weap_recoil*8, {"weapon_recoil"},NULL,NULL,NULL,NULL}, + {"ENABLE BOBBING",S_YESNO,m_null,WP_X, WP_Y+weap_bobbing*8, {"player_bobbing"},NULL,NULL,NULL,NULL}, - {"1ST CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref1*8, {"weapon_choice_1"}}, - {"2nd CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref2*8, {"weapon_choice_2"}}, - {"3rd CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref3*8, {"weapon_choice_3"}}, - {"4th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref4*8, {"weapon_choice_4"}}, - {"5th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref5*8, {"weapon_choice_5"}}, - {"6th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref6*8, {"weapon_choice_6"}}, - {"7th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref7*8, {"weapon_choice_7"}}, - {"8th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref8*8, {"weapon_choice_8"}}, - {"9th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref9*8, {"weapon_choice_9"}}, + {"1ST CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref1*8, {"weapon_choice_1"},NULL,NULL,NULL,NULL}, + {"2nd CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref2*8, {"weapon_choice_2"},NULL,NULL,NULL,NULL}, + {"3rd CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref3*8, {"weapon_choice_3"},NULL,NULL,NULL,NULL}, + {"4th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref4*8, {"weapon_choice_4"},NULL,NULL,NULL,NULL}, + {"5th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref5*8, {"weapon_choice_5"},NULL,NULL,NULL,NULL}, + {"6th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref6*8, {"weapon_choice_6"},NULL,NULL,NULL,NULL}, + {"7th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref7*8, {"weapon_choice_7"},NULL,NULL,NULL,NULL}, + {"8th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref8*8, {"weapon_choice_8"},NULL,NULL,NULL,NULL}, + {"9th CHOICE WEAPON",S_WEAP,m_null,WP_X,WP_Y+weap_pref9*8, {"weapon_choice_9"},NULL,NULL,NULL,NULL}, {"Enable Fist/Chainsaw\n& SG/SSG toggle", S_YESNO, m_null, WP_X, - WP_Y+ weap_toggle*8, {"doom_weapon_toggles"}}, + WP_Y+ weap_toggle*8, {"doom_weapon_toggles"},NULL,NULL,NULL,NULL}, // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; @@ -2465,29 +2466,29 @@ setup_menu_t* stat_settings[] = setup_menu_t stat_settings1[] = // Status Bar and HUD Settings screen { - {"STATUS BAR" ,S_SKIP|S_TITLE,m_null,ST_X,ST_Y+ 1*8 }, + {"STATUS BAR" ,S_SKIP|S_TITLE,m_null,ST_X,ST_Y+ 1*8,{NULL},NULL,NULL,NULL,NULL }, - {"USE RED NUMBERS" ,S_YESNO, m_null,ST_X,ST_Y+ 2*8, {"sts_always_red"}}, - {"GRAY %" ,S_YESNO, m_null,ST_X,ST_Y+ 3*8, {"sts_pct_always_gray"}}, - {"SINGLE KEY DISPLAY",S_YESNO, m_null,ST_X,ST_Y+ 4*8, {"sts_traditional_keys"}}, + {"USE RED NUMBERS" ,S_YESNO, m_null,ST_X,ST_Y+ 2*8, {"sts_always_red"},NULL,NULL,NULL,NULL}, + {"GRAY %" ,S_YESNO, m_null,ST_X,ST_Y+ 3*8, {"sts_pct_always_gray"},NULL,NULL,NULL,NULL}, + {"SINGLE KEY DISPLAY",S_YESNO, m_null,ST_X,ST_Y+ 4*8, {"sts_traditional_keys"},NULL,NULL,NULL,NULL}, - {"HEADS-UP DISPLAY" ,S_SKIP|S_TITLE,m_null,ST_X,ST_Y+ 6*8}, + {"HEADS-UP DISPLAY" ,S_SKIP|S_TITLE,m_null,ST_X,ST_Y+ 6*8,{NULL},NULL,NULL,NULL,NULL}, - {"HIDE SECRETS" ,S_YESNO ,m_null,ST_X,ST_Y+ 7*8, {"hud_nosecrets"}}, - {"HEALTH LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+ 8*8, {"health_red"}}, - {"HEALTH OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+ 9*8, {"health_yellow"}}, - {"HEALTH GOOD/EXTRA" ,S_NUM ,m_null,ST_X,ST_Y+10*8, {"health_green"}}, - {"ARMOR LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+11*8, {"armor_red"}}, - {"ARMOR OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+12*8, {"armor_yellow"}}, - {"ARMOR GOOD/EXTRA" ,S_NUM ,m_null,ST_X,ST_Y+13*8, {"armor_green"}}, - {"AMMO LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+14*8, {"ammo_red"}}, - {"AMMO OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+15*8, {"ammo_yellow"}}, + {"HIDE SECRETS" ,S_YESNO ,m_null,ST_X,ST_Y+ 7*8, {"hud_nosecrets"},NULL,NULL,NULL,NULL}, + {"HEALTH LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+ 8*8, {"health_red"},NULL,NULL,NULL,NULL}, + {"HEALTH OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+ 9*8, {"health_yellow"},NULL,NULL,NULL,NULL}, + {"HEALTH GOOD/EXTRA" ,S_NUM ,m_null,ST_X,ST_Y+10*8, {"health_green"},NULL,NULL,NULL,NULL}, + {"ARMOR LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+11*8, {"armor_red"},NULL,NULL,NULL,NULL}, + {"ARMOR OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+12*8, {"armor_yellow"},NULL,NULL,NULL,NULL}, + {"ARMOR GOOD/EXTRA" ,S_NUM ,m_null,ST_X,ST_Y+13*8, {"armor_green"},NULL,NULL,NULL,NULL}, + {"AMMO LOW/OK" ,S_NUM ,m_null,ST_X,ST_Y+14*8, {"ammo_red"},NULL,NULL,NULL,NULL}, + {"AMMO OK/GOOD" ,S_NUM ,m_null,ST_X,ST_Y+15*8, {"ammo_yellow"},NULL,NULL,NULL,NULL}, // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; // Setting up for the Status Bar / HUD screen. Turn on flags, set pointers, @@ -2555,58 +2556,58 @@ setup_menu_t* auto_settings[] = setup_menu_t auto_settings1[] = // 1st AutoMap Settings screen { - {"background", S_COLOR, m_null, AU_X, AU_Y, {"mapcolor_back"}}, - {"grid lines", S_COLOR, m_null, AU_X, AU_Y + 1*8, {"mapcolor_grid"}}, - {"normal 1s wall", S_COLOR, m_null,AU_X,AU_Y+ 2*8, {"mapcolor_wall"}}, - {"line at floor height change", S_COLOR, m_null, AU_X, AU_Y+ 3*8, {"mapcolor_fchg"}}, - {"line at ceiling height change" ,S_COLOR,m_null,AU_X,AU_Y+ 4*8, {"mapcolor_cchg"}}, - {"line at sector with floor = ceiling",S_COLOR,m_null,AU_X,AU_Y+ 5*8, {"mapcolor_clsd"}}, - {"red key" ,S_COLOR,m_null,AU_X,AU_Y+ 6*8, {"mapcolor_rkey"}}, - {"blue key" ,S_COLOR,m_null,AU_X,AU_Y+ 7*8, {"mapcolor_bkey"}}, - {"yellow key" ,S_COLOR,m_null,AU_X,AU_Y+ 8*8, {"mapcolor_ykey"}}, - {"red door" ,S_COLOR,m_null,AU_X,AU_Y+ 9*8, {"mapcolor_rdor"}}, - {"blue door" ,S_COLOR,m_null,AU_X,AU_Y+10*8, {"mapcolor_bdor"}}, - {"yellow door" ,S_COLOR,m_null,AU_X,AU_Y+11*8, {"mapcolor_ydor"}}, + {"background", S_COLOR, m_null, AU_X, AU_Y, {"mapcolor_back"},NULL,NULL,NULL,NULL}, + {"grid lines", S_COLOR, m_null, AU_X, AU_Y + 1*8, {"mapcolor_grid"},NULL,NULL,NULL,NULL}, + {"normal 1s wall", S_COLOR, m_null,AU_X,AU_Y+ 2*8, {"mapcolor_wall"},NULL,NULL,NULL,NULL}, + {"line at floor height change", S_COLOR, m_null, AU_X, AU_Y+ 3*8, {"mapcolor_fchg"},NULL,NULL,NULL,NULL}, + {"line at ceiling height change" ,S_COLOR,m_null,AU_X,AU_Y+ 4*8, {"mapcolor_cchg"},NULL,NULL,NULL,NULL}, + {"line at sector with floor = ceiling",S_COLOR,m_null,AU_X,AU_Y+ 5*8, {"mapcolor_clsd"},NULL,NULL,NULL,NULL}, + {"red key" ,S_COLOR,m_null,AU_X,AU_Y+ 6*8, {"mapcolor_rkey"},NULL,NULL,NULL,NULL}, + {"blue key" ,S_COLOR,m_null,AU_X,AU_Y+ 7*8, {"mapcolor_bkey"},NULL,NULL,NULL,NULL}, + {"yellow key" ,S_COLOR,m_null,AU_X,AU_Y+ 8*8, {"mapcolor_ykey"},NULL,NULL,NULL,NULL}, + {"red door" ,S_COLOR,m_null,AU_X,AU_Y+ 9*8, {"mapcolor_rdor"},NULL,NULL,NULL,NULL}, + {"blue door" ,S_COLOR,m_null,AU_X,AU_Y+10*8, {"mapcolor_bdor"},NULL,NULL,NULL,NULL}, + {"yellow door" ,S_COLOR,m_null,AU_X,AU_Y+11*8, {"mapcolor_ydor"},NULL,NULL,NULL,NULL}, - {"AUTOMAP LEVEL TITLE COLOR" ,S_CRITEM,m_null,AU_X,AU_Y+13*8, {"hudcolor_titl"}}, - {"AUTOMAP COORDINATES COLOR" ,S_CRITEM,m_null,AU_X,AU_Y+14*8, {"hudcolor_xyco"}}, + {"AUTOMAP LEVEL TITLE COLOR" ,S_CRITEM,m_null,AU_X,AU_Y+13*8, {"hudcolor_titl"},NULL,NULL,NULL,NULL}, + {"AUTOMAP COORDINATES COLOR" ,S_CRITEM,m_null,AU_X,AU_Y+14*8, {"hudcolor_xyco"},NULL,NULL,NULL,NULL}, - {"Show Secrets only after entering",S_YESNO,m_null,AU_X,AU_Y+15*8, {"map_secret_after"}}, + {"Show Secrets only after entering",S_YESNO,m_null,AU_X,AU_Y+15*8, {"map_secret_after"},NULL,NULL,NULL,NULL}, - {"Show coordinates of automap pointer",S_YESNO,m_null,AU_X,AU_Y+16*8, {"map_point_coord"}}, // killough 10/98 + {"Show coordinates of automap pointer",S_YESNO,m_null,AU_X,AU_Y+16*8, {"map_point_coord"},NULL,NULL,NULL,NULL}, // killough 10/98 // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, - {"NEXT ->",S_SKIP|S_NEXT,m_null,AU_NEXT,AU_Y+20*8, {auto_settings2}}, + {"NEXT ->",S_SKIP|S_NEXT,m_null,AU_NEXT,AU_Y+20*8, {auto_settings2},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; setup_menu_t auto_settings2[] = // 2nd AutoMap Settings screen { - {"teleporter line" ,S_COLOR ,m_null,AU_X,AU_Y, {"mapcolor_tele"}}, - {"secret sector boundary" ,S_COLOR ,m_null,AU_X,AU_Y+ 1*8, {"mapcolor_secr"}}, + {"teleporter line" ,S_COLOR ,m_null,AU_X,AU_Y, {"mapcolor_tele"},NULL,NULL,NULL,NULL}, + {"secret sector boundary" ,S_COLOR ,m_null,AU_X,AU_Y+ 1*8, {"mapcolor_secr"},NULL,NULL,NULL,NULL}, //jff 4/23/98 add exit line to automap - {"exit line" ,S_COLOR ,m_null,AU_X,AU_Y+ 2*8, {"mapcolor_exit"}}, - {"computer map unseen line" ,S_COLOR ,m_null,AU_X,AU_Y+ 3*8, {"mapcolor_unsn"}}, - {"line w/no floor/ceiling changes",S_COLOR ,m_null,AU_X,AU_Y+ 4*8, {"mapcolor_flat"}}, - {"general sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 5*8, {"mapcolor_sprt"}}, - {"countable enemy sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 6*8, {"mapcolor_enemy"}}, // cph 2006/06/30 - {"countable item sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 7*8, {"mapcolor_item"}}, // mead 3/4/2003 - {"crosshair" ,S_COLOR ,m_null,AU_X,AU_Y+ 8*8, {"mapcolor_hair"}}, - {"single player arrow" ,S_COLOR ,m_null,AU_X,AU_Y+ 9*8, {"mapcolor_sngl"}}, - {"your colour in multiplayer" ,S_COLOR ,m_null,AU_X,AU_Y+10*8, {"mapcolor_me"}}, + {"exit line" ,S_COLOR ,m_null,AU_X,AU_Y+ 2*8, {"mapcolor_exit"},NULL,NULL,NULL,NULL}, + {"computer map unseen line" ,S_COLOR ,m_null,AU_X,AU_Y+ 3*8, {"mapcolor_unsn"},NULL,NULL,NULL,NULL}, + {"line w/no floor/ceiling changes",S_COLOR ,m_null,AU_X,AU_Y+ 4*8, {"mapcolor_flat"},NULL,NULL,NULL,NULL}, + {"general sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 5*8, {"mapcolor_sprt"},NULL,NULL,NULL,NULL}, + {"countable enemy sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 6*8, {"mapcolor_enemy"},NULL,NULL,NULL,NULL}, // cph 2006/06/30 + {"countable item sprite" ,S_COLOR ,m_null,AU_X,AU_Y+ 7*8, {"mapcolor_item"},NULL,NULL,NULL,NULL}, // mead 3/4/2003 + {"crosshair" ,S_COLOR ,m_null,AU_X,AU_Y+ 8*8, {"mapcolor_hair"},NULL,NULL,NULL,NULL}, + {"single player arrow" ,S_COLOR ,m_null,AU_X,AU_Y+ 9*8, {"mapcolor_sngl"},NULL,NULL,NULL,NULL}, + {"your colour in multiplayer" ,S_COLOR ,m_null,AU_X,AU_Y+10*8, {"mapcolor_me"},NULL,NULL,NULL,NULL}, - {"friends" ,S_COLOR ,m_null,AU_X,AU_Y+12*8, {"mapcolor_frnd"}}, // killough 8/8/98 + {"friends" ,S_COLOR ,m_null,AU_X,AU_Y+12*8, {"mapcolor_frnd"},NULL,NULL,NULL,NULL}, // killough 8/8/98 - {"<- PREV",S_SKIP|S_PREV,m_null,AU_PREV,AU_Y+20*8, {auto_settings1}}, + {"<- PREV",S_SKIP|S_PREV,m_null,AU_PREV,AU_Y+20*8, {auto_settings1},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; @@ -2734,22 +2735,22 @@ enum { setup_menu_t enem_settings1[] = // Enemy Settings screen { // killough 7/19/98 - {"Monster Infighting When Provoked",S_YESNO,m_null,E_X,E_Y+ enem_infighting*8, {"monster_infighting"}}, + {"Monster Infighting When Provoked",S_YESNO,m_null,E_X,E_Y+ enem_infighting*8, {"monster_infighting"},NULL,NULL,NULL,NULL}, - {"Remember Previous Enemy",S_YESNO,m_null,E_X,E_Y+ enem_remember*8, {"monsters_remember"}}, + {"Remember Previous Enemy",S_YESNO,m_null,E_X,E_Y+ enem_remember*8, {"monsters_remember"},NULL,NULL,NULL,NULL}, // killough 9/8/98 - {"Monster Backing Out",S_YESNO,m_null,E_X,E_Y+ enem_backing*8, {"monster_backing"}}, + {"Monster Backing Out",S_YESNO,m_null,E_X,E_Y+ enem_backing*8, {"monster_backing"},NULL,NULL,NULL,NULL}, - {"Climb Steep Stairs", S_YESNO,m_null,E_X,E_Y+enem_monkeys*8, {"monkeys"}}, + {"Climb Steep Stairs", S_YESNO,m_null,E_X,E_Y+enem_monkeys*8, {"monkeys"},NULL,NULL,NULL,NULL}, // killough 9/9/98 - {"Intelligently Avoid Hazards",S_YESNO,m_null,E_X,E_Y+ enem_avoid_hazards*8, {"monster_avoid_hazards"}}, + {"Intelligently Avoid Hazards",S_YESNO,m_null,E_X,E_Y+ enem_avoid_hazards*8, {"monster_avoid_hazards"},NULL,NULL,NULL,NULL}, // killough 10/98 - {"Affected by Friction",S_YESNO,m_null,E_X,E_Y+ enem_friction*8, {"monster_friction"}}, + {"Affected by Friction",S_YESNO,m_null,E_X,E_Y+ enem_friction*8, {"monster_friction"},NULL,NULL,NULL,NULL}, - {"Rescue Dying Friends",S_YESNO,m_null,E_X,E_Y+ enem_help_friends*8, {"help_friends"}}, + {"Rescue Dying Friends",S_YESNO,m_null,E_X,E_Y+ enem_help_friends*8, {"help_friends"},NULL,NULL,NULL,NULL}, #ifdef DOGS // killough 7/19/98 @@ -2762,10 +2763,10 @@ setup_menu_t enem_settings1[] = // Enemy Settings screen #endif // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; @@ -2874,25 +2875,25 @@ static const char *gltexformats[] = {"GL_RGBA","GL_RGB5_A1", setup_menu_t gen_settings1[] = { // General Settings screen1 - {"Video" ,S_SKIP|S_TITLE, m_null, G_X, G_YA - 12}, + {"Video" ,S_SKIP|S_TITLE, m_null, G_X, G_YA - 12,{NULL},NULL,NULL,NULL,NULL}, {"Enable Translucency", S_YESNO, m_null, G_X, - G_YA + general_trans*8, {"translucency"}, 0, 0, M_Trans}, + G_YA + general_trans*8, {"translucency"}, 0, 0, M_Trans,NULL}, {"Translucency filter percentage", S_NUM, m_null, G_X, - G_YA + general_transpct*8, {"tran_filter_pct"}, 0, 0, M_Trans}, + G_YA + general_transpct*8, {"tran_filter_pct"}, 0, 0, M_Trans,NULL}, {"Fullscreen Video mode", S_YESNO|S_PRGWARN, m_null, G_X, - G_YA + general_fullscreen*8, {"use_fullscreen"}, 0, 0, NULL}, + G_YA + general_fullscreen*8, {"use_fullscreen"},NULL,NULL,NULL,NULL}, {"Video mode", S_CHOICE|S_PRGWARN, m_null, G_X, G_YA + general_videomode*8, {"videomode"}, 0, 0, NULL, videomodes}, {"Uncapped Framerate", S_YESNO, m_null, G_X, - G_YA + general_uncapped*8, {"uncapped_framerate"}}, + G_YA + general_uncapped*8, {"uncapped_framerate"},NULL,NULL,NULL,NULL}, #ifdef GL_DOOM - {"OpenGL", S_SKIP|S_TITLE, m_null, G_X, G_YA2 - 12}, + {"OpenGL", S_SKIP|S_TITLE, m_null, G_X, G_YA2 - 12,{NULL},NULL,NULL,NULL,NULL}, {"Texture filter", S_CHOICE|S_PRGWARN, m_null, G_X, G_YA2 + general_gl_texfilter*8, {"gl_tex_filter_string"}, 0, 0, NULL, gltexfilters}, @@ -2901,7 +2902,7 @@ setup_menu_t gen_settings1[] = { // General Settings screen1 G_YA2 + general_gl_texformat*8, {"gl_tex_format_string"}, 0, 0, NULL, gltexformats}, {"Item out of Floor offset", S_NUM, m_null, G_X, - G_YA2 + general_flooroffset*8, {"gl_sprite_offset"}}, + G_YA2 + general_flooroffset*8, {"gl_sprite_offset"},NULL,NULL,NULL,NULL}, #endif #if 0 @@ -2914,7 +2915,7 @@ setup_menu_t gen_settings1[] = { // General Settings screen1 G_YA + general_diskicon*8, {"disk_icon"}}, #endif - {"Sound & Music", S_SKIP|S_TITLE, m_null, G_X, G_YA3 - 12}, + {"Sound & Music", S_SKIP|S_TITLE, m_null, G_X, G_YA3 - 12,{NULL},NULL,NULL,NULL,NULL}, #if 0 // MBF {"Sound Card", S_NUM|S_PRGWARN, m_null, G_X, G_YA2 + general_sndcard*8, {"sound_card"}}, @@ -2927,18 +2928,18 @@ setup_menu_t gen_settings1[] = { // General Settings screen1 #endif {"Number of Sound Channels", S_NUM|S_PRGWARN, m_null, G_X, - G_YA3 + general_sndchan*8, {"snd_channels"}}, + G_YA3 + general_sndchan*8, {"snd_channels"},NULL,NULL,NULL,NULL}, {"Enable v1.1 Pitch Effects", S_YESNO, m_null, G_X, - G_YA3 + general_pitch*8, {"pitched_sounds"}}, + G_YA3 + general_pitch*8, {"pitched_sounds"},NULL,NULL,NULL,NULL}, // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, - {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {gen_settings2}}, + {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {gen_settings2},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; enum { @@ -2973,49 +2974,49 @@ static const char *gen_skillstrings[] = { setup_menu_t gen_settings2[] = { // General Settings screen2 - {"Input Devices" ,S_SKIP|S_TITLE, m_null, G_X, G_YB - 12}, + {"Input Devices" ,S_SKIP|S_TITLE, m_null, G_X, G_YB - 12,{NULL},NULL,NULL,NULL,NULL}, {"Enable Mouse", S_YESNO, m_null, G_X, - G_YB + general_mouse*8, {"use_mouse"}}, + G_YB + general_mouse*8, {"use_mouse"},NULL,NULL,NULL,NULL}, {"Enable Joystick", S_YESNO, m_null, G_X, - G_YB + general_joy*8, {"use_joystick"}}, + G_YB + general_joy*8, {"use_joystick"},NULL,NULL,NULL,NULL}, {"Files Preloaded at Game Startup",S_SKIP|S_TITLE, m_null, G_X, - G_YB1 - 12}, + G_YB1 - 12,{NULL},NULL,NULL,NULL,NULL}, - {"WAD # 1", S_FILE, m_null, GF_X, G_YB1 + general_wad1*8, {"wadfile_1"}}, + {"WAD # 1", S_FILE, m_null, GF_X, G_YB1 + general_wad1*8, {"wadfile_1"},NULL,NULL,NULL,NULL}, - {"WAD #2", S_FILE, m_null, GF_X, G_YB1 + general_wad2*8, {"wadfile_2"}}, + {"WAD #2", S_FILE, m_null, GF_X, G_YB1 + general_wad2*8, {"wadfile_2"},NULL,NULL,NULL,NULL}, - {"DEH/BEX # 1", S_FILE, m_null, GF_X, G_YB1 + general_deh1*8, {"dehfile_1"}}, + {"DEH/BEX # 1", S_FILE, m_null, GF_X, G_YB1 + general_deh1*8, {"dehfile_1"},NULL,NULL,NULL,NULL}, - {"DEH/BEX #2", S_FILE, m_null, GF_X, G_YB1 + general_deh2*8, {"dehfile_2"}}, + {"DEH/BEX #2", S_FILE, m_null, GF_X, G_YB1 + general_deh2*8, {"dehfile_2"},NULL,NULL,NULL,NULL}, - {"Miscellaneous" ,S_SKIP|S_TITLE, m_null, G_X, G_YB2 - 12}, + {"Miscellaneous" ,S_SKIP|S_TITLE, m_null, G_X, G_YB2 - 12,{NULL},NULL,NULL,NULL,NULL}, {"Maximum number of player corpses", S_NUM|S_PRGWARN, m_null, G_X, - G_YB2 + general_corpse*8, {"max_player_corpse"}}, + G_YB2 + general_corpse*8, {"max_player_corpse"},NULL,NULL,NULL,NULL}, {"Game speed, percentage of normal", S_NUM|S_PRGWARN, m_null, G_X, - G_YB2 + general_realtic*8, {"realtic_clock_rate"}}, + G_YB2 + general_realtic*8, {"realtic_clock_rate"},NULL,NULL,NULL,NULL}, {"Smooth Demo Playback", S_YESNO, m_null, G_X, - G_YB2 + general_smooth*8, {"demo_smoothturns"}, 0, 0, M_ChangeDemoSmoothTurns}, + G_YB2 + general_smooth*8, {"demo_smoothturns"}, 0, 0, M_ChangeDemoSmoothTurns,NULL}, {"Smooth Demo Playback Factor", S_NUM, m_null, G_X, - G_YB2 + general_smoothfactor*8, {"demo_smoothturnsfactor"}, 0, 0, M_ChangeDemoSmoothTurns}, + G_YB2 + general_smoothfactor*8, {"demo_smoothturnsfactor"}, 0, 0, M_ChangeDemoSmoothTurns,NULL}, {"Default skill level", S_CHOICE, m_null, G_X, G_YB2 + general_defskill*8, {"default_skill"}, 0, 0, NULL, gen_skillstrings}, - {"<- PREV",S_SKIP|S_PREV, m_null, KB_PREV, KB_Y+20*8, {gen_settings1}}, + {"<- PREV",S_SKIP|S_PREV, m_null, KB_PREV, KB_Y+20*8, {gen_settings1},NULL,NULL,NULL,NULL}, - {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {gen_settings3}}, + {"NEXT ->",S_SKIP|S_NEXT,m_null,KB_NEXT,KB_Y+20*8, {gen_settings3},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; enum { @@ -3037,7 +3038,7 @@ static const char *edgetypes[] = {"jagged", "sloped"}; setup_menu_t gen_settings3[] = { // General Settings screen2 - {"Renderer settings" ,S_SKIP|S_TITLE, m_null, G_X, G_YB - 12}, + {"Renderer settings" ,S_SKIP|S_TITLE, m_null, G_X, G_YB - 12,{NULL},NULL,NULL,NULL,NULL}, {"Filter for walls", S_CHOICE, m_null, G_X, G_YC + general_filterwall*8, {"filter_wall"}, 0, 0, NULL, renderfilters}, @@ -3061,13 +3062,13 @@ setup_menu_t gen_settings3[] = { // General Settings screen2 G_YC + general_patchedges*8, {"patch_edges"}, 0, 0, NULL, edgetypes}, {"Flashing HOM indicator", S_YESNO, m_null, G_X, - G_YC + general_hom*8, {"flashing_hom"}}, + G_YC + general_hom*8, {"flashing_hom"},NULL,NULL,NULL,NULL}, - {"<- PREV",S_SKIP|S_PREV, m_null, KB_PREV, KB_Y+20*8, {gen_settings2}}, + {"<- PREV",S_SKIP|S_PREV, m_null, KB_PREV, KB_Y+20*8, {gen_settings2},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; void M_Trans(void) // To reset translucency after setting it in menu @@ -3186,104 +3187,104 @@ enum setup_menu_t comp_settings1[] = // Compatibility Settings screen #1 { {"Any monster can telefrag on MAP30", S_YESNO, m_null, C_X, - C_Y + compat_telefrag * COMP_SPC, {"comp_telefrag"}}, + C_Y + compat_telefrag * COMP_SPC, {"comp_telefrag"},NULL,NULL,NULL,NULL}, {"Some objects never hang over tall ledges", S_YESNO, m_null, C_X, - C_Y + compat_dropoff * COMP_SPC, {"comp_dropoff"}}, + C_Y + compat_dropoff * COMP_SPC, {"comp_dropoff"},NULL,NULL,NULL,NULL}, {"Objects don't fall under their own weight", S_YESNO, m_null, C_X, - C_Y + compat_falloff * COMP_SPC, {"comp_falloff"}}, + C_Y + compat_falloff * COMP_SPC, {"comp_falloff"},NULL,NULL,NULL,NULL}, {"Monsters randomly walk off of moving lifts", S_YESNO, m_null, C_X, - C_Y + compat_staylift * COMP_SPC, {"comp_staylift"}}, + C_Y + compat_staylift * COMP_SPC, {"comp_staylift"},NULL,NULL,NULL,NULL}, {"Monsters get stuck on doortracks", S_YESNO, m_null, C_X, - C_Y + compat_doorstuck * COMP_SPC, {"comp_doorstuck"}}, + C_Y + compat_doorstuck * COMP_SPC, {"comp_doorstuck"},NULL,NULL,NULL,NULL}, {"Monsters don't give up pursuit of targets", S_YESNO, m_null, C_X, - C_Y + compat_pursuit * COMP_SPC, {"comp_pursuit"}}, + C_Y + compat_pursuit * COMP_SPC, {"comp_pursuit"},NULL,NULL,NULL,NULL}, {"Arch-Vile resurrects invincible ghosts", S_YESNO, m_null, C_X, - C_Y + compat_vile * COMP_SPC, {"comp_vile"}}, + C_Y + compat_vile * COMP_SPC, {"comp_vile"},NULL,NULL,NULL,NULL}, {"Pain Elementals limited to 21 lost souls", S_YESNO, m_null, C_X, - C_Y + compat_pain * COMP_SPC, {"comp_pain"}}, + C_Y + compat_pain * COMP_SPC, {"comp_pain"},NULL,NULL,NULL,NULL}, {"Lost souls get stuck behind walls", S_YESNO, m_null, C_X, - C_Y + compat_skull * COMP_SPC, {"comp_skull"}}, + C_Y + compat_skull * COMP_SPC, {"comp_skull"},NULL,NULL,NULL,NULL}, {"Blazing doors make double closing sounds", S_YESNO, m_null, C_X, - C_Y + compat_blazing * COMP_SPC, {"comp_blazing"}}, + C_Y + compat_blazing * COMP_SPC, {"comp_blazing"},NULL,NULL,NULL,NULL}, // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, - {"NEXT ->",S_SKIP|S_NEXT, m_null, KB_NEXT, C_Y+C_NEXTPREV, {comp_settings2}}, + {"NEXT ->",S_SKIP|S_NEXT, m_null, KB_NEXT, C_Y+C_NEXTPREV, {comp_settings2},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; setup_menu_t comp_settings2[] = // Compatibility Settings screen #2 { {"Tagged doors don't trigger special lighting", S_YESNO, m_null, C_X, - C_Y + compat_doorlight * COMP_SPC, {"comp_doorlight"}}, + C_Y + compat_doorlight * COMP_SPC, {"comp_doorlight"},NULL,NULL,NULL,NULL}, {"God mode isn't absolute", S_YESNO, m_null, C_X, - C_Y + compat_god * COMP_SPC, {"comp_god"}}, + C_Y + compat_god * COMP_SPC, {"comp_god"},NULL,NULL,NULL,NULL}, {"Powerup cheats are not infinite duration", S_YESNO, m_null, C_X, - C_Y + compat_infcheat * COMP_SPC, {"comp_infcheat"}}, + C_Y + compat_infcheat * COMP_SPC, {"comp_infcheat"},NULL,NULL,NULL,NULL}, {"Dead players can exit levels", S_YESNO, m_null, C_X, - C_Y + compat_zombie * COMP_SPC, {"comp_zombie"}}, + C_Y + compat_zombie * COMP_SPC, {"comp_zombie"},NULL,NULL,NULL,NULL}, {"Sky is unaffected by invulnerability", S_YESNO, m_null, C_X, - C_Y + compat_skymap * COMP_SPC, {"comp_skymap"}}, + C_Y + compat_skymap * COMP_SPC, {"comp_skymap"},NULL,NULL,NULL,NULL}, {"Use exactly Doom's stairbuilding method", S_YESNO, m_null, C_X, - C_Y + compat_stairs * COMP_SPC, {"comp_stairs"}}, + C_Y + compat_stairs * COMP_SPC, {"comp_stairs"},NULL,NULL,NULL,NULL}, {"Use exactly Doom's floor motion behavior", S_YESNO, m_null, C_X, - C_Y + compat_floors * COMP_SPC, {"comp_floors"}}, + C_Y + compat_floors * COMP_SPC, {"comp_floors"},NULL,NULL,NULL,NULL}, {"Use exactly Doom's movement clipping code", S_YESNO, m_null, C_X, - C_Y + compat_moveblock * COMP_SPC, {"comp_moveblock"}}, + C_Y + compat_moveblock * COMP_SPC, {"comp_moveblock"},NULL,NULL,NULL,NULL}, {"Use exactly Doom's linedef trigger model", S_YESNO, m_null, C_X, - C_Y + compat_model * COMP_SPC, {"comp_model"}}, + C_Y + compat_model * COMP_SPC, {"comp_model"},NULL,NULL,NULL,NULL}, {"Linedef effects work with sector tag = 0", S_YESNO, m_null, C_X, - C_Y + compat_zerotags * COMP_SPC, {"comp_zerotags"}}, + C_Y + compat_zerotags * COMP_SPC, {"comp_zerotags"},NULL,NULL,NULL,NULL}, - {"<- PREV", S_SKIP|S_PREV, m_null, KB_PREV, C_Y+C_NEXTPREV,{comp_settings1}}, + {"<- PREV", S_SKIP|S_PREV, m_null, KB_PREV, C_Y+C_NEXTPREV,{comp_settings1},NULL,NULL,NULL,NULL}, - {"NEXT ->",S_SKIP|S_NEXT, m_null, KB_NEXT, C_Y+C_NEXTPREV, {comp_settings3}}, + {"NEXT ->",S_SKIP|S_NEXT, m_null, KB_NEXT, C_Y+C_NEXTPREV, {comp_settings3},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; setup_menu_t comp_settings3[] = // Compatibility Settings screen #2 { {"All boss types can trigger tag 666 at ExM8", S_YESNO, m_null, C_X, - C_Y + compat_666 * COMP_SPC, {"comp_666"}}, + C_Y + compat_666 * COMP_SPC, {"comp_666"},NULL,NULL,NULL,NULL}, {"Lost souls don't bounce off flat surfaces", S_YESNO, m_null, C_X, - C_Y + compat_soul * COMP_SPC, {"comp_soul"}}, + C_Y + compat_soul * COMP_SPC, {"comp_soul"},NULL,NULL,NULL,NULL}, {"2S middle textures do not animate", S_YESNO, m_null, C_X, - C_Y + compat_maskedanim * COMP_SPC, {"comp_maskedanim"}}, + C_Y + compat_maskedanim * COMP_SPC, {"comp_maskedanim"},NULL,NULL,NULL,NULL}, {"Use exactly Doom's sound code behavior", S_YESNO, m_null, C_X, - C_Y + compat_sound * COMP_SPC, {"comp_sound"}}, + C_Y + compat_sound * COMP_SPC, {"comp_sound"},NULL,NULL,NULL,NULL}, - {"<- PREV", S_SKIP|S_PREV, m_null, KB_PREV, C_Y+C_NEXTPREV,{comp_settings2}}, + {"<- PREV", S_SKIP|S_PREV, m_null, KB_PREV, C_Y+C_NEXTPREV,{comp_settings2},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; // Setting up for the Compatibility screen. Turn on flags, set pointers, @@ -3359,7 +3360,7 @@ setup_menu_t* mess_settings[] = setup_menu_t mess_settings1[] = // Messages screen { {"Message Color During Play", S_CRITEM, m_null, M_X, - M_Y + mess_color_play*8, {"hudcolor_mesg"}}, + M_Y + mess_color_play*8, {"hudcolor_mesg"},NULL,NULL,NULL,NULL}, #if 0 {"Message Duration During Play (ms)", S_NUM, m_null, M_X, @@ -3367,7 +3368,7 @@ setup_menu_t mess_settings1[] = // Messages screen #endif {"Chat Message Color", S_CRITEM, m_null, M_X, - M_Y + mess_color_chat*8, {"hudcolor_chat"}}, + M_Y + mess_color_chat*8, {"hudcolor_chat"},NULL,NULL,NULL,NULL}, #if 0 {"Chat Message Duration (ms)", S_NUM, m_null, M_X, @@ -3375,7 +3376,7 @@ setup_menu_t mess_settings1[] = // Messages screen #endif {"Message Review Color", S_CRITEM, m_null, M_X, - M_Y + mess_color_review*8, {"hudcolor_list"}}, + M_Y + mess_color_review*8, {"hudcolor_list"},NULL,NULL,NULL,NULL}, #if 0 {"Message Listing Review is Temporary", S_YESNO, m_null, M_X, @@ -3386,7 +3387,7 @@ setup_menu_t mess_settings1[] = // Messages screen #endif {"Number of Review Message Lines", S_NUM, m_null, M_X, - M_Y + mess_lines*8, {"hud_msg_lines"}}, + M_Y + mess_lines*8, {"hud_msg_lines"},NULL,NULL,NULL,NULL}, #if 0 {"Message Listing Scrolls Upwards", S_YESNO, m_null, M_X, @@ -3394,14 +3395,14 @@ setup_menu_t mess_settings1[] = // Messages screen #endif {"Message Background", S_YESNO, m_null, M_X, - M_Y + mess_background*8, {"hud_list_bgon"}}, + M_Y + mess_background*8, {"hud_list_bgon"},NULL,NULL,NULL,NULL}, // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; @@ -3461,22 +3462,22 @@ setup_menu_t* chat_settings[] = setup_menu_t chat_settings1[] = // Chat Strings screen { - {"1",S_CHAT,m_null,CS_X,CS_Y+ 1*8, {"chatmacro1"}}, - {"2",S_CHAT,m_null,CS_X,CS_Y+ 2*8, {"chatmacro2"}}, - {"3",S_CHAT,m_null,CS_X,CS_Y+ 3*8, {"chatmacro3"}}, - {"4",S_CHAT,m_null,CS_X,CS_Y+ 4*8, {"chatmacro4"}}, - {"5",S_CHAT,m_null,CS_X,CS_Y+ 5*8, {"chatmacro5"}}, - {"6",S_CHAT,m_null,CS_X,CS_Y+ 6*8, {"chatmacro6"}}, - {"7",S_CHAT,m_null,CS_X,CS_Y+ 7*8, {"chatmacro7"}}, - {"8",S_CHAT,m_null,CS_X,CS_Y+ 8*8, {"chatmacro8"}}, - {"9",S_CHAT,m_null,CS_X,CS_Y+ 9*8, {"chatmacro9"}}, - {"0",S_CHAT,m_null,CS_X,CS_Y+10*8, {"chatmacro0"}}, + {"1",S_CHAT,m_null,CS_X,CS_Y+ 1*8, {"chatmacro1"},NULL,NULL,NULL,NULL}, + {"2",S_CHAT,m_null,CS_X,CS_Y+ 2*8, {"chatmacro2"},NULL,NULL,NULL,NULL}, + {"3",S_CHAT,m_null,CS_X,CS_Y+ 3*8, {"chatmacro3"},NULL,NULL,NULL,NULL}, + {"4",S_CHAT,m_null,CS_X,CS_Y+ 4*8, {"chatmacro4"},NULL,NULL,NULL,NULL}, + {"5",S_CHAT,m_null,CS_X,CS_Y+ 5*8, {"chatmacro5"},NULL,NULL,NULL,NULL}, + {"6",S_CHAT,m_null,CS_X,CS_Y+ 6*8, {"chatmacro6"},NULL,NULL,NULL,NULL}, + {"7",S_CHAT,m_null,CS_X,CS_Y+ 7*8, {"chatmacro7"},NULL,NULL,NULL,NULL}, + {"8",S_CHAT,m_null,CS_X,CS_Y+ 8*8, {"chatmacro8"},NULL,NULL,NULL,NULL}, + {"9",S_CHAT,m_null,CS_X,CS_Y+ 9*8, {"chatmacro9"},NULL,NULL,NULL,NULL}, + {"0",S_CHAT,m_null,CS_X,CS_Y+10*8, {"chatmacro0"},NULL,NULL,NULL,NULL}, // Button for resetting to defaults - {0,S_RESET,m_null,X_BUTTON,Y_BUTTON}, + {0,S_RESET,m_null,X_BUTTON,Y_BUTTON,{NULL},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; @@ -3596,7 +3597,7 @@ static void M_ResetDefaults(void) p->m_joy == dp->location.pi) { if (IS_STRING(*dp)) - free((char*)*dp->location.ppsz), + (void)(free((char*)*dp->location.ppsz)), *dp->location.ppsz = strdup(dp->defaultvalue.psz); else *dp->location.pi = dp->defaultvalue.i; @@ -3870,67 +3871,67 @@ int M_GetKeyString(int c,int offset) setup_menu_t helpstrings[] = // HELP screen strings { - {"SCREEN" ,S_SKIP|S_TITLE,m_null,KT_X1,KT_Y1}, - {"HELP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 1*8,{&key_help}}, - {"MENU" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 2*8,{&key_escape}}, - {"SETUP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 3*8,{&key_setup}}, - {"PAUSE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 4*8,{&key_pause}}, - {"AUTOMAP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 5*8,{&key_map}}, - {"SOUND VOLUME",S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 6*8,{&key_soundvolume}}, - {"HUD" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 7*8,{&key_hud}}, - {"MESSAGES" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 8*8,{&key_messages}}, - {"GAMMA FIX" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 9*8,{&key_gamma}}, - {"SPY" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+10*8,{&key_spy}}, - {"LARGER VIEW" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+11*8,{&key_zoomin}}, - {"SMALLER VIEW",S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+12*8,{&key_zoomout}}, - {"SCREENSHOT" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+13*8,{&key_screenshot}}, - - {"AUTOMAP" ,S_SKIP|S_TITLE,m_null,KT_X1,KT_Y2}, - {"FOLLOW MODE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 1*8,{&key_map_follow}}, - {"ZOOM IN" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 2*8,{&key_map_zoomin}}, - {"ZOOM OUT" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 3*8,{&key_map_zoomout}}, - {"MARK PLACE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 4*8,{&key_map_mark}}, - {"CLEAR MARKS" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 5*8,{&key_map_clear}}, - {"FULL/ZOOM" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 6*8,{&key_map_gobig}}, - {"GRID" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 7*8,{&key_map_grid}}, - - {"WEAPONS" ,S_SKIP|S_TITLE,m_null,KT_X3,KT_Y1}, - {"FIST" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 1*8,{&key_weapon1}}, - {"PISTOL" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 2*8,{&key_weapon2}}, - {"SHOTGUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 3*8,{&key_weapon3}}, - {"CHAINGUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 4*8,{&key_weapon4}}, - {"ROCKET" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 5*8,{&key_weapon5}}, - {"PLASMA" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 6*8,{&key_weapon6}}, - {"BFG 9000" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 7*8,{&key_weapon7}}, - {"CHAINSAW" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 8*8,{&key_weapon8}}, - {"SSG" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 9*8,{&key_weapon9}}, - {"BEST" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+10*8,{&key_weapontoggle}}, - {"FIRE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+11*8,{&key_fire},&mousebfire,&joybfire}, - - {"MOVEMENT" ,S_SKIP|S_TITLE,m_null,KT_X3,KT_Y3}, - {"FORWARD" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 1*8,{&key_up},&mousebforward}, - {"BACKWARD" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 2*8,{&key_down}}, - {"TURN LEFT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 3*8,{&key_left}}, - {"TURN RIGHT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 4*8,{&key_right}}, - {"RUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 5*8,{&key_speed},0,&joybspeed}, - {"STRAFE LEFT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 6*8,{&key_strafeleft}}, - {"STRAFE RIGHT",S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 7*8,{&key_straferight}}, - {"STRAFE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 8*8,{&key_strafe},&mousebstrafe,&joybstrafe}, - {"AUTORUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 9*8,{&key_autorun}}, - {"180 TURN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+10*8,{&key_reverse}}, - {"USE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+11*8,{&key_use},&mousebforward,&joybuse}, - - {"GAME" ,S_SKIP|S_TITLE,m_null,KT_X2,KT_Y1}, - {"SAVE" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 1*8,{&key_savegame}}, - {"LOAD" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 2*8,{&key_loadgame}}, - {"QUICKSAVE" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 3*8,{&key_quicksave}}, - {"END GAME" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 4*8,{&key_endgame}}, - {"QUICKLOAD" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 5*8,{&key_quickload}}, - {"QUIT" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 6*8,{&key_quit}}, + {"SCREEN" ,S_SKIP|S_TITLE,m_null,KT_X1,KT_Y1,{NULL},NULL,NULL,NULL,NULL}, + {"HELP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 1*8,{&key_help},NULL,NULL,NULL,NULL}, + {"MENU" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 2*8,{&key_escape},NULL,NULL,NULL,NULL}, + {"SETUP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 3*8,{&key_setup},NULL,NULL,NULL,NULL}, + {"PAUSE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 4*8,{&key_pause},NULL,NULL,NULL,NULL}, + {"AUTOMAP" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 5*8,{&key_map},NULL,NULL,NULL,NULL}, + {"SOUND VOLUME",S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 6*8,{&key_soundvolume},NULL,NULL,NULL,NULL}, + {"HUD" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 7*8,{&key_hud},NULL,NULL,NULL,NULL}, + {"MESSAGES" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 8*8,{&key_messages},NULL,NULL,NULL,NULL}, + {"GAMMA FIX" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+ 9*8,{&key_gamma},NULL,NULL,NULL,NULL}, + {"SPY" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+10*8,{&key_spy},NULL,NULL,NULL,NULL}, + {"LARGER VIEW" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+11*8,{&key_zoomin},NULL,NULL,NULL,NULL}, + {"SMALLER VIEW",S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+12*8,{&key_zoomout},NULL,NULL,NULL,NULL}, + {"SCREENSHOT" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y1+13*8,{&key_screenshot},NULL,NULL,NULL,NULL}, + + {"AUTOMAP" ,S_SKIP|S_TITLE,m_null,KT_X1,KT_Y2,{NULL},NULL,NULL,NULL,NULL}, + {"FOLLOW MODE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 1*8,{&key_map_follow},NULL,NULL,NULL,NULL}, + {"ZOOM IN" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 2*8,{&key_map_zoomin},NULL,NULL,NULL,NULL}, + {"ZOOM OUT" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 3*8,{&key_map_zoomout},NULL,NULL,NULL,NULL}, + {"MARK PLACE" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 4*8,{&key_map_mark},NULL,NULL,NULL,NULL}, + {"CLEAR MARKS" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 5*8,{&key_map_clear},NULL,NULL,NULL,NULL}, + {"FULL/ZOOM" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 6*8,{&key_map_gobig},NULL,NULL,NULL,NULL}, + {"GRID" ,S_SKIP|S_KEY,m_null,KT_X1,KT_Y2+ 7*8,{&key_map_grid},NULL,NULL,NULL,NULL}, + + {"WEAPONS" ,S_SKIP|S_TITLE,m_null,KT_X3,KT_Y1,{NULL},NULL,NULL,NULL,NULL}, + {"FIST" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 1*8,{&key_weapon1},NULL,NULL,NULL,NULL}, + {"PISTOL" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 2*8,{&key_weapon2},NULL,NULL,NULL,NULL}, + {"SHOTGUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 3*8,{&key_weapon3},NULL,NULL,NULL,NULL}, + {"CHAINGUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 4*8,{&key_weapon4},NULL,NULL,NULL,NULL}, + {"ROCKET" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 5*8,{&key_weapon5},NULL,NULL,NULL,NULL}, + {"PLASMA" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 6*8,{&key_weapon6},NULL,NULL,NULL,NULL}, + {"BFG 9000" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 7*8,{&key_weapon7},NULL,NULL,NULL,NULL}, + {"CHAINSAW" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 8*8,{&key_weapon8},NULL,NULL,NULL,NULL}, + {"SSG" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+ 9*8,{&key_weapon9},NULL,NULL,NULL,NULL}, + {"BEST" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+10*8,{&key_weapontoggle},NULL,NULL,NULL,NULL}, + {"FIRE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y1+11*8,{&key_fire},&mousebfire,&joybfire,NULL,NULL}, + + {"MOVEMENT" ,S_SKIP|S_TITLE,m_null,KT_X3,KT_Y3,{NULL},NULL,NULL,NULL,NULL}, + {"FORWARD" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 1*8,{&key_up},&mousebforward,NULL,NULL,NULL}, + {"BACKWARD" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 2*8,{&key_down},NULL,NULL,NULL,NULL}, + {"TURN LEFT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 3*8,{&key_left},NULL,NULL,NULL,NULL}, + {"TURN RIGHT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 4*8,{&key_right},NULL,NULL,NULL,NULL}, + {"RUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 5*8,{&key_speed},0,&joybspeed,NULL,NULL}, + {"STRAFE LEFT" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 6*8,{&key_strafeleft},NULL,NULL,NULL,NULL}, + {"STRAFE RIGHT",S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 7*8,{&key_straferight},NULL,NULL,NULL,NULL}, + {"STRAFE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 8*8,{&key_strafe},&mousebstrafe,&joybstrafe,NULL,NULL}, + {"AUTORUN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+ 9*8,{&key_autorun},NULL,NULL,NULL,NULL}, + {"180 TURN" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+10*8,{&key_reverse},NULL,NULL,NULL,NULL}, + {"USE" ,S_SKIP|S_KEY,m_null,KT_X3,KT_Y3+11*8,{&key_use},&mousebforward,&joybuse,NULL,NULL}, + + {"GAME" ,S_SKIP|S_TITLE,m_null,KT_X2,KT_Y1,{NULL},NULL,NULL,NULL,NULL}, + {"SAVE" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 1*8,{&key_savegame},NULL,NULL,NULL,NULL}, + {"LOAD" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 2*8,{&key_loadgame},NULL,NULL,NULL,NULL}, + {"QUICKSAVE" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 3*8,{&key_quicksave},NULL,NULL,NULL,NULL}, + {"END GAME" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 4*8,{&key_endgame},NULL,NULL,NULL,NULL}, + {"QUICKLOAD" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 5*8,{&key_quickload},NULL,NULL,NULL,NULL}, + {"QUIT" ,S_SKIP|S_KEY,m_null,KT_X2,KT_Y1+ 6*8,{&key_quit},NULL,NULL,NULL,NULL}, // Final entry - {0,S_SKIP|S_END,m_null} + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; #define SPACEWIDTH 4 @@ -4041,23 +4042,23 @@ enum { setup_menu_t cred_settings[]={ - {"Programmers",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X, CR_Y + CR_S*prog + CR_SH*cr_prog}, - {"Florian 'Proff' Schulze",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+1) + CR_SH*cr_prog}, - {"Colin Phipps",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+2) + CR_SH*cr_prog}, - {"Neil Stevens",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+3) + CR_SH*cr_prog}, - {"Andrey Budko",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+4) + CR_SH*cr_prog}, - - {"Additional Credit To",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X, CR_Y + CR_S*adcr + CR_SH*cr_adcr}, - {"id Software for DOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+1)+CR_SH*cr_adcr}, - {"TeamTNT for BOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+2)+CR_SH*cr_adcr}, - {"Lee Killough for MBF",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+3)+CR_SH*cr_adcr}, - {"The DOSDoom-Team for DOSDOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+4)+CR_SH*cr_adcr}, - {"Randy Heit for ZDOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+5)+CR_SH*cr_adcr}, - {"Michael 'Kodak' Ryssen for DOOMGL",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+6)+CR_SH*cr_adcr}, - {"Jess Haas for lSDLDoom",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+7) + CR_SH*cr_adcr}, - {"all others who helped (see AUTHORS file)",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+8)+CR_SH*cr_adcr}, - - {0,S_SKIP|S_END,m_null} + {"Programmers",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X, CR_Y + CR_S*prog + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL}, + {"Florian 'Proff' Schulze",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+1) + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL}, + {"Colin Phipps",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+2) + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL}, + {"Neil Stevens",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+3) + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL}, + {"Andrey Budko",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(prog+4) + CR_SH*cr_prog,{NULL},NULL,NULL,NULL,NULL}, + + {"Additional Credit To",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X, CR_Y + CR_S*adcr + CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + {"id Software for DOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+1)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + {"TeamTNT for BOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+2)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + {"Lee Killough for MBF",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+3)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + {"The DOSDoom-Team for DOSDOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+4)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + {"Randy Heit for ZDOOM",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+5)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + {"Michael 'Kodak' Ryssen for DOOMGL",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+6)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + {"Jess Haas for lSDLDoom",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+7) + CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + {"all others who helped (see AUTHORS file)",S_SKIP|S_CREDIT|S_LEFTJUST,m_null, CR_X2, CR_Y + CR_S*(adcr+8)+CR_SH*cr_adcr,{NULL},NULL,NULL,NULL,NULL}, + + {0,S_SKIP|S_END,m_null,0,0,{NULL},NULL,NULL,NULL,NULL} }; void M_DrawCredits(void) // killough 10/98: credit screen @@ -4092,11 +4093,7 @@ boolean M_Responder (event_t* ev) { int ch; int i; static int joywait = 0; - static int mousewait = 0; - static int mousey = 0; - static int lasty = 0; - static int mousex = 0; - static int lastx = 0; + static int mousewait = 0; ch = -1; // will be changed to a legit char if we're going to use it here @@ -4680,7 +4677,7 @@ boolean M_Responder (event_t* ev) { } else if (ev->type == ev_mouse) { - int i,oldbutton,group; + int oldbutton,group; boolean search = true; if (!ptr1->m_mouse) @@ -4717,7 +4714,7 @@ boolean M_Responder (event_t* ev) { } else // keyboard key { - int i,oldkey,group; + int oldkey,group; boolean search = true; // see if 'ch' is already bound elsewhere. if so, you have @@ -5348,7 +5345,7 @@ void M_Ticker (void) // Message Routines // -void M_StartMessage (const char* string,void* routine,boolean input) +void M_StartMessage (const char* string,MessageRoutineFunction routine,boolean input) { messageLastMenuActive = menuactive; messageToPrint = 1; diff --git a/code/prboom/m_misc.c b/code/prboom/m_misc.c old mode 100644 new mode 100755 index 718c638..fcfb4ca --- a/code/prboom/m_misc.c +++ b/code/prboom/m_misc.c @@ -124,7 +124,7 @@ int M_ReadFile(char const *name, byte **buffer) { fclose(fp); I_EndRead(); - return length; + return (int)length; } fclose(fp); } @@ -153,8 +153,8 @@ extern int viewheight; extern int gl_nearclip; extern int gl_colorbuffer_bits; extern int gl_depthbuffer_bits; -extern char *gl_tex_filter_string; -extern char *gl_tex_format_string; +extern const char *gl_tex_filter_string; +extern const char *gl_tex_format_string; extern int gl_drawskys; extern int gl_sortsprites; extern int gl_use_paletted_texture; @@ -170,6 +170,7 @@ extern int showMessages; #ifndef DJGPP int mus_pause_opt; // 0 = kill music, 1 = pause, 2 = continue +bool mus_on = true; #endif extern const char* chat_macros[]; @@ -185,63 +186,63 @@ int map_point_coordinates; default_t defaults[] = { - {"Misc settings",{NULL},{0},UL,UL,def_none,ss_none}, - {"default_compatibility_level",{(int*)&default_compatibility_level}, - {-1},-1,MAX_COMPATIBILITY_LEVEL-1, - def_int,ss_none}, // compatibility level" - CPhipps - {"realtic_clock_rate",{&realtic_clock_rate},{100},0,UL, - def_int,ss_none}, // percentage of normal speed (35 fps) realtic clock runs at - {"max_player_corpse", {&bodyquesize}, {32},-1,UL, // killough 2/8/98 - def_int,ss_none}, // number of dead bodies in view supported (-1 = no limit) - {"flashing_hom",{&flashing_hom},{0},0,1, - def_bool,ss_none}, // killough 10/98 - enable flashing HOM indicator - {"demo_insurance",{&default_demo_insurance},{2},0,2, // killough 3/31/98 - def_int,ss_none}, // 1=take special steps ensuring demo sync, 2=only during recordings - {"endoom_mode", {&endoom_mode},{5},0,7, // CPhipps - endoom flags - def_hex, ss_none}, // 0, +1 for colours, +2 for non-ascii chars, +4 for skip-last-line - {"level_precache",{(int*)&precache},{0},0,1, - def_bool,ss_none}, // precache level data? - {"demo_smoothturns", {&demo_smoothturns}, {0},0,1, - def_bool,ss_stat}, - {"demo_smoothturnsfactor", {&demo_smoothturnsfactor}, {6},1,SMOOTH_PLAYING_MAXFACTOR, - def_int,ss_stat}, - - {"Files",{NULL},{0},UL,UL,def_none,ss_none}, + {"Misc settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, + {"default_compatibility_level",{(int*)&default_compatibility_level,NULL}, + {-1,NULL},-1,MAX_COMPATIBILITY_LEVEL-1, + def_int,ss_none,NULL,NULL}, // compatibility level" - CPhipps + {"realtic_clock_rate",{&realtic_clock_rate,NULL},{100,NULL},0,UL, + def_int,ss_none,NULL,NULL}, // percentage of normal speed (35 fps) realtic clock runs at + {"max_player_corpse", {&bodyquesize,NULL}, {32,NULL},-1,UL, // killough 2/8/98 + def_int,ss_none,NULL,NULL}, // number of dead bodies in view supported (-1 = no limit) + {"flashing_hom",{&flashing_hom,NULL},{0,NULL},0,1, + def_bool,ss_none,NULL,NULL}, // killough 10/98 - enable flashing HOM indicator + {"demo_insurance",{&default_demo_insurance,NULL},{2,NULL},0,2, // killough 3/31/98 + def_int,ss_none,NULL,NULL}, // 1=take special steps ensuring demo sync, 2=only during recordings + {"endoom_mode", {&endoom_mode,NULL},{5,NULL},0,7, // CPhipps - endoom flags + def_hex, ss_none,NULL,NULL}, // 0, +1 for colours, +2 for non-ascii chars, +4 for skip-last-line + {"level_precache",{(int*)&precache,NULL},{0,NULL},0,1, + def_bool,ss_none,NULL,NULL}, // precache level data? + {"demo_smoothturns", {&demo_smoothturns,NULL}, {0,NULL},0,1, + def_bool,ss_stat,NULL,NULL}, + {"demo_smoothturnsfactor", {&demo_smoothturnsfactor,NULL}, {6,NULL},1,SMOOTH_PLAYING_MAXFACTOR, + def_int,ss_stat,NULL,NULL}, + + {"Files",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, /* cph - MBF-like wad/deh/bex autoload code */ - {"wadfile_1",{NULL,&wad_files[0]},{0,""},UL,UL,def_str,ss_none}, - {"wadfile_2",{NULL,&wad_files[1]},{0,""},UL,UL,def_str,ss_none}, - {"dehfile_1",{NULL,&deh_files[0]},{0,""},UL,UL,def_str,ss_none}, - {"dehfile_2",{NULL,&deh_files[1]},{0,""},UL,UL,def_str,ss_none}, - - {"Game settings",{NULL},{0},UL,UL,def_none,ss_none}, - {"default_skill",{&defaultskill},{3},1,5, // jff 3/24/98 allow default skill setting - def_int,ss_none}, // selects default skill 1=TYTD 2=NTR 3=HMP 4=UV 5=NM - {"weapon_recoil",{&default_weapon_recoil},{0},0,1, - def_bool,ss_weap, &weapon_recoil}, + {"wadfile_1",{NULL,&wad_files[0]},{0,""},UL,UL,def_str,ss_none,NULL,NULL}, + {"wadfile_2",{NULL,&wad_files[1]},{0,""},UL,UL,def_str,ss_none,NULL,NULL}, + {"dehfile_1",{NULL,&deh_files[0]},{0,""},UL,UL,def_str,ss_none,NULL,NULL}, + {"dehfile_2",{NULL,&deh_files[1]},{0,""},UL,UL,def_str,ss_none,NULL,NULL}, + + {"Game settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, + {"default_skill",{&defaultskill,NULL},{3,NULL},1,5, // jff 3/24/98 allow default skill setting + def_int,ss_none,NULL,NULL}, // selects default skill 1=TYTD 2=NTR 3=HMP 4=UV 5=NM + {"weapon_recoil",{&default_weapon_recoil,NULL},{0,NULL},0,1, + def_bool,ss_weap, &weapon_recoil,NULL}, /* killough 10/98 - toggle between SG/SSG and Fist/Chainsaw */ - {"doom_weapon_toggles",{&doom_weapon_toggles}, {1}, 0, 1, - def_bool, ss_weap }, - {"player_bobbing",{&default_player_bobbing},{1},0,1, // phares 2/25/98 - def_bool,ss_weap, &player_bobbing}, - {"monsters_remember",{&default_monsters_remember},{1},0,1, // killough 3/1/98 - def_bool,ss_enem, &monsters_remember}, + {"doom_weapon_toggles",{&doom_weapon_toggles,NULL}, {1,NULL}, 0, 1, + def_bool, ss_weap,NULL,NULL}, + {"player_bobbing",{&default_player_bobbing,NULL},{1,NULL},0,1, // phares 2/25/98 + def_bool,ss_weap, &player_bobbing,NULL}, + {"monsters_remember",{&default_monsters_remember,NULL},{1,NULL},0,1, // killough 3/1/98 + def_bool,ss_enem, &monsters_remember,NULL}, /* MBF AI enhancement options */ - {"monster_infighting",{&default_monster_infighting}, {1}, 0, 1, - def_bool, ss_enem, &monster_infighting}, - {"monster_backing",{&default_monster_backing}, {0}, 0, 1, - def_bool, ss_enem, &monster_backing}, - {"monster_avoid_hazards",{&default_monster_avoid_hazards}, {1}, 0, 1, - def_bool, ss_enem, &monster_avoid_hazards}, - {"monkeys",{&default_monkeys}, {0}, 0, 1, - def_bool, ss_enem, &monkeys}, - {"monster_friction",{&default_monster_friction}, {1}, 0, 1, - def_bool, ss_enem, &monster_friction}, - {"help_friends",{&default_help_friends}, {1}, 0, 1, - def_bool, ss_enem, &help_friends}, - {"allow_pushers",{&default_allow_pushers},{1},0,1, - def_bool,ss_weap, &allow_pushers}, - {"variable_friction",{&default_variable_friction},{1},0,1, - def_bool,ss_weap, &variable_friction}, + {"monster_infighting",{&default_monster_infighting,NULL}, {1,NULL}, 0, 1, + def_bool, ss_enem, &monster_infighting,NULL}, + {"monster_backing",{&default_monster_backing,NULL}, {0,NULL}, 0, 1, + def_bool, ss_enem, &monster_backing,NULL}, + {"monster_avoid_hazards",{&default_monster_avoid_hazards,NULL}, {1,NULL}, 0, 1, + def_bool, ss_enem, &monster_avoid_hazards,NULL}, + {"monkeys",{&default_monkeys,NULL}, {0,NULL}, 0, 1, + def_bool, ss_enem, &monkeys,NULL}, + {"monster_friction",{&default_monster_friction,NULL}, {1,NULL}, 0, 1, + def_bool, ss_enem, &monster_friction,NULL}, + {"help_friends",{&default_help_friends,NULL}, {1,NULL}, 0, 1, + def_bool, ss_enem, &help_friends,NULL}, + {"allow_pushers",{&default_allow_pushers,NULL},{1,NULL},0,1, + def_bool,ss_weap, &allow_pushers,NULL}, + {"variable_friction",{&default_variable_friction,NULL},{1,NULL},0,1, + def_bool,ss_weap, &variable_friction,NULL}, #ifdef DOGS {"player_helpers",{&default_dogs}, {0}, 0, 3, def_bool, ss_enem }, @@ -252,153 +253,153 @@ default_t defaults[] = #endif /* End of MBF AI extras */ - {"sts_always_red",{&sts_always_red},{1},0,1, // no color changes on status bar - def_bool,ss_stat}, - {"sts_pct_always_gray",{&sts_pct_always_gray},{0},0,1, // 2/23/98 chg default - def_bool,ss_stat}, // makes percent signs on status bar always gray - {"sts_traditional_keys",{&sts_traditional_keys},{0},0,1, // killough 2/28/98 - def_bool,ss_stat}, // disables doubled card and skull key display on status bar - {"show_messages",{&showMessages},{1},0,1, - def_bool,ss_none}, // enables message display - {"autorun",{&autorun},{0},0,1, // killough 3/6/98: preserve autorun across games - def_bool,ss_none}, - - {"Compatibility settings",{NULL},{0},UL,UL,def_none,ss_none}, - {"comp_zombie",{&default_comp[comp_zombie]},{0},0,1,def_bool,ss_comp,&comp[comp_zombie]}, - {"comp_infcheat",{&default_comp[comp_infcheat]},{0},0,1,def_bool,ss_comp,&comp[comp_infcheat]}, - {"comp_stairs",{&default_comp[comp_stairs]},{0},0,1,def_bool,ss_comp,&comp[comp_stairs]}, - {"comp_telefrag",{&default_comp[comp_telefrag]},{0},0,1,def_bool,ss_comp,&comp[comp_telefrag]}, - {"comp_dropoff",{&default_comp[comp_dropoff]},{0},0,1,def_bool,ss_comp,&comp[comp_dropoff]}, - {"comp_falloff",{&default_comp[comp_falloff]},{0},0,1,def_bool,ss_comp,&comp[comp_falloff]}, - {"comp_staylift",{&default_comp[comp_staylift]},{0},0,1,def_bool,ss_comp,&comp[comp_staylift]}, - {"comp_doorstuck",{&default_comp[comp_doorstuck]},{0},0,1,def_bool,ss_comp,&comp[comp_doorstuck]}, - {"comp_pursuit",{&default_comp[comp_pursuit]},{0},0,1,def_bool,ss_comp,&comp[comp_pursuit]}, - {"comp_vile",{&default_comp[comp_vile]},{0},0,1,def_bool,ss_comp,&comp[comp_vile]}, - {"comp_pain",{&default_comp[comp_pain]},{0},0,1,def_bool,ss_comp,&comp[comp_pain]}, - {"comp_skull",{&default_comp[comp_skull]},{0},0,1,def_bool,ss_comp,&comp[comp_skull]}, - {"comp_blazing",{&default_comp[comp_blazing]},{0},0,1,def_bool,ss_comp,&comp[comp_blazing]}, - {"comp_doorlight",{&default_comp[comp_doorlight]},{0},0,1,def_bool,ss_comp,&comp[comp_doorlight]}, - {"comp_god",{&default_comp[comp_god]},{0},0,1,def_bool,ss_comp,&comp[comp_god]}, - {"comp_skymap",{&default_comp[comp_skymap]},{0},0,1,def_bool,ss_comp,&comp[comp_skymap]}, - {"comp_floors",{&default_comp[comp_floors]},{0},0,1,def_bool,ss_comp,&comp[comp_floors]}, - {"comp_model",{&default_comp[comp_model]},{0},0,1,def_bool,ss_comp,&comp[comp_model]}, - {"comp_zerotags",{&default_comp[comp_zerotags]},{0},0,1,def_bool,ss_comp,&comp[comp_zerotags]}, - {"comp_moveblock",{&default_comp[comp_moveblock]},{0},0,1,def_bool,ss_comp,&comp[comp_moveblock]}, - {"comp_sound",{&default_comp[comp_sound]},{0},0,1,def_bool,ss_comp,&comp[comp_sound]}, - {"comp_666",{&default_comp[comp_666]},{0},0,1,def_bool,ss_comp,&comp[comp_666]}, - {"comp_soul",{&default_comp[comp_soul]},{0},0,1,def_bool,ss_comp,&comp[comp_soul]}, - {"comp_maskedanim",{&default_comp[comp_maskedanim]},{0},0,1,def_bool,ss_comp,&comp[comp_maskedanim]}, - - {"Sound settings",{NULL},{0},UL,UL,def_none,ss_none}, - {"sound_card",{&snd_card},{-1},-1,7, // jff 1/18/98 allow Allegro drivers - def_int,ss_none}, // select sounds driver (DOS), -1 is autodetect, 0 is none; in Linux, non-zero enables sound - {"music_card",{&mus_card},{-1},-1,9, // to be set, -1 = autodetect - def_int,ss_none}, // select music driver (DOS), -1 is autodetect, 0 is none"; in Linux, non-zero enables music - {"pitched_sounds",{&pitched_sounds},{0},0,1, // killough 2/21/98 - def_bool,ss_none}, // enables variable pitch in sound effects (from id's original code) - {"samplerate",{&snd_samplerate},{22050},11025,48000, def_int,ss_none}, - {"sfx_volume",{&snd_SfxVolume},{8},0,15, def_int,ss_none}, - {"music_volume",{&snd_MusicVolume},{8},0,15, def_int,ss_none}, - {"mus_pause_opt",{&mus_pause_opt},{2},0,2, // CPhipps - music pausing - def_int, ss_none}, // 0 = kill music when paused, 1 = pause music, 2 = let music continue - {"snd_channels",{&default_numChannels},{8},1,32, - def_int,ss_none}, // number of audio events simultaneously // killough - - {"Video settings",{NULL},{0},UL,UL,def_none,ss_none}, + {"sts_always_red",{&sts_always_red,NULL},{1,NULL},0,1, // no color changes on status bar + def_bool,ss_stat,NULL,NULL}, + {"sts_pct_always_gray",{&sts_pct_always_gray,NULL},{0,NULL},0,1, // 2/23/98 chg default + def_bool,ss_stat,NULL,NULL}, // makes percent signs on status bar always gray + {"sts_traditional_keys",{&sts_traditional_keys,NULL},{0,NULL},0,1, // killough 2/28/98 + def_bool,ss_stat,NULL,NULL}, // disables doubled card and skull key display on status bar + {"show_messages",{&showMessages,NULL},{1,NULL},0,1, + def_bool,ss_none,NULL,NULL}, // enables message display + {"autorun",{&autorun,NULL},{0,NULL},0,1, // killough 3/6/98: preserve autorun across games + def_bool,ss_none,NULL,NULL}, + + {"Compatibility settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, + {"comp_zombie",{&default_comp[comp_zombie],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_zombie],NULL}, + {"comp_infcheat",{&default_comp[comp_infcheat],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_infcheat],NULL}, + {"comp_stairs",{&default_comp[comp_stairs],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_stairs],NULL}, + {"comp_telefrag",{&default_comp[comp_telefrag],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_telefrag],NULL}, + {"comp_dropoff",{&default_comp[comp_dropoff],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_dropoff],NULL}, + {"comp_falloff",{&default_comp[comp_falloff],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_falloff],NULL}, + {"comp_staylift",{&default_comp[comp_staylift],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_staylift],NULL}, + {"comp_doorstuck",{&default_comp[comp_doorstuck],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_doorstuck],NULL}, + {"comp_pursuit",{&default_comp[comp_pursuit],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_pursuit],NULL}, + {"comp_vile",{&default_comp[comp_vile],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_vile],NULL}, + {"comp_pain",{&default_comp[comp_pain],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_pain],NULL}, + {"comp_skull",{&default_comp[comp_skull],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_skull],NULL}, + {"comp_blazing",{&default_comp[comp_blazing],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_blazing],NULL}, + {"comp_doorlight",{&default_comp[comp_doorlight],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_doorlight],NULL}, + {"comp_god",{&default_comp[comp_god],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_god],NULL}, + {"comp_skymap",{&default_comp[comp_skymap],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_skymap],NULL}, + {"comp_floors",{&default_comp[comp_floors],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_floors],NULL}, + {"comp_model",{&default_comp[comp_model],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_model],NULL}, + {"comp_zerotags",{&default_comp[comp_zerotags],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_zerotags],NULL}, + {"comp_moveblock",{&default_comp[comp_moveblock],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_moveblock],NULL}, + {"comp_sound",{&default_comp[comp_sound],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_sound],NULL}, + {"comp_666",{&default_comp[comp_666],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_666],NULL}, + {"comp_soul",{&default_comp[comp_soul],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_soul],NULL}, + {"comp_maskedanim",{&default_comp[comp_maskedanim],NULL},{0,NULL},0,1,def_bool,ss_comp,&comp[comp_maskedanim],NULL}, + + {"Sound settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, + {"sound_card",{&snd_card,NULL},{-1,NULL},-1,7, // jff 1/18/98 allow Allegro drivers + def_int,ss_none,NULL,NULL}, // select sounds driver (DOS), -1 is autodetect, 0 is none; in Linux, non-zero enables sound + {"music_card",{&mus_card,NULL},{-1,NULL},-1,9, // to be set, -1 = autodetect + def_int,ss_none,NULL,NULL}, // select music driver (DOS), -1 is autodetect, 0 is none"; in Linux, non-zero enables music + {"pitched_sounds",{&pitched_sounds,NULL},{0,NULL},0,1, // killough 2/21/98 + def_bool,ss_none,NULL,NULL}, // enables variable pitch in sound effects (from id's original code) + {"samplerate",{&snd_samplerate,NULL},{22050,NULL},11025,48000, def_int,ss_none,NULL,NULL}, + {"sfx_volume",{&snd_SfxVolume,NULL},{8,NULL},0,15, def_int,ss_none,NULL,NULL}, + {"music_volume",{&snd_MusicVolume,NULL},{8,NULL},0,15, def_int,ss_none,NULL,NULL}, + {"mus_pause_opt",{&mus_pause_opt,NULL},{2,NULL},0,2, // CPhipps - music pausing + def_int, ss_none,NULL,NULL}, // 0 = kill music when paused, 1 = pause music, 2 = let music continue + {"snd_channels",{&default_numChannels,NULL},{16,NULL},1,32, + def_int,ss_none,NULL,NULL}, // number of audio events simultaneously // killough + + {"Video settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, #ifdef GL_DOOM #ifdef _MSC_VER {"videomode",{NULL, &default_videomode},{0,"gl"},UL,UL,def_str,ss_none}, #else - {"videomode",{NULL, &default_videomode},{0,"8"},UL,UL,def_str,ss_none}, + {"videomode",{NULL, &default_videomode},{0,"8"},UL,UL,def_str,ss_none,NULL,NULL}, #endif #else {"videomode",{NULL, &default_videomode},{0,"8"},UL,UL,def_str,ss_none}, #endif /* 640x480 default resolution */ - {"screen_width",{&desired_screenwidth},{640}, 320, MAX_SCREENWIDTH, - def_int,ss_none}, - {"screen_height",{&desired_screenheight},{480},200,MAX_SCREENHEIGHT, - def_int,ss_none}, - {"use_fullscreen",{&use_fullscreen},{1},0,1, /* proff 21/05/2000 */ - def_bool,ss_none}, + {"screen_width",{&desired_screenwidth,NULL},{640,NULL}, 320, MAX_SCREENWIDTH, + def_int,ss_none,NULL,NULL}, + {"screen_height",{&desired_screenheight,NULL},{480,NULL},200,MAX_SCREENHEIGHT, + def_int,ss_none,NULL,NULL}, + {"use_fullscreen",{&use_fullscreen,NULL},{1,NULL},0,1, /* proff 21/05/2000 */ + def_bool,ss_none,NULL,NULL}, #ifndef DISABLE_DOUBLEBUFFER {"use_doublebuffer",{&use_doublebuffer},{1},0,1, // proff 2001-7-4 def_bool,ss_none}, // enable doublebuffer to avoid display tearing (fullscreen) #endif #ifdef IPHONE // JDC, don't waste time builing the tables at startup -{"translucency",{&default_translucency},{0},0,1, // phares -def_bool,ss_none}, // enables translucency +{"translucency",{&default_translucency,NULL},{0,NULL},0,1, // phares +def_bool,ss_none,NULL,NULL}, // enables translucency #else {"translucency",{&default_translucency},{1},0,1, // phares def_bool,ss_none}, // enables translucency #endif - {"tran_filter_pct",{&tran_filter_pct},{66},0,100, // killough 2/21/98 - def_int,ss_none}, // set percentage of foreground/background translucency mix - {"screenblocks",{&screenblocks},{10},3,11, // killough 2/21/98: default to 10 - def_int,ss_none}, - {"usegamma",{&usegamma},{3},0,4, //jff 3/6/98 fix erroneous upper limit in range - def_int,ss_none}, // gamma correction level // killough 1/18/98 - {"uncapped_framerate", {&movement_smooth}, {0},0,1, - def_bool,ss_stat}, - {"filter_wall",{(int*)&drawvars.filterwall},{RDRAW_FILTER_POINT}, - RDRAW_FILTER_POINT, RDRAW_FILTER_ROUNDED, def_int,ss_none}, - {"filter_floor",{(int*)&drawvars.filterfloor},{RDRAW_FILTER_POINT}, - RDRAW_FILTER_POINT, RDRAW_FILTER_ROUNDED, def_int,ss_none}, - {"filter_sprite",{(int*)&drawvars.filtersprite},{RDRAW_FILTER_POINT}, - RDRAW_FILTER_POINT, RDRAW_FILTER_ROUNDED, def_int,ss_none}, - {"filter_z",{(int*)&drawvars.filterz},{RDRAW_FILTER_POINT}, - RDRAW_FILTER_POINT, RDRAW_FILTER_LINEAR, def_int,ss_none}, - {"filter_patch",{(int*)&drawvars.filterpatch},{RDRAW_FILTER_POINT}, - RDRAW_FILTER_POINT, RDRAW_FILTER_ROUNDED, def_int,ss_none}, - {"filter_threshold",{(int*)&drawvars.mag_threshold},{49152}, - 0, UL, def_int,ss_none}, - {"sprite_edges",{(int*)&drawvars.sprite_edges},{RDRAW_MASKEDCOLUMNEDGE_SQUARE}, - RDRAW_MASKEDCOLUMNEDGE_SQUARE, RDRAW_MASKEDCOLUMNEDGE_SLOPED, def_int,ss_none}, - {"patch_edges",{(int*)&drawvars.patch_edges},{RDRAW_MASKEDCOLUMNEDGE_SQUARE}, - RDRAW_MASKEDCOLUMNEDGE_SQUARE, RDRAW_MASKEDCOLUMNEDGE_SLOPED, def_int,ss_none}, + {"tran_filter_pct",{&tran_filter_pct,NULL},{66,NULL},0,100, // killough 2/21/98 + def_int,ss_none,NULL,NULL}, // set percentage of foreground/background translucency mix + {"screenblocks",{&screenblocks,NULL},{10,NULL},3,11, // killough 2/21/98: default to 10 + def_int,ss_none,NULL,NULL}, + {"usegamma",{&usegamma,NULL},{3,NULL},0,4, //jff 3/6/98 fix erroneous upper limit in range + def_int,ss_none,NULL,NULL}, // gamma correction level // killough 1/18/98 + {"uncapped_framerate", {&movement_smooth,NULL}, {0,NULL},0,1, + def_bool,ss_stat,NULL,NULL}, + {"filter_wall",{(int*)&drawvars.filterwall,NULL},{RDRAW_FILTER_POINT,NULL}, + RDRAW_FILTER_POINT, RDRAW_FILTER_ROUNDED, def_int,ss_none,NULL,NULL}, + {"filter_floor",{(int*)&drawvars.filterfloor,NULL},{RDRAW_FILTER_POINT,NULL}, + RDRAW_FILTER_POINT, RDRAW_FILTER_ROUNDED, def_int,ss_none,NULL,NULL}, + {"filter_sprite",{(int*)&drawvars.filtersprite,NULL},{RDRAW_FILTER_POINT,NULL}, + RDRAW_FILTER_POINT, RDRAW_FILTER_ROUNDED, def_int,ss_none,NULL,NULL}, + {"filter_z",{(int*)&drawvars.filterz,NULL},{RDRAW_FILTER_POINT,NULL}, + RDRAW_FILTER_POINT, RDRAW_FILTER_LINEAR, def_int,ss_none,NULL,NULL}, + {"filter_patch",{(int*)&drawvars.filterpatch,NULL},{RDRAW_FILTER_POINT,NULL}, + RDRAW_FILTER_POINT, RDRAW_FILTER_ROUNDED, def_int,ss_none,NULL,NULL}, + {"filter_threshold",{(int*)&drawvars.mag_threshold,NULL},{49152,NULL}, + 0, UL, def_int,ss_none,NULL,NULL}, + {"sprite_edges",{(int*)&drawvars.sprite_edges,NULL},{RDRAW_MASKEDCOLUMNEDGE_SQUARE,NULL}, + RDRAW_MASKEDCOLUMNEDGE_SQUARE, RDRAW_MASKEDCOLUMNEDGE_SLOPED, def_int,ss_none,NULL,NULL}, + {"patch_edges",{(int*)&drawvars.patch_edges,NULL},{RDRAW_MASKEDCOLUMNEDGE_SQUARE,NULL}, + RDRAW_MASKEDCOLUMNEDGE_SQUARE, RDRAW_MASKEDCOLUMNEDGE_SLOPED, def_int,ss_none,NULL,NULL}, #ifdef GL_DOOM - {"OpenGL settings",{NULL},{0},UL,UL,def_none,ss_none}, - {"gl_nearclip",{&gl_nearclip},{5},0,UL, - def_int,ss_none}, /* near clipping plane pos */ - {"gl_colorbuffer_bits",{&gl_colorbuffer_bits},{16},16,32, - def_int,ss_none}, - {"gl_depthbuffer_bits",{&gl_depthbuffer_bits},{16},16,32, - def_int,ss_none}, + {"OpenGL settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, + {"gl_nearclip",{&gl_nearclip,NULL},{5,NULL},0,UL, + def_int,ss_none,NULL,NULL}, /* near clipping plane pos */ + {"gl_colorbuffer_bits",{&gl_colorbuffer_bits,NULL},{16,NULL},16,32, + def_int,ss_none,NULL,NULL}, + {"gl_depthbuffer_bits",{&gl_depthbuffer_bits,NULL},{16,NULL},16,32, + def_int,ss_none,NULL,NULL}, {"gl_tex_filter_string", {NULL,&gl_tex_filter_string}, {0,"GL_LINEAR"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"gl_tex_format_string", {NULL,&gl_tex_format_string}, {0,"GL_RGB5_A1"},UL,UL, - def_str,ss_none}, - {"gl_drawskys",{&gl_drawskys},{1},0,1, - def_bool,ss_none}, - {"gl_sortsprites",{&gl_sortsprites},{1},0,1, - def_bool,ss_none}, - {"gl_use_paletted_texture",{&gl_use_paletted_texture},{0},0,1, - def_bool,ss_none}, - {"gl_use_shared_texture_palette",{&gl_use_shared_texture_palette},{0},0,1, - def_bool,ss_none}, + def_str,ss_none,NULL,NULL}, + {"gl_drawskys",{&gl_drawskys,NULL},{1,NULL},0,1, + def_bool,ss_none,NULL,NULL}, + {"gl_sortsprites",{&gl_sortsprites,NULL},{1,NULL},0,1, + def_bool,ss_none,NULL,NULL}, + {"gl_use_paletted_texture",{&gl_use_paletted_texture,NULL},{0,NULL},0,1, + def_bool,ss_none,NULL,NULL}, + {"gl_use_shared_texture_palette",{&gl_use_shared_texture_palette,NULL},{0,NULL},0,1, + def_bool,ss_none,NULL,NULL}, #ifdef GL_DOOM - {"gl_sprite_offset",{&gl_sprite_offset},{0}, 0, 5, - def_int,ss_none}, // amount to bring items out of floor (GL) Mead 8/13/03 + {"gl_sprite_offset",{&gl_sprite_offset,NULL},{0,NULL}, 0, 5, + def_int,ss_none,NULL,NULL}, // amount to bring items out of floor (GL) Mead 8/13/03 #endif #endif - {"Mouse settings",{NULL},{0},UL,UL,def_none,ss_none}, - {"use_mouse",{&usemouse},{1},0,1, - def_bool,ss_none}, // enables use of mouse with DOOM + {"Mouse settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, + {"use_mouse",{&usemouse,NULL},{1,NULL},0,1, + def_bool,ss_none,NULL,NULL}, // enables use of mouse with DOOM //jff 4/3/98 allow unlimited sensitivity - {"mouse_sensitivity_horiz",{&mouseSensitivity_horiz},{10},0,UL, - def_int,ss_none}, /* adjust horizontal (x) mouse sensitivity killough/mead */ + {"mouse_sensitivity_horiz",{&mouseSensitivity_horiz,NULL},{10,NULL},0,UL, + def_int,ss_none,NULL,NULL}, /* adjust horizontal (x) mouse sensitivity killough/mead */ //jff 4/3/98 allow unlimited sensitivity - {"mouse_sensitivity_vert",{&mouseSensitivity_vert},{10},0,UL, - def_int,ss_none}, /* adjust vertical (y) mouse sensitivity killough/mead */ + {"mouse_sensitivity_vert",{&mouseSensitivity_vert,NULL},{10,NULL},0,UL, + def_int,ss_none,NULL,NULL}, /* adjust vertical (y) mouse sensitivity killough/mead */ //jff 3/8/98 allow -1 in mouse bindings to disable mouse function - {"mouseb_fire",{&mousebfire},{0},-1,MAX_MOUSEB, - def_int,ss_keys}, // mouse button number to use for fire - {"mouseb_strafe",{&mousebstrafe},{1},-1,MAX_MOUSEB, - def_int,ss_keys}, // mouse button number to use for strafing - {"mouseb_forward",{&mousebforward},{2},-1,MAX_MOUSEB, - def_int,ss_keys}, // mouse button number to use for forward motion + {"mouseb_fire",{&mousebfire,NULL},{0,NULL},-1,MAX_MOUSEB, + def_int,ss_keys,NULL,NULL}, // mouse button number to use for fire + {"mouseb_strafe",{&mousebstrafe,NULL},{1,NULL},-1,MAX_MOUSEB, + def_int,ss_keys,NULL,NULL}, // mouse button number to use for strafing + {"mouseb_forward",{&mousebforward,NULL},{2,NULL},-1,MAX_MOUSEB, + def_int,ss_keys,NULL,NULL}, // mouse button number to use for forward motion //jff 3/8/98 end of lower range change for -1 allowed in mouse binding // For key bindings, the values stored in the key_* variables // phares @@ -406,443 +407,461 @@ def_bool,ss_none}, // enables translucency // file are the keyboard codes. // CPhipps - now they're the doom codes, so default.cfg can be portable - {"Key bindings",{NULL},{0},UL,UL,def_none,ss_none}, - {"key_right", {&key_right}, {KEYD_RIGHTARROW}, - 0,MAX_KEY,def_key,ss_keys}, // key to turn right - {"key_left", {&key_left}, {KEYD_LEFTARROW} , - 0,MAX_KEY,def_key,ss_keys}, // key to turn left - {"key_up", {&key_up}, {KEYD_UPARROW} , - 0,MAX_KEY,def_key,ss_keys}, // key to move forward - {"key_down", {&key_down}, {KEYD_DOWNARROW}, - 0,MAX_KEY,def_key,ss_keys}, // key to move backward - {"key_menu_right", {&key_menu_right}, {KEYD_RIGHTARROW},// phares 3/7/98 - 0,MAX_KEY,def_key,ss_keys}, // key to move right in a menu // | - {"key_menu_left", {&key_menu_left}, {KEYD_LEFTARROW} ,// V - 0,MAX_KEY,def_key,ss_keys}, // key to move left in a menu - {"key_menu_up", {&key_menu_up}, {KEYD_UPARROW} , - 0,MAX_KEY,def_key,ss_keys}, // key to move up in a menu - {"key_menu_down", {&key_menu_down}, {KEYD_DOWNARROW} , - 0,MAX_KEY,def_key,ss_keys}, // key to move down in a menu - {"key_menu_backspace",{&key_menu_backspace},{KEYD_BACKSPACE} , - 0,MAX_KEY,def_key,ss_keys}, // delete key in a menu - {"key_menu_escape", {&key_menu_escape}, {KEYD_ESCAPE} , - 0,MAX_KEY,def_key,ss_keys}, // key to leave a menu , // phares 3/7/98 - {"key_menu_enter", {&key_menu_enter}, {KEYD_ENTER} , - 0,MAX_KEY,def_key,ss_keys}, // key to select from menu - {"key_strafeleft", {&key_strafeleft}, {','} , - 0,MAX_KEY,def_key,ss_keys}, // key to strafe left - {"key_straferight", {&key_straferight}, {'.'} , - 0,MAX_KEY,def_key,ss_keys}, // key to strafe right - - {"key_fire", {&key_fire}, {KEYD_RCTRL} , - 0,MAX_KEY,def_key,ss_keys}, // duh - {"key_use", {&key_use}, {' '} , - 0,MAX_KEY,def_key,ss_keys}, // key to open a door, use a switch - {"key_strafe", {&key_strafe}, {KEYD_RALT} , - 0,MAX_KEY,def_key,ss_keys}, // key to use with arrows to strafe - {"key_speed", {&key_speed}, {KEYD_RSHIFT} , - 0,MAX_KEY,def_key,ss_keys}, // key to run - - {"key_savegame", {&key_savegame}, {KEYD_F2} , - 0,MAX_KEY,def_key,ss_keys}, // key to save current game - {"key_loadgame", {&key_loadgame}, {KEYD_F3} , - 0,MAX_KEY,def_key,ss_keys}, // key to restore from saved games - {"key_soundvolume", {&key_soundvolume}, {KEYD_F4} , - 0,MAX_KEY,def_key,ss_keys}, // key to bring up sound controls - {"key_hud", {&key_hud}, {KEYD_F5} , - 0,MAX_KEY,def_key,ss_keys}, // key to adjust HUD - {"key_quicksave", {&key_quicksave}, {KEYD_F6} , - 0,MAX_KEY,def_key,ss_keys}, // key to to quicksave - {"key_endgame", {&key_endgame}, {KEYD_F7} , - 0,MAX_KEY,def_key,ss_keys}, // key to end the game - {"key_messages", {&key_messages}, {KEYD_F8} , - 0,MAX_KEY,def_key,ss_keys}, // key to toggle message enable - {"key_quickload", {&key_quickload}, {KEYD_F9} , - 0,MAX_KEY,def_key,ss_keys}, // key to load from quicksave - {"key_quit", {&key_quit}, {KEYD_F10} , - 0,MAX_KEY,def_key,ss_keys}, // key to quit game - {"key_gamma", {&key_gamma}, {KEYD_F11} , - 0,MAX_KEY,def_key,ss_keys}, // key to adjust gamma correction - {"key_spy", {&key_spy}, {KEYD_F12} , - 0,MAX_KEY,def_key,ss_keys}, // key to view from another coop player's view - {"key_pause", {&key_pause}, {KEYD_PAUSE} , - 0,MAX_KEY,def_key,ss_keys}, // key to pause the game - {"key_autorun", {&key_autorun}, {KEYD_CAPSLOCK} , - 0,MAX_KEY,def_key,ss_keys}, // key to toggle always run mode - {"key_chat", {&key_chat}, {'t'} , - 0,MAX_KEY,def_key,ss_keys}, // key to enter a chat message - {"key_backspace", {&key_backspace}, {KEYD_BACKSPACE} , - 0,MAX_KEY,def_key,ss_keys}, // backspace key - {"key_enter", {&key_enter}, {KEYD_ENTER} , - 0,MAX_KEY,def_key,ss_keys}, // key to select from menu or see last message - {"key_map", {&key_map}, {KEYD_TAB} , - 0,MAX_KEY,def_key,ss_keys}, // key to toggle automap display - {"key_map_right", {&key_map_right}, {KEYD_RIGHTARROW},// phares 3/7/98 - 0,MAX_KEY,def_key,ss_keys}, // key to shift automap right // | - {"key_map_left", {&key_map_left}, {KEYD_LEFTARROW} ,// V - 0,MAX_KEY,def_key,ss_keys}, // key to shift automap left - {"key_map_up", {&key_map_up}, {KEYD_UPARROW} , - 0,MAX_KEY,def_key,ss_keys}, // key to shift automap up - {"key_map_down", {&key_map_down}, {KEYD_DOWNARROW} , - 0,MAX_KEY,def_key,ss_keys}, // key to shift automap down - {"key_map_zoomin", {&key_map_zoomin}, {'='} , - 0,MAX_KEY,def_key,ss_keys}, // key to enlarge automap - {"key_map_zoomout", {&key_map_zoomout}, {'-'} , - 0,MAX_KEY,def_key,ss_keys}, // key to reduce automap - {"key_map_gobig", {&key_map_gobig}, {'0'} , - 0,MAX_KEY,def_key,ss_keys}, // key to get max zoom for automap - {"key_map_follow", {&key_map_follow}, {'f'} , - 0,MAX_KEY,def_key,ss_keys}, // key to toggle follow mode - {"key_map_mark", {&key_map_mark}, {'m'} , - 0,MAX_KEY,def_key,ss_keys}, // key to drop a marker on automap - {"key_map_clear", {&key_map_clear}, {'c'} , - 0,MAX_KEY,def_key,ss_keys}, // key to clear all markers on automap - {"key_map_grid", {&key_map_grid}, {'g'} , - 0,MAX_KEY,def_key,ss_keys}, // key to toggle grid display over automap - {"key_map_rotate", {&key_map_rotate}, {'r'} , - 0,MAX_KEY,def_key,ss_keys}, // key to toggle rotating the automap to match the player's orientation - {"key_map_overlay", {&key_map_overlay}, {'o'} , - 0,MAX_KEY,def_key,ss_keys}, // key to toggle overlaying the automap on the rendered display - {"key_reverse", {&key_reverse}, {'/'} , - 0,MAX_KEY,def_key,ss_keys}, // key to spin 180 instantly - {"key_zoomin", {&key_zoomin}, {'='} , - 0,MAX_KEY,def_key,ss_keys}, // key to enlarge display - {"key_zoomout", {&key_zoomout}, {'-'} , - 0,MAX_KEY,def_key,ss_keys}, // key to reduce display - {"key_chatplayer1", {&destination_keys[0]}, {'g'} , - 0,MAX_KEY,def_key,ss_keys}, // key to chat with player 1 + {"Key bindings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, + {"key_right", {&key_right,NULL}, {KEYD_RIGHTARROW,NULL}, + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to turn right + {"key_left", {&key_left,NULL}, {KEYD_LEFTARROW,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to turn left + {"key_up", {&key_up,NULL}, {KEYD_UPARROW,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to move forward + {"key_down", {&key_down,NULL}, {KEYD_DOWNARROW,NULL}, + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to move backward + {"key_menu_right", {&key_menu_right,NULL}, {KEYD_RIGHTARROW,NULL},// phares 3/7/98 + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to move right in a menu // | + {"key_menu_left", {&key_menu_left,NULL}, {KEYD_LEFTARROW,NULL} ,// V + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to move left in a menu + {"key_menu_up", {&key_menu_up,NULL}, {KEYD_UPARROW,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to move up in a menu + {"key_menu_down", {&key_menu_down,NULL}, {KEYD_DOWNARROW,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to move down in a menu + {"key_menu_backspace",{&key_menu_backspace,NULL}, {KEYD_BACKSPACE,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // delete key in a menu + {"key_menu_escape", {&key_menu_escape,NULL}, {KEYD_ESCAPE,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to leave a menu , // phares 3/7/98 + {"key_menu_enter", {&key_menu_enter,NULL}, {KEYD_ENTER,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to select from menu + {"key_strafeleft", {&key_strafeleft,NULL}, {',',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to strafe left + {"key_straferight", {&key_straferight,NULL}, {'.',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to strafe right + + {"key_fire", {&key_fire,NULL}, {KEYD_RCTRL,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // duh + {"key_use", {&key_use,NULL}, {' ',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to open a door, use a switch + {"key_strafe", {&key_strafe,NULL}, {KEYD_RALT,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to use with arrows to strafe + {"key_speed", {&key_speed,NULL}, {KEYD_RSHIFT,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to run + + {"key_savegame", {&key_savegame,NULL}, {KEYD_F2,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to save current game + {"key_loadgame", {&key_loadgame,NULL}, {KEYD_F3,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to restore from saved games + {"key_soundvolume", {&key_soundvolume,NULL}, {KEYD_F4,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to bring up sound controls + {"key_hud", {&key_hud,NULL}, {KEYD_F5,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to adjust HUD + {"key_quicksave", {&key_quicksave,NULL}, {KEYD_F6,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to to quicksave + {"key_endgame", {&key_endgame,NULL}, {KEYD_F7,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to end the game + {"key_messages", {&key_messages,NULL}, {KEYD_F8,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to toggle message enable + {"key_quickload", {&key_quickload,NULL}, {KEYD_F9,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to load from quicksave + {"key_quit", {&key_quit,NULL}, {KEYD_F10,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to quit game + {"key_gamma", {&key_gamma,NULL}, {KEYD_F11,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to adjust gamma correction + {"key_spy", {&key_spy,NULL}, {KEYD_F12,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to view from another coop player's view + {"key_pause", {&key_pause,NULL}, {KEYD_PAUSE,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to pause the game + {"key_autorun", {&key_autorun,NULL}, {KEYD_CAPSLOCK,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to toggle always run mode + {"key_chat", {&key_chat,NULL}, {'t',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to enter a chat message + {"key_backspace", {&key_backspace,NULL}, {KEYD_BACKSPACE,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // backspace key + {"key_enter", {&key_enter,NULL}, {KEYD_ENTER,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to select from menu or see last message + {"key_map", {&key_map,NULL}, {KEYD_TAB,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to toggle automap display + {"key_map_right", {&key_map_right,NULL}, {KEYD_RIGHTARROW,NULL},// phares 3/7/98 + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to shift automap right // | + {"key_map_left", {&key_map_left,NULL}, {KEYD_LEFTARROW,NULL} ,// V + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to shift automap left + {"key_map_up", {&key_map_up,NULL}, {KEYD_UPARROW,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to shift automap up + {"key_map_down", {&key_map_down,NULL}, {KEYD_DOWNARROW,NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to shift automap down + {"key_map_zoomin", {&key_map_zoomin,NULL}, {'=',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to enlarge automap + {"key_map_zoomout", {&key_map_zoomout,NULL}, {'-',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to reduce automap + {"key_map_gobig", {&key_map_gobig,NULL}, {'0',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to get max zoom for automap + {"key_map_follow", {&key_map_follow,NULL}, {'f',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to toggle follow mode + {"key_map_mark", {&key_map_mark,NULL}, {'m',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to drop a marker on automap + {"key_map_clear", {&key_map_clear,NULL}, {'c',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to clear all markers on automap + {"key_map_grid", {&key_map_grid,NULL}, {'g',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to toggle grid display over automap + {"key_map_rotate", {&key_map_rotate,NULL}, {'r',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to toggle rotating the automap to match the player's orientation + {"key_map_overlay", {&key_map_overlay,NULL}, {'o',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to toggle overlaying the automap on the rendered display + {"key_reverse", {&key_reverse,NULL}, {'/',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to spin 180 instantly + {"key_zoomin", {&key_zoomin,NULL}, {'=',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to enlarge display + {"key_zoomout", {&key_zoomout,NULL}, {'-',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to reduce display + {"key_chatplayer1", {&destination_keys[0],NULL}, {'g',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to chat with player 1 // killough 11/98: fix 'i'/'b' reversal - {"key_chatplayer2", {&destination_keys[1]}, {'i'} , - 0,MAX_KEY,def_key,ss_keys}, // key to chat with player 2 - {"key_chatplayer3", {&destination_keys[2]}, {'b'} , - 0,MAX_KEY,def_key,ss_keys}, // key to chat with player 3 - {"key_chatplayer4", {&destination_keys[3]}, {'r'} , - 0,MAX_KEY,def_key,ss_keys}, // key to chat with player 4 - {"key_weapontoggle",{&key_weapontoggle}, {'0'} , - 0,MAX_KEY,def_key,ss_keys}, // key to toggle between two most preferred weapons with ammo - {"key_weapon1", {&key_weapon1}, {'1'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 1 (fist/chainsaw) - {"key_weapon2", {&key_weapon2}, {'2'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 2 (pistol) - {"key_weapon3", {&key_weapon3}, {'3'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 3 (supershotgun/shotgun) - {"key_weapon4", {&key_weapon4}, {'4'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 4 (chaingun) - {"key_weapon5", {&key_weapon5}, {'5'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 5 (rocket launcher) - {"key_weapon6", {&key_weapon6}, {'6'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 6 (plasma rifle) - {"key_weapon7", {&key_weapon7}, {'7'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 7 (bfg9000) // ^ - {"key_weapon8", {&key_weapon8}, {'8'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 8 (chainsaw) // | - {"key_weapon9", {&key_weapon9}, {'9'} , - 0,MAX_KEY,def_key,ss_keys}, // key to switch to weapon 9 (supershotgun) // phares + {"key_chatplayer2", {&destination_keys[1],NULL}, {'i',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to chat with player 2 + {"key_chatplayer3", {&destination_keys[2],NULL}, {'b',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to chat with player 3 + {"key_chatplayer4", {&destination_keys[3],NULL}, {'r',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to chat with player 4 + {"key_weapontoggle",{&key_weapontoggle,NULL}, {'0',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to toggle between two most preferred weapons with ammo + {"key_weapon1", {&key_weapon1,NULL}, {'1',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 1 (fist/chainsaw) + {"key_weapon2", {&key_weapon2,NULL}, {'2',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 2 (pistol) + {"key_weapon3", {&key_weapon3,NULL}, {'3',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 3 (supershotgun/shotgun) + {"key_weapon4", {&key_weapon4,NULL}, {'4',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 4 (chaingun) + {"key_weapon5", {&key_weapon5,NULL}, {'5',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 5 (rocket launcher) + {"key_weapon6", {&key_weapon6,NULL}, {'6',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 6 (plasma rifle) + {"key_weapon7", {&key_weapon7,NULL}, {'7',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 7 (bfg9000) // ^ + {"key_weapon8", {&key_weapon8,NULL}, {'8',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 8 (chainsaw) // | + {"key_weapon9", {&key_weapon9,NULL}, {'9',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to switch to weapon 9 (supershotgun) // phares // killough 2/22/98: screenshot key - {"key_screenshot", {&key_screenshot}, {'*'} , - 0,MAX_KEY,def_key,ss_keys}, // key to take a screenshot - - {"Joystick settings",{NULL},{0},UL,UL,def_none,ss_none}, - {"use_joystick",{&usejoystick},{0},0,2, - def_int,ss_none}, // number of joystick to use (0 for none) - {"joy_left",{&joyleft},{0}, UL,UL,def_int,ss_none}, - {"joy_right",{&joyright},{0},UL,UL,def_int,ss_none}, - {"joy_up", {&joyup}, {0}, UL,UL,def_int,ss_none}, - {"joy_down",{&joydown},{0}, UL,UL,def_int,ss_none}, - {"joyb_fire",{&joybfire},{0},0,UL, - def_int,ss_keys}, // joystick button number to use for fire - {"joyb_strafe",{&joybstrafe},{1},0,UL, - def_int,ss_keys}, // joystick button number to use for strafing - {"joyb_speed",{&joybspeed},{2},0,UL, - def_int,ss_keys}, // joystick button number to use for running - {"joyb_use",{&joybuse},{3},0,UL, - def_int,ss_keys}, // joystick button number to use for use/open - - {"Chat macros",{NULL},{0},UL,UL,def_none,ss_none}, + {"key_screenshot", {&key_screenshot,NULL}, {'*',NULL} , + 0,MAX_KEY,def_key,ss_keys,NULL,NULL}, // key to take a screenshot + + {"Joystick settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, + {"use_joystick",{&usejoystick,NULL},{0,NULL},0,2, + def_int,ss_none,NULL,NULL}, // number of joystick to use (0 for none) + {"joy_left",{&joyleft,NULL},{0,NULL}, UL,UL,def_int,ss_none,NULL,NULL}, + {"joy_right",{&joyright,NULL},{0,NULL},UL,UL,def_int,ss_none,NULL,NULL}, + {"joy_up", {&joyup,NULL}, {0,NULL}, UL,UL,def_int,ss_none,NULL,NULL}, + {"joy_down",{&joydown,NULL},{0,NULL}, UL,UL,def_int,ss_none,NULL,NULL}, + {"joyb_fire",{&joybfire,NULL},{0,NULL},0,UL, + def_int,ss_keys,NULL,NULL}, // joystick button number to use for fire + {"joyb_strafe",{&joybstrafe,NULL},{1,NULL},0,UL, + def_int,ss_keys,NULL,NULL}, // joystick button number to use for strafing + {"joyb_speed",{&joybspeed,NULL},{2,NULL},0,UL, + def_int,ss_keys,NULL,NULL}, // joystick button number to use for running + {"joyb_use",{&joybuse,NULL},{3,NULL},0,UL, + def_int,ss_keys,NULL,NULL}, // joystick button number to use for use/open + + {"Chat macros",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, {"chatmacro0", {0,&chat_macros[0]}, {0,HUSTR_CHATMACRO0},UL,UL, - def_str,ss_chat}, // chat string associated with 0 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 0 key {"chatmacro1", {0,&chat_macros[1]}, {0,HUSTR_CHATMACRO1},UL,UL, - def_str,ss_chat}, // chat string associated with 1 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 1 key {"chatmacro2", {0,&chat_macros[2]}, {0,HUSTR_CHATMACRO2},UL,UL, - def_str,ss_chat}, // chat string associated with 2 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 2 key {"chatmacro3", {0,&chat_macros[3]}, {0,HUSTR_CHATMACRO3},UL,UL, - def_str,ss_chat}, // chat string associated with 3 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 3 key {"chatmacro4", {0,&chat_macros[4]}, {0,HUSTR_CHATMACRO4},UL,UL, - def_str,ss_chat}, // chat string associated with 4 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 4 key {"chatmacro5", {0,&chat_macros[5]}, {0,HUSTR_CHATMACRO5},UL,UL, - def_str,ss_chat}, // chat string associated with 5 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 5 key {"chatmacro6", {0,&chat_macros[6]}, {0,HUSTR_CHATMACRO6},UL,UL, - def_str,ss_chat}, // chat string associated with 6 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 6 key {"chatmacro7", {0,&chat_macros[7]}, {0,HUSTR_CHATMACRO7},UL,UL, - def_str,ss_chat}, // chat string associated with 7 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 7 key {"chatmacro8", {0,&chat_macros[8]}, {0,HUSTR_CHATMACRO8},UL,UL, - def_str,ss_chat}, // chat string associated with 8 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 8 key {"chatmacro9", {0,&chat_macros[9]}, {0,HUSTR_CHATMACRO9},UL,UL, - def_str,ss_chat}, // chat string associated with 9 key + def_str,ss_chat,NULL,NULL}, // chat string associated with 9 key - {"Automap settings",{NULL},{0},UL,UL,def_none,ss_none}, + {"Automap settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, //jff 1/7/98 defaults for automap colors //jff 4/3/98 remove -1 in lower range, 0 now disables new map features - {"mapcolor_back", {&mapcolor_back}, {247},0,255, // black //jff 4/6/98 new black - def_colour,ss_auto}, // color used as background for automap - {"mapcolor_grid", {&mapcolor_grid}, {104},0,255, // dk gray - def_colour,ss_auto}, // color used for automap grid lines - {"mapcolor_wall", {&mapcolor_wall}, {23},0,255, // red-brown - def_colour,ss_auto}, // color used for one side walls on automap - {"mapcolor_fchg", {&mapcolor_fchg}, {55},0,255, // lt brown - def_colour,ss_auto}, // color used for lines floor height changes across - {"mapcolor_cchg", {&mapcolor_cchg}, {215},0,255, // orange - def_colour,ss_auto}, // color used for lines ceiling height changes across - {"mapcolor_clsd", {&mapcolor_clsd}, {208},0,255, // white - def_colour,ss_auto}, // color used for lines denoting closed doors, objects - {"mapcolor_rkey", {&mapcolor_rkey}, {175},0,255, // red - def_colour,ss_auto}, // color used for red key sprites - {"mapcolor_bkey", {&mapcolor_bkey}, {204},0,255, // blue - def_colour,ss_auto}, // color used for blue key sprites - {"mapcolor_ykey", {&mapcolor_ykey}, {231},0,255, // yellow - def_colour,ss_auto}, // color used for yellow key sprites - {"mapcolor_rdor", {&mapcolor_rdor}, {175},0,255, // red - def_colour,ss_auto}, // color used for closed red doors - {"mapcolor_bdor", {&mapcolor_bdor}, {204},0,255, // blue - def_colour,ss_auto}, // color used for closed blue doors - {"mapcolor_ydor", {&mapcolor_ydor}, {231},0,255, // yellow - def_colour,ss_auto}, // color used for closed yellow doors - {"mapcolor_tele", {&mapcolor_tele}, {119},0,255, // dk green - def_colour,ss_auto}, // color used for teleporter lines - {"mapcolor_secr", {&mapcolor_secr}, {252},0,255, // purple - def_colour,ss_auto}, // color used for lines around secret sectors - {"mapcolor_exit", {&mapcolor_exit}, {0},0,255, // none - def_colour,ss_auto}, // color used for exit lines - {"mapcolor_unsn", {&mapcolor_unsn}, {104},0,255, // dk gray - def_colour,ss_auto}, // color used for lines not seen without computer map - {"mapcolor_flat", {&mapcolor_flat}, {88},0,255, // lt gray - def_colour,ss_auto}, // color used for lines with no height changes - {"mapcolor_sprt", {&mapcolor_sprt}, {112},0,255, // green - def_colour,ss_auto}, // color used as things - {"mapcolor_item", {&mapcolor_item}, {231},0,255, // yellow - def_colour,ss_auto}, // color used for counted items - {"mapcolor_hair", {&mapcolor_hair}, {208},0,255, // white - def_colour,ss_auto}, // color used for dot crosshair denoting center of map - {"mapcolor_sngl", {&mapcolor_sngl}, {208},0,255, // white - def_colour,ss_auto}, // color used for the single player arrow - {"mapcolor_me", {&mapcolor_me}, {112},0,255, // green - def_colour,ss_auto}, // your (player) colour - {"mapcolor_enemy", {&mapcolor_enemy}, {177},0,255, - def_colour,ss_auto}, - {"mapcolor_frnd", {&mapcolor_frnd}, {112},0,255, - def_colour,ss_auto}, + {"mapcolor_back", {&mapcolor_back,NULL}, {247,NULL},0,255, // black //jff 4/6/98 new black + def_colour,ss_auto,NULL,NULL}, // color used as background for automap + {"mapcolor_grid", {&mapcolor_grid,NULL}, {104,NULL},0,255, // dk gray + def_colour,ss_auto,NULL,NULL}, // color used for automap grid lines + {"mapcolor_wall", {&mapcolor_wall,NULL}, {23,NULL},0,255, // red-brown + def_colour,ss_auto,NULL,NULL}, // color used for one side walls on automap + {"mapcolor_fchg", {&mapcolor_fchg,NULL}, {55,NULL},0,255, // lt brown + def_colour,ss_auto,NULL,NULL}, // color used for lines floor height changes across + {"mapcolor_cchg", {&mapcolor_cchg,NULL}, {215,NULL},0,255, // orange + def_colour,ss_auto,NULL,NULL}, // color used for lines ceiling height changes across + {"mapcolor_clsd", {&mapcolor_clsd,NULL}, {208,NULL},0,255, // white + def_colour,ss_auto,NULL,NULL}, // color used for lines denoting closed doors, objects + {"mapcolor_rkey", {&mapcolor_rkey,NULL}, {175,NULL},0,255, // red + def_colour,ss_auto,NULL,NULL}, // color used for red key sprites + {"mapcolor_bkey", {&mapcolor_bkey,NULL}, {204,NULL},0,255, // blue + def_colour,ss_auto,NULL,NULL}, // color used for blue key sprites + {"mapcolor_ykey", {&mapcolor_ykey,NULL}, {231,NULL},0,255, // yellow + def_colour,ss_auto,NULL,NULL}, // color used for yellow key sprites + {"mapcolor_rdor", {&mapcolor_rdor,NULL}, {175,NULL},0,255, // red + def_colour,ss_auto,NULL,NULL}, // color used for closed red doors + {"mapcolor_bdor", {&mapcolor_bdor,NULL}, {204,NULL},0,255, // blue + def_colour,ss_auto,NULL,NULL}, // color used for closed blue doors + {"mapcolor_ydor", {&mapcolor_ydor,NULL}, {231,NULL},0,255, // yellow + def_colour,ss_auto,NULL,NULL}, // color used for closed yellow doors + {"mapcolor_tele", {&mapcolor_tele,NULL}, {119,NULL},0,255, // dk green + def_colour,ss_auto,NULL,NULL}, // color used for teleporter lines + {"mapcolor_secr", {&mapcolor_secr,NULL}, {252,NULL},0,255, // purple + def_colour,ss_auto,NULL,NULL}, // color used for lines around secret sectors + {"mapcolor_exit", {&mapcolor_exit,NULL}, {0,NULL},0,255, // none + def_colour,ss_auto,NULL,NULL}, // color used for exit lines + {"mapcolor_unsn", {&mapcolor_unsn,NULL}, {104,NULL},0,255, // dk gray + def_colour,ss_auto,NULL,NULL}, // color used for lines not seen without computer map + {"mapcolor_flat", {&mapcolor_flat,NULL}, {88,NULL},0,255, // lt gray + def_colour,ss_auto,NULL,NULL}, // color used for lines with no height changes + {"mapcolor_sprt", {&mapcolor_sprt,NULL}, {112,NULL},0,255, // green + def_colour,ss_auto,NULL,NULL}, // color used as things + {"mapcolor_item", {&mapcolor_item,NULL}, {231,NULL},0,255, // yellow + def_colour,ss_auto,NULL,NULL}, // color used for counted items + {"mapcolor_hair", {&mapcolor_hair,NULL}, {208,NULL},0,255, // white + def_colour,ss_auto,NULL,NULL}, // color used for dot crosshair denoting center of map + {"mapcolor_sngl", {&mapcolor_sngl,NULL}, {208,NULL},0,255, // white + def_colour,ss_auto,NULL,NULL}, // color used for the single player arrow + {"mapcolor_me", {&mapcolor_me,NULL}, {112,NULL},0,255, // green + def_colour,ss_auto,NULL,NULL}, // your (player) colour + {"mapcolor_enemy", {&mapcolor_enemy,NULL}, {177,NULL},0,255, + def_colour,ss_auto,NULL,NULL}, + {"mapcolor_frnd", {&mapcolor_frnd,NULL}, {112,NULL},0,255, + def_colour,ss_auto,NULL,NULL}, //jff 3/9/98 add option to not show secrets til after found - {"map_secret_after", {&map_secret_after}, {0},0,1, // show secret after gotten - def_bool,ss_auto}, // prevents showing secret sectors till after entered - {"map_point_coord", {&map_point_coordinates}, {0},0,1, - def_bool,ss_auto}, + {"map_secret_after", {&map_secret_after,NULL}, {0,NULL},0,1, // show secret after gotten + def_bool,ss_auto,NULL,NULL}, // prevents showing secret sectors till after entered + {"map_point_coord", {&map_point_coordinates,NULL}, {0,NULL},0,1, + def_bool,ss_auto,NULL,NULL}, //jff 1/7/98 end additions for automap - {"automapmode", {(int*)&automapmode}, {0}, 0, 31, // CPhipps - remember automap mode - def_hex,ss_none}, // automap mode + {"automapmode", {(int*)&automapmode,NULL}, {0,NULL}, 0, 31, // CPhipps - remember automap mode + def_hex,ss_none,NULL,NULL}, // automap mode - {"Heads-up display settings",{NULL},{0},UL,UL,def_none,ss_none}, + {"Heads-up display settings",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, //jff 2/16/98 defaults for color ranges in hud and status - {"hudcolor_titl", {&hudcolor_titl}, {5},0,9, // gold range - def_int,ss_auto}, // color range used for automap level title - {"hudcolor_xyco", {&hudcolor_xyco}, {3},0,9, // green range - def_int,ss_auto}, // color range used for automap coordinates - {"hudcolor_mesg", {&hudcolor_mesg}, {6},0,9, // red range - def_int,ss_mess}, // color range used for messages during play - {"hudcolor_chat", {&hudcolor_chat}, {5},0,9, // gold range - def_int,ss_mess}, // color range used for chat messages and entry - {"hudcolor_list", {&hudcolor_list}, {5},0,9, // gold range //jff 2/26/98 - def_int,ss_mess}, // color range used for message review - {"hud_msg_lines", {&hud_msg_lines}, {1},1,16, // 1 line scrolling window - def_int,ss_mess}, // number of messages in review display (1=disable) - {"hud_list_bgon", {&hud_list_bgon}, {0},0,1, // solid window bg ena //jff 2/26/98 - def_bool,ss_mess}, // enables background window behind message review - {"hud_distributed",{&hud_distributed},{0},0,1, // hud broken up into 3 displays //jff 3/4/98 - def_bool,ss_none}, // splits HUD into three 2 line displays - - {"health_red", {&health_red} , {25},0,200, // below is red - def_int,ss_stat}, // amount of health for red to yellow transition - {"health_yellow", {&health_yellow}, {50},0,200, // below is yellow - def_int,ss_stat}, // amount of health for yellow to green transition - {"health_green", {&health_green} , {100},0,200,// below is green, above blue - def_int,ss_stat}, // amount of health for green to blue transition - {"armor_red", {&armor_red} , {25},0,200, // below is red - def_int,ss_stat}, // amount of armor for red to yellow transition - {"armor_yellow", {&armor_yellow} , {50},0,200, // below is yellow - def_int,ss_stat}, // amount of armor for yellow to green transition - {"armor_green", {&armor_green} , {100},0,200,// below is green, above blue - def_int,ss_stat}, // amount of armor for green to blue transition - {"ammo_red", {&ammo_red} , {25},0,100, // below 25% is red - def_int,ss_stat}, // percent of ammo for red to yellow transition - {"ammo_yellow", {&ammo_yellow} , {50},0,100, // below 50% is yellow, above green - def_int,ss_stat}, // percent of ammo for yellow to green transition + {"hudcolor_titl", {&hudcolor_titl,NULL}, {5,NULL},0,9, // gold range + def_int,ss_auto,NULL,NULL}, // color range used for automap level title + {"hudcolor_xyco", {&hudcolor_xyco,NULL}, {3,NULL},0,9, // green range + def_int,ss_auto,NULL,NULL}, // color range used for automap coordinates + {"hudcolor_mesg", {&hudcolor_mesg,NULL}, {6,NULL},0,9, // red range + def_int,ss_mess,NULL,NULL}, // color range used for messages during play + {"hudcolor_chat", {&hudcolor_chat,NULL}, {5,NULL},0,9, // gold range + def_int,ss_mess,NULL,NULL}, // color range used for chat messages and entry + {"hudcolor_list", {&hudcolor_list,NULL}, {5,NULL},0,9, // gold range //jff 2/26/98 + def_int,ss_mess,NULL,NULL}, // color range used for message review + {"hud_msg_lines", {&hud_msg_lines,NULL}, {1,NULL},1,16, // 1 line scrolling window + def_int,ss_mess,NULL,NULL}, // number of messages in review display (1=disable) + {"hud_list_bgon", {&hud_list_bgon,NULL}, {0,NULL},0,1, // solid window bg ena //jff 2/26/98 + def_bool,ss_mess,NULL,NULL}, // enables background window behind message review + {"hud_distributed",{&hud_distributed,NULL},{0,NULL},0,1, // hud broken up into 3 displays //jff 3/4/98 + def_bool,ss_none,NULL,NULL}, // splits HUD into three 2 line displays + + {"health_red", {&health_red,NULL} , {25,NULL},0,200, // below is red + def_int,ss_stat,NULL,NULL}, // amount of health for red to yellow transition + {"health_yellow", {&health_yellow,NULL}, {50,NULL},0,200, // below is yellow + def_int,ss_stat,NULL,NULL}, // amount of health for yellow to green transition + {"health_green", {&health_green,NULL} , {100,NULL},0,200,// below is green, above blue + def_int,ss_stat,NULL,NULL}, // amount of health for green to blue transition + {"armor_red", {&armor_red,NULL} , {25,NULL},0,200, // below is red + def_int,ss_stat,NULL,NULL}, // amount of armor for red to yellow transition + {"armor_yellow", {&armor_yellow,NULL} , {50,NULL},0,200, // below is yellow + def_int,ss_stat,NULL,NULL}, // amount of armor for yellow to green transition + {"armor_green", {&armor_green,NULL} , {100,NULL},0,200,// below is green, above blue + def_int,ss_stat,NULL,NULL}, // amount of armor for green to blue transition + {"ammo_red", {&ammo_red,NULL} , {25,NULL},0,100, // below 25% is red + def_int,ss_stat,NULL,NULL}, // percent of ammo for red to yellow transition + {"ammo_yellow", {&ammo_yellow,NULL} , {50,NULL},0,100, // below 50% is yellow, above green + def_int,ss_stat,NULL,NULL}, // percent of ammo for yellow to green transition //jff 2/16/98 HUD and status feature controls - {"hud_active", {&hud_active}, {2},0,2, // 0=off, 1=small, 2=full - def_int,ss_none}, // 0 for HUD off, 1 for HUD small, 2 for full HUD + {"hud_active", {&hud_active,NULL}, {2,NULL},0,2, // 0=off, 1=small, 2=full + def_int,ss_none,NULL,NULL}, // 0 for HUD off, 1 for HUD small, 2 for full HUD //jff 2/23/98 - {"hud_displayed", {&hud_displayed}, {0},0,1, // whether hud is displayed - def_bool,ss_none}, // enables display of HUD - {"hud_nosecrets", {&hud_nosecrets}, {0},0,1, // no secrets/items/kills HUD line - def_bool,ss_stat}, // disables display of kills/items/secrets on HUD + {"hud_displayed", {&hud_displayed,NULL}, {0,NULL},0,1, // whether hud is displayed + def_bool,ss_none,NULL,NULL}, // enables display of HUD + {"hud_nosecrets", {&hud_nosecrets,NULL}, {0,NULL},0,1, // no secrets/items/kills HUD line + def_bool,ss_stat,NULL,NULL}, // disables display of kills/items/secrets on HUD - {"Weapon preferences",{NULL},{0},UL,UL,def_none,ss_none}, + {"Weapon preferences",{NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, // killough 2/8/98: weapon preferences set by user: - {"weapon_choice_1", {&weapon_preferences[0][0]}, {6}, 0,9, - def_int,ss_weap}, // first choice for weapon (best) - {"weapon_choice_2", {&weapon_preferences[0][1]}, {9}, 0,9, - def_int,ss_weap}, // second choice for weapon - {"weapon_choice_3", {&weapon_preferences[0][2]}, {4}, 0,9, - def_int,ss_weap}, // third choice for weapon - {"weapon_choice_4", {&weapon_preferences[0][3]}, {3}, 0,9, - def_int,ss_weap}, // fourth choice for weapon - {"weapon_choice_5", {&weapon_preferences[0][4]}, {2}, 0,9, - def_int,ss_weap}, // fifth choice for weapon - {"weapon_choice_6", {&weapon_preferences[0][5]}, {8}, 0,9, - def_int,ss_weap}, // sixth choice for weapon - {"weapon_choice_7", {&weapon_preferences[0][6]}, {5}, 0,9, - def_int,ss_weap}, // seventh choice for weapon - {"weapon_choice_8", {&weapon_preferences[0][7]}, {7}, 0,9, - def_int,ss_weap}, // eighth choice for weapon - {"weapon_choice_9", {&weapon_preferences[0][8]}, {1}, 0,9, - def_int,ss_weap}, // ninth choice for weapon (worst) + {"weapon_choice_1", {&weapon_preferences[0][0],NULL}, {6,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // first choice for weapon (best) + {"weapon_choice_2", {&weapon_preferences[0][1],NULL}, {9,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // second choice for weapon + {"weapon_choice_3", {&weapon_preferences[0][2],NULL}, {4,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // third choice for weapon + {"weapon_choice_4", {&weapon_preferences[0][3],NULL}, {3,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // fourth choice for weapon + {"weapon_choice_5", {&weapon_preferences[0][4],NULL}, {2,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // fifth choice for weapon + {"weapon_choice_6", {&weapon_preferences[0][5],NULL}, {8,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // sixth choice for weapon + {"weapon_choice_7", {&weapon_preferences[0][6],NULL}, {5,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // seventh choice for weapon + {"weapon_choice_8", {&weapon_preferences[0][7],NULL}, {7,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // eighth choice for weapon + {"weapon_choice_9", {&weapon_preferences[0][8],NULL}, {1,NULL}, 0,9, + def_int,ss_weap,NULL,NULL}, // ninth choice for weapon (worst) // cournia - support for arbitrary music file (defaults are mp3) - {"Music", {NULL},{0},UL,UL,def_none,ss_none}, + {"Music", {NULL,NULL},{0,NULL},UL,UL,def_none,ss_none,NULL,NULL}, {"mus_e1m1", {0,&S_music_files[mus_e1m1]}, {0,"e1m1.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e1m2", {0,&S_music_files[mus_e1m2]}, {0,"e1m2.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e1m3", {0,&S_music_files[mus_e1m3]}, {0,"e1m3.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e1m4", {0,&S_music_files[mus_e1m4]}, {0,"e1m4.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e1m5", {0,&S_music_files[mus_e1m5]}, {0,"e1m5.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e1m6", {0,&S_music_files[mus_e1m6]}, {0,"e1m6.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e1m7", {0,&S_music_files[mus_e1m7]}, {0,"e1m7.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e1m8", {0,&S_music_files[mus_e1m8]}, {0,"e1m8.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e1m9", {0,&S_music_files[mus_e1m9]}, {0,"e1m9.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m1", {0,&S_music_files[mus_e2m1]}, {0,"e2m1.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m2", {0,&S_music_files[mus_e2m2]}, {0,"e2m2.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m3", {0,&S_music_files[mus_e2m3]}, {0,"e2m3.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m4", {0,&S_music_files[mus_e2m4]}, {0,"e2m4.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m5", {0,&S_music_files[mus_e2m5]}, {0,"e1m7.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m6", {0,&S_music_files[mus_e2m6]}, {0,"e2m6.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m7", {0,&S_music_files[mus_e2m7]}, {0,"e2m7.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m8", {0,&S_music_files[mus_e2m8]}, {0,"e2m8.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e2m9", {0,&S_music_files[mus_e2m9]}, {0,"e3m1.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m1", {0,&S_music_files[mus_e3m1]}, {0,"e3m1.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m2", {0,&S_music_files[mus_e3m2]}, {0,"e3m2.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m3", {0,&S_music_files[mus_e3m3]}, {0,"e3m3.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m4", {0,&S_music_files[mus_e3m4]}, {0,"e1m8.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m5", {0,&S_music_files[mus_e3m5]}, {0,"e1m7.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m6", {0,&S_music_files[mus_e3m6]}, {0,"e1m6.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m7", {0,&S_music_files[mus_e3m7]}, {0,"e2m7.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m8", {0,&S_music_files[mus_e3m8]}, {0,"e3m8.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_e3m9", {0,&S_music_files[mus_e3m9]}, {0,"e1m9.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_inter", {0,&S_music_files[mus_inter]}, {0,"e2m3.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_intro", {0,&S_music_files[mus_intro]}, {0,"intro.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_bunny", {0,&S_music_files[mus_bunny]}, {0,"bunny.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_victor", {0,&S_music_files[mus_victor]}, {0,"victor.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_introa", {0,&S_music_files[mus_introa]}, {0,"intro.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_runnin", {0,&S_music_files[mus_runnin]}, {0,"runnin.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_stalks", {0,&S_music_files[mus_stalks]}, {0,"stalks.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_countd", {0,&S_music_files[mus_countd]}, {0,"countd.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_betwee", {0,&S_music_files[mus_betwee]}, {0,"betwee.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_doom", {0,&S_music_files[mus_doom]}, {0,"doom.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_the_da", {0,&S_music_files[mus_the_da]}, {0,"the_da.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_shawn", {0,&S_music_files[mus_shawn]}, {0,"shawn.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_ddtblu", {0,&S_music_files[mus_ddtblu]}, {0,"ddtblu.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_in_cit", {0,&S_music_files[mus_in_cit]}, {0,"in_cit.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_dead", {0,&S_music_files[mus_dead]}, {0,"dead.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_stlks2", {0,&S_music_files[mus_stlks2]}, {0,"stalks.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_theda2", {0,&S_music_files[mus_theda2]}, {0,"the_da.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_doom2", {0,&S_music_files[mus_doom2]}, {0,"doom.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_ddtbl2", {0,&S_music_files[mus_ddtbl2]}, {0,"ddtblu.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_runni2", {0,&S_music_files[mus_runni2]}, {0,"runnin.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_dead2", {0,&S_music_files[mus_dead2]}, {0,"dead.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_stlks3", {0,&S_music_files[mus_stlks3]}, {0,"stalks.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_romero", {0,&S_music_files[mus_romero]}, {0,"romero.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_shawn2", {0,&S_music_files[mus_shawn2]}, {0,"shawn.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_messag", {0,&S_music_files[mus_messag]}, {0,"messag.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_count2", {0,&S_music_files[mus_count2]}, {0,"countd.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_ddtbl3", {0,&S_music_files[mus_ddtbl3]}, {0,"ddtblu.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_ampie", {0,&S_music_files[mus_ampie]}, {0,"ampie.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_theda3", {0,&S_music_files[mus_theda3]}, {0,"the_da.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_adrian", {0,&S_music_files[mus_adrian]}, {0,"adrian.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_messg2", {0,&S_music_files[mus_messg2]}, {0,"messag.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_romer2", {0,&S_music_files[mus_romer2]}, {0,"romero.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_tense", {0,&S_music_files[mus_tense]}, {0,"tense.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_shawn3", {0,&S_music_files[mus_shawn3]}, {0,"shawn.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_openin", {0,&S_music_files[mus_openin]}, {0,"openin.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_evil", {0,&S_music_files[mus_evil]}, {0,"evil.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_ultima", {0,&S_music_files[mus_ultima]}, {0,"ultima.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_read_m", {0,&S_music_files[mus_read_m]}, {0,"read_m.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, {"mus_dm2ttl", {0,&S_music_files[mus_dm2ttl]}, {0,"dm2ttl.mp3"},UL,UL, - def_str,ss_none}, - {"mus_dm2int", {0,&S_music_files[mus_dm2int]}, {0,"dm2int.mp3"},UL,UL, - def_str,ss_none}, + def_str,ss_none,NULL,NULL}, + {"mus_dm2int", {0,&S_music_files[mus_dm2int]}, {0,"dm2int.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m1", {0,&S_music_files[mus_e5m1]}, {0,"e5m1.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m2", {0,&S_music_files[mus_e5m2]}, {0,"e5m2.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m3", {0,&S_music_files[mus_e5m3]}, {0,"e5m3.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m4", {0,&S_music_files[mus_e5m4]}, {0,"e5m4.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m5", {0,&S_music_files[mus_e5m5]}, {0,"e5m5.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m6", {0,&S_music_files[mus_e5m6]}, {0,"e5m6.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m7", {0,&S_music_files[mus_e5m7]}, {0,"e5m7.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m8", {0,&S_music_files[mus_e5m8]}, {0,"e5m8.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, + {"mus_e5m9", {0,&S_music_files[mus_e5m9]}, {0,"e5m9.mp3"},UL,UL, + def_str,ss_none,NULL,NULL}, }; int numdefaults; @@ -900,7 +919,7 @@ void M_SaveDefaults (void) struct default_s *M_LookupDefault(const char *name) { int i; - for (i = 0 ; i < numdefaults ; i++) + for (i = 0 ; i < numdefaults - 1 ; i++) if ((defaults[i].type != def_none) && !strcmp(name, defaults[i].name)) return &defaults[i]; I_Error("M_LookupDefault: %s not found",name); @@ -943,16 +962,18 @@ void M_LoadDefaults (void) const char* exedir = I_DoomExeDir(); defaultfile = malloc(PATH_MAX+1); /* get config file from same directory as executable */ +#if ((defined GL_DOOM) && (defined _MSC_VER)) + #define PRBOOM_GL_OR_PR "gl" +#else + #define PRBOOM_GL_OR_PR "pr" +#endif + #ifdef HAVE_SNPRINTF snprintf((char *)defaultfile, PATH_MAX, + "%s%s%sboom.cfg", exedir, HasTrailingSlash(exedir) ? "" : "/", PRBOOM_GL_OR_PR ); #else sprintf ((char *)defaultfile, -#endif - "%s%s%sboom.cfg", exedir, HasTrailingSlash(exedir) ? "" : "/", -#if ((defined GL_DOOM) && (defined _MSC_VER)) - "gl"); -#else - "pr"); + "%s%s%sboom.cfg", exedir, HasTrailingSlash(exedir) ? "" : "/", PRBOOM_GL_OR_PR ); #endif } @@ -966,7 +987,7 @@ void M_LoadDefaults (void) while (!feof(f)) { isstring = false; - if (fscanf (f, "%79s %[^\n]\n", def, strparm) == 2) + if (fscanf (f, "%79s %99[^\n]\n", def, strparm) == 2) { //jff 3/3/98 skip lines not starting with an alphanum @@ -978,7 +999,7 @@ void M_LoadDefaults (void) // get a string default isstring = true; - len = strlen(strparm); + len = (int)strlen(strparm); newstring = (char *) malloc(len); strparm[len-1] = 0; // clears trailing double-quote mark strcpy(newstring, strparm+1); // clears leading double-quote mark diff --git a/code/prboom/m_swap.h b/code/prboom/m_swap.h old mode 100644 new mode 100755 index df86460..6a87c23 --- a/code/prboom/m_swap.h +++ b/code/prboom/m_swap.h @@ -35,9 +35,6 @@ #ifndef __M_SWAP__ #define __M_SWAP__ -#ifdef __GNUG__ -#pragma interface -#endif /* CPhipps - now the endianness handling, converting input or output to/from * the machine's endianness to that wanted for this type of I/O diff --git a/code/prboom/md5.c b/code/prboom/md5.c old mode 100644 new mode 100755 index d69ec0c..6d51e05 --- a/code/prboom/md5.c +++ b/code/prboom/md5.c @@ -131,7 +131,7 @@ MD5Final(md5byte digest[16], struct MD5Context *ctx) byteSwap(ctx->buf, 4); memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ + memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } #ifndef ASM_MD5 diff --git a/code/prboom/mmus2mid.c b/code/prboom/mmus2mid.c old mode 100644 new mode 100755 index 3669c36..16b2ed1 --- a/code/prboom/mmus2mid.c +++ b/code/prboom/mmus2mid.c @@ -620,7 +620,7 @@ int MidiToMIDI(UBYTE *mid,MIDI *mididata) } } mid += 4; - mididata->track[i].len = ReadLength(&mid); // get length, move mid past it + mididata->track[i].len = (int)ReadLength(&mid); // get length, move mid past it // read a track mididata->track[i].data = realloc(mididata->track[i].data,mididata->track[i].len); @@ -641,28 +641,9 @@ int MidiToMIDI(UBYTE *mid,MIDI *mididata) // /* it also provides a MUS to MID file converter*/ // proff: I moved this down, because I need MIDItoMidi -static void FreeTracks(MIDI *mididata); static void TWriteLength(UBYTE **midiptr,ULONG length); -// -// FreeTracks() -// -// Free all track allocations in the MIDI structure -// -// Passed a pointer to an Allegro MIDI structure -// Returns nothing -// -static void FreeTracks(MIDI *mididata) -{ - int i; - for (i=0; itrack[i].data); - mididata->track[i].data = NULL; - mididata->track[i].len = 0; - } -} // // TWriteLength() @@ -742,7 +723,7 @@ int MIDIToMidi(MIDI *mididata,UBYTE **mid,int *midlen) // return length information - *midlen = midiptr - *mid; + *midlen = (int)(midiptr - *mid); return 0; } diff --git a/code/prboom/p_checksum.c b/code/prboom/p_checksum.c old mode 100644 new mode 100755 index 5fb6101..db1e48a --- a/code/prboom/p_checksum.c +++ b/code/prboom/p_checksum.c @@ -88,7 +88,7 @@ void checksum_gamestate(int tic) { #endif buffer[sizeof(buffer)-1] = 0; - MD5Update(&md5ctx, (md5byte const *)&buffer, strlen(buffer)); + MD5Update(&md5ctx, (md5byte const *)&buffer, (unsigned)strlen(buffer)); } MD5Final(digest, &md5ctx); for (i=0; i<16; i++) { diff --git a/code/prboom/p_doors.c b/code/prboom/p_doors.c old mode 100644 new mode 100755 index ba9561c..2f42511 --- a/code/prboom/p_doors.c +++ b/code/prboom/p_doors.c @@ -158,7 +158,7 @@ void T_VerticalDoor (vldoor_t* door) break; case normal: - case close: + case closeDoor: case genRaise: case genClose: door->sector->ceilingdata = NULL; //jff 2/22/98 @@ -195,7 +195,7 @@ void T_VerticalDoor (vldoor_t* door) case genClose: case genBlazeClose: case blazeClose: - case close: // Close types do not bounce, merely wait + case closeDoor: // Close types do not bounce, merely wait break; case blazeRaise: @@ -252,7 +252,7 @@ void T_VerticalDoor (vldoor_t* door) case close30ThenOpen: // close and close/open doors are done case blazeOpen: - case open: + case openDoor: case genBlazeOpen: case genOpen: case genCdO: @@ -395,7 +395,7 @@ int EV_DoDoor S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls); break; - case close: + case closeDoor: door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; door->direction = -1; @@ -419,7 +419,7 @@ int EV_DoDoor break; case normal: - case open: + case openDoor: door->direction = 1; door->topheight = P_FindLowestCeilingSurrounding(sec); door->topheight -= 4*FRACUNIT; @@ -508,7 +508,7 @@ int EV_VerticalDoor // get the sector on the second side of activating linedef sec = sides[line->sidenum[1]].sector; - secnum = sec-sectors; + secnum = (int)(sec-sectors); /* if door already has a thinker, use it * cph 2001/04/05 - @@ -613,7 +613,7 @@ int EV_VerticalDoor case 32: case 33: case 34: - door->type = open; + door->type = openDoor; line->special = 0; break; diff --git a/code/prboom/p_enemy.c b/code/prboom/p_enemy.c old mode 100644 new mode 100755 index 937321e..8cb0737 --- a/code/prboom/p_enemy.c +++ b/code/prboom/p_enemy.c @@ -153,11 +153,11 @@ static boolean P_CheckMeleeRange(mobj_t *actor) static boolean P_HitFriend(mobj_t *actor) { return actor->flags & MF_FRIEND && actor->target && - (P_AimLineAttack(actor, - R_PointToAngle2(actor->x, actor->y, - actor->target->x, actor->target->y), - P_AproxDistance(actor->x-actor->target->x, - actor->y-actor->target->y), 0), + ((void)(P_AimLineAttack(actor, + R_PointToAngle2(actor->x, actor->y, + actor->target->x, actor->target->y), + P_AproxDistance(actor->x-actor->target->x, + actor->y-actor->target->y), 0)), linetarget) && linetarget != actor->target && !((linetarget->flags ^ actor->flags) & MF_FRIEND); } @@ -527,30 +527,31 @@ static void P_DoNewChaseDir(mobj_t *actor, fixed_t deltax, fixed_t deltay) // try other directions if (P_Random(pr_newchase) > 200 || D_abs(deltay)>D_abs(deltax)) - tdir = xdir, xdir = ydir, ydir = tdir; + (void)(tdir = xdir), (void)(xdir = ydir), ydir = tdir; if ((xdir == turnaround ? xdir = DI_NODIR : xdir) != DI_NODIR && - (actor->movedir = xdir, P_TryWalk(actor))) + ((void)(actor->movedir = xdir), P_TryWalk(actor))) return; // either moved forward or attacked if ((ydir == turnaround ? ydir = DI_NODIR : ydir) != DI_NODIR && - (actor->movedir = ydir, P_TryWalk(actor))) + ((void)(actor->movedir = ydir), P_TryWalk(actor))) return; // there is no direct path to the player, so pick another direction. - if (olddir != DI_NODIR && (actor->movedir = olddir, P_TryWalk(actor))) + if (olddir != DI_NODIR && ((void)(actor->movedir = olddir), P_TryWalk(actor))) return; // randomly determine direction of search + // suppressing this warning in the compiler with a -w flag as I think it can't be helped -tkidd if (P_Random(pr_newchasedir) & 1) { for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) - if (tdir != turnaround && (actor->movedir = tdir, P_TryWalk(actor))) + if (tdir != turnaround && ((void)(actor->movedir = tdir), P_TryWalk(actor))) return; } else for (tdir = DI_SOUTHEAST; tdir != DI_EAST-1; tdir--) - if (tdir != turnaround && (actor->movedir = tdir, P_TryWalk(actor))) + if (tdir != turnaround && ((void)(actor->movedir = tdir), P_TryWalk(actor))) return; if ((actor->movedir = turnaround) != DI_NODIR && !P_TryWalk(actor)) @@ -673,7 +674,7 @@ static void P_NewChaseDir(mobj_t *actor) distfriend << FRACBITS > dist && !P_IsOnLift(target) && !P_IsUnderDamage(actor)) { - deltax = -deltax, deltay = -deltay; + (void)(deltax = -deltax), deltay = -deltay; } else if (target->health > 0 && (actor->flags ^ target->flags) & MF_FRIEND) { // Live enemy target @@ -685,7 +686,7 @@ static void P_NewChaseDir(mobj_t *actor) target->player->readyweapon == wp_chainsaw)))) { // Back away from melee attacker actor->strafecount = P_Random(pr_enemystrafe) & 15; - deltax = -deltax, deltay = -deltay; + (void)(deltax = -deltax), deltay = -deltay; } } } @@ -1026,7 +1027,7 @@ void A_KeenDie(mobj_t* mo) } junk.tag = 666; - EV_DoDoor(&junk,open); + EV_DoDoor(&junk,openDoor); } @@ -1054,7 +1055,7 @@ void A_Look(mobj_t *actor) if (!(actor->flags & MF_FRIEND && P_LookForTargets(actor, false)) && !((targ = actor->subsector->sector->soundtarget) && targ->flags & MF_SHOOTABLE && - (P_SetTarget(&actor->target, targ), + ((void)(P_SetTarget(&actor->target, targ)), !(actor->flags & MF_AMBUSH) || P_CheckSight(actor, targ))) && (actor->flags & MF_FRIEND || !P_LookForTargets(actor, false))) return; @@ -1089,23 +1090,6 @@ void A_Look(mobj_t *actor) P_SetMobjState(actor, actor->info->seestate); } -// -// A_KeepChasing -// -// killough 10/98: -// Allows monsters to continue movement while attacking -// - -static void A_KeepChasing(mobj_t *actor) -{ - if (actor->movecount) - { - actor->movecount--; - if (actor->strafecount) - actor->strafecount--; - P_SmartMove(actor); - } -} // // A_Chase @@ -2541,8 +2525,8 @@ void A_Spawn(mobj_t *mo) if (mo->state->misc1) { /* mobj_t *newmobj = */ - P_SpawnMobj(mo->x, mo->y, (mo->state->misc2 << FRACBITS) + mo->z, - mo->state->misc1 - 1); + P_SpawnMobj(mo->x, mo->y, (int)(mo->state->misc2 << FRACBITS) + mo->z, + (int)mo->state->misc1 - 1); /* CPhipps - no friendlyness (yet) newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (mo->flags & MF_FRIEND); */ @@ -2561,20 +2545,20 @@ void A_Face(mobj_t *mo) void A_Scratch(mobj_t *mo) { - mo->target && (A_FaceTarget(mo), P_CheckMeleeRange(mo)) ? - mo->state->misc2 ? S_StartSound(mo, mo->state->misc2) : (void) 0, - P_DamageMobj(mo->target, mo, mo, mo->state->misc1) : (void) 0; + mo->target && ((void)(A_FaceTarget(mo)), P_CheckMeleeRange(mo)) ? + (void)(mo->state->misc2 ? S_StartSound(mo, (int)mo->state->misc2) : (void) 0), + P_DamageMobj(mo->target, mo, mo, (int)mo->state->misc1) : (void) 0; } void A_PlaySound(mobj_t *mo) { - S_StartSound(mo->state->misc2 ? NULL : mo, mo->state->misc1); + S_StartSound(mo->state->misc2 ? NULL : mo, (int)mo->state->misc1); } void A_RandomJump(mobj_t *mo) { if (P_Random(pr_randomjump) < mo->state->misc2) - P_SetMobjState(mo, mo->state->misc1); + P_SetMobjState(mo, (int)mo->state->misc1); } // diff --git a/code/prboom/p_enemy.h b/code/prboom/p_enemy.h old mode 100644 new mode 100755 index 3c85861..5cae6f9 --- a/code/prboom/p_enemy.h +++ b/code/prboom/p_enemy.h @@ -53,66 +53,66 @@ extern struct brain_s { /* killough 3/26/98: global state of boss brain // allows more extensive changes (see d_deh.c) // Doesn't work with g++, needs actionf_p1 -void A_Explode(); -void A_Pain(); -void A_PlayerScream(); -void A_Fall(); -void A_XScream(); -void A_Look(); -void A_Chase(); -void A_FaceTarget(); -void A_PosAttack(); -void A_Scream(); -void A_SPosAttack(); -void A_VileChase(); -void A_VileStart(); -void A_VileTarget(); -void A_VileAttack(); -void A_StartFire(); -void A_Fire(); -void A_FireCrackle(); -void A_Tracer(); -void A_SkelWhoosh(); -void A_SkelFist(); -void A_SkelMissile(); -void A_FatRaise(); -void A_FatAttack1(); -void A_FatAttack2(); -void A_FatAttack3(); -void A_BossDeath(); -void A_CPosAttack(); -void A_CPosRefire(); -void A_TroopAttack(); -void A_SargAttack(); -void A_HeadAttack(); -void A_BruisAttack(); -void A_SkullAttack(); -void A_Metal(); -void A_SpidRefire(); -void A_BabyMetal(); -void A_BspiAttack(); -void A_Hoof(); -void A_CyberAttack(); -void A_PainAttack(); -void A_PainDie(); -void A_KeenDie(); -void A_BrainPain(); -void A_BrainScream(); -void A_BrainDie(); -void A_BrainAwake(); -void A_BrainSpit(); -void A_SpawnSound(); -void A_SpawnFly(); -void A_BrainExplode(); -void A_Die(); -void A_Detonate(); /* killough 8/9/98: detonate a bomb or other device */ -void A_Mushroom(); /* killough 10/98: mushroom effect */ -void A_Spawn(); // killough 11/98 -void A_Turn(); // killough 11/98 -void A_Face(); // killough 11/98 -void A_Scratch(); // killough 11/98 -void A_PlaySound(); // killough 11/98 -void A_RandomJump(); // killough 11/98 -void A_LineEffect(); // killough 11/98 +void A_Explode(mobj_t *thingy); +void A_Pain(mobj_t *actor); +void A_PlayerScream(mobj_t *mo); +void A_Fall(mobj_t *actor); +void A_XScream(mobj_t *actor); +void A_Look(mobj_t *actor); +void A_Chase(mobj_t *actor); +void A_FaceTarget(mobj_t *actor); +void A_PosAttack(mobj_t *actor); +void A_Scream(mobj_t *actor); +void A_SPosAttack(mobj_t *actor); +void A_VileChase(mobj_t *actor); +void A_VileStart(mobj_t *actor); +void A_VileTarget(mobj_t *actor); +void A_VileAttack(mobj_t *actor); +void A_StartFire(mobj_t *actor); +void A_Fire(mobj_t *actor); +void A_FireCrackle(mobj_t *actor); +void A_Tracer(mobj_t *actor); +void A_SkelWhoosh(mobj_t *actor); +void A_SkelFist(mobj_t *actor); +void A_SkelMissile(mobj_t *actor); +void A_FatRaise(mobj_t *actor); +void A_FatAttack1(mobj_t *actor); +void A_FatAttack2(mobj_t *actor); +void A_FatAttack3(mobj_t *actor); +void A_BossDeath(mobj_t *mo); +void A_CPosAttack(mobj_t *actor); +void A_CPosRefire(mobj_t *actor); +void A_TroopAttack(mobj_t *actor); +void A_SargAttack(mobj_t *actor); +void A_HeadAttack(mobj_t *actor); +void A_BruisAttack(mobj_t *actor); +void A_SkullAttack(mobj_t *actor); +void A_Metal(mobj_t *mo); +void A_SpidRefire(mobj_t *actor); +void A_BabyMetal(mobj_t *mo); +void A_BspiAttack(mobj_t *actor); +void A_Hoof(mobj_t *mo); +void A_CyberAttack(mobj_t *actor); +void A_PainAttack(mobj_t *actor); +void A_PainDie(mobj_t *actor); +void A_KeenDie(mobj_t *mo); +void A_BrainPain(mobj_t *mo); +void A_BrainScream(mobj_t *mo); +void A_BrainDie(mobj_t *mo); +void A_BrainAwake(mobj_t *mo); +void A_BrainSpit(mobj_t *mo); +void A_SpawnSound(mobj_t *mo); +void A_SpawnFly(mobj_t *mo); +void A_BrainExplode(mobj_t *mo); +void A_Die(mobj_t *actor); +void A_Detonate(mobj_t *mo); /* killough 8/9/98: detonate a bomb or other device */ +void A_Mushroom(mobj_t *actor); /* killough 10/98: mushroom effect */ +void A_Spawn(mobj_t *mo); // killough 11/98 +void A_Turn(mobj_t *mo); // killough 11/98 +void A_Face(mobj_t *mo); // killough 11/98 +void A_Scratch(mobj_t *mo); // killough 11/98 +void A_PlaySound(mobj_t *mo); // killough 11/98 +void A_RandomJump(mobj_t *mo); // killough 11/98 +void A_LineEffect(mobj_t *mo); // killough 11/98 #endif // __P_ENEMY__ diff --git a/code/prboom/p_floor.c b/code/prboom/p_floor.c old mode 100644 new mode 100755 index ba55fdf..d92aa2c --- a/code/prboom/p_floor.c +++ b/code/prboom/p_floor.c @@ -618,7 +618,7 @@ int EV_DoFloor floor->oldspecial = sec->oldspecial; //jff 5/23/98 use model subroutine to unify fixes and handling - sec = P_FindModelFloorSector(floor->floordestheight,sec-sectors); + sec = P_FindModelFloorSector(floor->floordestheight,(int)(sec-sectors)); if (sec) { floor->texture = sec->floorpic; @@ -796,14 +796,14 @@ int EV_BuildStairs if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) continue; - newsecnum = tsec-sectors; + newsecnum = (int)(tsec-sectors); if (secnum != newsecnum) continue; tsec = (sec->lines[i])->backsector; if (!tsec) continue; //jff 5/7/98 if no backside, continue - newsecnum = tsec - sectors; + newsecnum = (int)(tsec - sectors); // if sector's floor is different texture, look for another if (tsec->floorpic != texture) @@ -915,7 +915,7 @@ int EV_DoDonut(line_t* line) // killough 4/5/98: changed demo_compatibility to compatibility if (comp[comp_model]) { - if ((!s2->lines[i]->flags & ML_TWOSIDED) || + if (((!s2->lines[i]->flags) & ML_TWOSIDED) || (s2->lines[i]->backsector == s1)) continue; } diff --git a/code/prboom/p_genlin.c b/code/prboom/p_genlin.c old mode 100644 new mode 100755 index 873b25b..845f36b --- a/code/prboom/p_genlin.c +++ b/code/prboom/p_genlin.c @@ -85,7 +85,7 @@ int EV_DoGenFloor { if (!(sec = line->backsector)) return rtn; - secnum = sec-sectors; + secnum = (int)(sec-sectors); manual = true; goto manual_floor; } @@ -187,16 +187,16 @@ int EV_DoGenFloor { if (ChgM) // if a numeric model change { - sector_t *sec; + sector_t *sector; //jff 5/23/98 find model with ceiling at target height if target //is a ceiling type - sec = (Targ==FtoLnC || Targ==FtoC)? + sector = (Targ==FtoLnC || Targ==FtoC)? P_FindModelCeilingSector(floor->floordestheight,secnum) : P_FindModelFloorSector(floor->floordestheight,secnum); - if (sec) + if (sector) { - floor->texture = sec->floorpic; + floor->texture = sector->floorpic; switch(ChgT) { case FChgZero: // zero type @@ -206,9 +206,9 @@ int EV_DoGenFloor floor->type = genFloorChg0; break; case FChgTyp: // copy type - floor->newspecial = sec->special; + floor->newspecial = sector->special; //jff 3/14/98 change old field too - floor->oldspecial = sec->oldspecial; + floor->oldspecial = sector->oldspecial; floor->type = genFloorChgT; break; case FChgTxt: // leave type be @@ -289,7 +289,7 @@ int EV_DoGenCeiling { if (!(sec = line->backsector)) return rtn; - secnum = sec-sectors; + secnum = (int)(sec-sectors); manual = true; goto manual_ceiling; } @@ -395,16 +395,16 @@ int EV_DoGenCeiling { if (ChgM) // if a numeric model change { - sector_t *sec; + sector_t *sector; //jff 5/23/98 find model with floor at target height if target //is a floor type - sec = (Targ==CtoHnF || Targ==CtoF)? + sector = (Targ==CtoHnF || Targ==CtoF)? P_FindModelFloorSector(targheight,secnum) : P_FindModelCeilingSector(targheight,secnum); - if (sec) + if (sector) { - ceiling->texture = sec->ceilingpic; + ceiling->texture = sector->ceilingpic; switch (ChgT) { case CChgZero: // type is zeroed @@ -414,9 +414,9 @@ int EV_DoGenCeiling ceiling->type = genCeilingChg0; break; case CChgTyp: // type is copied - ceiling->newspecial = sec->special; + ceiling->newspecial = sector->special; //jff 3/14/98 change old field too - ceiling->oldspecial = sec->oldspecial; + ceiling->oldspecial = sector->oldspecial; ceiling->type = genCeilingChgT; break; case CChgTxt: // type is left alone @@ -497,7 +497,7 @@ int EV_DoGenLift { if (!(sec = line->backsector)) return rtn; - secnum = sec-sectors; + secnum = (int)(sec-sectors); manual = true; goto manual_lift; } @@ -655,7 +655,7 @@ int EV_DoGenStairs { if (!(sec = line->backsector)) return rtn; - secnum = sec-sectors; + secnum = (int)(sec-sectors); manual = true; goto manual_stair; } @@ -748,13 +748,13 @@ int EV_DoGenStairs continue; tsec = (sec->lines[i])->frontsector; - newsecnum = tsec-sectors; + newsecnum = (int)(tsec-sectors); if (secnum != newsecnum) continue; tsec = (sec->lines[i])->backsector; - newsecnum = tsec - sectors; + newsecnum = (int)(tsec - sectors); if (!Igno && tsec->floorpic != texture) continue; @@ -843,7 +843,7 @@ int EV_DoGenCrusher { if (!(sec = line->backsector)) return rtn; - secnum = sec-sectors; + secnum = (int)(sec-sectors); manual = true; goto manual_crusher; } @@ -938,7 +938,7 @@ int EV_DoGenLockedDoor { if (!(sec = line->backsector)) return rtn; - secnum = sec-sectors; + secnum = (int)(sec-sectors); manual = true; goto manual_locked; } @@ -1047,7 +1047,7 @@ int EV_DoGenDoor { if (!(sec = line->backsector)) return rtn; - secnum = sec-sectors; + secnum = (int)(sec-sectors); manual = true; goto manual_door; } diff --git a/code/prboom/p_inter.c b/code/prboom/p_inter.c old mode 100644 new mode 100755 index adb2a69..5285782 --- a/code/prboom/p_inter.c +++ b/code/prboom/p_inter.c @@ -50,6 +50,8 @@ #endif #include "p_inter.h" +#include "doomiphone.h" + #define BONUSADD 6 // Ty 03/07/98 - add deh externals @@ -101,7 +103,7 @@ static boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int num) return false; #ifdef RANGECHECK - if (ammo < 0 || ammo > NUMAMMO) + if (ammo > NUMAMMO) I_Error ("P_GiveAmmo: bad type %i", ammo); #endif @@ -828,7 +830,8 @@ void P_DamageMobj(mobj_t *target,mobj_t *inflictor, mobj_t *source, int damage) player->damagecount += damage; // add damage after armor / invuln #ifdef IPHONE if ( player == &players[consoleplayer] && !demoplayback ) { // vibe during demos is annoying - SysIPhoneVibrate(); + // JDS: Stop vibration on pain + // SysIPhoneVibrate(); } #endif if (player->damagecount > 100) diff --git a/code/prboom/p_inter.h b/code/prboom/p_inter.h old mode 100644 new mode 100755 index 53b64a7..abce3f3 --- a/code/prboom/p_inter.h +++ b/code/prboom/p_inter.h @@ -37,9 +37,6 @@ #include "d_player.h" #include "p_mobj.h" -#ifdef __GNUG__ -#pragma interface -#endif /* Ty 03/09/98 Moved to an int in p_inter.c for deh and externalization */ #define MAXHEALTH maxhealth diff --git a/code/prboom/p_map.c b/code/prboom/p_map.c old mode 100644 new mode 100755 index a8c3a6d..8b4fbe8 --- a/code/prboom/p_map.c +++ b/code/prboom/p_map.c @@ -163,7 +163,7 @@ int P_GetFriction(const mobj_t *mo, int *frictionfactor) (sec->heightsec != -1 && mo->z <= sectors[sec->heightsec].floorheight && mbf_features))) - friction = sec->friction, movefactor = sec->movefactor; + (void)(friction = sec->friction), movefactor = sec->movefactor; if (frictionfactor) *frictionfactor = movefactor; @@ -373,12 +373,12 @@ boolean PIT_CrossLine (line_t* ld) static int untouched(line_t *ld) { - fixed_t x, y, tmbbox[4]; + fixed_t x, y, thetmbbox[4]; return - (tmbbox[BOXRIGHT] = (x=tmthing->x)+tmthing->radius) <= ld->bbox[BOXLEFT] || - (tmbbox[BOXLEFT] = x-tmthing->radius) >= ld->bbox[BOXRIGHT] || - (tmbbox[BOXTOP] = (y=tmthing->y)+tmthing->radius) <= ld->bbox[BOXBOTTOM] || - (tmbbox[BOXBOTTOM] = y-tmthing->radius) >= ld->bbox[BOXTOP] || + (thetmbbox[BOXRIGHT] = (x=tmthing->x)+tmthing->radius) <= ld->bbox[BOXLEFT] || + (thetmbbox[BOXLEFT] = x-tmthing->radius) >= ld->bbox[BOXRIGHT] || + (thetmbbox[BOXTOP] = (y=tmthing->y)+tmthing->radius) <= ld->bbox[BOXBOTTOM] || + (thetmbbox[BOXBOTTOM] = y-tmthing->radius) >= ld->bbox[BOXTOP] || P_BoxOnLineSide(tmbbox, ld) != -1; } @@ -532,9 +532,9 @@ static boolean PIT_CheckThing(mobj_t *thing) // killough 3/26/98: make static // A flying skull is smacking something. // Determine damage amount, and the skull comes to a dead stop. - int damage = ((P_Random(pr_skullfly)%8)+1)*tmthing->info->damage; + int skulldamage = ((P_Random(pr_skullfly)%8)+1)*tmthing->info->damage; - P_DamageMobj (thing, tmthing, tmthing, damage); + P_DamageMobj (thing, tmthing, tmthing, skulldamage); tmthing->flags &= ~MF_SKULLFLY; tmthing->momx = tmthing->momy = tmthing->momz = 0; @@ -795,7 +795,7 @@ boolean P_TryMove(mobj_t* thing,fixed_t x,fixed_t y, if (tmceilingz - tmfloorz < thing->height || // doesn't fit // mobj must lower to fit - (floatok = true, !(thing->flags & MF_TELEPORT) && + ((void)(floatok = true), !(thing->flags & MF_TELEPORT) && tmceilingz - thing->z < thing->height) || // too big a step up (!(thing->flags & MF_TELEPORT) && @@ -952,7 +952,7 @@ static boolean PIT_ApplyTorque(line_t *ld) dist = FixedMul(x,x) + FixedMul(y,y); while (dist > FRACUNIT*4 && mo->gear < MAXGEAR) - ++mo->gear, x >>= 1, y >>= 1, dist >>= 1; + (void)(++mo->gear), (void)(x >>= 1), (void)(y >>= 1), dist >>= 1; mo->momx -= x; mo->momy += y; @@ -1267,14 +1267,14 @@ void P_SlideMove(mobj_t *mo) // trace along the three leading corners if (mo->momx > 0) - leadx = mo->x + mo->radius, trailx = mo->x - mo->radius; + (void)(leadx = mo->x + mo->radius), trailx = mo->x - mo->radius; else - leadx = mo->x - mo->radius, trailx = mo->x + mo->radius; + (void)(leadx = mo->x - mo->radius), trailx = mo->x + mo->radius; if (mo->momy > 0) - leady = mo->y + mo->radius, traily = mo->y - mo->radius; + (void)(leady = mo->y + mo->radius), traily = mo->y - mo->radius; else - leady = mo->y - mo->radius, traily = mo->y + mo->radius; + (void)(leady = mo->y - mo->radius), traily = mo->y + mo->radius; bestslidefrac = FRACUNIT+1; @@ -1715,7 +1715,7 @@ boolean PTR_NoWayTraverse(intercept_t* in) // This linedef return ld->special || !( // Ignore specials ld->flags & ML_BLOCKING || ( // Always blocking - P_LineOpening(ld), // Find openings + (void)(P_LineOpening(ld)), // Find openings openrange <= 0 || // No opening openbottom > usething->z+24*FRACUNIT || // Too high it blocks opentop < usething->z+usething->height // Too low it blocks @@ -2253,7 +2253,7 @@ void P_CreateSecNodeList(mobj_t* thing,fixed_t x,fixed_t y) * And for tmbbox - cph 2003/08/10 */ if ((compatibility_level < boom_compatibility_compatibility) /* || (compatibility_level >= prboom_4_compatibility) */) { - tmx = saved_tmx, tmy = saved_tmy; + (void)(tmx = saved_tmx), tmy = saved_tmy; if (tmthing) { tmbbox[BOXTOP] = tmy + tmthing->radius; tmbbox[BOXBOTTOM] = tmy - tmthing->radius; @@ -2280,7 +2280,7 @@ void P_MapEnd(void) { static void SpechitOverrun(line_t *ld) { //int addr = 0x01C09C98 + (ld - lines) * 0x3E; - int addr = 0x00C09C98 + (ld - lines) * 0x3E; + int addr = (int)(0x00C09C98 + (ld - lines) * 0x3E); if (compatibility_level == dosdoom_compatibility || compatibility_level == tasdoom_compatibility) { diff --git a/code/prboom/p_maputl.c b/code/prboom/p_maputl.c old mode 100644 new mode 100755 index 62ce91c..71ac3e5 --- a/code/prboom/p_maputl.c +++ b/code/prboom/p_maputl.c @@ -79,9 +79,9 @@ int PUREFUNC P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line) int PUREFUNC P_BoxOnLineSide(const fixed_t *tmbox, const line_t *ld) { + int p; switch (ld->slopetype) { - int p; default: // shut up compiler warnings -- killough case ST_HORIZONTAL: return @@ -335,7 +335,7 @@ void P_SetThingPosition(mobj_t *thing) *link = thing; } else // thing is off the map - thing->bnext = NULL, thing->bprev = NULL; + (void)(thing->bnext = NULL), thing->bprev = NULL; } } @@ -365,7 +365,7 @@ boolean P_BlockLinesIterator(int x, int y, boolean func(line_t*)) if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) return true; offset = y*bmapwidth+x; - offset = *(blockmap+offset); + offset = (int)*(blockmap+offset); list = blockmaplump+offset; // original was reading // phares // delmiting 0 as linedef 0 // phares @@ -539,7 +539,7 @@ boolean PIT_AddThingIntercepts(mobj_t *thing) boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac) { intercept_t *in = NULL; - int count = intercept_p - intercepts; + int count = (int)(intercept_p - intercepts); while (count--) { fixed_t dist = INT_MAX; diff --git a/code/prboom/p_mobj.c b/code/prboom/p_mobj.c old mode 100644 new mode 100755 index 83d63e8..f77a914 --- a/code/prboom/p_mobj.c +++ b/code/prboom/p_mobj.c @@ -81,9 +81,9 @@ boolean P_SetMobjState(mobj_t* mobj,statenum_t state) st = &states[state]; mobj->state = st; - mobj->tics = st->tics; + mobj->tics = (int)st->tics; mobj->sprite = st->sprite; - mobj->frame = st->frame; + mobj->frame = (int)st->frame; // Modified handling. // Call action functions when the state is set @@ -760,7 +760,7 @@ void P_MobjThinker (mobj_t* mobj) !comp[comp_falloff]) // Not in old demos P_ApplyTorque(mobj); // Apply torque else - mobj->intflags &= ~MIF_FALLING, mobj->gear = 0; // Reset torque + (void)(mobj->intflags &= ~MIF_FALLING), mobj->gear = 0; // Reset torque } // cycle through states, @@ -844,9 +844,9 @@ mobj_t* P_SpawnMobj(fixed_t x,fixed_t y,fixed_t z,mobjtype_t type) st = &states[info->spawnstate]; mobj->state = st; - mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; + mobj->tics = (int)(st->tics); + mobj->sprite = (int)(st->sprite); + mobj->frame = (int)(st->frame); mobj->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98 // set subsector and/or block links @@ -918,6 +918,9 @@ void P_RemoveMobj (mobj_t* mobj) // stop any playing sound + // GUS temporarily disable + //S_StopSound (mobj); + // MAY NEED TVOS STUFF HERE -tkidd S_StopSound (mobj); // killough 11/98: @@ -1503,9 +1506,9 @@ void P_SpawnPlayerMissile(mobj_t* source,mobjtype_t type) if (!linetarget) slope = P_AimLineAttack(source, an -= 2<<26, 16*64*FRACUNIT, mask); if (!linetarget) - an = source->angle, slope = 0; + (void)(an = source->angle), slope = 0; } - while (mask && (mask=0, !linetarget)); // killough 8/2/98 + while (mask && ((void)(mask=0), !linetarget)); // killough 8/2/98 } x = source->x; diff --git a/code/prboom/p_pspr.c b/code/prboom/p_pspr.c old mode 100644 new mode 100755 index 1088860..57ba987 --- a/code/prboom/p_pspr.c +++ b/code/prboom/p_pspr.c @@ -88,13 +88,13 @@ static void P_SetPsprite(player_t *player, int position, statenum_t stnum) state = &states[stnum]; psp->state = state; - psp->tics = state->tics; // could be 0 + psp->tics = (int)state->tics; // could be 0 if (state->misc1) { // coordinate set - psp->sx = state->misc1 << FRACBITS; - psp->sy = state->misc2 << FRACBITS; + psp->sx = (int)state->misc1 << FRACBITS; + psp->sy = (int)state->misc2 << FRACBITS; } // Call action routine. @@ -498,7 +498,7 @@ void A_Punch(player_t *player, pspdef_t *psp) /* killough 8/2/98: make autoaiming prefer enemies */ if (!mbf_features || - (slope = P_AimLineAttack(player->mo, angle, MELEERANGE, MF_FRIEND), + ((void)(slope = P_AimLineAttack(player->mo, angle, MELEERANGE, MF_FRIEND)), !linetarget)) slope = P_AimLineAttack(player->mo, angle, MELEERANGE, 0); @@ -531,7 +531,7 @@ void A_Saw(player_t *player, pspdef_t *psp) /* Use meleerange + 1 so that the puff doesn't skip the flash * killough 8/2/98: make autoaiming prefer enemies */ if (!mbf_features || - (slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, MF_FRIEND), + ((void)(slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, MF_FRIEND)), !linetarget)) slope = P_AimLineAttack(player->mo, angle, MELEERANGE+1, 0); @@ -758,7 +758,7 @@ void A_FireCGun(player_t *player, pspdef_t *psp) P_SetMobjState(player->mo, S_PLAY_ATK2); player->ammo[weaponinfo[player->readyweapon].ammo]--; - A_FireSomething(player,psp->state - &states[S_CHAIN1]); // phares + A_FireSomething(player,(int)(psp->state - &states[S_CHAIN1])); // phares P_BulletSlope(player->mo); @@ -798,7 +798,7 @@ void A_BFGSpray(mobj_t *mo) // killough 8/2/98: make autoaiming prefer enemies if (!mbf_features || - (P_AimLineAttack(mo->target, an, 16*64*FRACUNIT, MF_FRIEND), + ((void)(P_AimLineAttack(mo->target, an, 16*64*FRACUNIT, MF_FRIEND)), !linetarget)) P_AimLineAttack(mo->target, an, 16*64*FRACUNIT, 0); diff --git a/code/prboom/p_pspr.h b/code/prboom/p_pspr.h old mode 100644 new mode 100755 index 46d9652..4a84502 --- a/code/prboom/p_pspr.h +++ b/code/prboom/p_pspr.h @@ -49,9 +49,6 @@ #include "info.h" -#ifdef __GNUG__ -#pragma interface -#endif /* * Frame flags: @@ -92,6 +89,10 @@ void P_SetupPsprites(struct player_s *curplayer); void P_MovePsprites(struct player_s *curplayer); void P_DropWeapon(struct player_s *player); +// suppressing these for now, will come back to later -tkidd + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" void A_Light0(); void A_WeaponReady(); void A_Lower(); @@ -115,5 +116,6 @@ void A_FirePlasma(); void A_BFGsound(); void A_FireBFG(); void A_BFGSpray(); +#pragma clang diagnostic pop #endif diff --git a/code/prboom/p_saveg.c b/code/prboom/p_saveg.c old mode 100644 new mode 100755 index 7e3d63b..aea7089 --- a/code/prboom/p_saveg.c +++ b/code/prboom/p_saveg.c @@ -268,6 +268,7 @@ void P_ThinkerToIndex(void) // count the number of thinkers, and mark each one with its index, using // the prev field as a placeholder, since it can be restored later. + // suppressing this warning in the compiler with a -w flag as I think it can't be helped -tkidd number_of_thinkers = 0; for (th = thinkercap.next ; th != &thinkercap ; th=th->next) if (th->function == P_MobjThinker) @@ -421,7 +422,7 @@ static int P_GetMobj(mobj_t* mi, size_t s) { size_t i = (size_t)mi; if (i >= s) I_Error("Corrupt savegame"); - return i; + return (int)i; } void P_UnArchiveThinkers (void) diff --git a/code/prboom/p_setup.c b/code/prboom/p_setup.c old mode 100644 new mode 100755 index 5247cb9..fd0c7db --- a/code/prboom/p_setup.c +++ b/code/prboom/p_setup.c @@ -768,18 +768,18 @@ static void P_LoadLineDefs2(int lump) { ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be NO_INDEX here ld->backsector = ld->sidenum[1]!=NO_INDEX ? sides[ld->sidenum[1]].sector : 0; + int thelump, j; switch (ld->special) { // killough 4/11/98: handle special types - int lump, j; case 260: // killough 4/11/98: translucent 2s textures - lump = sides[*ld->sidenum].special; // translucency from sidedef + thelump = sides[*ld->sidenum].special; // translucency from sidedef if (!ld->tag) // if tag==0, - ld->tranlump = lump; // affect this linedef only + ld->tranlump = thelump; // affect this linedef only else for (j=0;jtag) // affect all matching linedefs - lines[j].tranlump = lump; + lines[j].tranlump = thelump; break; } } @@ -831,21 +831,21 @@ static void P_LoadSideDefs2(int lump) case 242: // variable colormap via 242 linedef sd->bottomtexture = (sec->bottommap = R_ColormapNumForName(msd->bottomtexture)) < 0 ? - sec->bottommap = 0, R_TextureNumForName(msd->bottomtexture): 0 ; + (void)(sec->bottommap = 0), R_TextureNumForName(msd->bottomtexture): 0 ; sd->midtexture = (sec->midmap = R_ColormapNumForName(msd->midtexture)) < 0 ? - sec->midmap = 0, R_TextureNumForName(msd->midtexture) : 0 ; + (void)(sec->midmap = 0), R_TextureNumForName(msd->midtexture) : 0 ; sd->toptexture = (sec->topmap = R_ColormapNumForName(msd->toptexture)) < 0 ? - sec->topmap = 0, R_TextureNumForName(msd->toptexture) : 0 ; + (void)(sec->topmap = 0), R_TextureNumForName(msd->toptexture) : 0 ; break; case 260: // killough 4/11/98: apply translucency to 2s normal texture sd->midtexture = strncasecmp("TRANMAP", msd->midtexture, 8) ? (sd->special = W_CheckNumForName(msd->midtexture)) < 0 || W_LumpLength(sd->special) != 65536 ? - sd->special=0, R_TextureNumForName(msd->midtexture) : - (sd->special++, 0) : (sd->special=0); + (void)(sd->special=0), R_TextureNumForName(msd->midtexture) : + ((void)(sd->special++), 0) : (sd->special=0); sd->toptexture = R_TextureNumForName(msd->toptexture); sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); break; @@ -1217,10 +1217,10 @@ static void P_LoadBlockMap (int lump) W_UnlockLumpNum(lump); // cph - unlock the lump - bmaporgx = blockmaplump[0]<ceilingheight < back->ceilingheight ? + opentopheight = front->ceilingheight < back->ceilingheight ? front->ceilingheight : back->ceilingheight ; // because of floor height differences - openbottom = front->floorheight > back->floorheight ? + openbottomheight = front->floorheight > back->floorheight ? front->floorheight : back->floorheight ; // cph - reject if does not intrude in the z-space of the possible LOS - if ((opentop >= los.maxz) && (openbottom <= los.minz)) + if ((opentopheight >= los.maxz) && (openbottomheight <= los.minz)) continue; } @@ -159,8 +159,8 @@ static boolean P_CrossSubsector(int num) // cph - if bottom >= top or top < minz or bottom > maxz then it must be // solid wrt this LOS - if (!(line->flags & ML_TWOSIDED) || (openbottom >= opentop) || - (opentop < los.minz) || (openbottom > los.maxz)) + if (!(line->flags & ML_TWOSIDED) || (openbottomheight >= opentopheight) || + (opentopheight < los.minz) || (openbottomheight > los.maxz)) return false; { // crosses a two sided line @@ -171,14 +171,14 @@ static boolean P_CrossSubsector(int num) P_InterceptVector(&los.strace, &divl); if (front->floorheight != back->floorheight) { - fixed_t slope = FixedDiv(openbottom - los.sightzstart , frac); + fixed_t slope = FixedDiv(openbottomheight - los.sightzstart , frac); if (slope > los.bottomslope) los.bottomslope = slope; } if (front->ceilingheight != back->ceilingheight) { - fixed_t slope = FixedDiv(opentop - los.sightzstart , frac); + fixed_t slope = FixedDiv(opentopheight - los.sightzstart , frac); if (slope < los.topslope) los.topslope = slope; } @@ -263,7 +263,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) { const sector_t *s1 = t1->subsector->sector; const sector_t *s2 = t2->subsector->sector; - int pnum = (s1-sectors)*numsectors + (s2-sectors); + int pnum = (int)((s1-sectors)*numsectors + (s2-sectors)); // First check for trivial rejection. // Determine subsector entries in REJECT table. @@ -307,14 +307,14 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) los.strace.dy = (los.t2y = t2->y) - (los.strace.y = t1->y); if (t1->x > t2->x) - los.bbox[BOXRIGHT] = t1->x, los.bbox[BOXLEFT] = t2->x; + (void)(los.bbox[BOXRIGHT] = t1->x), los.bbox[BOXLEFT] = t2->x; else - los.bbox[BOXRIGHT] = t2->x, los.bbox[BOXLEFT] = t1->x; + (void)(los.bbox[BOXRIGHT] = t2->x), los.bbox[BOXLEFT] = t1->x; if (t1->y > t2->y) - los.bbox[BOXTOP] = t1->y, los.bbox[BOXBOTTOM] = t2->y; + (void)(los.bbox[BOXTOP] = t1->y), los.bbox[BOXBOTTOM] = t2->y; else - los.bbox[BOXTOP] = t2->y, los.bbox[BOXBOTTOM] = t1->y; + (void)(los.bbox[BOXTOP] = t2->y), los.bbox[BOXBOTTOM] = t1->y; /* cph - calculate min and max z of the potential line of sight * For old demos, we disable this optimisation by setting them to diff --git a/code/prboom/p_spec.c b/code/prboom/p_spec.c old mode 100644 new mode 100755 index 74d0f9d..f9188c4 --- a/code/prboom/p_spec.c +++ b/code/prboom/p_spec.c @@ -184,7 +184,7 @@ void P_InitPicAnims (void) animdefs[i].startname, animdefs[i].endname); - lastanim->speed = LONG(animdefs[i].speed); // killough 5/5/98: add LONG() + lastanim->speed = (int)LONG(animdefs[i].speed); // killough 5/5/98: add LONG() lastanim++; } W_UnlockLumpNum(lump); @@ -1265,13 +1265,13 @@ void P_CrossSpecialLine(line_t *line, int side, mobj_t *thing) case 2: // Open Door - if (EV_DoDoor(line,open) || demo_compatibility) + if (EV_DoDoor(line,openDoor) || demo_compatibility) line->special = 0; break; case 3: // Close Door - if (EV_DoDoor(line,close) || demo_compatibility) + if (EV_DoDoor(line,closeDoor) || demo_compatibility) line->special = 0; break; @@ -1534,7 +1534,7 @@ void P_CrossSpecialLine(line_t *line, int side, mobj_t *thing) case 75: // Close Door - EV_DoDoor(line,close); + EV_DoDoor(line,closeDoor); break; case 76: @@ -1579,7 +1579,7 @@ void P_CrossSpecialLine(line_t *line, int side, mobj_t *thing) case 86: // Open Door - EV_DoDoor(line,open); + EV_DoDoor(line,openDoor); break; case 87: @@ -2134,7 +2134,7 @@ void P_ShootSpecialLine case 46: // 46 GR open door, stay open - EV_DoDoor(line,open); + EV_DoDoor(line,openDoor); P_ChangeSwitchTexture(line,1); break; @@ -2229,6 +2229,7 @@ void P_PlayerInSpecialSector (player_t* player) case 9: // Tally player in secret sector, clear secret special player->secretcount++; + player->message = s_GOTSECRET; sector->special = 0; break; @@ -2540,15 +2541,15 @@ void P_SpawnSpecials (void) P_SpawnPushers(); // phares 3/20/98: New pusher model using linedefs - for (i=0; i= 0;) sectors[s].heightsec = sec; break; @@ -2556,7 +2557,7 @@ void P_SpawnSpecials (void) // killough 3/16/98: Add support for setting // floor lighting independently (e.g. lava) case 213: - sec = sides[*lines[i].sidenum].sector-sectors; + sec = (int)(sides[*lines[i].sidenum].sector-sectors); for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;) sectors[s].floorlightsec = sec; break; @@ -2564,7 +2565,7 @@ void P_SpawnSpecials (void) // killough 4/11/98: Add support for setting // ceiling lighting independently case 261: - sec = sides[*lines[i].sidenum].sector-sectors; + sec = (int)(sides[*lines[i].sidenum].sector-sectors); for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;) sectors[s].ceilinglightsec = sec; break; @@ -2629,13 +2630,14 @@ void T_Scroll(scroll_t *s) if (!(dx | dy)) // no-op if both (x,y) offsets 0 return; - switch (s->type) + side_t *side; + sector_t *sec; + fixed_t height, waterheight; // killough 4/4/98: add waterheight + msecnode_t *node; + mobj_t *thing; + + switch (s->type) { - side_t *side; - sector_t *sec; - fixed_t height, waterheight; // killough 4/4/98: add waterheight - msecnode_t *node; - mobj_t *thing; case sc_side: // killough 3/7/98: Scroll wall texture side = sides + s->affectee; @@ -2735,7 +2737,7 @@ static void Add_WallScroller(fixed_t dx, fixed_t dy, const line_t *l, { fixed_t x = D_abs(l->dx), y = D_abs(l->dy), d; if (y > x) - d = x, x = y, y = d; + (void)(d = x), (void)(x = y), y = d; d = FixedDiv(x, finesine[(tantoangle[FixedDiv(y,x) >> DBITS] + ANG90) >> ANGLETOFINESHIFT]); @@ -2781,19 +2783,19 @@ static void P_SpawnScrollers(void) if (special >= 245 && special <= 249) // displacement scrollers { special += 250-245; - control = sides[*l->sidenum].sector - sectors; + control = (int)(sides[*l->sidenum].sector - sectors); } else if (special >= 214 && special <= 218) // accelerative scrollers { accel = 1; special += 250-214; - control = sides[*l->sidenum].sector - sectors; + control = (int)(sides[*l->sidenum].sector - sectors); } + register int s; switch (special) { - register int s; case 250: // scroll effect ceiling for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;) diff --git a/code/prboom/p_spec.h b/code/prboom/p_spec.h old mode 100644 new mode 100755 index 1d5aa2b..60ce443 --- a/code/prboom/p_spec.h +++ b/code/prboom/p_spec.h @@ -366,8 +366,8 @@ typedef enum { normal, close30ThenOpen, - close, - open, + closeDoor, + openDoor, raiseIn5Mins, blazeRaise, blazeOpen, diff --git a/code/prboom/p_switch.c b/code/prboom/p_switch.c old mode 100644 new mode 100755 index 68a543e..0aa5358 --- a/code/prboom/p_switch.c +++ b/code/prboom/p_switch.c @@ -494,7 +494,7 @@ P_UseSpecialLine case 50: // Close Door - if (EV_DoDoor(line,close)) + if (EV_DoDoor(line,closeDoor)) P_ChangeSwitchTexture(line,0); break; @@ -532,7 +532,7 @@ P_UseSpecialLine case 103: // Open Door - if (EV_DoDoor(line,open)) + if (EV_DoDoor(line,openDoor)) P_ChangeSwitchTexture(line,0); break; @@ -1021,7 +1021,7 @@ P_UseSpecialLine // Buttons (retriggerable switches) case 42: // Close Door - if (EV_DoDoor(line,close)) + if (EV_DoDoor(line,closeDoor)) P_ChangeSwitchTexture(line,1); break; @@ -1045,7 +1045,7 @@ P_UseSpecialLine case 61: // Open Door - if (EV_DoDoor(line,open)) + if (EV_DoDoor(line,openDoor)) P_ChangeSwitchTexture(line,1); break; diff --git a/code/prboom/p_telept.c b/code/prboom/p_telept.c old mode 100644 new mode 100755 index 744e901..45db830 --- a/code/prboom/p_telept.c +++ b/code/prboom/p_telept.c @@ -236,7 +236,7 @@ int EV_SilentLineTeleport(line_t *line, int side, mobj_t *thing, // Get the angle between the two linedefs, for rotating // orientation and momentum. Rotate 180 degrees, and flip // the position across the exit linedef, if reversed. - angle_t angle = (reverse ? pos = FRACUNIT-pos, 0 : ANG180) + + angle_t angle = (reverse ? (void)(pos = FRACUNIT-pos), 0 : ANG180) + R_PointToAngle2(0, 0, l->dx, l->dy) - R_PointToAngle2(0, 0, line->dx, line->dy); @@ -286,14 +286,14 @@ int EV_SilentLineTeleport(line_t *line, int side, mobj_t *thing, // Exiting on side 1 slightly improves player viewing // when going down a step on a non-reversed teleporter. - int side = reverse || (player && stepdown); + int theside = reverse || (player && stepdown); // Make sure we are on correct side of exit linedef. - while (P_PointOnLineSide(x, y, l) != side && --fudge>=0) + while (P_PointOnLineSide(x, y, l) != theside && --fudge>=0) if (D_abs(l->dx) > D_abs(l->dy)) - y -= l->dx < 0 != side ? -1 : 1; + y -= l->dx < 0 != theside ? -1 : 1; else - x += l->dy < 0 != side ? -1 : 1; + x += l->dy < 0 != theside ? -1 : 1; // Attempt to teleport, aborting if blocked if (!P_TeleportMove(thing, x, y, false)) /* killough 8/9/98 */ diff --git a/code/prboom/p_user.c b/code/prboom/p_user.c old mode 100644 new mode 100755 index d280e55..29174b6 --- a/code/prboom/p_user.c +++ b/code/prboom/p_user.c @@ -311,7 +311,7 @@ void P_PlayerThink (player_t* player) ticcmd_t* cmd; weapontype_t newweapon; - if (movement_smooth && players && &players[displayplayer] == player) + if (movement_smooth && &players[displayplayer] == player) { original_view_vars.viewx = player->mo->x; original_view_vars.viewy = player->mo->y; diff --git a/code/prboom/protocol.h b/code/prboom/protocol.h old mode 100644 new mode 100755 index c2af10d..9da3ca3 --- a/code/prboom/protocol.h +++ b/code/prboom/protocol.h @@ -56,7 +56,7 @@ typedef struct { } PACKEDATTR packet_header_t; static inline void packet_set(packet_header_t* p, enum packet_type_e t, unsigned long tic) -{ p->tic = doom_htonl(tic); p->type = t; p->reserved[0] = 0; p->reserved[1] = 0; } +{ p->tic = (unsigned)doom_htonl(tic); p->type = t; p->reserved[0] = 0; p->reserved[1] = 0; } #ifndef GAME_OPTIONS_SIZE // From g_game.h diff --git a/code/prboom/r_bsp.c b/code/prboom/r_bsp.c old mode 100644 new mode 100755 index 1bbcf39..3bc79c3 --- a/code/prboom/r_bsp.c +++ b/code/prboom/r_bsp.c @@ -83,11 +83,11 @@ static void R_ClipWallSegment(int first, int last, boolean solid) while (first < last) { if (solidcol[first]) { if (!(p = memchr(solidcol+first, 0, last-first))) return; // All solid - first = p - solidcol; + first = (int)(p - solidcol); } else { int to; if (!(p = memchr(solidcol+first, 1, last-first))) to = last; - else to = p - solidcol; + else to = (int)(p - solidcol); R_StoreWallRange(first, to-1); if (solid) { memset(solidcol+first,1,to-first); @@ -222,8 +222,8 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, tempsec->ceilingheight = s->ceilingheight; // killough 11/98: prevent sudden light changes from non-water sectors: - if (underwater && (tempsec-> floorheight = sec->floorheight, - tempsec->ceilingheight = s->floorheight-1, !back)) + if (underwater && ((void)(tempsec-> floorheight = sec->floorheight), + (void)(tempsec->ceilingheight = s->floorheight-1), !back)) { // head-below-floor hack tempsec->floorpic = s->floorpic; tempsec->floor_xoffs = s->floor_xoffs; @@ -360,7 +360,7 @@ static void R_AddLine (seg_t *line) { if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM { - unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a + unsigned pos = (unsigned)(ds_p - drawsegs); // jff 8/9/98 fix from ZDOOM1.14a unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs)); //ds_p = drawsegs+maxdrawsegs; diff --git a/code/prboom/r_data.c b/code/prboom/r_data.c old mode 100644 new mode 100755 index bf2c6c7..ca9cee5 --- a/code/prboom/r_data.c +++ b/code/prboom/r_data.c @@ -140,7 +140,7 @@ static void R_InitTextures (void) // Load the patch names from pnames.lmp. name[8] = 0; names = W_CacheLumpNum(names_lump = W_GetNumForName("PNAMES")); - nummappatches = LONG(*((const int *)names)); + nummappatches = (int)LONG(*((const int *)names)); name_p = names+4; patchlookup = malloc(nummappatches*sizeof(*patchlookup)); // killough @@ -172,14 +172,14 @@ static void R_InitTextures (void) // TEXTURE1 for shareware, plus TEXTURE2 for commercial. maptex = maptex1 = W_CacheLumpNum(maptex_lump[0] = W_GetNumForName("TEXTURE1")); - numtextures1 = LONG(*maptex); + numtextures1 = (int)LONG(*maptex); maxoff = W_LumpLength(maptex_lump[0]); directory = maptex+1; if (W_CheckNumForName("TEXTURE2") != -1) { maptex2 = W_CacheLumpNum(maptex_lump[1] = W_GetNumForName("TEXTURE2")); - numtextures2 = LONG(*maptex2); + numtextures2 = (int)LONG(*maptex2); maxoff2 = W_LumpLength(maptex_lump[1]); } else @@ -208,7 +208,7 @@ static void R_InitTextures (void) directory = maptex+1; } - offset = LONG(*directory); + offset = (int)LONG(*directory); if (offset > maxoff) I_Error("R_InitTextures: Bad texture directory"); @@ -255,7 +255,6 @@ static void R_InitTextures (void) #else */ { - int j; for(j=0;jname);j++) texture->name[j]=mtexture->name[j]; } @@ -322,9 +321,9 @@ static void R_InitTextures (void) textures[i]->index = -1; while (--i >= 0) { - int j = W_LumpNameHash(textures[i]->name) % (unsigned) numtextures; - textures[i]->next = textures[j]->index; // Prepend to chain - textures[j]->index = i; + int texturej = W_LumpNameHash(textures[i]->name) % (unsigned) numtextures; + textures[i]->next = textures[texturej]->index; // Prepend to chain + textures[texturej]->index = i; } } @@ -408,16 +407,18 @@ int R_ColormapNumForName(const char *name) static inline int between(int l,int u,int x) { return (l > x ? l : x > u ? u : x); } -const lighttable_t* R_ColourMap(int lightlevel, fixed_t spryscale) +const lighttable_t* R_ColourMap(int lightlevel, fixed_t spriteyscale) { if (fixedcolormap) return fixedcolormap; else { - if (curline) - if (curline->v1->y == curline->v2->y) - lightlevel -= 1 << LIGHTSEGSHIFT; - else - if (curline->v1->x == curline->v2->x) - lightlevel += 1 << LIGHTSEGSHIFT; + if (curline) { + if (curline->v1->y == curline->v2->y) + lightlevel -= 1 << LIGHTSEGSHIFT; + else { + if (curline->v1->x == curline->v2->x) + lightlevel += 1 << LIGHTSEGSHIFT; + } + } lightlevel += extralight << LIGHTSEGSHIFT; @@ -434,7 +435,7 @@ const lighttable_t* R_ColourMap(int lightlevel, fixed_t spryscale) */ return fullcolormap + between(0,NUMCOLORMAPS-1, ((256-lightlevel)*2*NUMCOLORMAPS/256) - 4 - - (FixedMul(spryscale,pspriteiscale)/2 >> LIGHTSCALESHIFT) + - (FixedMul(spriteyscale,pspriteiscale)/2 >> LIGHTSCALESHIFT) )*256; } } @@ -532,8 +533,10 @@ void R_InitTranMap(int progress) long best = LONG_MAX; do if ((err = tot[color] - pal[0][color]*r - - pal[1][color]*g - pal[2][color]*b) < best) - best = err, *tp = color; + - pal[1][color]*g - pal[2][color]*b) < best) { + best = err; + *tp = color; + } while (--color >= 0); } } @@ -615,6 +618,39 @@ int PUREFUNC R_CheckTextureNumForName(const char *name) return i; } +// Maps textures with things we can't show in Germany to appropriate textures. +//static const char * germanyRemap[][2] = { +// { "ZZWOLF2", "ZZWOLF1" }, +// { "ZZWOLF3", "ZZWOLF1" }, +// { "ZZWOLF4", "ZZWOLF1" }, +// { "ZZWOLF6", "ZZWOLF5" }, +// { "ZZWOLF7", "ZZWOLF5" }, +// { "ZZWOLF12", "ZZWOLF11" }, +// { "ZZWOLF13", "ZZWOLF11" }, +// { NULL, NULL } +//}; + +// +// R_RemapTextureForGermany +// Given a texture name, returns a suitable replacement texture without any images of swastikas +// or Hitler. +// +const char * R_RemapTextureForGermany( const char * name ) { + return name; + +// const char ** currentTestPair = germanyRemap[0]; +// +// while ( currentTestPair[0] != NULL ) { +// if ( strncmp( currentTestPair[0], name, 8 ) == 0 ) { +// return currentTestPair[1]; +// } +// +// currentTestPair += 2; +// } +// +// return name; +} + // // R_TextureNumForName // Calls R_CheckTextureNumForName, @@ -623,9 +659,11 @@ int PUREFUNC R_CheckTextureNumForName(const char *name) int PUREFUNC R_TextureNumForName(const char *name) // const added -- killough { - int i = R_CheckTextureNumForName(name); + const char * remappedName = R_RemapTextureForGermany( name ); + + int i = R_CheckTextureNumForName(remappedName); if (i == -1) - I_Error("R_TextureNumForName: %.8s not found", name); + I_Error("R_TextureNumForName: %.8s not found", remappedName); return i; } @@ -634,10 +672,12 @@ int PUREFUNC R_TextureNumForName(const char *name) // const added -- killough // Calls R_CheckTextureNumForName, and changes any error to NO_TEXTURE int PUREFUNC R_SafeTextureNumForName(const char *name, int snum) { - int i = R_CheckTextureNumForName(name); + const char * remappedName = R_RemapTextureForGermany( name ); + + int i = R_CheckTextureNumForName(remappedName); if (i == -1) { i = NO_TEXTURE; // e6y - return "no texture" - lprintf(LO_DEBUG,"bad texture '%s' in sidedef %d\n",name,snum); + lprintf(LO_DEBUG,"bad texture '%s' in sidedef %d\n",remappedName,snum); } return i; } diff --git a/code/prboom/r_data.h b/code/prboom/r_data.h old mode 100644 new mode 100755 index 98f15b4..16aac96 --- a/code/prboom/r_data.h +++ b/code/prboom/r_data.h @@ -40,9 +40,6 @@ #include "r_state.h" #include "r_patch.h" -#ifdef __GNUG__ -#pragma interface -#endif // A single patch from a texture definition, basically // a rectangular area within the texture rectangle. diff --git a/code/prboom/r_defs.h b/code/prboom/r_defs.h old mode 100644 new mode 100755 index 88a5803..173d629 --- a/code/prboom/r_defs.h +++ b/code/prboom/r_defs.h @@ -48,9 +48,6 @@ // SECTORS do store MObjs anyway. #include "p_mobj.h" -#ifdef __GNUG__ -#pragma interface -#endif // Silhouette, needed for clipping Segs (mainly) // and sprites representing things. diff --git a/code/prboom/r_demo.c b/code/prboom/r_demo.c old mode 100644 new mode 100755 index 0f9e6f1..766f0bb --- a/code/prboom/r_demo.c +++ b/code/prboom/r_demo.c @@ -46,7 +46,7 @@ static angle_t smooth_playing_angle; void R_SmoothPlaying_Reset(player_t *player) { - if (demo_smoothturns && demoplayback && players) + if (demo_smoothturns && demoplayback) { if (!player) player = &players[displayplayer]; diff --git a/code/prboom/r_draw.c b/code/prboom/r_draw.c old mode 100644 new mode 100755 index 106ad60..a34d202 --- a/code/prboom/r_draw.c +++ b/code/prboom/r_draw.c @@ -62,6 +62,8 @@ int viewheight; int viewwindowx; int viewwindowy; +bool isiPhoneX; + // Color tables for different players, // translate a limited part to another // (color ramps used for suit colors). diff --git a/code/prboom/r_draw.h b/code/prboom/r_draw.h old mode 100644 new mode 100755 index 1b9bc62..47dfd68 --- a/code/prboom/r_draw.h +++ b/code/prboom/r_draw.h @@ -36,9 +36,6 @@ #include "r_defs.h" -#ifdef __GNUG__ -#pragma interface -#endif enum column_pipeline_e { RDC_PIPELINE_STANDARD, diff --git a/code/prboom/r_drawcolumn.inl b/code/prboom/r_drawcolumn.inl old mode 100644 new mode 100755 index 199a24e..84ef852 --- a/code/prboom/r_drawcolumn.inl +++ b/code/prboom/r_drawcolumn.inl @@ -251,9 +251,11 @@ static void R_DRAWCOLUMN_FUNCNAME(draw_column_vars_t *dcvars) const byte *source = dcvars->source; const lighttable_t *colormap = dcvars->colormap; const byte *translation = dcvars->translation; + #if (R_DRAWCOLUMN_PIPELINE & (RDC_BILINEAR|RDC_ROUNDED|RDC_DITHERZ)) int y = dcvars->yl; const int x = dcvars->x; + (void)x; #endif #if (R_DRAWCOLUMN_PIPELINE & RDC_DITHERZ) const int fracz = (dcvars->z >> 6) & 255; @@ -275,6 +277,11 @@ static void R_DRAWCOLUMN_FUNCNAME(draw_column_vars_t *dcvars) const unsigned int filter_fracu = (dcvars->source == dcvars->nextsource) ? 0 : (dcvars->texu>>8) & 0xff; #endif + /* Prevent unused variable warnings. */ + (void)source; + (void)colormap; + (void)translation; + count++; // Inner loop that does the actual texture mapping, @@ -318,7 +325,8 @@ static void R_DRAWCOLUMN_FUNCNAME(draw_column_vars_t *dcvars) INCY(y); } else { fixed_t nextfrac = 0; - + (void)nextfrac; + heightmask++; heightmask <<= FRACBITS; diff --git a/code/prboom/r_drawspan.inl b/code/prboom/r_drawspan.inl old mode 100644 new mode 100755 index 84cc95d..2953a8f --- a/code/prboom/r_drawspan.inl +++ b/code/prboom/r_drawspan.inl @@ -97,10 +97,14 @@ static void R_DRAWSPAN_FUNCNAME(draw_span_vars_t *dsvars) const fixed_t ystep = dsvars->ystep; const byte *source = dsvars->source; const byte *colormap = dsvars->colormap; + (void)colormap; SCREENTYPE *dest = drawvars.TOPLEFT + dsvars->y*drawvars.PITCH + dsvars->x1; #if (R_DRAWSPAN_PIPELINE & (RDC_DITHERZ|RDC_BILINEAR)) const int y = dsvars->y; int x1 = dsvars->x1; + + (void)y; + (void)x1; #endif #if (R_DRAWSPAN_PIPELINE & RDC_DITHERZ) const int fracz = (dsvars->z >> 12) & 255; diff --git a/code/prboom/r_filter.c b/code/prboom/r_filter.c old mode 100644 new mode 100755 index 4b44f14..ee49bf7 --- a/code/prboom/r_filter.c +++ b/code/prboom/r_filter.c @@ -33,8 +33,8 @@ #define DMR 16 byte filter_ditherMatrix[DITHER_DIM][DITHER_DIM] = { - 0*DMR, 14*DMR, 3*DMR, 13*DMR, 11*DMR, 5*DMR, 8*DMR, 6*DMR, - 12*DMR, 2*DMR, 15*DMR, 1*DMR, 7*DMR, 9*DMR, 4*DMR, 10*DMR + {0*DMR, 14*DMR, 3*DMR, 13*DMR}, {11*DMR, 5*DMR, 8*DMR, 6*DMR}, + {12*DMR, 2*DMR, 15*DMR, 1*DMR}, {7*DMR, 9*DMR, 4*DMR, 10*DMR} }; byte filter_roundedUVMap[FILTER_UVDIM*FILTER_UVDIM]; diff --git a/code/prboom/r_fps.h b/code/prboom/r_fps.h old mode 100644 new mode 100755 index bfbeab0..c9d43ec --- a/code/prboom/r_fps.h +++ b/code/prboom/r_fps.h @@ -64,12 +64,12 @@ void R_InterpolateView (player_t *player, fixed_t frac); extern boolean WasRenderedInTryRunTics; -void R_ResetViewInterpolation (); -void R_UpdateInterpolations(); +void R_ResetViewInterpolation (void); +void R_UpdateInterpolations(void); void R_StopAllInterpolations(void); void R_DoInterpolations(fixed_t smoothratio); -void R_RestoreInterpolations(); -void R_ActivateSectorInterpolations(); +void R_RestoreInterpolations(void); +void R_ActivateSectorInterpolations(void); void R_ActivateThinkerInterpolations(thinker_t *th); void R_StopInterpolationIfNeeded(thinker_t *th); diff --git a/code/prboom/r_main.c b/code/prboom/r_main.c old mode 100644 new mode 100755 index b8947b7..43fdeb2 --- a/code/prboom/r_main.c +++ b/code/prboom/r_main.c @@ -227,9 +227,9 @@ angle_t R_PointToAngle(fixed_t x, fixed_t y) #endif } -angle_t R_PointToAngle2(fixed_t viewx, fixed_t viewy, fixed_t x, fixed_t y) +angle_t R_PointToAngle2(fixed_t viewxpos, fixed_t viewypos, fixed_t x, fixed_t y) { - return (y -= viewy, (x -= viewx) || y) ? + return ((void)(y -= viewypos), (x -= viewxpos) || y) ? x >= 0 ? y >= 0 ? (x > y) ? tantoangle[SlopeDiv(y,x)] : // octant 0 @@ -322,13 +322,13 @@ static void R_InitLightTables (void) // for each level / distance combination. for (i=0; i< LIGHTLEVELS; i++) { - int j, startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; + int j, startcolormap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; for (j=0; j>= LIGHTSCALESHIFT)/DISTMAP; + int t, level = startcolormap - (scale >>= LIGHTSCALESHIFT)/DISTMAP; if (level < 0) level = 0; @@ -591,63 +591,22 @@ void R_RenderPlayerView (player_t* player) R_ClearSprites (); rendered_segs = rendered_visplanes = 0; - if (V_GetMode() == VID_MODEGL) - { -#ifdef GL_DOOM - // proff 11/99: clear buffers - gld_InitDrawScene(); - // proff 11/99: switch to perspective mode - gld_StartDrawScene(); -#endif - } else { - if (autodetect_hom) - { // killough 2/10/98: add flashing red HOM indicators - unsigned char color=(gametic % 20) < 9 ? 0xb0 : 0; - V_FillRect(0, viewwindowx, viewwindowy, viewwidth, viewheight, color); - R_DrawViewBorder(); - } - } - // check for new console commands. -#ifdef HAVE_NET - NetUpdate (); -#endif + // proff 11/99: clear buffers + gld_InitDrawScene(); + // proff 11/99: switch to perspective mode + gld_StartDrawScene(); // The head node is the last node output. R_RenderBSPNode (numnodes-1); R_ResetColumnBuffer(); + + // proff 11/99: draw the scene + gld_DrawScene(player); + + // proff 11/99: finishing off + gld_EndDrawScene(); - // Check for new console commands. -#ifdef HAVE_NET - NetUpdate (); -#endif - - if (V_GetMode() != VID_MODEGL) - R_DrawPlanes (); - - // Check for new console commands. -#ifdef HAVE_NET - NetUpdate (); -#endif - - if (V_GetMode() != VID_MODEGL) { - R_DrawMasked (); - R_ResetColumnBuffer(); - } - - // Check for new console commands. -#ifdef HAVE_NET - NetUpdate (); -#endif - - if (V_GetMode() == VID_MODEGL) { -#ifdef GL_DOOM - // proff 11/99: draw the scene - gld_DrawScene(player); - // proff 11/99: finishing off - gld_EndDrawScene(); -#endif - } if (rendering_stats) R_ShowStats(); diff --git a/code/prboom/r_main.h b/code/prboom/r_main.h old mode 100644 new mode 100755 index 05654bc..cadbafb --- a/code/prboom/r_main.h +++ b/code/prboom/r_main.h @@ -37,9 +37,6 @@ #include "d_player.h" #include "r_data.h" -#ifdef __GNUG__ -#pragma interface -#endif // // POV related. @@ -61,6 +58,8 @@ extern fixed_t projection; // proff 11/06/98: Added for high-res extern fixed_t projectiony; extern int validcount; +extern bool isiPhoneX; + // // Rendering stats diff --git a/code/prboom/r_patch.c b/code/prboom/r_patch.c old mode 100644 new mode 100755 index e466fb2..0f8a88f --- a/code/prboom/r_patch.c +++ b/code/prboom/r_patch.c @@ -82,6 +82,8 @@ void R_InitPatches(void) { patches = (rpatch_t*)malloc(numlumps * sizeof(rpatch_t)); // clear out new patches to signal they're uninitialized memset(patches, 0, sizeof(rpatch_t)*numlumps); + } else { + memset(patches, 0, sizeof(rpatch_t)*numlumps); } if (!texture_composites) { @@ -303,7 +305,7 @@ static void createPatch(int id) { } } - if (1 || patch->isNotTileable) { +// if (1 || patch->isNotTileable) { const rcolumn_t *column, *prevColumn; // copy the patch image down and to the right where there are @@ -345,7 +347,7 @@ static void createPatch(int id) { // verify that the patch truly is non-rectangular since // this determines tiling later on - } +// } W_UnlockLumpNum(patchNum); free(numPostsInColumn); @@ -618,7 +620,7 @@ static void createTextureCompositePatch(int id) { } } - if (1 || composite_patch->isNotTileable) { + if (/* DISABLES CODE */ (1) || composite_patch->isNotTileable) { const rcolumn_t *column, *prevColumn; // copy the patch image down and to the right where there are diff --git a/code/prboom/r_patch.h b/code/prboom/r_patch.h old mode 100644 new mode 100755 index b0d1387..f663dc7 --- a/code/prboom/r_patch.h +++ b/code/prboom/r_patch.h @@ -105,7 +105,7 @@ const rcolumn_t *R_GetPatchColumnClamped(const rpatch_t *patch, int columnIndex) const rcolumn_t *R_GetPatchColumn(const rpatch_t *patch, int columnIndex); -void R_InitPatches(); -void R_FlushAllPatches(); +void R_InitPatches(void); +void R_FlushAllPatches(void); #endif diff --git a/code/prboom/r_plane.c b/code/prboom/r_plane.c old mode 100644 new mode 100755 index 8eaa1e1..62ce4dd --- a/code/prboom/r_plane.c +++ b/code/prboom/r_plane.c @@ -198,7 +198,7 @@ void R_ClearPlanes(void) // opening / clipping determination for (i=0 ; iheight && picnum == check->picnum && lightlevel == check->lightlevel && - xoffs == check->xoffs && // killough 2/28/98: Add offset checks - yoffs == check->yoffs) + xoffset == check->xoffs && // killough 2/28/98: Add offset checks + yoffset == check->yoffs) return check; check = new_visplane(hash); // killough @@ -281,8 +281,8 @@ visplane_t *R_FindPlane(fixed_t height, int picnum, int lightlevel, check->lightlevel = lightlevel; check->minx = viewwidth; // Was SCREENWIDTH -- killough 11/98 check->maxx = -1; - check->xoffs = xoffs; // killough 2/28/98: Save offsets - check->yoffs = yoffs; + check->xoffs = xoffset; // killough 2/28/98: Save offsets + check->yoffs = yoffset; memset (check->top, 0xff, sizeof check->top); @@ -297,14 +297,14 @@ visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop) int intrl, intrh, unionl, unionh, x; if (start < pl->minx) - intrl = pl->minx, unionl = start; + (void)(intrl = pl->minx), unionl = start; else - unionl = pl->minx, intrl = start; + (void)(unionl = pl->minx), intrl = start; if (stop > pl->maxx) - intrh = pl->maxx, unionh = stop; + (void)(intrh = pl->maxx), unionh = stop; else - unionh = pl->maxx, intrh = stop; + (void)(unionh = pl->maxx), intrh = stop; for (x=intrl ; x <= intrh && pl->top[x] == 0xffffffffu; x++) // dropoff overflow ; diff --git a/code/prboom/r_segs.c b/code/prboom/r_segs.c old mode 100644 new mode 100755 index cb30b75..b7fd8ec --- a/code/prboom/r_segs.c +++ b/code/prboom/r_segs.c @@ -216,7 +216,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, int x1, int x2) if (t + (int_64_t) textureheight[texnum] * spryscale < 0 || t > (int_64_t) MAX_SCREENHEIGHT << FRACBITS*2) continue; // skip if the texture is out of screen's range - sprtopscreen = (long)(t >> FRACBITS); + sprtopscreen = (int)((long)(t >> FRACBITS)); } dcvars.iscale = 0xffffffffu / (unsigned) spryscale; @@ -479,7 +479,7 @@ void R_StoreWallRange(const int start, const int stop) if (ds_p == drawsegs+maxdrawsegs) // killough 1/98 -- fix 2s line HOM { - unsigned pos = ds_p - drawsegs; // jff 8/9/98 fix from ZDOOM1.14a + unsigned pos = (unsigned)(ds_p - drawsegs); // jff 8/9/98 fix from ZDOOM1.14a unsigned newmax = maxdrawsegs ? maxdrawsegs*2 : 128; // killough drawsegs = realloc(drawsegs,newmax*sizeof(*drawsegs)); ds_p = drawsegs + pos; // jff 8/9/98 fix from ZDOOM1.14a diff --git a/code/prboom/r_state.h b/code/prboom/r_state.h old mode 100644 new mode 100755 index 44784f2..1a444cb --- a/code/prboom/r_state.h +++ b/code/prboom/r_state.h @@ -39,9 +39,6 @@ #include "d_player.h" #include "r_data.h" -#ifdef __GNUG__ -#pragma interface -#endif // diff --git a/code/prboom/r_things.c b/code/prboom/r_things.c old mode 100644 new mode 100755 index 570f634..f678b57 --- a/code/prboom/r_things.c +++ b/code/prboom/r_things.c @@ -789,25 +789,25 @@ static void R_DrawPSprite (pspdef_t *psp, int lightlevel) #ifdef GL_DOOM else { - int lightlevel; + int finallightlevel; sector_t tmpsec; int floorlightlevel, ceilinglightlevel; if ((vis->colormap==fixedcolormap) || (vis->colormap==fullcolormap)) - lightlevel=255; + finallightlevel=255; else { -// lightlevel = (viewplayer->mo->subsector->sector->lightlevel) + (extralight << LIGHTSEGSHIFT); +// finallightlevel = (viewplayer->mo->subsector->sector->lightlevel) + (extralight << LIGHTSEGSHIFT); R_FakeFlat( viewplayer->mo->subsector->sector, &tmpsec, &floorlightlevel, &ceilinglightlevel, false); - lightlevel = ((floorlightlevel+ceilinglightlevel) >> 1) + (extralight << LIGHTSEGSHIFT); + finallightlevel = ((floorlightlevel+ceilinglightlevel) >> 1) + (extralight << LIGHTSEGSHIFT); - if (lightlevel < 0) - lightlevel = 0; - else if (lightlevel >= 255) - lightlevel = 255; + if (finallightlevel < 0) + finallightlevel = 0; + else if (finallightlevel >= 255) + finallightlevel = 255; } - gld_DrawWeapon(lump,vis,lightlevel); + gld_DrawWeapon(lump,vis,finallightlevel); } #endif } @@ -863,7 +863,7 @@ static void msort(vissprite_t **s, vissprite_t **t, int n) msort(s2, t, n2); while ((*s1)->scale > (*s2)->scale ? - (*d++ = *s1++, --n1) : (*d++ = *s2++, --n2)); + ((void)(*d++ = *s1++), --n1) : ((void)(*d++ = *s2++), --n2)); if (n2) bcopyp(d, s2, n2); @@ -892,7 +892,7 @@ void R_SortVisSprites (void) { if (num_vissprite) { - int i = num_vissprite; + int i = (int)num_vissprite; // If we need to allocate more pointers for the vissprites, // allocate as many as were allocated for sprites -- killough @@ -911,7 +911,7 @@ void R_SortVisSprites (void) // killough 9/22/98: replace qsort with merge sort, since the keys // are roughly in order to begin with, due to BSP rendering. - msort(vissprite_ptrs, vissprite_ptrs + num_vissprite, num_vissprite); + msort(vissprite_ptrs, vissprite_ptrs + num_vissprite, (int)num_vissprite); } } @@ -1056,8 +1056,8 @@ void R_DrawMasked(void) // draw all vissprites back to front - rendered_vissprites = num_vissprite; - for (i = num_vissprite ;--i>=0; ) + rendered_vissprites = (int)num_vissprite; + for (i = (int)num_vissprite ;--i>=0; ) R_DrawSprite(vissprite_ptrs[i]); // killough // render any remaining masked mid textures diff --git a/code/prboom/s_sound.c b/code/prboom/s_sound.c old mode 100644 new mode 100755 index 74aaa06..e2885c5 --- a/code/prboom/s_sound.c +++ b/code/prboom/s_sound.c @@ -71,7 +71,7 @@ typedef struct { sfxinfo_t *sfxinfo; // sound information (if null, channel avail.) void *origin; // origin of sound - int handle; // handle of the sound being played + long int handle; // handle of the sound being played (JDS: 64-bit) int is_pickup; // killough 4/25/98: whether sound is a player's weapon int volume; // JDC: perform overrides based on dynamic volume instead of static priority } channel_t; @@ -111,8 +111,6 @@ void S_StopChannel(int cnum); int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, int *vol, int *sep, int *pitch); -static int S_getChannel(void *origin, sfxinfo_t *sfxinfo, int is_pickup); - // Initializes sound stuff, including volume // Sets channels, SFX and music volume, // allocates channel buffer, sets S_sfx lookup. @@ -177,6 +175,9 @@ void S_Start(void) // kill all playing sounds at start of level // (trust me - a good idea) + //S_Stop(); + //Gus Temporarily Disable + // MAY NEED TVOS STUFF HERE -tkidd S_Stop(); //jff 1/22/98 return if music is not enabled @@ -206,10 +207,25 @@ void S_Start(void) mus_e1m9 // Tim e4m9 }; + static const int sigilmus[] = // Song - Who? - Where? + { + mus_e5m1, // Buckethead e5m1 + mus_e5m2, // Buckethead e5m2 + mus_e5m3, // Buckethead e5m3 + mus_e5m4, // Buckethead e5m4 + mus_e5m5, // Buckethead e5m5 + mus_e5m6, // Buckethead e5m6 + mus_e5m7, // Buckethead e5m7 + mus_e5m8, // Buckethead e5m8 + mus_e5m9 // Buckethead e5m9 + }; + if (gameepisode < 4) mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1; - else + else if (gameepisode == 4) mnum = spmus[gamemap-1]; + else + mnum = sigilmus[gamemap-1]; } S_ChangeMusic(mnum, true); } @@ -331,7 +347,7 @@ void S_StartSoundAtVolume(void *origin_p, int sfx_id, int volume) if ( cnum == numChannels ) { // nothing available - printf( "dropping sound for no channels available\n" ); + printf( "dropping sound for no channels available (%i)\n", numChannels ); return; } @@ -357,7 +373,8 @@ void S_StartSoundAtVolume(void *origin_p, int sfx_id, int volume) // Assigns the handle to one of the channels in the mix/output buffer. { // e6y: [Fix] Crash with zero-length sounds. - int h = I_StartSound(sfx_id, cnum, volume, sep, pitch, priority); + // JDS 64-bit handles + long int h = I_StartSound(sfx_id, cnum, volume, sep, pitch, priority); if (h != -1) channels[cnum].handle = h; } } @@ -464,7 +481,7 @@ void S_UpdateSounds(void* listener_p) &volume, &sep, &pitch)) S_StopChannel(cnum); else - I_UpdateSoundParams(c->handle, volume, sep, pitch); + I_UpdateSoundParams((int)c->handle, volume, sep, pitch); } } else // if channel is allocated but sound has stopped, free it @@ -516,7 +533,10 @@ void S_ChangeMusic(int musicnum, int looping) { musicinfo_t *music; int music_file_failed; // cournia - if true load the default MIDI music - char* music_filename; // cournia + char music_filename[ 1024 ]; // cournia + + (void)music_file_failed; + (void)music_filename; //jff 1/22/98 return if music is not enabled if (!mus_card || nomusicparm) @@ -530,11 +550,14 @@ void S_ChangeMusic(int musicnum, int looping) if (mus_playing == music) return; #endif - + +/* #ifdef IPHONE extern void iphonePlayMusic( const char *name ); iphonePlayMusic( music->name ); + #else +*/ // shutdown old music S_StopMusic(); @@ -545,34 +568,50 @@ void S_ChangeMusic(int musicnum, int looping) sprintf(namebuf, "d_%s", music->name); music->lumpnum = W_GetNumForName(namebuf); } - + music_file_failed = 1; // proff_fs - only load when from IWAD - if (lumpinfo[music->lumpnum].source == source_iwad) - { + //if (lumpinfo[music->lumpnum].source == source_iwad) +// { // cournia - check to see if we can play a higher quality music file // rather than the default MIDI - music_filename = I_FindFile(S_music_files[musicnum], ""); - if (music_filename) + + I_FindFile(S_music_files[musicnum], "", music_filename); + if ( music_filename[0] != '\0' ) { music_file_failed = I_RegisterMusic(music_filename, music); - free(music_filename); + //free(music_filename); } - } + + // } if (music_file_failed) { //cournia - could not load music file, play default MIDI music - + // load & register it music->data = W_CacheLumpNum(music->lumpnum); music->handle = I_RegisterSong(music->data, W_LumpLength(music->lumpnum)); } + + extern void iphoneStartMP3( const char *name ); + extern boolean sigilShredsLoaded; // Buckethead! + + if (sigilShredsLoaded) { + + char* mp3filename = I_RegisterMusic_MP3(music, music->data, W_LumpLength(music->lumpnum)); + + iphoneStartMP3(mp3filename); + + } else { // play it - I_PlaySong(music->handle, looping); -#endif + I_PlaySong(music->handle, looping); + } + + +//#endif mus_playing = music; } @@ -706,7 +745,7 @@ int S_AdjustSoundParams(mobj_t *listener, mobj_t *source, // If none available, return -1. Otherwise channel #. // // killough 4/25/98: made static, added is_pickup argument - +#ifndef IPHONE static int S_getChannel(void *origin, sfxinfo_t *sfxinfo, int is_pickup) { // channel number to use @@ -744,3 +783,4 @@ static int S_getChannel(void *origin, sfxinfo_t *sfxinfo, int is_pickup) c->is_pickup = is_pickup; // killough 4/25/98 return cnum; } +#endif diff --git a/code/prboom/s_sound.h b/code/prboom/s_sound.h old mode 100644 new mode 100755 index 29d3219..ac72d70 --- a/code/prboom/s_sound.h +++ b/code/prboom/s_sound.h @@ -34,9 +34,6 @@ #ifndef __S_SOUND__ #define __S_SOUND__ -#ifdef __GNUG__ -#pragma interface -#endif // // Initializes sound stuff, including volume diff --git a/code/prboom/sounds.c b/code/prboom/sounds.c old mode 100644 new mode 100755 index cc68a3c..a4f440d --- a/code/prboom/sounds.c +++ b/code/prboom/sounds.c @@ -38,6 +38,8 @@ #include "config.h" #endif +#include + #include "doomtype.h" #include "sounds.h" @@ -46,74 +48,83 @@ // musicinfo_t S_music[] = { - { 0 }, - { "e1m1", 0 }, - { "e1m2", 0 }, - { "e1m3", 0 }, - { "e1m4", 0 }, - { "e1m5", 0 }, - { "e1m6", 0 }, - { "e1m7", 0 }, - { "e1m8", 0 }, - { "e1m9", 0 }, - { "e2m1", 0 }, - { "e2m2", 0 }, - { "e2m3", 0 }, - { "e2m4", 0 }, - { "e2m5", 0 }, - { "e2m6", 0 }, - { "e2m7", 0 }, - { "e2m8", 0 }, - { "e2m9", 0 }, - { "e3m1", 0 }, - { "e3m2", 0 }, - { "e3m3", 0 }, - { "e3m4", 0 }, - { "e3m5", 0 }, - { "e3m6", 0 }, - { "e3m7", 0 }, - { "e3m8", 0 }, - { "e3m9", 0 }, - { "inter", 0 }, - { "intro", 0 }, - { "bunny", 0 }, - { "victor", 0 }, - { "introa", 0 }, - { "runnin", 0 }, - { "stalks", 0 }, - { "countd", 0 }, - { "betwee", 0 }, - { "doom", 0 }, - { "the_da", 0 }, - { "shawn", 0 }, - { "ddtblu", 0 }, - { "in_cit", 0 }, - { "dead", 0 }, - { "stlks2", 0 }, - { "theda2", 0 }, - { "doom2", 0 }, - { "ddtbl2", 0 }, - { "runni2", 0 }, - { "dead2", 0 }, - { "stlks3", 0 }, - { "romero", 0 }, - { "shawn2", 0 }, - { "messag", 0 }, - { "count2", 0 }, - { "ddtbl3", 0 }, - { "ampie", 0 }, - { "theda3", 0 }, - { "adrian", 0 }, - { "messg2", 0 }, - { "romer2", 0 }, - { "tense", 0 }, - { "shawn3", 0 }, - { "openin", 0 }, - { "evil", 0 }, - { "ultima", 0 }, - { "read_m", 0 }, - { "dm2ttl", 0 }, - { "dm2int", 0 }, + { NULL, 0, NULL, 0 }, + { "e1m1", 0, NULL, 0 }, + { "e1m2", 0, NULL, 0 }, + { "e1m3", 0, NULL, 0 }, + { "e1m4", 0, NULL, 0 }, + { "e1m5", 0, NULL, 0 }, + { "e1m6", 0, NULL, 0 }, + { "e1m7", 0, NULL, 0 }, + { "e1m8", 0, NULL, 0 }, + { "e1m9", 0, NULL, 0 }, + { "e2m1", 0, NULL, 0 }, + { "e2m2", 0, NULL, 0 }, + { "e2m3", 0, NULL, 0 }, + { "e2m4", 0, NULL, 0 }, + { "e2m5", 0, NULL, 0 }, + { "e2m6", 0, NULL, 0 }, + { "e2m7", 0, NULL, 0 }, + { "e2m8", 0, NULL, 0 }, + { "e2m9", 0, NULL, 0 }, + { "e3m1", 0, NULL, 0 }, + { "e3m2", 0, NULL, 0 }, + { "e3m3", 0, NULL, 0 }, + { "e3m4", 0, NULL, 0 }, + { "e3m5", 0, NULL, 0 }, + { "e3m6", 0, NULL, 0 }, + { "e3m7", 0, NULL, 0 }, + { "e3m8", 0, NULL, 0 }, + { "e3m9", 0, NULL, 0 }, + { "inter", 0, NULL, 0 }, + { "intro", 0, NULL, 0 }, + { "bunny", 0, NULL, 0 }, + { "victor", 0, NULL, 0 }, + { "introa", 0, NULL, 0 }, + { "runnin", 0, NULL, 0 }, + { "stalks", 0, NULL, 0 }, + { "countd", 0, NULL, 0 }, + { "betwee", 0, NULL, 0 }, + { "doom", 0, NULL, 0 }, + { "the_da", 0, NULL, 0 }, + { "shawn", 0, NULL, 0 }, + { "ddtblu", 0, NULL, 0 }, + { "in_cit", 0, NULL, 0 }, + { "dead", 0, NULL, 0 }, + { "stlks2", 0, NULL, 0 }, + { "theda2", 0, NULL, 0 }, + { "doom2", 0, NULL, 0 }, + { "ddtbl2", 0, NULL, 0 }, + { "runni2", 0, NULL, 0 }, + { "dead2", 0, NULL, 0 }, + { "stlks3", 0, NULL, 0 }, + { "romero", 0, NULL, 0 }, + { "shawn2", 0, NULL, 0 }, + { "messag", 0, NULL, 0 }, + { "count2", 0, NULL, 0 }, + { "ddtbl3", 0, NULL, 0 }, + { "ampie", 0, NULL, 0 }, + { "theda3", 0, NULL, 0 }, + { "adrian", 0, NULL, 0 }, + { "messg2", 0, NULL, 0 }, + { "romer2", 0, NULL, 0 }, + { "tense", 0, NULL, 0 }, + { "shawn3", 0, NULL, 0 }, + { "openin", 0, NULL, 0 }, + { "evil", 0, NULL, 0 }, + { "ultima", 0, NULL, 0 }, + { "read_m", 0, NULL, 0 }, + { "dm2ttl", 0, NULL, 0 }, + { "dm2int", 0, NULL, 0 }, + { "e5m1", 0, NULL, 0 }, + { "e5m2", 0, NULL, 0 }, + { "e5m3", 0, NULL, 0 }, + { "e5m4", 0, NULL, 0 }, + { "e5m5", 0, NULL, 0 }, + { "e5m6", 0, NULL, 0 }, + { "e5m7", 0, NULL, 0 }, + { "e5m8", 0, NULL, 0 }, + { "e5m9", 0, NULL, 0 }, }; @@ -123,116 +134,116 @@ musicinfo_t S_music[] = { sfxinfo_t S_sfx[] = { // S_sfx[0] needs to be a dummy for odd reasons. - { "none", false, 0, 0, -1, -1, 0 }, + { "none", false, 0, 0, -1, -1, 0, 0, 0 }, - { "pistol", false, 64, 0, -1, -1, 0 }, - { "shotgn", false, 64, 0, -1, -1, 0 }, - { "sgcock", false, 64, 0, -1, -1, 0 }, - { "dshtgn", false, 64, 0, -1, -1, 0 }, - { "dbopn", false, 64, 0, -1, -1, 0 }, - { "dbcls", false, 64, 0, -1, -1, 0 }, - { "dbload", false, 64, 0, -1, -1, 0 }, - { "plasma", false, 64, 0, -1, -1, 0 }, - { "bfg", false, 64, 0, -1, -1, 0 }, - { "sawup", false, 64, 0, -1, -1, 0 }, - { "sawidl", false, 118, 0, -1, -1, 0 }, - { "sawful", false, 64, 0, -1, -1, 0 }, - { "sawhit", false, 64, 0, -1, -1, 0 }, - { "rlaunc", false, 64, 0, -1, -1, 0 }, - { "rxplod", false, 70, 0, -1, -1, 0 }, - { "firsht", false, 70, 0, -1, -1, 0 }, - { "firxpl", false, 70, 0, -1, -1, 0 }, - { "pstart", false, 100, 0, -1, -1, 0 }, - { "pstop", false, 100, 0, -1, -1, 0 }, - { "doropn", false, 100, 0, -1, -1, 0 }, - { "dorcls", false, 100, 0, -1, -1, 0 }, - { "stnmov", false, 119, 0, -1, -1, 0 }, - { "swtchn", false, 78, 0, -1, -1, 0 }, - { "swtchx", false, 78, 0, -1, -1, 0 }, - { "plpain", false, 96, 0, -1, -1, 0 }, - { "dmpain", false, 96, 0, -1, -1, 0 }, - { "popain", false, 96, 0, -1, -1, 0 }, - { "vipain", false, 96, 0, -1, -1, 0 }, - { "mnpain", false, 96, 0, -1, -1, 0 }, - { "pepain", false, 96, 0, -1, -1, 0 }, - { "slop", false, 78, 0, -1, -1, 0 }, - { "itemup", true, 78, 0, -1, -1, 0 }, - { "wpnup", true, 78, 0, -1, -1, 0 }, - { "oof", false, 96, 0, -1, -1, 0 }, - { "telept", false, 32, 0, -1, -1, 0 }, - { "posit1", true, 98, 0, -1, -1, 0 }, - { "posit2", true, 98, 0, -1, -1, 0 }, - { "posit3", true, 98, 0, -1, -1, 0 }, - { "bgsit1", true, 98, 0, -1, -1, 0 }, - { "bgsit2", true, 98, 0, -1, -1, 0 }, - { "sgtsit", true, 98, 0, -1, -1, 0 }, - { "cacsit", true, 98, 0, -1, -1, 0 }, - { "brssit", true, 94, 0, -1, -1, 0 }, - { "cybsit", true, 92, 0, -1, -1, 0 }, - { "spisit", true, 90, 0, -1, -1, 0 }, - { "bspsit", true, 90, 0, -1, -1, 0 }, - { "kntsit", true, 90, 0, -1, -1, 0 }, - { "vilsit", true, 90, 0, -1, -1, 0 }, - { "mansit", true, 90, 0, -1, -1, 0 }, - { "pesit", true, 90, 0, -1, -1, 0 }, - { "sklatk", false, 70, 0, -1, -1, 0 }, - { "sgtatk", false, 70, 0, -1, -1, 0 }, - { "skepch", false, 70, 0, -1, -1, 0 }, - { "vilatk", false, 70, 0, -1, -1, 0 }, - { "claw", false, 70, 0, -1, -1, 0 }, - { "skeswg", false, 70, 0, -1, -1, 0 }, - { "pldeth", false, 32, 0, -1, -1, 0 }, - { "pdiehi", false, 32, 0, -1, -1, 0 }, - { "podth1", false, 70, 0, -1, -1, 0 }, - { "podth2", false, 70, 0, -1, -1, 0 }, - { "podth3", false, 70, 0, -1, -1, 0 }, - { "bgdth1", false, 70, 0, -1, -1, 0 }, - { "bgdth2", false, 70, 0, -1, -1, 0 }, - { "sgtdth", false, 70, 0, -1, -1, 0 }, - { "cacdth", false, 70, 0, -1, -1, 0 }, - { "skldth", false, 70, 0, -1, -1, 0 }, - { "brsdth", false, 32, 0, -1, -1, 0 }, - { "cybdth", false, 32, 0, -1, -1, 0 }, - { "spidth", false, 32, 0, -1, -1, 0 }, - { "bspdth", false, 32, 0, -1, -1, 0 }, - { "vildth", false, 32, 0, -1, -1, 0 }, - { "kntdth", false, 32, 0, -1, -1, 0 }, - { "pedth", false, 32, 0, -1, -1, 0 }, - { "skedth", false, 32, 0, -1, -1, 0 }, - { "posact", true, 120, 0, -1, -1, 0 }, - { "bgact", true, 120, 0, -1, -1, 0 }, - { "dmact", true, 120, 0, -1, -1, 0 }, - { "bspact", true, 100, 0, -1, -1, 0 }, - { "bspwlk", true, 100, 0, -1, -1, 0 }, - { "vilact", true, 100, 0, -1, -1, 0 }, - { "noway", false, 78, 0, -1, -1, 0 }, - { "barexp", false, 60, 0, -1, -1, 0 }, - { "punch", false, 64, 0, -1, -1, 0 }, - { "hoof", false, 70, 0, -1, -1, 0 }, - { "metal", false, 70, 0, -1, -1, 0 }, - { "chgun", false, 64, &S_sfx[sfx_pistol], 150, 0, 0 }, - { "tink", false, 60, 0, -1, -1, 0 }, - { "bdopn", false, 100, 0, -1, -1, 0 }, - { "bdcls", false, 100, 0, -1, -1, 0 }, - { "itmbk", false, 100, 0, -1, -1, 0 }, - { "flame", false, 32, 0, -1, -1, 0 }, - { "flamst", false, 32, 0, -1, -1, 0 }, - { "getpow", false, 60, 0, -1, -1, 0 }, - { "bospit", false, 70, 0, -1, -1, 0 }, - { "boscub", false, 70, 0, -1, -1, 0 }, - { "bossit", false, 70, 0, -1, -1, 0 }, - { "bospn", false, 70, 0, -1, -1, 0 }, - { "bosdth", false, 70, 0, -1, -1, 0 }, - { "manatk", false, 70, 0, -1, -1, 0 }, - { "mandth", false, 70, 0, -1, -1, 0 }, - { "sssit", false, 70, 0, -1, -1, 0 }, - { "ssdth", false, 70, 0, -1, -1, 0 }, - { "keenpn", false, 70, 0, -1, -1, 0 }, - { "keendt", false, 70, 0, -1, -1, 0 }, - { "skeact", false, 70, 0, -1, -1, 0 }, - { "skesit", false, 70, 0, -1, -1, 0 }, - { "skeatk", false, 70, 0, -1, -1, 0 }, - { "radio", false, 60, 0, -1, -1, 0 }, + { "pistol", false, 64, 0, -1, -1, 0, 0, 0 }, + { "shotgn", false, 64, 0, -1, -1, 0, 0, 0 }, + { "sgcock", false, 64, 0, -1, -1, 0, 0, 0 }, + { "dshtgn", false, 64, 0, -1, -1, 0, 0, 0 }, + { "dbopn", false, 64, 0, -1, -1, 0, 0, 0 }, + { "dbcls", false, 64, 0, -1, -1, 0, 0, 0 }, + { "dbload", false, 64, 0, -1, -1, 0, 0, 0 }, + { "plasma", false, 64, 0, -1, -1, 0, 0, 0 }, + { "bfg", false, 64, 0, -1, -1, 0, 0, 0 }, + { "sawup", false, 64, 0, -1, -1, 0, 0, 0 }, + { "sawidl", false, 118, 0, -1, -1, 0, 0, 0 }, + { "sawful", false, 64, 0, -1, -1, 0, 0, 0 }, + { "sawhit", false, 64, 0, -1, -1, 0, 0, 0 }, + { "rlaunc", false, 64, 0, -1, -1, 0, 0, 0 }, + { "rxplod", false, 70, 0, -1, -1, 0, 0, 0 }, + { "firsht", false, 70, 0, -1, -1, 0, 0, 0 }, + { "firxpl", false, 70, 0, -1, -1, 0, 0, 0 }, + { "pstart", false, 100, 0, -1, -1, 0, 0, 0 }, + { "pstop", false, 100, 0, -1, -1, 0, 0, 0 }, + { "doropn", false, 100, 0, -1, -1, 0, 0, 0 }, + { "dorcls", false, 100, 0, -1, -1, 0, 0, 0 }, + { "stnmov", false, 119, 0, -1, -1, 0, 0, 0 }, + { "swtchn", false, 78, 0, -1, -1, 0, 0, 0 }, + { "swtchx", false, 78, 0, -1, -1, 0, 0, 0 }, + { "plpain", false, 96, 0, -1, -1, 0, 0, 0 }, + { "dmpain", false, 96, 0, -1, -1, 0, 0, 0 }, + { "popain", false, 96, 0, -1, -1, 0, 0, 0 }, + { "vipain", false, 96, 0, -1, -1, 0, 0, 0 }, + { "mnpain", false, 96, 0, -1, -1, 0, 0, 0 }, + { "pepain", false, 96, 0, -1, -1, 0, 0, 0 }, + { "slop", false, 78, 0, -1, -1, 0, 0, 0 }, + { "itemup", true, 78, 0, -1, -1, 0, 0, 0 }, + { "wpnup", true, 78, 0, -1, -1, 0, 0, 0 }, + { "oof", false, 96, 0, -1, -1, 0, 0, 0 }, + { "telept", false, 32, 0, -1, -1, 0, 0, 0 }, + { "posit1", true, 98, 0, -1, -1, 0, 0, 0 }, + { "posit2", true, 98, 0, -1, -1, 0, 0, 0 }, + { "posit3", true, 98, 0, -1, -1, 0, 0, 0 }, + { "bgsit1", true, 98, 0, -1, -1, 0, 0, 0 }, + { "bgsit2", true, 98, 0, -1, -1, 0, 0, 0 }, + { "sgtsit", true, 98, 0, -1, -1, 0, 0, 0 }, + { "cacsit", true, 98, 0, -1, -1, 0, 0, 0 }, + { "brssit", true, 94, 0, -1, -1, 0, 0, 0 }, + { "cybsit", true, 92, 0, -1, -1, 0, 0, 0 }, + { "spisit", true, 90, 0, -1, -1, 0, 0, 0 }, + { "bspsit", true, 90, 0, -1, -1, 0, 0, 0 }, + { "kntsit", true, 90, 0, -1, -1, 0, 0, 0 }, + { "vilsit", true, 90, 0, -1, -1, 0, 0, 0 }, + { "mansit", true, 90, 0, -1, -1, 0, 0, 0 }, + { "pesit", true, 90, 0, -1, -1, 0, 0, 0 }, + { "sklatk", false, 70, 0, -1, -1, 0, 0, 0 }, + { "sgtatk", false, 70, 0, -1, -1, 0, 0, 0 }, + { "skepch", false, 70, 0, -1, -1, 0, 0, 0 }, + { "vilatk", false, 70, 0, -1, -1, 0, 0, 0 }, + { "claw", false, 70, 0, -1, -1, 0, 0, 0 }, + { "skeswg", false, 70, 0, -1, -1, 0, 0, 0 }, + { "pldeth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "pdiehi", false, 32, 0, -1, -1, 0, 0, 0 }, + { "podth1", false, 70, 0, -1, -1, 0, 0, 0 }, + { "podth2", false, 70, 0, -1, -1, 0, 0, 0 }, + { "podth3", false, 70, 0, -1, -1, 0, 0, 0 }, + { "bgdth1", false, 70, 0, -1, -1, 0, 0, 0 }, + { "bgdth2", false, 70, 0, -1, -1, 0, 0, 0 }, + { "sgtdth", false, 70, 0, -1, -1, 0, 0, 0 }, + { "cacdth", false, 70, 0, -1, -1, 0, 0, 0 }, + { "skldth", false, 70, 0, -1, -1, 0, 0, 0 }, + { "brsdth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "cybdth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "spidth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "bspdth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "vildth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "kntdth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "pedth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "skedth", false, 32, 0, -1, -1, 0, 0, 0 }, + { "posact", true, 120, 0, -1, -1, 0, 0, 0 }, + { "bgact", true, 120, 0, -1, -1, 0, 0, 0 }, + { "dmact", true, 120, 0, -1, -1, 0, 0, 0 }, + { "bspact", true, 100, 0, -1, -1, 0, 0, 0 }, + { "bspwlk", true, 100, 0, -1, -1, 0, 0, 0 }, + { "vilact", true, 100, 0, -1, -1, 0, 0, 0 }, + { "noway", false, 78, 0, -1, -1, 0, 0, 0 }, + { "barexp", false, 60, 0, -1, -1, 0, 0, 0 }, + { "punch", false, 64, 0, -1, -1, 0, 0, 0 }, + { "hoof", false, 70, 0, -1, -1, 0, 0, 0 }, + { "metal", false, 70, 0, -1, -1, 0, 0, 0 }, + { "chgun", false, 64, &S_sfx[sfx_pistol], 150, 0, 0, 0, 0 }, + { "tink", false, 60, 0, -1, -1, 0, 0, 0 }, + { "bdopn", false, 100, 0, -1, -1, 0, 0, 0 }, + { "bdcls", false, 100, 0, -1, -1, 0, 0, 0 }, + { "itmbk", false, 100, 0, -1, -1, 0, 0, 0 }, + { "flame", false, 32, 0, -1, -1, 0, 0, 0 }, + { "flamst", false, 32, 0, -1, -1, 0, 0, 0 }, + { "getpow", false, 60, 0, -1, -1, 0, 0, 0 }, + { "bospit", false, 70, 0, -1, -1, 0, 0, 0 }, + { "boscub", false, 70, 0, -1, -1, 0, 0, 0 }, + { "bossit", false, 70, 0, -1, -1, 0, 0, 0 }, + { "bospn", false, 70, 0, -1, -1, 0, 0, 0 }, + { "bosdth", false, 70, 0, -1, -1, 0, 0, 0 }, + { "manatk", false, 70, 0, -1, -1, 0, 0, 0 }, + { "mandth", false, 70, 0, -1, -1, 0, 0, 0 }, + { "sssit", false, 70, 0, -1, -1, 0, 0, 0 }, + { "ssdth", false, 70, 0, -1, -1, 0, 0, 0 }, + { "keenpn", false, 70, 0, -1, -1, 0, 0, 0 }, + { "keendt", false, 70, 0, -1, -1, 0, 0, 0 }, + { "skeact", false, 70, 0, -1, -1, 0, 0, 0 }, + { "skesit", false, 70, 0, -1, -1, 0, 0, 0 }, + { "skeatk", false, 70, 0, -1, -1, 0, 0, 0 }, + { "radio", false, 60, 0, -1, -1, 0, 0, 0 }, #ifdef DOGS // killough 11/98: dog sounds diff --git a/code/prboom/sounds.h b/code/prboom/sounds.h index 0f82333..a60ece3 100644 --- a/code/prboom/sounds.h +++ b/code/prboom/sounds.h @@ -172,6 +172,15 @@ typedef enum { mus_read_m, mus_dm2ttl, mus_dm2int, + mus_e5m1, + mus_e5m2, + mus_e5m3, + mus_e5m4, + mus_e5m5, + mus_e5m6, + mus_e5m7, + mus_e5m8, + mus_e5m9, NUMMUSIC } musicenum_t; diff --git a/code/prboom/st_stuff.c b/code/prboom/st_stuff.c old mode 100644 new mode 100755 index 1ae9cc2..d220d22 --- a/code/prboom/st_stuff.c +++ b/code/prboom/st_stuff.c @@ -949,11 +949,6 @@ static void ST_loadData(void) ST_loadGraphics(true); } -static void ST_unloadData(void) -{ - ST_loadGraphics(false); -} - static void ST_initData(void) { int i; diff --git a/code/prboom/tables.c b/code/prboom/tables.c old mode 100644 new mode 100755 index 2cf59e1..6fdf12d --- a/code/prboom/tables.c +++ b/code/prboom/tables.c @@ -120,6 +120,7 @@ void R_LoadTrigTables(void) #define CORRECT_TABLE_ENDIAN(tbl) \ for (n = 0; n= (unsigned)numlumps) - I_Error ("W_CacheLumpNum: %i >= numlumps",lump); -#endif - - if (!cachelump[lump].cache) // read the lump in - W_ReadLump(lump, Z_Malloc(W_LumpLength(lump), PU_CACHE, &cachelump[lump].cache)); - - /* cph - if wasn't locked but now is, tell z_zone to hold it */ - if (!cachelump[lump].locks && locks) { - Z_ChangeTag(cachelump[lump].cache,PU_STATIC); -#ifdef TIMEDIAG - cachelump[lump].locktic = gametic; -#endif - } - cachelump[lump].locks += locks; - -#ifdef SIMPLECHECKS - if (!((cachelump[lump].locks+1) & 0xf)) - lprintf(LO_DEBUG, "W_CacheLumpNum: High lock on %8s (%d)\n", - lumpinfo[lump].name, cachelump[lump].locks); -#endif - - return cachelump[lump].cache; -} - -const void *W_LockLumpNum(int lump) -{ - return W_CacheLumpNum(lump); -} - -/* - * W_UnlockLumpNum - * - * CPhipps - this changes (should reduce) the number of locks on a lump - */ - -void W_UnlockLumpNum(int lump) -{ - const int unlocks = 1; -#ifdef SIMPLECHECKS - if ((signed short)cachelump[lump].locks < unlocks) - lprintf(LO_DEBUG, "W_UnlockLumpNum: Excess unlocks on %8s (%d-%d)\n", - lumpinfo[lump].name, cachelump[lump].locks, unlocks); -#endif - cachelump[lump].locks -= unlocks; - /* cph - Note: must only tell z_zone to make purgeable if currently locked, - * else it might already have been purged - */ - if (unlocks && !cachelump[lump].locks) - Z_ChangeTag(cachelump[lump].cache, PU_CACHE); -} - diff --git a/code/prboom/w_mmap.c b/code/prboom/w_mmap.c old mode 100644 new mode 100755 index f1632b9..ace3607 --- a/code/prboom/w_mmap.c +++ b/code/prboom/w_mmap.c @@ -271,7 +271,7 @@ const void* W_CacheLumpNum(int lump) // printf( "W_CacheLumpNum( %i ) = %s\n", lump, lumpinfo[lump].name ); // JDC tracking hitches if (!lumpinfo[lump].wadfile) return NULL; - return (mapped_wad[lumpinfo[lump].wadfile->handle]+lumpinfo[lump].position); + return ((unsigned char*)mapped_wad[lumpinfo[lump].wadfile->handle]+lumpinfo[lump].position); } #endif diff --git a/code/prboom/w_wad.c b/code/prboom/w_wad.c old mode 100644 new mode 100755 index b771622..75258e2 --- a/code/prboom/w_wad.c +++ b/code/prboom/w_wad.c @@ -83,7 +83,7 @@ void ExtractFileBase (const char *path, char *dest) while ((*src) && (*src != '.') && (++length<9)) { *dest++ = toupper(*src); - *src++; + src++; } /* cph - length check removed, just truncate at 8 chars. * If there are 8 or more chars, we'll copy 8, and no zero termination @@ -168,7 +168,7 @@ static void W_AddFile(wadfile_info_t *wadfile) // single lump file fileinfo = &singleinfo; singleinfo.filepos = 0; - singleinfo.size = LONG(I_Filelength(wadfile->handle)); + singleinfo.size = (int)LONG(I_Filelength(wadfile->handle)); ExtractFileBase(wadfile->name, singleinfo.name); numlumps++; } @@ -179,8 +179,8 @@ static void W_AddFile(wadfile_info_t *wadfile) if (strncmp(header.identification,"IWAD",4) && strncmp(header.identification,"PWAD",4)) I_Error("W_AddFile: Wad file %s doesn't have IWAD or PWAD id", wadfile->name); - header.numlumps = LONG(header.numlumps); - header.infotableofs = LONG(header.infotableofs); + header.numlumps = (int)LONG(header.numlumps); + header.infotableofs = (int)LONG(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo2free = fileinfo = malloc(length); // killough lseek(wadfile->handle, header.infotableofs, SEEK_SET); @@ -196,11 +196,14 @@ static void W_AddFile(wadfile_info_t *wadfile) for (i=startlump ; (int)iwadfile = wadfile; // killough 4/25/98 - lump_p->position = LONG(fileinfo->filepos); - lump_p->size = LONG(fileinfo->size); + lump_p->position = (int)LONG(fileinfo->filepos); + lump_p->size = (int)LONG(fileinfo->size); lump_p->li_namespace = ns_global; // killough 4/17/98 strncpy (lump_p->name, fileinfo->name, 8); lump_p->source = wadfile->src; // Ty 08/29/98 + +// lprintf (LO_INFO," lump_p->wadfile %s lump_p->name %s i: %i\n",lump_p->wadfile->name, lump_p->name, i); + } free(fileinfo2free); // killough @@ -262,7 +265,7 @@ static void W_CoalesceMarkedResource(const char *start_marker, free(marked); // free marked list - numlumps = num_unmarked + num_marked; // new total number of lumps + numlumps = (unsigned)(num_unmarked + num_marked); // new total number of lumps if (mark_end) // add end marker { @@ -281,13 +284,13 @@ static void W_CoalesceMarkedResource(const char *start_marker, unsigned W_LumpNameHash(const char *s) { unsigned hash; - (void) ((hash = toupper(s[0]), s[1]) && - (hash = hash*3+toupper(s[1]), s[2]) && - (hash = hash*2+toupper(s[2]), s[3]) && - (hash = hash*2+toupper(s[3]), s[4]) && - (hash = hash*2+toupper(s[4]), s[5]) && - (hash = hash*2+toupper(s[5]), s[6]) && - (hash = hash*2+toupper(s[6]), + (void) (((void)(hash = toupper(s[0])), s[1]) && + ((void)(hash = hash*3+toupper(s[1])), s[2]) && + ((void)(hash = hash*2+toupper(s[2])), s[3]) && + ((void)(hash = hash*2+toupper(s[3])), s[4]) && + ((void)(hash = hash*2+toupper(s[4])), s[5]) && + ((void)(hash = hash*2+toupper(s[5])), s[6]) && + ((void)(hash = hash*2+toupper(s[6])), hash = hash*2+toupper(s[7])) ); return hash; @@ -396,7 +399,10 @@ size_t numwadfiles = 0; // CPhipps - size of the wadfiles array (dynamic, no lim void W_Init(void) { // CPhipps - start with nothing - + numlumps = 0; + free(lumpinfo); + lumpinfo = NULL; + numlumps = 0; lumpinfo = NULL; { // CPhipps - new wadfiles array used diff --git a/code/prboom/w_wad.h b/code/prboom/w_wad.h old mode 100644 new mode 100755 index 399869e..7199b90 --- a/code/prboom/w_wad.h +++ b/code/prboom/w_wad.h @@ -35,9 +35,6 @@ #ifndef __W_WAD__ #define __W_WAD__ -#ifdef __GNUG__ -#pragma interface -#endif // // TYPES diff --git a/code/prboom/wi_stuff.c b/code/prboom/wi_stuff.c old mode 100644 new mode 100755 index 9ed2c47..c4065a9 --- a/code/prboom/wi_stuff.c +++ b/code/prboom/wi_stuff.c @@ -224,39 +224,39 @@ static point_t lnodes[NUMEPISODES][NUMMAPS] = // static anim_t epsd0animinfo[] = { - { ANIM_ALWAYS, TICRATE/3, 3, { 224, 104 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 184, 160 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 112, 136 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 72, 112 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 88, 96 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 64, 48 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 192, 40 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 136, 16 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 80, 16 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 64, 24 } } + { ANIM_ALWAYS, TICRATE/3, 3, { 224, 104 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 184, 160 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 112, 136 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 72, 112 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 88, 96 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 64, 48 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 192, 40 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 136, 16 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 80, 16 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 64, 24 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 } }; static anim_t epsd1animinfo[] = { - { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 1 }, - { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 2 }, - { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 3 }, - { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 4 }, - { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 5 }, - { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 6 }, - { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 7 }, - { ANIM_LEVEL, TICRATE/3, 3, { 192, 144 }, 8 }, - { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 8 } + { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 1, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 2, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 3, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 4, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 5, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 6, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 7, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_LEVEL, TICRATE/3, 3, { 192, 144 }, 8, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 8, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 } }; static anim_t epsd2animinfo[] = { - { ANIM_ALWAYS, TICRATE/3, 3, { 104, 168 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 40, 136 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 160, 96 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 104, 80 } }, - { ANIM_ALWAYS, TICRATE/3, 3, { 120, 32 } }, - { ANIM_ALWAYS, TICRATE/4, 3, { 40, 0 } } + { ANIM_ALWAYS, TICRATE/3, 3, { 104, 168 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 40, 136 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 160, 96 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 104, 80 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/3, 3, { 120, 32 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 }, + { ANIM_ALWAYS, TICRATE/4, 3, { 40, 0 }, 0, 0, { {0, 0, 0, 0, 0} }, 0, 0, 0, 0 } }; static int NUMANIMS[NUMEPISODES] = @@ -415,6 +415,10 @@ static void WI_slamBackground(void) if (gamemode == commercial || (gamemode == retail && wbs->epsd == 3)) strcpy(name, "INTERPIC"); +#ifdef GAME_SIGIL + else if (wbs->epsd == 4) + sprintf(name, "SIGILINT"); +#endif else sprintf(name, "WIMAP%d", wbs->epsd); @@ -828,13 +832,13 @@ void WI_initNoState(void) // // cph - pulled from WI_drawStats below -static void WI_drawTimeStats(int cnt_time, int cnt_total_time, int cnt_par) +static void WI_drawTimeStats(int cnt_time_sec, int cnt_total_time_sec, int cnt_par_time_sec) { V_DrawNamePatch(SP_TIMEX, SP_TIMEY, FB, time1, CR_DEFAULT, VPT_STRETCH); - WI_drawTime(320/2 - SP_TIMEX, SP_TIMEY, cnt_time); + WI_drawTime(320/2 - SP_TIMEX, SP_TIMEY, cnt_time_sec); V_DrawNamePatch(SP_TIMEX, (SP_TIMEY+200)/2, FB, total, CR_DEFAULT, VPT_STRETCH); - WI_drawTime(320/2 - SP_TIMEX, (SP_TIMEY+200)/2, cnt_total_time); + WI_drawTime(320/2 - SP_TIMEX, (SP_TIMEY+200)/2, cnt_total_time_sec); // Ty 04/11/98: redid logic: should skip only if with pwad but // without deh patch @@ -846,7 +850,7 @@ static void WI_drawTimeStats(int cnt_time, int cnt_total_time, int cnt_par) if (wbs->epsd < 3) { V_DrawNamePatch(320/2 + SP_TIMEX, SP_TIMEY, FB, par, CR_DEFAULT, VPT_STRETCH); - WI_drawTime(320 - SP_TIMEX, SP_TIMEY, cnt_par); + WI_drawTime(320 - SP_TIMEX, SP_TIMEY, cnt_par_time_sec); } } } @@ -986,22 +990,22 @@ void WI_drawNoState(void) int WI_fragSum(int playernum) { int i; - int frags = 0; + int numfrags = 0; for (i=0 ; iblocks; @@ -71,7 +71,7 @@ void* Z_BMalloc(struct block_memory_alloc_s *pzone) while (*pool != NULL) { byte *p = memchr((*pool)->used, unused_block, (*pool)->blocks); // Scan for unused marker if (p) { - int n = p - (*pool)->used; + int n = (int)(p - (*pool)->used); #ifdef SIMPLECHECKS if ((n<0) || ((size_t)n>=(*pool)->blocks)) I_Error("Z_BMalloc: memchr returned pointer outside of array"); diff --git a/code/prboom/z_zone.h b/code/prboom/z_zone.h old mode 100644 new mode 100755 index f70ce08..c1455d9 --- a/code/prboom/z_zone.h +++ b/code/prboom/z_zone.h @@ -79,7 +79,7 @@ void Z_Close(void); void *(Z_Calloc)(size_t n, size_t n2, int tag, void **user DA(const char *, int)); void *(Z_Realloc)(void *p, size_t n, int tag, void **user DA(const char *, int)); char *(Z_Strdup)(const char *s, int tag, void **user DA(const char *, int)); -void (Z_CheckHeap)(DAC(const char *,int)); // killough 3/22/98: add file/line info +void (Z_CheckHeap)(DAC(const char *,int)void); // killough 3/22/98: add file/line info void Z_DumpHistory(char *); #ifdef INSTRUMENTED diff --git a/doomtool/doomtool.xcodeproj/project.pbxproj b/doomtool/doomtool.xcodeproj/project.pbxproj index f3b594b..772f060 100644 --- a/doomtool/doomtool.xcodeproj/project.pbxproj +++ b/doomtool/doomtool.xcodeproj/project.pbxproj @@ -105,9 +105,16 @@ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 1000; + }; buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "doomtool" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = en; hasScannedForEncodings = 1; + knownRegions = ( + en, + ); mainGroup = 08FB7794FE84155DC02AAC07 /* doomtool */; projectDirPath = ""; projectRoot = ""; @@ -133,9 +140,9 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_WEAK = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; INSTALL_PATH = /usr/local/bin; @@ -147,6 +154,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_WEAK = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_MODEL_TUNING = G5; INSTALL_PATH = /usr/local/bin; @@ -157,26 +165,69 @@ 1DEB928A08733DD80010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; - PREBINDING = NO; - SDKROOT = macosx10.5; + SDKROOT = macosx; }; name = Debug; }; 1DEB928B08733DD80010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - SDKROOT = macosx10.5; + SDKROOT = macosx; }; name = Release; }; diff --git a/doomtool/doomtool.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/doomtool/doomtool.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/doomtool/doomtool.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/doomtool/doomtool.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/xcschememanagement.plist b/doomtool/doomtool.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..76eb768 --- /dev/null +++ b/doomtool/doomtool.xcodeproj/xcuserdata/tomkidd.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + doomtool.xcscheme + + orderHint + 0 + + + + diff --git a/doomtool/main.c b/doomtool/main.c index e353e57..92dc400 100644 --- a/doomtool/main.c +++ b/doomtool/main.c @@ -53,9 +53,9 @@ typedef unsigned char byte; #include "doomtool.h" -const char *assetDirectory = "/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/assets"; -const char *outputFile = "/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/base.iPack"; -const char *parmFile = "/Volumes/Work/idMobileDepot/Archive/DoomClassicDepot/base.parm"; +const char *assetDirectory = "/Users/tomkidd/Documents/GitHub/DOOM-iOS/assets"; +const char *outputFile = "/Users/tomkidd/Documents/GitHub/DOOM-iOS/base/base.iPack"; +const char *parmFile = "/Users/tomkidd/Documents/GitHub/DOOM-iOS/base.parm"; pkHeader_t buildHeader; FILE *pakFile; diff --git a/icon_doom.png b/icon_doom.png new file mode 100644 index 0000000..3190e76 Binary files /dev/null and b/icon_doom.png differ diff --git a/idGinzaNar-Md2.otf b/idGinzaNar-Md2.otf new file mode 100644 index 0000000..18407f8 Binary files /dev/null and b/idGinzaNar-Md2.otf differ diff --git a/ss_doom.png b/ss_doom.png new file mode 100644 index 0000000..60c8de9 Binary files /dev/null and b/ss_doom.png differ