├── .gitignore ├── Square Wave ├── Podfile ├── Square Wave.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── abusman.xcuserdatad │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist ├── Square Wave │ ├── AddToPlaylistView.swift │ ├── AppDelegate.swift │ ├── ArtistsView.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── icon20x20.png │ │ │ ├── icon20x20@2x-1.png │ │ │ ├── icon20x20@2x-2.png │ │ │ ├── icon20x20@2x.png │ │ │ ├── icon20x20@3x.png │ │ │ ├── icon29x29.png │ │ │ ├── icon29x29@2x-1.png │ │ │ ├── icon29x29@2x.png │ │ │ ├── icon29x29@3x.png │ │ │ ├── icon40x40@2x-1.png │ │ │ ├── icon40x40@2x.png │ │ │ ├── icon60x60@2x-1.png │ │ │ ├── icon60x60@2x.png │ │ │ ├── icon60x60@3x.png │ │ │ ├── icon76x76.png │ │ │ ├── icon76x76@2x.png │ │ │ ├── icon83.5x83.5@2x.png │ │ │ └── itunes-icon.png │ │ ├── Consoles │ │ │ ├── Contents.json │ │ │ ├── atari.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── atari.png │ │ │ │ ├── atari@2x.png │ │ │ │ └── atari@3x.png │ │ │ ├── gameboy.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── gameboy.png │ │ │ │ ├── gameboy@2x.png │ │ │ │ └── gameboy@3x.png │ │ │ ├── master-system.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── master-system.png │ │ │ │ ├── master-system@2x.png │ │ │ │ └── master-system@3x.png │ │ │ ├── megadrive.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── megadrive.png │ │ │ │ ├── megadrive@2x.png │ │ │ │ └── megadrive@3x.png │ │ │ ├── msx.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── msx.png │ │ │ │ ├── msx@2x.png │ │ │ │ └── msx@3x.png │ │ │ ├── nes.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── nes.png │ │ │ │ ├── nes@2x.png │ │ │ │ └── nes@3x.png │ │ │ ├── snes.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── snes.png │ │ │ │ ├── snes@2x.png │ │ │ │ └── snes@3x.png │ │ │ ├── spectrum.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── spectrum.png │ │ │ │ ├── spectrum@2x.png │ │ │ │ └── spectrum@3x.png │ │ │ └── turbografx.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── turbografx.png │ │ │ │ ├── turbografx@2x.png │ │ │ │ └── turbografx@3x.png │ │ ├── Contents.json │ │ ├── placeholder-art.imageset │ │ │ ├── Contents.json │ │ │ ├── placeholder-note.png │ │ │ ├── placeholder-note@2x.png │ │ │ └── placeholder-note@3x.png │ │ └── placeholder-playlist.imageset │ │ │ ├── Contents.json │ │ │ ├── new_playlist@1x.png │ │ │ ├── new_playlist@2x.png │ │ │ └── new_playlist@3x.png │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── BlurView.swift │ ├── Engine │ │ ├── AudioEngine.h │ │ ├── AudioEngine.m │ │ ├── FileEngine.h │ │ ├── FileEngine.m │ │ ├── Square Wave-Bridging-Header.h │ │ └── gme │ │ │ ├── Ay_Apu.cpp │ │ │ ├── Ay_Apu.h │ │ │ ├── Ay_Cpu.cpp │ │ │ ├── Ay_Cpu.h │ │ │ ├── Ay_Emu.cpp │ │ │ ├── Ay_Emu.h │ │ │ ├── Blip_Buffer.cpp │ │ │ ├── Blip_Buffer.h │ │ │ ├── Classic_Emu.cpp │ │ │ ├── Classic_Emu.h │ │ │ ├── Data_Reader.cpp │ │ │ ├── Data_Reader.h │ │ │ ├── Dual_Resampler.cpp │ │ │ ├── Dual_Resampler.h │ │ │ ├── Effects_Buffer.cpp │ │ │ ├── Effects_Buffer.h │ │ │ ├── Fir_Resampler.cpp │ │ │ ├── Fir_Resampler.h │ │ │ ├── Gb_Apu.cpp │ │ │ ├── Gb_Apu.h │ │ │ ├── Gb_Cpu.cpp │ │ │ ├── Gb_Cpu.h │ │ │ ├── Gb_Oscs.cpp │ │ │ ├── Gb_Oscs.h │ │ │ ├── Gbs_Emu.cpp │ │ │ ├── Gbs_Emu.h │ │ │ ├── Gme_File.cpp │ │ │ ├── Gme_File.h │ │ │ ├── Gym_Emu.cpp │ │ │ ├── Gym_Emu.h │ │ │ ├── Hes_Apu.cpp │ │ │ ├── Hes_Apu.h │ │ │ ├── Hes_Cpu.cpp │ │ │ ├── Hes_Cpu.h │ │ │ ├── Hes_Emu.cpp │ │ │ ├── Hes_Emu.h │ │ │ ├── Kss_Cpu.cpp │ │ │ ├── Kss_Cpu.h │ │ │ ├── Kss_Emu.cpp │ │ │ ├── Kss_Emu.h │ │ │ ├── Kss_Scc_Apu.cpp │ │ │ ├── Kss_Scc_Apu.h │ │ │ ├── M3u_Playlist.cpp │ │ │ ├── M3u_Playlist.h │ │ │ ├── Multi_Buffer.cpp │ │ │ ├── Multi_Buffer.h │ │ │ ├── Music_Emu.cpp │ │ │ ├── Music_Emu.h │ │ │ ├── Nes_Apu.cpp │ │ │ ├── Nes_Apu.h │ │ │ ├── Nes_Cpu.cpp │ │ │ ├── Nes_Cpu.h │ │ │ ├── Nes_Fme7_Apu.cpp │ │ │ ├── Nes_Fme7_Apu.h │ │ │ ├── Nes_Namco_Apu.cpp │ │ │ ├── Nes_Namco_Apu.h │ │ │ ├── Nes_Oscs.cpp │ │ │ ├── Nes_Oscs.h │ │ │ ├── Nes_Vrc6_Apu.cpp │ │ │ ├── Nes_Vrc6_Apu.h │ │ │ ├── Nsf_Emu.cpp │ │ │ ├── Nsf_Emu.h │ │ │ ├── Nsfe_Emu.cpp │ │ │ ├── Nsfe_Emu.h │ │ │ ├── Sap_Apu.cpp │ │ │ ├── Sap_Apu.h │ │ │ ├── Sap_Cpu.cpp │ │ │ ├── Sap_Cpu.h │ │ │ ├── Sap_Emu.cpp │ │ │ ├── Sap_Emu.h │ │ │ ├── Sms_Apu.cpp │ │ │ ├── Sms_Apu.h │ │ │ ├── Sms_Oscs.h │ │ │ ├── Snes_Spc.cpp │ │ │ ├── Snes_Spc.h │ │ │ ├── Spc_Cpu.cpp │ │ │ ├── Spc_Cpu.h │ │ │ ├── Spc_Dsp.cpp │ │ │ ├── Spc_Dsp.h │ │ │ ├── Spc_Emu.cpp │ │ │ ├── Spc_Emu.h │ │ │ ├── Spc_Filter.cpp │ │ │ ├── Spc_Filter.h │ │ │ ├── Vgm_Emu.cpp │ │ │ ├── Vgm_Emu.h │ │ │ ├── Vgm_Emu_Impl.cpp │ │ │ ├── Vgm_Emu_Impl.h │ │ │ ├── Ym2413_Emu.cpp │ │ │ ├── Ym2413_Emu.h │ │ │ ├── Ym2612_Emu.h │ │ │ ├── Ym2612_GENS.cpp │ │ │ ├── Ym2612_GENS.h │ │ │ ├── Ym2612_MAME.cpp │ │ │ ├── Ym2612_MAME.h │ │ │ ├── Ym2612_Nuked.cpp │ │ │ ├── Ym2612_Nuked.h │ │ │ ├── blargg_common.h │ │ │ ├── blargg_config.h │ │ │ ├── blargg_endian.h │ │ │ ├── blargg_source.h │ │ │ ├── gb_cpu_io.h │ │ │ ├── gme.cpp │ │ │ ├── gme.h │ │ │ ├── gme_types.h │ │ │ ├── hes_cpu_io.h │ │ │ ├── nes_cpu_io.h │ │ │ └── sap_cpu_io.h │ ├── FilePicker.swift │ ├── GamesView.swift │ ├── GoogleService-Info.plist │ ├── IAPManager.swift │ ├── IAP_ProductIDs.plist │ ├── Info.plist │ ├── LibraryView.swift │ ├── ListArtView.swift │ ├── ListSectionIndexView.swift │ ├── Main.storyboard │ ├── NewPlaylistView.swift │ ├── NowPlayingMiniView.swift │ ├── NowPlayingView.swift │ ├── PlatformsView.swift │ ├── PlaybackState.swift │ ├── PlaylistView.swift │ ├── PlaylistsView.swift │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── Receipts │ │ ├── AppleIncRootCertificate.cer │ │ ├── ReceiptFetcher.swift │ │ ├── SwiftyLocalReceiptValidator.swift │ │ ├── pkcs7_union_accessors.c │ │ └── pkcs7_union_accessors.h │ ├── RootViewController.swift │ ├── SceneDelegate.swift │ ├── SettingsView.swift │ ├── SongTableViewCell.swift │ ├── SongTableViewCell.xib │ ├── SongsView.swift │ ├── Square Wave.entitlements │ ├── Square_Wave.xcdatamodeld │ │ └── Model.xcdatamodel │ │ │ └── contents │ ├── TextView.swift │ ├── UIListView.swift │ ├── Util.swift │ ├── VisualEffectView.swift │ ├── en.lproj │ │ └── Localizable.strings │ └── fr-CA.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Localizable.strings ├── Square WaveTests │ ├── Info.plist │ └── Square_WaveTests.swift ├── Square WaveUITests │ ├── Info.plist │ └── Square_WaveUITests.swift ├── Square Waves.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── Square Wave.xcscheme │ └── xcuserdata │ │ └── abusman.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── Square Waves.xcworkspace │ └── contents.xcworkspacedata └── privacy_policy.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.xcuserstate 3 | *.nsf 4 | -------------------------------------------------------------------------------- /Square Wave/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :ios, '13' 3 | 4 | target 'Square Waves' do 5 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for Square Waves 9 | pod 'SSZipArchive' 10 | pod 'UnrarKit' 11 | pod 'LzmaSDK-ObjC', :inhibit_warnings => true 12 | pod 'Firebase/Analytics' 13 | pod 'Firebase/Crashlytics' 14 | pod 'openssl-ios-bitcode' 15 | end 16 | -------------------------------------------------------------------------------- /Square Wave/Square Wave.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Square Wave/Square Wave.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Square Wave/Square Wave.xcworkspace/xcuserdata/abusman.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/ArtistsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArtistsView.swift 3 | // Square Waves 4 | // 5 | // Created by Alex Busman on 8/8/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ArtistsView: View { 12 | @FetchRequest(entity: Artist.entity(), sortDescriptors: []) var artists: FetchedResults 13 | 14 | var body: some View { 15 | UIListView(rows: Binding(get: { 16 | Array(self.artists) 17 | }, set: { _ in 18 | 19 | }), 20 | sortType: Binding(get: { 21 | SortType.title.rawValue 22 | }, set: { _ in 23 | 24 | }), isEditing: .constant(false), rowType: Artist.self, keypaths: UIListViewCellKeypaths(title: \Artist.name), showSearch: false, showsHeader: false) 25 | .navigationBarTitle(Text(NSLocalizedString("Artists", comment: "Artists")), displayMode: .inline) 26 | .edgesIgnoringSafeArea(.vertical) 27 | } 28 | } 29 | 30 | struct ArtistsView_Previews: PreviewProvider { 31 | static var previews: some View { 32 | ArtistsView() 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "icon20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "icon20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "icon29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "icon29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "icon40x40@2x-1.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "icon60x60@2x-1.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "icon60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "icon60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "icon20x20.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "icon20x20@2x-2.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "icon29x29.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "icon29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "icon20x20@2x-1.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "icon40x40@2x.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "icon76x76.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "icon76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "icon83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "itunes-icon.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20@2x-1.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20@2x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20@2x-2.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon20x20@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon29x29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon29x29.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon29x29@2x-1.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon29x29@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon29x29@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon40x40@2x-1.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon40x40@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon60x60@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon60x60@2x-1.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon60x60@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon60x60@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon76x76.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon76x76@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/icon83.5x83.5@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/itunes-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/AppIcon.appiconset/itunes-icon.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/atari.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "atari.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "atari@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "atari@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/atari.imageset/atari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/atari.imageset/atari.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/atari.imageset/atari@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/atari.imageset/atari@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/atari.imageset/atari@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/atari.imageset/atari@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/gameboy.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "gameboy.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "gameboy@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "gameboy@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/gameboy.imageset/gameboy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/gameboy.imageset/gameboy.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/gameboy.imageset/gameboy@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/gameboy.imageset/gameboy@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/gameboy.imageset/gameboy@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/gameboy.imageset/gameboy@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/master-system.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "master-system.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "master-system@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "master-system@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/master-system.imageset/master-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/master-system.imageset/master-system.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/master-system.imageset/master-system@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/master-system.imageset/master-system@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/master-system.imageset/master-system@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/master-system.imageset/master-system@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/megadrive.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "megadrive.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "megadrive@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "megadrive@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/megadrive.imageset/megadrive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/megadrive.imageset/megadrive.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/megadrive.imageset/megadrive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/megadrive.imageset/megadrive@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/megadrive.imageset/megadrive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/megadrive.imageset/megadrive@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/msx.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "msx.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "msx@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "msx@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/msx.imageset/msx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/msx.imageset/msx.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/msx.imageset/msx@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/msx.imageset/msx@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/msx.imageset/msx@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/msx.imageset/msx@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/nes.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "nes.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "nes@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "nes@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/nes.imageset/nes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/nes.imageset/nes.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/nes.imageset/nes@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/nes.imageset/nes@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/nes.imageset/nes@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/nes.imageset/nes@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/snes.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "snes.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "snes@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "snes@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/snes.imageset/snes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/snes.imageset/snes.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/snes.imageset/snes@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/snes.imageset/snes@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/snes.imageset/snes@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/snes.imageset/snes@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/spectrum.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "spectrum.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "spectrum@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "spectrum@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/spectrum.imageset/spectrum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/spectrum.imageset/spectrum.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/spectrum.imageset/spectrum@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/spectrum.imageset/spectrum@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/spectrum.imageset/spectrum@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/spectrum.imageset/spectrum@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/turbografx.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "turbografx.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "turbografx@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "turbografx@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/turbografx.imageset/turbografx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/turbografx.imageset/turbografx.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/turbografx.imageset/turbografx@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/turbografx.imageset/turbografx@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Consoles/turbografx.imageset/turbografx@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/Consoles/turbografx.imageset/turbografx@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/placeholder-art.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "placeholder-note.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "placeholder-note@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "placeholder-note@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/placeholder-art.imageset/placeholder-note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/placeholder-art.imageset/placeholder-note.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/placeholder-art.imageset/placeholder-note@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/placeholder-art.imageset/placeholder-note@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/placeholder-art.imageset/placeholder-note@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/placeholder-art.imageset/placeholder-note@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/placeholder-playlist.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "new_playlist@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "new_playlist@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "new_playlist@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "original" 25 | } 26 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/placeholder-playlist.imageset/new_playlist@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/placeholder-playlist.imageset/new_playlist@1x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/placeholder-playlist.imageset/new_playlist@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/placeholder-playlist.imageset/new_playlist@2x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Assets.xcassets/placeholder-playlist.imageset/new_playlist@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Assets.xcassets/placeholder-playlist.imageset/new_playlist@3x.png -------------------------------------------------------------------------------- /Square Wave/Square Wave/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/AudioEngine.h: -------------------------------------------------------------------------------- 1 | // 2 | // AudioEngine.h 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 5/6/18. 6 | // Copyright © 2018 Alex Busman. All rights reserved. 7 | // 8 | 9 | #ifndef AudioEngine_h 10 | #define AudioEngine_h 11 | 12 | #import 13 | 14 | @class AppDelegate; 15 | 16 | @interface TrackInfo : NSObject 17 | 18 | @property NSString *title; 19 | @property NSString *artist; 20 | @property NSString *system; 21 | @property NSString *game; 22 | @property int play_length; 23 | @property int length; 24 | @property int intro_length; 25 | @property int loop_length; 26 | @end 27 | 28 | @interface AudioEngine : NSObject 29 | 30 | + (AudioEngine *)sharedInstance; 31 | - (void)setFileName:(NSString *)fileName; 32 | - (void)setTrack:(int)track; 33 | - (void)setMuteVoices:(int)mask; 34 | - (int)getVoiceCount; 35 | - (const char *)getVoiceName:(int)index; 36 | - (void)play; 37 | - (void)pause; 38 | - (void)stop; 39 | - (void)nextTrack; 40 | - (void)prevTrack; 41 | - (TrackInfo *)getCurrentTrackInfo; 42 | - (int)getElapsedTime; 43 | - (BOOL)getTrackEnded; 44 | - (void)fadeOutCurrentTrack; 45 | - (void)setFadeTime:(int)msec; 46 | - (void)setTempo:(double)tempo; 47 | - (void)ignoreSilence; 48 | - (void)resetFadeTime; 49 | 50 | @end 51 | #endif /* AudioEngine_h */ 52 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/FileEngine.h: -------------------------------------------------------------------------------- 1 | // 2 | // FileEngine.h 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 5/8/18. 6 | // Copyright © 2018 Alex Busman. All rights reserved. 7 | // 8 | 9 | #define __DEBUG_FILE_ENGINE 10 | 11 | #if defined(__DEBUG_FILE_ENGINE) 12 | #define __DEBUG_FE(m, ...) NSLog((m), __VA_ARGS__) 13 | #else 14 | #define __DEBUG_FE(m, ...) 15 | #endif 16 | 17 | @class AppDelegate; 18 | @class Track; 19 | @class Game; 20 | @class System; 21 | @class Song; 22 | @class Artist; 23 | 24 | @protocol FileEngineDelegate 25 | - (void)progress:(NSUInteger)currentIndex total:(NSUInteger)total; 26 | - (void)complete; 27 | - (void)failed:(NSError *_Nonnull)error; 28 | @end 29 | 30 | @interface FileEngine : NSObject 31 | + (BOOL) removeGame:(Game *_Nonnull)game; 32 | + (BOOL) removeTrack:(Track *_Nonnull)track; 33 | + (void) reloadFromCloudWith:(id_Nonnull)delegate; 34 | + (BOOL) addFile:(nonnull NSURL *)url removeOriginal:(BOOL)removeOriginal; 35 | + (void) refreshDatabase; 36 | + (NSString *_Nonnull) getMusicDirectory; 37 | + (BOOL) clearAll; 38 | + (BOOL) clearDatabase; 39 | @end 40 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/Square Wave-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #include "pkcs7_union_accessors.h" 6 | #import "AudioEngine.h" 7 | #import "FileEngine.h" 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ay_Apu.h: -------------------------------------------------------------------------------- 1 | // AY-3-8910 sound chip emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef AY_APU_H 5 | #define AY_APU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | class Ay_Apu { 11 | public: 12 | // Set buffer to generate all sound into, or disable sound if NULL 13 | void output( Blip_Buffer* ); 14 | 15 | // Reset sound chip 16 | void reset(); 17 | 18 | // Write to register at specified time 19 | enum { reg_count = 16 }; 20 | void write( blip_time_t time, int addr, int data ); 21 | 22 | // Run sound to specified time, end current time frame, then start a new 23 | // time frame at time 0. Time frames have no effect on emulation and each 24 | // can be whatever length is convenient. 25 | void end_frame( blip_time_t length ); 26 | 27 | // Additional features 28 | 29 | // Set sound output of specific oscillator to buffer, where index is 30 | // 0, 1, or 2. If buffer is NULL, the specified oscillator is muted. 31 | enum { osc_count = 3 }; 32 | void osc_output( int index, Blip_Buffer* ); 33 | 34 | // Set overall volume (default is 1.0) 35 | void volume( double ); 36 | 37 | // Set treble equalization (see documentation) 38 | void treble_eq( blip_eq_t const& ); 39 | 40 | public: 41 | Ay_Apu(); 42 | typedef unsigned char byte; 43 | private: 44 | struct osc_t 45 | { 46 | blip_time_t period; 47 | blip_time_t delay; 48 | short last_amp; 49 | short phase; 50 | Blip_Buffer* output; 51 | } oscs [osc_count]; 52 | blip_time_t last_time; 53 | byte regs [reg_count]; 54 | 55 | struct { 56 | blip_time_t delay; 57 | blargg_ulong lfsr; 58 | } noise; 59 | 60 | struct { 61 | blip_time_t delay; 62 | byte const* wave; 63 | int pos; 64 | byte modes [8] [48]; // values already passed through volume table 65 | } env; 66 | 67 | void run_until( blip_time_t ); 68 | void write_data_( int addr, int data ); 69 | public: 70 | enum { amp_range = 255 }; 71 | Blip_Synth synth_; 72 | }; 73 | 74 | inline void Ay_Apu::volume( double v ) { synth_.volume( 0.7 / osc_count / amp_range * v ); } 75 | 76 | inline void Ay_Apu::treble_eq( blip_eq_t const& eq ) { synth_.treble_eq( eq ); } 77 | 78 | inline void Ay_Apu::write( blip_time_t time, int addr, int data ) 79 | { 80 | run_until( time ); 81 | write_data_( addr, data ); 82 | } 83 | 84 | inline void Ay_Apu::osc_output( int i, Blip_Buffer* buf ) 85 | { 86 | assert( (unsigned) i < osc_count ); 87 | oscs [i].output = buf; 88 | } 89 | 90 | inline void Ay_Apu::output( Blip_Buffer* buf ) 91 | { 92 | osc_output( 0, buf ); 93 | osc_output( 1, buf ); 94 | osc_output( 2, buf ); 95 | } 96 | 97 | inline void Ay_Apu::end_frame( blip_time_t time ) 98 | { 99 | if ( time > last_time ) 100 | run_until( time ); 101 | 102 | assert( last_time >= time ); 103 | last_time -= time; 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ay_Cpu.h: -------------------------------------------------------------------------------- 1 | // Z80 CPU emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef AY_CPU_H 5 | #define AY_CPU_H 6 | 7 | #include "blargg_endian.h" 8 | 9 | typedef blargg_long cpu_time_t; 10 | 11 | // must be defined by caller 12 | void ay_cpu_out( class Ay_Cpu*, cpu_time_t, unsigned addr, int data ); 13 | int ay_cpu_in( class Ay_Cpu*, unsigned addr ); 14 | 15 | class Ay_Cpu { 16 | public: 17 | // Clear all registers and keep pointer to 64K memory passed in 18 | void reset( void* mem_64k ); 19 | 20 | // Run until specified time is reached. Returns true if suspicious/unsupported 21 | // instruction was encountered at any point during run. 22 | bool run( cpu_time_t end_time ); 23 | 24 | // Time of beginning of next instruction 25 | cpu_time_t time() const { return state->time + state->base; } 26 | 27 | // Alter current time. Not supported during run() call. 28 | void set_time( cpu_time_t t ) { state->time = t - state->base; } 29 | void adjust_time( int delta ) { state->time += delta; } 30 | 31 | #if BLARGG_BIG_ENDIAN 32 | struct regs_t { uint8_t b, c, d, e, h, l, flags, a; }; 33 | #else 34 | struct regs_t { uint8_t c, b, e, d, l, h, a, flags; }; 35 | #endif 36 | BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 ); 37 | 38 | struct pairs_t { uint16_t bc, de, hl, fa; }; 39 | 40 | // Registers are not updated until run() returns 41 | struct registers_t { 42 | uint16_t pc; 43 | uint16_t sp; 44 | uint16_t ix; 45 | uint16_t iy; 46 | union { 47 | regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a 48 | pairs_t w; // w.bc, w.de, w.hl. w.fa 49 | }; 50 | union { 51 | regs_t b; 52 | pairs_t w; 53 | } alt; 54 | uint8_t iff1; 55 | uint8_t iff2; 56 | uint8_t r; 57 | uint8_t i; 58 | uint8_t im; 59 | }; 60 | //registers_t r; (below for efficiency) 61 | 62 | // can read this far past end of memory 63 | enum { cpu_padding = 0x100 }; 64 | 65 | public: 66 | Ay_Cpu(); 67 | private: 68 | uint8_t szpc [0x200]; 69 | uint8_t* mem; 70 | cpu_time_t end_time_; 71 | struct state_t { 72 | cpu_time_t base; 73 | cpu_time_t time; 74 | }; 75 | state_t* state; // points to state_ or a local copy within run() 76 | state_t state_; 77 | void set_end_time( cpu_time_t t ); 78 | public: 79 | registers_t r; 80 | }; 81 | 82 | inline void Ay_Cpu::set_end_time( cpu_time_t t ) 83 | { 84 | cpu_time_t delta = state->base - t; 85 | state->base = t; 86 | state->time += delta; 87 | } 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ay_Emu.h: -------------------------------------------------------------------------------- 1 | // Sinclair Spectrum AY music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef AY_EMU_H 5 | #define AY_EMU_H 6 | 7 | #include "Classic_Emu.h" 8 | #include "Ay_Apu.h" 9 | #include "Ay_Cpu.h" 10 | 11 | class Ay_Emu : private Ay_Cpu, public Classic_Emu { 12 | typedef Ay_Cpu cpu; 13 | public: 14 | // AY file header 15 | enum { header_size = 0x14 }; 16 | struct header_t 17 | { 18 | byte tag [8]; 19 | byte vers; 20 | byte player; 21 | byte unused [2]; 22 | byte author [2]; 23 | byte comment [2]; 24 | byte max_track; 25 | byte first_track; 26 | byte track_info [2]; 27 | }; 28 | 29 | static gme_type_t static_type() { return gme_ay_type; } 30 | public: 31 | Ay_Emu(); 32 | ~Ay_Emu(); 33 | struct file_t { 34 | header_t const* header; 35 | byte const* end; 36 | byte const* tracks; 37 | }; 38 | protected: 39 | blargg_err_t track_info_( track_info_t*, int track ) const; 40 | blargg_err_t load_mem_( byte const*, long ); 41 | blargg_err_t start_track_( int ); 42 | blargg_err_t run_clocks( blip_time_t&, int ); 43 | void set_tempo_( double ); 44 | void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); 45 | void update_eq( blip_eq_t const& ); 46 | private: 47 | file_t file; 48 | 49 | cpu_time_t play_period; 50 | cpu_time_t next_play; 51 | Blip_Buffer* beeper_output; 52 | int beeper_delta; 53 | int last_beeper; 54 | int apu_addr; 55 | int cpc_latch; 56 | bool spectrum_mode; 57 | bool cpc_mode; 58 | 59 | // large items 60 | struct { 61 | byte padding1 [0x100]; 62 | byte ram [0x10000 + 0x100]; 63 | } mem; 64 | Ay_Apu apu; 65 | friend void ay_cpu_out( Ay_Cpu*, cpu_time_t, unsigned addr, int data ); 66 | void cpu_out_misc( cpu_time_t, unsigned addr, int data ); 67 | }; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Classic_Emu.h: -------------------------------------------------------------------------------- 1 | // Common aspects of emulators which use Blip_Buffer for sound output 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef CLASSIC_EMU_H 5 | #define CLASSIC_EMU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | #include "Music_Emu.h" 10 | 11 | class Classic_Emu : public Music_Emu { 12 | public: 13 | Classic_Emu(); 14 | ~Classic_Emu(); 15 | void set_buffer( Multi_Buffer* ); 16 | blargg_err_t set_multi_channel( bool is_enabled ) override; 17 | protected: 18 | // Services 19 | enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type }; 20 | void set_voice_types( int const* t ) { voice_types = t; } 21 | blargg_err_t setup_buffer( long clock_rate ); 22 | long clock_rate() const { return clock_rate_; } 23 | void change_clock_rate( long ); // experimental 24 | 25 | // Overridable 26 | virtual void set_voice( int index, Blip_Buffer* center, 27 | Blip_Buffer* left, Blip_Buffer* right ) = 0; 28 | virtual void update_eq( blip_eq_t const& ) = 0; 29 | virtual blargg_err_t start_track_( int track ) = 0; 30 | virtual blargg_err_t run_clocks( blip_time_t& time_io, int msec ) = 0; 31 | protected: 32 | blargg_err_t set_sample_rate_( long sample_rate ); 33 | void mute_voices_( int ); 34 | void set_equalizer_( equalizer_t const& ); 35 | blargg_err_t play_( long, sample_t* ); 36 | private: 37 | Multi_Buffer* buf; 38 | Multi_Buffer* stereo_buffer; // NULL if using custom buffer 39 | long clock_rate_; 40 | unsigned buf_changed_count; 41 | int const* voice_types; 42 | }; 43 | 44 | inline void Classic_Emu::set_buffer( Multi_Buffer* new_buf ) 45 | { 46 | assert( !buf && new_buf ); 47 | buf = new_buf; 48 | } 49 | 50 | // ROM data handler, used by several Classic_Emu derivitives. Loads file data 51 | // with padding on both sides, allowing direct use in bank mapping. The main purpose 52 | // is to allow all file data to be loaded with only one read() call (for efficiency). 53 | 54 | class Rom_Data_ { 55 | public: 56 | typedef unsigned char byte; 57 | protected: 58 | enum { pad_extra = 8 }; 59 | blargg_vector rom; 60 | long file_size_; 61 | blargg_long rom_addr; 62 | blargg_long mask; 63 | blargg_long size_; // TODO: eliminate 64 | 65 | blargg_err_t load_rom_data_( Data_Reader& in, int header_size, void* header_out, 66 | int fill, long pad_size ); 67 | void set_addr_( long addr, int unit ); 68 | }; 69 | 70 | template 71 | class Rom_Data : public Rom_Data_ { 72 | enum { pad_size = unit + pad_extra }; 73 | public: 74 | // Load file data, using already-loaded header 'h' if not NULL. Copy header 75 | // from loaded file data into *out and fill unmapped bytes with 'fill'. 76 | blargg_err_t load( Data_Reader& in, int header_size, void* header_out, int fill ) 77 | { 78 | return load_rom_data_( in, header_size, header_out, fill, pad_size ); 79 | } 80 | 81 | // Size of file data read in (excluding header) 82 | long file_size() const { return file_size_; } 83 | 84 | // Pointer to beginning of file data 85 | byte* begin() const { return rom.begin() + pad_size; } 86 | 87 | // Set address that file data should start at 88 | void set_addr( long addr ) { set_addr_( addr, unit ); } 89 | 90 | // Free data 91 | void clear() { rom.clear(); } 92 | 93 | // Size of data + start addr, rounded to a multiple of unit 94 | long size() const { return size_; } 95 | 96 | // Pointer to unmapped page filled with same value 97 | byte* unmapped() { return rom.begin(); } 98 | 99 | // Mask address to nearest power of two greater than size() 100 | blargg_long mask_addr( blargg_long addr ) const 101 | { 102 | #ifdef check 103 | check( addr <= mask ); 104 | #endif 105 | return addr & mask; 106 | } 107 | 108 | // Pointer to page starting at addr. Returns unmapped() if outside data. 109 | byte* at_addr( blargg_long addr ) 110 | { 111 | blargg_ulong offset = mask_addr( addr ) - rom_addr; 112 | if ( offset > blargg_ulong (rom.size() - pad_size) ) 113 | offset = 0; // unmapped 114 | return &rom [offset]; 115 | } 116 | }; 117 | 118 | #ifndef GME_APU_HOOK 119 | #define GME_APU_HOOK( emu, addr, data ) ((void) 0) 120 | #endif 121 | 122 | #ifndef GME_FRAME_HOOK 123 | #define GME_FRAME_HOOK( emu ) ((void) 0) 124 | #else 125 | #define GME_FRAME_HOOK_DEFINED 1 126 | #endif 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Data_Reader.h: -------------------------------------------------------------------------------- 1 | // Data reader interface for uniform access 2 | 3 | // File_Extractor 0.4.0 4 | #ifndef DATA_READER_H 5 | #define DATA_READER_H 6 | 7 | #include "blargg_common.h" 8 | 9 | #ifdef HAVE_ZLIB_H 10 | #include 11 | #endif 12 | 13 | // Supports reading and finding out how many bytes are remaining 14 | class Data_Reader { 15 | public: 16 | virtual ~Data_Reader() { } 17 | 18 | static const char eof_error []; // returned by read() when request goes beyond end 19 | 20 | // Read at most count bytes and return number actually read, or <= 0 if error 21 | virtual long read_avail( void*, long n ) = 0; 22 | 23 | // Read exactly count bytes and return error if they couldn't be read 24 | virtual blargg_err_t read( void*, long count ); 25 | 26 | // Number of bytes remaining until end of file 27 | virtual long remain() const = 0; 28 | 29 | // Read and discard count bytes 30 | virtual blargg_err_t skip( long count ); 31 | 32 | public: 33 | Data_Reader() { } 34 | typedef blargg_err_t error_t; // deprecated 35 | private: 36 | // noncopyable 37 | Data_Reader( const Data_Reader& ); 38 | Data_Reader& operator = ( const Data_Reader& ); 39 | }; 40 | 41 | // Supports seeking in addition to Data_Reader operations 42 | class File_Reader : public Data_Reader { 43 | public: 44 | // Size of file 45 | virtual long size() const = 0; 46 | 47 | // Current position in file 48 | virtual long tell() const = 0; 49 | 50 | // Go to new position 51 | virtual blargg_err_t seek( long ) = 0; 52 | 53 | long remain() const; 54 | blargg_err_t skip( long n ); 55 | }; 56 | 57 | // Disk file reader 58 | class Std_File_Reader : public File_Reader { 59 | public: 60 | blargg_err_t open( const char* path ); 61 | void close(); 62 | 63 | public: 64 | Std_File_Reader(); 65 | ~Std_File_Reader(); 66 | long size() const; 67 | blargg_err_t read( void*, long ); 68 | long read_avail( void*, long ); 69 | long tell() const; 70 | blargg_err_t seek( long ); 71 | private: 72 | void* file_; // Either FILE* or zlib's gzFile 73 | #ifdef HAVE_ZLIB_H 74 | long size_; // TODO: Fix ABI compat 75 | #endif /* HAVE_ZLIB_H */ 76 | }; 77 | 78 | // Treats range of memory as a file 79 | class Mem_File_Reader : public File_Reader { 80 | public: 81 | Mem_File_Reader( const void*, long size ); 82 | #ifdef HAVE_ZLIB_H 83 | ~Mem_File_Reader( ); 84 | #endif /* HAVE_ZLIB_H */ 85 | 86 | public: 87 | long size() const; 88 | long read_avail( void*, long ); 89 | long tell() const; 90 | blargg_err_t seek( long ); 91 | private: 92 | #ifdef HAVE_ZLIB_H 93 | bool gz_decompress(); 94 | #endif /* HAVE_ZLIB_H */ 95 | 96 | const char* m_begin; 97 | long m_size; 98 | long m_pos; 99 | #ifdef HAVE_ZLIB_H 100 | bool m_ownedPtr = false; // set if we must free m_begin 101 | #endif /* HAVE_ZLIB_H */ 102 | }; 103 | 104 | 105 | // Makes it look like there are only count bytes remaining 106 | class Subset_Reader : public Data_Reader { 107 | public: 108 | Subset_Reader( Data_Reader*, long count ); 109 | 110 | public: 111 | long remain() const; 112 | long read_avail( void*, long ); 113 | private: 114 | Data_Reader* in; 115 | long remain_; 116 | }; 117 | 118 | // Joins already-read header and remaining data into original file (to avoid seeking) 119 | class Remaining_Reader : public Data_Reader { 120 | public: 121 | Remaining_Reader( void const* header, long size, Data_Reader* ); 122 | 123 | public: 124 | long remain() const; 125 | long read_avail( void*, long ); 126 | blargg_err_t read( void*, long ); 127 | private: 128 | char const* header; 129 | char const* header_end; 130 | Data_Reader* in; 131 | long read_first( void* out, long count ); 132 | }; 133 | 134 | // Invokes callback function to read data. Size of data must be specified in advance. 135 | class Callback_Reader : public Data_Reader { 136 | public: 137 | typedef const char* (*callback_t)( void* data, void* out, int count ); 138 | Callback_Reader( callback_t, long size, void* data = 0 ); 139 | public: 140 | long read_avail( void*, long ); 141 | blargg_err_t read( void*, long ); 142 | long remain() const; 143 | private: 144 | callback_t const callback; 145 | void* const data; 146 | long remain_; 147 | }; 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Dual_Resampler.cpp: -------------------------------------------------------------------------------- 1 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 2 | 3 | #include "Dual_Resampler.h" 4 | 5 | #include 6 | #include 7 | 8 | /* Copyright (C) 2003-2006 Shay Green. This module is free software; you 9 | can redistribute it and/or modify it under the terms of the GNU Lesser 10 | General Public License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. This 12 | module is distributed in the hope that it will be useful, but WITHOUT ANY 13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | details. You should have received a copy of the GNU Lesser General Public 16 | License along with this module; if not, write to the Free Software Foundation, 17 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18 | 19 | #include "blargg_source.h" 20 | 21 | unsigned const resampler_extra = 256; 22 | 23 | Dual_Resampler::Dual_Resampler() : 24 | sample_buf_size(0), 25 | oversamples_per_frame(-1), 26 | buf_pos(-1), 27 | resampler_size(0) 28 | { 29 | } 30 | 31 | Dual_Resampler::~Dual_Resampler() { } 32 | 33 | blargg_err_t Dual_Resampler::reset( int pairs ) 34 | { 35 | // expand allocations a bit 36 | RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) ); 37 | resize( pairs ); 38 | resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2); 39 | return resampler.buffer_size( resampler_size ); 40 | } 41 | 42 | void Dual_Resampler::resize( int pairs ) 43 | { 44 | int new_sample_buf_size = pairs * 2; 45 | if ( sample_buf_size != new_sample_buf_size ) 46 | { 47 | if ( (unsigned) new_sample_buf_size > sample_buf.size() ) 48 | { 49 | check( false ); 50 | return; 51 | } 52 | sample_buf_size = new_sample_buf_size; 53 | oversamples_per_frame = int (pairs * resampler.ratio()) * 2 + 2; 54 | clear(); 55 | } 56 | } 57 | 58 | void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out ) 59 | { 60 | long pair_count = sample_buf_size >> 1; 61 | blip_time_t blip_time = blip_buf.count_clocks( pair_count ); 62 | int sample_count = oversamples_per_frame - resampler.written(); 63 | 64 | int new_count = play_frame( blip_time, sample_count, resampler.buffer() ); 65 | assert( new_count < resampler_size ); 66 | 67 | blip_buf.end_frame( blip_time ); 68 | assert( blip_buf.samples_avail() == pair_count ); 69 | 70 | resampler.write( new_count ); 71 | 72 | #ifdef NDEBUG // Avoid warning when asserts are disabled 73 | resampler.read( sample_buf.begin(), sample_buf_size ); 74 | #else 75 | long count = resampler.read( sample_buf.begin(), sample_buf_size ); 76 | assert( count == (long) sample_buf_size ); 77 | #endif 78 | 79 | mix_samples( blip_buf, out ); 80 | blip_buf.remove_samples( pair_count ); 81 | } 82 | 83 | void Dual_Resampler::dual_play( long count, dsample_t* out, Blip_Buffer& blip_buf ) 84 | { 85 | // empty extra buffer 86 | long remain = sample_buf_size - buf_pos; 87 | if ( remain ) 88 | { 89 | if ( remain > count ) 90 | remain = count; 91 | count -= remain; 92 | memcpy( out, &sample_buf [buf_pos], remain * sizeof *out ); 93 | out += remain; 94 | buf_pos += remain; 95 | } 96 | 97 | // entire frames 98 | while ( count >= (long) sample_buf_size ) 99 | { 100 | play_frame_( blip_buf, out ); 101 | out += sample_buf_size; 102 | count -= sample_buf_size; 103 | } 104 | 105 | // extra 106 | if ( count ) 107 | { 108 | play_frame_( blip_buf, sample_buf.begin() ); 109 | buf_pos = count; 110 | memcpy( out, sample_buf.begin(), count * sizeof *out ); 111 | out += count; 112 | } 113 | } 114 | 115 | void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out ) 116 | { 117 | Blip_Reader sn; 118 | int bass = sn.begin( blip_buf ); 119 | const dsample_t* in = sample_buf.begin(); 120 | 121 | for ( int n = sample_buf_size >> 1; n--; ) 122 | { 123 | int s = sn.read(); 124 | blargg_long l = (blargg_long) in [0] * 2 + s; 125 | if ( (int16_t) l != l ) 126 | l = 0x7FFF - (l >> 24); 127 | 128 | sn.next( bass ); 129 | blargg_long r = (blargg_long) in [1] * 2 + s; 130 | if ( (int16_t) r != r ) 131 | r = 0x7FFF - (r >> 24); 132 | 133 | in += 2; 134 | out [0] = l; 135 | out [1] = r; 136 | out += 2; 137 | } 138 | 139 | sn.end( blip_buf ); 140 | } 141 | 142 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Dual_Resampler.h: -------------------------------------------------------------------------------- 1 | // Combination of Fir_Resampler and Blip_Buffer mixing. Used by Sega FM emulators. 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef DUAL_RESAMPLER_H 5 | #define DUAL_RESAMPLER_H 6 | 7 | #include "Fir_Resampler.h" 8 | #include "Blip_Buffer.h" 9 | 10 | class Dual_Resampler { 11 | public: 12 | Dual_Resampler(); 13 | virtual ~Dual_Resampler(); 14 | 15 | typedef short dsample_t; 16 | 17 | double setup( double oversample, double rolloff, double gain ); 18 | blargg_err_t reset( int max_pairs ); 19 | void resize( int pairs_per_frame ); 20 | void clear(); 21 | 22 | void dual_play( long count, dsample_t* out, Blip_Buffer& ); 23 | 24 | protected: 25 | virtual int play_frame( blip_time_t, int pcm_count, dsample_t* pcm_out ) = 0; 26 | private: 27 | 28 | blargg_vector sample_buf; 29 | int sample_buf_size; 30 | int oversamples_per_frame; 31 | int buf_pos; 32 | int resampler_size; 33 | 34 | Fir_Resampler<12> resampler; 35 | void mix_samples( Blip_Buffer&, dsample_t* ); 36 | void play_frame_( Blip_Buffer&, dsample_t* ); 37 | }; 38 | 39 | inline double Dual_Resampler::setup( double oversample, double rolloff, double gain ) 40 | { 41 | return resampler.time_ratio( oversample, rolloff, gain * 0.5 ); 42 | } 43 | 44 | inline void Dual_Resampler::clear() 45 | { 46 | buf_pos = sample_buf_size; 47 | resampler.clear(); 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Effects_Buffer.h: -------------------------------------------------------------------------------- 1 | // Multi-channel effects buffer with panning, echo and reverb 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef EFFECTS_BUFFER_H 5 | #define EFFECTS_BUFFER_H 6 | 7 | #include "Multi_Buffer.h" 8 | 9 | #include 10 | 11 | // Effects_Buffer uses several buffers and outputs stereo sample pairs. 12 | class Effects_Buffer : public Multi_Buffer { 13 | public: 14 | // nVoices indicates the number of voices for which buffers will be allocated 15 | // to make Effects_Buffer work as "mix everything to one", nVoices will be 1 16 | // If center_only is true, only center buffers are created and 17 | // less memory is used. 18 | Effects_Buffer( int nVoices = 1, bool center_only = false ); 19 | 20 | // Channel Effect Center Pan 21 | // --------------------------------- 22 | // 0,5 reverb pan_1 23 | // 1,6 reverb pan_2 24 | // 2,7 echo - 25 | // 3 echo - 26 | // 4 echo - 27 | 28 | // Channel configuration 29 | struct config_t { 30 | double pan_1; // -1.0 = left, 0.0 = center, 1.0 = right 31 | double pan_2; 32 | double echo_delay; // msec 33 | double echo_level; // 0.0 to 1.0 34 | double reverb_delay; // msec 35 | double delay_variance; // difference between left/right delays (msec) 36 | double reverb_level; // 0.0 to 1.0 37 | bool effects_enabled; // if false, use optimized simple mixer 38 | config_t(); 39 | }; 40 | 41 | // Set configuration of buffer 42 | virtual void config( const config_t& ); 43 | void set_depth( double ); 44 | 45 | public: 46 | ~Effects_Buffer(); 47 | blargg_err_t set_sample_rate( long samples_per_sec, int msec = blip_default_length ); 48 | void clock_rate( long ); 49 | void bass_freq( int ); 50 | void clear(); 51 | channel_t channel( int, int ); 52 | void end_frame( blip_time_t ); 53 | long read_samples( blip_sample_t*, long ); 54 | long samples_avail() const; 55 | private: 56 | typedef long fixed_t; 57 | int max_voices; 58 | enum { max_buf_count = 7 }; 59 | std::vector bufs; 60 | enum { chan_types_count = 3 }; 61 | std::vector chan_types; 62 | config_t config_; 63 | long stereo_remain; 64 | long effect_remain; 65 | int buf_count; 66 | bool effects_enabled; 67 | 68 | std::vector > reverb_buf; 69 | std::vector > echo_buf; 70 | std::vector reverb_pos; 71 | std::vector echo_pos; 72 | 73 | struct { 74 | fixed_t pan_1_levels [2]; 75 | fixed_t pan_2_levels [2]; 76 | int echo_delay_l; 77 | int echo_delay_r; 78 | fixed_t echo_level; 79 | int reverb_delay_l; 80 | int reverb_delay_r; 81 | fixed_t reverb_level; 82 | } chans; 83 | 84 | void mix_mono( blip_sample_t*, blargg_long ); 85 | void mix_stereo( blip_sample_t*, blargg_long ); 86 | void mix_enhanced( blip_sample_t*, blargg_long ); 87 | void mix_mono_enhanced( blip_sample_t*, blargg_long ); 88 | }; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Gb_Apu.h: -------------------------------------------------------------------------------- 1 | // Nintendo Game Boy PAPU sound chip emulator 2 | 3 | // Gb_Snd_Emu 0.1.5 4 | #ifndef GB_APU_H 5 | #define GB_APU_H 6 | 7 | #include "Gb_Oscs.h" 8 | 9 | class Gb_Apu { 10 | public: 11 | 12 | // Set overall volume of all oscillators, where 1.0 is full volume 13 | void volume( double ); 14 | 15 | // Set treble equalization 16 | void treble_eq( const blip_eq_t& ); 17 | 18 | // Outputs can be assigned to a single buffer for mono output, or to three 19 | // buffers for stereo output (using Stereo_Buffer to do the mixing). 20 | 21 | // Assign all oscillator outputs to specified buffer(s). If buffer 22 | // is NULL, silences all oscillators. 23 | void output( Blip_Buffer* mono ); 24 | void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); 25 | 26 | // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3, 27 | // which refer to Square 1, Square 2, Wave, and Noise. If buffer is NULL, 28 | // silences oscillator. 29 | enum { osc_count = 4 }; 30 | void osc_output( int index, Blip_Buffer* mono ); 31 | void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); 32 | 33 | // Reset oscillators and internal state 34 | void reset(); 35 | 36 | // Reads and writes at addr must satisfy start_addr <= addr <= end_addr 37 | enum { start_addr = 0xFF10 }; 38 | enum { end_addr = 0xFF3F }; 39 | enum { register_count = end_addr - start_addr + 1 }; 40 | 41 | // Write 'data' to address at specified time 42 | void write_register( blip_time_t, unsigned addr, int data ); 43 | 44 | // Read from address at specified time 45 | int read_register( blip_time_t, unsigned addr ); 46 | 47 | // Run all oscillators up to specified time, end current time frame, then 48 | // start a new frame at time 0. 49 | void end_frame( blip_time_t ); 50 | 51 | void set_tempo( double ); 52 | 53 | public: 54 | Gb_Apu(); 55 | private: 56 | // noncopyable 57 | Gb_Apu( const Gb_Apu& ); 58 | Gb_Apu& operator = ( const Gb_Apu& ); 59 | 60 | Gb_Osc* oscs [osc_count]; 61 | blip_time_t next_frame_time; 62 | blip_time_t last_time; 63 | blip_time_t frame_period; 64 | double volume_unit; 65 | int frame_count; 66 | 67 | Gb_Square square1; 68 | Gb_Square square2; 69 | Gb_Wave wave; 70 | Gb_Noise noise; 71 | uint8_t regs [register_count]; 72 | Gb_Square::Synth square_synth; // used by squares 73 | Gb_Wave::Synth other_synth; // used by wave and noise 74 | 75 | void update_volume(); 76 | void run_until( blip_time_t ); 77 | void write_osc( int index, int reg, int data ); 78 | }; 79 | 80 | inline void Gb_Apu::output( Blip_Buffer* b ) { output( b, b, b ); } 81 | 82 | inline void Gb_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); } 83 | 84 | inline void Gb_Apu::volume( double vol ) 85 | { 86 | volume_unit = 0.60 / osc_count / 15 /*steps*/ / 2 /*?*/ / 8 /*master vol range*/ * vol; 87 | update_volume(); 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Gb_Cpu.h: -------------------------------------------------------------------------------- 1 | // Nintendo Game Boy CPU emulator 2 | // Treats every instruction as taking 4 cycles 3 | 4 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 5 | #ifndef GB_CPU_H 6 | #define GB_CPU_H 7 | 8 | #include "blargg_common.h" 9 | #include "blargg_endian.h" 10 | 11 | typedef unsigned gb_addr_t; // 16-bit CPU address 12 | 13 | class Gb_Cpu { 14 | enum { clocks_per_instr = 4 }; 15 | public: 16 | // Clear registers and map all pages to unmapped 17 | void reset( void* unmapped = 0 ); 18 | 19 | // Map code memory (memory accessed via the program counter). Start and size 20 | // must be multiple of page_size. 21 | enum { page_size = 0x2000 }; 22 | void map_code( gb_addr_t start, unsigned size, void* code ); 23 | 24 | uint8_t* get_code( gb_addr_t ); 25 | 26 | // Push a byte on the stack 27 | void push_byte( int ); 28 | 29 | // Game Boy Z80 registers. *Not* kept updated during a call to run(). 30 | struct core_regs_t { 31 | #if BLARGG_BIG_ENDIAN 32 | uint8_t b, c, d, e, h, l, flags, a; 33 | #else 34 | uint8_t c, b, e, d, l, h, a, flags; 35 | #endif 36 | }; 37 | 38 | struct registers_t : core_regs_t { 39 | long pc; // more than 16 bits to allow overflow detection 40 | uint16_t sp; 41 | }; 42 | registers_t r; 43 | 44 | // Interrupt enable flag set by EI and cleared by DI 45 | //bool interrupts_enabled; // unused 46 | 47 | // Base address for RST vectors (normally 0) 48 | gb_addr_t rst_base; 49 | 50 | // If CPU executes opcode 0xFF at this address, it treats as illegal instruction 51 | enum { idle_addr = 0xF00D }; 52 | 53 | // Run CPU for at least 'count' cycles and return false, or return true if 54 | // illegal instruction is encountered. 55 | bool run( blargg_long count ); 56 | 57 | // Number of clock cycles remaining for most recent run() call 58 | blargg_long remain() const { return state->remain * clocks_per_instr; } 59 | 60 | // Can read this many bytes past end of a page 61 | enum { cpu_padding = 8 }; 62 | 63 | public: 64 | Gb_Cpu() : rst_base( 0 ) { state = &state_; } 65 | enum { page_shift = 13 }; 66 | enum { page_count = 0x10000 >> page_shift }; 67 | private: 68 | // noncopyable 69 | Gb_Cpu( const Gb_Cpu& ); 70 | Gb_Cpu& operator = ( const Gb_Cpu& ); 71 | 72 | struct state_t { 73 | uint8_t* code_map [page_count + 1]; 74 | blargg_long remain; 75 | }; 76 | state_t* state; // points to state_ or a local copy within run() 77 | state_t state_; 78 | 79 | void set_code_page( int, uint8_t* ); 80 | }; 81 | 82 | inline uint8_t* Gb_Cpu::get_code( gb_addr_t addr ) 83 | { 84 | return state->code_map [addr >> page_shift] + addr 85 | #if !BLARGG_NONPORTABLE 86 | % (unsigned) page_size 87 | #endif 88 | ; 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Gb_Oscs.h: -------------------------------------------------------------------------------- 1 | // Private oscillators used by Gb_Apu 2 | 3 | // Gb_Snd_Emu 0.1.5 4 | #ifndef GB_OSCS_H 5 | #define GB_OSCS_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | struct Gb_Osc 11 | { 12 | enum { trigger = 0x80 }; 13 | enum { len_enabled_mask = 0x40 }; 14 | 15 | Blip_Buffer* outputs [4]; // NULL, right, left, center 16 | Blip_Buffer* output; 17 | int output_select; 18 | uint8_t* regs; // osc's 5 registers 19 | 20 | int delay; 21 | int last_amp; 22 | int volume; 23 | int length; 24 | int enabled; 25 | 26 | void reset(); 27 | void clock_length(); 28 | int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; } 29 | }; 30 | 31 | struct Gb_Env : Gb_Osc 32 | { 33 | int env_delay; 34 | 35 | void reset(); 36 | void clock_envelope(); 37 | bool write_register( int, int ); 38 | }; 39 | 40 | struct Gb_Square : Gb_Env 41 | { 42 | enum { period_mask = 0x70 }; 43 | enum { shift_mask = 0x07 }; 44 | 45 | typedef Blip_Synth Synth; 46 | Synth const* synth; 47 | int sweep_delay; 48 | int sweep_freq; 49 | int phase; 50 | 51 | void reset(); 52 | void clock_sweep(); 53 | void run( blip_time_t, blip_time_t, int playing ); 54 | }; 55 | 56 | struct Gb_Noise : Gb_Env 57 | { 58 | typedef Blip_Synth Synth; 59 | Synth const* synth; 60 | unsigned bits; 61 | 62 | void run( blip_time_t, blip_time_t, int playing ); 63 | }; 64 | 65 | struct Gb_Wave : Gb_Osc 66 | { 67 | typedef Blip_Synth Synth; 68 | Synth const* synth; 69 | int wave_pos; 70 | enum { wave_size = 32 }; 71 | uint8_t wave [wave_size]; 72 | 73 | void write_register( int, int ); 74 | void run( blip_time_t, blip_time_t, int playing ); 75 | }; 76 | 77 | inline void Gb_Env::reset() 78 | { 79 | env_delay = 0; 80 | Gb_Osc::reset(); 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Gbs_Emu.h: -------------------------------------------------------------------------------- 1 | // Nintendo Game Boy GBS music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef GBS_EMU_H 5 | #define GBS_EMU_H 6 | 7 | #include "Classic_Emu.h" 8 | #include "Gb_Apu.h" 9 | #include "Gb_Cpu.h" 10 | 11 | class Gbs_Emu : private Gb_Cpu, public Classic_Emu { 12 | typedef Gb_Cpu cpu; 13 | public: 14 | // Equalizer profiles for Game Boy Color speaker and headphones 15 | static equalizer_t const handheld_eq; 16 | static equalizer_t const headphones_eq; 17 | 18 | // GBS file header 19 | enum { header_size = 112 }; 20 | struct header_t 21 | { 22 | char tag [3]; 23 | byte vers; 24 | byte track_count; 25 | byte first_track; 26 | byte load_addr [2]; 27 | byte init_addr [2]; 28 | byte play_addr [2]; 29 | byte stack_ptr [2]; 30 | byte timer_modulo; 31 | byte timer_mode; 32 | char game [32]; 33 | char author [32]; 34 | char copyright [32]; 35 | }; 36 | 37 | // Header for currently loaded file 38 | header_t const& header() const { return header_; } 39 | 40 | static gme_type_t static_type() { return gme_gbs_type; } 41 | 42 | public: 43 | // deprecated 44 | using Music_Emu::load; 45 | blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader 46 | { return load_remaining_( &h, sizeof h, in ); } 47 | 48 | public: 49 | Gbs_Emu(); 50 | ~Gbs_Emu(); 51 | protected: 52 | blargg_err_t track_info_( track_info_t*, int track ) const; 53 | blargg_err_t load_( Data_Reader& ); 54 | blargg_err_t start_track_( int ); 55 | blargg_err_t run_clocks( blip_time_t&, int ); 56 | void set_tempo_( double ); 57 | void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); 58 | void update_eq( blip_eq_t const& ); 59 | void unload(); 60 | private: 61 | // rom 62 | enum { bank_size = 0x4000 }; 63 | Rom_Data rom; 64 | void set_bank( int ); 65 | 66 | // timer 67 | blip_time_t cpu_time; 68 | blip_time_t play_period; 69 | blip_time_t next_play; 70 | void update_timer(); 71 | 72 | header_t header_; 73 | void cpu_jsr( gb_addr_t ); 74 | 75 | public: private: friend class Gb_Cpu; 76 | blip_time_t clock() const { return cpu_time - cpu::remain(); } 77 | 78 | enum { joypad_addr = 0xFF00 }; 79 | enum { ram_addr = 0xA000 }; 80 | enum { hi_page = 0xFF00 - ram_addr }; 81 | byte ram [0x4000 + 0x2000 + Gb_Cpu::cpu_padding]; 82 | Gb_Apu apu; 83 | 84 | int cpu_read( gb_addr_t ); 85 | void cpu_write( gb_addr_t, int ); 86 | }; 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Gym_Emu.h: -------------------------------------------------------------------------------- 1 | // Sega Genesis/Mega Drive GYM music file emulator 2 | // Includes with PCM timing recovery to improve sample quality. 3 | 4 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 5 | #ifndef GYM_EMU_H 6 | #define GYM_EMU_H 7 | 8 | #include "Dual_Resampler.h" 9 | #include "Ym2612_Emu.h" 10 | #include "Music_Emu.h" 11 | #include "Sms_Apu.h" 12 | 13 | class Gym_Emu : public Music_Emu, private Dual_Resampler { 14 | public: 15 | // GYM file header 16 | enum { header_size = 428 }; 17 | struct header_t 18 | { 19 | char tag [4]; 20 | char song [32]; 21 | char game [32]; 22 | char copyright [32]; 23 | char emulator [32]; 24 | char dumper [32]; 25 | char comment [256]; 26 | byte loop_start [4]; // in 1/60 seconds, 0 if not looped 27 | byte packed [4]; 28 | }; 29 | 30 | // Header for currently loaded file 31 | header_t const& header() const { return header_; } 32 | 33 | static gme_type_t static_type() { return gme_gym_type; } 34 | 35 | public: 36 | // deprecated 37 | using Music_Emu::load; 38 | blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader 39 | { return load_remaining_( &h, sizeof h, in ); } 40 | enum { gym_rate = 60 }; 41 | long track_length() const; // use track_info() 42 | 43 | public: 44 | Gym_Emu(); 45 | ~Gym_Emu(); 46 | protected: 47 | blargg_err_t load_mem_( byte const*, long ); 48 | blargg_err_t track_info_( track_info_t*, int track ) const; 49 | blargg_err_t set_sample_rate_( long sample_rate ); 50 | blargg_err_t start_track_( int ); 51 | blargg_err_t play_( long count, sample_t* ); 52 | void mute_voices_( int ); 53 | void set_tempo_( double ); 54 | int play_frame( blip_time_t blip_time, int sample_count, sample_t* buf ); 55 | private: 56 | // sequence data begin, loop begin, current position, end 57 | const byte* data; 58 | const byte* loop_begin; 59 | const byte* pos; 60 | const byte* data_end; 61 | blargg_long loop_remain; // frames remaining until loop beginning has been located 62 | header_t header_; 63 | double fm_sample_rate; 64 | blargg_long clocks_per_frame; 65 | void parse_frame(); 66 | 67 | // dac (pcm) 68 | int dac_amp; 69 | int prev_dac_count; 70 | bool dac_enabled; 71 | bool dac_muted; 72 | void run_dac( int ); 73 | 74 | // sound 75 | Blip_Buffer blip_buf; 76 | Ym2612_Emu fm; 77 | Blip_Synth dac_synth; 78 | Sms_Apu apu; 79 | byte dac_buf [1024]; 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Hes_Apu.h: -------------------------------------------------------------------------------- 1 | // Turbo Grafx 16 (PC Engine) PSG sound chip emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef HES_APU_H 5 | #define HES_APU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | struct Hes_Osc 11 | { 12 | unsigned char wave [32]; 13 | short volume [2]; 14 | int last_amp [2]; 15 | int delay; 16 | int period; 17 | unsigned char noise; 18 | unsigned char phase; 19 | unsigned char balance; 20 | unsigned char dac; 21 | blip_time_t last_time; 22 | 23 | Blip_Buffer* outputs [2]; 24 | Blip_Buffer* chans [3]; 25 | unsigned noise_lfsr; 26 | unsigned char control; 27 | 28 | enum { amp_range = 0x8000 }; 29 | typedef Blip_Synth synth_t; 30 | 31 | void run_until( synth_t& synth, blip_time_t ); 32 | }; 33 | 34 | class Hes_Apu { 35 | public: 36 | void treble_eq( blip_eq_t const& ); 37 | void volume( double ); 38 | 39 | enum { osc_count = 6 }; 40 | void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); 41 | 42 | void reset(); 43 | 44 | enum { start_addr = 0x0800 }; 45 | enum { end_addr = 0x0809 }; 46 | void write_data( blip_time_t, int addr, int data ); 47 | 48 | void end_frame( blip_time_t ); 49 | 50 | public: 51 | Hes_Apu(); 52 | private: 53 | Hes_Osc oscs [osc_count]; 54 | int latch; 55 | int balance; 56 | Hes_Osc::synth_t synth; 57 | 58 | void balance_changed( Hes_Osc& ); 59 | void recalc_chans(); 60 | }; 61 | 62 | inline void Hes_Apu::volume( double v ) { synth.volume( 1.8 / osc_count / Hes_Osc::amp_range * v ); } 63 | 64 | inline void Hes_Apu::treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Hes_Cpu.h: -------------------------------------------------------------------------------- 1 | // PC Engine CPU emulator for use with HES music files 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef HES_CPU_H 5 | #define HES_CPU_H 6 | 7 | #include "blargg_common.h" 8 | 9 | typedef blargg_long hes_time_t; // clock cycle count 10 | typedef unsigned hes_addr_t; // 16-bit address 11 | enum { future_hes_time = INT_MAX / 2 + 1 }; 12 | 13 | class Hes_Cpu { 14 | public: 15 | void reset(); 16 | 17 | enum { page_size = 0x2000 }; 18 | enum { page_shift = 13 }; 19 | enum { page_count = 8 }; 20 | void set_mmr( int reg, int bank ); 21 | 22 | uint8_t const* get_code( hes_addr_t ); 23 | 24 | uint8_t ram [page_size]; 25 | 26 | // not kept updated during a call to run() 27 | struct registers_t { 28 | uint16_t pc; 29 | uint8_t a; 30 | uint8_t x; 31 | uint8_t y; 32 | uint8_t status; 33 | uint8_t sp; 34 | }; 35 | registers_t r; 36 | 37 | // page mapping registers 38 | uint8_t mmr [page_count + 1]; 39 | 40 | // Set end_time and run CPU from current time. Returns true if any illegal 41 | // instructions were encountered. 42 | bool run( hes_time_t end_time ); 43 | 44 | // Time of beginning of next instruction to be executed 45 | hes_time_t time() const { return state->time + state->base; } 46 | void set_time( hes_time_t t ) { state->time = t - state->base; } 47 | void adjust_time( int delta ) { state->time += delta; } 48 | 49 | hes_time_t irq_time() const { return irq_time_; } 50 | void set_irq_time( hes_time_t ); 51 | 52 | hes_time_t end_time() const { return end_time_; } 53 | void set_end_time( hes_time_t ); 54 | 55 | void end_frame( hes_time_t ); 56 | 57 | // Attempt to execute instruction here results in CPU advancing time to 58 | // lesser of irq_time() and end_time() (or end_time() if IRQs are 59 | // disabled) 60 | enum { idle_addr = 0x1FFF }; 61 | 62 | // Can read this many bytes past end of a page 63 | enum { cpu_padding = 8 }; 64 | 65 | public: 66 | Hes_Cpu() { state = &state_; } 67 | enum { irq_inhibit = 0x04 }; 68 | private: 69 | // noncopyable 70 | Hes_Cpu( const Hes_Cpu& ); 71 | Hes_Cpu& operator = ( const Hes_Cpu& ); 72 | 73 | struct state_t { 74 | uint8_t const* code_map [page_count + 1]; 75 | hes_time_t base; 76 | blargg_long time; 77 | }; 78 | state_t* state; // points to state_ or a local copy within run() 79 | state_t state_; 80 | hes_time_t irq_time_; 81 | hes_time_t end_time_; 82 | 83 | void set_code_page( int, void const* ); 84 | inline int update_end_time( hes_time_t end, hes_time_t irq ); 85 | }; 86 | 87 | inline uint8_t const* Hes_Cpu::get_code( hes_addr_t addr ) 88 | { 89 | return state->code_map [addr >> page_shift] + addr 90 | #if !BLARGG_NONPORTABLE 91 | % (unsigned) page_size 92 | #endif 93 | ; 94 | } 95 | 96 | inline int Hes_Cpu::update_end_time( hes_time_t t, hes_time_t irq ) 97 | { 98 | if ( irq < t && !(r.status & irq_inhibit) ) t = irq; 99 | int delta = state->base - t; 100 | state->base = t; 101 | return delta; 102 | } 103 | 104 | inline void Hes_Cpu::set_irq_time( hes_time_t t ) 105 | { 106 | state->time += update_end_time( end_time_, (irq_time_ = t) ); 107 | } 108 | 109 | inline void Hes_Cpu::set_end_time( hes_time_t t ) 110 | { 111 | state->time += update_end_time( (end_time_ = t), irq_time_ ); 112 | } 113 | 114 | inline void Hes_Cpu::end_frame( hes_time_t t ) 115 | { 116 | assert( state == &state_ ); 117 | state_.base -= t; 118 | if ( irq_time_ < future_hes_time ) irq_time_ -= t; 119 | if ( end_time_ < future_hes_time ) end_time_ -= t; 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Hes_Emu.h: -------------------------------------------------------------------------------- 1 | // TurboGrafx-16/PC Engine HES music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef HES_EMU_H 5 | #define HES_EMU_H 6 | 7 | #include "Classic_Emu.h" 8 | #include "Hes_Apu.h" 9 | #include "Hes_Cpu.h" 10 | 11 | class Hes_Emu : private Hes_Cpu, public Classic_Emu { 12 | typedef Hes_Cpu cpu; 13 | public: 14 | // HES file header 15 | enum { header_size = 0x20 }; 16 | struct header_t 17 | { 18 | byte tag [4]; 19 | byte vers; 20 | byte first_track; 21 | byte init_addr [2]; 22 | byte banks [8]; 23 | byte data_tag [4]; 24 | byte size [4]; 25 | byte addr [4]; 26 | byte unused [4]; 27 | }; 28 | 29 | // Header for currently loaded file 30 | header_t const& header() const { return header_; } 31 | 32 | static gme_type_t static_type() { return gme_hes_type; } 33 | 34 | public: 35 | Hes_Emu(); 36 | ~Hes_Emu(); 37 | protected: 38 | blargg_err_t track_info_( track_info_t*, int track ) const; 39 | blargg_err_t load_( Data_Reader& ); 40 | blargg_err_t start_track_( int ); 41 | blargg_err_t run_clocks( blip_time_t&, int ); 42 | void set_tempo_( double ); 43 | void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); 44 | void update_eq( blip_eq_t const& ); 45 | void unload(); 46 | public: private: friend class Hes_Cpu; 47 | byte* write_pages [page_count + 1]; // 0 if unmapped or I/O space 48 | 49 | int cpu_read_( hes_addr_t ); 50 | int cpu_read( hes_addr_t ); 51 | void cpu_write_( hes_addr_t, int data ); 52 | void cpu_write( hes_addr_t, int ); 53 | void cpu_write_vdp( int addr, int data ); 54 | byte const* cpu_set_mmr( int page, int bank ); 55 | int cpu_done(); 56 | private: 57 | Rom_Data rom; 58 | header_t header_; 59 | hes_time_t play_period; 60 | hes_time_t last_frame_hook; 61 | int timer_base; 62 | 63 | struct { 64 | hes_time_t last_time; 65 | blargg_long count; 66 | blargg_long load; 67 | int raw_load; 68 | byte enabled; 69 | byte fired; 70 | } timer; 71 | 72 | struct { 73 | hes_time_t next_vbl; 74 | byte latch; 75 | byte control; 76 | } vdp; 77 | 78 | struct { 79 | hes_time_t timer; 80 | hes_time_t vdp; 81 | byte disables; 82 | } irq; 83 | 84 | void recalc_timer_load(); 85 | 86 | // large items 87 | Hes_Apu apu; 88 | byte sgx [3 * page_size + cpu_padding]; 89 | 90 | void irq_changed(); 91 | void run_until( hes_time_t ); 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Kss_Cpu.h: -------------------------------------------------------------------------------- 1 | // Z80 CPU emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef KSS_CPU_H 5 | #define KSS_CPU_H 6 | 7 | #include "blargg_endian.h" 8 | 9 | typedef blargg_long cpu_time_t; 10 | 11 | // must be defined by caller 12 | void kss_cpu_out( class Kss_Cpu*, cpu_time_t, unsigned addr, int data ); 13 | int kss_cpu_in( class Kss_Cpu*, cpu_time_t, unsigned addr ); 14 | void kss_cpu_write( class Kss_Cpu*, unsigned addr, int data ); 15 | 16 | class Kss_Cpu { 17 | public: 18 | // Clear registers and map all pages to unmapped 19 | void reset( void* unmapped_write, void const* unmapped_read ); 20 | 21 | // Map memory. Start and size must be multiple of page_size. 22 | enum { page_size = 0x2000 }; 23 | void map_mem( unsigned addr, blargg_ulong size, void* write, void const* read ); 24 | 25 | // Map address to page 26 | uint8_t* write( unsigned addr ); 27 | uint8_t const* read( unsigned addr ); 28 | 29 | // Run until specified time is reached. Returns true if suspicious/unsupported 30 | // instruction was encountered at any point during run. 31 | bool run( cpu_time_t end_time ); 32 | 33 | // Time of beginning of next instruction 34 | cpu_time_t time() const { return state->time + state->base; } 35 | 36 | // Alter current time. Not supported during run() call. 37 | void set_time( cpu_time_t t ) { state->time = t - state->base; } 38 | void adjust_time( int delta ) { state->time += delta; } 39 | 40 | #if BLARGG_BIG_ENDIAN 41 | struct regs_t { uint8_t b, c, d, e, h, l, flags, a; }; 42 | #else 43 | struct regs_t { uint8_t c, b, e, d, l, h, a, flags; }; 44 | #endif 45 | BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 ); 46 | 47 | struct pairs_t { uint16_t bc, de, hl, fa; }; 48 | 49 | // Registers are not updated until run() returns 50 | struct registers_t { 51 | uint16_t pc; 52 | uint16_t sp; 53 | uint16_t ix; 54 | uint16_t iy; 55 | union { 56 | regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a 57 | pairs_t w; // w.bc, w.de, w.hl. w.fa 58 | }; 59 | union { 60 | regs_t b; 61 | pairs_t w; 62 | } alt; 63 | uint8_t iff1; 64 | uint8_t iff2; 65 | uint8_t r; 66 | uint8_t i; 67 | uint8_t im; 68 | }; 69 | //registers_t r; (below for efficiency) 70 | 71 | enum { idle_addr = 0xFFFF }; 72 | 73 | // can read this far past end of a page 74 | enum { cpu_padding = 0x100 }; 75 | 76 | public: 77 | Kss_Cpu(); 78 | enum { page_shift = 13 }; 79 | enum { page_count = 0x10000 >> page_shift }; 80 | private: 81 | uint8_t szpc [0x200]; 82 | cpu_time_t end_time_; 83 | struct state_t { 84 | uint8_t const* read [page_count + 1]; 85 | uint8_t * write [page_count + 1]; 86 | cpu_time_t base; 87 | cpu_time_t time; 88 | }; 89 | state_t* state; // points to state_ or a local copy within run() 90 | state_t state_; 91 | void set_end_time( cpu_time_t t ); 92 | void set_page( int i, void* write, void const* read ); 93 | public: 94 | registers_t r; 95 | }; 96 | 97 | #if BLARGG_NONPORTABLE 98 | #define KSS_CPU_PAGE_OFFSET( addr ) (addr) 99 | #else 100 | #define KSS_CPU_PAGE_OFFSET( addr ) ((addr) & (page_size - 1)) 101 | #endif 102 | 103 | inline uint8_t* Kss_Cpu::write( unsigned addr ) 104 | { 105 | return state->write [addr >> page_shift] + KSS_CPU_PAGE_OFFSET( addr ); 106 | } 107 | 108 | inline uint8_t const* Kss_Cpu::read( unsigned addr ) 109 | { 110 | return state->read [addr >> page_shift] + KSS_CPU_PAGE_OFFSET( addr ); 111 | } 112 | 113 | inline void Kss_Cpu::set_end_time( cpu_time_t t ) 114 | { 115 | cpu_time_t delta = state->base - t; 116 | state->base = t; 117 | state->time += delta; 118 | } 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Kss_Emu.h: -------------------------------------------------------------------------------- 1 | // MSX computer KSS music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef KSS_EMU_H 5 | #define KSS_EMU_H 6 | 7 | #include "Classic_Emu.h" 8 | #include "Kss_Scc_Apu.h" 9 | #include "Kss_Cpu.h" 10 | #include "Sms_Apu.h" 11 | #include "Ay_Apu.h" 12 | 13 | class Kss_Emu : private Kss_Cpu, public Classic_Emu { 14 | typedef Kss_Cpu cpu; 15 | public: 16 | // KSS file header 17 | enum { header_size = 0x10 }; 18 | struct header_t 19 | { 20 | byte tag [4]; 21 | byte load_addr [2]; 22 | byte load_size [2]; 23 | byte init_addr [2]; 24 | byte play_addr [2]; 25 | byte first_bank; 26 | byte bank_mode; 27 | byte extra_header; 28 | byte device_flags; 29 | }; 30 | 31 | enum { ext_header_size = 0x10 }; 32 | struct ext_header_t 33 | { 34 | byte data_size [4]; 35 | byte unused [4]; 36 | byte first_track [2]; 37 | byte last_tack [2]; 38 | byte psg_vol; 39 | byte scc_vol; 40 | byte msx_music_vol; 41 | byte msx_audio_vol; 42 | }; 43 | 44 | struct composite_header_t : header_t, ext_header_t { }; 45 | 46 | // Header for currently loaded file 47 | composite_header_t const& header() const { return header_; } 48 | 49 | static gme_type_t static_type() { return gme_kss_type; } 50 | public: 51 | Kss_Emu(); 52 | ~Kss_Emu(); 53 | protected: 54 | blargg_err_t track_info_( track_info_t*, int track ) const; 55 | blargg_err_t load_( Data_Reader& ); 56 | blargg_err_t start_track_( int ); 57 | blargg_err_t run_clocks( blip_time_t&, int ); 58 | void set_tempo_( double ); 59 | void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); 60 | void update_eq( blip_eq_t const& ); 61 | void unload(); 62 | private: 63 | Rom_Data rom; 64 | composite_header_t header_; 65 | 66 | bool scc_accessed; 67 | bool gain_updated; 68 | void update_gain(); 69 | 70 | unsigned scc_enabled; // 0 or 0xC000 71 | int bank_count; 72 | void set_bank( int logical, int physical ); 73 | blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); } 74 | 75 | blip_time_t play_period; 76 | blip_time_t next_play; 77 | int ay_latch; 78 | 79 | friend void kss_cpu_out( class Kss_Cpu*, cpu_time_t, unsigned addr, int data ); 80 | friend int kss_cpu_in( class Kss_Cpu*, cpu_time_t, unsigned addr ); 81 | void cpu_write( unsigned addr, int data ); 82 | friend void kss_cpu_write( class Kss_Cpu*, unsigned addr, int data ); 83 | 84 | // large items 85 | enum { mem_size = 0x10000 }; 86 | byte ram [mem_size + cpu_padding]; 87 | 88 | Ay_Apu ay; 89 | Scc_Apu scc; 90 | Sms_Apu* sn; 91 | byte unmapped_read [0x100]; 92 | byte unmapped_write [page_size]; 93 | }; 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Kss_Scc_Apu.cpp: -------------------------------------------------------------------------------- 1 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 2 | 3 | #include "Kss_Scc_Apu.h" 4 | 5 | /* Copyright (C) 2006 Shay Green. This module is free software; you 6 | can redistribute it and/or modify it under the terms of the GNU Lesser 7 | General Public License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. This 9 | module is distributed in the hope that it will be useful, but WITHOUT ANY 10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 12 | details. You should have received a copy of the GNU Lesser General Public 13 | License along with this module; if not, write to the Free Software Foundation, 14 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #include "blargg_source.h" 17 | 18 | // Tones above this frequency are treated as disabled tone at half volume. 19 | // Power of two is more efficient (avoids division). 20 | unsigned const inaudible_freq = 16384; 21 | 22 | int const wave_size = 0x20; 23 | 24 | void Scc_Apu::run_until( blip_time_t end_time ) 25 | { 26 | for ( int index = 0; index < osc_count; index++ ) 27 | { 28 | osc_t& osc = oscs [index]; 29 | 30 | Blip_Buffer* const output = osc.output; 31 | if ( !output ) 32 | continue; 33 | output->set_modified(); 34 | 35 | blip_time_t period = (regs [0x80 + index * 2 + 1] & 0x0F) * 0x100 + 36 | regs [0x80 + index * 2] + 1; 37 | int volume = 0; 38 | if ( regs [0x8F] & (1 << index) ) 39 | { 40 | blip_time_t inaudible_period = (blargg_ulong) (output->clock_rate() + 41 | inaudible_freq * 32) / (inaudible_freq * 16); 42 | if ( period > inaudible_period ) 43 | volume = (regs [0x8A + index] & 0x0F) * (amp_range / 256 / 15); 44 | } 45 | 46 | int8_t const* wave = (int8_t*) regs + index * wave_size; 47 | if ( index == osc_count - 1 ) 48 | wave -= wave_size; // last two oscs share wave 49 | { 50 | int amp = wave [osc.phase] * volume; 51 | int delta = amp - osc.last_amp; 52 | if ( delta ) 53 | { 54 | osc.last_amp = amp; 55 | synth.offset( last_time, delta, output ); 56 | } 57 | } 58 | 59 | blip_time_t time = last_time + osc.delay; 60 | if ( time < end_time ) 61 | { 62 | if ( !volume ) 63 | { 64 | // maintain phase 65 | blargg_long count = (end_time - time + period - 1) / period; 66 | osc.phase = (osc.phase + count) & (wave_size - 1); 67 | time += count * period; 68 | } 69 | else 70 | { 71 | 72 | int phase = osc.phase; 73 | int last_wave = wave [phase]; 74 | phase = (phase + 1) & (wave_size - 1); // pre-advance for optimal inner loop 75 | 76 | do 77 | { 78 | int amp = wave [phase]; 79 | phase = (phase + 1) & (wave_size - 1); 80 | int delta = amp - last_wave; 81 | if ( delta ) 82 | { 83 | last_wave = amp; 84 | synth.offset( time, delta * volume, output ); 85 | } 86 | time += period; 87 | } 88 | while ( time < end_time ); 89 | 90 | osc.phase = phase = (phase - 1) & (wave_size - 1); // undo pre-advance 91 | osc.last_amp = wave [phase] * volume; 92 | } 93 | } 94 | osc.delay = time - end_time; 95 | } 96 | last_time = end_time; 97 | } 98 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Kss_Scc_Apu.h: -------------------------------------------------------------------------------- 1 | // Konami SCC sound chip emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef KSS_SCC_APU_H 5 | #define KSS_SCC_APU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | #include 10 | 11 | class Scc_Apu { 12 | public: 13 | // Set buffer to generate all sound into, or disable sound if NULL 14 | void output( Blip_Buffer* ); 15 | 16 | // Reset sound chip 17 | void reset(); 18 | 19 | // Write to register at specified time 20 | enum { reg_count = 0x90 }; 21 | void write( blip_time_t time, int reg, int data ); 22 | 23 | // Run sound to specified time, end current time frame, then start a new 24 | // time frame at time 0. Time frames have no effect on emulation and each 25 | // can be whatever length is convenient. 26 | void end_frame( blip_time_t length ); 27 | 28 | // Additional features 29 | 30 | // Set sound output of specific oscillator to buffer, where index is 31 | // 0 to 4. If buffer is NULL, the specified oscillator is muted. 32 | enum { osc_count = 5 }; 33 | void osc_output( int index, Blip_Buffer* ); 34 | 35 | // Set overall volume (default is 1.0) 36 | void volume( double ); 37 | 38 | // Set treble equalization (see documentation) 39 | void treble_eq( blip_eq_t const& ); 40 | 41 | public: 42 | Scc_Apu(); 43 | private: 44 | enum { amp_range = 0x8000 }; 45 | struct osc_t 46 | { 47 | int delay; 48 | int phase; 49 | int last_amp; 50 | Blip_Buffer* output; 51 | }; 52 | osc_t oscs [osc_count]; 53 | blip_time_t last_time; 54 | unsigned char regs [reg_count]; 55 | Blip_Synth synth; 56 | 57 | void run_until( blip_time_t ); 58 | }; 59 | 60 | inline void Scc_Apu::volume( double v ) { synth.volume( 0.43 / osc_count / amp_range * v ); } 61 | 62 | inline void Scc_Apu::treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); } 63 | 64 | inline void Scc_Apu::osc_output( int index, Blip_Buffer* b ) 65 | { 66 | assert( (unsigned) index < osc_count ); 67 | oscs [index].output = b; 68 | } 69 | 70 | inline void Scc_Apu::write( blip_time_t time, int addr, int data ) 71 | { 72 | assert( (unsigned) addr < reg_count ); 73 | run_until( time ); 74 | regs [addr] = data; 75 | } 76 | 77 | inline void Scc_Apu::end_frame( blip_time_t end_time ) 78 | { 79 | if ( end_time > last_time ) 80 | run_until( end_time ); 81 | last_time -= end_time; 82 | assert( last_time >= 0 ); 83 | } 84 | 85 | inline void Scc_Apu::output( Blip_Buffer* buf ) 86 | { 87 | for ( int i = 0; i < osc_count; i++ ) 88 | oscs [i].output = buf; 89 | } 90 | 91 | inline Scc_Apu::Scc_Apu() 92 | { 93 | output( 0 ); 94 | } 95 | 96 | inline void Scc_Apu::reset() 97 | { 98 | last_time = 0; 99 | 100 | for ( int i = 0; i < osc_count; i++ ) 101 | memset( &oscs [i], 0, offsetof (osc_t,output) ); 102 | 103 | memset( regs, 0, sizeof regs ); 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/M3u_Playlist.h: -------------------------------------------------------------------------------- 1 | // M3U playlist file parser, with support for subtrack information 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef M3U_PLAYLIST_H 5 | #define M3U_PLAYLIST_H 6 | 7 | #include "blargg_common.h" 8 | #include "Data_Reader.h" 9 | 10 | class M3u_Playlist { 11 | public: 12 | // Load playlist data 13 | blargg_err_t load( const char* path ); 14 | blargg_err_t load( Data_Reader& in ); 15 | blargg_err_t load( void const* data, long size ); 16 | 17 | // Line number of first parse error, 0 if no error. Any lines with parse 18 | // errors are ignored. 19 | int first_error() const { return first_error_; } 20 | 21 | struct info_t 22 | { 23 | const char* title; 24 | const char* composer; 25 | const char* engineer; 26 | const char* ripping; 27 | const char* tagging; 28 | }; 29 | info_t const& info() const { return info_; } 30 | 31 | struct entry_t 32 | { 33 | const char* file; // filename without stupid ::TYPE suffix 34 | const char* type; // if filename has ::TYPE suffix, this will be "TYPE". "" if none. 35 | const char* name; 36 | bool decimal_track; // true if track was specified in hex 37 | // integers are -1 if not present 38 | int track; // 1-based 39 | int length; // milliseconds 40 | int intro; 41 | int loop; 42 | int fade; 43 | int repeat; // count 44 | }; 45 | entry_t const& operator [] ( int i ) const { return entries [i]; } 46 | int size() const { return entries.size(); } 47 | 48 | void clear(); 49 | 50 | private: 51 | blargg_vector entries; 52 | blargg_vector data; 53 | int first_error_; 54 | info_t info_; 55 | 56 | blargg_err_t parse(); 57 | blargg_err_t parse_(); 58 | }; 59 | 60 | inline void M3u_Playlist::clear() 61 | { 62 | first_error_ = 0; 63 | entries.clear(); 64 | data.clear(); 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nes_Cpu.h: -------------------------------------------------------------------------------- 1 | // NES 6502 CPU emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef NES_CPU_H 5 | #define NES_CPU_H 6 | 7 | #include "blargg_common.h" 8 | 9 | typedef blargg_long nes_time_t; // clock cycle count 10 | typedef unsigned nes_addr_t; // 16-bit address 11 | enum { future_nes_time = INT_MAX / 2 + 1 }; 12 | 13 | class Nes_Cpu { 14 | public: 15 | // Clear registers, map low memory and its three mirrors to address 0, 16 | // and mirror unmapped_page in remaining memory 17 | void reset( void const* unmapped_page = 0 ); 18 | 19 | // Map code memory (memory accessed via the program counter). Start and size 20 | // must be multiple of page_size. If mirror is true, repeats code page 21 | // throughout address range. 22 | enum { page_size = 0x800 }; 23 | void map_code( nes_addr_t start, unsigned size, void const* code, bool mirror = false ); 24 | 25 | // Access emulated memory as CPU does 26 | uint8_t const* get_code( nes_addr_t ); 27 | 28 | // 2KB of RAM at address 0 29 | uint8_t low_mem [0x800]; 30 | 31 | // NES 6502 registers. Not kept updated during a call to run(). 32 | struct registers_t { 33 | uint16_t pc; 34 | uint8_t a; 35 | uint8_t x; 36 | uint8_t y; 37 | uint8_t status; 38 | uint8_t sp; 39 | }; 40 | registers_t r; 41 | 42 | // Set end_time and run CPU from current time. Returns true if execution 43 | // stopped due to encountering bad_opcode. 44 | bool run( nes_time_t end_time ); 45 | 46 | // Time of beginning of next instruction to be executed 47 | nes_time_t time() const { return state->time + state->base; } 48 | void set_time( nes_time_t t ) { state->time = t - state->base; } 49 | void adjust_time( int delta ) { state->time += delta; } 50 | 51 | nes_time_t irq_time() const { return irq_time_; } 52 | void set_irq_time( nes_time_t ); 53 | 54 | nes_time_t end_time() const { return end_time_; } 55 | void set_end_time( nes_time_t ); 56 | 57 | // Number of undefined instructions encountered and skipped 58 | void clear_error_count() { error_count_ = 0; } 59 | unsigned long error_count() const { return error_count_; } 60 | 61 | // CPU invokes bad opcode handler if it encounters this 62 | enum { bad_opcode = 0xF2 }; 63 | 64 | public: 65 | Nes_Cpu() { state = &state_; } 66 | enum { page_bits = 11 }; 67 | enum { page_count = 0x10000 >> page_bits }; 68 | enum { irq_inhibit = 0x04 }; 69 | private: 70 | struct state_t { 71 | uint8_t const* code_map [page_count + 1]; 72 | nes_time_t base; 73 | int time; 74 | }; 75 | state_t* state; // points to state_ or a local copy within run() 76 | state_t state_; 77 | nes_time_t irq_time_; 78 | nes_time_t end_time_; 79 | unsigned long error_count_; 80 | 81 | void set_code_page( int, void const* ); 82 | inline int update_end_time( nes_time_t end, nes_time_t irq ); 83 | }; 84 | 85 | inline uint8_t const* Nes_Cpu::get_code( nes_addr_t addr ) 86 | { 87 | return state->code_map [addr >> page_bits] + addr 88 | #if !BLARGG_NONPORTABLE 89 | % (unsigned) page_size 90 | #endif 91 | ; 92 | } 93 | 94 | inline int Nes_Cpu::update_end_time( nes_time_t t, nes_time_t irq ) 95 | { 96 | if ( irq < t && !(r.status & irq_inhibit) ) t = irq; 97 | int delta = state->base - t; 98 | state->base = t; 99 | return delta; 100 | } 101 | 102 | inline void Nes_Cpu::set_irq_time( nes_time_t t ) 103 | { 104 | state->time += update_end_time( end_time_, (irq_time_ = t) ); 105 | } 106 | 107 | inline void Nes_Cpu::set_end_time( nes_time_t t ) 108 | { 109 | state->time += update_end_time( (end_time_ = t), irq_time_ ); 110 | } 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nes_Fme7_Apu.cpp: -------------------------------------------------------------------------------- 1 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 2 | 3 | #include "Nes_Fme7_Apu.h" 4 | 5 | #include 6 | 7 | /* Copyright (C) 2003-2006 Shay Green. This module is free software; you 8 | can redistribute it and/or modify it under the terms of the GNU Lesser 9 | General Public License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. This 11 | module is distributed in the hope that it will be useful, but WITHOUT ANY 12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | details. You should have received a copy of the GNU Lesser General Public 15 | License along with this module; if not, write to the Free Software Foundation, 16 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 17 | 18 | #include "blargg_source.h" 19 | 20 | void Nes_Fme7_Apu::reset() 21 | { 22 | last_time = 0; 23 | 24 | for ( int i = 0; i < osc_count; i++ ) 25 | oscs [i].last_amp = 0; 26 | 27 | fme7_apu_state_t* state = this; 28 | memset( state, 0, sizeof *state ); 29 | } 30 | 31 | unsigned char const Nes_Fme7_Apu::amp_table [16] = 32 | { 33 | #define ENTRY( n ) (unsigned char) (n * amp_range + 0.5) 34 | ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156), 35 | ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624), 36 | ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498), 37 | ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000) 38 | #undef ENTRY 39 | }; 40 | 41 | void Nes_Fme7_Apu::run_until( blip_time_t end_time ) 42 | { 43 | require( end_time >= last_time ); 44 | 45 | for ( int index = 0; index < osc_count; index++ ) 46 | { 47 | int mode = regs [7] >> index; 48 | int vol_mode = regs [010 + index]; 49 | int volume = amp_table [vol_mode & 0x0F]; 50 | 51 | Blip_Buffer* const osc_output = oscs [index].output; 52 | if ( !osc_output ) 53 | continue; 54 | osc_output->set_modified(); 55 | 56 | // check for unsupported mode 57 | #ifndef NDEBUG 58 | if ( (mode & 011) <= 001 && vol_mode & 0x1F ) 59 | debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n", 60 | mode, vol_mode & 0x1F ); 61 | #endif 62 | 63 | if ( (mode & 001) | (vol_mode & 0x10) ) 64 | volume = 0; // noise and envelope aren't supported 65 | 66 | // period 67 | int const period_factor = 16; 68 | unsigned period = (regs [index * 2 + 1] & 0x0F) * 0x100 * period_factor + 69 | regs [index * 2] * period_factor; 70 | if ( period < 50 ) // around 22 kHz 71 | { 72 | volume = 0; 73 | if ( !period ) // on my AY-3-8910A, period doesn't have extra one added 74 | period = period_factor; 75 | } 76 | 77 | // current amplitude 78 | int amp = volume; 79 | if ( !phases [index] ) 80 | amp = 0; 81 | { 82 | int delta = amp - oscs [index].last_amp; 83 | if ( delta ) 84 | { 85 | oscs [index].last_amp = amp; 86 | synth.offset( last_time, delta, osc_output ); 87 | } 88 | } 89 | 90 | blip_time_t time = last_time + delays [index]; 91 | if ( time < end_time ) 92 | { 93 | int delta = amp * 2 - volume; 94 | if ( volume ) 95 | { 96 | do 97 | { 98 | delta = -delta; 99 | synth.offset_inline( time, delta, osc_output ); 100 | time += period; 101 | } 102 | while ( time < end_time ); 103 | 104 | oscs [index].last_amp = (delta + volume) >> 1; 105 | phases [index] = (delta > 0); 106 | } 107 | else 108 | { 109 | // maintain phase when silent 110 | int count = (end_time - time + period - 1) / period; 111 | phases [index] ^= count & 1; 112 | time += (blargg_long) count * period; 113 | } 114 | } 115 | 116 | delays [index] = time - end_time; 117 | } 118 | 119 | last_time = end_time; 120 | } 121 | 122 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nes_Fme7_Apu.h: -------------------------------------------------------------------------------- 1 | // Sunsoft FME-7 sound emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef NES_FME7_APU_H 5 | #define NES_FME7_APU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | struct fme7_apu_state_t 11 | { 12 | enum { reg_count = 14 }; 13 | uint8_t regs [reg_count]; 14 | uint8_t phases [3]; // 0 or 1 15 | uint8_t latch; 16 | uint16_t delays [3]; // a, b, c 17 | }; 18 | 19 | class Nes_Fme7_Apu : private fme7_apu_state_t { 20 | public: 21 | // See Nes_Apu.h for reference 22 | void reset(); 23 | void volume( double ); 24 | void treble_eq( blip_eq_t const& ); 25 | void output( Blip_Buffer* ); 26 | enum { osc_count = 3 }; 27 | void osc_output( int index, Blip_Buffer* ); 28 | void end_frame( blip_time_t ); 29 | void save_state( fme7_apu_state_t* ) const; 30 | void load_state( fme7_apu_state_t const& ); 31 | 32 | // Mask and addresses of registers 33 | enum { addr_mask = 0xE000 }; 34 | enum { data_addr = 0xE000 }; 35 | enum { latch_addr = 0xC000 }; 36 | 37 | // (addr & addr_mask) == latch_addr 38 | void write_latch( int ); 39 | 40 | // (addr & addr_mask) == data_addr 41 | void write_data( blip_time_t, int data ); 42 | 43 | public: 44 | Nes_Fme7_Apu(); 45 | BLARGG_DISABLE_NOTHROW 46 | private: 47 | // noncopyable 48 | Nes_Fme7_Apu( const Nes_Fme7_Apu& ); 49 | Nes_Fme7_Apu& operator = ( const Nes_Fme7_Apu& ); 50 | 51 | static unsigned char const amp_table [16]; 52 | 53 | struct { 54 | Blip_Buffer* output; 55 | int last_amp; 56 | } oscs [osc_count]; 57 | blip_time_t last_time; 58 | 59 | enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff 60 | Blip_Synth synth; 61 | 62 | void run_until( blip_time_t ); 63 | }; 64 | 65 | inline void Nes_Fme7_Apu::volume( double v ) 66 | { 67 | synth.volume( 0.38 / amp_range * v ); // to do: fine-tune 68 | } 69 | 70 | inline void Nes_Fme7_Apu::treble_eq( blip_eq_t const& eq ) 71 | { 72 | synth.treble_eq( eq ); 73 | } 74 | 75 | inline void Nes_Fme7_Apu::osc_output( int i, Blip_Buffer* buf ) 76 | { 77 | assert( (unsigned) i < osc_count ); 78 | oscs [i].output = buf; 79 | } 80 | 81 | inline void Nes_Fme7_Apu::output( Blip_Buffer* buf ) 82 | { 83 | for ( int i = 0; i < osc_count; i++ ) 84 | osc_output( i, buf ); 85 | } 86 | 87 | inline Nes_Fme7_Apu::Nes_Fme7_Apu() 88 | { 89 | output( NULL ); 90 | volume( 1.0 ); 91 | reset(); 92 | } 93 | 94 | inline void Nes_Fme7_Apu::write_latch( int data ) { latch = data; } 95 | 96 | inline void Nes_Fme7_Apu::write_data( blip_time_t time, int data ) 97 | { 98 | if ( (unsigned) latch >= reg_count ) 99 | { 100 | #ifdef debug_printf 101 | debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch ); 102 | #endif 103 | return; 104 | } 105 | 106 | run_until( time ); 107 | regs [latch] = data; 108 | } 109 | 110 | inline void Nes_Fme7_Apu::end_frame( blip_time_t time ) 111 | { 112 | if ( time > last_time ) 113 | run_until( time ); 114 | 115 | assert( last_time >= time ); 116 | last_time -= time; 117 | } 118 | 119 | inline void Nes_Fme7_Apu::save_state( fme7_apu_state_t* out ) const 120 | { 121 | *out = *this; 122 | } 123 | 124 | inline void Nes_Fme7_Apu::load_state( fme7_apu_state_t const& in ) 125 | { 126 | reset(); 127 | fme7_apu_state_t* state = this; 128 | *state = in; 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nes_Namco_Apu.cpp: -------------------------------------------------------------------------------- 1 | // Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/ 2 | 3 | #include "Nes_Namco_Apu.h" 4 | 5 | /* Copyright (C) 2003-2006 Shay Green. This module is free software; you 6 | can redistribute it and/or modify it under the terms of the GNU Lesser 7 | General Public License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. This 9 | module is distributed in the hope that it will be useful, but WITHOUT ANY 10 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 11 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 12 | details. You should have received a copy of the GNU Lesser General Public 13 | License along with this module; if not, write to the Free Software Foundation, 14 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #include "blargg_source.h" 17 | 18 | Nes_Namco_Apu::Nes_Namco_Apu() 19 | { 20 | output( NULL ); 21 | volume( 1.0 ); 22 | reset(); 23 | } 24 | 25 | void Nes_Namco_Apu::reset() 26 | { 27 | last_time = 0; 28 | addr_reg = 0; 29 | 30 | int i; 31 | for ( i = 0; i < reg_count; i++ ) 32 | reg [i] = 0; 33 | 34 | for ( i = 0; i < osc_count; i++ ) 35 | { 36 | Namco_Osc& osc = oscs [i]; 37 | osc.delay = 0; 38 | osc.last_amp = 0; 39 | osc.wave_pos = 0; 40 | } 41 | } 42 | 43 | void Nes_Namco_Apu::output( Blip_Buffer* buf ) 44 | { 45 | for ( int i = 0; i < osc_count; i++ ) 46 | osc_output( i, buf ); 47 | } 48 | 49 | /* 50 | void Nes_Namco_Apu::reflect_state( Tagged_Data& data ) 51 | { 52 | reflect_int16( data, BLARGG_4CHAR('A','D','D','R'), &addr_reg ); 53 | 54 | static const char hex [17] = "0123456789ABCDEF"; 55 | int i; 56 | for ( i = 0; i < reg_count; i++ ) 57 | reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], ® [i] ); 58 | 59 | for ( i = 0; i < osc_count; i++ ) 60 | { 61 | reflect_int32( data, BLARGG_4CHAR('D','L','Y','0') + i, &oscs [i].delay ); 62 | reflect_int16( data, BLARGG_4CHAR('P','O','S','0') + i, &oscs [i].wave_pos ); 63 | } 64 | } 65 | */ 66 | 67 | void Nes_Namco_Apu::end_frame( blip_time_t time ) 68 | { 69 | if ( time > last_time ) 70 | run_until( time ); 71 | 72 | assert( last_time >= time ); 73 | last_time -= time; 74 | } 75 | 76 | void Nes_Namco_Apu::run_until( blip_time_t nes_end_time ) 77 | { 78 | int active_oscs = (reg [0x7F] >> 4 & 7) + 1; 79 | for ( int i = osc_count - active_oscs; i < osc_count; i++ ) 80 | { 81 | Namco_Osc& osc = oscs [i]; 82 | Blip_Buffer* output = osc.output; 83 | if ( !output ) 84 | continue; 85 | output->set_modified(); 86 | 87 | blip_resampled_time_t time = 88 | output->resampled_time( last_time ) + osc.delay; 89 | blip_resampled_time_t end_time = output->resampled_time( nes_end_time ); 90 | osc.delay = 0; 91 | if ( time < end_time ) 92 | { 93 | const uint8_t* osc_reg = ® [i * 8 + 0x40]; 94 | if ( !(osc_reg [4] & 0xE0) ) 95 | continue; 96 | 97 | int volume = osc_reg [7] & 15; 98 | if ( !volume ) 99 | continue; 100 | 101 | blargg_long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0]; 102 | if ( freq < 64 * active_oscs ) 103 | continue; // prevent low frequencies from excessively delaying freq changes 104 | blip_resampled_time_t period = 105 | output->resampled_duration( 983040 ) / freq * active_oscs; 106 | 107 | int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4; 108 | if ( !wave_size ) 109 | continue; 110 | 111 | int last_amp = osc.last_amp; 112 | int wave_pos = osc.wave_pos; 113 | 114 | do 115 | { 116 | // read wave sample 117 | int addr = wave_pos + osc_reg [6]; 118 | int sample = reg [addr >> 1] >> (addr << 2 & 4); 119 | wave_pos++; 120 | sample = (sample & 15) * volume; 121 | 122 | // output impulse if amplitude changed 123 | int delta = sample - last_amp; 124 | if ( delta ) 125 | { 126 | last_amp = sample; 127 | synth.offset_resampled( time, delta, output ); 128 | } 129 | 130 | // next sample 131 | time += period; 132 | if ( wave_pos >= wave_size ) 133 | wave_pos = 0; 134 | } 135 | while ( time < end_time ); 136 | 137 | osc.wave_pos = wave_pos; 138 | osc.last_amp = last_amp; 139 | } 140 | osc.delay = time - end_time; 141 | } 142 | 143 | last_time = nes_end_time; 144 | } 145 | 146 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nes_Namco_Apu.h: -------------------------------------------------------------------------------- 1 | // Namco 106 sound chip emulator 2 | 3 | // Nes_Snd_Emu 0.1.8 4 | #ifndef NES_NAMCO_APU_H 5 | #define NES_NAMCO_APU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | struct namco_state_t; 11 | 12 | class Nes_Namco_Apu { 13 | public: 14 | // See Nes_Apu.h for reference. 15 | void volume( double ); 16 | void treble_eq( const blip_eq_t& ); 17 | void output( Blip_Buffer* ); 18 | enum { osc_count = 8 }; 19 | void osc_output( int index, Blip_Buffer* ); 20 | void reset(); 21 | void end_frame( blip_time_t ); 22 | 23 | // Read/write data register is at 0x4800 24 | enum { data_reg_addr = 0x4800 }; 25 | void write_data( blip_time_t, int ); 26 | int read_data(); 27 | 28 | // Write-only address register is at 0xF800 29 | enum { addr_reg_addr = 0xF800 }; 30 | void write_addr( int ); 31 | 32 | // to do: implement save/restore 33 | void save_state( namco_state_t* out ) const; 34 | void load_state( namco_state_t const& ); 35 | 36 | public: 37 | Nes_Namco_Apu(); 38 | BLARGG_DISABLE_NOTHROW 39 | private: 40 | // noncopyable 41 | Nes_Namco_Apu( const Nes_Namco_Apu& ); 42 | Nes_Namco_Apu& operator = ( const Nes_Namco_Apu& ); 43 | 44 | struct Namco_Osc { 45 | blargg_long delay; 46 | Blip_Buffer* output; 47 | short last_amp; 48 | short wave_pos; 49 | }; 50 | 51 | Namco_Osc oscs [osc_count]; 52 | 53 | blip_time_t last_time; 54 | int addr_reg; 55 | 56 | enum { reg_count = 0x80 }; 57 | uint8_t reg [reg_count]; 58 | Blip_Synth synth; 59 | 60 | uint8_t& access(); 61 | void run_until( blip_time_t ); 62 | }; 63 | /* 64 | struct namco_state_t 65 | { 66 | uint8_t regs [0x80]; 67 | uint8_t addr; 68 | uint8_t unused; 69 | uint8_t positions [8]; 70 | uint32_t delays [8]; 71 | }; 72 | */ 73 | 74 | inline uint8_t& Nes_Namco_Apu::access() 75 | { 76 | int addr = addr_reg & 0x7F; 77 | if ( addr_reg & 0x80 ) 78 | addr_reg = (addr + 1) | 0x80; 79 | return reg [addr]; 80 | } 81 | 82 | inline void Nes_Namco_Apu::volume( double v ) { synth.volume( 0.10 / osc_count * v ); } 83 | 84 | inline void Nes_Namco_Apu::treble_eq( const blip_eq_t& eq ) { synth.treble_eq( eq ); } 85 | 86 | inline void Nes_Namco_Apu::write_addr( int v ) { addr_reg = v; } 87 | 88 | inline int Nes_Namco_Apu::read_data() { return access(); } 89 | 90 | inline void Nes_Namco_Apu::osc_output( int i, Blip_Buffer* buf ) 91 | { 92 | assert( (unsigned) i < osc_count ); 93 | oscs [i].output = buf; 94 | } 95 | 96 | inline void Nes_Namco_Apu::write_data( blip_time_t time, int data ) 97 | { 98 | run_until( time ); 99 | access() = data; 100 | } 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nes_Oscs.h: -------------------------------------------------------------------------------- 1 | // Private oscillators used by Nes_Apu 2 | 3 | // Nes_Snd_Emu 0.1.8 4 | #ifndef NES_OSCS_H 5 | #define NES_OSCS_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | class Nes_Apu; 11 | 12 | struct Nes_Osc 13 | { 14 | unsigned char regs [4]; 15 | bool reg_written [4]; 16 | Blip_Buffer* output; 17 | int length_counter;// length counter (0 if unused by oscillator) 18 | int delay; // delay until next (potential) transition 19 | int last_amp; // last amplitude oscillator was outputting 20 | 21 | void clock_length( int halt_mask ); 22 | int period() const { 23 | return (regs [3] & 7) * 0x100 + (regs [2] & 0xFF); 24 | } 25 | void reset() { 26 | delay = 0; 27 | last_amp = 0; 28 | } 29 | int update_amp( int amp ) { 30 | int delta = amp - last_amp; 31 | last_amp = amp; 32 | return delta; 33 | } 34 | }; 35 | 36 | struct Nes_Envelope : Nes_Osc 37 | { 38 | int envelope; 39 | int env_delay; 40 | 41 | void clock_envelope(); 42 | int volume() const; 43 | void reset() { 44 | envelope = 0; 45 | env_delay = 0; 46 | Nes_Osc::reset(); 47 | } 48 | }; 49 | 50 | // Nes_Square 51 | struct Nes_Square : Nes_Envelope 52 | { 53 | enum { negate_flag = 0x08 }; 54 | enum { shift_mask = 0x07 }; 55 | enum { phase_range = 8 }; 56 | int phase; 57 | int sweep_delay; 58 | 59 | typedef Blip_Synth Synth; 60 | Synth const& synth; // shared between squares 61 | 62 | Nes_Square( Synth const* s ) : synth( *s ) { } 63 | 64 | void clock_sweep( int adjust ); 65 | void run( nes_time_t, nes_time_t ); 66 | void reset() { 67 | sweep_delay = 0; 68 | Nes_Envelope::reset(); 69 | } 70 | nes_time_t maintain_phase( nes_time_t time, nes_time_t end_time, 71 | nes_time_t timer_period ); 72 | }; 73 | 74 | // Nes_Triangle 75 | struct Nes_Triangle : Nes_Osc 76 | { 77 | enum { phase_range = 16 }; 78 | int phase; 79 | int linear_counter; 80 | Blip_Synth synth; 81 | 82 | int calc_amp() const; 83 | void run( nes_time_t, nes_time_t ); 84 | void clock_linear_counter(); 85 | void reset() { 86 | linear_counter = 0; 87 | phase = 1; 88 | Nes_Osc::reset(); 89 | } 90 | nes_time_t maintain_phase( nes_time_t time, nes_time_t end_time, 91 | nes_time_t timer_period ); 92 | }; 93 | 94 | // Nes_Noise 95 | struct Nes_Noise : Nes_Envelope 96 | { 97 | int noise; 98 | Blip_Synth synth; 99 | 100 | void run( nes_time_t, nes_time_t ); 101 | void reset() { 102 | noise = 1 << 14; 103 | Nes_Envelope::reset(); 104 | } 105 | }; 106 | 107 | // Nes_Dmc 108 | struct Nes_Dmc : Nes_Osc 109 | { 110 | int address; // address of next byte to read 111 | int period; 112 | //int length_counter; // bytes remaining to play (already defined in Nes_Osc) 113 | int buf; 114 | int bits_remain; 115 | int bits; 116 | bool buf_full; 117 | bool silence; 118 | 119 | enum { loop_flag = 0x40 }; 120 | 121 | int dac; 122 | 123 | nes_time_t next_irq; 124 | bool irq_enabled; 125 | bool irq_flag; 126 | bool pal_mode; 127 | bool nonlinear; 128 | 129 | int (*prg_reader)( void*, nes_addr_t ); // needs to be initialized to prg read function 130 | void* prg_reader_data; 131 | 132 | Nes_Apu* apu; 133 | 134 | Blip_Synth synth; 135 | 136 | void start(); 137 | void write_register( int, int ); 138 | void run( nes_time_t, nes_time_t ); 139 | void recalc_irq(); 140 | void fill_buffer(); 141 | void reload_sample(); 142 | void reset(); 143 | int count_reads( nes_time_t, nes_time_t* ) const; 144 | nes_time_t next_read_time() const; 145 | }; 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nes_Vrc6_Apu.h: -------------------------------------------------------------------------------- 1 | // Konami VRC6 sound chip emulator 2 | 3 | // Nes_Snd_Emu 0.1.8 4 | #ifndef NES_VRC6_APU_H 5 | #define NES_VRC6_APU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | struct vrc6_apu_state_t; 11 | 12 | class Nes_Vrc6_Apu { 13 | public: 14 | // See Nes_Apu.h for reference 15 | void reset(); 16 | void volume( double ); 17 | void treble_eq( blip_eq_t const& ); 18 | void output( Blip_Buffer* ); 19 | enum { osc_count = 3 }; 20 | void osc_output( int index, Blip_Buffer* ); 21 | void end_frame( blip_time_t ); 22 | void save_state( vrc6_apu_state_t* ) const; 23 | void load_state( vrc6_apu_state_t const& ); 24 | 25 | // Oscillator 0 write-only registers are at $9000-$9002 26 | // Oscillator 1 write-only registers are at $A000-$A002 27 | // Oscillator 2 write-only registers are at $B000-$B002 28 | enum { reg_count = 3 }; 29 | enum { base_addr = 0x9000 }; 30 | enum { addr_step = 0x1000 }; 31 | void write_osc( blip_time_t, int osc, int reg, int data ); 32 | 33 | public: 34 | Nes_Vrc6_Apu(); 35 | BLARGG_DISABLE_NOTHROW 36 | private: 37 | // noncopyable 38 | Nes_Vrc6_Apu( const Nes_Vrc6_Apu& ); 39 | Nes_Vrc6_Apu& operator = ( const Nes_Vrc6_Apu& ); 40 | 41 | struct Vrc6_Osc 42 | { 43 | uint8_t regs [3]; 44 | Blip_Buffer* output; 45 | int delay; 46 | int last_amp; 47 | int phase; 48 | int amp; // only used by saw 49 | 50 | int period() const 51 | { 52 | return (regs [2] & 0x0F) * 0x100L + regs [1] + 1; 53 | } 54 | }; 55 | 56 | Vrc6_Osc oscs [osc_count]; 57 | blip_time_t last_time; 58 | 59 | Blip_Synth saw_synth; 60 | Blip_Synth square_synth; 61 | 62 | void run_until( blip_time_t ); 63 | void run_square( Vrc6_Osc& osc, blip_time_t ); 64 | void run_saw( blip_time_t ); 65 | }; 66 | 67 | struct vrc6_apu_state_t 68 | { 69 | uint8_t regs [3] [3]; 70 | uint8_t saw_amp; 71 | uint16_t delays [3]; 72 | uint8_t phases [3]; 73 | uint8_t unused; 74 | }; 75 | 76 | inline void Nes_Vrc6_Apu::osc_output( int i, Blip_Buffer* buf ) 77 | { 78 | assert( (unsigned) i < osc_count ); 79 | oscs [i].output = buf; 80 | } 81 | 82 | inline void Nes_Vrc6_Apu::volume( double v ) 83 | { 84 | double const factor = 0.0967 * 2; 85 | saw_synth.volume( factor / 31 * v ); 86 | square_synth.volume( factor * 0.5 / 15 * v ); 87 | } 88 | 89 | inline void Nes_Vrc6_Apu::treble_eq( blip_eq_t const& eq ) 90 | { 91 | saw_synth.treble_eq( eq ); 92 | square_synth.treble_eq( eq ); 93 | } 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nsf_Emu.h: -------------------------------------------------------------------------------- 1 | // Nintendo NES/Famicom NSF music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef NSF_EMU_H 5 | #define NSF_EMU_H 6 | 7 | #include "Classic_Emu.h" 8 | #include "Nes_Apu.h" 9 | #include "Nes_Cpu.h" 10 | 11 | class Nsf_Emu : private Nes_Cpu, public Classic_Emu { 12 | typedef Nes_Cpu cpu; 13 | public: 14 | // Equalizer profiles for US NES and Japanese Famicom 15 | static equalizer_t const nes_eq; 16 | static equalizer_t const famicom_eq; 17 | 18 | // NSF file header 19 | enum { header_size = 0x80 }; 20 | struct header_t 21 | { 22 | char tag [5]; 23 | byte vers; 24 | byte track_count; 25 | byte first_track; 26 | byte load_addr [2]; 27 | byte init_addr [2]; 28 | byte play_addr [2]; 29 | char game [32]; 30 | char author [32]; 31 | char copyright [32]; 32 | byte ntsc_speed [2]; 33 | byte banks [8]; 34 | byte pal_speed [2]; 35 | byte speed_flags; 36 | byte chip_flags; 37 | byte unused [4]; 38 | }; 39 | 40 | // Header for currently loaded file 41 | header_t const& header() const { return header_; } 42 | 43 | static gme_type_t static_type() { return gme_nsf_type; } 44 | 45 | public: 46 | // deprecated 47 | using Music_Emu::load; 48 | blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader 49 | { return load_remaining_( &h, sizeof h, in ); } 50 | 51 | public: 52 | Nsf_Emu(); 53 | ~Nsf_Emu(); 54 | Nes_Apu* apu_() { return &apu; } 55 | protected: 56 | blargg_err_t track_info_( track_info_t*, int track ) const; 57 | blargg_err_t load_( Data_Reader& ); 58 | blargg_err_t start_track_( int ); 59 | blargg_err_t run_clocks( blip_time_t&, int ); 60 | void set_tempo_( double ); 61 | void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); 62 | void update_eq( blip_eq_t const& ); 63 | void unload(); 64 | protected: 65 | enum { bank_count = 8 }; 66 | byte initial_banks [bank_count]; 67 | nes_addr_t init_addr; 68 | nes_addr_t play_addr; 69 | double clock_rate_; 70 | bool pal_only; 71 | 72 | // timing 73 | Nes_Cpu::registers_t saved_state; 74 | nes_time_t next_play; 75 | nes_time_t play_period; 76 | int play_extra; 77 | int play_ready; 78 | 79 | enum { rom_begin = 0x8000 }; 80 | enum { bank_select_addr = 0x5FF8 }; 81 | enum { bank_size = 0x1000 }; 82 | Rom_Data rom; 83 | 84 | public: private: friend class Nes_Cpu; 85 | void cpu_jsr( nes_addr_t ); 86 | int cpu_read( nes_addr_t ); 87 | void cpu_write( nes_addr_t, int ); 88 | void cpu_write_misc( nes_addr_t, int ); 89 | enum { badop_addr = bank_select_addr }; 90 | 91 | private: 92 | class Nes_Namco_Apu* namco; 93 | class Nes_Vrc6_Apu* vrc6; 94 | class Nes_Fme7_Apu* fme7; 95 | Nes_Apu apu; 96 | static int pcm_read( void*, nes_addr_t ); 97 | blargg_err_t init_sound(); 98 | 99 | header_t header_; 100 | 101 | enum { sram_addr = 0x6000 }; 102 | byte sram [0x2000]; 103 | byte unmapped_code [Nes_Cpu::page_size + 8]; 104 | }; 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Nsfe_Emu.h: -------------------------------------------------------------------------------- 1 | // Nintendo NES/Famicom NSFE music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef NSFE_EMU_H 5 | #define NSFE_EMU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Nsf_Emu.h" 9 | 10 | // Allows reading info from NSFE file without creating emulator 11 | class Nsfe_Info { 12 | public: 13 | blargg_err_t load( Data_Reader&, Nsf_Emu* ); 14 | 15 | struct info_t : Nsf_Emu::header_t 16 | { 17 | char game [256]; 18 | char author [256]; 19 | char copyright [256]; 20 | char dumper [256]; 21 | } info; 22 | 23 | void disable_playlist( bool = true ); 24 | 25 | blargg_err_t track_info_( track_info_t* out, int track ) const; 26 | 27 | int remap_track( int i ) const; 28 | 29 | void unload(); 30 | 31 | Nsfe_Info(); 32 | ~Nsfe_Info(); 33 | private: 34 | blargg_vector track_name_data; 35 | blargg_vector track_names; 36 | blargg_vector playlist; 37 | blargg_vector track_times; 38 | int actual_track_count_; 39 | bool playlist_disabled; 40 | }; 41 | 42 | class Nsfe_Emu : public Nsf_Emu { 43 | public: 44 | static gme_type_t static_type() { return gme_nsfe_type; } 45 | 46 | public: 47 | // deprecated 48 | struct header_t { char tag [4]; }; 49 | using Music_Emu::load; 50 | blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader 51 | { return load_remaining_( &h, sizeof h, in ); } 52 | void disable_playlist( bool = true ); // use clear_playlist() 53 | 54 | public: 55 | Nsfe_Emu(); 56 | ~Nsfe_Emu(); 57 | protected: 58 | blargg_err_t load_( Data_Reader& ); 59 | blargg_err_t track_info_( track_info_t*, int track ) const; 60 | blargg_err_t start_track_( int ); 61 | void unload(); 62 | void clear_playlist_(); 63 | private: 64 | Nsfe_Info info; 65 | bool loading; 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Sap_Apu.h: -------------------------------------------------------------------------------- 1 | // Atari POKEY sound chip emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef SAP_APU_H 5 | #define SAP_APU_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | class Sap_Apu_Impl; 11 | 12 | class Sap_Apu { 13 | public: 14 | enum { osc_count = 4 }; 15 | void osc_output( int index, Blip_Buffer* ); 16 | 17 | void reset( Sap_Apu_Impl* ); 18 | 19 | enum { start_addr = 0xD200 }; 20 | enum { end_addr = 0xD209 }; 21 | void write_data( blip_time_t, unsigned addr, int data ); 22 | 23 | void end_frame( blip_time_t ); 24 | 25 | public: 26 | Sap_Apu(); 27 | private: 28 | struct osc_t 29 | { 30 | unsigned char regs [2]; 31 | unsigned char phase; 32 | unsigned char invert; 33 | int last_amp; 34 | blip_time_t delay; 35 | blip_time_t period; // always recalculated before use; here for convenience 36 | Blip_Buffer* output; 37 | }; 38 | osc_t oscs [osc_count]; 39 | Sap_Apu_Impl* impl; 40 | blip_time_t last_time; 41 | int poly5_pos; 42 | int poly4_pos; 43 | int polym_pos; 44 | int control; 45 | 46 | void calc_periods(); 47 | void run_until( blip_time_t ); 48 | 49 | enum { poly4_len = (1L << 4) - 1 }; 50 | enum { poly9_len = (1L << 9) - 1 }; 51 | enum { poly17_len = (1L << 17) - 1 }; 52 | friend class Sap_Apu_Impl; 53 | }; 54 | 55 | // Common tables and Blip_Synth that can be shared among multiple Sap_Apu objects 56 | class Sap_Apu_Impl { 57 | public: 58 | Blip_Synth synth; 59 | 60 | Sap_Apu_Impl(); 61 | void volume( double d ) { synth.volume( 1.0 / Sap_Apu::osc_count / 30 * d ); } 62 | 63 | private: 64 | typedef unsigned char byte; 65 | byte poly4 [Sap_Apu::poly4_len / 8 + 1]; 66 | byte poly9 [Sap_Apu::poly9_len / 8 + 1]; 67 | byte poly17 [Sap_Apu::poly17_len / 8 + 1]; 68 | friend class Sap_Apu; 69 | }; 70 | 71 | inline void Sap_Apu::osc_output( int i, Blip_Buffer* b ) 72 | { 73 | assert( (unsigned) i < osc_count ); 74 | oscs [i].output = b; 75 | } 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Sap_Cpu.h: -------------------------------------------------------------------------------- 1 | // Atari 6502 CPU emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef SAP_CPU_H 5 | #define SAP_CPU_H 6 | 7 | #include "blargg_common.h" 8 | 9 | typedef blargg_long sap_time_t; // clock cycle count 10 | typedef unsigned sap_addr_t; // 16-bit address 11 | enum { future_sap_time = INT_MAX / 2 + 1 }; 12 | 13 | class Sap_Cpu { 14 | public: 15 | // Clear all registers and keep pointer to 64K memory passed in 16 | void reset( void* mem_64k ); 17 | 18 | // Run until specified time is reached. Returns true if suspicious/unsupported 19 | // instruction was encountered at any point during run. 20 | bool run( sap_time_t end_time ); 21 | 22 | // Registers are not updated until run() returns (except I flag in status) 23 | struct registers_t { 24 | uint16_t pc; 25 | uint8_t a; 26 | uint8_t x; 27 | uint8_t y; 28 | uint8_t status; 29 | uint8_t sp; 30 | }; 31 | registers_t r; 32 | 33 | enum { idle_addr = 0xFEFF }; 34 | 35 | // Time of beginning of next instruction to be executed 36 | sap_time_t time() const { return state->time + state->base; } 37 | void set_time( sap_time_t t ) { state->time = t - state->base; } 38 | void adjust_time( int delta ) { state->time += delta; } 39 | 40 | sap_time_t irq_time() const { return irq_time_; } 41 | void set_irq_time( sap_time_t ); 42 | 43 | sap_time_t end_time() const { return end_time_; } 44 | void set_end_time( sap_time_t ); 45 | 46 | public: 47 | Sap_Cpu() { state = &state_; } 48 | enum { irq_inhibit = 0x04 }; 49 | private: 50 | struct state_t { 51 | sap_time_t base; 52 | sap_time_t time; 53 | }; 54 | state_t* state; // points to state_ or a local copy within run() 55 | state_t state_; 56 | sap_time_t irq_time_; 57 | sap_time_t end_time_; 58 | uint8_t* mem; 59 | 60 | inline sap_time_t update_end_time( sap_time_t end, sap_time_t irq ); 61 | }; 62 | 63 | inline sap_time_t Sap_Cpu::update_end_time( sap_time_t t, sap_time_t irq ) 64 | { 65 | if ( irq < t && !(r.status & irq_inhibit) ) t = irq; 66 | sap_time_t delta = state->base - t; 67 | state->base = t; 68 | return delta; 69 | } 70 | 71 | inline void Sap_Cpu::set_irq_time( sap_time_t t ) 72 | { 73 | state->time += update_end_time( end_time_, (irq_time_ = t) ); 74 | } 75 | 76 | inline void Sap_Cpu::set_end_time( sap_time_t t ) 77 | { 78 | state->time += update_end_time( (end_time_ = t), irq_time_ ); 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Sap_Emu.h: -------------------------------------------------------------------------------- 1 | // Atari XL/XE SAP music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef SAP_EMU_H 5 | #define SAP_EMU_H 6 | 7 | #include "Classic_Emu.h" 8 | #include "Sap_Apu.h" 9 | #include "Sap_Cpu.h" 10 | 11 | class Sap_Emu : private Sap_Cpu, public Classic_Emu { 12 | typedef Sap_Cpu cpu; 13 | public: 14 | static gme_type_t static_type() { return gme_sap_type; } 15 | public: 16 | Sap_Emu(); 17 | ~Sap_Emu(); 18 | struct info_t { 19 | byte const* rom_data; 20 | const char* warning; 21 | long init_addr; 22 | long play_addr; 23 | long music_addr; 24 | int type; 25 | int track_count; 26 | int fastplay; 27 | bool stereo; 28 | char author [256]; 29 | char name [256]; 30 | char copyright [ 32]; 31 | }; 32 | protected: 33 | blargg_err_t track_info_( track_info_t*, int track ) const; 34 | blargg_err_t load_mem_( byte const*, long ); 35 | blargg_err_t start_track_( int ); 36 | blargg_err_t run_clocks( blip_time_t&, int ); 37 | void set_tempo_( double ); 38 | void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); 39 | void update_eq( blip_eq_t const& ); 40 | public: private: friend class Sap_Cpu; 41 | int cpu_read( sap_addr_t ); 42 | void cpu_write( sap_addr_t, int ); 43 | void cpu_write_( sap_addr_t, int ); 44 | private: 45 | info_t info; 46 | 47 | byte const* file_end; 48 | sap_time_t scanline_period; 49 | sap_time_t next_play; 50 | sap_time_t time_mask; 51 | Sap_Apu apu; 52 | Sap_Apu apu2; 53 | 54 | // large items 55 | struct { 56 | byte padding1 [0x100]; 57 | byte ram [0x10000 + 0x100]; 58 | } mem; 59 | Sap_Apu_Impl apu_impl; 60 | 61 | sap_time_t play_period() const; 62 | void call_play(); 63 | void cpu_jsr( sap_addr_t ); 64 | void call_init( int track ); 65 | void run_routine( sap_addr_t ); 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Sms_Apu.h: -------------------------------------------------------------------------------- 1 | // Sega Master System SN76489 PSG sound chip emulator 2 | 3 | // Sms_Snd_Emu 0.1.4 4 | #ifndef SMS_APU_H 5 | #define SMS_APU_H 6 | 7 | #include "Sms_Oscs.h" 8 | 9 | class Sms_Apu { 10 | public: 11 | // Set overall volume of all oscillators, where 1.0 is full volume 12 | void volume( double ); 13 | 14 | // Set treble equalization 15 | void treble_eq( const blip_eq_t& ); 16 | 17 | // Outputs can be assigned to a single buffer for mono output, or to three 18 | // buffers for stereo output (using Stereo_Buffer to do the mixing). 19 | 20 | // Assign all oscillator outputs to specified buffer(s). If buffer 21 | // is NULL, silences all oscillators. 22 | void output( Blip_Buffer* mono ); 23 | void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); 24 | 25 | // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3, 26 | // which refer to Square 1, Square 2, Square 3, and Noise. If buffer is NULL, 27 | // silences oscillator. 28 | enum { osc_count = 4 }; 29 | void osc_output( int index, Blip_Buffer* mono ); 30 | void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); 31 | 32 | // Reset oscillators and internal state 33 | void reset( unsigned noise_feedback = 0, int noise_width = 0 ); 34 | 35 | // Write GameGear left/right assignment byte 36 | void write_ggstereo( blip_time_t, int ); 37 | 38 | // Write to data port 39 | void write_data( blip_time_t, int ); 40 | 41 | // Run all oscillators up to specified time, end current frame, then 42 | // start a new frame at time 0. 43 | void end_frame( blip_time_t ); 44 | 45 | public: 46 | Sms_Apu(); 47 | ~Sms_Apu(); 48 | private: 49 | // noncopyable 50 | Sms_Apu( const Sms_Apu& ); 51 | Sms_Apu& operator = ( const Sms_Apu& ); 52 | 53 | Sms_Osc* oscs [osc_count]; 54 | Sms_Square squares [3]; 55 | Sms_Square::Synth square_synth; // used by squares 56 | blip_time_t last_time; 57 | int latch; 58 | Sms_Noise noise; 59 | unsigned noise_feedback; 60 | unsigned looped_feedback; 61 | 62 | void run_until( blip_time_t ); 63 | }; 64 | 65 | struct sms_apu_state_t 66 | { 67 | unsigned char regs [8] [2]; 68 | unsigned char latch; 69 | }; 70 | 71 | inline void Sms_Apu::output( Blip_Buffer* b ) { output( b, b, b ); } 72 | 73 | inline void Sms_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Sms_Oscs.h: -------------------------------------------------------------------------------- 1 | // Private oscillators used by Sms_Apu 2 | 3 | // Sms_Snd_Emu 0.1.4 4 | #ifndef SMS_OSCS_H 5 | #define SMS_OSCS_H 6 | 7 | #include "blargg_common.h" 8 | #include "Blip_Buffer.h" 9 | 10 | struct Sms_Osc 11 | { 12 | Blip_Buffer* outputs [4]; // NULL, right, left, center 13 | Blip_Buffer* output; 14 | int output_select; 15 | 16 | int delay; 17 | int last_amp; 18 | int volume; 19 | 20 | Sms_Osc(); 21 | void reset(); 22 | }; 23 | 24 | struct Sms_Square : Sms_Osc 25 | { 26 | int period; 27 | int phase; 28 | 29 | typedef Blip_Synth Synth; 30 | const Synth* synth; 31 | 32 | void reset(); 33 | void run( blip_time_t, blip_time_t ); 34 | }; 35 | 36 | struct Sms_Noise : Sms_Osc 37 | { 38 | const int* period; 39 | unsigned shifter; 40 | unsigned feedback; 41 | 42 | typedef Blip_Synth Synth; 43 | Synth synth; 44 | 45 | void reset(); 46 | void run( blip_time_t, blip_time_t ); 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Spc_Emu.h: -------------------------------------------------------------------------------- 1 | // Super Nintendo SPC music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef SPC_EMU_H 5 | #define SPC_EMU_H 6 | 7 | #include "Fir_Resampler.h" 8 | #include "Music_Emu.h" 9 | #include "Snes_Spc.h" 10 | #include "Spc_Filter.h" 11 | 12 | class Spc_Emu : public Music_Emu { 13 | public: 14 | // The Super Nintendo hardware samples at 32kHz. Other sample rates are 15 | // handled by resampling the 32kHz output; emulation accuracy is not affected. 16 | enum { native_sample_rate = 32000 }; 17 | 18 | // SPC file header 19 | enum { header_size = 0x100 }; 20 | struct header_t 21 | { 22 | char tag [35]; 23 | byte format; 24 | byte version; 25 | byte pc [2]; 26 | byte a, x, y, psw, sp; 27 | byte unused [2]; 28 | char song [32]; 29 | char game [32]; 30 | char dumper [16]; 31 | char comment [32]; 32 | byte date [11]; 33 | byte len_secs [3]; 34 | byte fade_msec [4]; 35 | char author [32]; // sometimes first char should be skipped (see official SPC spec) 36 | byte mute_mask; 37 | byte emulator; 38 | byte unused2 [46]; 39 | }; 40 | 41 | // Header for currently loaded file 42 | header_t const& header() const { return *(header_t const*) file_data; } 43 | 44 | // Prevents channels and global volumes from being phase-negated 45 | void disable_surround( bool disable = true ); 46 | 47 | static gme_type_t static_type() { return gme_spc_type; } 48 | 49 | public: 50 | // deprecated 51 | using Music_Emu::load; 52 | blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader 53 | { return load_remaining_( &h, sizeof h, in ); } 54 | byte const* trailer() const; // use track_info() 55 | long trailer_size() const; 56 | 57 | public: 58 | Spc_Emu(); 59 | ~Spc_Emu(); 60 | protected: 61 | blargg_err_t load_mem_( byte const*, long ); 62 | blargg_err_t track_info_( track_info_t*, int track ) const; 63 | blargg_err_t set_sample_rate_( long ); 64 | blargg_err_t start_track_( int ); 65 | blargg_err_t play_( long, sample_t* ); 66 | blargg_err_t skip_( long ); 67 | void mute_voices_( int ); 68 | void set_tempo_( double ); 69 | void enable_accuracy_( bool ); 70 | private: 71 | byte const* file_data; 72 | long file_size; 73 | Fir_Resampler<24> resampler; 74 | SPC_Filter filter; 75 | Snes_Spc apu; 76 | 77 | blargg_err_t play_and_filter( long count, sample_t out [] ); 78 | }; 79 | 80 | inline void Spc_Emu::disable_surround( bool b ) { apu.disable_surround( b ); } 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Spc_Filter.cpp: -------------------------------------------------------------------------------- 1 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 2 | 3 | #include "Spc_Filter.h" 4 | 5 | #include 6 | 7 | /* Copyright (C) 2007 Shay Green. This module is free software; you 8 | can redistribute it and/or modify it under the terms of the GNU Lesser 9 | General Public License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. This 11 | module is distributed in the hope that it will be useful, but WITHOUT ANY 12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | details. You should have received a copy of the GNU Lesser General Public 15 | License along with this module; if not, write to the Free Software Foundation, 16 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 17 | 18 | #include "blargg_source.h" 19 | 20 | void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); } 21 | 22 | SPC_Filter::SPC_Filter() 23 | { 24 | enabled = true; 25 | gain = gain_unit; 26 | bass = bass_norm; 27 | clear(); 28 | } 29 | 30 | void SPC_Filter::run( short* io, int count ) 31 | { 32 | require( (count & 1) == 0 ); // must be even 33 | 34 | int const gain = this->gain; 35 | if ( enabled ) 36 | { 37 | int const bass = this->bass; 38 | chan_t* c = &ch [2]; 39 | do 40 | { 41 | // cache in registers 42 | int sum = (--c)->sum; 43 | int pp1 = c->pp1; 44 | int p1 = c->p1; 45 | 46 | for ( int i = 0; i < count; i += 2 ) 47 | { 48 | // Low-pass filter (two point FIR with coeffs 0.25, 0.75) 49 | int f = io [i] + p1; 50 | p1 = io [i] * 3; 51 | 52 | // High-pass filter ("leaky integrator") 53 | int delta = f - pp1; 54 | pp1 = f; 55 | int s = sum >> (gain_bits + 2); 56 | sum += (delta * gain) - (sum >> bass); 57 | 58 | // Clamp to 16 bits 59 | if ( (short) s != s ) 60 | s = (s >> 31) ^ 0x7FFF; 61 | 62 | io [i] = (short) s; 63 | } 64 | 65 | c->p1 = p1; 66 | c->pp1 = pp1; 67 | c->sum = sum; 68 | ++io; 69 | } 70 | while ( c != ch ); 71 | } 72 | else if ( gain != gain_unit ) 73 | { 74 | short* const end = io + count; 75 | while ( io < end ) 76 | { 77 | int s = (*io * gain) >> gain_bits; 78 | if ( (short) s != s ) 79 | s = (s >> 31) ^ 0x7FFF; 80 | *io++ = (short) s; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Spc_Filter.h: -------------------------------------------------------------------------------- 1 | // Simple low-pass and high-pass filter to better match sound output of a SNES 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef SPC_FILTER_H 5 | #define SPC_FILTER_H 6 | 7 | #include "blargg_common.h" 8 | 9 | struct SPC_Filter { 10 | public: 11 | 12 | // Filters count samples of stereo sound in place. Count must be a multiple of 2. 13 | typedef short sample_t; 14 | void run( sample_t* io, int count ); 15 | 16 | // Optional features 17 | 18 | // Clears filter to silence 19 | void clear(); 20 | 21 | // Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit 22 | // are fine, since output is clamped to 16-bit sample range. 23 | enum { gain_unit = 0x100 }; 24 | void set_gain( int gain ); 25 | 26 | // Enables/disables filtering (when disabled, gain is still applied) 27 | void enable( bool b ); 28 | 29 | // Sets amount of bass (logarithmic scale) 30 | enum { bass_none = 0 }; 31 | enum { bass_norm = 8 }; // normal amount 32 | enum { bass_max = 31 }; 33 | void set_bass( int bass ); 34 | 35 | public: 36 | SPC_Filter(); 37 | BLARGG_DISABLE_NOTHROW 38 | private: 39 | enum { gain_bits = 8 }; 40 | int gain; 41 | int bass; 42 | bool enabled; 43 | struct chan_t { int p1, pp1, sum; }; 44 | chan_t ch [2]; 45 | }; 46 | 47 | inline void SPC_Filter::enable( bool b ) { enabled = b; } 48 | 49 | inline void SPC_Filter::set_gain( int g ) { gain = g; } 50 | 51 | inline void SPC_Filter::set_bass( int b ) { bass = b; } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Vgm_Emu.h: -------------------------------------------------------------------------------- 1 | // Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef VGM_EMU_H 5 | #define VGM_EMU_H 6 | 7 | #include "Vgm_Emu_Impl.h" 8 | 9 | // Emulates VGM music using SN76489/SN76496 PSG, YM2612, and YM2413 FM sound chips. 10 | // Supports custom sound buffer and frequency equalization when VGM uses just the PSG. 11 | // FM sound chips can be run at their proper rates, or slightly higher to reduce 12 | // aliasing on high notes. Currently YM2413 support requires that you supply a 13 | // YM2413 sound chip emulator. I can provide one I've modified to work with the library. 14 | class Vgm_Emu : public Vgm_Emu_Impl { 15 | public: 16 | // True if custom buffer and custom equalization are supported 17 | // TODO: move into Music_Emu and rename to something like supports_custom_buffer() 18 | bool is_classic_emu() const { return !uses_fm; } 19 | 20 | blargg_err_t set_multi_channel ( bool is_enabled ) override; 21 | 22 | // Disable running FM chips at higher than normal rate. Will result in slightly 23 | // more aliasing of high notes. 24 | void disable_oversampling( bool disable = true ) { disable_oversampling_ = disable; } 25 | 26 | // VGM header format 27 | enum { header_size = 0x40 }; 28 | struct header_t 29 | { 30 | char tag [4]; 31 | byte data_size [4]; 32 | byte version [4]; 33 | byte psg_rate [4]; 34 | byte ym2413_rate [4]; 35 | byte gd3_offset [4]; 36 | byte track_duration [4]; 37 | byte loop_offset [4]; 38 | byte loop_duration [4]; 39 | byte frame_rate [4]; 40 | byte noise_feedback [2]; 41 | byte noise_width; 42 | byte unused1; 43 | byte ym2612_rate [4]; 44 | byte ym2151_rate [4]; 45 | byte data_offset [4]; 46 | byte unused2 [8]; 47 | }; 48 | 49 | // Header for currently loaded file 50 | header_t const& header() const { return *(header_t const*) data; } 51 | 52 | static gme_type_t static_type() { return gme_vgm_type; } 53 | 54 | public: 55 | // deprecated 56 | using Music_Emu::load; 57 | blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader 58 | { return load_remaining_( &h, sizeof h, in ); } 59 | byte const* gd3_data( int* size_out = 0 ) const; // use track_info() 60 | 61 | public: 62 | Vgm_Emu(); 63 | ~Vgm_Emu(); 64 | protected: 65 | blargg_err_t track_info_( track_info_t*, int track ) const; 66 | blargg_err_t load_mem_( byte const*, long ); 67 | blargg_err_t set_sample_rate_( long sample_rate ); 68 | blargg_err_t start_track_( int ); 69 | blargg_err_t play_( long count, sample_t* ); 70 | blargg_err_t run_clocks( blip_time_t&, int ); 71 | void set_tempo_( double ); 72 | void mute_voices_( int mask ); 73 | void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); 74 | void update_eq( blip_eq_t const& ); 75 | private: 76 | // removed; use disable_oversampling() and set_tempo() instead 77 | Vgm_Emu( bool oversample, double tempo = 1.0 ); 78 | double fm_rate; 79 | long psg_rate; 80 | long vgm_rate; 81 | bool disable_oversampling_; 82 | bool uses_fm; 83 | blargg_err_t setup_fm(); 84 | }; 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Vgm_Emu_Impl.h: -------------------------------------------------------------------------------- 1 | // Low-level parts of Vgm_Emu 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef VGM_EMU_IMPL_H 5 | #define VGM_EMU_IMPL_H 6 | 7 | #include "Dual_Resampler.h" 8 | #include "Classic_Emu.h" 9 | #include "Ym2413_Emu.h" 10 | #include "Ym2612_Emu.h" 11 | #include "Sms_Apu.h" 12 | 13 | template 14 | class Ym_Emu : public Emu { 15 | protected: 16 | int last_time; 17 | short* out; 18 | enum { disabled_time = -1 }; 19 | public: 20 | Ym_Emu() : last_time( disabled_time ), out( NULL ) { } 21 | void enable( bool b ) { last_time = b ? 0 : disabled_time; } 22 | bool enabled() const { return last_time != disabled_time; } 23 | void begin_frame( short* p ); 24 | int run_until( int time ); 25 | }; 26 | 27 | class Vgm_Emu_Impl : public Classic_Emu, private Dual_Resampler { 28 | public: 29 | typedef Classic_Emu::sample_t sample_t; 30 | protected: 31 | enum { stereo = 2 }; 32 | 33 | typedef int vgm_time_t; 34 | 35 | enum { fm_time_bits = 12 }; 36 | typedef int fm_time_t; 37 | long fm_time_offset; 38 | int fm_time_factor; 39 | fm_time_t to_fm_time( vgm_time_t ) const; 40 | 41 | enum { blip_time_bits = 12 }; 42 | int blip_time_factor; 43 | blip_time_t to_blip_time( vgm_time_t ) const; 44 | 45 | byte const* data; 46 | byte const* loop_begin; 47 | byte const* data_end; 48 | void update_fm_rates( long* ym2413_rate, long* ym2612_rate ) const; 49 | 50 | vgm_time_t vgm_time; 51 | byte const* pos; 52 | blip_time_t run_commands( vgm_time_t ); 53 | int play_frame( blip_time_t blip_time, int sample_count, sample_t* buf ); 54 | 55 | byte const* pcm_data; 56 | byte const* pcm_pos; 57 | int dac_amp; 58 | int dac_disabled; // -1 if disabled 59 | void write_pcm( vgm_time_t, int amp ); 60 | 61 | Ym_Emu ym2612[2]; 62 | Ym_Emu ym2413[2]; 63 | 64 | Blip_Buffer blip_buf; 65 | Sms_Apu psg[2]; 66 | bool psg_dual; 67 | bool psg_t6w28; 68 | Blip_Synth dac_synth; 69 | 70 | friend class Vgm_Emu; 71 | }; 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ym2413_Emu.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Use in place of Ym2413_Emu.cpp and ym2413.c to disable support for this chip 3 | 4 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 5 | 6 | #include "Ym2413_Emu.h" 7 | 8 | Ym2413_Emu::Ym2413_Emu() { } 9 | 10 | Ym2413_Emu::~Ym2413_Emu() { } 11 | 12 | int Ym2413_Emu::set_rate( double, double ) { return 2; } 13 | 14 | void Ym2413_Emu::reset() { } 15 | 16 | void Ym2413_Emu::write( int, int ) { } 17 | 18 | void Ym2413_Emu::mute_voices( int ) { } 19 | 20 | void Ym2413_Emu::run( int, sample_t* ) { } 21 | 22 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ym2413_Emu.h: -------------------------------------------------------------------------------- 1 | // YM2413 FM sound chip emulator interface 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef YM2413_EMU_H 5 | #define YM2413_EMU_H 6 | 7 | class Ym2413_Emu { 8 | struct OPLL* opll; 9 | public: 10 | Ym2413_Emu(); 11 | ~Ym2413_Emu(); 12 | 13 | // Set output sample rate and chip clock rates, in Hz. Returns non-zero 14 | // if error. 15 | int set_rate( double sample_rate, double clock_rate ); 16 | 17 | // Reset to power-up state 18 | void reset(); 19 | 20 | // Mute voice n if bit n (1 << n) of mask is set 21 | enum { channel_count = 14 }; 22 | void mute_voices( int mask ); 23 | 24 | // Write 'data' to 'addr' 25 | void write( int addr, int data ); 26 | 27 | // Run and write pair_count samples to output 28 | typedef short sample_t; 29 | enum { out_chan_count = 2 }; // stereo 30 | void run( int pair_count, sample_t* out ); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ym2612_Emu.h: -------------------------------------------------------------------------------- 1 | // YM2612 FM sound chip emulator interface 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | 5 | #include "gme_types.h" 6 | 7 | #ifdef VGM_YM2612_GENS // LGPL v2.1+ license 8 | #include "Ym2612_GENS.h" 9 | typedef Ym2612_GENS_Emu Ym2612_Emu; 10 | #endif 11 | 12 | #ifdef VGM_YM2612_NUKED // LGPL v2.1+ license 13 | #include "Ym2612_Nuked.h" 14 | typedef Ym2612_Nuked_Emu Ym2612_Emu; 15 | #endif 16 | 17 | #ifdef VGM_YM2612_MAME // GPL v2+ license 18 | #include "Ym2612_MAME.h" 19 | typedef Ym2612_MAME_Emu Ym2612_Emu; 20 | #endif 21 | 22 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ym2612_GENS.h: -------------------------------------------------------------------------------- 1 | // YM2612 FM sound chip emulator interface 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef YM2612_EMU_H 5 | #define YM2612_EMU_H 6 | 7 | struct Ym2612_GENS_Impl; 8 | 9 | class Ym2612_GENS_Emu { 10 | Ym2612_GENS_Impl* impl; 11 | public: 12 | Ym2612_GENS_Emu() { impl = 0; } 13 | ~Ym2612_GENS_Emu(); 14 | 15 | // Set output sample rate and chip clock rates, in Hz. Returns non-zero 16 | // if error. 17 | const char* set_rate( double sample_rate, double clock_rate ); 18 | 19 | // Reset to power-up state 20 | void reset(); 21 | 22 | // Mute voice n if bit n (1 << n) of mask is set 23 | enum { channel_count = 6 }; 24 | void mute_voices( int mask ); 25 | 26 | // Write addr to register 0 then data to register 1 27 | void write0( int addr, int data ); 28 | 29 | // Write addr to register 2 then data to register 3 30 | void write1( int addr, int data ); 31 | 32 | // Run and add pair_count samples into current output buffer contents 33 | typedef short sample_t; 34 | enum { out_chan_count = 2 }; // stereo 35 | void run( int pair_count, sample_t* out ); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ym2612_MAME.h: -------------------------------------------------------------------------------- 1 | // YM2612 FM sound chip emulator interface 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef YM2612_EMU_H 5 | #define YM2612_EMU_H 6 | 7 | typedef void Ym2612_MAME_Impl; 8 | 9 | class Ym2612_MAME_Emu { 10 | Ym2612_MAME_Impl* impl; 11 | public: 12 | Ym2612_MAME_Emu(); 13 | ~Ym2612_MAME_Emu(); 14 | 15 | // Set output sample rate and chip clock rates, in Hz. Returns non-zero 16 | // if error. 17 | const char* set_rate( double sample_rate, double clock_rate ); 18 | 19 | // Reset to power-up state 20 | void reset(); 21 | 22 | // Mute voice n if bit n (1 << n) of mask is set 23 | enum { channel_count = 6 }; 24 | void mute_voices( int mask ); 25 | 26 | // Write addr to register 0 then data to register 1 27 | void write0( int addr, int data ); 28 | 29 | // Write addr to register 2 then data to register 3 30 | void write1( int addr, int data ); 31 | 32 | // Run and add pair_count samples into current output buffer contents 33 | typedef short sample_t; 34 | enum { out_chan_count = 2 }; // stereo 35 | void run( int pair_count, sample_t* out ); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/Ym2612_Nuked.h: -------------------------------------------------------------------------------- 1 | // YM2612 FM sound chip emulator interface 2 | 3 | // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ 4 | #ifndef YM2612_EMU_H 5 | #define YM2612_EMU_H 6 | 7 | typedef void Ym2612_Nuked_Impl; 8 | 9 | class Ym2612_Nuked_Emu { 10 | Ym2612_Nuked_Impl* impl; 11 | double prev_sample_rate; 12 | double prev_clock_rate; 13 | public: 14 | Ym2612_Nuked_Emu(); 15 | ~Ym2612_Nuked_Emu(); 16 | 17 | // Set output sample rate and chip clock rates, in Hz. Returns non-zero 18 | // if error. 19 | const char* set_rate( double sample_rate, double clock_rate ); 20 | 21 | // Reset to power-up state 22 | void reset(); 23 | 24 | // Mute voice n if bit n (1 << n) of mask is set 25 | enum { channel_count = 6 }; 26 | void mute_voices( int mask ); 27 | 28 | // Write addr to register 0 then data to register 1 29 | void write0( int addr, int data ); 30 | 31 | // Write addr to register 2 then data to register 3 32 | void write1( int addr, int data ); 33 | 34 | // Run and add pair_count samples into current output buffer contents 35 | typedef short sample_t; 36 | enum { out_chan_count = 2 }; // stereo 37 | void run( int pair_count, sample_t* out ); 38 | }; 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/blargg_config.h: -------------------------------------------------------------------------------- 1 | // Library configuration. Modify this file as necessary. 2 | 3 | #ifndef BLARGG_CONFIG_H 4 | #define BLARGG_CONFIG_H 5 | 6 | // Uncomment to use zlib for transparent decompression of gzipped files 7 | //#define HAVE_ZLIB_H 8 | 9 | // Uncomment and edit list to support only the listed game music types, 10 | // so that the others don't get linked in at all. 11 | /* 12 | #define GME_TYPE_LIST \ 13 | gme_ay_type,\ 14 | gme_gbs_type,\ 15 | gme_gym_type,\ 16 | gme_hes_type,\ 17 | gme_kss_type,\ 18 | gme_nsf_type,\ 19 | gme_nsfe_type,\ 20 | gme_sap_type,\ 21 | gme_spc_type,\ 22 | gme_vgm_type,\ 23 | gme_vgz_type 24 | */ 25 | 26 | // Uncomment to enable platform-specific optimizations 27 | //#define BLARGG_NONPORTABLE 1 28 | 29 | // Uncomment to use faster, lower quality sound synthesis 30 | //#define BLIP_BUFFER_FAST 1 31 | 32 | // Uncomment if automatic byte-order determination doesn't work 33 | //#define BLARGG_BIG_ENDIAN 1 34 | 35 | // Uncomment if you get errors in the bool section of blargg_common.h 36 | //#define BLARGG_COMPILER_HAS_BOOL 1 37 | 38 | // Use standard config.h if present 39 | #ifdef HAVE_CONFIG_H 40 | #include "config.h" 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/blargg_source.h: -------------------------------------------------------------------------------- 1 | /* Included at the beginning of library source files, after all other #include lines. 2 | * Sets up helpful macros and services used in my source code. They don't need 3 | * module an annoying module prefix on their names since they are defined after 4 | * all other #include lines. */ 5 | 6 | #ifndef BLARGG_SOURCE_H 7 | #define BLARGG_SOURCE_H 8 | 9 | /* If debugging is enabled, abort program if expr is false. Meant for checking 10 | * internal state and consistency. A failed assertion indicates a bug in the module. 11 | * void assert( bool expr ); */ 12 | #include 13 | 14 | /* If debugging is enabled and expr is false, abort program. Meant for checking 15 | * caller-supplied parameters and operations that are outside the control of the 16 | * module. A failed requirement indicates a bug outside the module. 17 | * void require( bool expr ); */ 18 | #undef require 19 | 20 | #if DEBUG_BLARGG 21 | #define require( expr ) assert( expr ) 22 | #else 23 | #define require( expr ) ( expr ) 24 | #undef assert 25 | #define assert( expr ) ( expr ) 26 | #endif 27 | 28 | /* Use to provide hints to compiler for optimized code layout in situations where we 29 | * can almost always expect a conditional to go one way or the other. Should only be 30 | * used in situations where an unexpected branch is truly exceptional though! */ 31 | #undef likely 32 | #undef unlikely 33 | #ifdef __GNUC__ 34 | #define likely( x ) __builtin_expect(x, 1) 35 | #define unlikely( x ) __builtin_expect(x, 0) 36 | #else 37 | #define likely( x ) (x) 38 | #define unlikely( x ) (x) 39 | #endif 40 | 41 | /* Like printf() except output goes to debug log file. Might be defined to do 42 | * nothing (not even evaluate its arguments). 43 | * void debug_printf( const char* format, ... ); */ 44 | #if defined(__cplusplus) && defined(BLARGG_BUILD_DLL) 45 | static inline void blargg_dprintf_( const char* fmt_str, ... ) { (void) fmt_str; } 46 | #undef debug_printf 47 | #define debug_printf (1) ? (void) 0 : blargg_dprintf_ 48 | #else 49 | #define NDEBUG 50 | #endif 51 | 52 | /* If enabled, evaluate expr and if false, make debug log entry with source file 53 | * and line. Meant for finding situations that should be examined further, but that 54 | * don't indicate a problem. In all cases, execution continues normally. */ 55 | #undef check 56 | #define check( expr ) ((void) 0) 57 | 58 | /* If expr yields error string, return it from current function, otherwise continue. */ 59 | #undef RETURN_ERR 60 | #define RETURN_ERR( expr ) do { \ 61 | blargg_err_t blargg_return_err_ = (expr); \ 62 | if ( blargg_return_err_ ) return blargg_return_err_; \ 63 | } while ( 0 ) 64 | 65 | /* If ptr is 0, return out of memory error string. */ 66 | #undef CHECK_ALLOC 67 | #define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) 68 | 69 | /* TODO: good idea? bad idea? */ 70 | #undef byte 71 | #define byte byte_ 72 | typedef unsigned char byte; 73 | 74 | /* Setup compiler defines useful for exporting required public API symbols in gme.cpp */ 75 | #ifndef BLARGG_EXPORT 76 | #if defined (_WIN32) 77 | #if defined(BLARGG_BUILD_DLL) 78 | #define BLARGG_EXPORT __declspec(dllexport) 79 | #else 80 | #define BLARGG_EXPORT /* Leave blank: friendly with both static and shared linking */ 81 | #endif 82 | #elif defined (LIBGME_VISIBILITY) && defined(__cplusplus) 83 | #define BLARGG_EXPORT __attribute__((visibility ("default"))) 84 | #else 85 | #define BLARGG_EXPORT 86 | #endif 87 | #endif 88 | 89 | /* deprecated */ 90 | #define BLARGG_CHECK_ALLOC CHECK_ALLOC 91 | #define BLARGG_RETURN_ERR RETURN_ERR 92 | 93 | /* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of debug_printf and check */ 94 | #ifdef BLARGG_SOURCE_BEGIN 95 | #include BLARGG_SOURCE_BEGIN 96 | #endif 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/gb_cpu_io.h: -------------------------------------------------------------------------------- 1 | 2 | #include "Gbs_Emu.h" 3 | 4 | #include "blargg_source.h" 5 | 6 | int Gbs_Emu::cpu_read( gb_addr_t addr ) 7 | { 8 | int result = *cpu::get_code( addr ); 9 | if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count ) 10 | result = apu.read_register( clock(), addr ); 11 | #ifndef NDEBUG 12 | else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 ) 13 | debug_printf( "Read from unmapped memory $%.4x\n", (unsigned) addr ); 14 | else if ( unsigned (addr - 0xFF01) < 0xFF80 - 0xFF01 ) 15 | debug_printf( "Unhandled I/O read 0x%4X\n", (unsigned) addr ); 16 | #endif 17 | return result; 18 | } 19 | 20 | void Gbs_Emu::cpu_write( gb_addr_t addr, int data ) 21 | { 22 | unsigned offset = addr - ram_addr; 23 | if ( offset <= 0xFFFF - ram_addr ) 24 | { 25 | ram [offset] = data; 26 | if ( (addr ^ 0xE000) <= 0x1F80 - 1 ) 27 | { 28 | if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count ) 29 | { 30 | GME_APU_HOOK( this, addr - Gb_Apu::start_addr, data ); 31 | apu.write_register( clock(), addr, data ); 32 | } 33 | else if ( (addr ^ 0xFF06) < 2 ) 34 | update_timer(); 35 | else if ( addr == joypad_addr ) 36 | ram [offset] = 0; // keep joypad return value 0 37 | else 38 | ram [offset] = 0xFF; 39 | 40 | //if ( addr == 0xFFFF ) 41 | // debug_printf( "Wrote interrupt mask\n" ); 42 | } 43 | } 44 | else if ( (addr ^ 0x2000) <= 0x2000 - 1 ) 45 | { 46 | set_bank( data ); 47 | } 48 | #ifndef NDEBUG 49 | else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 ) 50 | { 51 | debug_printf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr ); 52 | } 53 | #endif 54 | } 55 | 56 | #define CPU_READ_FAST( cpu, addr, time, out ) \ 57 | CPU_READ_FAST_( STATIC_CAST(Gbs_Emu*,cpu), addr, time, out ) 58 | 59 | #define CPU_READ_FAST_( emu, addr, time, out ) \ 60 | {\ 61 | out = READ_PROG( addr );\ 62 | if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count )\ 63 | out = emu->apu.read_register( emu->cpu_time - time * clocks_per_instr, addr );\ 64 | else\ 65 | check( out == emu->cpu_read( addr ) );\ 66 | } 67 | 68 | #define CPU_READ( cpu, addr, time ) \ 69 | STATIC_CAST(Gbs_Emu*,cpu)->cpu_read( addr ) 70 | 71 | #define CPU_WRITE( cpu, addr, data, time ) \ 72 | STATIC_CAST(Gbs_Emu*,cpu)->cpu_write( addr, data ) 73 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/gme_types.h: -------------------------------------------------------------------------------- 1 | #ifndef GME_TYPES_H 2 | #define GME_TYPES_H 3 | 4 | /* 5 | * This is a default gme_types.h for use when *not* using 6 | * CMake. If CMake is in use gme_types.h.in will be 7 | * processed instead. 8 | */ 9 | #define USE_GME_AY 10 | #define USE_GME_GBS 11 | #define USE_GME_GYM 12 | #define USE_GME_HES 13 | #define USE_GME_KSS 14 | #define USE_GME_NSF 15 | #define USE_GME_NSFE 16 | #define USE_GME_SAP 17 | #define USE_GME_SPC 18 | /* VGM and VGZ are a package deal */ 19 | #define USE_GME_VGM 20 | #define VGM_YM2612_GENS 21 | 22 | #endif /* GME_TYPES_H */ 23 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/hes_cpu_io.h: -------------------------------------------------------------------------------- 1 | 2 | #include "Hes_Emu.h" 3 | 4 | #include "blargg_source.h" 5 | 6 | int Hes_Emu::cpu_read( hes_addr_t addr ) 7 | { 8 | check( addr <= 0xFFFF ); 9 | int result = *cpu::get_code( addr ); 10 | if ( mmr [addr >> page_shift] == 0xFF ) 11 | result = cpu_read_( addr ); 12 | return result; 13 | } 14 | 15 | void Hes_Emu::cpu_write( hes_addr_t addr, int data ) 16 | { 17 | check( addr <= 0xFFFF ); 18 | byte* out = write_pages [addr >> page_shift]; 19 | addr &= page_size - 1; 20 | if ( out ) 21 | out [addr] = data; 22 | else if ( mmr [addr >> page_shift] == 0xFF ) 23 | cpu_write_( addr, data ); 24 | } 25 | 26 | inline byte const* Hes_Emu::cpu_set_mmr( int page, int bank ) 27 | { 28 | write_pages [page] = 0; 29 | if ( bank < 0x80 ) 30 | return rom.at_addr( bank * (blargg_long) page_size ); 31 | 32 | byte* data = 0; 33 | switch ( bank ) 34 | { 35 | case 0xF8: 36 | data = cpu::ram; 37 | break; 38 | 39 | case 0xF9: 40 | case 0xFA: 41 | case 0xFB: 42 | data = &sgx [(bank - 0xF9) * page_size]; 43 | break; 44 | 45 | default: 46 | #ifndef NDEBUG 47 | if ( bank != 0xFF ) 48 | debug_printf( "Unmapped bank $%02X\n", bank ); 49 | #endif 50 | return rom.unmapped(); 51 | } 52 | 53 | write_pages [page] = data; 54 | return data; 55 | } 56 | 57 | #define CPU_READ_FAST( cpu, addr, time, out ) \ 58 | CPU_READ_FAST_( STATIC_CAST(Hes_Emu*,cpu), addr, time, out ) 59 | 60 | #define CPU_READ_FAST_( cpu, addr, time, out ) \ 61 | {\ 62 | out = READ_PROG( addr );\ 63 | if ( mmr [addr >> page_shift] == 0xFF )\ 64 | {\ 65 | FLUSH_TIME();\ 66 | out = cpu->cpu_read_( addr );\ 67 | CACHE_TIME();\ 68 | }\ 69 | } 70 | 71 | #define CPU_WRITE_FAST( cpu, addr, data, time ) \ 72 | CPU_WRITE_FAST_( STATIC_CAST(Hes_Emu*,cpu), addr, data, time ) 73 | 74 | #define CPU_WRITE_FAST_( cpu, addr, data, time ) \ 75 | {\ 76 | byte* out = cpu->write_pages [addr >> page_shift];\ 77 | addr &= page_size - 1;\ 78 | if ( out )\ 79 | {\ 80 | out [addr] = data;\ 81 | }\ 82 | else if ( mmr [addr >> page_shift] == 0xFF )\ 83 | {\ 84 | FLUSH_TIME();\ 85 | cpu->cpu_write_( addr, data );\ 86 | CACHE_TIME();\ 87 | }\ 88 | } 89 | 90 | #define CPU_READ( cpu, addr, time ) \ 91 | STATIC_CAST(Hes_Emu*,cpu)->cpu_read( addr ) 92 | 93 | #define CPU_WRITE( cpu, addr, data, time ) \ 94 | STATIC_CAST(Hes_Emu*,cpu)->cpu_write( addr, data ) 95 | 96 | #define CPU_WRITE_VDP( cpu, addr, data, time ) \ 97 | STATIC_CAST(Hes_Emu*,cpu)->cpu_write_vdp( addr, data ) 98 | 99 | #define CPU_SET_MMR( cpu, page, bank ) \ 100 | STATIC_CAST(Hes_Emu*,cpu)->cpu_set_mmr( page, bank ) 101 | 102 | #define CPU_DONE( cpu, time, result_out ) \ 103 | result_out = STATIC_CAST(Hes_Emu*,cpu)->cpu_done() 104 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/nes_cpu_io.h: -------------------------------------------------------------------------------- 1 | 2 | #include "Nsf_Emu.h" 3 | 4 | #if !NSF_EMU_APU_ONLY 5 | #include "Nes_Namco_Apu.h" 6 | #endif 7 | 8 | #include "blargg_source.h" 9 | 10 | int Nsf_Emu::cpu_read( nes_addr_t addr ) 11 | { 12 | int result; 13 | 14 | result = cpu::low_mem [addr & 0x7FF]; 15 | if ( !(addr & 0xE000) ) 16 | goto exit; 17 | 18 | result = *cpu::get_code( addr ); 19 | if ( addr > 0x7FFF ) 20 | goto exit; 21 | 22 | result = sram [addr & (sizeof sram - 1)]; 23 | if ( addr > 0x5FFF ) 24 | goto exit; 25 | 26 | if ( addr == Nes_Apu::status_addr ) 27 | return apu.read_status( cpu::time() ); 28 | 29 | #if !NSF_EMU_APU_ONLY 30 | if ( addr == Nes_Namco_Apu::data_reg_addr && namco ) 31 | return namco->read_data(); 32 | #endif 33 | 34 | result = addr >> 8; // simulate open bus 35 | 36 | #ifndef NDEBUG 37 | if ( addr != 0x2002 ) 38 | debug_printf( "Read unmapped $%.4X\n", (unsigned) addr ); 39 | #endif 40 | 41 | exit: 42 | return result; 43 | } 44 | 45 | void Nsf_Emu::cpu_write( nes_addr_t addr, int data ) 46 | { 47 | { 48 | nes_addr_t offset = addr ^ sram_addr; 49 | if ( offset < sizeof sram ) 50 | { 51 | sram [offset] = data; 52 | return; 53 | } 54 | } 55 | { 56 | int temp = addr & 0x7FF; 57 | if ( !(addr & 0xE000) ) 58 | { 59 | cpu::low_mem [temp] = data; 60 | return; 61 | } 62 | } 63 | 64 | if ( unsigned (addr - Nes_Apu::start_addr) <= Nes_Apu::end_addr - Nes_Apu::start_addr ) 65 | { 66 | GME_APU_HOOK( this, addr - Nes_Apu::start_addr, data ); 67 | apu.write_register( cpu::time(), addr, data ); 68 | return; 69 | } 70 | 71 | unsigned bank = addr - bank_select_addr; 72 | if ( bank < bank_count ) 73 | { 74 | blargg_long offset = rom.mask_addr( data * (blargg_long) bank_size ); 75 | if ( offset >= rom.size() ) 76 | set_warning( "Invalid bank" ); 77 | cpu::map_code( (bank + 8) * bank_size, bank_size, rom.at_addr( offset ) ); 78 | return; 79 | } 80 | 81 | cpu_write_misc( addr, data ); 82 | } 83 | 84 | #define CPU_READ( cpu, addr, time ) STATIC_CAST(Nsf_Emu&,*cpu).cpu_read( addr ) 85 | #define CPU_WRITE( cpu, addr, data, time ) STATIC_CAST(Nsf_Emu&,*cpu).cpu_write( addr, data ) 86 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Engine/gme/sap_cpu_io.h: -------------------------------------------------------------------------------- 1 | 2 | #include "Sap_Emu.h" 3 | 4 | #include "blargg_source.h" 5 | 6 | #define CPU_WRITE( cpu, addr, data, time ) STATIC_CAST(Sap_Emu&,*cpu).cpu_write( addr, data ) 7 | 8 | void Sap_Emu::cpu_write( sap_addr_t addr, int data ) 9 | { 10 | mem.ram [addr] = data; 11 | if ( (addr >> 8) == 0xD2 ) 12 | cpu_write_( addr, data ); 13 | } 14 | 15 | #ifdef NDEBUG 16 | #define CPU_READ( cpu, addr, time ) READ_LOW( addr ) 17 | #else 18 | #define CPU_READ( cpu, addr, time ) STATIC_CAST(Sap_Emu&,*cpu).cpu_read( addr ) 19 | 20 | int Sap_Emu::cpu_read( sap_addr_t addr ) 21 | { 22 | if ( (addr & 0xF900) == 0xD000 ) 23 | debug_printf( "Unmapped read $%04X\n", addr ); 24 | return mem.ram [addr]; 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/FilePicker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FilePicker.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 2/13/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import MobileCoreServices 11 | 12 | struct FilePicker: UIViewControllerRepresentable { 13 | @Environment(\.presentationMode) var presentationMode 14 | 15 | func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIDocumentPickerViewController { 16 | let sevenZipUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "7z" as CFString, nil)?.takeRetainedValue() as String? ?? "" 17 | let rarUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, "rar" as CFString, nil)?.takeRetainedValue() as String? ?? "" 18 | let documentTypes: [String] = [kUTTypeZipArchive as String, "com.abusman.nsf", "com.abusman.ay", "com.abusman.gbs", "com.abusman.gym", "com.abusman.hes", "com.abusman.kss", "com.abusman.sap", "com.abusman.spc", "com.abusman.vgm", sevenZipUTI, rarUTI] 19 | 20 | let picker = UIDocumentPickerViewController(documentTypes: documentTypes, in: .import) 21 | picker.allowsMultipleSelection = true 22 | picker.delegate = context.coordinator 23 | return picker 24 | } 25 | 26 | func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: UIViewControllerRepresentableContext) { 27 | 28 | } 29 | 30 | func makeCoordinator() -> Coordinator { 31 | Coordinator(self) 32 | } 33 | 34 | class Coordinator: NSObject, UINavigationControllerDelegate, UIDocumentPickerDelegate { 35 | var parent: FilePicker 36 | 37 | init(_ parent: FilePicker) { 38 | self.parent = parent 39 | } 40 | 41 | func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { 42 | for file in urls { 43 | if FileManager.default.fileExists(atPath: file.path) { 44 | FileEngine.addFile(file, removeOriginal: true) 45 | } 46 | } 47 | } 48 | } 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/GamesView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GamesView.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 2/13/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import CoreData 11 | 12 | struct GamesView: View { 13 | @FetchRequest(entity: Game.entity(), sortDescriptors: []) var games: FetchedResults 14 | 15 | var body: some View { 16 | UIListView(rows: Binding(get: { 17 | Array(self.games) 18 | }, set: { _ in 19 | 20 | }), 21 | sortType: Binding(get: { 22 | SortType.title.rawValue 23 | }, set: { _ in 24 | 25 | }), isEditing: .constant(false), rowType: Game.self, keypaths: UIListViewCellKeypaths(art: \Game.system?.name, title: \Game.name, desc: \Game.system?.name), showSearch: false, showsHeader: false) 26 | .navigationBarTitle(Text(NSLocalizedString("Games", comment: "Games")), displayMode: .inline) 27 | .edgesIgnoringSafeArea(.vertical) 28 | } 29 | } 30 | 31 | struct GamesView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | GamesView() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/GoogleService-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CLIENT_ID 6 | 568783072531-eha6nct4vmihcu8o0jq666ckgje1ffsd.apps.googleusercontent.com 7 | REVERSED_CLIENT_ID 8 | com.googleusercontent.apps.568783072531-eha6nct4vmihcu8o0jq666ckgje1ffsd 9 | API_KEY 10 | AIzaSyDdNArgKF6i354aaIm64wU_cH7GGAKeU_k 11 | GCM_SENDER_ID 12 | 568783072531 13 | PLIST_VERSION 14 | 1 15 | BUNDLE_ID 16 | com.abusman.Square-Wave 17 | PROJECT_ID 18 | square-wave-e799a 19 | STORAGE_BUCKET 20 | square-wave-e799a.appspot.com 21 | IS_ADS_ENABLED 22 | 23 | IS_ANALYTICS_ENABLED 24 | 25 | IS_APPINVITE_ENABLED 26 | 27 | IS_GCM_ENABLED 28 | 29 | IS_SIGNIN_ENABLED 30 | 31 | GOOGLE_APP_ID 32 | 1:568783072531:ios:b8f47bf6684a1d0a2bbee6 33 | DATABASE_URL 34 | https://square-wave-e799a.firebaseio.com 35 | 36 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/IAP_ProductIDs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.abusman.square_waves.premium 6 | 7 | 8 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/LibraryView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryView.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 2/13/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct LibraryView: View { 12 | @Environment(\.managedObjectContext) var context 13 | @EnvironmentObject var playbackState: PlaybackState 14 | @State var hasTracks: Bool = false 15 | @State var isShowingPicker: Bool = false 16 | static var miniViewPosition: CGFloat = 75.0 17 | 18 | var body: some View { 19 | Group { 20 | if self.hasTracks { 21 | List { 22 | NavigationLink(destination: PlaylistsView().environment(\.managedObjectContext, context).environmentObject(playbackState)) { 23 | Text(NSLocalizedString("Playlists", comment: "Playlists")) 24 | } 25 | NavigationLink(destination: PlatformsView().environment(\.managedObjectContext, context)) { 26 | Text(NSLocalizedString("Platforms", comment: "Platforms")) 27 | } 28 | NavigationLink(destination: ArtistsView().environment(\.managedObjectContext, context)) { 29 | Text(NSLocalizedString("Artists", comment: "Artists")) 30 | } 31 | NavigationLink(destination: GamesView().environment(\.managedObjectContext, context)) { 32 | Text(NSLocalizedString("Games", comment: "Games")) 33 | } 34 | NavigationLink(destination: SongsView(predicate: nil).environment(\.managedObjectContext, context).environmentObject(playbackState)) { 35 | Text(NSLocalizedString("Songs", comment: "Songs")) 36 | } 37 | } 38 | .navigationBarTitle(Text(NSLocalizedString("Library", comment: "Library"))) 39 | } else { 40 | VStack { 41 | Spacer() 42 | Button(action: { 43 | self.isShowingPicker.toggle() 44 | }) { 45 | Image(systemName: "plus") 46 | .resizable() 47 | .aspectRatio(contentMode: .fit) 48 | .padding(Edge.Set(arrayLiteral: [.horizontal, .top]), 100) 49 | } 50 | Text(NSLocalizedString("Add Files", comment: "Add Files")).multilineTextAlignment(.center) 51 | .lineLimit(6) 52 | .padding() 53 | .padding(.bottom, 50) 54 | Spacer() 55 | } 56 | .foregroundColor(Color(.tertiaryLabel)) 57 | .navigationBarTitle(Text(NSLocalizedString("Library", comment: "Library"))) 58 | .sheet(isPresented: self.$isShowingPicker) { 59 | FilePicker() 60 | } 61 | } 62 | }.onAppear { 63 | self.hasTracks = self.playbackState.hasTracks 64 | } 65 | .onReceive(self.playbackState.$hasTracks) { value in 66 | self.hasTracks = value 67 | } 68 | } 69 | } 70 | 71 | /* 72 | struct LibraryView_Previews: PreviewProvider { 73 | static let playbackState = PlaybackState() 74 | static var previews: some View { 75 | LibraryView().environmentObject(playbackState) 76 | } 77 | } 78 | */ 79 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/ListSectionIndexView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListSectionIndexView.swift 3 | // 4 | // 5 | // Created by Alex Busman on 2/26/20. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ListSectionIndexView: View { 11 | @Binding var index: Int 12 | 13 | var indices: [Character] 14 | 15 | var body: some View { 16 | VStack { 17 | ForEach(indicies, id: \.self) { index in 18 | Text(index) 19 | } 20 | }.background(Rectangle()) 21 | } 22 | } 23 | 24 | struct ListSectionIndexView_Previews: PreviewProvider { 25 | static var previews: some View { 26 | ListSectionIndexView(index: .constant(0)) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/NewPlaylistView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NewPlaylistView.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 3/1/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct NewPlaylistView: View { 12 | @Environment(\.presentationMode) var presentationMode: Binding 13 | @State var playlist: Playlist? 14 | @ObservedObject var playlistModel = PlaylistModel() 15 | var body: some View { 16 | NavigationView { 17 | PlaylistView(isNewPlaylist: true, playlistModel: self.playlistModel) 18 | .navigationBarTitle(Text(NSLocalizedString("New Playlist", comment: "New Playlist")), displayMode: .inline) 19 | .navigationBarItems(leading: Button(action: { 20 | self.presentationMode.wrappedValue.dismiss() 21 | }) { 22 | Text(NSLocalizedString("Cancel", comment: "Cancel")) 23 | }, trailing: Button(action: { 24 | let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 25 | let playlist = Playlist(entity: Playlist.entity(), insertInto: context) 26 | 27 | playlist.id = UUID() 28 | playlist.name = self.playlistModel.titleText 29 | playlist.tracks = NSOrderedSet(array: self.playlistModel.tracks) 30 | playlist.dateAdded = Date() 31 | let image = self.playlistModel.image 32 | self.savePlaylistImage(playlist, image: image) 33 | 34 | self.presentationMode.wrappedValue.dismiss() 35 | }) { 36 | Text(NSLocalizedString("Done", comment: "Done")) 37 | .bold() 38 | }) 39 | } 40 | } 41 | 42 | func savePlaylistImage(_ playlist: Playlist, image: UIImage?) { 43 | if let filename = Util.getPlaylistImagesDirectory()?.appendingPathComponent("\(playlist.id!).png") { 44 | let url = URL(fileURLWithPath: "\(playlist.id!).png") 45 | let delegate = UIApplication.shared.delegate as! AppDelegate 46 | if image != nil { 47 | let data = image!.pngData() 48 | do { 49 | try data?.write(to: filename) 50 | playlist.art = url 51 | delegate.saveContext() 52 | } catch { 53 | NSLog("Failed to write image data to \(filename.path)") 54 | } 55 | } else { 56 | do { 57 | try FileManager.default.removeItem(at: filename) 58 | playlist.art = nil 59 | delegate.saveContext() 60 | } catch { 61 | NSLog("Failed to remove \(filename.path)") 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | /* 69 | struct NewPlaylistView_Previews: PreviewProvider { 70 | static var previews: some View { 71 | NewPlaylistView() 72 | } 73 | } 74 | */ 75 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/NowPlayingMiniView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NowPlayingMiniView.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 2/14/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Combine 11 | 12 | class NowPlayingMiniViewDelegate: ObservableObject { 13 | var willChange = PassthroughSubject() 14 | var didChange = PassthroughSubject() 15 | 16 | var didTap: Bool = false { 17 | willSet { 18 | willChange.send(self) 19 | } 20 | 21 | didSet { 22 | didChange.send(self) 23 | } 24 | } 25 | } 26 | 27 | struct NowPlayingMiniView: View { 28 | @State var playButtonImage = "play.fill" 29 | @EnvironmentObject var playbackState: PlaybackState 30 | 31 | @ObservedObject var delegate: NowPlayingMiniViewDelegate 32 | let impactGenerator = UIImpactFeedbackGenerator() 33 | var swipe: some Gesture { 34 | DragGesture() 35 | .onChanged({ value in 36 | if value.predictedEndLocation.y < -20.0 { 37 | self.delegate.didTap = true 38 | } 39 | }) 40 | } 41 | 42 | var body: some View { 43 | VStack { 44 | Divider() 45 | .offset(y: 12) 46 | HStack { 47 | Image(uiImage: ListArtView.getImage(for: self.playbackState.nowPlayingTrack?.system?.name ?? "") ?? UIImage(named: "placeholder-art")!) 48 | .resizable() 49 | .aspectRatio(contentMode: .fit) 50 | .frame(height: 50.0) 51 | .cornerRadius(6.0) 52 | .overlay(RoundedRectangle(cornerRadius: 6.0).stroke(Color(.systemGray4), lineWidth: 0.5)) 53 | .shadow(radius: 5.0) 54 | .padding() 55 | VStack(alignment: .leading) { 56 | Text(self.playbackState.nowPlayingTrack?.name ?? NSLocalizedString("Not Playing", comment: "Not Playing")) 57 | .foregroundColor(Color(.label)) 58 | .lineLimit(1) 59 | if (self.playbackState.nowPlayingTrack?.game?.name?.count ?? 0) > 0 { 60 | Text(self.playbackState.nowPlayingTrack?.game?.name ?? "") 61 | .foregroundColor(Color(.secondaryLabel)) 62 | .lineLimit(1) 63 | } 64 | } 65 | Spacer() 66 | Button(action: { 67 | self.impactGenerator.impactOccurred(intensity: 1.0) 68 | if !self.playbackState.isNowPlaying { 69 | self.playbackState.play() 70 | } else { 71 | self.playbackState.pause() 72 | } 73 | }) { 74 | Image(systemName: self.playbackState.isNowPlaying ? "pause.fill" : "play.fill") 75 | .resizable() 76 | .aspectRatio(contentMode: .fit) 77 | .frame(height: 25.0) 78 | }.foregroundColor(Color(.label)) 79 | Button(action: { 80 | self.impactGenerator.impactOccurred(intensity: 0.5) 81 | self.playbackState.nextTrack() 82 | }) { 83 | Image(systemName: "forward.end.fill") 84 | .resizable() 85 | .aspectRatio(contentMode: .fit) 86 | .frame(height: 20.0) 87 | .padding() 88 | }.foregroundColor(Color(.label)) 89 | } 90 | Spacer() 91 | }.contentShape(Rectangle()) 92 | .onTapGesture { 93 | self.delegate.didTap = true 94 | }.gesture(self.swipe) 95 | .onAppear { 96 | self.impactGenerator.prepare() 97 | } 98 | } 99 | } 100 | 101 | struct NowPlayingMiniView_Previews: PreviewProvider { 102 | static var previews: some View { 103 | NowPlayingMiniView(delegate: NowPlayingMiniViewDelegate()) 104 | .frame(width: UIScreen.main.bounds.width, height: 75.0) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/PlatformsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlatformsView.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 2/13/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import CoreData 11 | 12 | struct PlatformsView: View { 13 | @FetchRequest(entity: System.entity(), sortDescriptors: []) var platforms: FetchedResults 14 | var body: some View { 15 | UIListView(rows: Binding(get: { 16 | Array(self.platforms) 17 | }, set: { _ in 18 | 19 | }), 20 | sortType: Binding(get: { 21 | SortType.title.rawValue 22 | }, set: { _ in 23 | 24 | }), isEditing: .constant(false), rowType: System.self, keypaths: UIListViewCellKeypaths(art: \System.name, title: \System.name, desc: nil), showSections: false) 25 | .navigationBarTitle(Text(NSLocalizedString("Platforms", comment: "Platforms"))) 26 | .edgesIgnoringSafeArea(.vertical) 27 | } 28 | } 29 | 30 | struct PlatformsView_Previews: PreviewProvider { 31 | static var previews: some View { 32 | PlatformsView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Square Wave/Square Wave/Receipts/AppleIncRootCertificate.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/Receipts/AppleIncRootCertificate.cer -------------------------------------------------------------------------------- /Square Wave/Square Wave/Receipts/ReceiptFetcher.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReceiptFetcher.swift 3 | // Square Waves 4 | // 5 | // Created by Alex Busman on 3/20/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import StoreKit 10 | 11 | class ReceiptFetcher: NSObject, SKRequestDelegate { 12 | let receiptRefreshRequest = SKReceiptRefreshRequest() 13 | 14 | override init() { 15 | super.init() 16 | 17 | self.receiptRefreshRequest.delegate = self 18 | } 19 | 20 | func fetchReceipt() { 21 | guard let receiptUrl = Bundle.main.appStoreReceiptURL else { 22 | NSLog("Unable to retrieve receipt URL") 23 | return 24 | } 25 | 26 | do { 27 | let reachable = try receiptUrl.checkResourceIsReachable() 28 | 29 | if !reachable { 30 | self.receiptRefreshRequest.start() 31 | } 32 | } catch { 33 | NSLog("Could not check if resource was reachable: \(error.localizedDescription)") 34 | self.receiptRefreshRequest.start() 35 | } 36 | } 37 | 38 | func requestDidFinish(_ request: SKRequest) { 39 | NSLog("Request finished successfully") 40 | } 41 | 42 | func request(_ request: SKRequest, didFailWithError error: Error) { 43 | NSLog("Request failed with error \(error.localizedDescription)") 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Receipts/pkcs7_union_accessors.c: -------------------------------------------------------------------------------- 1 | // 2 | // pkcs7_union_accessors.c 3 | // SwiftyReceiptValidatorDemo 4 | // 5 | // Created by Andrew Bancroft on 10/26/17. 6 | // Copyright © 2017 Andrew Bancroft. All rights reserved. 7 | // 8 | 9 | #include "pkcs7_union_accessors.h" 10 | 11 | inline char *pkcs7_d_char(PKCS7 *ptr) { 12 | return ptr->d.ptr; 13 | } 14 | 15 | inline ASN1_OCTET_STRING *pkcs7_d_data(PKCS7 *ptr) { 16 | return ptr->d.data; 17 | } 18 | 19 | inline PKCS7_SIGNED *pkcs7_d_sign(PKCS7 *ptr) { 20 | return ptr->d.sign; 21 | } 22 | 23 | inline PKCS7_ENVELOPE *pkcs7_d_enveloped(PKCS7 *ptr) { 24 | return ptr->d.enveloped; 25 | } 26 | 27 | inline PKCS7_SIGN_ENVELOPE *pkcs7_d_signed_and_enveloped(PKCS7 *ptr) { 28 | return ptr->d.signed_and_enveloped; 29 | } 30 | 31 | inline PKCS7_DIGEST *pkcs7_d_digest(PKCS7 *ptr) { 32 | return ptr->d.digest; 33 | } 34 | 35 | inline PKCS7_ENCRYPT *pkcs7_d_encrypted(PKCS7 *ptr) { 36 | return ptr->d.encrypted; 37 | } 38 | 39 | inline ASN1_TYPE *pkcs7_d_other(PKCS7 *ptr) { 40 | return ptr->d.other; 41 | } 42 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Receipts/pkcs7_union_accessors.h: -------------------------------------------------------------------------------- 1 | #ifndef pkcs7_union_accessors_h 2 | #define pkcs7_union_accessors_h 3 | 4 | #include 5 | 6 | char *pkcs7_d_char(PKCS7 *ptr); 7 | ASN1_OCTET_STRING *pkcs7_d_data(PKCS7 *ptr); 8 | PKCS7_SIGNED *pkcs7_d_sign(PKCS7 *ptr); 9 | PKCS7_ENVELOPE *pkcs7_d_enveloped(PKCS7 *ptr); 10 | PKCS7_SIGN_ENVELOPE *pkcs7_d_signed_and_enveloped(PKCS7 *ptr); 11 | PKCS7_DIGEST *pkcs7_d_digest(PKCS7 *ptr); 12 | PKCS7_ENCRYPT *pkcs7_d_encrypted(PKCS7 *ptr); 13 | ASN1_TYPE *pkcs7_d_other(PKCS7 *ptr); 14 | 15 | #endif /* pkcs7_union_accessors_h */ 16 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 2/10/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | import AVKit 12 | 13 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | guard let _ = (scene as? UIWindowScene) else { return } 22 | } 23 | 24 | func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { 25 | for urlContext in URLContexts { 26 | FileEngine.addFile(urlContext.url, removeOriginal: true) 27 | } 28 | } 29 | 30 | func sceneDidDisconnect(_ scene: UIScene) { 31 | // Called as the scene is being released by the system. 32 | // This occurs shortly after the scene enters the background, or when its session is discarded. 33 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 34 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 35 | } 36 | 37 | func sceneDidBecomeActive(_ scene: UIScene) { 38 | // Called when the scene has moved from an inactive state to an active state. 39 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 40 | do { 41 | try AVAudioSession.sharedInstance().setCategory(.playback) 42 | } catch { 43 | NSLog("\(error.localizedDescription)") 44 | } 45 | } 46 | 47 | func sceneWillResignActive(_ scene: UIScene) { 48 | // Called when the scene will move from an active state to an inactive state. 49 | // This may occur due to temporary interruptions (ex. an incoming phone call). 50 | } 51 | 52 | func sceneWillEnterForeground(_ scene: UIScene) { 53 | // Called as the scene transitions from the background to the foreground. 54 | // Use this method to undo the changes made on entering the background. 55 | } 56 | 57 | func sceneDidEnterBackground(_ scene: UIScene) { 58 | // Called as the scene transitions from the foreground to the background. 59 | // Use this method to save data, release shared resources, and store enough scene-specific state information 60 | // to restore the scene back to its current state. 61 | 62 | // Save changes in the application's managed object context when the application transitions to the background. 63 | (UIApplication.shared.delegate as? AppDelegate)?.saveContext() 64 | } 65 | 66 | 67 | } 68 | 69 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Square Wave.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.icloud-container-identifiers 6 | 7 | iCloud.com.abusman.square-wave 8 | 9 | com.apple.developer.icloud-services 10 | 11 | CloudDocuments 12 | 13 | com.apple.developer.ubiquity-container-identifiers 14 | 15 | iCloud.com.abusman.square-wave 16 | 17 | com.apple.developer.ubiquity-kvstore-identifier 18 | $(TeamIdentifierPrefix)$(CFBundleIdentifier) 19 | keychain-access-groups 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/TextView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextView.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 3/1/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct TextView: UIViewRepresentable { 12 | var title: String 13 | @Binding var text: String 14 | var placeholder = UILabel() 15 | 16 | func makeCoordinator() -> Coordinator { 17 | Coordinator(self) 18 | } 19 | 20 | func makeUIView(context: Context) -> UITextView { 21 | 22 | let myTextView = UITextView() 23 | myTextView.delegate = context.coordinator 24 | myTextView.isScrollEnabled = true 25 | myTextView.isEditable = true 26 | myTextView.isUserInteractionEnabled = true 27 | myTextView.backgroundColor = .clear 28 | myTextView.font = UIFont.preferredFont(forTextStyle: .headline) 29 | myTextView.returnKeyType = .done 30 | myTextView.text = self.text 31 | 32 | self.placeholder.text = self.title 33 | self.placeholder.textColor = .placeholderText 34 | self.placeholder.font = UIFont.preferredFont(forTextStyle: .headline) 35 | myTextView.addSubview(self.placeholder) 36 | 37 | self.placeholder.translatesAutoresizingMaskIntoConstraints = false 38 | self.placeholder.isUserInteractionEnabled = false 39 | 40 | self.placeholder.leadingAnchor.constraint(equalTo: myTextView.leadingAnchor, constant: 6).isActive = true 41 | self.placeholder.topAnchor.constraint(equalTo: myTextView.topAnchor, constant: 7.5).isActive = true 42 | 43 | if !self.text.isEmpty { 44 | self.placeholder.isHidden = true 45 | } 46 | return myTextView 47 | } 48 | 49 | func updateUIView(_ uiView: UITextView, context: Context) { 50 | 51 | } 52 | 53 | class Coordinator : NSObject, UITextViewDelegate { 54 | 55 | var parent: TextView 56 | 57 | init(_ uiTextView: TextView) { 58 | self.parent = uiTextView 59 | } 60 | 61 | func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { 62 | if text == "\n" { 63 | textView.resignFirstResponder() 64 | return false 65 | } 66 | return true 67 | } 68 | 69 | func textViewDidChange(_ textView: UITextView) { 70 | self.parent.text = textView.text 71 | 72 | if self.parent.text.isEmpty { 73 | self.parent.placeholder.isHidden = false 74 | } else { 75 | self.parent.placeholder.isHidden = true 76 | } 77 | } 78 | } 79 | } 80 | 81 | struct TextView_Previews: PreviewProvider { 82 | static var previews: some View { 83 | TextView(title: "Preview", text: .constant("")) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/Util.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Util.swift 3 | // Square Wave 4 | // 5 | // Created by Alex Busman on 3/8/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class Util { 12 | class func getPlaylistImagesDirectory() -> URL? { 13 | var ret: URL? 14 | do { 15 | let docsDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 16 | ret = docsDir.appendingPathComponent("images/playlists") 17 | } catch { 18 | NSLog("Could not get docs dir") 19 | } 20 | return ret 21 | } 22 | 23 | class func getPurchased() -> Bool { 24 | return PlaybackStateProperty.purchased.getProperty() ?? false 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/VisualEffectView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct VisualEffectView: UIViewRepresentable { 4 | var effect: UIVisualEffect? 5 | func makeUIView(context: UIViewRepresentableContext) -> UIVisualEffectView { UIVisualEffectView() } 6 | func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext) { uiView.effect = effect } 7 | } 8 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | Square Waves 4 | 5 | Created by Alex Busman on 4/4/20. 6 | Copyright © 2020 Alex Busman. All rights reserved. 7 | */ 8 | 9 | "Library" = "Library"; 10 | "Settings" = "Settings"; 11 | "Playlists" = "Playlists"; 12 | "Platforms" = "Platforms"; 13 | "Games" = "Games"; 14 | "Songs" = "Songs"; 15 | "Track Length" = "Track Length"; 16 | "Add Files" = "Add files by pressing the \"+\" button in the top right, or by adding them to the\nSquare Wave folder on your iCloud Drive"; 17 | "Track Length Description" = "For tracks without loop information, you can choose how long you want the track to play for before moving on to the next track."; 18 | "Loop Count" = "Loop Count"; 19 | "Loop Count Description" = "For tracks with loop information, you can choose how many times you want the track to loop before moving on to the next track."; 20 | "Upgrade" = "Upgrade"; 21 | "Upgrade Description %@" = "With the free version, you are limited to %@ tracks per day. Upgrade, and get unlimited playback, playlist support, voice toggling, and more!"; 22 | "Restore Purchases" = "Restore Purchases"; 23 | "Upgrade Purchased" = "Upgrade Purchased. Thanks!"; 24 | "Delete All" = "Delete All"; 25 | "Done" = "Done"; 26 | "Edit" = "Edit"; 27 | "Cancel" = "Cancel"; 28 | "Playback Rate" = "Playback Rate"; 29 | "Voices" = "Voices"; 30 | "Play Count Exceeded" = "Play Count Exceeded"; 31 | "Exceeded Error" = "You have exceeded the maximum amount of tracks per day. Would you like to purchase premium?"; 32 | "Yes" = "Yes"; 33 | "No" = "No"; 34 | "Playlists Premium" = "Playlists are a premium feature. Upgrade to get this and more!"; 35 | "Confirm Playlists" = "Sounds like fun!"; 36 | "Sort" = "Sort"; 37 | "Sort By" = "Sort by..."; 38 | "Title" = "Title"; 39 | "Game" = "Game"; 40 | "Playlist Title" = "Playlist Title"; 41 | "Add Songs" = "Add Songs"; 42 | "Error" = "Error"; 43 | "Okay" = "Okay"; 44 | "Delete All Question" = "Delete All?"; 45 | "Delete All Description" = "This will delete all your music and playlists. This will NOT delete anything stored in your cloud drive.\nAre you sure?"; 46 | "Delete All Confirm" = "Yes, Delete"; 47 | "Purchase Error Description %@" = "Could not complete purchase. %@"; 48 | "Add To Playlist" = "Add to Playlist"; 49 | "Search" = "Search"; 50 | "New Playlist" = "New Playlist"; 51 | "tracks" = "tracks"; 52 | "Remove" = "Remove"; 53 | "Delete" = "Delete"; 54 | "Rename" = "Rename"; 55 | "Save" = "Save"; 56 | "No Name" = "No Name"; 57 | "Shuffle" = "Shuffle"; 58 | "Play" = "Play"; 59 | "Not Playing" = "Not Playing"; 60 | "Artists" = "Artists"; 61 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/fr-CA.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Square Wave/Square Wave/fr-CA.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a-busman/SquareWaveSwift/cd194d8dcc6bafa8f64d6156b1f6af0dde744005/Square Wave/Square Wave/fr-CA.lproj/Localizable.strings -------------------------------------------------------------------------------- /Square Wave/Square WaveTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Square Wave/Square WaveTests/Square_WaveTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Square_WaveTests.swift 3 | // Square WaveTests 4 | // 5 | // Created by Alex Busman on 2/10/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Square_Wave 11 | 12 | class Square_WaveTests: XCTestCase { 13 | 14 | override func setUp() { 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | } 21 | 22 | func testExample() { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | } 26 | 27 | func testPerformanceExample() { 28 | // This is an example of a performance test case. 29 | self.measure { 30 | // Put the code you want to measure the time of here. 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /Square Wave/Square WaveUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Square Wave/Square WaveUITests/Square_WaveUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Square_WaveUITests.swift 3 | // Square WaveUITests 4 | // 5 | // Created by Alex Busman on 2/10/20. 6 | // Copyright © 2020 Alex Busman. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class Square_WaveUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | 16 | // In UI tests it is usually best to stop immediately when a failure occurs. 17 | continueAfterFailure = false 18 | 19 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 20 | } 21 | 22 | override func tearDown() { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | } 25 | 26 | func testExample() { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use recording to get started writing UI tests. 32 | // Use XCTAssert and related functions to verify your tests produce the correct results. 33 | } 34 | 35 | func testLaunchPerformance() { 36 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) { 37 | // This measures how long it takes to launch your application. 38 | measure(metrics: [XCTOSSignpostMetric.applicationLaunch]) { 39 | XCUIApplication().launch() 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Square Wave/Square Waves.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Square Wave/Square Waves.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Square Wave/Square Waves.xcodeproj/xcshareddata/xcschemes/Square Wave.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Square Wave/Square Waves.xcodeproj/xcuserdata/abusman.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Square Wave.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FA822D3123F1F81C005FCFB3 16 | 17 | primary 18 | 19 | 20 | FA822D4A23F1F81E005FCFB3 21 | 22 | primary 23 | 24 | 25 | FA822D5523F1F81E005FCFB3 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Square Wave/Square Waves.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | --------------------------------------------------------------------------------